26# include <sys/cygwin.h>
31# if !(defined(__has_feature) && defined(__has_attribute))
36# define API_AVAILABLE(...)
37# define API_DEPRECATED(...)
39# include <CoreFoundation/CFString.h>
56#ifdef HAVE_SYS_PARAM_H
57# include <sys/param.h>
60# define MAXPATHLEN 1024
65#elif defined HAVE_SYS_UTIME_H
66# include <sys/utime.h>
73#ifdef HAVE_SYS_SYSMACROS_H
74# include <sys/sysmacros.h>
80#ifdef HAVE_SYS_MKDEV_H
81# include <sys/mkdev.h>
84#if defined(HAVE_FCNTL_H)
88#if defined(HAVE_SYS_TIME_H)
92#if !defined HAVE_LSTAT && !defined lstat
99# define STAT(p, s) rb_w32_ustati128((p), (s))
101# define lstat(p, s) rb_w32_ulstati128((p), (s))
103# define access(p, m) rb_w32_uaccess((p), (m))
105# define truncate(p, n) rb_w32_utruncate((p), (n))
107# define chmod(p, m) rb_w32_uchmod((p), (m))
109# define chown(p, o, g) rb_w32_uchown((p), (o), (g))
111# define lchown(p, o, g) rb_w32_ulchown((p), (o), (g))
113# define utimensat(s, p, t, f) rb_w32_uutimensat((s), (p), (t), (f))
115# define link(f, t) rb_w32_ulink((f), (t))
117# define unlink(p) rb_w32_uunlink(p)
119# define rename(f, t) rb_w32_urename((f), (t))
121# define symlink(s, l) rb_w32_usymlink((s), (l))
129# define STAT(p, s) stat((p), (s))
132#if defined _WIN32 || defined __APPLE__
134# define TO_OSPATH(str) rb_str_encode_ospath(str)
137# define TO_OSPATH(str) (str)
141#if defined DOSISH || defined __CYGWIN__
146#if defined HAVE_REALPATH && defined __sun && defined __SVR4
161#include "internal/error.h"
228 obj = file_path_convert(obj);
230 check_path_encoding(obj);
255#if 0 && defined _WIN32
270# define NORMALIZE_UTF8PATH 1
272# ifdef HAVE_WORKING_FORK
274rb_CFString_class_initialize_before_fork(
void)
297 const char small_str[] =
"/";
298 long len =
sizeof(small_str) - 1;
300 const CFAllocatorRef alloc = kCFAllocatorDefault;
301 CFStringRef s = CFStringCreateWithBytesNoCopy(alloc,
302 (
const UInt8 *)small_str,
303 len, kCFStringEncodingUTF8,
304 FALSE, kCFAllocatorNull);
305 CFMutableStringRef m = CFStringCreateMutableCopy(alloc,
len, s);
312rb_str_append_normalized_ospath(
VALUE str,
const char *
ptr,
long len)
316 CFStringRef s = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
318 kCFStringEncodingUTF8,
FALSE,
320 CFMutableStringRef m = CFStringCreateMutableCopy(kCFAllocatorDefault,
len, s);
323 CFStringNormalize(m, kCFStringNormalizationFormC);
324 all = CFRangeMake(0, CFStringGetLength(m));
325 CFStringGetBytes(m, all, kCFStringEncodingUTF8,
'?',
FALSE,
NULL, 0, &buflen);
327 CFStringGetBytes(m, all, kCFStringEncodingUTF8,
'?',
FALSE,
336rb_str_normalize_ospath(
const char *
ptr,
long len)
339 const char *e =
ptr +
len;
350 static const char invalid[3] =
"\xEF\xBF\xBD";
351 rb_str_append_normalized_ospath(
str, p1, p-p1);
359 if ((0x2000 <= c && c <= 0x2FFF) || (0xF900 <= c && c <= 0xFAFF) ||
360 (0x2F800 <= c && c <= 0x2FAFF)) {
362 rb_str_append_normalized_ospath(
str, p1, p-p1);
373 rb_str_append_normalized_ospath(
str, p1, p-p1);
380ignored_char_p(
const char *p,
const char *e,
rb_encoding *enc)
383 if (p+3 > e)
return 0;
384 switch ((
unsigned char)*p) {
386 switch ((
unsigned char)p[1]) {
388 c = (
unsigned char)p[2];
390 if (c >= 0x8c && c <= 0x8f)
return 3;
392 if (c >= 0xaa && c <= 0xae)
return 3;
395 c = (
unsigned char)p[2];
397 if (c >= 0xaa && c <= 0xaf)
return 3;
403 if ((
unsigned char)p[1] == 0xbb &&
404 (
unsigned char)p[2] == 0xbf)
411# define NORMALIZE_UTF8PATH 0
414#define apply2args(n) (rb_check_arity(argc, n, UNLIMITED_ARGUMENTS), argc-=n)
431no_gvl_apply2files(
void *
ptr)
435 for (aa->
i = 0; aa->
i < aa->
argc; aa->
i++) {
446static int utime_internal(
const char *,
void *);
462 for (aa->
i = 0; aa->
i <
argc; aa->
i++) {
473 if (
func == utime_internal) {
506rb_file_path(
VALUE obj)
521stat_memsize(
const void *p)
523 return sizeof(
struct stat);
533stat_new_0(
VALUE klass,
const struct stat *st)
535 struct stat *nst = 0;
582 struct timespec ts1 = stat_mtimespec(get_stat(self));
583 struct timespec ts2 = stat_mtimespec(get_stat(other));
595#define ST2UINT(val) ((val) & ~(~1UL << (sizeof(val) * CHAR_BIT - 1)))
598# define NUM2DEVT(v) NUM2UINT(v)
601# define DEVT2NUM(v) UINT2NUM(v)
603#ifndef PRI_DEVT_PREFIX
604# define PRI_DEVT_PREFIX ""
618rb_stat_dev(
VALUE self)
620 return DEVT2NUM(get_stat(self)->st_dev);
635rb_stat_dev_major(
VALUE self)
638 return UINT2NUM(major(get_stat(self)->st_dev));
656rb_stat_dev_minor(
VALUE self)
659 return UINT2NUM(minor(get_stat(self)->st_dev));
676rb_stat_ino(
VALUE self)
678#ifdef HAVE_STRUCT_STAT_ST_INOHIGH
684#elif SIZEOF_STRUCT_STAT_ST_INO > SIZEOF_LONG
685 return ULL2NUM(get_stat(self)->st_ino);
687 return ULONG2NUM(get_stat(self)->st_ino);
705rb_stat_mode(
VALUE self)
723rb_stat_nlink(
VALUE self)
726 const struct stat *
ptr = get_stat(self);
728 if (
sizeof(
ptr->st_nlink) <=
sizeof(
int)) {
731 else if (
sizeof(
ptr->st_nlink) ==
sizeof(
long)) {
734 else if (
sizeof(
ptr->st_nlink) ==
sizeof(LONG_LONG)) {
735 return ULL2NUM((
unsigned LONG_LONG)
ptr->st_nlink);
738 rb_bug(
":FIXME: don't know what to do");
753rb_stat_uid(
VALUE self)
755 return UIDT2NUM(get_stat(self)->st_uid);
769rb_stat_gid(
VALUE self)
771 return GIDT2NUM(get_stat(self)->st_gid);
787rb_stat_rdev(
VALUE self)
789#ifdef HAVE_STRUCT_STAT_ST_RDEV
790 return DEVT2NUM(get_stat(self)->st_rdev);
808rb_stat_rdev_major(
VALUE self)
810#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(major)
811 return UINT2NUM(major(get_stat(self)->st_rdev));
829rb_stat_rdev_minor(
VALUE self)
831#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(minor)
832 return UINT2NUM(minor(get_stat(self)->st_rdev));
848rb_stat_size(
VALUE self)
850 return OFFT2NUM(get_stat(self)->st_size);
865rb_stat_blksize(
VALUE self)
867#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
868 return ULONG2NUM(get_stat(self)->st_blksize);
886rb_stat_blocks(
VALUE self)
888#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
889# if SIZEOF_STRUCT_STAT_ST_BLOCKS > SIZEOF_LONG
890 return ULL2NUM(get_stat(self)->st_blocks);
892 return ULONG2NUM(get_stat(self)->st_blocks);
904#if defined(HAVE_STRUCT_STAT_ST_ATIM)
905 ts.tv_nsec = st->st_atim.tv_nsec;
906#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
907 ts.tv_nsec = st->st_atimespec.tv_nsec;
908#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
909 ts.tv_nsec = (
long)st->st_atimensec;
917stat_atime(
const struct stat *st)
919 struct timespec ts = stat_atimespec(st);
928#if defined(HAVE_STRUCT_STAT_ST_MTIM)
929 ts.tv_nsec = st->st_mtim.tv_nsec;
930#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
931 ts.tv_nsec = st->st_mtimespec.tv_nsec;
932#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
933 ts.tv_nsec = (
long)st->st_mtimensec;
941stat_mtime(
const struct stat *st)
943 struct timespec ts = stat_mtimespec(st);
952#if defined(HAVE_STRUCT_STAT_ST_CTIM)
953 ts.tv_nsec = st->st_ctim.tv_nsec;
954#elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
955 ts.tv_nsec = st->st_ctimespec.tv_nsec;
956#elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
957 ts.tv_nsec = (
long)st->st_ctimensec;
965stat_ctime(
const struct stat *st)
967 struct timespec ts = stat_ctimespec(st);
971#define HAVE_STAT_BIRTHTIME
972#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
973typedef struct stat statx_data;
975stat_birthtime(
const struct stat *st)
977 const struct timespec *ts = &st->st_birthtimespec;
981typedef struct stat statx_data;
982# define stat_birthtime stat_ctime
984# undef HAVE_STAT_BIRTHTIME
999rb_stat_atime(
VALUE self)
1001 return stat_atime(get_stat(self));
1015rb_stat_mtime(
VALUE self)
1017 return stat_mtime(get_stat(self));
1035rb_stat_ctime(
VALUE self)
1037 return stat_ctime(get_stat(self));
1040#if defined(HAVE_STAT_BIRTHTIME)
1066 return stat_birthtime(get_stat(self));
1069# define rb_stat_birthtime rb_f_notimplement
1088rb_stat_inspect(
VALUE self)
1092 static const struct {
1096 {
"dev", rb_stat_dev},
1097 {
"ino", rb_stat_ino},
1098 {
"mode", rb_stat_mode},
1099 {
"nlink", rb_stat_nlink},
1100 {
"uid", rb_stat_uid},
1101 {
"gid", rb_stat_gid},
1102 {
"rdev", rb_stat_rdev},
1103 {
"size", rb_stat_size},
1104 {
"blksize", rb_stat_blksize},
1105 {
"blocks", rb_stat_blocks},
1106 {
"atime", rb_stat_atime},
1107 {
"mtime", rb_stat_mtime},
1108 {
"ctime", rb_stat_ctime},
1109#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
1124 for (i = 0; i <
sizeof(member)/
sizeof(member[0]); i++) {
1132 v = (*member[i].func)(self);
1136 else if (i == 0 || i == 6) {
1157no_gvl_fstat(
void *data)
1164fstat_without_gvl(
int fd,
struct stat *st)
1175no_gvl_stat(
void * data)
1182stat_without_gvl(
const char *path,
struct stat *st)
1193#if !defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) && \
1194 defined(HAVE_STRUCT_STATX_STX_BTIME)
1197# ifdef HAVE_SYSCALL_H
1198# include <syscall.h>
1199# elif defined HAVE_SYS_SYSCALL_H
1200# include <sys/syscall.h>
1202# if defined __linux__
1203# include <linux/stat.h>
1205statx(
int dirfd,
const char *pathname,
int flags,
1206 unsigned int mask,
struct statx *statxbuf)
1208 return (
int)syscall(__NR_statx, dirfd, pathname, flags,
mask, statxbuf);
1213typedef struct no_gvl_statx_data {
1222io_blocking_statx(
void *data)
1224 no_gvl_statx_data *arg = data;
1225 return (
VALUE)statx(arg->fd, arg->path, arg->flags, arg->mask, arg->stx);
1229no_gvl_statx(
void *data)
1231 return (
void *)io_blocking_statx(data);
1235statx_without_gvl(
const char *path,
struct statx *stx,
unsigned int mask)
1237 no_gvl_statx_data data = {stx,
AT_FDCWD, path, 0,
mask};
1245fstatx_without_gvl(
int fd,
struct statx *stx,
unsigned int mask)
1247 no_gvl_statx_data data = {stx, fd,
"", AT_EMPTY_PATH,
mask};
1263 result = fstatx_without_gvl(fptr->
fd, stx,
mask);
1275# define statx_has_birthtime(st) ((st)->stx_mask & STATX_BTIME)
1277NORETURN(
static void statx_notimplement(
const char *field_name));
1282statx_notimplement(
const char *field_name)
1285 "%s is unimplemented on this filesystem",
1290statx_birthtime(
const struct statx *stx,
VALUE fname)
1294 statx_notimplement(
"birthtime");
1296 return rb_time_nano_new((time_t)stx->stx_btime.tv_sec, stx->stx_btime.tv_nsec);
1299typedef struct statx statx_data;
1300# define HAVE_STAT_BIRTHTIME
1302#elif defined(HAVE_STAT_BIRTHTIME)
1303# define statx_without_gvl(path, st, mask) stat_without_gvl(path, st)
1304# define fstatx_without_gvl(fd, st, mask) fstat_without_gvl(fd, st)
1305# define statx_birthtime(st, fname) stat_birthtime(st)
1306# define statx_has_birthtime(st) 1
1307# define rb_statx(file, st, mask) rb_stat(file, st)
1309# define statx_has_birthtime(st) 0
1323 result = fstat_without_gvl(fptr->
fd, st);
1352 if (stat_without_gvl(
RSTRING_PTR(fname), &st) < 0) {
1374rb_io_stat(
VALUE obj)
1380 if (
fstat(fptr->
fd, &st) == -1) {
1388no_gvl_lstat(
void *
ptr)
1395lstat_without_gvl(
const char *path,
struct stat *st)
1434 return rb_file_s_stat(klass, fname);
1453rb_file_lstat(
VALUE obj)
1463 if (lstat_without_gvl(
RSTRING_PTR(path), &st) == -1) {
1468 return rb_io_stat(obj);
1473rb_group_member(GETGROUPS_T gid)
1475#if defined(_WIN32) || !defined(HAVE_GETGROUPS)
1493 gary =
ALLOCV_N(GETGROUPS_T, v, groups);
1494 anum = getgroups(groups, gary);
1495 if (anum != -1 && anum != groups)
1506 while (--anum >= 0) {
1507 if (gary[anum] == gid) {
1520# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
1523#if defined(S_IXGRP) && !defined(_WIN32) && !defined(__CYGWIN__)
1524#define USE_GETEUID 1
1541 if (
STAT(path, &st) < 0)
1557 if (st.st_uid == euid)
1559 else if (rb_group_member(st.st_gid))
1562 if ((
int)(st.st_mode &
mode) ==
mode)
return 0;
1577nogvl_eaccess(
void *
ptr)
1599nogvl_access(
void *
ptr)
1649# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
1654 if (rb_stat(fname, &st) < 0)
return Qfalse;
1673# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
1678 if (rb_stat(fname, &st) < 0)
return Qfalse;
1679 if (S_ISFIFO(st.st_mode))
return Qtrue;
1697# define S_ISLNK(m) _S_ISLNK(m)
1700# define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
1703# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
1735# define S_ISSOCK(m) _S_ISSOCK(m)
1738# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
1741# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
1750 if (rb_stat(fname, &st) < 0)
return Qfalse;
1751 if (S_ISSOCK(st.st_mode))
return Qtrue;
1771# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
1773# define S_ISBLK(m) (0)
1780 if (rb_stat(fname, &st) < 0)
return Qfalse;
1799# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
1804 if (rb_stat(fname, &st) < 0)
return Qfalse;
1826 if (rb_stat(fname, &st) < 0)
return Qfalse;
1834 const char *s =
"FileTest#exist?";
1836 s =
"FileTest.exist?";
1844 return rb_file_exist_p(obj, fname);
1861 if (rb_eaccess(fname,
R_OK) < 0)
return Qfalse;
1877rb_file_readable_real_p(
VALUE obj,
VALUE fname)
1879 if (rb_access(fname,
R_OK) < 0)
return Qfalse;
1884# define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
1888# define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
1908rb_file_world_readable_p(
VALUE obj,
VALUE fname)
1913 if (rb_stat(fname, &st) < 0)
return Qnil;
1935 if (rb_eaccess(fname,
W_OK) < 0)
return Qfalse;
1951rb_file_writable_real_p(
VALUE obj,
VALUE fname)
1953 if (rb_access(fname,
W_OK) < 0)
return Qfalse;
1974rb_file_world_writable_p(
VALUE obj,
VALUE fname)
1979 if (rb_stat(fname, &st) < 0)
return Qnil;
2005 if (rb_eaccess(fname,
X_OK) < 0)
return Qfalse;
2025rb_file_executable_real_p(
VALUE obj,
VALUE fname)
2027 if (rb_access(fname,
X_OK) < 0)
return Qfalse;
2032# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
2052 if (rb_stat(fname, &st) < 0)
return Qfalse;
2072 if (rb_stat(fname, &st) < 0)
return Qfalse;
2073 if (st.st_size == 0)
return Qtrue;
2092 if (rb_stat(fname, &st) < 0)
return Qnil;
2093 if (st.st_size == 0)
return Qnil;
2113 if (rb_stat(fname, &st) < 0)
return Qfalse;
2123 if (rb_stat(fname, &st) < 0)
return Qfalse;
2145 if (rb_stat(fname, &st) < 0)
return Qfalse;
2146 if (rb_group_member(st.st_gid))
return Qtrue;
2151#if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
2157 if (rb_stat(fname, &st) < 0)
return Qfalse;
2176 return check3rdbyte(fname, S_ISUID);
2195 return check3rdbyte(fname, S_ISGID);
2214 return check3rdbyte(fname, S_ISVTX);
2243 struct stat st1, st2;
2245 if (rb_stat(fname1, &st1) < 0)
return Qfalse;
2246 if (rb_stat(fname2, &st2) < 0)
return Qfalse;
2247 if (st1.st_dev != st2.st_dev)
return Qfalse;
2248 if (st1.st_ino != st2.st_ino)
return Qfalse;
2270 if (rb_stat(fname, &st) < 0) {
2279rb_file_ftype(
const struct stat *st)
2286 else if (
S_ISDIR(st->st_mode)) {
2289 else if (
S_ISCHR(st->st_mode)) {
2290 t =
"characterSpecial";
2293 else if (
S_ISBLK(st->st_mode)) {
2298 else if (S_ISFIFO(st->st_mode)) {
2303 else if (
S_ISLNK(st->st_mode)) {
2308 else if (S_ISSOCK(st->st_mode)) {
2345 return rb_file_ftype(&st);
2365 if (rb_stat(fname, &st) < 0) {
2370 return stat_atime(&st);
2385rb_file_atime(
VALUE obj)
2391 if (
fstat(fptr->
fd, &st) == -1) {
2394 return stat_atime(&st);
2414 if (rb_stat(fname, &st) < 0) {
2419 return stat_mtime(&st);
2433rb_file_mtime(
VALUE obj)
2439 if (
fstat(fptr->
fd, &st) == -1) {
2442 return stat_mtime(&st);
2466 if (rb_stat(fname, &st) < 0) {
2471 return stat_ctime(&st);
2488rb_file_ctime(
VALUE obj)
2494 if (
fstat(fptr->
fd, &st) == -1) {
2497 return stat_ctime(&st);
2514#if defined(HAVE_STAT_BIRTHTIME)
2515RUBY_FUNC_EXPORTED
VALUE
2520 if (rb_statx(fname, &st, STATX_BTIME) < 0) {
2525 return statx_birthtime(&st, fname);
2528# define rb_file_s_birthtime rb_f_notimplement
2531#if defined(HAVE_STAT_BIRTHTIME)
2551 if (fstatx_without_gvl(fptr->
fd, &st, STATX_BTIME) == -1) {
2554 return statx_birthtime(&st, fptr->
pathv);
2557# define rb_file_birthtime rb_f_notimplement
2571rb_file_size(
VALUE obj)
2580 if (
fstat(fptr->
fd, &st) == -1) {
2587chmod_internal(
const char *path,
void *
mode)
2634#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
2650#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
2660#if defined(HAVE_LCHMOD)
2662lchmod_internal(
const char *path,
void *
mode)
2685 return apply2files(lchmod_internal,
argc,
argv, &
mode);
2688#define rb_file_s_lchmod rb_f_notimplement
2691static inline rb_uid_t
2695 return (rb_uid_t)-1;
2700static inline rb_gid_t
2704 return (rb_gid_t)-1;
2715chown_internal(
const char *path,
void *arg)
2742 arg.owner = to_uid(*
argv++);
2743 arg.group = to_gid(*
argv++);
2745 return apply2files(chown_internal,
argc,
argv, &arg);
2782 if (fchown(fptr->
fd, o,
g) == -1)
2789#if defined(HAVE_LCHOWN)
2791lchown_internal(
const char *path,
void *arg)
2814 arg.owner = to_uid(*
argv++);
2815 arg.group = to_gid(*
argv++);
2817 return apply2files(lchown_internal,
argc,
argv, &arg);
2820#define rb_file_s_lchown rb_f_notimplement
2839 if (ua->
tsp && e == EINVAL) {
2851 if (
NIL_P(a)) e[0] = m;
2871#if defined(HAVE_UTIMES)
2874utime_internal(
const char *path,
void *arg)
2880#if defined(HAVE_UTIMENSAT)
2881 static int try_utimensat = 1;
2882# ifdef AT_SYMLINK_NOFOLLOW
2883 static int try_utimensat_follow = 1;
2885 const int try_utimensat_follow = 0;
2889 if (v->
follow ? try_utimensat_follow : try_utimensat) {
2890# ifdef AT_SYMLINK_NOFOLLOW
2892 flags = AT_SYMLINK_NOFOLLOW;
2896 if (utimensat(
AT_FDCWD, path, tsp, flags) < 0) {
2897 if (errno == ENOSYS) {
2898# ifdef AT_SYMLINK_NOFOLLOW
2899 try_utimensat_follow = 0;
2913 tvbuf[0].tv_sec = tsp[0].
tv_sec;
2914 tvbuf[0].tv_usec = (
int)(tsp[0].tv_nsec / 1000);
2915 tvbuf[1].tv_sec = tsp[1].
tv_sec;
2916 tvbuf[1].tv_usec = (
int)(tsp[1].tv_nsec / 1000);
2920 if (v->
follow)
return lutimes(path, tvp);
2922 return utimes(path, tvp);
2927#if !defined HAVE_UTIME_H && !defined HAVE_SYS_UTIME_H
2935utime_internal(
const char *path,
void *arg)
2945 return utime(path, utp);
2957 args.atime = *
argv++;
2958 args.mtime = *
argv++;
2960 args.follow = follow;
2962 if (!
NIL_P(args.atime) || !
NIL_P(args.mtime)) {
2965 if (args.atime == args.mtime)
2972 return apply2files(utime_internal,
argc,
argv, &args);
2992#if defined(HAVE_UTIMES) && (defined(HAVE_LUTIMES) || (defined(HAVE_UTIMENSAT) && defined(AT_SYMLINK_NOFOLLOW)))
3011#define rb_file_s_lutime rb_f_notimplement
3014#ifdef RUBY_FUNCTION_NAME_STRING
3015# define syserr_fail2(e, s1, s2) syserr_fail2_in(RUBY_FUNCTION_NAME_STRING, e, s1, s2)
3017# define syserr_fail2_in(func, e, s1, s2) syserr_fail2(e, s1, s2)
3019#define sys_fail2(s1, s2) syserr_fail2(errno, s1, s2)
3026 const int max_pathlen = MAX_PATH;
3039#ifdef RUBY_FUNCTION_NAME_STRING
3040 rb_syserr_fail_path_in(func, e,
str);
3073#define rb_file_s_link rb_f_notimplement
3103#define rb_file_s_symlink rb_f_notimplement
3125struct readlink_arg {
3132nogvl_readlink(
void *
ptr)
3134 struct readlink_arg *ra =
ptr;
3136 return (
void *)(
VALUE)
readlink(ra->path, ra->buf, ra->size);
3142 struct readlink_arg ra;
3162 while ((rv = readlink_without_gvl(path, v,
size)) ==
size
3164 || (rv < 0 && errno == ERANGE)
3182#define rb_file_s_readlink rb_f_notimplement
3186unlink_internal(
const char *path,
void *arg)
3188 return unlink(path);
3210 return apply2files(unlink_internal,
argc,
argv, 0);
3219no_gvl_rename(
void *
ptr)
3248#if defined __CYGWIN__
3257 if (chmod(ra.dst, 0666) == 0 &&
3258 unlink(ra.dst) == 0 &&
3259 rename(ra.src, ra.dst) == 0)
3263 syserr_fail2(e, from, to);
3306#if defined __CYGWIN__ || defined DOSISH
3308#define DOSISH_DRIVE_LETTER
3309#define FILE_ALT_SEPARATOR '\\'
3311#ifdef FILE_ALT_SEPARATOR
3312#define isdirsep(x) ((x) == '/' || (x) == FILE_ALT_SEPARATOR)
3314static const char file_alt_separator[] = {FILE_ALT_SEPARATOR,
'\0'};
3317#define isdirsep(x) ((x) == '/')
3329# define USE_NTFS_ADS 1
3331# define USE_NTFS_ADS 0
3336#define istrailinggarbage(x) ((x) == '.' || (x) == ' ')
3338#define istrailinggarbage(x) 0
3341# define isADS(x) ((x) == ':')
3346#define Next(p, e, enc) ((p) + rb_enc_mbclen((p), (e), (enc)))
3347#define Inc(p, e, enc) ((p) = Next((p), (e), (enc)))
3349#if defined(DOSISH_UNC)
3350#define has_unc(buf) (isdirsep((buf)[0]) && isdirsep((buf)[1]))
3352#define has_unc(buf) 0
3355#ifdef DOSISH_DRIVE_LETTER
3357has_drive_letter(
const char *
buf)
3372 char *drvcwd, *oldcwd;
3383 if (chdir(drive) == 0) {
3397not_same_drive(
VALUE path,
int drive)
3401 if (has_drive_letter(p)) {
3411skiproot(
const char *path,
const char *end,
rb_encoding *enc)
3413#ifdef DOSISH_DRIVE_LETTER
3414 if (path + 2 <= end && has_drive_letter(path)) path += 2;
3416 while (path < end &&
isdirsep(*path)) path++;
3417 return (
char *)path;
3420#define nextdirsep rb_enc_path_next
3430#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
3431#define skipprefix rb_enc_path_skip_prefix
3433#define skipprefix(path, end, enc) (path)
3438#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
3442 while (path < end &&
isdirsep(*path)) path++;
3445 return (
char *)path;
3448#ifdef DOSISH_DRIVE_LETTER
3449 if (has_drive_letter(path))
3450 return (
char *)(path + 2);
3453 return (
char *)path;
3457skipprefixroot(
const char *path,
const char *end,
rb_encoding *enc)
3459#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
3464 return skiproot(path, end, enc);
3468#define strrdirsep rb_enc_path_last_separator
3473 while (path < end) {
3475 const char *tmp = path++;
3476 while (path < end &&
isdirsep(*path)) path++;
3477 if (path >= end)
break;
3481 Inc(path, end, enc);
3488chompdirsep(
const char *path,
const char *end,
rb_encoding *enc)
3490 while (path < end) {
3492 const char *
last = path++;
3493 while (path < end &&
isdirsep(*path)) path++;
3494 if (path >= end)
return (
char *)
last;
3497 Inc(path, end, enc);
3500 return (
char *)path;
3506 if (path < end &&
isdirsep(*path)) path++;
3507 return chompdirsep(path, end, enc);
3512ntfs_tail(
const char *path,
const char *end,
rb_encoding *enc)
3514 while (path < end && *path ==
'.') path++;
3515 while (path < end && !
isADS(*path)) {
3517 const char *
last = path++;
3519 if (path >= end ||
isADS(*path))
return (
char *)
last;
3522 const char *
last = path++;
3523 while (path < end &&
isdirsep(*path)) path++;
3524 if (path >= end)
return (
char *)
last;
3525 if (
isADS(*path)) path++;
3528 Inc(path, end, enc);
3531 return (
char *)path;
3535#define BUFCHECK(cond) do {\
3538 do {buflen *= 2;} while (cond);\
3539 rb_str_resize(result, buflen);\
3540 buf = RSTRING_PTR(result);\
3542 pend = buf + buflen;\
3547 p = buf = RSTRING_PTR(result),\
3548 buflen = RSTRING_LEN(result),\
3552# define SKIPPATHSEP(p) ((*(p)) ? 1 : 0)
3554# define SKIPPATHSEP(p) 1
3557#define BUFCOPY(srcptr, srclen) do { \
3558 const int skip = SKIPPATHSEP(p); \
3559 rb_str_set_len(result, p-buf+skip); \
3560 BUFCHECK(bdiff + ((srclen)+skip) >= buflen); \
3562 memcpy(p, (srcptr), (srclen)); \
3566#define WITH_ROOTDIFF(stmt) do { \
3567 long rootdiff = root - buf; \
3569 root = buf + rootdiff; \
3573copy_home_path(
VALUE result,
const char *dir)
3576#if defined DOSISH || defined __CYGWIN__
3588#if defined DOSISH || defined __CYGWIN__
3590 for (bend = (p =
buf) + dirlen; p < bend;
Inc(p, bend, enc)) {
3603 struct passwd *pwPtr;
3606 const char *pwPtr = 0;
3607 # define endpwent() ((void)0)
3621 pwPtr = getpwnam(username);
3624 dir = pwPtr =
getenv(
"HOME");
3631 dir = pwPtr->pw_dir;
3633 copy_home_path(result, dir);
3642 const char *dir =
getenv(
"HOME");
3644#if defined HAVE_PWD_H
3658 VALUE login_name = rb_getlogin();
3660# if !defined(HAVE_GETPWUID_R) && !defined(HAVE_GETPWUID)
3665 if (
NIL_P(login_name)) {
3670 VALUE pw_dir = rb_getpwdirnam_for_login(login_name);
3671 if (
NIL_P(pw_dir)) {
3672 pw_dir = rb_getpwdiruid();
3673 if (
NIL_P(pw_dir)) {
3687 return copy_home_path(result, dir);
3693#if NORMALIZE_UTF8PATH
3705 char *
buf, *cwdp = dir;
3711 if (direnc != fsenc) {
3720 do {buflen *= 2;}
while (dirlen > buflen);
3727 return buf + dirlen;
3733 const char *s, *b, *fend;
3735 size_t buflen, bdiff;
3743 if (s[0] ==
'~' && abs_mode == 0) {
3745 if (
isdirsep(s[1]) || s[1] ==
'\0') {
3756 BUFCHECK(bdiff + userlen >= buflen);
3768 (
int)userlen, b, fname);
3777#ifdef DOSISH_DRIVE_LETTER
3779 else if (has_drive_letter(s)) {
3792 if (!
NIL_P(dname) && !not_same_drive(dname, s[0])) {
3801 char *e = append_fspath(result, fname, getcwdofdrv(*s), &enc, fsenc);
3809 p = chompdirsep(skiproot(
buf, p, enc), p, enc);
3815 if (!
NIL_P(dname)) {
3822 char *e = append_fspath(result, fname,
ruby_getcwd(), &enc, fsenc);
3826#if defined DOSISH || defined __CYGWIN__
3834 p = chompdirsep(skiproot(
buf, p, enc), p, enc);
3847 if (p >
buf && p[-1] ==
'/')
3870 if (*(s+1) ==
'\0' ||
isdirsep(*(s+1))) {
3889#if defined DOSISH || defined __CYGWIN__
3914#if defined DOSISH || defined __CYGWIN__
3926 int n = ignored_char_p(s, fend, enc);
3945 static const char prime[] =
":$DATA";
3946 enum {prime_len =
sizeof(prime) -1};
3950 if (s > b + prime_len &&
strncasecmp(s - prime_len, prime, prime_len) == 0) {
3953 if (
isADS(*(s - (prime_len+1)))) {
3956 else if (memchr(b,
':', s - prime_len - b)) {
3965 if (p == skiproot(
buf, p + !!*p, enc) - 1) p++;
3969 if ((s =
strrdirsep(b =
buf, p, enc)) != 0 && !strpbrk(s,
"*?")) {
3974 WIN32_FIND_DATAW wfd;
3977#ifdef HAVE_CYGWIN_CONV_PATH
3978 char *w32buf =
NULL;
3979 const int flags = CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
3985 int lnk_added = 0, is_symlink = 0;
3989 if (lstat_without_gvl(
buf, &st) == 0 &&
S_ISLNK(st.st_mode)) {
3996#ifdef HAVE_CYGWIN_CONV_PATH
3997 bufsize = cygwin_conv_path(flags, path,
NULL, 0);
4000 if (lnk_added) bufsize += 4;
4002 if (cygwin_conv_path(flags, path, w32buf, bufsize) == 0) {
4008 if (cygwin_conv_to_win32_path(path, w32buf) == 0) {
4012 if (is_symlink && b == w32buf) {
4016 strlcat(w32buf,
".lnk", bufsize);
4032 MultiByteToWideChar(CP_UTF8, 0,
RSTRING_PTR(tmp), -1, wstr,
len);
4034 h = FindFirstFileW(wstr, &wfd);
4039 len = lstrlenW(wfd.cFileName);
4041 if (lnk_added &&
len > 4 &&
4042 wcscasecmp(wfd.cFileName +
len - 4,
L".lnk") == 0) {
4043 wfd.cFileName[
len -= 4] =
L'\0';
4050 len = WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen,
NULL, 0,
NULL,
NULL);
4051 if (tmp == result) {
4053 WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, p,
len + 1,
NULL,
NULL);
4080#define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, MAXPATHLEN + 2)
4089#define expand_path(fname, dname, abs_mode, long_name, result) \
4090 str_shrink(rb_file_expand_path_internal(fname, dname, abs_mode, long_name, result))
4092#define check_expand_path_args(fname, dname) \
4093 (((fname) = rb_get_path(fname)), \
4094 (void)(NIL_P(dname) ? (dname) : ((dname) = rb_get_path(dname))))
4097file_expand_path_1(
VALUE fname)
4216realpath_rec(
long *prefixlenp,
VALUE *resolvedp,
const char *unresolved,
VALUE fallback,
4219 const char *pend = unresolved +
strlen(unresolved);
4223 while (unresolved < pend) {
4224 const char *testname = unresolved;
4226 long testnamelen = unresolved_firstsep - unresolved;
4227 const char *unresolved_nextname = unresolved_firstsep;
4228 while (unresolved_nextname < pend &&
isdirsep(*unresolved_nextname))
4229 unresolved_nextname++;
4230 unresolved = unresolved_nextname;
4231 if (testnamelen == 1 && testname[0] ==
'.') {
4233 else if (testnamelen == 2 && testname[0] ==
'.' && testname[1] ==
'.') {
4235 const char *resolved_str =
RSTRING_PTR(*resolvedp);
4236 const char *resolved_names = resolved_str + *prefixlenp;
4238 long len = lastsep ? lastsep - resolved_names : 0;
4247#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
4248 if (*prefixlenp > 1 && *prefixlenp ==
RSTRING_LEN(testpath)) {
4256 if (!
NIL_P(checkval)) {
4257 if (checkval ==
ID2SYM(resolving)) {
4271 ret = lstat_without_gvl(
RSTRING_PTR(testpath), &sbuf);
4274 if (e == ENOENT && !
NIL_P(fallback)) {
4275 if (stat_without_gvl(
RSTRING_PTR(fallback), &sbuf) == 0) {
4284 *resolvedp = testpath;
4295 const char *link_prefix, *link_names;
4296 long link_prefixlen;
4301 link_prefixlen = link_names - link_prefix;
4302 if (link_prefixlen > 0) {
4309 *prefixlenp = link_prefixlen;
4311 if (realpath_rec(prefixlenp, resolvedp, link_names, testpath,
4312 loopcheck,
mode, !*unresolved_firstsep))
4322 *resolvedp = testpath;
4335 VALUE unresolved_path;
4340 char *path_names =
NULL, *basedir_names =
NULL, *curdir_names =
NULL;
4341 char *
ptr, *prefixptr =
NULL, *pend;
4346 if (!
NIL_P(basedir)) {
4352 unresolved_path =
TO_OSPATH(unresolved_path);
4355 if (
ptr != path_names) {
4360 if (!
NIL_P(basedir)) {
4363 if (
ptr != basedir_names) {
4376 pend = prefixptr + prefixlen;
4377 ptr = chompdirsep(prefixptr, pend, enc);
4379 prefixlen = ++
ptr - prefixptr;
4382#ifdef FILE_ALT_SEPARATOR
4383 while (prefixptr <
ptr) {
4384 if (*prefixptr == FILE_ALT_SEPARATOR) {
4387 Inc(prefixptr, pend, enc);
4399 if (realpath_rec(&prefixlen, &resolved, curdir_names,
Qnil, loopcheck,
mode, 0))
4402 if (basedir_names) {
4403 if (realpath_rec(&prefixlen, &resolved, basedir_names,
Qnil, loopcheck,
mode, 0))
4406 if (realpath_rec(&prefixlen, &resolved, path_names,
Qnil, loopcheck,
mode, 1))
4409 if (origenc && origenc !=
rb_enc_get(resolved)) {
4429 VALUE unresolved_path;
4430 char *resolved_ptr =
NULL;
4434 return rb_check_realpath_emulate(basedir, path, origenc,
mode);
4439 unresolved_path = rb_file_join(
rb_assoc_new(basedir, unresolved_path));
4441 if (origenc) unresolved_path =
TO_OSPATH(unresolved_path);
4449 if (errno == ENOTDIR ||
4450 (errno == ENOENT && rb_file_exist_p(0, unresolved_path))) {
4451 return rb_check_realpath_emulate(basedir, path, origenc,
mode);
4462# if !defined(__LINUX__) && !defined(__APPLE__)
4466 if (stat_without_gvl(
RSTRING_PTR(resolved), &st) < 0) {
4474 if (origenc && origenc !=
rb_enc_get(resolved)) {
4491 return rb_check_realpath_emulate(basedir, path, origenc,
mode);
4500 return rb_check_realpath_internal(basedir, path,
rb_enc_get(path),
mode);
4553rmext(
const char *p,
long l0,
long l1,
const char *e,
long l2,
rb_encoding *enc)
4557 const char *s, *
last;
4559 if (!e || !l2)
return 0;
4562 if (
rb_enc_ascget(e + len1, e + l2, &len2, enc) ==
'*' && len1 + len2 == l2) {
4563 if (c ==
'.')
return l0;
4573 if (l1 < l2)
return l1;
4577#if CASEFOLD_FILESYSTEM
4578#define fncomp strncasecmp
4580#define fncomp strncmp
4582 if (
fncomp(s, e, l2) == 0) {
4591 const char *p, *q, *e, *end;
4592#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
4599#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
4607#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
4611#ifdef DOSISH_DRIVE_LETTER
4612 else if (*p ==
':') {
4632 n = ntfs_tail(p, end, enc) - p;
4634 n = chompdirsep(p, end, enc) - p;
4636 for (q = p; q - p < n && *q ==
'.'; q++);
4637 for (e = 0; q - p < n;
Inc(q, end, enc)) {
4638 if (*q ==
'.') e = q;
4671 VALUE fname, fext, basename;
4672 const char *
name, *p;
4680 enc = check_path_encoding(fext);
4756#ifdef DOSISH_DRIVE_LETTER
4758 const char *
top = skiproot(
name + 2, end, enc);
4765#ifdef DOSISH_DRIVE_LETTER
4797 while (*p && *p ==
'.') p++;
4801 const char *
last = p++, *dot =
last;
4803 if (*p ==
'.') dot = p;
4806 if (!*p ||
isADS(*p)) {
4810 if (*
last ==
'.' || dot >
last) e = dot;
4817 else if (
isADS(*p)) {
4828 if (!e || e ==
name)
4867 const char *
name, *e;
4920 return rb_file_join(arg);
4924rb_file_join(
VALUE ary)
4928 const char *
name, *tail;
4938 check_path_encoding(tmp);
4947 RBASIC_CLEAR_CLASS(result);
4952 if (!checked) check_path_encoding(tmp);
5003 return rb_file_join(args);
5006#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE)
5007struct truncate_arg {
5009#if defined(HAVE_TRUNCATE)
5010#define NUM2POS(n) NUM2OFFT(n)
5013#define NUM2POS(n) NUM2LONG(n)
5019nogvl_truncate(
void *
ptr)
5021 struct truncate_arg *ta =
ptr;
5031 if (chsize(tmpfd, ta->pos) < 0) {
5061 struct truncate_arg ta;
5064 ta.pos = NUM2POS(
len);
5077#define rb_file_s_truncate rb_f_notimplement
5080#if defined(HAVE_FTRUNCATE) || defined(HAVE_CHSIZE)
5081struct ftruncate_arg {
5083#if defined(HAVE_FTRUNCATE)
5084#define NUM2POS(n) NUM2OFFT(n)
5087#define NUM2POS(n) NUM2LONG(n)
5093nogvl_ftruncate(
void *
ptr)
5095 struct ftruncate_arg *fa =
ptr;
5097#ifdef HAVE_FTRUNCATE
5100 return (
VALUE)chsize(fa->fd, fa->pos);
5122 struct ftruncate_arg fa;
5124 fa.pos = NUM2POS(
len);
5138#define rb_file_truncate rb_f_notimplement
5155#include <winerror.h>
5159rb_thread_flock(
void *data)
5162 int old_errno = errno;
5164 int *op = data, ret =
flock(op[0], op[1]);
5167 if (GetLastError() == ERROR_NOT_LOCKED) {
5226 op[1] = op1 =
NUM2INT(operation);
5238#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
5244 time.tv_usec = 100 * 1000;
5250#if defined(ERESTART)
5269 for (i=1; i<n; i++) {
5276#define CHECK(n) test_check((n), argc, argv)
5346 if (
strchr(
"bcdefgGkloOprRsSuwWxXz", cmd)) {
5350 return rb_file_blockdev_p(0,
argv[1]);
5353 return rb_file_chardev_p(0,
argv[1]);
5359 return rb_file_exist_p(0,
argv[1]);
5362 return rb_file_file_p(0,
argv[1]);
5365 return rb_file_sgid_p(0,
argv[1]);
5368 return rb_file_grpowned_p(0,
argv[1]);
5371 return rb_file_sticky_p(0,
argv[1]);
5374 return rb_file_symlink_p(0,
argv[1]);
5377 return rb_file_owned_p(0,
argv[1]);
5380 return rb_file_rowned_p(0,
argv[1]);
5383 return rb_file_pipe_p(0,
argv[1]);
5386 return rb_file_readable_p(0,
argv[1]);
5389 return rb_file_readable_real_p(0,
argv[1]);
5392 return rb_file_size_p(0,
argv[1]);
5395 return rb_file_socket_p(0,
argv[1]);
5398 return rb_file_suid_p(0,
argv[1]);
5401 return rb_file_writable_p(0,
argv[1]);
5404 return rb_file_writable_real_p(0,
argv[1]);
5407 return rb_file_executable_p(0,
argv[1]);
5410 return rb_file_executable_real_p(0,
argv[1]);
5413 return rb_file_zero_p(0,
argv[1]);
5417 if (
strchr(
"MAC", cmd)) {
5422 if (rb_stat(fname, &st) == -1) {
5430 return stat_atime(&st);
5432 return stat_mtime(&st);
5434 return stat_ctime(&st);
5440 return rb_file_identical_p(0,
argv[1],
argv[2]);
5443 if (
strchr(
"=<>", cmd)) {
5444 struct stat st1, st2;
5448 if (rb_stat(
argv[1], &st1) < 0)
return Qfalse;
5449 if (rb_stat(
argv[2], &st2) < 0)
return Qfalse;
5451 t1 = stat_mtimespec(&st1);
5452 t2 = stat_mtimespec(&st2);
5495rb_stat_s_alloc(
VALUE klass)
5497 return stat_new_0(klass, 0);
5512 struct stat st, *nst;
5565rb_stat_ftype(
VALUE obj)
5567 return rb_file_ftype(get_stat(obj));
5600 if (S_ISFIFO(get_stat(obj)->st_mode))
return Qtrue;
5647 if (S_ISSOCK(get_stat(obj)->st_mode))
return Qtrue;
5709rb_stat_owned(
VALUE obj)
5716rb_stat_rowned(
VALUE obj)
5718 if (get_stat(obj)->st_uid ==
getuid())
return Qtrue;
5735rb_stat_grpowned(
VALUE obj)
5738 if (rb_group_member(get_stat(obj)->st_gid))
return Qtrue;
5757 struct stat *st = get_stat(obj);
5763 if (rb_stat_owned(obj))
5767 if (rb_stat_grpowned(obj))
5790 struct stat *st = get_stat(obj);
5796 if (rb_stat_rowned(obj))
5800 if (rb_group_member(get_stat(obj)->st_gid))
5823rb_stat_wr(
VALUE obj)
5826 struct stat *st = get_stat(obj);
5850 struct stat *st = get_stat(obj);
5856 if (rb_stat_owned(obj))
5860 if (rb_stat_grpowned(obj))
5883 struct stat *st = get_stat(obj);
5889 if (rb_stat_rowned(obj))
5893 if (rb_group_member(get_stat(obj)->st_gid))
5916rb_stat_ww(
VALUE obj)
5919 struct stat *st = get_stat(obj);
5945 struct stat *st = get_stat(obj);
5953 if (rb_stat_owned(obj))
5957 if (rb_stat_grpowned(obj))
5977 struct stat *st = get_stat(obj);
5985 if (rb_stat_rowned(obj))
5989 if (rb_group_member(get_stat(obj)->st_gid))
6030 if (get_stat(obj)->st_size == 0)
return Qtrue;
6065rb_stat_suid(
VALUE obj)
6068 if (get_stat(obj)->st_mode & S_ISUID)
return Qtrue;
6086rb_stat_sgid(
VALUE obj)
6089 if (get_stat(obj)->st_mode & S_ISGID)
return Qtrue;
6107rb_stat_sticky(
VALUE obj)
6110 if (get_stat(obj)->st_mode & S_ISVTX)
return Qtrue;
6115#if !defined HAVE_MKFIFO && defined HAVE_MKNOD && defined S_IFIFO
6116#define mkfifo(path, mode) mknod(path, (mode)&~S_IFMT|S_IFIFO, 0)
6127nogvl_mkfifo(
void *
ptr)
6129 struct mkfifo_arg *ma =
ptr;
6131 return (
void *)(
VALUE)mkfifo(ma->path, ma->mode);
6148 struct mkfifo_arg ma;
6165#define rb_file_s_mkfifo rb_f_notimplement
6168static VALUE rb_mFConst;
6179#ifdef DOSISH_DRIVE_LETTER
6180 if (has_drive_letter(path) &&
isdirsep(path[2]))
return 1;
6186 if (path[0] ==
'/')
return 1;
6191#ifndef ENABLE_PATH_CHECK
6192# if defined DOSISH || defined __CYGWIN__
6193# define ENABLE_PATH_CHECK 0
6195# define ENABLE_PATH_CHECK 1
6199#if ENABLE_PATH_CHECK
6201path_check_0(
VALUE path)
6229 && !(p && (st.st_mode & S_ISVTX))
6232 rb_enc_warn(enc,
"Insecure world writable dir %s in PATH, mode 0%"
6233 PRI_MODET_PREFIX
"o",
6241 if (!s || s == p0)
return 1;
6252#if ENABLE_PATH_CHECK
6253 const char *p0, *p, *pend;
6256 if (!path)
return 1;
6258 pend = path +
strlen(path);
6268 if (p0 > pend)
break;
6284 if (
fstat(fd, &st) < 0)
6290 if (S_ISFIFO(st.st_mode) ||
S_ISCHR(st.st_mode))
6311 int mode = (O_RDONLY |
6312#if defined O_NONBLOCK
6314#elif defined O_NDELAY
6319 if (fd == -1)
return 0;
6328is_explicit_relative(
const char *path)
6330 if (*path++ !=
'.')
return 0;
6331 if (*path ==
'.') path++;
6348 VALUE fname = *filep, load_path, tmp;
6352 if (!ext[0])
return 0;
6355 fname = file_expand_path_1(fname);
6362 if (!expanded) fname = file_expand_path_1(fname);
6364 for (i=0; ext[i]; i++) {
6367 *filep = copy_path_class(fname, *filep);
6376 if (!load_path)
return 0;
6379 RBASIC_CLEAR_CLASS(fname);
6383 for (j=0; ext[j]; j++) {
6385 for (i = 0; i <
RARRAY_LEN(load_path); i++) {
6392 *filep = copy_path_class(tmp, *filep);
6406 VALUE tmp, load_path;
6411 tmp = file_expand_path_1(path);
6412 path = copy_path_class(tmp, path);
6420 path = copy_path_class(file_expand_path_1(path), path);
6430 for (i = 0; i <
RARRAY_LEN(load_path); i++) {
6447 return copy_path_class(tmp, path);
6460#elif defined AMIGA || defined __amigaos__
6505#if defined(__APPLE__) && defined(HAVE_WORKING_FORK)
6506 rb_CFString_class_initialize_before_fork();
6515 define_filetest_function(
"exist?", rb_file_exist_p, 1);
6516 define_filetest_function(
"exists?", rb_file_exists_p, 1);
6517 define_filetest_function(
"readable?", rb_file_readable_p, 1);
6518 define_filetest_function(
"readable_real?", rb_file_readable_real_p, 1);
6519 define_filetest_function(
"world_readable?", rb_file_world_readable_p, 1);
6520 define_filetest_function(
"writable?", rb_file_writable_p, 1);
6521 define_filetest_function(
"writable_real?", rb_file_writable_real_p, 1);
6522 define_filetest_function(
"world_writable?", rb_file_world_writable_p, 1);
6523 define_filetest_function(
"executable?", rb_file_executable_p, 1);
6524 define_filetest_function(
"executable_real?", rb_file_executable_real_p, 1);
6525 define_filetest_function(
"file?", rb_file_file_p, 1);
6526 define_filetest_function(
"zero?", rb_file_zero_p, 1);
6527 define_filetest_function(
"empty?", rb_file_zero_p, 1);
6528 define_filetest_function(
"size?", rb_file_size_p, 1);
6529 define_filetest_function(
"size", rb_file_s_size, 1);
6530 define_filetest_function(
"owned?", rb_file_owned_p, 1);
6531 define_filetest_function(
"grpowned?", rb_file_grpowned_p, 1);
6533 define_filetest_function(
"pipe?", rb_file_pipe_p, 1);
6534 define_filetest_function(
"symlink?", rb_file_symlink_p, 1);
6535 define_filetest_function(
"socket?", rb_file_socket_p, 1);
6537 define_filetest_function(
"blockdev?", rb_file_blockdev_p, 1);
6538 define_filetest_function(
"chardev?", rb_file_chardev_p, 1);
6540 define_filetest_function(
"setuid?", rb_file_suid_p, 1);
6541 define_filetest_function(
"setgid?", rb_file_sgid_p, 1);
6542 define_filetest_function(
"sticky?", rb_file_sticky_p, 1);
6544 define_filetest_function(
"identical?", rb_file_identical_p, 2);
6642#if defined(O_NDELAY) || defined(O_NONBLOCK)
6644# define O_NONBLOCK O_NDELAY
6660#ifndef O_SHARE_DELETE
6661# define O_SHARE_DELETE 0
#define offsetof(p_type, field)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
#define UNREACHABLE_RETURN
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Internal header absorbing C compipler differences.
#define OBJ_BUILTIN_TYPE(obj)
Our own, locale independent, character handling routines.
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
#define rb_define_module_function(klass, mid, func, arity)
Defines klass#mid and makes it a module function.
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
VALUE rb_dir_getwd_ospath(void)
char * strchr(char *, char)
#define rb_usascii_encindex()
#define ENCINDEX_US_ASCII
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
int rb_filesystem_encindex(void)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
rb_encoding * rb_utf8_encoding(void)
rb_encoding * rb_ascii8bit_encoding(void)
unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len_p, rb_encoding *enc)
rb_encoding * rb_enc_from_index(int index)
rb_encoding * rb_filesystem_encoding(void)
rb_encoding * rb_default_internal_encoding(void)
rb_encoding * rb_enc_get(VALUE obj)
void rb_enc_copy(VALUE obj1, VALUE obj2)
int rb_enc_to_index(rb_encoding *enc)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
VALUE rb_enc_associate_index(VALUE obj, int idx)
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
char str[HTML_ESCAPE_MAX_LEN+1]
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
VALUE rb_stat_new(const struct stat *st)
VALUE rb_get_path(VALUE obj)
#define sys_fail2(s1, s2)
VALUE rb_get_path_check_convert(VALUE obj)
const char * ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc)
int ruby_is_fd_loadable(int fd)
#define WITH_ROOTDIFF(stmt)
char * rb_enc_path_end(const char *path, const char *end, rb_encoding *enc)
VALUE rb_find_file(VALUE path)
int rb_path_check(const char *path)
VALUE rb_get_path_no_checksafe(VALUE obj)
VALUE rb_file_expand_path_fast(VALUE fname, VALUE dname)
char * rb_enc_path_next(const char *s, const char *e, rb_encoding *enc)
#define statx_has_birthtime(st)
VALUE rb_file_s_absolute_path(int argc, const VALUE *argv)
VALUE rb_str_encode_ospath(VALUE path)
int rb_file_load_ok(const char *path)
#define rb_file_s_symlink
#define BUFCOPY(srcptr, srclen)
#define rb_file_birthtime
int eaccess(const char *path, int mode)
int rb_is_absolute_path(const char *path)
char * rb_enc_path_last_separator(const char *path, const char *end, rb_encoding *enc)
#define syserr_fail2_in(func, e, s1, s2)
#define rb_file_s_readlink
#define istrailinggarbage(x)
#define check_expand_path_args(fname, dname)
const char ruby_null_device[]
int rb_find_file_ext(VALUE *filep, const char *const *ext)
char * rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc)
#define rb_file_s_birthtime
VALUE rb_file_directory_p(VALUE obj, VALUE fname)
const char * ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc)
VALUE rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *enc)
#define rb_stat_birthtime
#define expand_path(fname, dname, abs_mode, long_name, result)
#define skipprefix(path, end, enc)
VALUE rb_get_path_check_to_string(VALUE obj)
VALUE rb_file_s_expand_path(int argc, const VALUE *argv)
VALUE rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result)
VALUE rb_home_dir_of(VALUE user, VALUE result)
VALUE rb_file_expand_path(VALUE fname, VALUE dname)
void rb_file_const(const char *name, VALUE value)
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
#define EXPAND_PATH_BUFFER()
#define rb_file_s_truncate
VALUE rb_file_dirname(VALUE fname)
VALUE rb_file_absolute_path(VALUE fname, VALUE dname)
#define NORMALIZE_UTF8PATH
VALUE rb_default_home_dir(VALUE result)
void rb_include_module(VALUE klass, VALUE module)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_define_module(const char *name)
VALUE rb_define_module_under(VALUE outer, const char *name)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_enc_warn(rb_encoding *enc, const char *fmt,...)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
void rb_bug(const char *fmt,...)
void rb_warn_deprecated(const char *fmt, const char *suggest,...)
VALUE rb_eSystemCallError
VALUE rb_cObject
Object class.
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
VALUE rb_obj_class(VALUE)
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_class_inherited_p(VALUE, VALUE)
Determines if mod inherits arg.
VALUE rb_equal(VALUE, VALUE)
This function is an optimized version of calling #==.
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
unsigned short prefix[65536]
VALUE rb_hash_aref(VALUE hash, VALUE key)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
#define ENC_CODERANGE_7BIT
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
#define rb_enc_left_char_head(s, p, e, enc)
int rb_enc_str_coderange(VALUE)
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
#define ENCODING_GET(obj)
#define rb_enc_mbc_to_codepoint(p, e, enc)
#define MBCLEN_CHARFOUND_LEN(ret)
#define rb_enc_asciicompat(enc)
int rb_enc_str_asciionly_p(VALUE)
#define ENC_CODERANGE_BROKEN
#define MBCLEN_CHARFOUND_P(ret)
#define ENC_CODERANGE_CLEAR(obj)
Thin wrapper to ruby/config.h.
#define INTEGER_PACK_NATIVE_BYTE_ORDER
#define INTEGER_PACK_2COMP
#define INTEGER_PACK_LSWORD_FIRST
void rb_error_arity(int, int, int)
void rb_update_max_fd(int fd)
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
#define OBJ_INIT_COPY(obj, orig)
VALUE rb_str_resize(VALUE, long)
VALUE rb_str_new_shared(VALUE)
VALUE rb_str_plus(VALUE, VALUE)
#define rb_str_new(str, len)
VALUE rb_str_cat(VALUE, const char *, long)
void rb_str_set_len(VALUE, long)
VALUE rb_str_replace(VALUE, VALUE)
VALUE rb_str_buf_new(long)
VALUE rb_str_inspect(VALUE)
#define rb_usascii_str_new2
VALUE rb_str_tmp_new(long)
VALUE rb_str_ellipsize(VALUE, long)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
int rb_str_cmp(VALUE, VALUE)
VALUE rb_str_subseq(VALUE, long, long)
VALUE rb_str_append(VALUE, VALUE)
void rb_str_modify_expand(VALUE, long)
VALUE rb_str_buf_append(VALUE, VALUE)
#define rb_str_dup_frozen
size_t rb_str_capacity(VALUE)
#define rb_str_new_cstr(str)
void rb_thread_wait_for(struct timeval)
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
struct timespec rb_time_timespec(VALUE time)
VALUE rb_time_nano_new(time_t, long)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
void rb_define_const(VALUE, const char *, VALUE)
VALUE rb_io_taint_check(VALUE)
void rb_io_check_closed(rb_io_t *)
void rb_io_check_initialized(rb_io_t *)
size_t strlcat(char *, const char *, size_t)
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
#define rb_syserr_fail_path(err, path)
#define rb_sys_fail_path(path)
Internal header for File.
VALUE rb_io_flush_raw(VALUE, int)
Internal header for require.
VALUE rb_get_expanded_load_path(void)
Internal header for Object.
Internal header for Process.
VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts)
#define rb_fstring_lit(str)
char * rb_str_to_cstr(VALUE str)
Internal header for Thread.
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
Internal header for RubyVM.
VALUE rb_check_funcall_default(VALUE, ID, int, const VALUE *, VALUE)
#define rb_fstring_cstr(...)
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
#define INVALID_HANDLE_VALUE
Historical shim for <limits.h>.
#define ALLOCA_N(type, n)
#define RARRAY_AREF(a, i)
#define StringValuePtr(v)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
#define StringValueCStr(v)
#define RTYPEDDATA_DATA(v)
#define RUBY_TYPED_DEFAULT_FREE
#define TypedData_Get_Struct(obj, type, data_type, sval)
#define TypedData_Wrap_Struct(klass, data_type, sval)
@ RUBY_TYPED_FREE_IMMEDIATELY
const char * rb_obj_classname(VALUE)
#define FilePathStringValue(v)
VALUE rb_str_catf(VALUE, const char *,...)
VALUE rb_sprintf(const char *,...)
size_t strlen(const char *)
struct apply_filename fn[FLEX_ARY_LEN]
int(* func)(const char *, void *)
union no_gvl_stat_data::@78 file
const struct timespec * tsp
VALUE rb_readlink(VALUE path, rb_encoding *resultenc)
int fchmod(int fd, int mode)
int lchown(const char *path, int owner, int group)
VALUE rb_w32_file_identical_p(VALUE fname1, VALUE fname2)
ssize_t readlink(const char *, char *, size_t)
#define SIZEOF_STRUCT_STAT_ST_INO
int symlink(const char *src, const char *link)
int link(const char *, const char *)
#define access(path, mode)
int chown(const char *, int, int)