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/