[前][次][番号順一覧][スレッド一覧]

ruby-changes:13872

From: nobu <ko1@a...>
Date: Fri, 6 Nov 2009 16:15:41 +0900 (JST)
Subject: [ruby-changes:13872] Ruby:r25672 (mvm): * dir.c (rb_dir_aref, rb_dir_glob): added methods, Dir#[] and

nobu	2009-11-06 16:15:21 +0900 (Fri, 06 Nov 2009)

  New Revision: 25672

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=25672

  Log:
    * dir.c (rb_dir_aref, rb_dir_glob): added methods, Dir#[] and
      Dir#glob.

  Modified files:
    branches/mvm/ChangeLog
    branches/mvm/dir.c
    branches/mvm/version.h

Index: mvm/ChangeLog
===================================================================
--- mvm/ChangeLog	(revision 25671)
+++ mvm/ChangeLog	(revision 25672)
@@ -1,3 +1,8 @@
+Fri Nov  6 16:15:17 2009  Nobuyoshi Nakada  <nobu@r...>
+
+	* dir.c (rb_dir_aref, rb_dir_glob): added methods, Dir#[] and
+	  Dir#glob.
+
 Wed Nov  4 21:04:58 2009  Nobuyoshi Nakada  <nobu@r...>
 
 	* dir.c (GetDIR): fixed a variable name.
Index: mvm/dir.c
===================================================================
--- mvm/dir.c	(revision 25671)
+++ mvm/dir.c	(revision 25672)
@@ -984,9 +984,20 @@
 
 /* System call with warning */
 static int
-do_stat(const char *path, struct stat *pst, int flags)
+do_stat(const struct dir_data *dp, const char *path, struct stat *pst, int flags)
 {
-    int ret = stat(path, pst);
+    int ret = 0;
+    if (dp) {
+#if USE_OPENAT
+	ret = fstatat(dirfd(dp->dir), path, pst, 0);
+#else
+	VALUE fullpath = rb_str_cat2(rb_str_dup(dp->path), path);
+	dirp = stat(RSTRING_PTR(fullpath), pst);
+#endif
+    }
+    else {
+	ret = stat(path, pst);
+    }
     if (ret < 0 && !to_be_ignored(errno))
 	sys_warning(path);
 
@@ -994,9 +1005,20 @@
 }
 
 static int
-do_lstat(const char *path, struct stat *pst, int flags)
+do_lstat(const struct dir_data *dp, const char *path, struct stat *pst, int flags)
 {
-    int ret = lstat(path, pst);
+    int ret = 0;
+    if (dp) {
+#if USE_OPENAT
+	ret = fstatat(dirfd(dp->dir), path, pst, AT_SYMLINK_NOFOLLOW);
+#else
+	VALUE fullpath = rb_str_cat2(rb_str_dup(dp->path), path);
+	dirp = lstat(RSTRING_PTR(fullpath), pst);
+#endif
+    }
+    else {
+	ret = lstat(path, pst);
+    }
     if (ret < 0 && !to_be_ignored(errno))
 	sys_warning(path);
 
@@ -1004,9 +1026,23 @@
 }
 
 static DIR *
