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;
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 850 const char *dist =
getenv(
"HOME");
860 rb_warn(
"conflicting chdir during another chdir block");
867 args.new_path = path;
922 if (pend - path <
len) {
928 #if defined(HAVE_CHROOT) 948 #define dir_s_chroot rb_f_notimplement 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] ==
'/');
1196 if (!magic && !recursive && *m) {
1208 memcpy(
buf,
p, m-
p);
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
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;
1557 rb_warning(
"Dir.glob() ignores File::FNM_CASEFOLD");
1582 const char *
p = str;
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;
1629 else if (!lbrace && !rbrace) {
1630 status = (*func)(s, arg,
enc);
1710 while (
p < pend && !*
p)
1824 VALUE str, rflags, ary;
#define RSTRING_LEN(string)
static long NUM2LONG(VALUE x)
static void dir_closed(void)
#define DEFINE_STRUCT_DIRENT
#define MBCLEN_CHARFOUND_P(ret)
static void dir_free(void *ptr)
static int chdir_blocking
void rb_bug(const char *fmt,...)
static VALUE dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
static int ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
static VALUE chdir_restore(struct chdir_data *args)
size_t strlen(const char *)
static const rb_data_type_t dir_data_type
static VALUE chdir_thread
struct glob_pattern * next
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
enum glob_pattern_type type
void rb_file_const(const char *name, VALUE value)
int ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
static VALUE dir_rewind(VALUE dir)
static VALUE file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
void(* func)(const char *, VALUE, void *)
static VALUE dir_inspect(VALUE dir)
static DIR * do_opendir(const char *path, int flags, rb_encoding *enc)
#define TypedData_Get_Struct(obj, type, data_type, sval)
VALUE rb_ary_each(VALUE array)
static void dir_chdir(VALUE path)
static VALUE dir_s_alloc(VALUE klass)
rb_encoding * rb_to_encoding(VALUE enc)
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *)
static int glob_brace(const char *path, VALUE val, void *enc)
static size_t dir_memsize(const void *ptr)
VALUE rb_ary_push(VALUE ary, VALUE item)
SSL_METHOD *(* func)(void)
static VALUE glob_func_caller(VALUE val)
#define FilePathStringValue(v)
static char * bracket(const char *p, const char *pend, const char *s, const char *send, int flags, rb_encoding *enc)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
int ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
#define RSTRING_PTR(string)
static VALUE dir_s_chdir(int argc, VALUE *argv, VALUE obj)
void rb_raise(VALUE exc, const char *fmt,...)
#define STRUCT_DIRENT(entry)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
VALUE rb_tainted_str_new2(const char *)
#define RARRAY_LEN(ARRAY)
void rb_include_module(VALUE klass, VALUE module)
void rb_gc_mark(VALUE ptr)
rb_encoding * rb_utf8_encoding(void)
VALUE rb_str_dup_frozen(VALUE)
static int ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
RUBY_EXTERN void * memmove(void *, const void *, size_t)
int rb_enc_toupper(int c, rb_encoding *enc)
static VALUE dir_s_aref(int argc, VALUE *argv, VALUE obj)
char * rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc)
static struct glob_pattern * glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc)
VALUE rb_class_name(VALUE)
int rb_block_given_p(void)
VALUE rb_str_encode_ospath(VALUE path)
RUBY_EXTERN VALUE rb_cObject
#define GetDIR(obj, dirp)
VALUE rb_str_cat2(VALUE, const char *)
#define READDIR(dir, enc, entry, dp)
static VALUE dir_s_home(int argc, VALUE *argv, VALUE obj)
VALUE rb_thread_current(void)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_home_dir(const char *user, VALUE result)
#define GLOB_JUMP_TAG(status)
#define MEMCPY(p1, p2, type, n)
#define rb_enc_codepoint(p, e, enc)
static void check_dirname(volatile VALUE *dir)
static VALUE chdir_yield(struct chdir_data *args)
VALUE rb_str_subseq(VALUE, long, long)
static VALUE dir_set_pos(VALUE dir, VALUE pos)
static char * join_path(const char *path, int dirsep, const char *name)
VALUE rb_funcall2(VALUE, ID, int, const VALUE *)
Calls a method.
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
static VALUE dir_read(VALUE dir)
static VALUE dir_globs(long argc, VALUE *argv, int flags)
#define RB_GC_GUARD(object)
static int rb_glob_caller(const char *path, VALUE a, void *enc)
static int fnmatch_helper(const char **pcur, const char **scur, int flags, rb_encoding *enc)
static VALUE sys_warning_1(VALUE mesg)
int ruby_glob_func(const char *, VALUE, void *)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
static void dir_mark(void *ptr)
static VALUE dir_s_rmdir(VALUE obj, VALUE dir)
unsigned char buf[MIME_BUF_SIZE]
rb_encoding * rb_usascii_encoding(void)
VALUE rb_file_directory_p(VALUE obj, VALUE fname)
static int glob_helper(const char *path, int dirsep, enum answer exist, enum answer isdir, struct glob_pattern **beg, struct glob_pattern **end, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
#define glob_call_func(func, path, arg, enc)
static VALUE dir_each(VALUE dir)
char * strchr(char *, char)
static VALUE dir_path(VALUE dir)
register unsigned int len
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
#define RARRAY_PTR(ARRAY)
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
VALUE rb_str_new_cstr(const char *)
int memcmp(const void *s1, const void *s2, size_t len)
static struct dir_data * dir_check(VALUE dir)
static void shift(struct cparse_params *v, long act, VALUE tok, VALUE val)
void rb_sys_fail(const char *mesg)
static int do_stat(const char *path, struct stat *pst, int flags)
void rb_glob(const char *path, void(*func)(const char *, VALUE, void *), VALUE arg)
static VALUE dir_s_glob(int argc, VALUE *argv, VALUE obj)
static VALUE dir_s_getwd(VALUE dir)
#define StringValueCStr(v)
#define IF_HAVE_READDIR_R(something)
static int rb_glob2(const char *path, int flags, void(*func)(const char *, VALUE, void *), VALUE arg, rb_encoding *enc)
rb_encoding * rb_enc_get(VALUE obj)
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
static VALUE dir_close(VALUE)
static VALUE dir_entries(int argc, VALUE *argv, VALUE io)
static void glob_free_pattern(struct glob_pattern *list)
VALUE rb_check_array_type(VALUE ary)
static VALUE dir_initialize(int argc, VALUE *argv, VALUE dir)
VALUE rb_hash_aref(VALUE hash, VALUE key)
RUBY_EXTERN char * strerror(int)
struct rb_encoding_entry * list
rb_encoding * rb_filesystem_encoding(void)
#define rb_sys_fail_path(path)
static void remove_backslashes(char *p, rb_encoding *enc)
static int push_glob(VALUE ary, VALUE str, int flags)
#define TypedData_Make_Struct(klass, type, data_type, sval)
static int do_lstat(const char *path, struct stat *pst, int flags)
int ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
static void push_pattern(const char *path, VALUE ary, void *enc)
static int fnmatch(const char *pattern, rb_encoding *enc, const char *string, int flags)
#define RETURN_ENUMERATOR(obj, argc, argv)
#define SafeStringValue(v)
static VALUE dir_open_dir(int argc, VALUE *argv)
char * rb_enc_path_end(const char *path, const char *end, rb_encoding *enc)
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
static VALUE dir_s_open(int argc, VALUE *argv, VALUE klass)
RUBY_EXTERN VALUE rb_eIOError
static char * find_dirsep(const char *p, const char *pend, int flags, rb_encoding *enc)
RUBY_EXTERN size_t strlcat(char *, const char *, size_t)
static VALUE dir_foreach(int argc, VALUE *argv, VALUE io)
VALUE rb_int2inum(SIGNED_VALUE n)
rb_encoding * rb_ascii8bit_encoding(void)
void rb_warning(const char *fmt,...)
static VALUE rb_push_glob(VALUE str, int flags)
#define rb_check_frozen(obj)
static int ruby_brace_glob0(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_str_append(VALUE, VALUE)
VALUE rb_str_new2(const char *)
void rb_warn(const char *fmt,...)
#define GLOB_ALLOC_N(type, n)
#define GlobPathValue(str, safe)
void rb_sys_warning(const char *fmt,...)
static int has_magic(const char *p, const char *pend, int flags, rb_encoding *enc)
VALUE rb_str_new(const char *, long)