From 2db158667ae995c2685eb0eb48a5b6430e112e07 Mon Sep 17 00:00:00 2001 From: usa Date: Tue, 8 Jul 2008 02:44:12 +0000 Subject: * dir.c: shoudn't use ruby object in globbing, because glob service routines are called before initializing ruby on some platforms (ex. windows). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17953 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- dir.c | 124 +++++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 51 deletions(-) (limited to 'dir.c') diff --git a/dir.c b/dir.c index f5a15e2301..15769cea57 100644 --- a/dir.c +++ b/dir.c @@ -87,13 +87,14 @@ static int char_casecmp(const char *p1, const char *p2, rb_encoding *enc, const int nocase) { const char *p1end, *p2end; + int c1, c2; if (!*p1) return *p1; if (!*p2) return -*p2; p1end = p1 + strlen(p1); p2end = p2 + strlen(p2); - int c1 = rb_enc_codepoint(p1, p1end, enc); - int c2 = rb_enc_codepoint(p2, p2end, enc); + c1 = rb_enc_codepoint(p1, p1end, enc); + c2 = rb_enc_codepoint(p2, p2end, enc); if (c1 == c2) return 0; if (nocase) { @@ -237,16 +238,16 @@ fnmatch_helper( static int fnmatch( - VALUE pattern, - VALUE string, + const char *pattern, + rb_encoding *enc, + const char *string, int flags) { - const char *p = RSTRING_PTR(pattern); /* pattern */ - const char *s = RSTRING_PTR(string); /* string */ - const char *send = RSTRING_END(string); + const char *p = pattern; + const char *s = string; + const char *send = s + strlen(string); const int period = !(flags & FNM_DOTMATCH); const int pathname = flags & FNM_PATHNAME; - rb_encoding *enc = rb_enc_get(pattern); const char *ptmp = 0; const char *stmp = 0; @@ -1180,9 +1181,10 @@ enum answer { YES, NO, UNKNOWN }; #endif struct glob_args { - void (*func)(VALUE, VALUE); - VALUE path; + void (*func)(const char *, VALUE, rb_encoding *); + const char *path; VALUE value; + rb_encoding *enc; }; static VALUE @@ -1190,15 +1192,15 @@ glob_func_caller(VALUE val) { struct glob_args *args = (struct glob_args *)val; - (*args->func)(args->path, args->value); + (*args->func)(args->path, args->value, args->enc); return Qnil; } -#define glob_call_func(func, path, arg) (*func)(path, arg) +#define glob_call_func(func, path, arg, enc) (*func)(path, arg, enc) static int glob_helper( - VALUE vpath, + const char *path, int dirsep, /* '/' should be placed before appending child entry's name to 'path'. */ enum answer exist, /* Does 'path' indicate an existing entry? */ enum answer isdir, /* Does 'path' indicate a directory or a symlink to a directory? */ @@ -1206,9 +1208,9 @@ glob_helper( struct glob_pattern **end, int flags, ruby_glob_func *func, - VALUE arg) + VALUE arg, + rb_encoding *enc) { - const char *path = RSTRING_PTR(vpath); struct stat st; int status = 0; struct glob_pattern **cur, **new_beg, **new_end; @@ -1261,13 +1263,13 @@ glob_helper( } } if (match_all && exist == YES) { - status = glob_call_func(func, rb_tainted_str_new2(path), arg); + status = glob_call_func(func, path, arg, enc); if (status) return status; } if (match_dir && isdir == YES) { char *tmp = join_path(path, dirsep, ""); if (!tmp) return -1; - status = glob_call_func(func, rb_tainted_str_new2(tmp), arg); + status = glob_call_func(func, tmp, arg, enc); GLOB_FREE(tmp); if (status) return status; } @@ -1289,7 +1291,7 @@ glob_helper( break; } if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0 - && fnmatch(rb_usascii_str_new2("*"), rb_str_new2(dp->d_name), flags) == 0) { + && fnmatch("*", rb_usascii_encoding(), dp->d_name, flags) == 0) { #ifndef _WIN32 if (do_lstat(buf, &st, flags) == 0) new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO; @@ -1315,13 +1317,13 @@ glob_helper( p = p->next; /* 0 times recursion */ } if (p->type == PLAIN || p->type == MAGICAL) { - if (fnmatch(rb_str_new2(p->str), rb_str_new2(dp->d_name), flags) == 0) + if (fnmatch(p->str, enc, dp->d_name, flags) == 0) *new_end++ = p->next; } } - status = glob_helper(rb_enc_str_new(buf, strlen(buf), rb_enc_get(vpath)), 1, - YES, new_isdir, new_beg, new_end, flags, func, arg); + status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end, + flags, func, arg, enc); GLOB_FREE(buf); GLOB_FREE(new_beg); if (status) break; @@ -1347,7 +1349,7 @@ glob_helper( break; } strcpy(name, (*cur)->str); - if (escape) remove_backslashes(name, rb_enc_get(vpath)); + if (escape) remove_backslashes(name, enc); new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg); if (!new_beg) { @@ -1357,7 +1359,7 @@ glob_helper( } *new_end++ = (*cur)->next; for (cur2 = cur + 1; cur2 < copy_end; ++cur2) { - if (*cur2 && fnmatch(rb_str_new2((*cur2)->str), rb_str_new2(name), flags) == 0) { + if (*cur2 && fnmatch((*cur2)->str, enc, name, flags) == 0) { *new_end++ = (*cur2)->next; *cur2 = 0; } @@ -1370,8 +1372,8 @@ glob_helper( status = -1; break; } - status = glob_helper(rb_enc_str_new(buf, strlen(buf), rb_enc_get(vpath)), 1, - UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg); + status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, + new_end, flags, func, arg, enc); GLOB_FREE(buf); GLOB_FREE(new_beg); if (status) break; @@ -1385,14 +1387,15 @@ glob_helper( } static int -ruby_glob0(VALUE path, int flags, ruby_glob_func *func, VALUE arg) +ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc) { struct glob_pattern *list; const char *root, *start; + char *buf; + int n; int status; - VALUE buf; - start = root = RSTRING_PTR(path); + start = root = path; flags |= FNM_SYSCASE; #if defined DOSISH root = rb_path_skip_prefix(root); @@ -1400,14 +1403,20 @@ ruby_glob0(VALUE path, int flags, ruby_glob_func *func, VALUE arg) if (root && *root == '/') root++; - buf = rb_enc_str_new(start, root - start, rb_enc_get(path)); + n = root - start; + buf = GLOB_ALLOC_N(char, n + 1); + if (!buf) return -1; + MEMCPY(buf, start, char, n); + buf[n] = '\0'; - list = glob_make_pattern(root, flags, rb_enc_get(path)); + list = glob_make_pattern(root, flags, enc); if (!list) { + GLOB_FREE(buf); return -1; } - status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg); + status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg, enc); glob_free_pattern(list); + GLOB_FREE(buf); return status; } @@ -1415,51 +1424,59 @@ ruby_glob0(VALUE path, int flags, ruby_glob_func *func, VALUE arg) int ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg) { - return ruby_glob0(rb_str_new2(path), flags & ~GLOB_VERBOSE, func, arg); + return ruby_glob0(path, flags & ~GLOB_VERBOSE, func, arg, + rb_ascii8bit_encoding()); } static int -rb_glob_caller(VALUE path, VALUE a) +rb_glob_caller(const char *path, VALUE a, rb_encoding *enc) { int status; struct glob_args *args = (struct glob_args *)a; args->path = path; + args->enc = enc; rb_protect(glob_func_caller, a, &status); return status; } static int -rb_glob2(VALUE path, int flags, void (*func)(VALUE, VALUE), VALUE arg) +rb_glob2(const char *path, int flags, + void (*func)(const char *, VALUE, rb_encoding *), VALUE arg, + rb_encoding* enc) { struct glob_args args; args.func = func; args.value = arg; + args.enc = enc; if (flags & FNM_SYSCASE) { rb_warning("Dir.glob() ignores File::FNM_CASEFOLD"); } - return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args); + return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args, + enc); } void -rb_glob(const char *path, void (*func)(VALUE, VALUE), VALUE arg) +rb_glob(const char *path, void (*func)(const char *, VALUE, void *), VALUE arg) { - int status = rb_glob2(rb_str_new2(path), 0, func, arg); + int status = rb_glob2(path, 0, func, arg, rb_ascii8bit_encoding()); if (status) GLOB_JUMP_TAG(status); } static void -push_pattern(VALUE path, VALUE ary) +push_pattern(const char *path, VALUE ary, rb_encoding *enc) { - OBJ_TAINT(path); - rb_ary_push(ary, path); + VALUE vpath = rb_tainted_str_new2(path); + rb_enc_associate(vpath, enc); + rb_ary_push(ary, vpath); } static int -ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc) +ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg, + rb_encoding *enc) { const int escape = !(flags & FNM_NOESCAPE); const char *p = str; @@ -1509,7 +1526,7 @@ ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg, r GLOB_FREE(buf); } else if (!lbrace && !rbrace) { - status = (*func)(rb_enc_str_new(s, strlen(s), enc), arg); + status = (*func)(s, arg, enc); } return status; @@ -1522,28 +1539,30 @@ struct brace_args { }; static int -glob_brace(VALUE path, VALUE val) +glob_brace(const char *path, VALUE val, rb_encoding *enc) { struct brace_args *arg = (struct brace_args *)val; - return ruby_glob0(path, arg->flags, arg->func, arg->value); + return ruby_glob0(path, arg->flags, arg->func, arg->value, enc); } static int -ruby_brace_glob0(VALUE str, int flags, ruby_glob_func *func, VALUE arg) +ruby_brace_glob0(const char *str, int flags, ruby_glob_func *func, VALUE arg, + rb_encoding* enc) { struct brace_args args; args.func = func; args.value = arg; args.flags = flags; - return ruby_brace_expand(RSTRING_PTR(str), flags, glob_brace, (VALUE)&args, rb_enc_get(str)); + return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args, enc); } int ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg) { - return ruby_brace_glob0(rb_str_new2(str), flags & ~GLOB_VERBOSE, func, arg); + return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg, + rb_ascii8bit_encoding()); } static int @@ -1553,7 +1572,8 @@ push_glob(VALUE ary, VALUE str, int flags) args.func = push_pattern; args.value = ary; - return ruby_brace_glob0(str, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args); + return ruby_brace_glob0(RSTRING_PTR(str), flags | GLOB_VERBOSE, + rb_glob_caller, (VALUE)&args, rb_enc_get(str)); } static VALUE @@ -1567,9 +1587,10 @@ rb_push_glob(VALUE str, int flags) /* '\0' is delimiter */ while (offset < RSTRING_LEN(str)) { char *p, *pend; + int status; p = RSTRING_PTR(str) + offset; - int status = push_glob(ary, - rb_enc_str_new(p, strlen(p), rb_enc_get(str)), flags); + status = push_glob(ary, rb_enc_str_new(p, strlen(p), rb_enc_get(str)), + flags); if (status) GLOB_JUMP_TAG(status); if (offset >= RSTRING_LEN(str)) break; p += strlen(p) + 1; @@ -1863,7 +1884,8 @@ file_s_fnmatch(int argc, VALUE *argv, VALUE obj) StringValue(pattern); FilePathStringValue(path); - if (fnmatch(pattern, path, flags) == 0) + if (fnmatch(RSTRING_PTR(pattern), rb_enc_get(pattern), RSTRING_PTR(path), + flags) == 0) return Qtrue; return Qfalse; -- cgit v1.2.3