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

ruby-changes:36909

From: nobu <ko1@a...>
Date: Thu, 25 Dec 2014 15:36:33 +0900 (JST)
Subject: [ruby-changes:36909] nobu:r48990 (trunk): dir.c: replace_real_basename

nobu	2014-12-25 15:36:18 +0900 (Thu, 25 Dec 2014)

  New Revision: 48990

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

  Log:
    dir.c: replace_real_basename
    
    * dir.c (replace_real_basename): get the real name and replace the
      base name with it by getattrlist(2) if available.
      suggested by Matthew Draper at [ruby-core:67116].  [Bug #10015]
    * dir.c (glob_helper): get the real name of the whole path, not
      only the last name.

  Modified files:
    trunk/ChangeLog
    trunk/configure.in
    trunk/dir.c
    trunk/test/ruby/test_dir.rb
Index: configure.in
===================================================================
--- configure.in	(revision 48989)
+++ configure.in	(revision 48990)
@@ -1188,6 +1188,7 @@ AC_CHECK_HEADERS( \ https://github.com/ruby/ruby/blob/trunk/configure.in#L1188
   malloc_np.h \
   malloc/malloc.h \
   setjmpex.h \
+  sys/attr.h \
   sys/id.h
 )
 
@@ -2038,6 +2039,7 @@ AC_CHECK_FUNCS(fmod) https://github.com/ruby/ruby/blob/trunk/configure.in#L2039
 AC_CHECK_FUNCS(fsync)
 AC_CHECK_FUNCS(ftruncate)
 AC_CHECK_FUNCS(ftruncate64)		# used for Win32 platform
+AC_CHECK_FUNCS(getattrlist)
 AC_CHECK_FUNCS(getcwd)
 AC_CHECK_FUNCS(getgidx)
 AC_CHECK_FUNCS(getgrnam)
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 48989)
+++ ChangeLog	(revision 48990)
@@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Dec 25 15:36:15 2014  Nobuyoshi Nakada  <nobu@r...>
+
+	* dir.c (replace_real_basename): get the real name and replace the
+	  base name with it by getattrlist(2) if available.
+	  suggested by Matthew Draper at [ruby-core:67116].  [Bug #10015]
+
+	* dir.c (glob_helper): get the real name of the whole path, not
+	  only the last name.
+
 Thu Dec 25 13:59:17 2014  Nobuyoshi Nakada  <nobu@r...>
 
 	* configure.in (NET_LUID): include also ifdef.h as a workaround of
Index: dir.c
===================================================================
--- dir.c	(revision 48989)
+++ dir.c	(revision 48990)
@@ -73,6 +73,16 @@ char *strchr(char*,char); https://github.com/ruby/ruby/blob/trunk/dir.c#L73
 #define opendir(p) rb_w32_uopendir(p)
 #endif
 
+#ifdef HAVE_SYS_ATTR_H
+#include <sys/attr.h>
+#endif
+
+#ifdef HAVE_GETATTRLIST
+# define USE_NAME_ON_FS 1
+#else
+# define USE_NAME_ON_FS 0
+#endif
+
 #ifdef __APPLE__
 # define HAVE_HFS 1
 #else
@@ -1053,6 +1063,7 @@ sys_warning_1(VALUE mesg) https://github.com/ruby/ruby/blob/trunk/dir.c#L1063
 
 #define GLOB_ALLOC(type) ((type *)malloc(sizeof(type)))
 #define GLOB_ALLOC_N(type, n) ((type *)malloc(sizeof(type) * (n)))
+#define GLOB_REALLOC(ptr, size) realloc((ptr), (size))
 #define GLOB_FREE(ptr) free(ptr)
 #define GLOB_JUMP_TAG(status) (((status) == -1) ? rb_memerror() : rb_jump_tag(status))
 
@@ -1241,8 +1252,7 @@ glob_make_pattern(const char *p, const c https://github.com/ruby/ruby/blob/trunk/dir.c#L1252
 	else {
 	    const char *m = find_dirsep(p, e, flags, enc);
 	    const enum glob_pattern_type magic = has_magic(p, m, flags, enc);
-	    const enum glob_pattern_type non_magic =
-		((HAVE_HFS || FNM_SYSCASE) && (m == e || (m+1 == e && *m == '/'))) ? PLAIN : ALPHA;
+	    const enum glob_pattern_type non_magic = (USE_NAME_ON_FS || FNM_SYSCASE) ? PLAIN : ALPHA;
 	    char *buf;
 
 	    if (!(FNM_SYSCASE || magic > non_magic) && !recursive && *m) {
@@ -1316,6 +1326,45 @@ join_path(const char *path, long len, in https://github.com/ruby/ruby/blob/trunk/dir.c#L1326
     return buf;
 }
 
+#ifdef HAVE_GETATTRLIST
+static char *
+replace_real_basename(char *path, long base, int hfs_p)
+{
+    u_int32_t attrbuf[(sizeof(attrreference_t) + MAXPATHLEN * 3 + sizeof(u_int32_t) - 1) / sizeof(u_int32_t) + 1];
+    struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_NAME};
+    const attrreference_t *ar = (void *)(attrbuf+1);
+    const char *name;
+    long len;
+    char *tmp;
+    IF_HAVE_HFS(VALUE utf8str = Qnil);
+
+    if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
+	return path;
+
+    name = (char *)ar + ar->attr_dataoffset;
+    len = (long)ar->attr_length - 1;
+    if (name + len > (char *)attrbuf + sizeof(attrbuf))
+	return path;
+
+# if HAVE_HFS
+    if (hfs_p && has_nonascii(name, len)) {
+	if (!NIL_P(utf8str = rb_str_normalize_ospath(name, len))) {
+	    RSTRING_GETMEM(utf8str, name, len);
+	}
+    }
+# endif
+
+    tmp = GLOB_REALLOC(path, base + len + 1);
+    if (tmp) {
+	path = tmp;
+	memcpy(path + base, name, len);
+	path[base + len] = '\0';
+    }
+    IF_HAVE_HFS(if (!NIL_P(utf8str)) rb_str_resize(utf8str, 0));
+    return path;
+}
+#endif
+
 enum answer {UNKNOWN = -1, NO, YES};
 
 #ifndef S_ISDIR
@@ -1379,7 +1428,11 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1428
 	    plain = 1;
 	    break;
 	  case ALPHA:
+#ifdef HAVE_GETATTRLIST
+	    plain = 1;
+#else
 	    magical = 1;
+#endif
 	    break;
 	  case MAGICAL:
 	    magical = 2;
@@ -1602,6 +1655,12 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1655
 		    status = -1;
 		    break;
 		}
+#ifdef HAVE_GETATTRLIST
+		if ((*cur)->type == ALPHA) {
+		    long base = pathlen + (dirsep != 0);
+		    buf = replace_real_basename(buf, base, IF_HAVE_HFS(1)+0);
+		}
+#endif
 		status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg,
 				     new_end, flags, func, arg, enc);
 		GLOB_FREE(buf);
Index: test/ruby/test_dir.rb
===================================================================
--- test/ruby/test_dir.rb	(revision 48989)
+++ test/ruby/test_dir.rb	(revision 48990)
@@ -237,16 +237,8 @@ class TestDir < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_dir.rb#L237
       return unless File.exist?("filewithcases")
       assert_equal(%w"FileWithCases", Dir.glob("filewithcases"), feature5994)
     end
-    Dir.chdir(File.join(@root, "c")) do
-      open("FileWithCases", "w") {}
-      mode = File.stat(".").mode
-      begin
-        File.chmod(mode & ~0444, ".")
-        return if mode == File.stat(".").mode
-        assert_equal(%w"filewithcases", Dir.glob("filewithcases"), feature5994)
-      ensure
-        File.chmod(mode, ".")
-      end
+    Dir.chdir(@root) do
+      assert_equal(%w"a/FileWithCases", Dir.glob("A/filewithcases"), feature5994)
     end
   end
 

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

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