summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1999-05-07 08:24:37 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1999-05-07 08:24:37 +0000
commit3376271d9e3c6b96acb63720eb4d59643abeb32c (patch)
tree9a9d174d90329951c082fb46e950a8edcdb001b8 /dir.c
parentc09a226803d177f2ab3426ec2c72a3186d789010 (diff)
990507
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_3@460 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c182
1 files changed, 161 insertions, 21 deletions
diff --git a/dir.c b/dir.c
index 31c574e536..c12fd542bc 100644
--- a/dir.c
+++ b/dir.c
@@ -47,14 +47,23 @@
# endif
#endif
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#else
+#include "missing/fnmatch.h"
+#endif
+
#include <errno.h>
+#ifdef USE_CWGUSI
+# include <sys/errno.h>
+#endif
-#ifndef NT
+#ifndef HAVE_STDLIB_H
char *getenv();
#endif
-#ifdef USE_CWGUSI
-# include <sys/errno.h>
+#ifndef HAVE_STRING_H
+char *strchr _((char*,char));
#endif
VALUE rb_cDir;
@@ -149,10 +158,10 @@ static VALUE
dir_tell(dir)
VALUE dir;
{
+#if !defined(__CYGWIN32__) && !defined(__BEOS__)
DIR *dirp;
- int pos;
+ long pos;
-#if !defined(__CYGWIN32__) && !defined(__BEOS__)
GetDIR(dir, dirp);
pos = telldir(dirp);
return rb_int2inum(pos);
@@ -303,29 +312,158 @@ dir_s_rmdir(obj, dir)
return Qtrue;
}
-#define isdelim(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\0')
+/* Return nonzero if S has any special globbing chars in it. */
+static int
+has_magic(s, send)
+ char *s, *send;
+{
+ register char *p = s;
+ register char c;
+ int open = 0;
+
+ while ((c = *p++) != '\0') {
+ switch (c) {
+ case '?':
+ case '*':
+ return Qtrue;
+
+ case '[': /* Only accept an open brace if there is a close */
+ open++; /* brace to match it. Bracket expressions must be */
+ continue; /* complete, according to Posix.2 */
+ case ']':
+ if (open)
+ return Qtrue;
+ continue;
+
+ case '\\':
+ if (*p++ == '\0')
+ return Qfalse;
+ }
+
+ if (send && p >= send) break;
+ }
+ return Qfalse;
+}
+
+struct glob1_arg {
+ void (*func)();
+ char *basename;
+ VALUE arg;
+};
+
+static char*
+extract_path(p, pend)
+ char *p, *pend;
+{
+ char *alloc;
+ int len;
+
+ len = pend - p;
+ alloc = ALLOC_N(char, len+1);
+ memcpy(alloc, p, len);
+ if (len > 0 && pend[-1] == '/') {
+ alloc[len-1] = 0;
+ }
+ else {
+ alloc[len] = 0;
+ }
+
+ return alloc;
+}
+
+static char*
+extract_elem(path)
+ char *path;
+{
+ char *pend;
+
+ pend = strchr(path, '/');
+ if (!pend) pend = path + strlen(path);
+
+ return extract_path(path, pend);
+}
+
+#ifndef S_ISDIR
+# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
+#endif
+
+static void
+glob(path, func, arg)
+ char *path;
+ void (*func)();
+ VALUE arg;
+{
+ struct stat st;
+ char *p, *m;
+
+ if (!has_magic(path, 0)) {
+ if (stat(path, &st) == 0) {
+ (*func)(path, arg);
+ }
+ return;
+ }
+
+ p = path;
+ while (p) {
+ if (*p == '/') p++;
+ m = strchr(p, '/');
+ if (has_magic(p, m)) {
+ char *dir, *base, *magic;
+ DIR *dirp;
+ struct dirent *dp;
+
+ base = extract_path(path, p);
+ if (path == p) dir = ".";
+ else dir = base;
+
+ dirp = opendir(dir);
+ if (dirp == NULL) {
+ free(base);
+ break;
+ }
+ magic = extract_elem(p);
+ for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+ if (fnmatch(magic, dp->d_name, FNM_PERIOD|FNM_PATHNAME) == 0) {
+ char *fix = ALLOC_N(char, strlen(base)+strlen(dp->d_name)+2);
+
+ sprintf(fix, "%s%s%s", base, (p==path)?"":"/", dp->d_name);
+ if (!m) {
+ (*func)(fix, arg);
+ free(fix);
+ continue;
+ }
+ stat(fix, &st); /* should success */
+ if (S_ISDIR(st.st_mode)) {
+ char *t = ALLOC_N(char, strlen(fix)+strlen(m)+2);
+ sprintf(t, "%s%s", fix, m);
+ glob(t, func, arg);
+ free(t);
+ }
+ free(fix);
+ }
+ }
+ closedir(dirp);
+ free(base);
+ free(magic);
+ }
+ p = m;
+ }
+}
-char **glob_filename();
-extern char *glob_error_return;
+static void
+push_pattern(path, ary)
+ char *path;
+ VALUE ary;
+{
+ rb_ary_push(ary, rb_tainted_str_new2(path));
+}
static void
push_globs(ary, s)
VALUE ary;
char *s;
{
- char **fnames, **ff;
-
- fnames = glob_filename(s);
- if (fnames == (char**)-1) rb_sys_fail(s);
- ff = fnames;
- while (*ff) {
- rb_ary_push(ary, rb_tainted_str_new2(*ff));
- free(*ff);
- ff++;
- }
- if (fnames != &glob_error_return) {
- free(fnames);
- }
+ glob(s, push_pattern, ary);
}
static void
@@ -374,6 +512,8 @@ push_braces(ary, s)
}
}
+#define isdelim(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\0')
+
static VALUE
dir_s_glob(dir, str)
VALUE dir, str;