19 #include <sys/cygwin.h>
33 #ifdef HAVE_SYS_FILE_H
34 # include <sys/file.h>
39 #ifdef HAVE_SYS_PARAM_H
40 # include <sys/param.h>
43 # define MAXPATHLEN 1024
52 #elif defined HAVE_SYS_UTIME_H
53 #include <sys/utime.h>
60 #include <sys/types.h>
63 #if defined(__native_client__) && defined(NACL_NEWLIB)
70 #ifdef HAVE_SYS_MKDEV_H
71 #include <sys/mkdev.h>
74 #if defined(HAVE_FCNTL_H)
78 #if defined(HAVE_SYS_TIME_H)
82 #if !defined HAVE_LSTAT && !defined lstat
88 #define STAT(p, s) rb_w32_ustati64((p), (s))
90 #define lstat(p, s) rb_w32_ustati64((p), (s))
92 #define access(p, m) rb_w32_uaccess((p), (m))
94 #define chmod(p, m) rb_w32_uchmod((p), (m))
96 #define chown(p, o, g) rb_w32_uchown((p), (o), (g))
98 #define utime(p, t) rb_w32_uutime((p), (t))
100 #define link(f, t) rb_w32_ulink((f), (t))
102 #define unlink(p) rb_w32_uunlink(p)
104 #define rename(f, t) rb_w32_urename((f), (t))
106 #define STAT(p, s) stat((p), (s))
109 #define rb_sys_fail_path(path) rb_sys_fail_str(path)
111 #if defined(__BEOS__) || defined(__HAIKU__)
113 be_chown(
const char *
path, uid_t owner, gid_t group)
115 if (owner == (uid_t)-1 || group == (gid_t)-1) {
117 if (
STAT(path, &st) < 0)
return -1;
118 if (owner == (uid_t)-1) owner = st.st_uid;
119 if (group == (gid_t)-1) group = st.st_gid;
121 return chown(path, owner, group);
123 #define chown be_chown
125 be_fchown(
int fd, uid_t owner, gid_t group)
127 if (owner == (uid_t)-1 || group == (gid_t)-1) {
129 if (
fstat(fd, &
st) < 0)
return -1;
130 if (owner == (uid_t)-1) owner =
st.st_uid;
131 if (group == (gid_t)-1) group =
st.st_gid;
133 return fchown(fd, owner, group);
135 #define fchown be_fchown
142 #define insecure_obj_p(obj, level) ((level) >= 4 || ((level) > 0 && OBJ_TAINTED(obj)))
292 return p ?
sizeof(
struct stat) : 0;
303 struct stat *nst = 0;
361 #define ST2UINT(val) ((val) & ~(~1UL << (sizeof(val) * CHAR_BIT - 1)))
364 # define NUM2DEVT(v) NUM2UINT(v)
367 # define DEVT2NUM(v) UINT2NUM(v)
369 #ifndef PRI_DEVT_PREFIX
370 # define PRI_DEVT_PREFIX ""
444 #if SIZEOF_STRUCT_STAT_ST_INO > SIZEOF_LONG
445 return ULL2NUM(
get_stat(
self)->st_ino);
556 #if defined(HAVE_ST_RDEV) && defined(major)
577 #if defined(HAVE_ST_RDEV) && defined(minor)
613 #ifdef HAVE_ST_BLKSIZE
634 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
635 # if SIZEOF_STRUCT_STAT_ST_BLOCKS > SIZEOF_LONG
636 return ULL2NUM(
get_stat(
self)->st_blocks);
650 #if defined(HAVE_STRUCT_STAT_ST_ATIM)
652 #elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
654 #elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
674 #if defined(HAVE_STRUCT_STAT_ST_MTIM)
676 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
678 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
698 #if defined(HAVE_STRUCT_STAT_ST_CTIM)
700 #elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
702 #elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
789 static const struct {
818 for (i = 0; i <
sizeof(member)/
sizeof(member[0]); i++) {
826 v = (*member[
i].func)(
self);
830 else if (i == 0 || i == 6) {
863 w32_io_info(
VALUE *file, BY_HANDLE_FILE_INFORMATION *
st)
874 if (f == (HANDLE)-1)
return INVALID_HANDLE_VALUE;
886 MultiByteToWideChar(CP_UTF8, 0,
RSTRING_PTR(tmp), -1, ptr, len);
887 f = CreateFileW(ptr, 0,
888 FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
889 FILE_FLAG_BACKUP_SEMANTICS,
NULL);
891 if (f == INVALID_HANDLE_VALUE)
return f;
894 if (GetFileType(f) == FILE_TYPE_DISK) {
895 ZeroMemory(st,
sizeof(*st));
896 if (GetFileInformationByHandle(f, st))
return ret;
898 if (ret) CloseHandle(ret);
899 return INVALID_HANDLE_VALUE;
949 if (
fstat(fptr->
fd, &st) == -1) {
1043 gary =
ALLOCV_N(GETGROUPS_T, v, groups);
1044 anum = getgroups(groups, gary);
1045 if (anum != -1 && anum != groups)
1056 while (--anum >= 0) {
1057 if (gary[anum] == gid) {
1070 # define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
1073 #if defined(S_IXGRP) && !defined(_WIN32) && !defined(__CYGWIN__)
1074 #define USE_GETEUID 1
1077 #ifndef HAVE_EACCESS
1085 if (
STAT(path, &st) < 0)
1103 if (st.st_uid == euid)
1108 if ((
int)(st.st_mode & mode) == mode)
return 0;
1112 return access(path, mode);
1147 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
1171 # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
1177 if (S_ISFIFO(st.st_mode))
return Qtrue;
1195 # define S_ISLNK(m) _S_ISLNK(m)
1198 # define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
1201 # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
1234 # define S_ISSOCK(m) _S_ISSOCK(m)
1237 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
1240 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
1250 if (S_ISSOCK(st.st_mode))
return Qtrue;
1270 # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
1272 # define S_ISBLK(m) (0)
1298 # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
1367 # define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
1371 # define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
1507 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1546 if (st.st_size == 0)
return Qtrue;
1566 if (st.st_size == 0)
return Qnil;
1624 #if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
1634 if (st.st_mode & mode)
return Qtrue;
1650 return check3rdbyte(fname, S_ISUID);
1667 return check3rdbyte(fname, S_ISGID);
1684 return check3rdbyte(fname, S_ISVTX);
1713 struct stat st1, st2;
1717 if (st1.st_dev != st2.st_dev)
return Qfalse;
1718 if (st1.st_ino != st2.st_ino)
return Qfalse;
1721 BY_HANDLE_FILE_INFORMATION st1, st2;
1722 HANDLE f1 = 0, f2 = 0;
1727 f1 = w32_io_info(&fname1, &st1);
1728 if (f1 == INVALID_HANDLE_VALUE)
return Qfalse;
1729 f2 = w32_io_info(&fname2, &st2);
1730 if (f1) CloseHandle(f1);
1731 if (f2 == INVALID_HANDLE_VALUE)
return Qfalse;
1732 if (f2) CloseHandle(f2);
1734 if (st1.dwVolumeSerialNumber == st2.dwVolumeSerialNumber &&
1735 st1.nFileIndexHigh == st2.nFileIndexHigh &&
1736 st1.nFileIndexLow == st2.nFileIndexLow)
1738 if (!f1 || !f2)
return Qfalse;
1771 if (
rb_stat(fname, &st) < 0) {
1786 else if (
S_ISDIR(st->st_mode)) {
1789 else if (
S_ISCHR(st->st_mode)) {
1790 t =
"characterSpecial";
1793 else if (
S_ISBLK(st->st_mode)) {
1798 else if (S_ISFIFO(st->st_mode)) {
1803 else if (
S_ISLNK(st->st_mode)) {
1808 else if (S_ISSOCK(st->st_mode)) {
1866 if (
rb_stat(fname, &st) < 0) {
1891 if (
fstat(fptr->
fd, &st) == -1) {
1914 if (
rb_stat(fname, &st) < 0) {
1938 if (
fstat(fptr->
fd, &st) == -1) {
1965 if (
rb_stat(fname, &st) < 0) {
1992 if (
fstat(fptr->
fd, &st) == -1) {
2018 if (
fstat(fptr->
fd, &st) == -1) {
2027 if (chmod(path, *(
int *)mode) < 0)
2087 if (fchmod(fptr->
fd, mode) == -1)
2099 #if defined(HAVE_LCHMOD)
2101 lchmod_internal(
const char *
path,
VALUE pathv,
void *mode)
2103 if (lchmod(path, (
int)(
VALUE)mode) < 0)
2128 n =
apply2files(lchmod_internal, rest, (
void *)(
long)mode);
2132 #define rb_file_s_lchmod rb_f_notimplement
2223 if (fchown(fptr->
fd, o, g) == -1)
2230 #if defined(HAVE_LCHOWN)
2232 lchown_internal(
const char *path,
VALUE pathv,
void *
arg)
2235 if (lchown(path, args->
owner, args->
group) < 0)
2276 #define rb_file_s_lchown rb_f_notimplement
2284 #if defined DOSISH || defined __CYGWIN__
2290 if (tsp &&
errno == EINVAL) {
2293 if (!
NIL_P(atime)) {
2296 if (!
NIL_P(mtime) && mtime != atime && !
rb_equal(atime, mtime)) {
2319 #define utime_failed(path, tsp, atime, mtime) rb_sys_fail_path(path)
2322 #if defined(HAVE_UTIMES)
2331 #ifdef HAVE_UTIMENSAT
2332 static int try_utimensat = 1;
2334 if (try_utimensat) {
2335 if (utimensat(AT_FDCWD, path, tsp, 0) < 0) {
2336 if (
errno == ENOSYS) {
2349 tvbuf[0].
tv_usec = (
int)(tsp[0].tv_nsec / 1000);
2351 tvbuf[1].
tv_usec = (
int)(tsp[1].tv_nsec / 1000);
2354 if (
utimes(path, tvp) < 0)
2360 #if !defined HAVE_UTIME_H && !defined HAVE_SYS_UTIME_H
2378 if (
utime(path, utp) < 0)
2421 const int max_pathlen = MAX_PATH;
2462 #define rb_file_s_link rb_f_notimplement
2493 #define rb_file_s_symlink rb_f_notimplement
2496 #ifdef HAVE_READLINK
2513 return rb_readlink(path);
2517 rb_readlink(
VALUE path)
2529 || (rv < 0 &&
errno == ERANGE)
2544 #define rb_file_s_readlink rb_f_notimplement
2550 if (unlink(path) < 0)
2597 #if defined __CYGWIN__
2600 if (rename(src, dst) < 0) {
2604 #if defined (__EMX__)
2607 if (chmod(dst, 0666) == 0 &&
2609 rename(src, dst) == 0)
2644 else if (argc == 1) {
2656 #if defined __CYGWIN__ || defined DOSISH
2658 #define DOSISH_DRIVE_LETTER
2659 #define FILE_ALT_SEPARATOR '\\'
2661 #ifdef FILE_ALT_SEPARATOR
2662 #define isdirsep(x) ((x) == '/' || (x) == FILE_ALT_SEPARATOR)
2663 static const char file_alt_separator[] = {FILE_ALT_SEPARATOR,
'\0'};
2665 #define isdirsep(x) ((x) == '/')
2669 #if defined _WIN32 || defined __CYGWIN__
2677 #define istrailinggarbage(x) ((x) == '.' || (x) == ' ')
2679 #define istrailinggarbage(x) 0
2682 #define Next(p, e, enc) ((p) + rb_enc_mbclen((p), (e), (enc)))
2683 #define Inc(p, e, enc) ((p) = Next((p), (e), (enc)))
2685 #if defined(DOSISH_UNC)
2686 #define has_unc(buf) (isdirsep((buf)[0]) && isdirsep((buf)[1]))
2688 #define has_unc(buf) 0
2691 #ifdef DOSISH_DRIVE_LETTER
2693 has_drive_letter(
const char *
buf)
2695 if (
ISALPHA(buf[0]) && buf[1] ==
':') {
2705 getcwdofdrv(
int drv)
2708 char *drvcwd, *oldcwd;
2719 if (chdir(drive) == 0) {
2733 not_same_drive(
VALUE path,
int drive)
2737 if (has_drive_letter(p)) {
2746 static inline char *
2749 #ifdef DOSISH_DRIVE_LETTER
2750 if (path + 2 <= end && has_drive_letter(path)) path += 2;
2752 while (path < end &&
isdirsep(*path)) path++;
2753 return (
char *)
path;
2756 #define nextdirsep rb_enc_path_next
2766 #if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
2767 #define skipprefix rb_enc_path_skip_prefix
2769 #define skipprefix(path, end, enc) (path)
2774 #if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
2778 while (path < end &&
isdirsep(*path)) path++;
2781 return (
char *)
path;
2784 #ifdef DOSISH_DRIVE_LETTER
2785 if (has_drive_letter(path))
2786 return (
char *)(path + 2);
2789 return (
char *)
path;
2792 static inline char *
2795 #if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
2804 #define strrdirsep rb_enc_path_last_separator
2809 while (path < end) {
2811 const char *tmp = path++;
2812 while (path < end &&
isdirsep(*path)) path++;
2813 if (path >= end)
break;
2817 Inc(path, end, enc);
2826 while (path < end) {
2828 const char *
last = path++;
2829 while (path < end &&
isdirsep(*path)) path++;
2830 if (path >= end)
return (
char *)
last;
2833 Inc(path, end, enc);
2836 return (
char *)
path;
2842 if (path < end &&
isdirsep(*path)) path++;
2850 while (path < end && *path ==
'.') path++;
2851 while (path < end && *path !=
':') {
2853 const char *
last = path++;
2855 if (path >= end || *path ==
':')
return (
char *)
last;
2858 const char *last = path++;
2859 while (path < end &&
isdirsep(*path)) path++;
2860 if (path >= end)
return (
char *)
last;
2861 if (*path ==
':') path++;
2864 Inc(path, end, enc);
2867 return (
char *)
path;
2871 #define BUFCHECK(cond) do {\
2874 do {buflen *= 2;} while (cond);\
2875 rb_str_resize(result, buflen);\
2876 buf = RSTRING_PTR(result);\
2878 pend = buf + buflen;\
2882 #define BUFINIT() (\
2883 p = buf = RSTRING_PTR(result),\
2884 buflen = RSTRING_LEN(result),\
2892 #if defined DOSISH || defined __CYGWIN__
2898 if (!user || !*user) {
2899 if (!(dir =
getenv(
"HOME"))) {
2908 struct passwd *pwPtr = getpwnam(user);
2913 dirlen =
strlen(pwPtr->pw_dir);
2923 #if defined DOSISH || defined __CYGWIN__
2924 for (bend = (p = buf) + dirlen; p < bend;
Inc(p, bend, enc)) {
2937 char *
buf, *cwdp = dir;
2941 if (*enc != fsenc) {
2943 if (direnc != fsenc) {
2949 do {buflen *= 2;}
while (dirlen > buflen);
2952 memcpy(buf, cwdp, dirlen);
2956 return buf + dirlen;
2962 const char *
s, *
b, *fend;
2963 char *
buf, *
p, *pend, *root;
2964 size_t buflen, bdiff;
2974 if (s[0] ==
'~' && abs_mode == 0) {
2977 if (
isdirsep(s[1]) || s[1] ==
'\0') {
2986 BUFCHECK(bdiff + userlen >= buflen);
3006 #ifdef DOSISH_DRIVE_LETTER
3008 else if (has_drive_letter(s)) {
3021 if (!
NIL_P(dname) && !not_same_drive(dname, s[0])) {
3030 char *e =
append_fspath(result, fname, getcwdofdrv(*s), &enc, fsenc);
3045 if (!
NIL_P(dname)) {
3057 #if defined DOSISH || defined __CYGWIN__
3078 if (p > buf && p[-1] ==
'/')
3101 if (*(s+1) ==
'\0' ||
isdirsep(*(s+1))) {
3120 #if defined DOSISH || defined __CYGWIN__
3145 #if defined DOSISH || defined __CYGWIN__
3149 long rootdiff = root -
buf;
3151 BUFCHECK(bdiff + (s-b+1) >= buflen);
3152 root = buf + rootdiff;
3167 static const char prime[] =
":$DATA";
3168 enum {prime_len =
sizeof(prime) -1};
3170 if (s > b + prime_len &&
strncasecmp(s - prime_len, prime, prime_len) == 0) {
3173 if (*(s - (prime_len+1)) ==
':') {
3176 else if (memchr(b,
':', s - prime_len - b)) {
3187 if (p ==
skiproot(buf, p + !!*p, enc) - 1) p++;
3191 if ((s =
strrdirsep(b = buf, p, enc)) != 0 && !strpbrk(s,
"*?")) {
3196 WIN32_FIND_DATAW wfd;
3199 #ifdef HAVE_CYGWIN_CONV_PATH
3200 char *w32buf =
NULL;
3201 const int flags = CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
3207 int lnk_added = 0, is_symlink = 0;
3213 if (len > 4 &&
STRCASECMP(p + len - 4,
".lnk") != 0) {
3217 path = *buf ? buf :
"/";
3218 #ifdef HAVE_CYGWIN_CONV_PATH
3219 bufsize = cygwin_conv_path(flags, path,
NULL, 0);
3222 if (lnk_added) bufsize += 4;
3224 if (cygwin_conv_path(flags, path, w32buf, bufsize) == 0) {
3230 if (cygwin_conv_to_win32_path(path, w32buf) == 0) {
3234 if (is_symlink && b == w32buf) {
3238 strlcat(w32buf,
".lnk", bufsize);
3254 MultiByteToWideChar(CP_UTF8, 0,
RSTRING_PTR(tmp), -1, wstr, len);
3256 h = FindFirstFileW(wstr, &wfd);
3258 if (h != INVALID_HANDLE_VALUE) {
3261 len = lstrlenW(wfd.cFileName);
3263 if (lnk_added && len > 4 &&
3264 wcscasecmp(wfd.cFileName + len - 4, L
".lnk") == 0) {
3265 wfd.cFileName[len -= 4] = L
'\0';
3272 len = WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen,
NULL, 0,
NULL,
NULL);
3274 WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, p, len + 1,
NULL,
NULL);
3275 if (tmp != result) {
3301 #define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, MAXPATHLEN + 2)
3303 #define check_expand_path_args(fname, dname) \
3304 (((fname) = rb_get_path(fname)), \
3305 (void)(NIL_P(dname) ? (dname) : ((dname) = rb_get_path(dname))))
3392 const char *pend = unresolved +
strlen(unresolved);
3396 while (unresolved < pend) {
3397 const char *testname = unresolved;
3399 long testnamelen = unresolved_firstsep - unresolved;
3400 const char *unresolved_nextname = unresolved_firstsep;
3401 while (unresolved_nextname < pend &&
isdirsep(*unresolved_nextname))
3402 unresolved_nextname++;
3403 unresolved = unresolved_nextname;
3404 if (testnamelen == 1 && testname[0] ==
'.') {
3406 else if (testnamelen == 2 && testname[0] ==
'.' && testname[1] ==
'.') {
3408 const char *resolved_str =
RSTRING_PTR(*resolvedp);
3409 const char *resolved_names = resolved_str + *prefixlenp;
3411 long len = lastsep ? lastsep - resolved_names : 0;
3420 #if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
3421 if (*prefixlenp > 1 && *prefixlenp ==
RSTRING_LEN(testpath)) {
3423 const char *last =
rb_enc_left_char_head(prefix, prefix + *prefixlenp - 1, prefix + *prefixlenp, enc);
3429 if (!
NIL_P(checkval)) {
3430 if (checkval ==
ID2SYM(resolving)) {
3442 #ifdef __native_client__
3448 if (
errno == ENOENT) {
3449 if (strict || !last || *unresolved_firstsep)
3451 *resolvedp = testpath;
3458 #ifdef HAVE_READLINK
3462 const char *link_prefix, *link_names;
3463 long link_prefixlen;
3465 link = rb_readlink(testpath);
3468 link_prefixlen = link_names - link_prefix;
3469 if (link_prefixlen > 0) {
3476 *prefixlenp = link_prefixlen;
3478 realpath_rec(prefixlenp, resolvedp, link_names, loopcheck, strict, *unresolved_firstsep ==
'\0');
3487 *resolvedp = testpath;
3494 #ifdef __native_client__
3506 volatile VALUE unresolved_path;
3511 char *path_names =
NULL, *basedir_names =
NULL, *curdir_names =
NULL;
3512 char *
ptr, *prefixptr =
NULL, *pend;
3520 if (!
NIL_P(basedir)) {
3527 if (ptr != path_names) {
3528 resolved =
rb_str_subseq(unresolved_path, 0, path_names - ptr);
3532 if (!
NIL_P(basedir)) {
3535 if (ptr != basedir_names) {
3548 pend = prefixptr + prefixlen;
3552 prefixlen = ++ptr - prefixptr;
3555 #ifdef FILE_ALT_SEPARATOR
3556 while (prefixptr < ptr) {
3557 if (*prefixptr == FILE_ALT_SEPARATOR) {
3560 Inc(prefixptr, pend, enc);
3566 realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, 1, 0);
3568 realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, 1, 0);
3569 realpath_rec(&prefixlen, &resolved, path_names, loopcheck, strict, 1);
3622 const char *
s, *
last;
3624 if (!e || !l2)
return 0;
3627 if (
rb_enc_ascget(e + len1, e + l2, &len2, enc) ==
'*' && len1 + len2 == l2) {
3628 if (c ==
'.')
return l0;
3638 if (l1 < l2)
return l1;
3642 #if CASEFOLD_FILESYSTEM
3643 #define fncomp strncasecmp
3645 #define fncomp strncmp
3647 if (
fncomp(s, e, l2) == 0) {
3656 const char *
p, *
q, *
e, *
end;
3657 #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
3662 end = name + (alllen ? (size_t)*alllen :
strlen(name));
3664 #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
3672 #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
3676 #ifdef DOSISH_DRIVE_LETTER
3677 else if (*p ==
':') {
3697 n = ntfs_tail(p, end, enc) -
p;
3701 for (q = p; q - p < n && *q ==
'.'; q++);
3702 for (e = 0; q - p <
n;
Inc(q, end, enc)) {
3703 if (*q ==
'.') e =
q;
3734 VALUE fname, fext, basename;
3735 const char *
name, *
p;
3739 if (
rb_scan_args(argc, argv,
"11", &fname, &fext) == 2) {
3804 if (root > name + 1 &&
isdirsep(*name))
3805 root =
skipprefix(name = root - 2, end, enc);
3807 if (root > name + 1)
3816 #ifdef DOSISH_DRIVE_LETTER
3817 if (has_drive_letter(name) &&
isdirsep(*(name + 2))) {
3825 #ifdef DOSISH_DRIVE_LETTER
3826 if (has_drive_letter(name) && root == name + 2 && p - name == 2)
3849 const char *
p, *
e, *end = name + (len ? *len : (long)
strlen(name));
3858 while (*p && *p ==
'.') p++;
3862 const char *last = p++, *dot =
last;
3864 if (*p ==
'.') dot =
p;
3867 if (!*p || *p ==
':') {
3871 if (*last ==
'.' || dot > last) e = dot;
3878 else if (*p ==
':') {
3889 if (!e || e == name)
3924 const char *
name, *
e;
4013 RBASIC(result)->klass = 0;
4017 switch (
TYPE(tmp)) {
4042 else if (!
NIL_P(sep)) {
4079 #if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE)
4104 #ifdef HAVE_TRUNCATE
4115 if (chsize(tmpfd, pos) < 0) {
4125 #define rb_file_s_truncate rb_f_notimplement
4128 #if defined(HAVE_FTRUNCATE) || defined(HAVE_CHSIZE)
4156 #ifdef HAVE_FTRUNCATE
4160 if (chsize(fptr->
fd, pos) < 0)
4166 #define rb_file_truncate rb_f_notimplement
4183 #include <winerror.h>
4184 extern unsigned long __attribute__((stdcall)) GetLastError(
void);
4191 int old_errno =
errno;
4193 int *op =
data, ret =
flock(op[0], op[1]);
4196 if (GetLastError() == ERROR_NOT_LOCKED) {
4256 op[1] = op1 =
NUM2INT(operation);
4267 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
4279 #if defined(ERESTART)
4300 for (i=1; i<
n; i++) {
4307 #define CHECK(n) test_check((n), argc, argv)
4384 if (
strchr(
"bcdefgGkloOprRsSuwWxXz", cmd)) {
4456 if (
strchr(
"MAC", cmd)) {
4458 VALUE fname = argv[1];
4461 if (
rb_stat(fname, &st) == -1) {
4481 if (
strchr(
"=<>", cmd)) {
4482 struct stat st1, st2;
4490 if (st1.st_mtime == st2.st_mtime)
return Qtrue;
4494 if (st1.st_mtime > st2.st_mtime)
return Qtrue;
4498 if (st1.st_mtime < st2.st_mtime)
return Qtrue;
4538 struct stat st, *nst;
5075 if (size == 0)
return Qnil;
5152 #ifdef DOSISH_DRIVE_LETTER
5153 if (has_drive_letter(path) &&
isdirsep(path[2]))
return 1;
5159 if (path[0] ==
'/')
return 1;
5164 #ifndef ENABLE_PATH_CHECK
5165 # if defined DOSISH || defined __CYGWIN__
5166 # define ENABLE_PATH_CHECK 0
5168 # define ENABLE_PATH_CHECK 1
5172 #if ENABLE_PATH_CHECK
5198 # define S_IWOTH 002
5202 && !(p && execpath && (st.st_mode & S_ISVTX))
5205 rb_warn(
"Insecure world writable dir %s in %sPATH, mode 0%"
5206 PRI_MODET_PREFIX
"o",
5207 p0, (execpath ?
"" :
"LOAD_"), st.st_mode);
5214 if (!s || s == p0)
return 1;
5222 #if ENABLE_PATH_CHECK
5223 #define fpath_check(path) path_check_0((path), FALSE)
5225 #define fpath_check(path) 1
5231 #if ENABLE_PATH_CHECK
5232 const char *p0, *
p, *pend;
5235 if (!path)
return 1;
5237 pend = path +
strlen(path);
5247 if (p0 > pend)
break;
5256 #ifdef __native_client__
5257 __attribute__((noinline))
5264 if (fd == -1)
return 0;
5282 if (*path++ !=
'.')
return 0;
5283 if (*path ==
'.') path++;
5305 VALUE fname = *filep, load_path,
tmp;
5309 if (!ext[0])
return 0;
5327 for (i=0; ext[
i]; i++) {
5338 if (safe_level >= 4) {
5343 if (!load_path)
return 0;
5346 RBASIC(fname)->klass = 0;
5350 for (j=0; ext[j]; j++) {
5352 for (i = 0; i <
RARRAY_LEN(load_path); i++) {
5403 if (safe_level >= 4) {
5413 for (i = 0; i <
RARRAY_LEN(load_path); i++) {
5446 #elif defined AMIGA || defined __amigaos__
5611 #if defined(O_NDELAY) || defined(O_NONBLOCK)
5613 # define O_NONBLOCK O_NDELAY
#define RB_TYPE_P(obj, type)
RUBY_EXTERN int flock(int, int)
static VALUE rb_stat_ino(VALUE self)
void rb_w32_init_file(void)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
VALUE rb_home_dir(const char *user, VALUE result)
VALUE rb_str_ellipsize(VALUE, long)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
static VALUE rb_file_socket_p(VALUE obj, VALUE fname)
static VALUE rb_file_s_mtime(VALUE klass, VALUE fname)
int rb_is_absolute_path(const char *)
static VALUE stat_mtime(struct stat *st)
void rb_enc_copy(VALUE obj1, VALUE obj2)
void rb_file_const(const char *, VALUE)
static VALUE rb_file_sgid_p(VALUE obj, VALUE fname)
static struct timespec stat_atimespec(struct stat *st)
size_t strlen(const char *)
static VALUE rb_get_path_check(VALUE obj, int level)
static VALUE rb_stat_z(VALUE obj)
VALUE rb_class_new_instance(int, VALUE *, VALUE)
RUBY_EXTERN VALUE rb_cStat
static VALUE rb_stat_init(VALUE obj, VALUE fname)
const char * rb_obj_classname(VALUE)
static VALUE rb_file_executable_p(VALUE obj, VALUE fname)
static VALUE rb_stat_rdev(VALUE self)
static VALUE rb_stat_cmp(VALUE self, VALUE other)
VALUE rb_get_expanded_load_path(void)
static VALUE rb_stat_init_copy(VALUE copy, VALUE orig)
static VALUE rb_file_grpowned_p(VALUE obj, VALUE fname)
VALUE rb_str_tmp_new(long)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
VALUE rb_str_buf_append(VALUE, VALUE)
#define skipprefix(path, end, enc)
#define access(path, mode)
static VALUE rb_file_size_p(VALUE obj, VALUE fname)
int rb_file_load_ok(const char *)
static VALUE rb_file_s_size(VALUE klass, VALUE fname)
char * rb_enc_path_next(const char *, const char *, rb_encoding *)
static VALUE rb_f_test(int argc, VALUE *argv)
static VALUE rb_stat_mode(VALUE self)
SSL_METHOD *(* func)(void)
#define rb_usascii_str_new2
static VALUE rb_file_world_writable_p(VALUE obj, VALUE fname)
int rb_str_cmp(VALUE, VALUE)
VALUE rb_file_s_absolute_path(int, VALUE *)
static VALUE rb_file_readable_p(VALUE obj, VALUE fname)
VALUE rb_time_nano_new(time_t, long)
static VALUE rb_stat_f(VALUE obj)
void rb_io_check_initialized(rb_io_t *)
VALUE rb_str_subseq(VALUE, long, long)
VALUE rb_str_new_cstr(const char *)
const char * ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc)
VALUE rb_enc_from_encoding(rb_encoding *encoding)
SOCKET rb_w32_get_osfhandle(int)
VALUE rb_obj_freeze(VALUE)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
int rb_find_file_ext_safe(VALUE *, const char *const *, int)
void rb_update_max_fd(int fd)
rb_encoding * rb_default_internal_encoding(void)
VALUE rb_file_expand_path_fast(VALUE, VALUE)
static VALUE rb_file_flock(VALUE obj, VALUE operation)
int rb_usascii_encindex(void)
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
VALUE rb_str_buf_cat2(VALUE, const char *)
static VALUE rb_stat_blocks(VALUE self)
static VALUE copy_path_class(VALUE path, VALUE orig)
VALUE rb_find_file_safe(VALUE, int)
unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len_p, rb_encoding *enc)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_raise(VALUE exc, const char *fmt,...)
static long apply2files(void(*func)(const char *, VALUE, void *), VALUE vargs, void *arg)
static struct timespec stat_mtimespec(struct stat *st)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
VALUE rb_obj_class(VALUE)
static VALUE rb_stat_w(VALUE obj)
VALUE rb_io_taint_check(VALUE)
VALUE rb_str_encode_ospath(VALUE)
#define rb_enc_left_char_head(s, p, e, enc)
static VALUE rb_file_zero_p(VALUE obj, VALUE fname)
RUBY_EXTERN VALUE rb_eIOError
static VALUE rb_stat_d(VALUE obj)
static VALUE file_inspect_join(VALUE ary, VALUE argp, int recur)
static VALUE rb_file_size(VALUE obj)
void rb_include_module(VALUE klass, VALUE module)
static VALUE file_path_convert(VALUE name)
static VALUE rb_file_lstat(VALUE obj)
static VALUE rb_stat_dev_minor(VALUE self)
static VALUE rb_file_suid_p(VALUE obj, VALUE fname)
static VALUE rb_file_s_basename(int argc, VALUE *argv)
static VALUE rb_stat_S(VALUE obj)
static VALUE file_expand_path_1(VALUE fname)
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
static VALUE rb_file_s_utime(int argc, VALUE *argv)
static VALUE rb_stat_s(VALUE obj)
static VALUE rb_stat_dev(VALUE self)
rb_encoding * rb_utf8_encoding(void)
static void realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE loopcheck, int strict, int last)
static void sys_fail2(VALUE s1, VALUE s2)
static VALUE rb_file_ctime(VALUE obj)
static VALUE rb_stat_uid(VALUE self)
#define GetOpenFile(obj, fp)
VALUE rb_str_append(VALUE, VALUE)
static VALUE rb_stat_r(VALUE obj)
static VALUE rb_stat_grpowned(VALUE obj)
VALUE rb_equal(VALUE, VALUE)
int truncate(const char *path, off_t new_size)
void rb_str_modify_expand(VALUE, long)
VALUE rb_file_expand_path(VALUE, VALUE)
#define ENCODING_GET(obj)
static VALUE rb_stat_x(VALUE obj)
VALUE rb_get_path_no_checksafe(VALUE)
static char * chompdirsep(const char *path, const char *end, rb_encoding *enc)
#define rb_file_s_readlink
void rb_exc_raise(VALUE mesg)
static VALUE rb_file_blockdev_p(VALUE obj, VALUE fname)
static VALUE rb_file_world_readable_p(VALUE obj, VALUE fname)
static VALUE rb_stat_s_alloc(VALUE klass)
int utimes(const char *filename, const struct timeval times[2])
static VALUE rb_file_ftype(const struct stat *st)
RUBY_EXTERN size_t strlcat(char *, const char *, size_t)
VALUE rb_find_file(VALUE)
static VALUE rb_thread_flock(void *data)
VALUE rb_file_dirname(VALUE fname)
static int path_check_0(VALUE path, int execpath)
static VALUE stat_ctime(struct stat *st)
static rb_encoding * check_path_encoding(VALUE str)
static VALUE rb_stat_size(VALUE self)
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
static VALUE rb_file_s_split(VALUE klass, VALUE path)
RUBY_EXTERN VALUE rb_mFileTest
static VALUE rb_file_pipe_p(VALUE obj, VALUE fname)
#define FilePathStringValue(v)
static VALUE rb_file_s_chmod(int argc, VALUE *argv)
#define TypedData_Get_Struct(obj, type, data_type, sval)
static VALUE rb_file_s_lstat(VALUE klass, VALUE fname)
size_t rb_str_capacity(VALUE)
#define StringValuePtr(v)
#define STRCASECMP(s1, s2)
static VALUE rb_file_readable_real_p(VALUE obj, VALUE fname)
#define rb_file_s_symlink
char * rb_enc_path_skip_prefix(const char *, const char *, rb_encoding *)
static VALUE rb_file_s_stat(VALUE klass, VALUE fname)
static VALUE rb_file_mtime(VALUE obj)
static VALUE rb_file_s_chown(int argc, VALUE *argv)
static VALUE rb_file_s_realpath(int argc, VALUE *argv, VALUE klass)
VALUE rb_get_path_check_convert(VALUE, VALUE, int)
static VALUE rb_stat_owned(VALUE obj)
#define StringValueCStr(v)
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
static int is_explicit_relative(const char *path)
void rb_define_const(VALUE, const char *, VALUE)
#define ENC_CODERANGE_CLEAR(obj)
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
static VALUE rb_file_exist_p(VALUE obj, VALUE fname)
int chown(const char *, int, int)
static char * skiproot(const char *path, const char *end, rb_encoding *enc)
#define OBJ_INIT_COPY(obj, orig)
#define insecure_obj_p(obj, level)
static VALUE rb_file_sticky_p(VALUE obj, VALUE fname)
static VALUE rb_file_s_join(VALUE klass, VALUE args)
static VALUE rb_file_atime(VALUE obj)
static size_t stat_memsize(const void *p)
mode_t umask(mode_t mask)
static VALUE rb_stat_b(VALUE obj)
#define TypedData_Wrap_Struct(klass, data_type, sval)
#define fpath_check(path)
unsigned char buf[MIME_BUF_SIZE]
VALUE rb_enc_associate_index(VALUE obj, int idx)
static void chmod_internal(const char *path, VALUE pathv, void *mode)
#define ALLOCA_N(type, n)
VALUE rb_check_funcall(VALUE, ID, int, VALUE *)
static VALUE rb_stat_suid(VALUE obj)
int link(const char *, const char *)
static VALUE rb_file_writable_real_p(VALUE obj, VALUE fname)
static VALUE rb_stat_sticky(VALUE obj)
static VALUE rb_stat_ftype(VALUE obj)
const char * ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc)
static char * append_fspath(VALUE result, VALUE fname, char *dir, rb_encoding **enc, rb_encoding *fsenc)
VALUE rb_str_new_shared(VALUE)
VALUE rb_str_buf_cat(VALUE, const char *, long)
VALUE rb_file_absolute_path(VALUE, VALUE)
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
VALUE rb_file_directory_p(VALUE, VALUE)
static VALUE rb_stat_blksize(VALUE self)
VALUE rb_str_resize(VALUE, long)
static VALUE rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
char * rb_enc_path_end(const char *, const char *, rb_encoding *)
VALUE rb_sprintf(const char *format,...)
RUBY_EXTERN int eaccess(const char *, int)
VALUE rb_eSystemCallError
static VALUE rb_file_s_path(VALUE klass, VALUE fname)
static VALUE rb_stat_dev_major(VALUE self)
#define CONST_ID(var, str)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
static char * skipprefixroot(const char *path, const char *end, rb_encoding *enc)
static VALUE rb_stat_ctime(VALUE self)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
rb_encoding * rb_usascii_encoding(void)
VALUE rb_file_s_expand_path(int, VALUE *)
VALUE rb_str_inspect(VALUE)
static int rb_group_member(GETGROUPS_T gid)
int ftruncate(int fd, off_t new_size)
#define EXPAND_PATH_BUFFER()
#define check_expand_path_args(fname, dname)
VALUE rb_str_buf_new(long)
#define RUBY_TYPED_DEFAULT_FREE
static VALUE rb_stat_sgid(VALUE obj)
char * strchr(char *, char)
static VALUE rb_stat_inspect(VALUE self)
char * rb_enc_path_last_separator(const char *, const char *, rb_encoding *)
static VALUE rb_file_writable_p(VALUE obj, VALUE fname)
static void utime_internal(const char *path, VALUE pathv, void *arg)
static struct timespec stat_ctimespec(struct stat *st)
RUBY_EXTERN VALUE rb_cString
static void chown_internal(const char *path, VALUE pathv, void *arg)
int rb_find_file_ext(VALUE *, const char *const *)
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
static void test_check(int n, int argc, VALUE *argv)
VALUE rb_define_module_under(VALUE outer, const char *name)
VALUE rb_obj_taint(VALUE)
static VALUE rb_stat_wr(VALUE obj)
RUBY_EXTERN VALUE rb_cFile
static VALUE rb_stat_mtime(VALUE self)
static VALUE stat_new(struct stat *st)
VALUE rb_str_cat(VALUE, const char *, long)
#define ENC_CODERANGE_7BIT
rb_encoding * rb_enc_get(VALUE obj)
#define utime_failed(path, tsp, atime, mtime)
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
void rb_insecure_operation(void)
static const char null_device[]
static VALUE stat_new_0(VALUE klass, struct stat *st)
void rb_thread_wait_for(struct timeval)
int utime(const char *filename, const struct utimbuf *times)
static VALUE rb_file_s_ftype(VALUE klass, VALUE fname)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
int rb_enc_str_asciionly_p(VALUE)
static const rb_data_type_t stat_data_type
static VALUE rb_file_chown(VALUE obj, VALUE owner, VALUE group)
static VALUE rb_stat_rowned(VALUE obj)
static VALUE rb_stat_c(VALUE obj)
static VALUE rb_file_s_extname(VALUE klass, VALUE fname)
#define rb_str_dup_frozen
static VALUE rb_file_chmod(VALUE obj, VALUE vmode)
VALUE rb_str_catf(VALUE str, const char *format,...)
RUBY_EXTERN VALUE rb_cObject
static VALUE rb_file_chardev_p(VALUE obj, VALUE fname)
static VALUE stat_atime(struct stat *st)
static VALUE rb_file_s_dirname(VALUE klass, VALUE fname)
static VALUE rb_file_owned_p(VALUE obj, VALUE fname)
static void unlink_internal(const char *path, VALUE pathv, void *arg)
rb_encoding * rb_filesystem_encoding(void)
static VALUE rb_stat_atime(VALUE self)
static VALUE rb_stat_gid(VALUE self)
static VALUE rb_file_rowned_p(VALUE obj, VALUE fname)
static size_t rmext(const char *p, long l0, long l1, const char *e, long l2, rb_encoding *enc)
static VALUE rb_file_s_rename(VALUE klass, VALUE from, VALUE to)
static VALUE rb_stat_p(VALUE obj)
static VALUE rb_stat_rdev_major(VALUE self)
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
VALUE rb_str_new(const char *, long)
static struct stat * get_stat(VALUE self)
static int rb_stat(VALUE file, struct stat *st)
static VALUE rb_stat_X(VALUE obj)
#define istrailinggarbage(x)
#define rb_enc_asciicompat(enc)
static VALUE rb_file_executable_real_p(VALUE obj, VALUE fname)
VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE)
static VALUE rb_stat_ww(VALUE obj)
static VALUE rb_file_s_ctime(VALUE klass, VALUE fname)
static VALUE rb_file_path(VALUE obj)
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
static VALUE rb_io_stat(VALUE obj)
#define rb_check_arity(argc, min, max)
VALUE rb_hash_aref(VALUE, VALUE)
int rb_path_check(const char *)
rb_encoding * rb_ascii8bit_encoding(void)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
static VALUE rb_stat_nlink(VALUE self)
VALUE rb_get_path_check_to_string(VALUE, int)
struct timespec rb_time_timespec(VALUE time)
VALUE rb_define_module(const char *name)
static VALUE rb_file_s_umask(int argc, VALUE *argv)
int rb_memcicmp(const void *, const void *, long)
#define rb_file_s_truncate
int rb_enc_str_coderange(VALUE)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
static VALUE rb_stat_rdev_minor(VALUE self)
static VALUE rb_stat_l(VALUE obj)
static VALUE rb_file_s_realdirpath(int argc, VALUE *argv, VALUE klass)
static VALUE rb_file_s_unlink(VALUE klass, VALUE args)
#define ALLOCV_N(type, v, n)
static VALUE rb_file_join(VALUE ary, VALUE sep)
void rb_warn(const char *fmt,...)
void rb_io_check_closed(rb_io_t *)
static VALUE rb_stat_W(VALUE obj)
static VALUE rb_file_s_atime(VALUE klass, VALUE fname)
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
static VALUE rb_stat_R(VALUE obj)
VALUE rb_str_plus(VALUE, VALUE)
static void define_filetest_function(const char *name, VALUE(*func)(ANYARGS), int argc)
rb_encoding * rb_enc_from_index(int index)
#define rb_sys_fail_path(path)
static VALUE rb_file_file_p(VALUE obj, VALUE fname)
static VALUE rb_file_symlink_p(VALUE obj, VALUE fname)
void rb_str_set_len(VALUE, long)