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

ruby-changes:37903

From: nobu <ko1@a...>
Date: Tue, 17 Mar 2015 17:23:42 +0900 (JST)
Subject: [ruby-changes:37903] nobu:r49983 (trunk): dir.c: fix DT_UNKNOWN recursion

nobu	2015-03-17 17:23:14 +0900 (Tue, 17 Mar 2015)

  New Revision: 49983

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

  Log:
    dir.c: fix DT_UNKNOWN recursion
    
    * dir.c (glob_helper): distinguish not-yet-stated and DT_UNKNOWN
      by readdir, and traverse recursively for the former.  Linux
      readdir returns DT_UNKNOWN on some filesystems, e.g., smbfs,
      iso9660.

  Modified files:
    trunk/ChangeLog
    trunk/dir.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 49982)
+++ ChangeLog	(revision 49983)
@@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Mar 17 17:23:11 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* dir.c (glob_helper): distinguish not-yet-stated and DT_UNKNOWN
+	  by readdir, and traverse recursively for the former.  Linux
+	  readdir returns DT_UNKNOWN on some filesystems, e.g., smbfs,
+	  iso9660.
+
 Mon Mar 16 17:43:21 2015  SHIBATA Hiroshi  <shibata.hiroshi@g...>
 
 	* lib/webrick/server.rb: Fix regression bug in WEBrick's
Index: dir.c
===================================================================
--- dir.c	(revision 49982)
+++ dir.c	(revision 49983)
@@ -1522,7 +1522,25 @@ replace_real_basename(char *path, long b https://github.com/ruby/ruby/blob/trunk/dir.c#L1522
 # error not implemented
 #endif
 
-enum answer {UNKNOWN = -1, NO, YES};
+#ifndef IFTODT
+# define IFTODT(m)	(((m) & S_IFMT) / ((~S_IFMT & S_IFMT-1) + 1))
+#endif
+
+typedef enum {
+#ifdef DT_UNKNOWN
+    path_exist     = DT_UNKNOWN,
+    path_directory = DT_DIR,
+    path_regular   = DT_REG,
+    path_symlink   = DT_LNK,
+#else
+    path_exist,
+    path_directory = IFTODT(S_IFDIR),
+    path_regular   = IFTODT(S_IFREG),
+    path_symlink   = IFTODT(S_IFLNK),
+#endif
+    path_noent = -1,
+    path_unknown = -2
+} rb_pathtype_t;
 
 #ifndef S_ISDIR
 #   define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
@@ -1570,8 +1588,7 @@ static int https://github.com/ruby/ruby/blob/trunk/dir.c#L1588
 glob_helper(
     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? */
+    rb_pathtype_t pathtype, /* type of 'path' */
     struct glob_pattern **beg,
     struct glob_pattern **end,
     int flags,
@@ -1619,31 +1636,27 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1636
 
     pathlen = strlen(path);
     if (*path) {
-	if (match_all && exist == UNKNOWN) {
+	if (match_all && pathtype == path_unknown) {
 	    if (do_lstat(path, &st, flags, enc) == 0) {
-		exist = YES;
-		isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
+		pathtype = IFTODT(st.st_mode);
 	    }
 	    else {
-		exist = NO;
-		isdir = NO;
+		pathtype = path_noent;
 	    }
 	}
-	if (match_dir && isdir == UNKNOWN) {
+	if (match_dir && pathtype == path_unknown) {
 	    if (do_stat(path, &st, flags, enc) == 0) {
-		exist = YES;
-		isdir = S_ISDIR(st.st_mode) ? YES : NO;
+		pathtype = IFTODT(st.st_mode);
 	    }
 	    else {
-		exist = NO;
-		isdir = NO;
+		pathtype = path_noent;
 	    }
 	}
-	if (match_all && exist == YES) {
+	if (match_all && pathtype > path_noent) {
 	    status = glob_call_func(func, path, arg, enc);
 	    if (status) return status;
 	}
-	if (match_dir && isdir == YES) {
+	if (match_dir && pathtype == path_directory) {
 	    char *tmp = join_path(path, pathlen, dirsep, "", 0);
 	    if (!tmp) return -1;
 	    status = glob_call_func(func, tmp, arg, enc);
@@ -1652,7 +1665,7 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1665
 	}
     }
 
-    if (exist == NO || isdir == NO) return 0;
+    if (pathtype == path_noent) return 0;
 
     if (magical || recursive) {
 	struct dirent *dp;
@@ -1694,7 +1707,7 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1707
 # endif
 	while ((dp = READDIR(dirp, enc)) != NULL) {
 	    char *buf;
-	    enum answer new_isdir = UNKNOWN;
+	    rb_pathtype_t new_pathtype = path_unknown;
 	    const char *name;
 	    size_t namlen;
 	    int dotfile = 0;
@@ -1733,13 +1746,11 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1746
 		/* RECURSIVE never match dot files unless FNM_DOTMATCH is set */
 #ifndef DT_DIR
 		if (do_lstat(buf, &st, flags, enc) == 0)
-		    new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
+		    new_pathtype = IFTODT(st.st_mode);
 		else
-		    new_isdir = NO;
+		    new_pathtype = path_noent;
 #else
-		new_isdir = dp->d_type == DT_DIR ? YES :
-		    (dp->d_type == DT_LNK || dp->d_type == DT_UNKNOWN) ? UNKNOWN :
-		    NO;
+		new_pathtype = dp->d_type;
 #endif
 	    }
 
@@ -1753,7 +1764,8 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1764
 	    for (cur = beg; cur < end; ++cur) {
 		struct glob_pattern *p = *cur;
 		if (p->type == RECURSIVE) {
-		    if (new_isdir == YES) /* not symlink but real directory */
+		    if (new_pathtype == path_directory || /* not symlink but real directory */
+			new_pathtype == path_exist)
 			*new_end++ = p; /* append recursive pattern */
 		    p = p->next; /* 0 times recursion */
 		}
@@ -1774,7 +1786,7 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1786
 		}
 	    }
 
-	    status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end,
+	    status = glob_helper(buf, 1, new_pathtype, new_beg, new_end,
 				 flags, func, arg, enc);
 	    GLOB_FREE(buf);
 	    GLOB_FREE(new_beg);
@@ -1835,7 +1847,7 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1847
 		    buf = replace_real_basename(buf, base, enc, IF_NORMALIZE_UTF8PATH(1)+0);
 		}
 #endif
-		status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg,
+		status = glob_helper(buf, 1, path_unknown, new_beg,
 				     new_end, flags, func, arg, enc);
 		GLOB_FREE(buf);
 		GLOB_FREE(new_beg);
@@ -1877,7 +1889,7 @@ ruby_glob0(const char *path, int flags, https://github.com/ruby/ruby/blob/trunk/dir.c#L1889
 	GLOB_FREE(buf);
 	return -1;
     }
-    status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg, enc);
+    status = glob_helper(buf, 0, path_unknown, &list, &list + 1, flags, func, arg, enc);
     glob_free_pattern(list);
     GLOB_FREE(buf);
 

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

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