Skip to content
Browse files

compose HFS file names

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


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39821 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information...
1 parent 353cd01 commit 29dc980e6562b4083f72f121465eca2f5427af39 @nobu nobu committed Mar 19, 2013
Showing with 87 additions and 2 deletions.
  1. +5 −0 ChangeLog
  2. +64 −2 dir.c
  3. +18 −0 test/ruby/test_dir_m17n.rb
View
5 ChangeLog
@@ -1,3 +1,8 @@
+Tue Mar 19 17:06:50 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * 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@gmail.com>
* internal.h: added a declaration of ruby_kill().
View
66 dir.c
@@ -79,6 +79,49 @@ char *strchr(char*,char);
#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(
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(
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(
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;
}
}
View
18 test/ruby/test_dir_m17n.rb
@@ -269,4 +269,22 @@ def test_glob_incompatible
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

0 comments on commit 29dc980

Please sign in to comment.
Something went wrong with that request. Please try again.