18 #include <sys/types.h>
25 #if defined HAVE_DIRENT_H && !defined _WIN32
27 # define NAMLEN(dirent) strlen((dirent)->d_name)
28 #elif defined HAVE_DIRECT_H && !defined _WIN32
30 # define NAMLEN(dirent) strlen((dirent)->d_name)
32 # define dirent direct
33 # if !defined __NeXT__
34 # define NAMLEN(dirent) (dirent)->d_namlen
37 # define NAMLEN(dirent) strlen((dirent)->d_name)
40 # include <sys/ndir.h>
67 #if !defined HAVE_LSTAT && !defined lstat
74 #define chdir(p) rb_w32_uchdir(p)
76 #define mkdir(p, m) rb_w32_umkdir((p), (m))
78 #define rmdir(p) rb_w32_urmdir(p)
80 #define opendir(p) rb_w32_uopendir(p)
83 #define rb_sys_fail_path(path) rb_sys_fail_str(path)
85 #define FNM_NOESCAPE 0x01
86 #define FNM_PATHNAME 0x02
87 #define FNM_DOTMATCH 0x04
88 #define FNM_CASEFOLD 0x08
89 #if CASEFOLD_FILESYSTEM
90 #define FNM_SYSCASE FNM_CASEFOLD
98 # define Next(p, e, enc) ((p)+ rb_enc_mbclen((p), (e), (enc)))
99 # define Inc(p, e, enc) ((p) = Next((p), (e), (enc)))
116 if (p >= pend)
return NULL;
117 if (*p ==
'!' || *p ==
'^') {
124 if (escape && *t1 ==
'\\')
129 if (p >= pend)
return NULL;
130 if (p[0] ==
'-' && p[1] !=
']') {
131 const char *t2 = p + 1;
133 if (escape && *t2 ==
'\\')
139 if ((r <= (send-s) &&
memcmp(t1, s, r) == 0) ||
140 (r2 <= (send-s) &&
memcmp(t2, s, r) == 0)) {
148 if (c1 < c2)
continue;
151 if (c1 > c2)
continue;
155 if (r <= (send-s) &&
memcmp(t1, s, r) == 0) {
159 if (!nocase)
continue;
162 if (c1 != c2)
continue;
167 return ok == not ?
NULL : (
char *)p + 1;
175 #define UNESCAPE(p) (escape && *(p) == '\\' ? (p) + 1 : (p))
176 #define ISEND(p) (!*(p) || (pathname && *(p) == '/'))
177 #define RETURN(val) return *pcur = p, *scur = s, (val);
191 const char *ptmp = 0;
192 const char *stmp = 0;
194 const char *
p = *pcur;
195 const char *pend = p +
strlen(p);
196 const char *s = *scur;
197 const char *send = s +
strlen(s);
201 if (period && *s ==
'.' && *
UNESCAPE(p) !=
'.')
207 do { p++; }
while (*p ==
'*');
229 if ((t =
bracket(p + 1, pend, s, send, flags, enc)) != 0) {
247 if (r <= (send-s) &&
memcmp(p, s, r) == 0) {
252 if (!nocase)
goto failed;
263 Inc(stmp, send, enc);
278 const char *
p = pattern;
279 const char *s = string;
280 const char *send = s +
strlen(
string);
284 const char *ptmp = 0;
285 const char *stmp = 0;
289 if (p[0] ==
'*' && p[1] ==
'*' && p[2] ==
'/') {
290 do { p += 3; }
while (p[0] ==
'*' && p[1] ==
'*' && p[2] ==
'/');
295 while (*s && *s !=
'/')
Inc(s, send, enc);
305 if (ptmp && stmp && !(period && *stmp ==
'.')) {
306 while (*stmp && *stmp !=
'/')
Inc(stmp, send, enc);
349 return ptr ?
sizeof(
struct dir_data) : 0;
359 #define GlobPathValue(str, safe) \
361 (!RB_TYPE_P((str), T_STRING) ? \
362 (void)FilePathValue(str) : \
363 (void)(check_safe_glob((str), (safe)), \
364 check_glob_encoding(str), (str)))
365 #define check_safe_glob(str, safe) ((safe) ? rb_check_safe_obj(str) : (void)0)
366 #define check_glob_encoding(str) rb_enc_check((str), rb_enc_from_encoding(rb_usascii_encoding()))
392 VALUE dirname, opt, orig;
393 static VALUE sym_enc;
477 #define GetDIR(obj, dirp) ((dirp) = dir_check(obj))
522 #if defined HAVE_READDIR_R
523 # define READDIR(dir, enc, entry, dp) (readdir_r((dir), (entry), &(dp)) == 0 && (dp) != 0)
525 # define READDIR(dir, enc, entry, dp) (((dp) = rb_w32_readdir_with_enc((dir), (enc))) != 0)
527 # define READDIR(dir, enc, entry, dp) (((dp) = readdir(dir)) != 0)
529 #if defined HAVE_READDIR_R
530 # define IF_HAVE_READDIR_R(something) something
532 # define IF_HAVE_READDIR_R(something)
535 #if defined SIZEOF_STRUCT_DIRENT_TOO_SMALL
537 # define NAME_MAX_FOR_STRUCT_DIRENT 255
538 # if defined NAME_MAX
539 # if NAME_MAX_FOR_STRUCT_DIRENT < NAME_MAX
540 # undef NAME_MAX_FOR_STRUCT_DIRENT
541 # define NAME_MAX_FOR_STRUCT_DIRENT NAME_MAX
544 # if defined _POSIX_NAME_MAX
545 # if NAME_MAX_FOR_STRUCT_DIRENT < _POSIX_NAME_MAX
546 # undef NAME_MAX_FOR_STRUCT_DIRENT
547 # define NAME_MAX_FOR_STRUCT_DIRENT _POSIX_NAME_MAX
550 # if defined _XOPEN_NAME_MAX
551 # if NAME_MAX_FOR_STRUCT_DIRENT < _XOPEN_NAME_MAX
552 # undef NAME_MAX_FOR_STRUCT_DIRENT
553 # define NAME_MAX_FOR_STRUCT_DIRENT _XOPEN_NAME_MAX
556 # define DEFINE_STRUCT_DIRENT \
558 struct dirent dirent; \
559 char dummy[offsetof(struct dirent, d_name) + \
560 NAME_MAX_FOR_STRUCT_DIRENT + 1]; \
562 # define STRUCT_DIRENT(entry) ((entry).dirent)
564 # define DEFINE_STRUCT_DIRENT struct dirent
565 # define STRUCT_DIRENT(entry) (entry)
592 else if (
errno == 0) {
663 #define dir_tell rb_f_notimplement
692 #define dir_seek rb_f_notimplement
783 if (chdir_thread ==
Qnil)
793 if (chdir_blocking == 0)
850 const char *dist =
getenv(
"HOME");
858 if (chdir_blocking > 0) {
860 rb_warn(
"conflicting chdir during another chdir block");
922 if (pend - path < len) {
928 #if defined(HAVE_CHROOT)
948 #define dir_s_chroot rb_f_notimplement
972 if (
rb_scan_args(argc, argv,
"11", &path, &vmode) == 2) {
1012 #define GLOB_VERBOSE (1U << (sizeof(int) * CHAR_BIT - 1))
1013 #define sys_warning(val) \
1014 (void)((flags & GLOB_VERBOSE) && rb_protect(sys_warning_1, (VALUE)(val), 0))
1016 #define GLOB_ALLOC(type) ((type *)malloc(sizeof(type)))
1017 #define GLOB_ALLOC_N(type, n) ((type *)malloc(sizeof(type) * (n)))
1018 #define GLOB_FREE(ptr) free(ptr)
1019 #define GLOB_JUMP_TAG(status) (((status) == -1) ? rb_memerror() : rb_jump_tag(status))
1025 #define to_be_ignored(e) ((e) == ENOENT || (e) == ENOTDIR)
1032 int ret =
stat(path, pst);
1042 int ret =
lstat(path, pst);
1079 while (p < pend && (c = *p++) != 0) {
1087 if (escape && !(c = *p++))
1096 p =
Next(p-1, pend, enc);
1111 while ((c = *p++) != 0) {
1126 if (escape && !(c = *p++))
1131 p =
Next(p-1, pend, enc);
1141 register const char *pend = p +
strlen(p);
1180 while (p < e && *p) {
1182 if (!tmp)
goto error;
1183 if (p[0] ==
'*' && p[1] ==
'*' && p[2] ==
'/') {
1185 do { p += 3;
while (*p ==
'/') p++; }
while (p[0] ==
'*' && p[1] ==
'*' && p[2] ==
'/');
1193 int magic =
has_magic(p, m, flags, enc);
1196 if (!magic && !recursive && *m) {
1208 memcpy(buf, p, m-p);
1256 long len2 =
strlen(name)+(dirsep?1:0)+1;
1260 memcpy(buf, path, len);
1272 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
1277 # define S_ISLNK(m) (0)
1279 # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
1299 #define glob_call_func(func, path, arg, enc) (*(func))((path), (arg), (enc))
1317 int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0;
1320 for (cur = beg; cur < end; ++cur) {
1340 rb_bug(
"continuous RECURSIVEs");
1345 if (match_all && exist ==
UNKNOWN) {
1346 if (
do_lstat(path, &st, flags) == 0) {
1355 if (match_dir && isdir ==
UNKNOWN) {
1356 if (
do_stat(path, &st, flags) == 0) {
1365 if (match_all && exist ==
YES) {
1367 if (status)
return status;
1369 if (match_dir && isdir ==
YES) {
1370 char *tmp =
join_path(path, dirsep,
"");
1371 if (!tmp)
return -1;
1374 if (status)
return status;
1378 if (exist ==
NO || isdir ==
NO)
return 0;
1380 if (magical || recursive) {
1384 dirp =
do_opendir(*path ? path :
".", flags, enc);
1385 if (dirp ==
NULL)
return 0;
1395 if (recursive && strcmp(dp->d_name,
".") != 0 && strcmp(dp->d_name,
"..") != 0
1398 if (
do_lstat(buf, &st, flags) == 0)
1403 new_isdir = dp->d_isdir ? (!dp->d_isrep ?
YES :
UNKNOWN) :
NO;
1414 for (cur = beg; cur < end; ++cur) {
1417 if (new_isdir ==
YES)
1422 if (
fnmatch(p->
str, enc, dp->d_name, flags) == 0)
1423 *new_end++ = p->
next;
1428 flags, func, arg, enc);
1440 if (!copy_beg)
return -1;
1441 for (cur = beg; cur < end; ++cur)
1442 *copy_end++ = (*cur)->
type ==
PLAIN ? *cur : 0;
1444 for (cur = copy_beg; cur < copy_end; ++cur) {
1454 memcpy(name, (*cur)->str, len);
1463 *new_end++ = (*cur)->
next;
1464 for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
1465 if (*cur2 &&
fnmatch((*cur2)->str, enc, name, flags) == 0) {
1466 *new_end++ = (*cur2)->
next;
1479 new_end, flags, func, arg, enc);
1496 const char *root, *start;
1501 start = root = path;
1507 if (root && *root ==
'/') root++;
1511 if (!buf)
return -1;
1512 MEMCPY(buf, start,
char, n);
1557 rb_warning(
"Dir.glob() ignores File::FNM_CASEFOLD");
1582 const char *
p = str;
1583 const char *pend = p +
strlen(p);
1585 const char *lbrace = 0, *rbrace = 0;
1586 int nest = 0, status = 0;
1589 if (*p ==
'{' && nest++ == 0) {
1592 if (*p ==
'}' && --nest <= 0) {
1596 if (*p ==
'\\' && escape) {
1602 if (lbrace && rbrace) {
1607 if (!buf)
return -1;
1608 memcpy(buf, s, lbrace-s);
1611 while (p < rbrace) {
1612 const char *t = ++
p;
1614 while (p < rbrace && !(*p ==
',' && nest == 0)) {
1615 if (*p ==
'{') nest++;
1616 if (*p ==
'}') nest--;
1617 if (*p ==
'\\' && escape) {
1618 if (++p == rbrace)
break;
1622 memcpy(buf+shift, t, p-t);
1623 strlcpy(buf+shift+(p-t), rbrace+1, len-(shift+(p-t)));
1629 else if (!lbrace && !rbrace) {
1630 status = (*func)(s,
arg,
enc);
1710 while (p < pend && !*p)
1724 for (i = 0; i <
argc; ++
i) {
1824 VALUE str, rflags, ary;
1827 if (
rb_scan_args(argc, argv,
"11", &str, &rflags) == 2)
1998 if (
rb_scan_args(argc, argv,
"21", &pattern, &path, &rflags) == 3)