-do_opendir(const char *path, int flags)
+do_opendir(const struct dir_data *dp, const char *path, int flags)
 {
-    DIR *dirp = opendir(path);
+    DIR *dirp = NULL;
+    if (dp) {
+#if USE_OPENAT
+	int base = openat(dirfd(dp->dir), path, O_RDONLY|O_LARGEFILE|O_DIRECTORY);
+	if (base != -1 && !(dirp = fdopendir(base))) {
+	    preserving_errno(close(base));
+	}
+#else
+	VALUE fullpath = rb_str_cat2(rb_str_dup(dp->path), path);
+	dirp = opendir(RSTRING_PTR(fullpath));
+#endif
+    }
+    else {
+	dirp = opendir(path);
+    }
     if (dirp == NULL && !to_be_ignored(errno))
 	sys_warning(path);
 
@@ -1218,6 +1254,7 @@
 #endif
 
 struct glob_args {
+    const struct dir_data *base;
     void (*func)(const char *, VALUE, void *);
     const char *path;
     VALUE value;
@@ -1237,6 +1274,7 @@
 
 static int
 glob_helper(
+    const struct dir_data *base,
     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? */
@@ -1280,7 +1318,7 @@
 
     if (*path) {
 	if (match_all && exist == UNKNOWN) {
-	    if (do_lstat(path, &st, flags) == 0) {
+	    if (do_lstat(base, path, &st, flags) == 0) {
 		exist = YES;
 		isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
 	    }
@@ -1290,7 +1328,7 @@
 	    }
 	}
 	if (match_dir && isdir == UNKNOWN) {
-	    if (do_stat(path, &st, flags) == 0) {
+	    if (do_stat(base, path, &st, flags) == 0) {
 		exist = YES;
 		isdir = S_ISDIR(st.st_mode) ? YES : NO;
 	    }
@@ -1316,7 +1354,7 @@
 
     if (magical || recursive) {
 	struct dirent *dp;
-	DIR *dirp = do_opendir(*path ? path : ".", flags);
+	DIR *dirp = do_opendir(base, *path ? path : ".", flags);
 	if (dirp == NULL) return 0;
 
 	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
@@ -1330,7 +1368,7 @@
 	    if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0
 		&& fnmatch("*", rb_usascii_encoding(), dp->d_name, flags) == 0) {
 #ifndef _WIN32
-		if (do_lstat(buf, &st, flags) == 0)
+		if (do_lstat(base, buf, &st, flags) == 0)
 		    new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
 		else
 		    new_isdir = NO;
@@ -1359,7 +1397,7 @@
 		}
 	    }
 
-	    status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end,
+	    status = glob_helper(base, buf, 1, YES, new_isdir, new_beg, new_end,
 				 flags, func, arg, enc);
 	    GLOB_FREE(buf);
 	    GLOB_FREE(new_beg);
@@ -1409,7 +1447,7 @@
 		    status = -1;
 		    break;
 		}
-		status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg,
+		status = glob_helper(base, buf, 1, UNKNOWN, UNKNOWN, new_beg,
 				     new_end, flags, func, arg, enc);
 		GLOB_FREE(buf);
 		GLOB_FREE(new_beg);
@@ -1424,7 +1462,8 @@
 }
 
 static int
-ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
+ruby_glob0(const struct dir_data *base, const char *path, int flags,
+	   ruby_glob_func *func, VALUE arg, rb_encoding *enc)
 {
     struct glob_pattern *list;
     const char *root, *start;
@@ -1451,7 +1490,8 @@
 	GLOB_FREE(buf);
 	return -1;
     }
-    status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg, enc);
+    status = glob_helper(base, buf, 0, UNKNOWN, UNKNOWN,
+			 &list, &list + 1, flags, func, arg, enc);
     glob_free_pattern(list);
     GLOB_FREE(buf);
 
@@ -1461,7 +1501,7 @@
 int
 ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
 {
-    return ruby_glob0(path, flags & ~GLOB_VERBOSE, func, arg,
+    return ruby_glob0(NULL, path, flags & ~GLOB_VERBOSE, func, arg,
 		      rb_ascii8bit_encoding());
 }
 
@@ -1491,7 +1531,7 @@
 	rb_warning("Dir.glob() ignores File::FNM_CASEFOLD");
     }
 
-    return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args,
+    return ruby_glob0(NULL, path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args,
 		      enc);
 }
 
@@ -1567,6 +1607,7 @@
 }
 
 struct brace_args {
+    const struct dir_data *base;
     ruby_glob_func *func;
     VALUE value;
     int flags;
@@ -1577,15 +1618,16 @@
 {
     struct brace_args *arg = (struct brace_args *)val;
 
-    return ruby_glob0(path, arg->flags, arg->func, arg->value, enc);
+    return ruby_glob0(arg->base, path, arg->flags, arg->func, arg->value, enc);
 }
 
 static int
-ruby_brace_glob0(const char *str, int flags, ruby_glob_func *func, VALUE arg,
-		 rb_encoding* enc)
+ruby_brace_glob0(const struct dir_data *base, const char *str, int flags,
+		 ruby_glob_func *func, VALUE arg, rb_encoding* enc)
 {
     struct brace_args args;
 
+    args.base = base;
     args.func = func;
     args.value = arg;
     args.flags = flags;
@@ -1595,12 +1637,12 @@
 int
 ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
 {
-    return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg,
+    return ruby_brace_glob0(NULL, str, flags & ~GLOB_VERBOSE, func, arg,
 			    rb_ascii8bit_encoding());
 }
 
 static int
-push_glob(VALUE ary, VALUE str, int flags)
+push_glob(const struct dir_data *base, VALUE ary, VALUE str, int flags)
 {
     struct glob_args args;
     rb_encoding *enc = rb_enc_get(str);
@@ -1610,12 +1652,12 @@
     args.value = ary;
     args.enc = enc;
 
-    return ruby_brace_glob0(RSTRING_PTR(str), flags | GLOB_VERBOSE,
+    return ruby_brace_glob0(base, RSTRING_PTR(str), flags | GLOB_VERBOSE,
 			    rb_glob_caller, (VALUE)&args, enc);
 }
 
 static VALUE
-rb_push_glob(VALUE str, int flags) /* '\0' is delimiter */
+rb_push_glob(const struct dir_data *base, VALUE str, int flags) /* '\0' is delimiter */
 {
     long offset = 0;
     VALUE ary;
@@ -1624,10 +1666,10 @@
     ary = rb_ary_new();
 
     while (offset < RSTRING_LEN(str)) {
-	char *p, *pend;
+	const char *p, *pend;
 	int status;
 	p = RSTRING_PTR(str) + offset;
-	status = push_glob(ary, rb_enc_str_new(p, strlen(p), rb_enc_get(str)),
+	status = push_glob(base, 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;
@@ -1642,7 +1684,7 @@
 }
 
 static VALUE
-dir_globs(long argc, VALUE *argv, int flags)
+dir_globs(long argc, VALUE *argv, const struct dir_data *base, int flags)
 {
     VALUE ary = rb_ary_new();
     long i;
@@ -1651,13 +1693,22 @@
 	int status;
 	VALUE str = argv[i];
 	SafeStringValue(str);
-	status = push_glob(ary, str, flags);
+	status = push_glob(base, ary, str, flags);
 	if (status) GLOB_JUMP_TAG(status);
     }
 
     return ary;
 }
 
+static VALUE
+dir_aref(int argc, VALUE *argv, const struct dir_data *base)
+{
+    if (argc == 1) {
+	return rb_push_glob(base, argv[0], 0);
+    }
+    return dir_globs(argc, argv, base, 0);
+}
+
 /*
  *  call-seq:
  *     Dir[ array ]                 => array
@@ -1671,10 +1722,42 @@
 static VALUE
 dir_s_aref(int argc, VALUE *argv, VALUE obj)
 {
-    if (argc == 1) {
-	return rb_push_glob(argv[0], 0);
+    return dir_aref(argc, argv, NULL);
+}
+
+static VALUE
+rb_dir_aref(int argc, VALUE *argv, VALUE obj)
+{
+    struct dir_data *base;
+    GetDIR(obj, base);
+    return dir_aref(argc, argv, base);
+}
+
+static VALUE
+dir_glob(int argc, VALUE *argv, const struct dir_data *base)
+{
+    VALUE str, rflags, ary;
+    int flags;
+
+    if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2)
+	flags = NUM2INT(rflags);
+    else
+	flags = 0;
+
+    ary = rb_check_array_type(str);
+    if (NIL_P(ary)) {
+	ary = rb_push_glob(base, str, flags);
     }
-    return dir_globs(argc, argv, 0);
+    else {
+	volatile VALUE v = ary;
+	ary = dir_globs(RARRAY_LEN(v), RARRAY_PTR(v), base, flags);
+    }
+
+    if (rb_block_given_p()) {
+	rb_ary_each(ary);
+	return Qnil;
+    }
+    return ary;
 }
 
 /*
@@ -1740,30 +1823,18 @@
 static VALUE
 dir_s_glob(int argc, VALUE *argv, VALUE obj)
 {
-    VALUE str, rflags, ary;
-    int flags;
+    return dir_glob(argc, argv, NULL);
+}
 
-    if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2)
-	flags = NUM2INT(rflags);
-    else
-	flags = 0;
+static VALUE
+rb_dir_glob(int argc, VALUE *argv, VALUE obj)
+{
+    struct dir_data *base;
+    GetDIR(obj, base);
+    return dir_glob(argc, argv, base);
+}
 
-    ary = rb_check_array_type(str);
-    if (NIL_P(ary)) {
-	ary = rb_push_glob(str, flags);
-    }
-    else {
-	volatile VALUE v = ary;
-	ary = dir_globs(RARRAY_LEN(v), RARRAY_PTR(v), flags);
-    }
 
-    if (rb_block_given_p()) {
-	rb_ary_each(ary);
-	return Qnil;
-    }
-    return ary;
-}
-
 static VALUE
 dir_open_dir(int argc, VALUE *argv)
 {
@@ -2405,6 +2476,8 @@
     rb_define_method(rb_cDir, "rmdir", rb_dir_rmdir, 1);
     rb_define_method(rb_cDir, "unlink", rb_dir_unlink, 1);
     rb_define_method(rb_cDir, "chdir", rb_dir_chdir, -1);
+    rb_define_method(rb_cDir,"glob", rb_dir_glob, -1);
+    rb_define_method(rb_cDir,"[]", rb_dir_aref, -1);
 
     rb_define_singleton_method(rb_cDir,"chdir", dir_s_chdir, -1);
     rb_define_singleton_method(rb_cDir,"getwd", dir_s_getwd, 0);
Index: mvm/version.h
===================================================================
--- mvm/version.h	(revision 25671)
+++ mvm/version.h	(revision 25672)
@@ -1,7 +1,7 @@
 #define RUBY_VERSION "1.9.1"
-#define RUBY_RELEASE_DATE "2009-11-04"
+#define RUBY_RELEASE_DATE "2009-11-06"
 #define RUBY_VERSION_CODE 191
-#define RUBY_RELEASE_CODE 20091104
+#define RUBY_RELEASE_CODE 20091106
 #define RUBY_PATCHLEVEL 5000
 
 #define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
 #define RUBY_VERSION_TEENY 1
 #define RUBY_RELEASE_YEAR 2009
 #define RUBY_RELEASE_MONTH 11
-#define RUBY_RELEASE_DAY 4
+#define RUBY_RELEASE_DAY 6
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]