diff options
Diffstat (limited to 'file.c')
-rw-r--r-- | file.c | 33 |
1 files changed, 16 insertions, 17 deletions
@@ -242,7 +242,7 @@ rb_str_encode_ospath(VALUE path) encidx = rb_filesystem_encindex(); } #endif - if (encidx != ENCINDEX_UTF_8) { + if (encidx != ENCINDEX_ASCII && encidx != ENCINDEX_UTF_8) { rb_encoding *enc = rb_enc_from_index(encidx); rb_encoding *utf8 = rb_utf8_encoding(); path = rb_str_conv_enc(path, enc, utf8); @@ -4243,7 +4243,7 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE f } static VALUE -rb_check_realpath_emulate(VALUE basedir, VALUE path, enum rb_realpath_mode mode) +rb_check_realpath_emulate(VALUE basedir, VALUE path, rb_encoding *origenc, enum rb_realpath_mode mode) { long prefixlen; VALUE resolved; @@ -4251,7 +4251,7 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, enum rb_realpath_mode mode) VALUE loopcheck; VALUE curdir = Qnil; - rb_encoding *enc, *origenc; + rb_encoding *enc; char *path_names = NULL, *basedir_names = NULL, *curdir_names = NULL; char *ptr, *prefixptr = NULL, *pend; long len; @@ -4264,7 +4264,6 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, enum rb_realpath_mode mode) } enc = rb_enc_get(unresolved_path); - origenc = enc; unresolved_path = TO_OSPATH(unresolved_path); RSTRING_GETMEM(unresolved_path, ptr, len); path_names = skipprefixroot(ptr, ptr + len, rb_enc_get(unresolved_path)); @@ -4322,7 +4321,7 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, enum rb_realpath_mode mode) if (realpath_rec(&prefixlen, &resolved, path_names, Qnil, loopcheck, mode, 1)) return Qnil; - if (origenc != rb_enc_get(resolved)) { + if (origenc && origenc != rb_enc_get(resolved)) { if (rb_enc_str_asciionly_p(resolved)) { rb_enc_associate(resolved, origenc); } @@ -4339,25 +4338,23 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, enum rb_realpath_mode mode) static VALUE rb_file_join(VALUE ary); static VALUE -rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode) +rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum rb_realpath_mode mode) { #ifdef HAVE_REALPATH VALUE unresolved_path; - rb_encoding *origenc; char *resolved_ptr = NULL; VALUE resolved; struct stat st; if (mode == RB_REALPATH_DIR) { - return rb_check_realpath_emulate(basedir, path, mode); + return rb_check_realpath_emulate(basedir, path, origenc, mode); } unresolved_path = rb_str_dup_frozen(path); - origenc = rb_enc_get(unresolved_path); if (*RSTRING_PTR(unresolved_path) != '/' && !NIL_P(basedir)) { unresolved_path = rb_file_join(rb_assoc_new(basedir, unresolved_path)); } - unresolved_path = TO_OSPATH(unresolved_path); + if (origenc) unresolved_path = TO_OSPATH(unresolved_path); if ((resolved_ptr = realpath(RSTRING_PTR(unresolved_path), NULL)) == NULL) { /* glibc realpath(3) does not allow /path/to/file.rb/../other_file.rb, @@ -4367,7 +4364,7 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode Fallback to the emulated approach in either of those cases. */ if (errno == ENOTDIR || (errno == ENOENT && rb_file_exist_p(0, unresolved_path))) { - return rb_check_realpath_emulate(basedir, path, mode); + return rb_check_realpath_emulate(basedir, path, origenc, mode); } if (mode == RB_REALPATH_CHECK) { @@ -4378,14 +4375,16 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode resolved = ospath_new(resolved_ptr, strlen(resolved_ptr), rb_filesystem_encoding()); free(resolved_ptr); - if (rb_stat(resolved, &st) < 0) { + /* As `resolved` is a String in the filesystem encoding, no + * conversion is needed */ + if (stat_without_gvl(RSTRING_PTR(resolved), &st) < 0) { if (mode == RB_REALPATH_CHECK) { return Qnil; } rb_sys_fail_path(unresolved_path); } - if (origenc != rb_enc_get(resolved)) { + if (origenc && origenc != rb_enc_get(resolved)) { if (!rb_enc_str_asciionly_p(resolved)) { resolved = rb_str_conv_enc(resolved, NULL, origenc); } @@ -4402,7 +4401,7 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode RB_GC_GUARD(unresolved_path); return resolved; #else - return rb_check_realpath_emulate(basedir, path, mode); + return rb_check_realpath_emulate(basedir, path, origenc, mode); #endif /* HAVE_REALPATH */ } @@ -4411,13 +4410,13 @@ 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); + return rb_check_realpath_internal(basedir, path, rb_enc_get(path), mode); } VALUE -rb_check_realpath(VALUE basedir, VALUE path) +rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *enc) { - return rb_check_realpath_internal(basedir, path, RB_REALPATH_CHECK); + return rb_check_realpath_internal(basedir, path, enc, RB_REALPATH_CHECK); } /* |