19 #include <sys/cygwin.h> 23 #include <CoreFoundation/CFString.h> 37 #ifdef HAVE_SYS_TIME_H 38 # include <sys/time.h> 41 #ifdef HAVE_SYS_FILE_H 42 # include <sys/file.h> 47 #ifdef HAVE_SYS_PARAM_H 48 # include <sys/param.h> 51 # define MAXPATHLEN 1024 60 #elif defined HAVE_SYS_UTIME_H 61 #include <sys/utime.h> 68 #ifdef HAVE_SYS_SYSMACROS_H 69 #include <sys/sysmacros.h> 72 #include <sys/types.h> 75 #if defined(__native_client__) 76 # if defined(NACL_NEWLIB) 81 # undef HAVE_UTIMENSAT 85 #ifdef HAVE_SYS_MKDEV_H 86 #include <sys/mkdev.h> 89 #if defined(HAVE_FCNTL_H) 93 #if defined(HAVE_SYS_TIME_H) 97 #if !defined HAVE_LSTAT && !defined lstat 104 #define STAT(p, s) rb_w32_ustati64((p), (s)) 106 #define lstat(p, s) rb_w32_ulstati64((p), (s)) 108 #define access(p, m) rb_w32_uaccess((p), (m)) 110 #define truncate(p, n) rb_w32_utruncate((p), (n)) 112 #define chmod(p, m) rb_w32_uchmod((p), (m)) 114 #define chown(p, o, g) rb_w32_uchown((p), (o), (g)) 116 #define lchown(p, o, g) rb_w32_ulchown((p), (o), (g)) 118 #define utime(p, t) rb_w32_uutime((p), (t)) 120 #define link(f, t) rb_w32_ulink((f), (t)) 122 #define unlink(p) rb_w32_uunlink(p) 124 #define rename(f, t) rb_w32_urename((f), (t)) 126 #define symlink(s, l) rb_w32_usymlink((s), (l)) 128 #define STAT(p, s) stat((p), (s)) 131 #if defined _WIN32 || defined __APPLE__ 132 # define USE_OSPATH 1 133 # define TO_OSPATH(str) rb_str_encode_ospath(str) 135 # define USE_OSPATH 0 136 # define TO_OSPATH(str) (str) 143 #define insecure_obj_p(obj, level) ((level) > 0 && OBJ_TAINTED(obj)) 167 check_path_encoding(
VALUE str)
199 tmp = file_path_convert(tmp);
204 check_path_encoding(tmp);
251 # define NORMALIZE_UTF8PATH 1 253 rb_str_append_normalized_ospath(
VALUE str,
const char *ptr,
long len)
257 CFStringRef s = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
258 (
const UInt8 *)ptr, len,
259 kCFStringEncodingUTF8,
FALSE,
261 CFMutableStringRef m = CFStringCreateMutableCopy(kCFAllocatorDefault, len, s);
264 CFStringNormalize(m, kCFStringNormalizationFormC);
265 all = CFRangeMake(0, CFStringGetLength(m));
266 CFStringGetBytes(m, all, kCFStringEncodingUTF8,
'?',
FALSE,
NULL, 0, &buflen);
268 CFStringGetBytes(m, all, kCFStringEncodingUTF8,
'?',
FALSE,
269 (UInt8 *)(
RSTRING_PTR(str) + oldlen), buflen, &buflen);
277 rb_str_normalize_ospath(
const char *ptr,
long len)
280 const char *e = ptr +
len;
291 static const char invalid[3] =
"\xEF\xBF\xBD";
292 rb_str_append_normalized_ospath(str, p1, p-p1);
300 if ((0x2000 <= c && c <= 0x2FFF) || (0xF900 <= c && c <= 0xFAFF) ||
301 (0x2F800 <= c && c <= 0x2FAFF)) {
303 rb_str_append_normalized_ospath(str, p1, p-p1);
314 rb_str_append_normalized_ospath(str, p1, p-p1);
324 if (p+3 > e)
return 0;
325 switch ((
unsigned char)*p) {
327 switch ((
unsigned char)p[1]) {
329 c = (
unsigned char)p[2];
331 if (c >= 0x8c && c <= 0x8f)
return 3;
333 if (c >= 0xaa && c <= 0xae)
return 3;
336 c = (
unsigned char)p[2];
338 if (c >= 0xaa && c <= 0xaf)
return 3;
344 if ((
unsigned char)p[1] == 0xbb &&
345 (
unsigned char)p[2] == 0xbf)
352 # define NORMALIZE_UTF8PATH 0 355 #define apply2args(n) (rb_check_arity(argc, n, UNLIMITED_ARGUMENTS), argc-=n) 358 apply2files(
void (*func)(
const char *,
VALUE,
void *),
int argc,
VALUE *
argv,
void *arg)
363 for (i=0; i<
argc; i++) {
368 (*func)(s,
path, arg);
394 rb_file_path(
VALUE obj)
409 stat_memsize(
const void *p)
411 return sizeof(
struct stat);
421 stat_new_0(
VALUE klass,
const struct stat *st)
423 struct stat *nst = 0;
449 static struct timespec stat_mtimespec(struct stat *st);
470 struct timespec ts1 = stat_mtimespec(get_stat(
self));
471 struct timespec ts2 = stat_mtimespec(get_stat(other));
483 #define ST2UINT(val) ((val) & ~(~1UL << (sizeof(val) * CHAR_BIT - 1))) 486 # define NUM2DEVT(v) NUM2UINT(v) 489 # define DEVT2NUM(v) UINT2NUM(v) 491 #ifndef PRI_DEVT_PREFIX 492 # define PRI_DEVT_PREFIX "" 506 rb_stat_dev(
VALUE self)
508 return DEVT2NUM(get_stat(
self)->st_dev);
523 rb_stat_dev_major(
VALUE self)
526 return DEVT2NUM(major(get_stat(
self)->st_dev));
544 rb_stat_dev_minor(
VALUE self)
547 return DEVT2NUM(minor(get_stat(
self)->st_dev));
564 rb_stat_ino(
VALUE self)
567 struct stat *st = get_stat(
self);
568 unsigned short *p2 = (
unsigned short *)st;
569 unsigned int *p4 = (
unsigned int *)st;
577 #elif SIZEOF_STRUCT_STAT_ST_INO > SIZEOF_LONG 578 return ULL2NUM(get_stat(
self)->st_ino);
580 return ULONG2NUM(get_stat(
self)->st_ino);
598 rb_stat_mode(
VALUE self)
616 rb_stat_nlink(
VALUE self)
618 return UINT2NUM(get_stat(
self)->st_nlink);
632 rb_stat_uid(
VALUE self)
634 return UIDT2NUM(get_stat(
self)->st_uid);
648 rb_stat_gid(
VALUE self)
650 return GIDT2NUM(get_stat(
self)->st_gid);
666 rb_stat_rdev(
VALUE self)
668 #ifdef HAVE_STRUCT_STAT_ST_RDEV 669 return DEVT2NUM(get_stat(
self)->st_rdev);
687 rb_stat_rdev_major(
VALUE self)
689 #if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(major) 690 return DEVT2NUM(major(get_stat(
self)->st_rdev));
708 rb_stat_rdev_minor(
VALUE self)
710 #if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(minor) 711 return DEVT2NUM(minor(get_stat(
self)->st_rdev));
727 rb_stat_size(
VALUE self)
729 return OFFT2NUM(get_stat(
self)->st_size);
744 rb_stat_blksize(
VALUE self)
746 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 747 return ULONG2NUM(get_stat(
self)->st_blksize);
765 rb_stat_blocks(
VALUE self)
767 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS 768 # if SIZEOF_STRUCT_STAT_ST_BLOCKS > SIZEOF_LONG 769 return ULL2NUM(get_stat(
self)->st_blocks);
771 return ULONG2NUM(get_stat(
self)->st_blocks);
779 stat_atimespec(struct stat *st)
783 #if defined(HAVE_STRUCT_STAT_ST_ATIM) 784 ts.
tv_nsec = st->st_atim.tv_nsec;
785 #elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC) 786 ts.
tv_nsec = st->st_atimespec.tv_nsec;
787 #elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC) 788 ts.
tv_nsec = (long)st->st_atimensec;
796 stat_atime(
struct stat *st)
798 struct timespec ts = stat_atimespec(st);
803 stat_mtimespec(struct stat *st)
807 #if defined(HAVE_STRUCT_STAT_ST_MTIM) 808 ts.
tv_nsec = st->st_mtim.tv_nsec;
809 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC) 810 ts.
tv_nsec = st->st_mtimespec.tv_nsec;
811 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) 812 ts.
tv_nsec = (long)st->st_mtimensec;
820 stat_mtime(
struct stat *st)
822 struct timespec ts = stat_mtimespec(st);
827 stat_ctimespec(struct stat *st)
831 #if defined(HAVE_STRUCT_STAT_ST_CTIM) 832 ts.
tv_nsec = st->st_ctim.tv_nsec;
833 #elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC) 834 ts.
tv_nsec = st->st_ctimespec.tv_nsec;
835 #elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC) 836 ts.
tv_nsec = (long)st->st_ctimensec;
844 stat_ctime(
struct stat *st)
846 struct timespec ts = stat_ctimespec(st);
850 #define HAVE_STAT_BIRTHTIME 851 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) 853 stat_birthtime(
struct stat *st)
855 struct timespec *ts = &st->st_birthtimespec;
858 #elif defined(_WIN32) 859 # define stat_birthtime stat_ctime 861 # undef HAVE_STAT_BIRTHTIME 876 rb_stat_atime(
VALUE self)
878 return stat_atime(get_stat(
self));
892 rb_stat_mtime(
VALUE self)
894 return stat_mtime(get_stat(
self));
912 rb_stat_ctime(
VALUE self)
914 return stat_ctime(get_stat(
self));
917 #if defined(HAVE_STAT_BIRTHTIME) 943 return stat_birthtime(get_stat(
self));
946 # define rb_stat_birthtime rb_f_notimplement 965 rb_stat_inspect(
VALUE self)
969 static const struct {
973 {
"dev", rb_stat_dev},
974 {
"ino", rb_stat_ino},
975 {
"mode", rb_stat_mode},
976 {
"nlink", rb_stat_nlink},
977 {
"uid", rb_stat_uid},
978 {
"gid", rb_stat_gid},
979 {
"rdev", rb_stat_rdev},
980 {
"size", rb_stat_size},
981 {
"blksize", rb_stat_blksize},
982 {
"blocks", rb_stat_blocks},
983 {
"atime", rb_stat_atime},
984 {
"mtime", rb_stat_mtime},
985 {
"ctime", rb_stat_ctime},
986 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) 1001 for (i = 0; i <
sizeof(member)/
sizeof(member[0]); i++) {
1009 v = (*member[i].func)(
self);
1013 else if (i == 0 || i == 6) {
1035 no_gvl_fstat(
void *data)
1042 no_gvl_stat(
void * data)
1049 rb_stat(
VALUE file,
struct stat *st)
1074 w32_io_info(
VALUE *file, BY_HANDLE_FILE_INFORMATION *st)
1085 if (f == (HANDLE)-1)
return INVALID_HANDLE_VALUE;
1097 MultiByteToWideChar(CP_UTF8, 0,
RSTRING_PTR(tmp), -1, ptr, len);
1098 f = CreateFileW(ptr, 0,
1099 FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
1100 FILE_FLAG_BACKUP_SEMANTICS,
NULL);
1102 if (f == INVALID_HANDLE_VALUE)
return f;
1105 if (GetFileType(f) == FILE_TYPE_DISK) {
1106 ZeroMemory(st,
sizeof(*st));
1107 if (GetFileInformationByHandle(f, st))
return ret;
1109 if (ret) CloseHandle(ret);
1110 return INVALID_HANDLE_VALUE;
1114 close_handle(
VALUE h)
1116 CloseHandle((HANDLE)h);
1120 struct w32_io_info_args {
1122 BY_HANDLE_FILE_INFORMATION *st;
1126 call_w32_io_info(
VALUE arg)
1128 struct w32_io_info_args *p = (
void *)arg;
1129 return (
VALUE)w32_io_info(p->fname, p->st);
1150 if (rb_stat(fname, &st) < 0) {
1172 rb_io_stat(
VALUE obj)
1178 if (
fstat(fptr->
fd, &st) == -1) {
1186 no_gvl_lstat(
void *ptr)
1193 lstat_without_gvl(
const char *path,
struct stat *st)
1232 return rb_file_s_stat(klass, fname);
1251 rb_file_lstat(
VALUE obj)
1261 if (lstat_without_gvl(
RSTRING_PTR(path), &st) == -1) {
1266 return rb_io_stat(obj);
1271 rb_group_member(GETGROUPS_T gid)
1273 #if defined(_WIN32) || !defined(HAVE_GETGROUPS) 1291 gary =
ALLOCV_N(GETGROUPS_T, v, groups);
1292 anum = getgroups(groups, gary);
1293 if (anum != -1 && anum != groups)
1304 while (--anum >= 0) {
1305 if (gary[anum] == gid) {
1318 # define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) 1321 #if defined(S_IXGRP) && !defined(_WIN32) && !defined(__CYGWIN__) 1322 #define USE_GETEUID 1 1325 #ifdef __native_client__ 1330 # undef HAVE_EACCESS 1334 #ifndef HAVE_EACCESS 1346 return access(path, mode);
1348 if (
STAT(path, &st) < 0)
1364 if (st.st_uid == euid)
1366 else if (rb_group_member(st.st_gid))
1369 if ((
int)(st.st_mode & mode) == mode)
return 0;
1373 return access(path, mode);
1408 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 1413 if (rb_stat(fname, &st) < 0)
return Qfalse;
1432 # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) 1437 if (rb_stat(fname, &st) < 0)
return Qfalse;
1438 if (S_ISFIFO(st.st_mode))
return Qtrue;
1456 # define S_ISLNK(m) _S_ISLNK(m) 1459 # define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK) 1462 # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) 1494 # define S_ISSOCK(m) _S_ISSOCK(m) 1497 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK) 1500 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) 1509 if (rb_stat(fname, &st) < 0)
return Qfalse;
1510 if (S_ISSOCK(st.st_mode))
return Qtrue;
1530 # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) 1532 # define S_ISBLK(m) (0) 1539 if (rb_stat(fname, &st) < 0)
return Qfalse;
1558 # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) 1563 if (rb_stat(fname, &st) < 0)
return Qfalse;
1585 if (rb_stat(fname, &st) < 0)
return Qfalse;
1598 const char *s =
"FileTest#";
1607 rb_warning(
"%sexists? is a deprecated name, use %sexist? instead", s, s);
1608 return rb_file_exist_p(obj, fname);
1637 rb_file_readable_real_p(
VALUE obj,
VALUE fname)
1646 # define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH) 1650 # define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH) 1670 rb_file_world_readable_p(
VALUE obj,
VALUE fname)
1675 if (rb_stat(fname, &st) < 0)
return Qnil;
1709 rb_file_writable_real_p(
VALUE obj,
VALUE fname)
1734 rb_file_world_writable_p(
VALUE obj,
VALUE fname)
1739 if (rb_stat(fname, &st) < 0)
return Qnil;
1773 rb_file_executable_real_p(
VALUE obj,
VALUE fname)
1782 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 1802 if (rb_stat(fname, &st) < 0)
return Qfalse;
1822 if (rb_stat(fname, &st) < 0)
return Qfalse;
1823 if (st.st_size == 0)
return Qtrue;
1842 if (rb_stat(fname, &st) < 0)
return Qnil;
1843 if (st.st_size == 0)
return Qnil;
1863 if (rb_stat(fname, &st) < 0)
return Qfalse;
1873 if (rb_stat(fname, &st) < 0)
return Qfalse;
1895 if (rb_stat(fname, &st) < 0)
return Qfalse;
1896 if (rb_group_member(st.st_gid))
return Qtrue;
1901 #if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX) 1903 check3rdbyte(
VALUE fname,
int mode)
1907 if (rb_stat(fname, &st) < 0)
return Qfalse;
1908 if (st.st_mode & mode)
return Qtrue;
1924 return check3rdbyte(fname, S_ISUID);
1941 return check3rdbyte(fname, S_ISGID);
1958 return check3rdbyte(fname, S_ISVTX);
1987 struct stat st1, st2;
1989 if (rb_stat(fname1, &st1) < 0)
return Qfalse;
1990 if (rb_stat(fname2, &st2) < 0)
return Qfalse;
1991 if (st1.st_dev != st2.st_dev)
return Qfalse;
1992 if (st1.st_ino != st2.st_ino)
return Qfalse;
1995 BY_HANDLE_FILE_INFORMATION st1, st2;
1996 HANDLE f1 = 0, f2 = 0;
1998 f1 = w32_io_info(&fname1, &st1);
1999 if (f1 == INVALID_HANDLE_VALUE)
return Qfalse;
2001 struct w32_io_info_args arg;
2002 arg.fname = &fname2;
2007 f2 = w32_io_info(&fname2, &st2);
2009 if (f2 == INVALID_HANDLE_VALUE)
return Qfalse;
2010 if (f2) CloseHandle(f2);
2012 if (st1.dwVolumeSerialNumber == st2.dwVolumeSerialNumber &&
2013 st1.nFileIndexHigh == st2.nFileIndexHigh &&
2014 st1.nFileIndexLow == st2.nFileIndexLow)
2034 if (rb_stat(fname, &st) < 0) {
2043 rb_file_ftype(
const struct stat *st)
2050 else if (
S_ISDIR(st->st_mode)) {
2053 else if (
S_ISCHR(st->st_mode)) {
2054 t =
"characterSpecial";
2057 else if (
S_ISBLK(st->st_mode)) {
2062 else if (S_ISFIFO(st->st_mode)) {
2067 else if (
S_ISLNK(st->st_mode)) {
2072 else if (S_ISSOCK(st->st_mode)) {
2109 return rb_file_ftype(&st);
2129 if (rb_stat(fname, &st) < 0) {
2134 return stat_atime(&st);
2149 rb_file_atime(
VALUE obj)
2155 if (
fstat(fptr->
fd, &st) == -1) {
2158 return stat_atime(&st);
2178 if (rb_stat(fname, &st) < 0) {
2183 return stat_mtime(&st);
2197 rb_file_mtime(
VALUE obj)
2203 if (
fstat(fptr->
fd, &st) == -1) {
2206 return stat_mtime(&st);
2230 if (rb_stat(fname, &st) < 0) {
2235 return stat_ctime(&st);
2252 rb_file_ctime(
VALUE obj)
2258 if (
fstat(fptr->
fd, &st) == -1) {
2261 return stat_ctime(&st);
2264 #if defined(HAVE_STAT_BIRTHTIME) 2284 if (rb_stat(fname, &st) < 0) {
2289 return stat_birthtime(&st);
2292 # define rb_file_s_birthtime rb_f_notimplement 2295 #if defined(HAVE_STAT_BIRTHTIME) 2315 if (
fstat(fptr->
fd, &st) == -1) {
2318 return stat_birthtime(&st);
2321 # define rb_file_birthtime rb_f_notimplement 2335 rb_file_size(
VALUE obj)
2344 if (
fstat(fptr->
fd, &st) == -1) {
2351 chmod_internal(
const char *path,
VALUE pathv,
void *mode)
2353 if (chmod(path, *(
int *)mode) < 0)
2378 return apply2files(chmod_internal, argc, argv, &mode);
2399 #if !defined HAVE_FCHMOD || !HAVE_FCHMOD 2407 if (
fchmod(fptr->
fd, mode) == -1) {
2415 #if !defined HAVE_FCHMOD || !HAVE_FCHMOD 2425 #if defined(HAVE_LCHMOD) 2427 lchmod_internal(
const char *path,
VALUE pathv,
void *mode)
2429 if (lchmod(path, (
int)(
VALUE)mode) < 0)
2451 return apply2files(lchmod_internal, argc, argv, (
void *)(
long)mode);
2454 #define rb_file_s_lchmod rb_f_notimplement 2457 static inline rb_uid_t
2461 return (rb_uid_t)-1;
2466 static inline rb_gid_t
2470 return (rb_gid_t)-1;
2481 chown_internal(
const char *path,
VALUE pathv,
void *arg)
2504 rb_file_s_chown(
int argc,
VALUE *argv)
2509 arg.
owner = to_uid(*argv++);
2510 arg.
group = to_gid(*argv++);
2512 return apply2files(chown_internal, argc, argv, &arg);
2549 if (fchown(fptr->
fd, o, g) == -1)
2556 #if defined(HAVE_LCHOWN) 2558 lchown_internal(
const char *path,
VALUE pathv,
void *arg)
2582 arg.
owner = to_uid(*argv++);
2583 arg.
group = to_gid(*argv++);
2585 return apply2files(lchown_internal, argc, argv, &arg);
2588 #define rb_file_s_lchown rb_f_notimplement 2596 #if defined DOSISH || defined __CYGWIN__ 2603 if (tsp && e == EINVAL) {
2606 if (!
NIL_P(atime)) {
2609 if (!
NIL_P(mtime) && mtime != atime && !
rb_equal(atime, mtime)) {
2612 if (
NIL_P(a)) e[0] = m;
2631 #define utime_failed(path, tsp, atime, mtime) rb_sys_fail_path(path) 2634 #if defined(HAVE_UTIMES) 2637 utime_internal(
const char *path,
VALUE pathv,
void *arg)
2643 #if defined(HAVE_UTIMENSAT) 2644 static int try_utimensat = 1;
2646 if (try_utimensat) {
2647 if (utimensat(
AT_FDCWD, path, tsp, 0) < 0) {
2648 if (
errno == ENOSYS) {
2666 if (
utimes(path, tvp) < 0)
2672 #if !defined HAVE_UTIME_H && !defined HAVE_SYS_UTIME_H 2680 utime_internal(
const char *path,
VALUE pathv,
void *arg)
2690 if (
utime(path, utp) < 0)
2706 rb_file_s_utime(
int argc,
VALUE *argv)
2712 args.
atime = *argv++;
2713 args.
mtime = *argv++;
2725 return apply2files(utime_internal, argc, argv, &args);
2728 #ifdef RUBY_FUNCTION_NAME_STRING 2729 # define syserr_fail2(e, s1, s2) syserr_fail2_in(RUBY_FUNCTION_NAME_STRING, e, s1, s2) 2731 # define syserr_fail2_in(func, e, s1, s2) syserr_fail2(e, s1, s2) 2733 #define sys_fail2(s1, s2) syserr_fail2(errno, s1, s2) 2740 const int max_pathlen = MAX_PATH;
2753 #ifdef RUBY_FUNCTION_NAME_STRING 2754 rb_syserr_fail_path_in(func, e, str);
2787 #define rb_file_s_link rb_f_notimplement 2817 #define rb_file_s_symlink rb_f_notimplement 2820 #ifdef HAVE_READLINK 2851 || (rv < 0 &&
errno == ERANGE)
2869 #define rb_file_s_readlink rb_f_notimplement 2873 unlink_internal(
const char *path,
VALUE pathv,
void *arg)
2875 if (unlink(path) < 0)
2896 rb_file_s_unlink(
int argc,
VALUE *argv,
VALUE klass)
2898 return apply2files(unlink_internal, argc, argv, 0);
2907 no_gvl_rename(
void *ptr)
2936 #if defined __CYGWIN__ 2945 if (chmod(ra.
dst, 0666) == 0 &&
2946 unlink(ra.
dst) == 0 &&
2947 rename(ra.
src, ra.
dst) == 0)
2951 syserr_fail2(e, from, to);
2973 rb_file_s_umask(
int argc,
VALUE *argv)
2981 else if (argc == 1) {
2993 #if defined __CYGWIN__ || defined DOSISH 2995 #define DOSISH_DRIVE_LETTER 2996 #define FILE_ALT_SEPARATOR '\\' 2998 #ifdef FILE_ALT_SEPARATOR 2999 #define isdirsep(x) ((x) == '/' || (x) == FILE_ALT_SEPARATOR) 3001 static const char file_alt_separator[] = {FILE_ALT_SEPARATOR,
'\0'};
3004 #define isdirsep(x) ((x) == '/') 3014 #ifndef USE_NTFS_ADS 3016 # define USE_NTFS_ADS 1 3018 # define USE_NTFS_ADS 0 3023 #define istrailinggarbage(x) ((x) == '.' || (x) == ' ') 3025 #define istrailinggarbage(x) 0 3028 # define isADS(x) ((x) == ':') 3033 #define Next(p, e, enc) ((p) + rb_enc_mbclen((p), (e), (enc))) 3034 #define Inc(p, e, enc) ((p) = Next((p), (e), (enc))) 3036 #if defined(DOSISH_UNC) 3037 #define has_unc(buf) (isdirsep((buf)[0]) && isdirsep((buf)[1])) 3039 #define has_unc(buf) 0 3042 #ifdef DOSISH_DRIVE_LETTER 3044 has_drive_letter(
const char *
buf)
3046 if (
ISALPHA(buf[0]) && buf[1] ==
':') {
3056 getcwdofdrv(
int drv)
3059 char *drvcwd, *oldcwd;
3070 if (chdir(drive) == 0) {
3084 not_same_drive(
VALUE path,
int drive)
3088 if (has_drive_letter(p)) {
3097 static inline char *
3098 skiproot(
const char *path,
const char *end,
rb_encoding *enc)
3100 #ifdef DOSISH_DRIVE_LETTER 3101 if (path + 2 <= end && has_drive_letter(path)) path += 2;
3103 while (path < end &&
isdirsep(*path)) path++;
3104 return (
char *)path;
3107 #define nextdirsep rb_enc_path_next 3117 #if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER) 3118 #define skipprefix rb_enc_path_skip_prefix 3120 #define skipprefix(path, end, enc) (path) 3125 #if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER) 3129 while (path < end &&
isdirsep(*path)) path++;
3132 return (
char *)path;
3135 #ifdef DOSISH_DRIVE_LETTER 3136 if (has_drive_letter(path))
3137 return (
char *)(path + 2);
3140 return (
char *)path;
3143 static inline char *
3144 skipprefixroot(
const char *path,
const char *end,
rb_encoding *enc)
3146 #if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER) 3151 return skiproot(path, end, enc);
3155 #define strrdirsep rb_enc_path_last_separator 3160 while (path < end) {
3162 const char *tmp = path++;
3163 while (path < end &&
isdirsep(*path)) path++;
3164 if (path >= end)
break;
3168 Inc(path, end, enc);
3175 chompdirsep(
const char *path,
const char *end,
rb_encoding *enc)
3177 while (path < end) {
3179 const char *
last = path++;
3180 while (path < end &&
isdirsep(*path)) path++;
3181 if (path >= end)
return (
char *)
last;
3184 Inc(path, end, enc);
3187 return (
char *)path;
3193 if (path < end &&
isdirsep(*path)) path++;
3194 return chompdirsep(path, end, enc);
3199 ntfs_tail(
const char *path,
const char *end,
rb_encoding *enc)
3201 while (path < end && *path ==
'.') path++;
3202 while (path < end && !
isADS(*path)) {
3204 const char *
last = path++;
3206 if (path >= end ||
isADS(*path))
return (
char *)
last;
3209 const char *
last = path++;
3210 while (path < end &&
isdirsep(*path)) path++;
3211 if (path >= end)
return (
char *)
last;
3212 if (
isADS(*path)) path++;
3215 Inc(path, end, enc);
3218 return (
char *)path;
3222 #define BUFCHECK(cond) do {\ 3225 do {buflen *= 2;} while (cond);\ 3226 rb_str_resize(result, buflen);\ 3227 buf = RSTRING_PTR(result);\ 3229 pend = buf + buflen;\ 3233 #define BUFINIT() (\ 3234 p = buf = RSTRING_PTR(result),\ 3235 buflen = RSTRING_LEN(result),\ 3239 # define SKIPPATHSEP(p) ((*(p)) ? 1 : 0) 3241 # define SKIPPATHSEP(p) 1 3244 #define BUFCOPY(srcptr, srclen) do { \ 3245 const int skip = SKIPPATHSEP(p); \ 3246 rb_str_set_len(result, p-buf+skip); \ 3247 BUFCHECK(bdiff + ((srclen)+skip) >= buflen); \ 3249 memcpy(p, (srcptr), (srclen)); \ 3253 #define WITH_ROOTDIFF(stmt) do { \ 3254 long rootdiff = root - buf; \ 3256 root = buf + rootdiff; \ 3260 copy_home_path(
VALUE result,
const char *dir)
3263 #if defined DOSISH || defined __CYGWIN__ 3275 #if defined DOSISH || defined __CYGWIN__ 3277 for (bend = (p = buf) + dirlen; p < bend;
Inc(p, bend, enc)) {
3290 struct passwd *pwPtr;
3293 const char *pwPtr = 0;
3294 # define endpwent() ((void)0) 3308 pwPtr = getpwnam(username);
3311 dir = pwPtr =
getenv(
"HOME");
3318 dir = pwPtr->pw_dir;
3320 copy_home_path(result, dir);
3329 const char *dir =
getenv(
"HOME");
3331 #if defined HAVE_PWD_H 3335 struct passwd *pw = getpwnam(login);
3337 copy_home_path(result, pw->pw_dir);
3353 return copy_home_path(result, dir);
3359 #if NORMALIZE_UTF8PATH 3360 VALUE path = rb_str_normalize_ospath(ptr, len);
3371 char *
buf, *cwdp = dir;
3377 if (direnc != fsenc) {
3386 do {buflen *= 2;}
while (dirlen > buflen);
3389 memcpy(buf, cwdp, dirlen);
3393 return buf + dirlen;
3399 const char *s, *b, *fend;
3400 char *
buf, *p, *pend, *root;
3401 size_t buflen, bdiff;
3411 if (s[0] ==
'~' && abs_mode == 0) {
3414 if (
isdirsep(s[1]) || s[1] ==
'\0') {
3425 BUFCHECK(bdiff + userlen >= buflen);
3426 memcpy(p, b, userlen);
3437 (
int)userlen, b, fname);
3446 #ifdef DOSISH_DRIVE_LETTER 3448 else if (has_drive_letter(s)) {
3461 if (!
NIL_P(dname) && !not_same_drive(dname, s[0])) {
3470 char *e = append_fspath(result, fname, getcwdofdrv(*s), &enc, fsenc);
3479 p = chompdirsep(skiproot(buf, p, enc), p, enc);
3485 if (!
NIL_P(dname)) {
3492 char *e = append_fspath(result, fname,
my_getcwd(), &enc, fsenc);
3497 #if defined DOSISH || defined __CYGWIN__ 3505 p = chompdirsep(skiproot(buf, p, enc), p, enc);
3514 memset(buf,
'/', len);
3518 if (p > buf && p[-1] ==
'/')
3541 if (*(s+1) ==
'\0' ||
isdirsep(*(s+1))) {
3560 #if defined DOSISH || defined __CYGWIN__ 3585 #if defined DOSISH || defined __CYGWIN__ 3597 int n = ignored_char_p(s, fend, enc);
3616 static const char prime[] =
":$DATA";
3617 enum {prime_len =
sizeof(prime) -1};
3621 if (s > b + prime_len &&
strncasecmp(s - prime_len, prime, prime_len) == 0) {
3624 if (
isADS(*(s - (prime_len+1)))) {
3627 else if (memchr(b,
':', s - prime_len - b)) {
3636 if (p == skiproot(buf, p + !!*p, enc) - 1) p++;
3640 if ((s =
strrdirsep(b = buf, p, enc)) != 0 && !strpbrk(s,
"*?")) {
3645 WIN32_FIND_DATAW wfd;
3648 #ifdef HAVE_CYGWIN_CONV_PATH 3649 char *w32buf =
NULL;
3650 const int flags = CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
3656 int lnk_added = 0, is_symlink = 0;
3660 if (lstat_without_gvl(buf, &st) == 0 &&
S_ISLNK(st.st_mode)) {
3662 if (len > 4 &&
STRCASECMP(p + len - 4,
".lnk") != 0) {
3666 path = *buf ?
buf :
"/";
3667 #ifdef HAVE_CYGWIN_CONV_PATH 3668 bufsize = cygwin_conv_path(flags, path,
NULL, 0);
3671 if (lnk_added) bufsize += 4;
3673 if (cygwin_conv_path(flags, path, w32buf, bufsize) == 0) {
3679 if (cygwin_conv_to_win32_path(path, w32buf) == 0) {
3683 if (is_symlink && b == w32buf) {
3687 strlcat(w32buf,
".lnk", bufsize);
3703 MultiByteToWideChar(CP_UTF8, 0,
RSTRING_PTR(tmp), -1, wstr, len);
3705 h = FindFirstFileW(wstr, &wfd);
3707 if (h != INVALID_HANDLE_VALUE) {
3710 len = lstrlenW(wfd.cFileName);
3712 if (lnk_added && len > 4 &&
3713 wcscasecmp(wfd.cFileName + len - 4, L
".lnk") == 0) {
3714 wfd.cFileName[len -= 4] = L
'\0';
3721 len = WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen,
NULL, 0,
NULL,
NULL);
3722 if (tmp == result) {
3724 WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, p, len + 1,
NULL,
NULL);
3728 WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen,
RSTRING_PTR(tmp), len + 1,
NULL,
NULL);
3752 #define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, MAXPATHLEN + 2) 3755 str_shrink(
VALUE str)
3761 #define expand_path(fname, dname, abs_mode, long_name, result) \ 3762 str_shrink(rb_file_expand_path_internal(fname, dname, abs_mode, long_name, result)) 3764 #define check_expand_path_args(fname, dname) \ 3765 (((fname) = rb_get_path(fname)), \ 3766 (void)(NIL_P(dname) ? (dname) : ((dname) = rb_get_path(dname)))) 3769 file_expand_path_1(
VALUE fname)
3849 #ifdef __native_client__ 3870 realpath_rec(
long *prefixlenp,
VALUE *resolvedp,
const char *unresolved,
3873 const char *pend = unresolved +
strlen(unresolved);
3877 while (unresolved < pend) {
3878 const char *testname = unresolved;
3880 long testnamelen = unresolved_firstsep - unresolved;
3881 const char *unresolved_nextname = unresolved_firstsep;
3882 while (unresolved_nextname < pend &&
isdirsep(*unresolved_nextname))
3883 unresolved_nextname++;
3884 unresolved = unresolved_nextname;
3885 if (testnamelen == 1 && testname[0] ==
'.') {
3887 else if (testnamelen == 2 && testname[0] ==
'.' && testname[1] ==
'.') {
3889 const char *resolved_str =
RSTRING_PTR(*resolvedp);
3890 const char *resolved_names = resolved_str + *prefixlenp;
3892 long len = lastsep ? lastsep - resolved_names : 0;
3901 #if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER) 3902 if (*prefixlenp > 1 && *prefixlenp ==
RSTRING_LEN(testpath)) {
3904 const char *last =
rb_enc_left_char_head(prefix, prefix + *prefixlenp - 1, prefix + *prefixlenp, enc);
3910 if (!
NIL_P(checkval)) {
3911 if (checkval ==
ID2SYM(resolving)) {
3925 #ifdef __native_client__ 3928 ret = lstat_without_gvl(
RSTRING_PTR(testpath), &sbuf);
3936 *resolvedp = testpath;
3943 #ifdef HAVE_READLINK 3947 const char *link_prefix, *link_names;
3948 long link_prefixlen;
3953 link_prefixlen = link_names - link_prefix;
3954 if (link_prefixlen > 0) {
3961 *prefixlenp = link_prefixlen;
3963 if (realpath_rec(prefixlenp, resolvedp, link_names,
3964 loopcheck, mode, !*unresolved_firstsep))
3974 *resolvedp = testpath;
3987 VALUE unresolved_path;
3992 char *path_names =
NULL, *basedir_names =
NULL, *curdir_names =
NULL;
3993 char *ptr, *prefixptr =
NULL, *pend;
3998 if (!
NIL_P(basedir)) {
4005 unresolved_path =
TO_OSPATH(unresolved_path);
4007 path_names = skipprefixroot(ptr, ptr + len,
rb_enc_get(unresolved_path));
4008 if (ptr != path_names) {
4009 resolved =
rb_str_subseq(unresolved_path, 0, path_names - ptr);
4013 if (!
NIL_P(basedir)) {
4015 basedir_names = skipprefixroot(ptr, ptr + len,
rb_enc_get(basedir));
4016 if (ptr != basedir_names) {
4024 curdir_names = skipprefixroot(ptr, ptr + len,
rb_enc_get(curdir));
4029 pend = prefixptr + prefixlen;
4030 ptr = chompdirsep(prefixptr, pend, enc);
4032 prefixlen = ++ptr - prefixptr;
4035 #ifdef FILE_ALT_SEPARATOR 4036 while (prefixptr < ptr) {
4037 if (*prefixptr == FILE_ALT_SEPARATOR) {
4040 Inc(prefixptr, pend, enc);
4052 if (realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, mode, 0))
4055 if (basedir_names) {
4056 if (realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, mode, 0))
4059 if (realpath_rec(&prefixlen, &resolved, path_names, loopcheck, mode, 1))
4082 return rb_check_realpath_internal(basedir, path, mode);
4106 rb_file_s_realpath(
int argc,
VALUE *argv,
VALUE klass)
4109 VALUE path = argv[0];
4127 rb_file_s_realdirpath(
int argc,
VALUE *argv,
VALUE klass)
4130 VALUE path = argv[0];
4136 rmext(
const char *p,
long l0,
long l1,
const char *e,
long l2,
rb_encoding *enc)
4140 const char *s, *
last;
4142 if (!e || !l2)
return 0;
4145 if (
rb_enc_ascget(e + len1, e + l2, &len2, enc) ==
'*' && len1 + len2 == l2) {
4146 if (c ==
'.')
return l0;
4156 if (l1 < l2)
return l1;
4160 #if CASEFOLD_FILESYSTEM 4161 #define fncomp strncasecmp 4163 #define fncomp strncmp 4165 if (
fncomp(s, e, l2) == 0) {
4174 const char *p, *q, *e, *end;
4175 #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC 4180 end = name + (alllen ? (size_t)*alllen :
strlen(name));
4182 #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC 4190 #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC 4194 #ifdef DOSISH_DRIVE_LETTER 4195 else if (*p ==
':') {
4215 n = ntfs_tail(p, end, enc) - p;
4217 n = chompdirsep(p, end, enc) - p;
4219 for (q = p; q - p < n && *q ==
'.'; q++);
4220 for (e = 0; q - p < n;
Inc(q, end, enc)) {
4221 if (*q ==
'.') e = q;
4253 rb_file_s_basename(
int argc,
VALUE *argv)
4255 VALUE fname, fext, basename;
4256 const char *
name, *p;
4264 enc = check_path_encoding(fext);
4283 if (!(f = rmext(p, f, n, fp,
RSTRING_LEN(fext), enc))) {
4319 const char *
name, *root, *p, *end;
4327 root = skiproot(name, end, enc);
4329 if (root > name + 1 &&
isdirsep(*name))
4330 root =
skipprefix(name = root - 2, end, enc);
4332 if (root > name + 1)
4341 #ifdef DOSISH_DRIVE_LETTER 4342 if (has_drive_letter(name) &&
isdirsep(*(name + 2))) {
4343 const char *
top = skiproot(name + 2, end, enc);
4350 #ifdef DOSISH_DRIVE_LETTER 4351 if (has_drive_letter(name) && root == name + 2 && p - name == 2)
4374 const char *p, *e, *end = name + (len ? *
len : (long)
strlen(name));
4380 do name = ++p;
while (
isdirsep(*p));
4383 while (*p && *p ==
'.') p++;
4387 const char *
last = p++, *dot =
last;
4389 if (*p ==
'.') dot = p;
4392 if (!*p ||
isADS(*p)) {
4396 if (*last ==
'.' || dot > last) e = dot;
4403 else if (
isADS(*p)) {
4414 if (!e || e == name)
4450 const char *
name, *e;
4506 return rb_file_join(arg);
4510 rb_file_join(
VALUE ary)
4514 const char *
name, *tail;
4524 check_path_encoding(tmp);
4539 if (!checked) check_path_encoding(tmp);
4559 tail = chompdirsep(name, name + len,
rb_enc_get(result));
4590 return rb_file_join(args);
4593 #if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE) 4612 #ifdef HAVE_TRUNCATE 4613 #define NUM2POS(n) NUM2OFFT(n) 4616 #define NUM2POS(n) NUM2LONG(n) 4623 #ifdef HAVE_TRUNCATE 4634 if (chsize(tmpfd, pos) < 0) {
4646 #define rb_file_s_truncate rb_f_notimplement 4649 #if defined(HAVE_FTRUNCATE) || defined(HAVE_CHSIZE) 4668 #if defined(HAVE_FTRUNCATE) 4669 #define NUM2POS(n) NUM2OFFT(n) 4672 #define NUM2POS(n) NUM2LONG(n) 4682 #ifdef HAVE_FTRUNCATE 4686 if (chsize(fptr->
fd, pos) < 0)
4693 #define rb_file_truncate rb_f_notimplement 4710 #include <winerror.h> 4714 rb_thread_flock(
void *data)
4717 int old_errno =
errno;
4719 int *op = data, ret =
flock(op[0], op[1]);
4722 if (GetLastError() == ERROR_NOT_LOCKED) {
4781 op[1] = op1 =
NUM2INT(operation);
4793 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 4805 #if defined(ERESTART) 4818 test_check(
int n,
int argc,
VALUE *argv)
4824 for (i=1; i<n; i++) {
4831 #define CHECK(n) test_check((n), argc, argv) 4892 rb_f_test(
int argc,
VALUE *argv)
4908 if (
strchr(
"bcdefgGkloOprRsSuwWxXz", cmd)) {
4912 return rb_file_blockdev_p(0, argv[1]);
4915 return rb_file_chardev_p(0, argv[1]);
4921 return rb_file_exist_p(0, argv[1]);
4924 return rb_file_file_p(0, argv[1]);
4927 return rb_file_sgid_p(0, argv[1]);
4930 return rb_file_grpowned_p(0, argv[1]);
4933 return rb_file_sticky_p(0, argv[1]);
4936 return rb_file_symlink_p(0, argv[1]);
4939 return rb_file_owned_p(0, argv[1]);
4942 return rb_file_rowned_p(0, argv[1]);
4945 return rb_file_pipe_p(0, argv[1]);
4948 return rb_file_readable_p(0, argv[1]);
4951 return rb_file_readable_real_p(0, argv[1]);
4954 return rb_file_size_p(0, argv[1]);
4957 return rb_file_socket_p(0, argv[1]);
4960 return rb_file_suid_p(0, argv[1]);
4963 return rb_file_writable_p(0, argv[1]);
4966 return rb_file_writable_real_p(0, argv[1]);
4969 return rb_file_executable_p(0, argv[1]);
4972 return rb_file_executable_real_p(0, argv[1]);
4975 return rb_file_zero_p(0, argv[1]);
4979 if (
strchr(
"MAC", cmd)) {
4981 VALUE fname = argv[1];
4984 if (rb_stat(fname, &st) == -1) {
4992 return stat_atime(&st);
4994 return stat_mtime(&st);
4996 return stat_ctime(&st);
5002 return rb_file_identical_p(0, argv[1], argv[2]);
5005 if (
strchr(
"=<>", cmd)) {
5006 struct stat st1, st2;
5010 if (rb_stat(argv[1], &st1) < 0)
return Qfalse;
5011 if (rb_stat(argv[2], &st2) < 0)
return Qfalse;
5013 t1 = stat_mtimespec(&st1);
5014 t2 = stat_mtimespec(&st2);
5051 rb_stat_s_alloc(
VALUE klass)
5053 return stat_new_0(klass, 0);
5068 struct stat st, *nst;
5079 nst =
ALLOC(
struct stat);
5098 nst =
ALLOC(
struct stat);
5099 *nst = *(
struct stat*)
DATA_PTR(orig);
5121 rb_stat_ftype(
VALUE obj)
5123 return rb_file_ftype(get_stat(obj));
5138 rb_stat_d(
VALUE obj)
5153 rb_stat_p(
VALUE obj)
5156 if (S_ISFIFO(get_stat(obj)->st_mode))
return Qtrue;
5180 rb_stat_l(
VALUE obj)
5201 rb_stat_S(
VALUE obj)
5204 if (S_ISSOCK(get_stat(obj)->st_mode))
return Qtrue;
5224 rb_stat_b(
VALUE obj)
5246 rb_stat_c(
VALUE obj)
5266 rb_stat_owned(
VALUE obj)
5273 rb_stat_rowned(
VALUE obj)
5275 if (get_stat(obj)->st_uid ==
getuid())
return Qtrue;
5292 rb_stat_grpowned(
VALUE obj)
5295 if (rb_group_member(get_stat(obj)->st_gid))
return Qtrue;
5312 rb_stat_r(
VALUE obj)
5314 struct stat *st = get_stat(obj);
5320 if (rb_stat_owned(obj))
5324 if (rb_stat_grpowned(obj))
5345 rb_stat_R(
VALUE obj)
5347 struct stat *st = get_stat(obj);
5353 if (rb_stat_rowned(obj))
5357 if (rb_group_member(get_stat(obj)->st_gid))
5380 rb_stat_wr(
VALUE obj)
5383 struct stat *st = get_stat(obj);
5405 rb_stat_w(
VALUE obj)
5407 struct stat *st = get_stat(obj);
5413 if (rb_stat_owned(obj))
5417 if (rb_stat_grpowned(obj))
5438 rb_stat_W(
VALUE obj)
5440 struct stat *st = get_stat(obj);
5446 if (rb_stat_rowned(obj))
5450 if (rb_group_member(get_stat(obj)->st_gid))
5473 rb_stat_ww(
VALUE obj)
5476 struct stat *st = get_stat(obj);
5500 rb_stat_x(
VALUE obj)
5502 struct stat *st = get_stat(obj);
5510 if (rb_stat_owned(obj))
5514 if (rb_stat_grpowned(obj))
5532 rb_stat_X(
VALUE obj)
5534 struct stat *st = get_stat(obj);
5542 if (rb_stat_rowned(obj))
5546 if (rb_group_member(get_stat(obj)->st_gid))
5567 rb_stat_f(
VALUE obj)
5585 rb_stat_z(
VALUE obj)
5587 if (get_stat(obj)->st_size == 0)
return Qtrue;
5602 rb_stat_s(
VALUE obj)
5606 if (size == 0)
return Qnil;
5622 rb_stat_suid(
VALUE obj)
5625 if (get_stat(obj)->st_mode & S_ISUID)
return Qtrue;
5643 rb_stat_sgid(
VALUE obj)
5646 if (get_stat(obj)->st_mode & S_ISGID)
return Qtrue;
5664 rb_stat_sticky(
VALUE obj)
5667 if (get_stat(obj)->st_mode & S_ISVTX)
return Qtrue;
5672 #if !defined HAVE_MKFIFO && defined HAVE_MKNOD && defined S_IFIFO 5673 #define mkfifo(path, mode) mknod(path, (mode)&~S_IFMT|S_IFIFO, 0) 5707 #define rb_file_s_mkfifo rb_f_notimplement 5721 #ifdef DOSISH_DRIVE_LETTER 5722 if (has_drive_letter(path) &&
isdirsep(path[2]))
return 1;
5728 if (path[0] ==
'/')
return 1;
5733 #ifndef ENABLE_PATH_CHECK 5734 # if defined DOSISH || defined __CYGWIN__ 5735 # define ENABLE_PATH_CHECK 0 5737 # define ENABLE_PATH_CHECK 1 5741 #if ENABLE_PATH_CHECK 5743 path_check_0(
VALUE path,
int execpath)
5767 # define S_IWOTH 002 5771 && !(p && execpath && (st.st_mode & S_ISVTX))
5774 rb_enc_warn(enc,
"Insecure world writable dir %s in %sPATH, mode 0%" 5775 PRI_MODET_PREFIX
"o",
5776 p0, (execpath ?
"" :
"LOAD_"), st.st_mode);
5783 if (!s || s == p0)
return 1;
5791 #if ENABLE_PATH_CHECK 5792 #define fpath_check(path) path_check_0((path), FALSE) 5794 #define fpath_check(path) 1 5800 #if ENABLE_PATH_CHECK 5801 const char *p0, *p, *pend;
5804 if (!path)
return 1;
5806 pend = path +
strlen(path);
5816 if (p0 > pend)
break;
5832 if (
fstat(fd, &st) < 0)
5838 if (S_ISFIFO(st.st_mode))
5859 int mode = (O_RDONLY |
5860 #if defined O_NONBLOCK 5862 #elif defined O_NDELAY 5867 if (fd == -1)
return 0;
5876 is_explicit_relative(
const char *path)
5878 if (*path++ !=
'.')
return 0;
5879 if (*path ==
'.') path++;
5902 VALUE fname = *filep, load_path, tmp;
5906 if (!ext[0])
return 0;
5909 fname = file_expand_path_1(fname);
5922 if (!expanded) fname = file_expand_path_1(fname);
5924 for (i=0; ext[i]; i++) {
5927 *filep = copy_path_class(fname, *filep);
5936 if (!load_path)
return 0;
5943 for (j=0; ext[j]; j++) {
5945 for (i = 0; i <
RARRAY_LEN(load_path); i++) {
5952 *filep = copy_path_class(tmp, *filep);
5973 VALUE tmp, load_path;
5978 tmp = file_expand_path_1(path);
5982 path = copy_path_class(tmp, path);
5993 path = copy_path_class(file_expand_path_1(path), path);
6003 for (i = 0; i <
RARRAY_LEN(load_path); i++) {
6024 return copy_path_class(tmp, path);
6028 define_filetest_function(
const char *
name,
VALUE (*func)(
ANYARGS),
int argc)
6034 static const char null_device[] =
6037 #elif defined AMIGA || defined __amigaos__ 6089 define_filetest_function(
"exist?", rb_file_exist_p, 1);
6090 define_filetest_function(
"exists?", rb_file_exists_p, 1);
6091 define_filetest_function(
"readable?", rb_file_readable_p, 1);
6092 define_filetest_function(
"readable_real?", rb_file_readable_real_p, 1);
6093 define_filetest_function(
"world_readable?", rb_file_world_readable_p, 1);
6094 define_filetest_function(
"writable?", rb_file_writable_p, 1);
6095 define_filetest_function(
"writable_real?", rb_file_writable_real_p, 1);
6096 define_filetest_function(
"world_writable?", rb_file_world_writable_p, 1);
6097 define_filetest_function(
"executable?", rb_file_executable_p, 1);
6098 define_filetest_function(
"executable_real?", rb_file_executable_real_p, 1);
6099 define_filetest_function(
"file?", rb_file_file_p, 1);
6100 define_filetest_function(
"zero?", rb_file_zero_p, 1);
6101 define_filetest_function(
"empty?", rb_file_zero_p, 1);
6102 define_filetest_function(
"size?", rb_file_size_p, 1);
6103 define_filetest_function(
"size", rb_file_s_size, 1);
6104 define_filetest_function(
"owned?", rb_file_owned_p, 1);
6105 define_filetest_function(
"grpowned?", rb_file_grpowned_p, 1);
6107 define_filetest_function(
"pipe?", rb_file_pipe_p, 1);
6108 define_filetest_function(
"symlink?", rb_file_symlink_p, 1);
6109 define_filetest_function(
"socket?", rb_file_socket_p, 1);
6111 define_filetest_function(
"blockdev?", rb_file_blockdev_p, 1);
6112 define_filetest_function(
"chardev?", rb_file_chardev_p, 1);
6114 define_filetest_function(
"setuid?", rb_file_suid_p, 1);
6115 define_filetest_function(
"setgid?", rb_file_sgid_p, 1);
6116 define_filetest_function(
"sticky?", rb_file_sticky_p, 1);
6118 define_filetest_function(
"identical?", rb_file_identical_p, 2);
6213 #if defined(O_NDELAY) || defined(O_NONBLOCK) 6215 # define O_NONBLOCK O_NDELAY 6231 #ifndef O_SHARE_DELETE 6232 # define O_SHARE_DELETE 0 RUBY_EXTERN VALUE rb_cString
#define RBASIC_CLEAR_CLASS(obj)
VALUE rb_get_path_check_convert(VALUE obj, VALUE tmp, int level)
#define ENCINDEX_US_ASCII
VALUE rb_get_path(VALUE obj)
#define MBCLEN_CHARFOUND_P(ret)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
#define MBCLEN_CHARFOUND_LEN(ret)
#define rb_enc_mbc_to_codepoint(p, e, enc)
void rb_enc_copy(VALUE obj1, VALUE obj2)
#define RUBY_TYPED_FREE_IMMEDIATELY
size_t strlen(const char *)
void rb_update_max_fd(int fd)
VALUE rb_time_nano_new(time_t, long)
union no_gvl_stat_data::@48 file
int rb_is_absolute_path(const char *path)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
#define skipprefix(path, end, enc)
#define access(path, mode)
#define expand_path(fname, dname, abs_mode, long_name, result)
#define rb_usascii_str_new2
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
void rb_file_const(const char *name, VALUE value)
VALUE rb_fstring_cstr(const char *str)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_str_cat(VALUE, const char *, long)
int rb_find_file_ext(VALUE *filep, const char *const *ext)
VALUE rb_dir_getwd_ospath(void)
#define TypedData_Wrap_Struct(klass, data_type, sval)
#define OBJ_INIT_COPY(obj, orig)
ssize_t readlink(const char *, char *, size_t)
void rb_io_check_initialized(rb_io_t *)
#define TypedData_Get_Struct(obj, type, data_type, sval)
VALUE rb_get_path_check_to_string(VALUE obj, int level)
const struct timespec * tsp
#define ENC_CODERANGE_CLEAR(obj)
SOCKET rb_w32_get_osfhandle(int)
int eaccess(const char *path, int mode)
int lchown(const char *path, int owner, int group)
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
rb_encoding * rb_default_internal_encoding(void)
VALUE rb_str_buf_new2(const char *)
const char * ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc)
int rb_usascii_encindex(void)
VALUE rb_str_plus(VALUE, VALUE)
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
#define FilePathStringValue(v)
void rb_str_set_len(VALUE, long)
#define RBASIC_SET_CLASS(obj, cls)
int rb_enc_str_coderange(VALUE)
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.
#define RSTRING_GETMEM(str, ptrvar, lenvar)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
VALUE rb_io_taint_check(VALUE)
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_readlink(VALUE path, rb_encoding *resultenc)
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
void rb_include_module(VALUE klass, VALUE module)
#define rb_file_birthtime
int rb_str_cmp(VALUE, VALUE)
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
An equivalent to ensure clause.
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
int rb_filesystem_encindex(void)
rb_encoding * rb_utf8_encoding(void)
VALUE rb_str_dup_frozen(VALUE)
VALUE rb_str_tmp_new(long)
VALUE rb_str_buf_append(VALUE, VALUE)
#define GetOpenFile(obj, fp)
int truncate(const char *path, off_t new_size)
#define ENC_CODERANGE_7BIT
const char * rb_obj_classname(VALUE)
struct timespec rb_time_timespec(VALUE time)
#define rb_file_s_readlink
char * rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc)
#define RBASIC_SET_CLASS_RAW(obj, cls)
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class
#define RB_TYPE_P(obj, type)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false
int utimes(const char *filename, const struct timeval times[2])
int rb_enc_to_index(rb_encoding *enc)
unsigned long long uint64_t
VALUE rb_obj_taint(VALUE)
call-seq: obj.taint -> obj
VALUE rb_find_file(VALUE path)
VALUE rb_equal(VALUE, VALUE)
call-seq: obj === other -> true or false
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
VALUE rb_str_new_shared(VALUE)
VALUE rb_str_encode_ospath(VALUE path)
#define rb_file_s_symlink
RUBY_EXTERN VALUE rb_cObject
VALUE rb_home_dir_of(VALUE user, VALUE result)
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_str_buf_cat2(VALUE, const char *)
VALUE rb_file_s_expand_path(int argc, const VALUE *argv)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
int chown(const char *, int, int)
#define OBJ_BUILTIN_TYPE(obj)
void rb_define_const(VALUE, const char *, VALUE)
char * rb_enc_path_next(const char *s, const char *e, rb_encoding *enc)
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
VALUE rb_io_flush_raw(VALUE, int)
#define insecure_obj_p(obj, level)
#define ALLOCV_N(type, v, n)
mode_t umask(mode_t mask)
#define ALLOCA_N(type, n)
#define fpath_check(path)
VALUE rb_enc_associate_index(VALUE obj, int idx)
VALUE rb_find_file_safe(VALUE path, int safe_level)
int link(const char *, const char *)
#define rb_file_s_birthtime
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
VALUE rb_file_absolute_path(VALUE fname, VALUE dname)
VALUE rb_str_resize(VALUE, long)
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
VALUE rb_str_subseq(VALUE, long, long)
#define syserr_fail2_in(func, e, s1, s2)
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
VALUE rb_obj_freeze(VALUE)
call-seq: obj.freeze -> obj
VALUE rb_sprintf(const char *format,...)
int ruby_is_fd_loadable(int fd)
VALUE rb_file_s_absolute_path(int argc, const VALUE *argv)
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
#define NORMALIZE_UTF8PATH
VALUE rb_file_dirname(VALUE fname)
#define WITH_ROOTDIFF(stmt)
void rb_str_modify_expand(VALUE, long)
VALUE rb_class_inherited_p(VALUE mod, VALUE arg)
call-seq: mod <= other -> true, false, or nil
unsigned char buf[MIME_BUF_SIZE]
VALUE rb_assoc_new(VALUE car, VALUE cdr)
VALUE rb_file_directory_p(VALUE obj, VALUE fname)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
int ftruncate(int fd, off_t new_size)
#define EXPAND_PATH_BUFFER()
VALUE rb_check_realpath(VALUE basedir, VALUE path)
#define check_expand_path_args(fname, dname)
VALUE rb_eSystemCallError
char * strchr(char *, char)
#define rb_enc_asciicompat(enc)
VALUE rb_str_ellipsize(VALUE, long)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
VALUE rb_str_new_cstr(const char *)
VALUE rb_stat_new(const struct stat *st)
register unsigned int len
VALUE rb_define_module_under(VALUE outer, const char *name)
#define StringValueCStr(v)
void rb_thread_wait_for(struct timeval)
#define sys_fail2(s1, s2)
#define ENCODING_GET(obj)
rb_encoding * rb_enc_get(VALUE obj)
#define utime_failed(path, tsp, atime, mtime)
void rb_insecure_operation(void)
int utime(const char *filename, const struct utimbuf *times)
#define RARRAY_AREF(a, i)
int rb_path_check(const char *path)
VALUE rb_file_expand_path(VALUE fname, VALUE dname)
struct no_gvl_stat_data no_gvl_stat_data
VALUE rb_hash_aref(VALUE hash, VALUE key)
VALUE rb_str_catf(VALUE str, const char *format,...)
void rb_warning(const char *fmt,...)
#define rb_stat_birthtime
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
VALUE rb_default_home_dir(VALUE result)
size_t rb_str_capacity(VALUE str)
rb_encoding * rb_filesystem_encoding(void)
#define BUFCOPY(srcptr, srclen)
void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt,...)
#define rb_enc_left_char_head(s, p, e, enc)
VALUE rb_str_inspect(VALUE)
VALUE rb_get_expanded_load_path(void)
void rb_enc_warn(rb_encoding *enc, const char *fmt,...)
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)
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
#define istrailinggarbage(x)
char * rb_enc_path_last_separator(const char *path, const char *end, rb_encoding *enc)
RUBY_EXTERN VALUE rb_eIOError
int rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level)
int rb_file_load_ok(const char *path)
RUBY_EXTERN size_t strlcat(char *, const char *, size_t)
VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts)
#define StringValuePtr(v)
#define STRCASECMP(s1, s2)
NORETURN(static void syserr_fail2_in(const char *, int, VALUE, VALUE))
#define RTYPEDDATA_DATA(v)
#define rb_syserr_fail_path(err, path)
#define CONST_ID(var, str)
#define RUBY_TYPED_DEFAULT_FREE
int fchmod(int fd, int mode)
VALUE rb_define_module(const char *name)
VALUE rb_get_path_check(VALUE obj, int level)
int rb_enc_str_asciionly_p(VALUE)
int symlink(const char *src, const char *link)
const char * ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc)
VALUE rb_str_buf_new(long)
VALUE rb_get_path_no_checksafe(VALUE obj)
VALUE rb_check_funcall_default(VALUE, ID, int, const VALUE *, VALUE)
#define rb_file_s_truncate
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_str_append(VALUE, VALUE)
void rb_io_check_closed(rb_io_t *)
char * rb_str_to_cstr(VALUE str)
VALUE rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result)
VALUE rb_file_expand_path_fast(VALUE fname, VALUE dname)
rb_encoding * rb_enc_from_index(int index)
VALUE rb_str_new(const char *, long)