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

ruby-changes:27769

From: nobu <ko1@a...>
Date: Tue, 19 Mar 2013 17:09:15 +0900 (JST)
Subject: [ruby-changes:27769] nobu:r39821 (trunk): compose HFS file names

nobu	2013-03-19 17:06:53 +0900 (Tue, 19 Mar 2013)

  New Revision: 39821

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

  Log:
    compose HFS file names
    
    * dir.c (glob_helper): compose HFS file names from UTF8-MAC.
      [ruby-core:48745] [Bug #7267]

  Modified files:
    trunk/ChangeLog
    trunk/dir.c
    trunk/test/ruby/test_dir_m17n.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 39820)
+++ ChangeLog	(revision 39821)
@@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Mar 19 17:06:50 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* dir.c (glob_helper): compose HFS file names from UTF8-MAC.
+	  [ruby-core:48745] [Bug #7267]
+
 Sat Mar 16 01:44:29 2013  KOSAKI Motohiro  <kosaki.motohiro@g...>
 
 	* internal.h: added a declaration of ruby_kill().
Index: dir.c
===================================================================
--- dir.c	(revision 39820)
+++ dir.c	(revision 39821)
@@ -79,6 +79,49 @@ char *strchr(char*,char); https://github.com/ruby/ruby/blob/trunk/dir.c#L79
 #define opendir(p) rb_w32_uopendir(p)
 #endif
 
+#ifdef __APPLE__
+# define HAVE_HFS 1
+#else
+# define HAVE_HFS 0
+#endif
+#if HAVE_HFS
+#include <sys/param.h>
+#include <sys/mount.h>
+
+rb_encoding *
+rb_utf8mac_encoding(void)
+{
+    static rb_encoding *utf8mac;
+    if (!utf8mac) utf8mac = rb_enc_find("UTF8-MAC");
+    return utf8mac;
+}
+
+static inline int
+is_hfs(const char *path)
+{
+    struct statfs buf;
+    if (statfs(path, &buf) == 0) {
+	return buf.f_type == 17; /* HFS on darwin */
+    }
+    return FALSE;
+}
+
+static inline int
+has_nonascii(const char *ptr, size_t len)
+{
+    while (len > 0) {
+	if (!ISASCII(*ptr)) return 1;
+	ptr++;
+	--len;
+    }
+    return 0;
+}
+
+# define IF_HAVE_HFS(something) something
+#else
+# define IF_HAVE_HFS(something) /* nothing */
+#endif
+
 #define FNM_NOESCAPE	0x01
 #define FNM_PATHNAME	0x02
 #define FNM_DOTMATCH	0x04
@@ -1377,12 +1420,17 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1420
 	struct dirent *dp;
 	DIR *dirp;
 	IF_HAVE_READDIR_R(DEFINE_STRUCT_DIRENT entry);
+	IF_HAVE_HFS(int hfs_p);
 	dirp = do_opendir(*path ? path : ".", flags, enc);
 	if (dirp == NULL) return 0;
+	IF_HAVE_HFS(hfs_p = is_hfs(*path ? path : "."));
 
 	while (READDIR(dirp, enc, &STRUCT_DIRENT(entry), dp)) {
 	    char *buf;
 	    enum answer new_isdir = UNKNOWN;
+	    const char *name;
+	    size_t namlen;
+	    IF_HAVE_HFS(VALUE utf8str = Qnil);
 
 	    if (recursive && dp->d_name[0] == '.') {
 		/* RECURSIVE never match dot files unless FNM_DOTMATCH is set */
@@ -1393,11 +1441,25 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1441
 		if (dp->d_name[1] == '.' && !dp->d_name[2]) continue;
 	    }
 
-	    buf = join_path(path, pathlen, dirsep, dp->d_name, NAMLEN(dp));
+	    name = dp->d_name;
+	    namlen = NAMLEN(dp);
+# if HAVE_HFS
+	    if (hfs_p && has_nonascii(name, namlen)) {
+		rb_encoding *utf8mac = rb_utf8mac_encoding();
+		if (utf8mac) {
+		    utf8str = rb_str_conv_enc(rb_str_new(name, namlen),
+					      utf8mac, rb_utf8_encoding());
+		    RSTRING_GETMEM(utf8str, name, namlen);
+		}
+	    }
+# endif
+	    buf = join_path(path, pathlen, dirsep, name, namlen);
+	    IF_HAVE_HFS(if (!NIL_P(utf8str)) rb_str_resize(utf8str, 0));
 	    if (!buf) {
 		status = -1;
 		break;
 	    }
+	    name = buf + pathlen + (dirsep != 0);
 	    if (recursive) {
 #ifndef _WIN32
 		if (do_lstat(buf, &st, flags) == 0)
@@ -1424,7 +1486,7 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L1486
 		    p = p->next; /* 0 times recursion */
 		}
 		if (p->type == PLAIN || p->type == MAGICAL) {
-		    if (fnmatch(p->str, enc, dp->d_name, flags) == 0)
+		    if (fnmatch(p->str, enc, name, flags) == 0)
 			*new_end++ = p->next;
 		}
 	    }
Index: test/ruby/test_dir_m17n.rb
===================================================================
--- test/ruby/test_dir_m17n.rb	(revision 39820)
+++ test/ruby/test_dir_m17n.rb	(revision 39821)
@@ -269,4 +269,22 @@ class TestDir_M17N < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/ruby/test_dir_m17n.rb#L269
     m = Class.new {define_method(:to_path) {d}}
     assert_raise(Encoding::CompatibilityError) {Dir.glob(m.new)}
   end
+
+  def test_glob_compose
+    bug7267 = '[ruby-core:48745] [Bug #7267]'
+
+    pp = Object.new.extend(Test::Unit::Assertions)
+    def pp.mu_pp(str) #:nodoc:
+      str.dump
+    end
+
+    with_tmpdir {|d|
+      orig = %W"d\u{e9}tente x\u{304c 304e 3050 3052 3054}"
+      orig.each {|n| open(n, "w") {}}
+      orig.each do |o|
+        n = Dir.glob("#{o[0..0]}*")[0]
+        pp.assert_equal(o, n, bug7267)
+      end
+    }
+  end
 end

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

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