summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--dir.c38
-rw-r--r--test/ruby/test_dir.rb6
3 files changed, 37 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 205b0588e2..c5fa0a665c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Sat May 17 01:49:23 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (glob_pattern_type): separate names with alphabet but no
+ magical from plain.
+
+ * dir.c (glob_helper): match plain names as-is to treat super-root
+ same as the root. [ruby-core:61552] [Bug #9648]
+
Fri May 16 17:38:22 2014 Koichi Sasada <ko1@atdot.net>
* gc.c (gc_marks, gc_marks_body): increase the counter of young objects
diff --git a/dir.c b/dir.c
index 35e9aa71d2..fb13be1c80 100644
--- a/dir.c
+++ b/dir.c
@@ -1086,12 +1086,16 @@ do_opendir(const char *path, int flags, rb_encoding *enc)
return dirp;
}
+/* Globing pattern */
+enum glob_pattern_type { PLAIN, ALPHA, MAGICAL, RECURSIVE, MATCH_ALL, MATCH_DIR };
+
/* Return nonzero if S has any special globbing chars in it. */
-static int
+static enum glob_pattern_type
has_magic(const char *p, const char *pend, int flags, rb_encoding *enc)
{
const int escape = !(flags & FNM_NOESCAPE);
const int nocase = flags & FNM_CASEFOLD;
+ int hasalpha = 0;
register char c;
@@ -1100,22 +1104,23 @@ has_magic(const char *p, const char *pend, int flags, rb_encoding *enc)
case '*':
case '?':
case '[':
- return 1;
+ return MAGICAL;
case '\\':
if (escape && !(c = *p++))
- return 0;
+ return PLAIN;
continue;
default:
- if (!FNM_SYSCASE && ISALPHA(c) && nocase)
- return 1;
+ if (ISALPHA(c)) {
+ if (FNM_SYSCASE || nocase) hasalpha = 1;
+ }
}
p = Next(p-1, pend, enc);
}
- return 0;
+ return hasalpha ? ALPHA : PLAIN;
}
/* Find separator in globbing pattern. */
@@ -1179,9 +1184,6 @@ remove_backslashes(char *p, register const char *pend, rb_encoding *enc)
return p;
}
-/* Globing pattern */
-enum glob_pattern_type { PLAIN, MAGICAL, RECURSIVE, MATCH_ALL, MATCH_DIR };
-
struct glob_pattern {
char *str;
enum glob_pattern_type type;
@@ -1210,12 +1212,13 @@ glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc)
}
else {
const char *m = find_dirsep(p, e, flags, enc);
- const int magic = has_magic(p, m, 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) ? PLAIN : ALPHA;
char *buf;
- if (!(FNM_SYSCASE || HAVE_HFS || magic) && !recursive && *m) {
+ if (!(FNM_SYSCASE || magic > non_magic) && !recursive && *m) {
const char *m2;
- while (!has_magic(m+1, m2 = find_dirsep(m+1, e, flags, enc), flags, enc) &&
+ while (has_magic(m+1, m2 = find_dirsep(m+1, e, flags, enc), flags, enc) <= non_magic &&
*m2) {
m = m2;
}
@@ -1227,7 +1230,7 @@ glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc)
}
memcpy(buf, p, m-p);
buf[m-p] = '\0';
- tmp->type = magic ? MAGICAL : PLAIN;
+ tmp->type = magic > MAGICAL ? MAGICAL : magic;
tmp->str = buf;
if (*m) {
dirsep = 1;
@@ -1346,6 +1349,7 @@ glob_helper(
case PLAIN:
plain = 1;
break;
+ case ALPHA:
case MAGICAL:
magical = 1;
break;
@@ -1397,7 +1401,7 @@ glob_helper(
if (exist == NO || isdir == NO) return 0;
- if (magical || recursive || ((FNM_SYSCASE || HAVE_HFS) && plain)) {
+ if (magical || recursive) {
struct dirent *dp;
DIR *dirp;
IF_HAVE_HFS(int hfs_p);
@@ -1483,9 +1487,13 @@ glob_helper(
*new_end++ = p; /* append recursive pattern */
p = p->next; /* 0 times recursion */
}
- if (p->type == PLAIN || p->type == MAGICAL) {
+ switch (p->type) {
+ case ALPHA:
+ case MAGICAL:
if (fnmatch(p->str, enc, name, flags) == 0)
*new_end++ = p->next;
+ default:
+ break;
}
}
diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb
index b0d848c83f..3f2acb22fc 100644
--- a/test/ruby/test_dir.rb
+++ b/test/ruby/test_dir.rb
@@ -249,6 +249,12 @@ class TestDir < Test::Unit::TestCase
end
end
+ def test_glob_super_root
+ bug9648 = '[ruby-core:61552] [Bug #9648]'
+ roots = Dir.glob("/*")
+ assert_equal(roots.map {|n| "/..#{n}"}, Dir.glob("/../*"), bug9648)
+ end
+
def test_home
env_home = ENV["HOME"]
env_logdir = ENV["LOGDIR"]