зеркало из https://github.com/github/ruby.git
* 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
This commit is contained in:
Родитель
933d553de0
Коммит
2db158667a
|
@ -1,3 +1,9 @@
|
|||
Tue Jul 8 11:41:17 2008 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* dir.c: shoudn't use ruby object in globbing, because glob service
|
||||
routines are called before initializing ruby on some platforms (ex.
|
||||
windows).
|
||||
|
||||
Tue Jul 8 10:08:40 2008 NARUSE, Yui <naruse@ruby-lang.org>
|
||||
|
||||
* dir.c (Next): use rb_enc_mbclen. [ruby-dev:35390]
|
||||
|
|
124
dir.c
124
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;
|
||||
|
|
|
@ -725,8 +725,8 @@ struct RBignum {
|
|||
|
||||
void rb_obj_infect(VALUE,VALUE);
|
||||
|
||||
typedef int ruby_glob_func(VALUE,VALUE);
|
||||
void rb_glob(const char*,void(*)(VALUE,VALUE),VALUE);
|
||||
typedef int ruby_glob_func(const char*,VALUE, void*);
|
||||
void rb_glob(const char*,void(*)(const char*,VALUE,void*),VALUE);
|
||||
int ruby_glob(const char*,int,ruby_glob_func*,VALUE);
|
||||
int ruby_brace_glob(const char*,int,ruby_glob_func*,VALUE);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче