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

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59040 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2017-06-08 01:58:44 +00:00
Родитель 6502c03815
Коммит aac0b43ed5
3 изменённых файлов: 51 добавлений и 19 удалений

33
dir.c
Просмотреть файл

@ -1082,30 +1082,25 @@ dir_s_chdir(int argc, VALUE *argv, VALUE obj)
} }
VALUE VALUE
rb_dir_getwd(void) rb_dir_getwd_ospath(void)
{ {
char *path; char *path;
VALUE cwd; VALUE cwd;
rb_encoding *fs = rb_filesystem_encoding();
int fsenc = rb_enc_to_index(fs);
VALUE path_guard; VALUE path_guard;
#undef RUBY_UNTYPED_DATA_WARNING #undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0 #define RUBY_UNTYPED_DATA_WARNING 0
if (fsenc == ENCINDEX_US_ASCII) fsenc = ENCINDEX_ASCII;
path_guard = Data_Wrap_Struct((VALUE)0, NULL, RUBY_DEFAULT_FREE, NULL); path_guard = Data_Wrap_Struct((VALUE)0, NULL, RUBY_DEFAULT_FREE, NULL);
path = my_getcwd(); path = my_getcwd();
DATA_PTR(path_guard) = path; DATA_PTR(path_guard) = path;
#ifdef _WIN32 #ifdef _WIN32
cwd = rb_str_conv_enc(rb_utf8_str_new_cstr(path), NULL, fs); cwd = rb_utf8_str_new_cstr(path);
#else OBJ_TAINT(cwd);
#ifdef __APPLE__ #elif defined __APPLE__
cwd = rb_str_normalize_ospath(path, strlen(path)); cwd = rb_str_normalize_ospath(path, strlen(path));
OBJ_TAINT(cwd); OBJ_TAINT(cwd);
#else #else
cwd = rb_tainted_str_new2(path); cwd = rb_tainted_str_new2(path);
#endif
rb_enc_associate_index(cwd, fsenc);
#endif #endif
DATA_PTR(path_guard) = 0; DATA_PTR(path_guard) = 0;
@ -1113,6 +1108,26 @@ rb_dir_getwd(void)
return cwd; return cwd;
} }
VALUE
rb_dir_getwd(void)
{
rb_encoding *fs = rb_filesystem_encoding();
int fsenc = rb_enc_to_index(fs);
VALUE cwd = rb_dir_getwd_ospath();
switch (fsenc) {
case ENCINDEX_US_ASCII:
fsenc = ENCINDEX_ASCII;
case ENCINDEX_ASCII:
break;
#if defined _WIN32 || defined __APPLE__
default:
return rb_str_conv_enc(cwd, NULL, fs);
#endif
}
return rb_enc_associate_index(cwd, fsenc);
}
/* /*
* call-seq: * call-seq:
* Dir.getwd -> string * Dir.getwd -> string

34
file.c
Просмотреть файл

@ -127,6 +127,14 @@ int flock(int, int);
#define STAT(p, s) stat((p), (s)) #define STAT(p, s) stat((p), (s))
#endif #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_cFile;
VALUE rb_mFileTest; VALUE rb_mFileTest;
VALUE rb_cStat; VALUE rb_cStat;
@ -222,7 +230,7 @@ rb_get_path(VALUE obj)
VALUE VALUE
rb_str_encode_ospath(VALUE path) rb_str_encode_ospath(VALUE path)
{ {
#if defined _WIN32 || defined __APPLE__ #if USE_OSPATH
int encidx = ENCODING_GET(path); int encidx = ENCODING_GET(path);
#ifdef _WIN32 #ifdef _WIN32
if (encidx == ENCINDEX_ASCII) { if (encidx == ENCINDEX_ASCII) {
@ -3811,11 +3819,10 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE l
else { else {
struct stat sbuf; struct stat sbuf;
int ret; int ret;
VALUE testpath2 = rb_str_encode_ospath(testpath);
#ifdef __native_client__ #ifdef __native_client__
ret = stat(RSTRING_PTR(testpath2), &sbuf); ret = stat(RSTRING_PTR(testpath), &sbuf);
#else #else
ret = lstat(RSTRING_PTR(testpath2), &sbuf); ret = lstat(RSTRING_PTR(testpath), &sbuf);
#endif #endif
if (ret == -1) { if (ret == -1) {
int e = errno; int e = errno;
@ -3890,9 +3897,12 @@ rb_realpath_internal(VALUE basedir, VALUE path, int strict)
if (!NIL_P(basedir)) { if (!NIL_P(basedir)) {
FilePathValue(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); RSTRING_GETMEM(unresolved_path, ptr, len);
path_names = skipprefixroot(ptr, ptr + len, rb_enc_get(unresolved_path)); path_names = skipprefixroot(ptr, ptr + len, rb_enc_get(unresolved_path));
if (ptr != path_names) { if (ptr != path_names) {
@ -3909,7 +3919,7 @@ rb_realpath_internal(VALUE basedir, VALUE path, int strict)
} }
} }
curdir = rb_dir_getwd(); curdir = rb_dir_getwd_ospath();
RSTRING_GETMEM(curdir, ptr, len); RSTRING_GETMEM(curdir, ptr, len);
curdir_names = skipprefixroot(ptr, ptr + len, rb_enc_get(curdir)); curdir_names = skipprefixroot(ptr, ptr + len, rb_enc_get(curdir));
resolved = rb_str_subseq(curdir, 0, curdir_names - ptr); resolved = rb_str_subseq(curdir, 0, curdir_names - ptr);
@ -3917,7 +3927,6 @@ rb_realpath_internal(VALUE basedir, VALUE path, int strict)
root_found: root_found:
RSTRING_GETMEM(resolved, prefixptr, prefixlen); RSTRING_GETMEM(resolved, prefixptr, prefixlen);
pend = prefixptr + prefixlen; pend = prefixptr + prefixlen;
enc = rb_enc_get(resolved);
ptr = chompdirsep(prefixptr, pend, enc); ptr = chompdirsep(prefixptr, pend, enc);
if (ptr < pend) { if (ptr < pend) {
prefixlen = ++ptr - prefixptr; prefixlen = ++ptr - prefixptr;
@ -3932,7 +3941,6 @@ rb_realpath_internal(VALUE basedir, VALUE path, int strict)
} }
#endif #endif
origenc = enc;
switch (rb_enc_to_index(enc)) { switch (rb_enc_to_index(enc)) {
case ENCINDEX_ASCII: case ENCINDEX_ASCII:
case ENCINDEX_US_ASCII: case ENCINDEX_US_ASCII:
@ -3946,8 +3954,14 @@ rb_realpath_internal(VALUE basedir, VALUE path, int strict)
realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, 1, 0); realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, 1, 0);
realpath_rec(&prefixlen, &resolved, path_names, loopcheck, strict, 1); realpath_rec(&prefixlen, &resolved, path_names, loopcheck, strict, 1);
if (origenc != enc && rb_enc_str_asciionly_p(resolved)) if (origenc != rb_enc_get(resolved)) {
rb_enc_associate(resolved, origenc); if (rb_enc_str_asciionly_p(resolved)) {
rb_enc_associate(resolved, origenc);
}
else {
resolved = rb_str_conv_enc(resolved, NULL, origenc);
}
}
OBJ_TAINT(resolved); OBJ_TAINT(resolved);
return resolved; return resolved;

Просмотреть файл

@ -1088,6 +1088,9 @@ void ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(ANYARGS), VALUE
/* debug.c */ /* debug.c */
PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2); PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2);
/* dir.c */
VALUE rb_dir_getwd_ospath(void);
/* dmyext.c */ /* dmyext.c */
void Init_enc(void); void Init_enc(void);
void Init_ext(void); void Init_ext(void);