1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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
This commit is contained in:
nobu 2013-03-19 08:06:53 +00:00
parent 353cd01e2f
commit 29dc980e65
3 changed files with 87 additions and 2 deletions

View file

@ -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().

66
dir.c
View file

@ -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 file

@ -269,4 +269,22 @@ class TestDir_M17N < Test::Unit::TestCase
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