ruby-changes:47862
From: nobu <ko1@a...>
Date: Thu, 21 Sep 2017 16:29:21 +0900 (JST)
Subject: [ruby-changes:47862] nobu:r59983 (trunk): file.c: rb_check_realpath
nobu 2017-09-21 16:29:16 +0900 (Thu, 21 Sep 2017) New Revision: 59983 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=59983 Log: file.c: rb_check_realpath * file.c (rb_check_realpath): returns real path which has no symbolic links. similar to rb_realpath except for returning Qnil if any parts did not exist. Modified files: trunk/file.c trunk/internal.h Index: file.c =================================================================== --- file.c (revision 59982) +++ file.c (revision 59983) @@ -3775,8 +3775,29 @@ rb_file_s_absolute_path(int argc, const https://github.com/ruby/ruby/blob/trunk/file.c#L3775 return rb_file_absolute_path(argv[0], argc > 1 ? argv[1] : Qnil); } -static void -realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE loopcheck, int strict, int last) +#ifdef __native_client__ +VALUE +rb_realpath_internal(VALUE basedir, VALUE path, int strict) +{ + return path; +} + +VALUE +rb_check_realpath(VALUE basedir, VALUE path) +{ + return path; +} +#else +enum rb_realpath_mode { + RB_REALPATH_CHECK, + RB_REALPATH_DIR, + RB_REALPATH_STRICT, + RB_REALPATH_MODE_MAX +}; + +static int +realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, + VALUE loopcheck, enum rb_realpath_mode mode, int last) { const char *pend = unresolved + strlen(unresolved); rb_encoding *enc = rb_enc_get(*resolvedp); @@ -3817,6 +3838,10 @@ realpath_rec(long *prefixlenp, VALUE *re https://github.com/ruby/ruby/blob/trunk/file.c#L3838 checkval = rb_hash_aref(loopcheck, testpath); if (!NIL_P(checkval)) { if (checkval == ID2SYM(resolving)) { + if (mode == RB_REALPATH_CHECK) { + errno = ELOOP; + return -1; + } rb_syserr_fail_path(ELOOP, testpath); } else { @@ -3833,8 +3858,9 @@ realpath_rec(long *prefixlenp, VALUE *re https://github.com/ruby/ruby/blob/trunk/file.c#L3858 #endif if (ret == -1) { int e = errno; + if (mode == RB_REALPATH_CHECK) return -1; if (e == ENOENT) { - if (strict || !last || *unresolved_firstsep) + if (mode == RB_REALPATH_STRICT || !last || *unresolved_firstsep) rb_syserr_fail_path(e, testpath); *resolvedp = testpath; break; @@ -3863,7 +3889,9 @@ realpath_rec(long *prefixlenp, VALUE *re https://github.com/ruby/ruby/blob/trunk/file.c#L3889 *resolvedp = link; *prefixlenp = link_prefixlen; } - realpath_rec(prefixlenp, resolvedp, link_names, loopcheck, strict, *unresolved_firstsep == '\0'); + if (realpath_rec(prefixlenp, resolvedp, link_names, + loopcheck, mode, !*unresolved_firstsep)) + return -1; RB_GC_GUARD(link_orig); rb_hash_aset(loopcheck, testpath, rb_str_dup_frozen(*resolvedp)); } @@ -3877,17 +3905,11 @@ realpath_rec(long *prefixlenp, VALUE *re https://github.com/ruby/ruby/blob/trunk/file.c#L3905 } } } + return 0; } -#ifdef __native_client__ -VALUE -rb_realpath_internal(VALUE basedir, VALUE path, int strict) -{ - return path; -} -#else -VALUE -rb_realpath_internal(VALUE basedir, VALUE path, int strict) +static VALUE +rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode) { long prefixlen; VALUE resolved; @@ -3955,11 +3977,16 @@ rb_realpath_internal(VALUE basedir, VALU https://github.com/ruby/ruby/blob/trunk/file.c#L3977 } loopcheck = rb_hash_new(); - if (curdir_names) - realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, 1, 0); - if (basedir_names) - realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, 1, 0); - realpath_rec(&prefixlen, &resolved, path_names, loopcheck, strict, 1); + if (curdir_names) { + if (realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, mode, 0)) + return Qnil; + } + if (basedir_names) { + if (realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, mode, 0)) + return Qnil; + } + if (realpath_rec(&prefixlen, &resolved, path_names, loopcheck, mode, 1)) + return Qnil; if (origenc != rb_enc_get(resolved)) { if (rb_enc_str_asciionly_p(resolved)) { @@ -3973,6 +4000,20 @@ rb_realpath_internal(VALUE basedir, VALU https://github.com/ruby/ruby/blob/trunk/file.c#L4000 OBJ_TAINT(resolved); return resolved; } + +VALUE +rb_realpath_internal(VALUE basedir, VALUE path, int strict) +{ + const enum rb_realpath_mode mode = + strict ? RB_REALPATH_STRICT : RB_REALPATH_DIR; + return rb_check_realpath_internal(basedir, path, mode); +} + +VALUE +rb_check_realpath(VALUE basedir, VALUE path) +{ + return rb_check_realpath_internal(basedir, path, RB_REALPATH_CHECK); +} #endif /* Index: internal.h =================================================================== --- internal.h (revision 59982) +++ internal.h (revision 59983) @@ -1179,6 +1179,7 @@ void rb_mark_end_proc(void); https://github.com/ruby/ruby/blob/trunk/internal.h#L1179 VALUE rb_home_dir_of(VALUE user, VALUE result); VALUE rb_default_home_dir(VALUE result); VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); +VALUE rb_check_realpath(VALUE basedir, VALUE path); void rb_file_const(const char*, VALUE); int rb_file_load_ok(const char *); VALUE rb_file_expand_path_fast(VALUE, VALUE); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/