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

ruby-changes:39025

From: nobu <ko1@a...>
Date: Thu, 2 Jul 2015 16:15:29 +0900 (JST)
Subject: [ruby-changes:39025] nobu:r51106 (trunk): dir.c: update path type

nobu	2015-07-02 16:15:09 +0900 (Thu, 02 Jul 2015)

  New Revision: 51106

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

  Log:
    dir.c: update path type
    
    * dir.c (replace_real_basename): update path type by the target
      attributes if possible, to improve the performance.  [Bug #10015]

  Modified files:
    trunk/ChangeLog
    trunk/dir.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 51105)
+++ ChangeLog	(revision 51106)
@@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Jul  2 16:15:04 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* dir.c (replace_real_basename): update path type by the target
+	  attributes if possible, to improve the performance.  [Bug #10015]
+
 Thu Jul  2 14:45:53 2015  NAKAMURA Usaku  <usa@r...>
 
 	* st.c: get rid of VC++'s warnings of C4700 (uninitialized local
Index: dir.c
===================================================================
--- dir.c	(revision 51105)
+++ dir.c	(revision 51106)
@@ -147,6 +147,26 @@ has_nonascii(const char *ptr, size_t len https://github.com/ruby/ruby/blob/trunk/dir.c#L147
 # define IF_NORMALIZE_UTF8PATH(something) /* nothing */
 #endif
 
+#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;
+
 #define FNM_NOESCAPE	0x01
 #define FNM_PATHNAME	0x02
 #define FNM_DOTMATCH	0x04
@@ -1442,23 +1462,31 @@ is_case_sensitive(DIR *dirp) https://github.com/ruby/ruby/blob/trunk/dir.c#L1462
 }
 
 static char *
-replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p)
+replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, rb_pathtype_t *type)
 {
     struct {
 	u_int32_t length;
 	attrreference_t ref[1];
+	fsobj_type_t objtype;
 	char path[MAXPATHLEN * 3];
     } __attribute__((aligned(4), packed)) attrbuf[1];
-    struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_NAME};
+    struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_NAME|ATTR_CMN_OBJTYPE};
     const attrreference_t *const ar = attrbuf[0].ref;
     const char *name;
     long len;
     char *tmp;
     IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil);
 
+    *type = path_noent;
     if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
 	return path;
 
+    switch (attrbuf[0].objtype) {
+      case VREG: *type = path_regular; break;
+      case VDIR: *type = path_directory; break;
+      case VLNK: *type = path_symlink; break;
+      default: *type = path_exist; break;
+    }
     name = (char *)ar + ar->attr_dataoffset;
     len = (long)ar->attr_length - 1;
     if (name + len > (char *)attrbuf + sizeof(attrbuf))
@@ -1485,7 +1513,7 @@ replace_real_basename(char *path, long b https://github.com/ruby/ruby/blob/trunk/dir.c#L1513
 VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
 
 static char *
-replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p)
+replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, rb_pathtype_t *type)
 {
     char *plainname = path;
     volatile VALUE tmp = 0;
@@ -1508,8 +1536,15 @@ replace_real_basename(char *path, long b https://github.com/ruby/ruby/blob/trunk/dir.c#L1536
     if (GetFileAttributesExW(wplain, GetFileExInfoStandard, &fa))
 	h = FindFirstFileW(wplain, &fd);
     free(wplain);
-    if (h == INVALID_HANDLE_VALUE) return path;
+    if (h == INVALID_HANDLE_VALUE) {
+	*type = path_noent;
+	return path;
+    }
     FindClose(h);
+    *type =
+	(fa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? path_symlink :
+	(fa.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? path_directory :
+	path_regular;
     if (tmp) {
 	char *buf;
 	tmp = rb_w32_conv_from_wchar(fd.cFileName, enc);
@@ -1544,26 +1579,6 @@ replace_real_basename(char *path, long b https://github.com/ruby/ruby/blob/trunk/dir.c#L1579
 # error not implemented
 #endif
 
-#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)
 #endif
@@ -1830,6 +1845,7 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1845
 
 	for (cur = copy_beg; cur < copy_end; ++cur) {
 	    if (*cur) {
+		rb_pathtype_t new_pathtype = path_unknown;
 		char *buf;
 		char *name;
 		size_t len = strlen((*cur)->str) + 1;
@@ -1866,10 +1882,11 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1882
 #if USE_NAME_ON_FS == 1
 		if ((*cur)->type == ALPHA) {
 		    long base = pathlen + (dirsep != 0);
-		    buf = replace_real_basename(buf, base, enc, IF_NORMALIZE_UTF8PATH(1)+0);
+		    buf = replace_real_basename(buf, base, enc, IF_NORMALIZE_UTF8PATH(1)+0,
+						&new_pathtype);
 		}
 #endif
-		status = glob_helper(buf, 1, path_unknown, new_beg,
+		status = glob_helper(buf, 1, new_pathtype, new_beg,
 				     new_end, flags, func, arg, enc);
 		GLOB_FREE(buf);
 		GLOB_FREE(new_beg);

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

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