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

ruby-changes:37811

From: nobu <ko1@a...>
Date: Sun, 8 Mar 2015 16:57:53 +0900 (JST)
Subject: [ruby-changes:37811] nobu:r49892 (trunk): dir.c: glob short names

nobu	2015-03-08 16:57:38 +0900 (Sun, 08 Mar 2015)

  New Revision: 49892

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

  Log:
    dir.c: glob short names
    
    * dir.c (glob_helper): match patterns against legacy short names
      too, not only ordinary names.  [ruby-core:67954] [Bug #10819]
    * win32/dir.h (struct direct): add short name members.
    * win32/win32.c (opendir_internal, readdir_internal): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/dir.c
    trunk/test/ruby/test_dir.rb
    trunk/win32/dir.h
    trunk/win32/win32.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 49891)
+++ ChangeLog	(revision 49892)
@@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun Mar  8 16:57:35 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* dir.c (glob_helper): match patterns against legacy short names
+	  too, not only ordinary names.  [ruby-core:67954] [Bug #10819]
+
+	* win32/dir.h (struct direct): add short name members.
+
+	* win32/win32.c (opendir_internal, readdir_internal): ditto.
+
 Sat Mar  7 09:36:05 2015  SHIBATA Hiroshi  <shibata.hiroshi@g...>
 
 	* array.c: document that first element is kept when using
Index: dir.c
===================================================================
--- dir.c	(revision 49891)
+++ dir.c	(revision 49892)
@@ -1554,6 +1554,18 @@ glob_func_caller(VALUE val) https://github.com/ruby/ruby/blob/trunk/dir.c#L1554
     return Qnil;
 }
 
