diff options
author | nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-02-16 16:25:40 +0000 |
---|---|---|
committer | nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-02-16 16:25:40 +0000 |
commit | eaba9da1d13fac380fe94f977d7f8d89bd40cde0 (patch) | |
tree | b17e09f3ce10f925571e406c0deed966270c7804 /file.c | |
parent | 99c76a47ef8c65a27ee6d9a7dab03671dc22647a (diff) |
merge revision(s) 59983,59984: [Backport #10222] [Backport #14372] [Backport #14424]
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.
load.c: real path to load
* load.c (rb_construct_expanded_load_path): expand load paths to
real paths to get rid of duplicate loading from symbolic-linked
directories. [Feature #10222]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@62440 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'file.c')
-rw-r--r-- | file.c | 77 |
1 files changed, 59 insertions, 18 deletions
@@ -3757,8 +3757,29 @@ rb_file_s_absolute_path(int argc, const VALUE *argv) 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); @@ -3799,6 +3820,10 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE l 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 { @@ -3816,8 +3841,9 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE l #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; @@ -3846,7 +3872,9 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE l *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)); } @@ -3860,17 +3888,11 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE l } } } + 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; @@ -3937,11 +3959,16 @@ rb_realpath_internal(VALUE basedir, VALUE path, int strict) } 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 != enc && rb_enc_str_asciionly_p(resolved)) rb_enc_associate(resolved, origenc); @@ -3949,6 +3976,20 @@ rb_realpath_internal(VALUE basedir, VALUE path, int strict) 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 /* |