18 #include <sys/types.h> 25 #ifndef USE_OPENDIR_AT 26 # if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD) && \ 27 defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) 28 # define USE_OPENDIR_AT 1 30 # define USE_OPENDIR_AT 0 40 #undef HAVE_DIRENT_NAMLEN 41 #if defined HAVE_DIRENT_H && !defined _WIN32 43 # define NAMLEN(dirent) strlen((dirent)->d_name) 44 #elif defined HAVE_DIRECT_H && !defined _WIN32 46 # define NAMLEN(dirent) strlen((dirent)->d_name) 48 # define dirent direct 49 # define NAMLEN(dirent) (dirent)->d_namlen 50 # define HAVE_DIRENT_NAMLEN 1 52 # include <sys/ndir.h> 64 #if defined(__native_client__) && defined(NACL_NEWLIB) 86 #define chdir(p) rb_w32_uchdir(p) 88 #define mkdir(p, m) rb_w32_umkdir((p), (m)) 90 #define rmdir(p) rb_w32_urmdir(p) 92 #define opendir(p) rb_w32_uopendir(p) 93 #define ruby_getcwd() rb_w32_ugetcwd(NULL, 0) 99 #ifdef HAVE_SYS_ATTR_H 100 #include <sys/attr.h> 103 #define USE_NAME_ON_FS_REAL_BASENAME 1 105 #define USE_NAME_ON_FS_BY_FNMATCH 2 108 #ifdef HAVE_GETATTRLIST 109 # define USE_NAME_ON_FS USE_NAME_ON_FS_REAL_BASENAME 110 # define RUP32(size) ((size)+3/4) 111 # define SIZEUP32(type) RUP32(sizeof(type)) 113 # define USE_NAME_ON_FS USE_NAME_ON_FS_REAL_BASENAME 115 # define USE_NAME_ON_FS USE_NAME_ON_FS_BY_FNMATCH 117 # define USE_NAME_ON_FS 0 121 # define NORMALIZE_UTF8PATH 1 123 # define NORMALIZE_UTF8PATH 0 126 #if NORMALIZE_UTF8PATH 127 #include <sys/param.h> 128 #include <sys/mount.h> 129 #include <sys/vnode.h> 131 # if defined HAVE_FGETATTRLIST || !defined HAVE_GETATTRLIST 132 # define need_normalization(dirp, path) need_normalization(dirp) 134 # define need_normalization(dirp, path) need_normalization(path) 137 need_normalization(
DIR *dirp,
const char *path)
139 # if defined HAVE_FGETATTRLIST || defined HAVE_GETATTRLIST 140 u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
141 struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
142 # if defined HAVE_FGETATTRLIST 143 int ret = fgetattrlist(dirfd(dirp), &al, attrbuf,
sizeof(attrbuf), 0);
145 int ret = getattrlist(path, &al, attrbuf,
sizeof(attrbuf), 0);
148 const fsobj_tag_t *tag = (
void *)(attrbuf+1);
160 has_nonascii(
const char *ptr,
size_t len)
170 # define IF_NORMALIZE_UTF8PATH(something) something 172 # define IF_NORMALIZE_UTF8PATH(something) 176 # define IFTODT(m) (((m) & S_IFMT) / ((~S_IFMT & S_IFMT-1) + 1)) 195 #define FNM_NOESCAPE 0x01 196 #define FNM_PATHNAME 0x02 197 #define FNM_DOTMATCH 0x04 198 #define FNM_CASEFOLD 0x08 199 #define FNM_EXTGLOB 0x10 200 #if CASEFOLD_FILESYSTEM 201 #define FNM_SYSCASE FNM_CASEFOLD 203 #define FNM_SYSCASE 0 206 #define FNM_SHORTNAME 0x20 208 #define FNM_SHORTNAME 0 211 #define FNM_NOMATCH 1 214 # define Next(p, e, enc) ((p)+ rb_enc_mbclen((p), (e), (enc))) 215 # define Inc(p, e, enc) ((p) = Next((p), (e), (enc))) 232 if (p >= pend)
return NULL;
233 if (*p ==
'!' || *p ==
'^') {
240 if (escape && *t1 ==
'\\')
245 if (p >= pend)
return NULL;
246 if (p[0] ==
'-' && p[1] !=
']') {
247 const char *t2 = p + 1;
249 if (escape && *t2 ==
'\\')
255 if ((r <= (send-s) &&
memcmp(t1, s, r) == 0) ||
256 (r2 <= (send-s) &&
memcmp(t2, s, r2) == 0)) {
264 if (c1 < c2)
continue;
267 if (c1 > c2)
continue;
271 if (r <= (send-s) &&
memcmp(t1, s, r) == 0) {
275 if (!nocase)
continue;
278 if (c1 != c2)
continue;
283 return ok == not ?
NULL : (
char *)p + 1;
291 #define UNESCAPE(p) (escape && *(p) == '\\' ? (p) + 1 : (p)) 292 #define ISEND(p) (!*(p) || (pathname && *(p) == '/')) 293 #define RETURN(val) return *pcur = p, *scur = s, (val); 307 const char *ptmp = 0;
308 const char *stmp = 0;
310 const char *p = *pcur;
311 const char *pend = p +
strlen(p);
312 const char *s = *scur;
313 const char *send = s +
strlen(s);
317 if (period && *s ==
'.' && *
UNESCAPE(p) !=
'.')
323 do { p++; }
while (*p ==
'*');
345 if ((t = bracket(p + 1, pend, s, send, flags, enc)) != 0) {
363 if (r <= (send-s) &&
memcmp(p, s, r) == 0) {
368 if (!nocase)
goto failed;
379 Inc(stmp, send, enc);
394 const char *p = pattern;
395 const char *s = string;
396 const char *send = s +
strlen(
string);
400 const char *ptmp = 0;
401 const char *stmp = 0;
405 if (p[0] ==
'*' && p[1] ==
'*' && p[2] ==
'/') {
406 do { p += 3; }
while (p[0] ==
'*' && p[1] ==
'*' && p[2] ==
'/');
410 if (fnmatch_helper(&p, &s, flags, enc) == 0) {
411 while (*s && *s !=
'/')
Inc(s, send, enc);
421 if (ptmp && stmp && !(period && *stmp ==
'.')) {
422 while (*stmp && *stmp !=
'/')
Inc(stmp, send, enc);
434 return fnmatch_helper(&p, &s, flags, enc);
462 dir_memsize(
const void *ptr)
469 {dir_mark, dir_free, dir_memsize,},
475 #define GlobPathValue(str, safe) \ 477 (!RB_TYPE_P((str), T_STRING) ? \ 478 (void)FilePathValue(str) : \ 479 (void)(check_safe_glob((str), (safe)), \ 480 check_glob_encoding(str), (str))) 481 #define check_safe_glob(str, safe) ((safe) ? rb_check_safe_obj(str) : (void)0) 482 #define check_glob_encoding(str) rb_enc_check((str), rb_enc_from_encoding(rb_usascii_encoding())) 485 dir_s_alloc(
VALUE klass)
512 VALUE dirname, opt, orig;
513 static ID keyword_ids[1];
516 if (!keyword_ids[0]) {
549 #ifdef HAVE_GETATTRLIST 551 u_int32_t attrbuf[1];
552 struct attrlist al = {ATTR_BIT_MAP_COUNT, 0};
553 if (getattrlist(path, &al, attrbuf,
sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) {
614 struct dir_data *dirp = dir_get(dir);
615 if (!dirp->
dir) dir_closed();
619 #define GetDIR(obj, dirp) ((dirp) = dir_check(obj)) 648 #if defined(__sun) && !defined(HAVE_DIRFD) 649 # if defined(HAVE_DIR_D_FD) 650 # define dirfd(x) ((x)->d_fd) 651 # define HAVE_DIRFD 1 652 # elif defined(HAVE_DIR_DD_FD) 653 # define dirfd(x) ((x)->dd_fd) 654 # define HAVE_DIRFD 1 680 fd = dirfd(dirp->
dir);
686 #define dir_fileno rb_f_notimplement 722 # define READDIR(dir, enc) rb_w32_readdir((dir), (enc)) 724 # define READDIR(dir, enc) readdir((dir)) 729 to_be_skipped(
const struct dirent *
dp)
731 const char *
name = dp->d_name;
732 if (name[0] !=
'.')
return FALSE;
733 #ifdef HAVE_DIRENT_NAMLEN 736 if (name[1] !=
'.')
return FALSE;
743 if (!name[1])
return TRUE;
744 if (name[1] !=
'.')
return FALSE;
745 if (!name[2])
return TRUE;
812 return dir_each_entry(dir, dir_yield,
Qnil,
FALSE);
826 const char *
name = dp->d_name;
827 size_t namlen =
NAMLEN(dp);
830 if (children_only && name[0] ==
'.') {
831 if (namlen == 1)
continue;
832 if (namlen == 2 && name[1] ==
'.')
continue;
834 #if NORMALIZE_UTF8PATH 835 if (norm_p && has_nonascii(name, namlen) &&
836 !
NIL_P(path = rb_str_normalize_ospath(name, namlen))) {
843 if (dirp->
dir ==
NULL) dir_closed();
873 #define dir_tell rb_f_notimplement 902 #define dir_seek rb_f_notimplement 927 #define dir_set_pos rb_f_notimplement 981 static int chdir_blocking = 0;
995 if (chdir_thread ==
Qnil)
1005 if (chdir_blocking == 0)
1006 chdir_thread =
Qnil;
1061 const char *dist =
getenv(
"HOME");
1069 if (chdir_blocking > 0) {
1071 rb_warn(
"conflicting chdir during another chdir block");
1095 #undef RUBY_UNTYPED_DATA_WARNING 1096 #define RUBY_UNTYPED_DATA_WARNING 0 1101 cwd = rb_str_normalize_ospath(path,
strlen(path));
1125 #if defined _WIN32 || defined __APPLE__ 1164 if (pend - path < len) {
1171 #if defined(HAVE_CHROOT) 1184 path = check_dirname(path);
1191 #define dir_s_chroot rb_f_notimplement 1215 if (
rb_scan_args(argc, argv,
"11", &path, &vmode) == 2) {
1222 path = check_dirname(path);
1241 dir = check_dirname(dir);
1249 #ifdef RUBY_FUNCTION_NAME_STRING 1256 #ifndef RUBY_FUNCTION_NAME_STRING 1257 #define sys_enc_warning_in(func, mesg, enc) sys_enc_warning(mesg, enc) 1261 sys_warning_1(
VALUE mesg)
1264 #ifdef RUBY_FUNCTION_NAME_STRING 1276 #ifdef RUBY_FUNCTION_NAME_STRING 1284 #define GLOB_VERBOSE (1U << (sizeof(int) * CHAR_BIT - 1)) 1285 #define sys_warning(val, enc) \ 1286 ((flags & GLOB_VERBOSE) ? sys_enc_warning_in(RUBY_FUNCTION_NAME_STRING, (val), (enc)) :(void)0) 1288 #define GLOB_ALLOC(type) ((type *)malloc(sizeof(type))) 1289 #define GLOB_ALLOC_N(type, n) ((type *)malloc(sizeof(type) * (n))) 1290 #define GLOB_REALLOC(ptr, size) realloc((ptr), (size)) 1291 #define GLOB_FREE(ptr) free(ptr) 1292 #define GLOB_JUMP_TAG(status) (((status) == -1) ? rb_memerror() : rb_jump_tag(status)) 1300 to_be_ignored(
int e)
1302 return e == ENOENT || e == ENOTDIR;
1306 #define STAT(p, s) rb_w32_ustati64((p), (s)) 1308 #define lstat(p, s) rb_w32_ulstati64((p), (s)) 1310 #define STAT(p, s) stat((p), (s)) 1324 int ret = fstatat(fd, path, pst, 0);
1326 int ret =
STAT(path, pst);
1328 if (ret < 0 && !to_be_ignored(
errno))
1334 #if defined HAVE_LSTAT || defined lstat || USE_OPENDIR_AT 1339 int ret = fstatat(fd, path, pst, AT_SYMLINK_NOFOLLOW);
1341 int ret =
lstat(path, pst);
1343 if (ret < 0 && !to_be_ignored(
errno))
1349 #define do_lstat do_stat 1353 do_opendir(
const int basefd,
const char *path,
int flags,
rb_encoding *enc,
1357 const int opendir_flags = (O_RDONLY|
O_CLOEXEC|
1367 if (!fundamental_encoding_p(enc)) {
1374 fd = openat(basefd, path, 0, opendir_flags);
1375 dirp = (fd < 0) ?
NULL : fdopendir(fd);
1384 if ((fd >= 0) || (fd = openat(basefd, path, 0, opendir_flags)) >= 0) {
1385 dirp = fdopendir(fd);
1395 if (fd >= 0) close(fd);
1398 if (to_be_ignored(e))
break;
1400 *status = (*errfunc)(
path, arg,
enc, e);
1418 has_magic(
const char *p,
const char *pend,
int flags,
rb_encoding *enc)
1425 while (p < pend && (c = *p++) != 0) {
1433 if (escape && p++ >= pend)
1452 p =
Next(p-1, pend, enc);
1460 find_dirsep(
const char *p,
const char *pend,
int flags,
rb_encoding *enc)
1467 while ((c = *p++) != 0) {
1482 if (escape && !(c = *p++))
1487 p =
Next(p-1, pend, enc);
1495 remove_backslashes(
char *p,
register const char *pend,
rb_encoding *enc)
1528 glob_make_pattern(
const char *p,
const char *e,
int flags,
rb_encoding *enc)
1534 while (p < e && *p) {
1536 if (!tmp)
goto error;
1537 if (p + 2 < e && p[0] ==
'*' && p[1] ==
'*' && p[2] ==
'/') {
1539 do { p += 3;
while (*p ==
'/') p++; }
while (p[0] ==
'*' && p[1] ==
'*' && p[2] ==
'/');
1546 const char *m = find_dirsep(p, e, flags, enc);
1551 if (!(
FNM_SYSCASE || magic > non_magic) && !recursive && *m) {
1553 while (has_magic(m+1, m2 = find_dirsep(m+1, e, flags, enc), flags, enc) <= non_magic &&
1563 memcpy(buf, p, m-p);
1584 glob_free_pattern(list);
1608 join_path(
const char *path,
size_t len,
int dirsep,
const char *
name,
size_t namlen)
1610 char *buf =
GLOB_ALLOC_N(
char, len+namlen+(dirsep?1:0)+1);
1613 memcpy(buf, path, len);
1617 memcpy(buf+len, name, namlen);
1618 buf[len+namlen] =
'\0';
1622 #ifdef HAVE_GETATTRLIST 1623 # if defined HAVE_FGETATTRLIST 1624 # define is_case_sensitive(dirp, path) is_case_sensitive(dirp) 1626 # define is_case_sensitive(dirp, path) is_case_sensitive(path) 1629 is_case_sensitive(
DIR *dirp,
const char *path)
1633 vol_capabilities_attr_t cap[1];
1634 } __attribute__((aligned(4), packed)) attrbuf[1];
1635 struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, 0, ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES};
1636 const vol_capabilities_attr_t *
const cap = attrbuf[0].cap;
1637 const int idx = VOL_CAPABILITIES_FORMAT;
1638 const uint32_t mask = VOL_CAP_FMT_CASE_SENSITIVE;
1640 # if defined HAVE_FGETATTRLIST 1641 if (fgetattrlist(dirfd(dirp), &al, attrbuf,
sizeof(attrbuf), FSOPT_NOFOLLOW))
1644 if (getattrlist(path, &al, attrbuf,
sizeof(attrbuf), FSOPT_NOFOLLOW))
1647 if (!(cap->valid[idx] & mask))
1649 return (cap->capabilities[idx] & mask) != 0;
1657 attrreference_t ref[1];
1658 fsobj_type_t objtype;
1660 } __attribute__((aligned(4), packed)) attrbuf[1];
1661 struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_NAME|ATTR_CMN_OBJTYPE};
1662 const attrreference_t *
const ar = attrbuf[0].ref;
1669 if (getattrlist(path, &al, attrbuf,
sizeof(attrbuf), FSOPT_NOFOLLOW)) {
1670 if (!to_be_ignored(
errno))
1675 switch (attrbuf[0].objtype) {
1681 name = (
char *)ar + ar->attr_dataoffset;
1682 len = (
long)ar->attr_length - 1;
1683 if (name + len > (
char *)attrbuf +
sizeof(attrbuf))
1686 # if NORMALIZE_UTF8PATH 1687 if (norm_p && has_nonascii(name, len)) {
1688 if (!
NIL_P(utf8str = rb_str_normalize_ospath(name, len))) {
1697 memcpy(path + base, name, len);
1698 path[base +
len] =
'\0';
1703 #elif defined _WIN32 1710 char *plainname =
path;
1711 volatile VALUE tmp = 0;
1712 WIN32_FIND_DATAW fd;
1713 WIN32_FILE_ATTRIBUTE_DATA fa;
1715 HANDLE h = INVALID_HANDLE_VALUE;
1718 if (!fundamental_encoding_p(enc)) {
1725 if (!wplain)
return path;
1726 if (GetFileAttributesExW(wplain, GetFileExInfoStandard, &fa)) {
1727 h = FindFirstFileW(wplain, &fd);
1730 if (fa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1732 fa.dwFileAttributes &= ~FILE_ATTRIBUTE_REPARSE_POINT;
1735 if (h == INVALID_HANDLE_VALUE) {
1737 if (e && !to_be_ignored(e)) {
1745 (fa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ?
path_symlink :
1746 (fa.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
path_directory :
1756 path[base + wlen] = 0;
1762 wlen = WideCharToMultiByte(CP_UTF8, 0, fd.cFileName, -1,
NULL, 0,
NULL,
NULL);
1766 WideCharToMultiByte(CP_UTF8, 0, fd.cFileName, -1, utf8filename, wlen,
NULL,
NULL);
1770 memcpy(path + base, utf8filename, wlen);
1771 path[base + wlen] = 0;
1778 #elif USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME 1779 # error not implemented 1783 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 1788 # define S_ISLNK(m) (0) 1790 # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) 1795 void (*func)(
const char *,
VALUE,
void *);
1803 #define glob_call_func(func, path, arg, enc) (*(func))((path), (arg), (void *)(enc)) 1830 rb_glob_warning(
const char *path,
VALUE a,
const void *enc,
int error)
1853 rb_glob_error(
const char *path,
VALUE a,
const void *enc,
int error)
1859 if (error == EACCES) {
1860 errfunc = glob_func_warning;
1870 dirent_match(
const char *pat,
rb_encoding *enc,
const char *name,
const struct dirent *
dp,
int flags)
1872 if (fnmatch(pat, enc, name, flags) == 0)
return 1;
1875 if (fnmatch(pat, enc, dp->d_altname, flags) == 0)
return 1;
1899 int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0;
1901 size_t pathlen = baselen + namelen;
1902 const char *base =
path;
1904 if (fd !=
AT_FDCWD && *(base += baselen) ==
'/') base++;
1906 for (cur = beg; cur < end; ++cur) {
1917 #if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME 1933 rb_bug(
"continuous RECURSIVEs");
1939 if (
do_lstat(fd, base, &st, flags, enc) == 0) {
1940 pathtype =
IFTODT(st.st_mode);
1947 if (do_stat(fd, base, &st, flags, enc) == 0) {
1948 pathtype =
IFTODT(st.st_mode);
1955 const char *subpath = path + baselen + (baselen && path[baselen] ==
'/');
1957 if (status)
return status;
1960 const char *subpath = path + baselen + (baselen && path[baselen] ==
'/');
1961 char *tmp = join_path(subpath, namelen, dirsep,
"", 0);
1962 if (!tmp)
return -1;
1965 if (status)
return status;
1971 if (magical || recursive) {
1974 # if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH 1975 char *plainname = 0;
1978 # if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH 1979 if (cur + 1 == end && (*cur)->
type <=
ALPHA) {
1980 plainname = join_path(path, pathlen, dirsep, (*cur)->str,
strlen((*cur)->str));
1981 if (!plainname)
return -1;
1982 dirp = do_opendir(fd, plainname, flags, enc, funcs->
error, arg, &status);
1989 dirp = do_opendir(fd, *base ? base :
".", flags, enc, funcs->
error, arg, &status);
1991 # if FNM_SYSCASE || NORMALIZE_UTF8PATH 1992 if ((magical < 2) && !recursive && (
errno == EACCES)) {
2001 # if NORMALIZE_UTF8PATH 2002 if (!(norm_p || magical || recursive)) {
2007 # ifdef HAVE_GETATTRLIST 2008 if (is_case_sensitive(dirp, path) == 0)
2021 if (recursive && name[0] ==
'.') {
2029 else if (namlen == 2 && name[1] ==
'.') {
2035 # if NORMALIZE_UTF8PATH 2036 if (norm_p && has_nonascii(name, namlen)) {
2037 if (!
NIL_P(utf8str = rb_str_normalize_ospath(name, namlen))) {
2042 buf = join_path(path, pathlen, dirsep, name, namlen);
2048 name = buf + pathlen + (dirsep != 0);
2052 new_pathtype = dp->d_type;
2055 if (recursive && dotfile < ((flags &
FNM_DOTMATCH) ? 2 : 1) &&
2058 if (
do_lstat(fd, buf, &st, flags, enc) == 0)
2059 new_pathtype =
IFTODT(st.st_mode);
2071 for (cur = beg; cur < end; ++cur) {
2076 if (dotfile < ((flags & FNM_DOTMATCH) ? 2 : 1))
2083 # if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH 2085 *new_end++ = p->
next;
2091 if (dirent_match(p->
str, enc, name, dp, flags))
2092 *new_end++ = p->
next;
2098 status = glob_helper(fd, buf, baselen, name - buf - baselen + namlen, 1,
2099 new_pathtype, new_beg, new_end,
2100 flags, funcs, arg, enc);
2111 # if FNM_SYSCASE || NORMALIZE_UTF8PATH 2115 if (!copy_beg)
return -1;
2116 for (cur = beg; cur < end; ++cur)
2117 *copy_end++ = (*cur)->
type <=
ALPHA ? *cur : 0;
2119 for (cur = copy_beg; cur < copy_end; ++cur) {
2124 size_t len =
strlen((*cur)->str) + 1;
2130 memcpy(name, (*cur)->str, len);
2132 len = remove_backslashes(name, name+len-1, enc) -
name;
2140 *new_end++ = (*cur)->
next;
2141 for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
2142 if (*cur2 && fnmatch((*cur2)->str, enc, name, flags) == 0) {
2143 *new_end++ = (*cur2)->
next;
2148 buf = join_path(path, pathlen, dirsep, name, len);
2155 #if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME 2156 if ((*cur)->type ==
ALPHA) {
2157 buf = replace_real_basename(buf, pathlen + (dirsep != 0), enc,
2159 flags, &new_pathtype);
2163 status = glob_helper(fd, buf, baselen,
2164 namelen +
strlen(buf + pathlen), 1,
2165 new_pathtype, new_beg, new_end,
2166 flags, funcs, arg, enc);
2180 ruby_glob0(
const char *path,
int fd,
const char *base,
int flags,
2185 const char *root, *start;
2187 size_t n, baselen = 0;
2188 int status, dirsep =
FALSE;
2190 start = root =
path;
2196 if (*root ==
'/') root++;
2206 if (!buf)
return -1;
2207 MEMCPY(buf, start,
char, n);
2210 list = glob_make_pattern(root, root +
strlen(root), flags, enc);
2215 status = glob_helper(fd, buf, baselen, n-baselen, dirsep,
2217 flags, funcs, arg, enc);
2218 glob_free_pattern(list);
2235 rb_glob_caller(
const char *path,
VALUE a,
void *enc)
2246 rb_glob_caller, rb_glob_error,
2265 push_pattern(
const char *path,
VALUE ary,
void *enc)
2267 #if defined _WIN32 || defined __APPLE__ 2283 const char *p = str;
2284 const char *pend = p +
strlen(p);
2286 const char *lbrace = 0, *rbrace = 0;
2287 int nest = 0, status = 0;
2290 if (*p ==
'{' && nest++ == 0) {
2293 if (*p ==
'}' && lbrace && --nest == 0) {
2297 if (*p ==
'\\' && escape) {
2303 if (lbrace && rbrace) {
2304 size_t len =
strlen(s) + 1;
2308 if (!buf)
return -1;
2309 memcpy(buf, s, lbrace-s);
2312 while (p < rbrace) {
2313 const char *t = ++p;
2315 while (p < rbrace && !(*p ==
',' && nest == 0)) {
2316 if (*p ==
'{') nest++;
2317 if (*p ==
'}') nest--;
2318 if (*p ==
'\\' && escape) {
2319 if (++p == rbrace)
break;
2323 memcpy(buf+shift, t, p-t);
2324 strlcpy(buf+shift+(p-t), rbrace+1, len-(shift+(p-t)));
2325 status = ruby_brace_expand(buf, flags, func, arg, enc, var);
2330 else if (!lbrace && !rbrace) {
2345 glob_brace(
const char *path,
VALUE val,
void *enc)
2362 return ruby_brace_expand(str, flags, glob_brace, (
VALUE)&args, enc,
Qfalse);
2378 push_caller(
const char *path,
VALUE val,
void *enc)
2382 return ruby_glob0(path, arg->
fd, arg->
glob.
base, arg->
flags, &rb_glob_funcs,
2392 #if defined _WIN32 || defined __APPLE__ 2409 if (!dirp->
dir) dir_closed();
2411 if ((args.
fd = dirfd(dirp->
dir)) == -1)
2418 #if defined _WIN32 || defined __APPLE__ 2423 push_caller, (
VALUE)&args, enc, str);
2427 rb_push_glob(
VALUE str,
VALUE base,
int flags)
2445 while (p < pend && !*p)
2459 for (i = 0; i <
argc; ++i) {
2461 VALUE str = argv[i];
2463 status = push_glob(ary, str, base, flags);
2471 dir_glob_options(
VALUE opt,
VALUE *base,
int *flags)
2491 if (flags && args[1] !=
Qundef) {
2509 dir_glob_options(opts, &base,
NULL);
2511 return rb_push_glob(argv[0], base, 0);
2513 return dir_globs(argc, argv, base, 0);
2606 VALUE str, rflags, ary, opts, base;
2609 argc =
rb_scan_args(argc, argv,
"11:", &str, &rflags, &opts);
2614 dir_glob_options(opts, &base, &flags);
2618 ary = rb_push_glob(str, base, flags);
2634 dir_open_dir(
int argc,
VALUE *argv)
2671 dir = dir_open_dir(argc, argv);
2672 rb_ensure(dir_each, dir, dir_close, dir);
2704 dir = dir_open_dir(argc, argv);
2705 return rb_ensure(dir_collect, dir, dir_close, dir);
2709 dir_each_child(
VALUE dir)
2711 return dir_each_entry(dir, dir_yield,
Qnil,
TRUE);
2736 dir_s_each_child(
int argc,
VALUE *argv,
VALUE io)
2741 dir = dir_open_dir(argc, argv);
2742 rb_ensure(dir_each_child, dir, dir_close, dir);
2747 dir_collect_children(
VALUE dir)
2770 dir_s_children(
int argc,
VALUE *argv,
VALUE io)
2774 dir = dir_open_dir(argc, argv);
2775 return rb_ensure(dir_collect_children, dir, dir_close, dir);
2779 fnmatch_brace(
const char *pattern,
VALUE val,
void *enc)
2786 if (enc_pattern != enc_path) {
2793 long len =
strlen(pattern);
2795 enc_pattern, &cr) != len)
2898 file_s_fnmatch(
int argc,
VALUE *argv,
VALUE obj)
2904 if (
rb_scan_args(argc, argv,
"21", &pattern, &path, &rflags) == 3)
2917 if (ruby_brace_expand(
RSTRING_PTR(pattern), flags, fnmatch_brace,
2947 user = (argc > 0) ? argv[0] :
Qnil;
2984 rb_warning(
"Dir.exists? is a deprecated name, use Dir.exist? instead");
2989 gc_for_fd_with_gvl(
void *ptr)
2997 nogvl_dir_empty_p(
void *ptr)
2999 const char *path = ptr;
3013 if (e == ENOTDIR)
return (
void *)
Qfalse;
3019 if (!to_be_skipped(dp)) {
3025 return (
void *)result;
3040 enum {false_on_notdir = 1};
3048 #if defined HAVE_GETATTRLIST && defined ATTR_DIR_ENTRYCOUNT 3050 u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
3051 struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
3052 if (getattrlist(path, &al, attrbuf,
sizeof(attrbuf), 0) != 0)
3054 if (*(
const fsobj_tag_t *)(attrbuf+1) == VT_HFS) {
3056 al.dirattr = ATTR_DIR_ENTRYCOUNT;
3057 if (getattrlist(path, &al, attrbuf,
sizeof(attrbuf), 0) == 0) {
3058 if (attrbuf[0] >= 2 *
sizeof(u_int32_t))
3060 if (false_on_notdir)
return Qfalse;
#define ENCINDEX_US_ASCII
VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc)
#define MBCLEN_CHARFOUND_P(ret)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
void rb_warn(const char *fmt,...)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
void rb_bug(const char *fmt,...)
void rb_syserr_fail(int e, const char *mesg)
#define RUBY_TYPED_FREE_IMMEDIATELY
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
size_t strlen(const char *)
#define RUBY_DEFAULT_FREE
#define GLOB_REALLOC(ptr, size)
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.
void rb_syserr_fail_str(int e, VALUE mesg)
int rb_block_given_p(void)
Determines if the current method is given a block.
enum glob_pattern_type type
void rb_file_const(const char *name, VALUE value)
void rb_raise(VALUE exc, const char *fmt,...)
int ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
VALUE rb_dir_getwd_ospath(void)
int lstat(const char *path, struct stat *result)
void(* func)(const char *, VALUE, void *)
#define TypedData_Get_Struct(obj, type, data_type, sval)
rb_encoding * rb_to_encoding(VALUE enc)
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *)
VALUE rb_ary_each(VALUE ary)
void rb_must_asciicompat(VALUE)
rb_encoding * rb_default_internal_encoding(void)
VALUE rb_ary_push(VALUE ary, VALUE item)
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
#define FilePathStringValue(v)
int ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
int rb_gc_for_fd(int err)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
void rb_include_module(VALUE klass, VALUE module)
void rb_gc_mark(VALUE ptr)
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
An equivalent to ensure clause.
VALUE rb_utf8_str_new_cstr(const char *)
rb_encoding * rb_utf8_encoding(void)
VALUE rb_str_dup_frozen(VALUE)
int rb_w32_map_errno(DWORD)
#define ENC_CODERANGE_7BIT
RUBY_EXTERN void * memmove(void *, const void *, size_t)
int rb_enc_toupper(int c, rb_encoding *enc)
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
void rewinddir(DIR *dirp)
#define Data_Wrap_Struct(klass, mark, free, sval)
char * rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc)
#define RB_TYPE_P(obj, type)
int rb_enc_to_index(rb_encoding *enc)
#define RUBY_TYPED_WB_PROTECTED
VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc)
VALUE rb_class_name(VALUE)
VALUE rb_str_encode_ospath(VALUE path)
RUBY_EXTERN VALUE rb_cObject
VALUE rb_home_dir_of(VALUE user, VALUE result)
#define sys_warning(val, enc)
#define GetDIR(obj, dirp)
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_thread_current(void)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
#define GLOB_JUMP_TAG(status)
#define MEMCPY(p1, p2, type, n)
VALUE rb_enc_associate_index(VALUE obj, int idx)
#define rb_enc_codepoint(p, e, enc)
void seekdir(DIR *dirp, long offset)
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
#define IF_NORMALIZE_UTF8PATH(something)
void rb_sys_enc_warning(rb_encoding *enc, const char *fmt,...)
int ruby_glob_errfunc(const char *, VALUE, const void *, int)
VALUE rb_str_resize(VALUE, long)
void rb_sys_fail(const char *mesg)
VALUE rb_str_subseq(VALUE, long, long)
#define RARRAY_CONST_PTR(a)
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
ALWAYS_INLINE(static int to_be_ignored(int e))
int ruby_glob_func(const char *, VALUE, void *)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
unsigned char buf[MIME_BUF_SIZE]
VALUE rb_file_directory_p(VALUE obj, VALUE fname)
#define glob_call_func(func, path, arg, enc)
#define READDIR(dir, enc)
char * strchr(char *, char)
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
#define rb_enc_asciicompat(enc)
VALUE rb_str_new_cstr(const char *)
int memcmp(const void *s1, const void *s2, size_t len)
#define rb_tainted_str_new2
void rb_glob(const char *path, void(*func)(const char *, VALUE, void *), VALUE arg)
register unsigned int len
#define StringValueCStr(v)
#define RB_OBJ_WRITE(a, slot, b)
rb_encoding * rb_enc_get(VALUE obj)
VALUE rb_check_array_type(VALUE ary)
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
int rb_w32_reparse_symlink_p(const WCHAR *path)
void rb_warning(const char *fmt,...)
VALUE rb_default_home_dir(VALUE result)
struct rb_encoding_entry * list
rb_encoding * rb_filesystem_encoding(void)
ruby_glob_errfunc * error
#define TypedData_Make_Struct(klass, type, data_type, sval)
int ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
WCHAR * rb_w32_mbstr_to_wstr(UINT, const char *, int, long *)
#define RETURN_ENUMERATOR(obj, argc, argv)
#define SafeStringValue(v)
char * rb_enc_path_end(const char *path, const char *end, rb_encoding *enc)
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
#define rb_sys_fail_path(path)
RUBY_EXTERN VALUE rb_eIOError
void rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt,...)
VALUE rb_int2inum(SIGNED_VALUE n)
rb_encoding * rb_ascii8bit_encoding(void)
#define sys_enc_warning_in(func, mesg, enc)
#define rb_syserr_fail_path(err, path)
#define rb_check_frozen(obj)
int rb_enc_str_asciionly_p(VALUE)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_str_append(VALUE, VALUE)
#define GLOB_ALLOC_N(type, n)
VALUE rb_enc_str_new_cstr(const char *, rb_encoding *)
#define GlobPathValue(str, safe)
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
VALUE rb_str_new(const char *, long)