From 2368dbdfa3c438b614a4727bde7cacac2d0a87a9 Mon Sep 17 00:00:00 2001 From: nagachika Date: Fri, 16 Mar 2018 17:34:44 +0000 Subject: merge revision(s) 58745,58780,59040,60743: [Backport #13863] rb_w32_ugetcwd: UTF-8 version getcwd * dir.c (rb_dir_getwd): convert from UTF-8. * win32/win32.c (w32_getcwd): codepage aware getcwd using GetCurrentDirectoryW. potential memory leak * dir.c (rb_dir_getwd): get rid of potential memory leak. * util.c (ruby_getcwd): ditto. file.c: realpath in OS path encoding * dir.c (rb_dir_getwd_ospath): return cwd path in the OS path encoding. * file.c (rb_realpath_internal): work in the OS path encoding load.c: cwd encoding * load.c (rb_get_expanded_load_path): save cwd cache in OS path encoding, to get rid of unnecessary conversion and infinite loading when it needs encoding conversion. [ruby-dev:50221] [Bug #13863] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@62784 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- file.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'file.c') diff --git a/file.c b/file.c index 0e67654da2..43040787d0 100644 --- a/file.c +++ b/file.c @@ -126,6 +126,14 @@ int flock(int, int); #define STAT(p, s) stat((p), (s)) #endif +#if defined _WIN32 || defined __APPLE__ +# define USE_OSPATH 1 +# define TO_OSPATH(str) rb_str_encode_ospath(str) +#else +# define USE_OSPATH 0 +# define TO_OSPATH(str) (str) +#endif + VALUE rb_cFile; VALUE rb_mFileTest; VALUE rb_cStat; @@ -222,7 +230,7 @@ rb_get_path(VALUE obj) VALUE rb_str_encode_ospath(VALUE path) { -#if defined _WIN32 || defined __APPLE__ +#if USE_OSPATH int encidx = ENCODING_GET(path); #ifdef _WIN32 if (encidx == ENCINDEX_ASCII) { @@ -3833,11 +3841,10 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, else { struct stat sbuf; int ret; - VALUE testpath2 = rb_str_encode_ospath(testpath); #ifdef __native_client__ - ret = stat(RSTRING_PTR(testpath2), &sbuf); + ret = stat(RSTRING_PTR(testpath), &sbuf); #else - ret = lstat(RSTRING_PTR(testpath2), &sbuf); + ret = lstat(RSTRING_PTR(testpath), &sbuf); #endif if (ret == -1) { int e = errno; @@ -3909,9 +3916,12 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode if (!NIL_P(basedir)) { FilePathValue(basedir); - basedir = rb_str_dup_frozen(basedir); + basedir = TO_OSPATH(rb_str_dup_frozen(basedir)); } + 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)); if (ptr != path_names) { @@ -3928,7 +3938,7 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode } } - curdir = rb_dir_getwd(); + curdir = rb_dir_getwd_ospath(); RSTRING_GETMEM(curdir, ptr, len); curdir_names = skipprefixroot(ptr, ptr + len, rb_enc_get(curdir)); resolved = rb_str_subseq(curdir, 0, curdir_names - ptr); @@ -3936,7 +3946,6 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode root_found: RSTRING_GETMEM(resolved, prefixptr, prefixlen); pend = prefixptr + prefixlen; - enc = rb_enc_get(resolved); ptr = chompdirsep(prefixptr, pend, enc); if (ptr < pend) { prefixlen = ++ptr - prefixptr; @@ -3951,7 +3960,6 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode } #endif - origenc = enc; switch (rb_enc_to_index(enc)) { case ENCINDEX_ASCII: case ENCINDEX_US_ASCII: @@ -3970,8 +3978,14 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode 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); + if (origenc != rb_enc_get(resolved)) { + if (rb_enc_str_asciionly_p(resolved)) { + rb_enc_associate(resolved, origenc); + } + else { + resolved = rb_str_conv_enc(resolved, NULL, origenc); + } + } OBJ_TAINT(resolved); return resolved; -- cgit v1.2.3