summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c125
1 files changed, 81 insertions, 44 deletions
diff --git a/dir.c b/dir.c
index 37cf332cb5..187ae1896e 100644
--- a/dir.c
+++ b/dir.c
@@ -26,10 +26,10 @@
#include <unistd.h>
#endif
-#if HAVE_DIRENT_H
+#if defined HAVE_DIRENT_H && !defined NT
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
-#elif HAVE_DIRECT_H
+#elif defined HAVE_DIRECT_H && !defined NT
# include <direct.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
@@ -44,8 +44,8 @@
# if HAVE_NDIR_H
# include <ndir.h>
# endif
-# if defined(NT) && defined(_MSC_VER)
-# include "missing/dir.h"
+# if defined(NT)
+# include "win32/dir.h"
# endif
#endif
@@ -61,6 +61,10 @@ char *strchr _((char*,char));
#include <ctype.h>
+#ifndef HAVE_LSTAT
+#define lstat rb_sys_stat
+#endif
+
#define FNM_NOESCAPE 0x01
#define FNM_PATHNAME 0x02
#define FNM_PERIOD 0x04
@@ -69,7 +73,7 @@ char *strchr _((char*,char));
#define FNM_NOMATCH 1
#define FNM_ERROR 2
-#define downcase(c) (nocase && isupper(c) ? tolower(c) : (c))
+#define downcase(c) (nocase && ISUPPER(c) ? tolower(c) : (c))
#if defined DOSISH
#define isdirsep(c) ((c) == '/' || (c) == '\\')
@@ -126,17 +130,18 @@ range(pat, test, flags)
return 0;
}
+#define ISDIRSEP(c) (pathname && isdirsep(c))
#define PERIOD(s) (period && *(s) == '.' && \
- ((s) == string || pathname && isdirsep(*(s))))
+ ((s) == string || ISDIRSEP((s)[-1])))
static int
fnmatch(pat, string, flags)
- char *pat;
- char *string;
+ const char *pat;
+ const char *string;
int flags;
{
int c;
int test;
- char *s = string;
+ const char *s = string;
int escape = !(flags & FNM_NOESCAPE);
int pathname = flags & FNM_PATHNAME;
int period = flags & FNM_PERIOD;
@@ -145,7 +150,7 @@ fnmatch(pat, string, flags)
while (c = *pat++) {
switch (c) {
case '?':
- if (!*s || pathname && isdirsep(*s) || PERIOD(s))
+ if (!*s || ISDIRSEP(*s) || PERIOD(s))
return FNM_NOMATCH;
s++;
break;
@@ -162,7 +167,7 @@ fnmatch(pat, string, flags)
else
return 0;
}
- else if (pathname && isdirsep(c)) {
+ else if (ISDIRSEP(c)) {
s = find_dirsep(s);
if (s)
break;
@@ -176,14 +181,14 @@ fnmatch(pat, string, flags)
if ((c == '[' || downcase(*s) == test) &&
!fnmatch(pat, s, flags & ~FNM_PERIOD))
return 0;
- else if (pathname && isdirsep(*s))
+ else if (ISDIRSEP(*s))
break;
s++;
}
return FNM_NOMATCH;
case '[':
- if (!*s || pathname && isdirsep(*s) || PERIOD(s))
+ if (!*s || ISDIRSEP(*s) || PERIOD(s))
return FNM_NOMATCH;
pat = range(pat, *s, flags);
if (!pat)
@@ -207,7 +212,7 @@ fnmatch(pat, string, flags)
default:
#if defined DOSISH
- if (pathname && isdirsep(c) && isdirsep(*s))
+ if (ISDIRSEP(c) && isdirsep(*s))
;
else
#endif
@@ -490,12 +495,14 @@ dir_s_rmdir(obj, dir)
/* Return nonzero if S has any special globbing chars in it. */
static int
-has_magic(s, send)
+has_magic(s, send, flags)
char *s, *send;
+ int flags;
{
register char *p = s;
register char c;
int open = 0;
+ int escape = !(flags & FNM_NOESCAPE);
while ((c = *p++) != '\0') {
switch (c) {
@@ -512,7 +519,7 @@ has_magic(s, send)
continue;
case '\\':
- if (*p++ == '\0')
+ if (escape && *p++ == '\0')
return Qfalse;
}
@@ -531,7 +538,11 @@ extract_path(p, pend)
len = pend - p;
alloc = ALLOC_N(char, len+1);
memcpy(alloc, p, len);
- if (len > 1 && pend[-1] == '/') {
+ if (len > 1 && pend[-1] == '/'
+#if defined DOSISH
+ && pend[-2] != ':'
+#endif
+ ) {
alloc[len-1] = 0;
}
else {
@@ -558,17 +569,17 @@ extract_elem(path)
#endif
void
-rb_glob_helper(path, flag, func, arg)
+rb_glob_helper(path, flags, func, arg)
char *path;
- int flag;
+ int flags;
void (*func)();
VALUE arg;
{
struct stat st;
char *p, *m;
- if (!has_magic(path, 0)) {
- if (stat(path, &st) == 0) {
+ if (!has_magic(path, 0, flags)) {
+ if (rb_sys_stat(path, &st) == 0) {
(*func)(path, arg);
}
return;
@@ -578,7 +589,7 @@ rb_glob_helper(path, flag, func, arg)
while (p) {
if (*p == '/') p++;
m = strchr(p, '/');
- if (has_magic(p, m)) {
+ if (has_magic(p, m, flags)) {
char *dir, *base, *magic, *buf;
DIR *dirp;
struct dirent *dp;
@@ -598,15 +609,30 @@ rb_glob_helper(path, flag, func, arg)
recursive = 1;
buf = ALLOC_N(char, strlen(base)+strlen(m)+3);
sprintf(buf, "%s%s%s", base, (*base)?"":".", m);
- rb_glob_helper(buf, flag, func, arg);
+ rb_glob_helper(buf, flags, func, arg);
free(buf);
}
- dirp = opendir(dir);
- if (dirp == NULL) {
- free(base);
- break;
+ if (rb_sys_stat(dir, &st) < 0) {
+ free(base);
+ break;
}
+ if (S_ISDIR(st.st_mode)) {
+ dirp = opendir(dir);
+ if (dirp == NULL) {
+ free(base);
+ break;
+ }
+ }
+ else {
+ free(base);
+ break;
+ }
+
+#if defined DOSISH
+#define BASE (*base && !((isdirsep(*base) && !base[1]) || (base[1] == ':' && isdirsep(base[2]) && !base[3])))
+#else
#define BASE (*base && !(*base == '/' && !base[1]))
+#endif
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
if (recursive) {
@@ -614,11 +640,19 @@ rb_glob_helper(path, flag, func, arg)
continue;
buf = ALLOC_N(char, strlen(base)+NAMLEN(dp)+strlen(m)+6);
sprintf(buf, "%s%s%s/**%s", base, (BASE)?"/":"", dp->d_name, m);
- rb_glob_helper(buf, flag, func, arg);
+ sprintf(buf, "%s%s%s", base, (BASE)?"/":"", dp->d_name);
+ if (lstat(buf, &st) < 0) {
+ continue;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ strcat(buf, "/**");
+ strcat(buf, m);
+ rb_glob_helper(buf, flags, func, arg);
+ }
free(buf);
continue;
}
- if (fnmatch(magic, dp->d_name, flag) == 0) {
+ if (fnmatch(magic, dp->d_name, flags) == 0) {
buf = ALLOC_N(char, strlen(base)+NAMLEN(dp)+2);
sprintf(buf, "%s%s%s", base, (BASE)?"/":"", dp->d_name);
if (!m) {
@@ -643,7 +677,7 @@ rb_glob_helper(path, flag, func, arg)
char *t = ALLOC_N(char, len+mlen+1);
sprintf(t, "%s%s", link->path, m);
- rb_glob_helper(t, flag, func, arg);
+ rb_glob_helper(t, flags, func, arg);
free(t);
}
tmp = link;
@@ -662,7 +696,7 @@ rb_glob(path, func, arg)
void (*func)();
VALUE arg;
{
- rb_glob_helper(path, FNM_PERIOD|FNM_PATHNAME, func, arg);
+ rb_glob_helper(path, FNM_PERIOD, func, arg);
}
void
@@ -671,7 +705,7 @@ rb_iglob(path, func, arg)
void (*func)();
VALUE arg;
{
- rb_glob_helper(path, FNM_PERIOD|FNM_PATHNAME|FNM_NOCASE, func, arg);
+ rb_glob_helper(path, FNM_PERIOD|FNM_NOCASE, func, arg);
}
static void
@@ -679,7 +713,14 @@ push_pattern(path, ary)
char *path;
VALUE ary;
{
- rb_ary_push(ary, rb_tainted_str_new2(path));
+ VALUE str = rb_tainted_str_new2(path);
+
+ if (ary) {
+ rb_ary_push(ary, str);
+ }
+ else {
+ rb_yield(str);
+ }
}
static void
@@ -750,15 +791,19 @@ dir_s_glob(dir, str)
VALUE dir, str;
{
char *p, *pend;
- char buffer[MAXPATHLEN], *buf = buffer;
+ char buffer[MAXPATHLEN], *buf;
char *t;
int nest;
- VALUE ary;
+ VALUE ary = 0;
Check_SafeStr(str);
- ary = rb_ary_new();
+ if (!rb_block_given_p()) {
+ ary = rb_ary_new();
+ }
if (RSTRING(str)->len >= MAXPATHLEN)
buf = xmalloc(RSTRING(str)->len + 1);
+ else
+ buf = buffer;
p = RSTRING(str)->ptr;
pend = p + RSTRING(str)->len;
@@ -783,14 +828,6 @@ dir_s_glob(dir, str)
}
if (buf != buffer)
free(buf);
- if (rb_block_given_p()) {
- long len = RARRAY(ary)->len;
- VALUE *ptr = RARRAY(ary)->ptr;
-
- while (len--) {
- rb_yield(*ptr++);
- }
- }
return ary;
}