+static inline int
+dirent_match(const char *pat, rb_encoding *enc, const char *name, const struct dirent *dp, int flags)
+{
+    if (fnmatch(pat, enc, name, flags) == 0) return 1;
+#ifdef _WIN32
+    if (dp->d_altname) {
+	if (fnmatch(pat, enc, dp->d_altname, flags) == 0) return 1;
+    }
+#endif
+    return 0;
+}
+
 static int
 glob_helper(
     const char *path,
@@ -1753,7 +1765,7 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1765
 # endif
 		  case PLAIN:
 		  case MAGICAL:
-		    if (fnmatch(p->str, enc, name, flags) == 0)
+		    if (dirent_match(p->str, enc, name, dp, flags))
 			*new_end++ = p->next;
 		  default:
 		    break;
Index: win32/win32.c
===================================================================
--- win32/win32.c	(revision 49891)
+++ win32/win32.c	(revision 49892)
@@ -1870,6 +1870,7 @@ opendir_internal(WCHAR *wpath, const cha https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L1870
     HANDLE fh;
     DIR *p;
     long len;
+    long altlen;
     long idx;
     WCHAR *tmpW;
     char *tmp;
@@ -1908,12 +1909,13 @@ opendir_internal(WCHAR *wpath, const cha https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L1909
     //
     do {
 	len = lstrlenW(fd.cFileName) + 1;
+	altlen = lstrlenW(fd.cAlternateFileName) + 1;
 
 	//
 	// bump the string table size by enough for the
 	// new name and it's null terminator
 	//
-	tmpW = realloc(p->start, (idx + len) * sizeof(WCHAR));
+	tmpW = realloc(p->start, (idx + len + altlen) * sizeof(WCHAR));
 	if (!tmpW) {
 	  error:
 	    rb_w32_closedir(p);
@@ -1924,6 +1926,7 @@ opendir_internal(WCHAR *wpath, const cha https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L1926
 
 	p->start = tmpW;
 	memcpy(&p->start[idx], fd.cFileName, len * sizeof(WCHAR));
+	memcpy(&p->start[idx + len], fd.cAlternateFileName, altlen * sizeof(WCHAR));
 
 	if (p->nfiles % DIRENT_PER_CHAR == 0) {
 	    tmp = realloc(p->bits, p->nfiles / DIRENT_PER_CHAR + 1);
@@ -1938,7 +1941,7 @@ opendir_internal(WCHAR *wpath, const cha https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L1941
 	    SetBit(p->bits, BitOfIsRep(p->nfiles));
 
 	p->nfiles++;
-	idx += len;
+	idx += len + altlen;
     } while (FindNextFileW(fh, &fd));
     FindClose(fh);
     p->size = idx;
@@ -2023,6 +2026,7 @@ move_to_next_entry(DIR *dirp) https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L2026
     if (dirp->curr) {
 	dirp->loc++;
 	dirp->curr += lstrlenW(dirp->curr) + 1;
+	dirp->curr += lstrlenW(dirp->curr) + 1;
 	if (dirp->curr >= (dirp->start + dirp->size)) {
 	    dirp->curr = NULL;
 	}
@@ -2035,11 +2039,16 @@ move_to_next_entry(DIR *dirp) https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L2039
 //
 /* License: Ruby's */
 static BOOL
-win32_direct_conv(const WCHAR *file, struct direct *entry, const void *enc)
+win32_direct_conv(const WCHAR *file, const WCHAR *alt, struct direct *entry, const void *enc)
 {
     UINT cp = *((UINT *)enc);
     if (!(entry->d_name = wstr_to_mbstr(cp, file, -1, &entry->d_namlen)))
 	return FALSE;
+    if (alt && *alt) {
+	long altlen = 0;
+	entry->d_altname = wstr_to_mbstr(cp, alt, -1, &altlen);
+	entry->d_altlen = altlen;
+    }
     return TRUE;
 }
 
@@ -2091,16 +2100,21 @@ rb_w32_conv_from_wstr(const WCHAR *wstr, https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L2100
 
 /* License: Ruby's */
 static BOOL
-ruby_direct_conv(const WCHAR *file, struct direct *entry, const void *enc)
+ruby_direct_conv(const WCHAR *file, const WCHAR *alt, struct direct *entry, const void *enc)
 {
     if (!(entry->d_name = rb_w32_conv_from_wstr(file, &entry->d_namlen, enc)))
 	return FALSE;
+    if (alt && *alt) {
+	long altlen = 0;
+	entry->d_altname = rb_w32_conv_from_wstr(alt, &altlen, enc);
+	entry->d_altlen = altlen;
+    }
     return TRUE;
 }
 
 /* License: Artistic or GPL */
 static struct direct *
-readdir_internal(DIR *dirp, BOOL (*conv)(const WCHAR *, struct direct *, const void *), const void *enc)
+readdir_internal(DIR *dirp, BOOL (*conv)(const WCHAR *, const WCHAR *, struct direct *, const void *), const void *enc)
 {
     static int dummy = 0;
 
@@ -2111,7 +2125,11 @@ readdir_internal(DIR *dirp, BOOL (*conv) https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L2125
 	//
 	if (dirp->dirstr.d_name)
 	    free(dirp->dirstr.d_name);
-	conv(dirp->curr, &dirp->dirstr, enc);
+	if (dirp->dirstr.d_altname)
+	    free(dirp->dirstr.d_altname);
+	dirp->dirstr.d_altname = 0;
+	dirp->dirstr.d_altlen = 0;
+	conv(dirp->curr, dirp->curr + lstrlenW(dirp->curr) + 1, &dirp->dirstr, enc);
 
 	//
 	// Fake inode
@@ -2202,6 +2220,8 @@ rb_w32_closedir(DIR *dirp) https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L2220
     if (dirp) {
 	if (dirp->dirstr.d_name)
 	    free(dirp->dirstr.d_name);
+	if (dirp->dirstr.d_altname)
+	    free(dirp->dirstr.d_altname);
 	if (dirp->start)
 	    free(dirp->start);
 	if (dirp->bits)
Index: win32/dir.h
===================================================================
--- win32/dir.h	(revision 49891)
+++ win32/dir.h	(revision 49892)
@@ -13,6 +13,8 @@ struct direct https://github.com/ruby/ruby/blob/trunk/win32/dir.h#L13
     long d_namlen;
     ino_t d_ino;
     char *d_name;
+    char *d_altname; /* short name */
+    short d_altlen;
     char d_isdir; /* directory */
     char d_isrep; /* reparse point */
 };
Index: test/ruby/test_dir.rb
===================================================================
--- test/ruby/test_dir.rb	(revision 49891)
+++ test/ruby/test_dir.rb	(revision 49892)
@@ -256,7 +256,11 @@ class TestDir < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_dir.rb#L256
       skip unless File.directory?(short)
       entries = Dir.glob("#{short}/Common*")
       assert_not_empty(entries, bug10819)
-      assert_equal(Dir.glob("#{File.expand_path(short)}/Common*"), entries, bug10819)
+      long = File.expand_path(short)
+      assert_equal(Dir.glob("#{long}/Common*"), entries, bug10819)
+      wild = short.sub(/1\z/, '*')
+      assert_include(Dir.glob(wild), long, bug10819)
+      assert_empty(entries - Dir.glob("#{wild}/Common*"), bug10819)
     end
   end
 

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

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