19#include <sys/cygwin.h>
23# if !(defined(__has_feature) && defined(__has_attribute))
28# define API_AVAILABLE(...)
29# define API_DEPRECATED(...)
31#include <CoreFoundation/CFString.h>
56#ifdef HAVE_SYS_PARAM_H
57# include <sys/param.h>
60# define MAXPATHLEN 1024
69#elif defined HAVE_SYS_UTIME_H
77#ifdef HAVE_SYS_SYSMACROS_H
78#include <sys/sysmacros.h>
84#ifdef HAVE_SYS_MKDEV_H
88#if defined(HAVE_FCNTL_H)
92#if defined(HAVE_SYS_TIME_H)
96#if !defined HAVE_LSTAT && !defined lstat
103#define STAT(p, s) rb_w32_ustati128((p), (s))
105#define lstat(p, s) rb_w32_ulstati128((p), (s))
107#define access(p, m) rb_w32_uaccess((p), (m))
109#define truncate(p, n) rb_w32_utruncate((p), (n))
111#define chmod(p, m) rb_w32_uchmod((p), (m))
113#define chown(p, o, g) rb_w32_uchown((p), (o), (g))
115#define lchown(p, o, g) rb_w32_ulchown((p), (o), (g))
117#define utimensat(s, p, t, f) rb_w32_uutimensat((s), (p), (t), (f))
119#define link(f, t) rb_w32_ulink((f), (t))
121#define unlink(p) rb_w32_uunlink(p)
123#define rename(f, t) rb_w32_urename((f), (t))
125#define symlink(s, l) rb_w32_usymlink((s), (l))
133#define STAT(p, s) stat((p), (s))
136#if defined _WIN32 || defined __APPLE__
138# define TO_OSPATH(str) rb_str_encode_ospath(str)
141# define TO_OSPATH(str) (str)
145#if defined DOSISH || defined __CYGWIN__
150#if defined HAVE_REALPATH && defined __sun && defined __SVR4
213 obj = file_path_convert(
obj);
215 check_path_encoding(
obj);
240#if 0 && defined _WIN32
255# define NORMALIZE_UTF8PATH 1
257# ifdef HAVE_WORKING_FORK
259rb_CFString_class_initialize_before_fork(
void)
282 const char small_str[] =
"/";
283 long len =
sizeof(small_str) - 1;
285 const CFAllocatorRef alloc = kCFAllocatorDefault;
286 CFStringRef s = CFStringCreateWithBytesNoCopy(alloc,
287 (
const UInt8 *)small_str,
288 len, kCFStringEncodingUTF8,
289 FALSE, kCFAllocatorNull);
290 CFMutableStringRef m = CFStringCreateMutableCopy(alloc,
len, s);
297rb_str_append_normalized_ospath(
VALUE str,
const char *
ptr,
long len)
301 CFStringRef s = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
303 kCFStringEncodingUTF8,
FALSE,
305 CFMutableStringRef m = CFStringCreateMutableCopy(kCFAllocatorDefault,
len, s);
308 CFStringNormalize(m, kCFStringNormalizationFormC);
309 all = CFRangeMake(0, CFStringGetLength(m));
310 CFStringGetBytes(m, all, kCFStringEncodingUTF8,
'?',
FALSE,
NULL, 0, &buflen);
312 CFStringGetBytes(m, all, kCFStringEncodingUTF8,
'?',
FALSE,
321rb_str_normalize_ospath(
const char *
ptr,
long len)
324 const char *e =
ptr +
len;
335 static const char invalid[3] =
"\xEF\xBF\xBD";
336 rb_str_append_normalized_ospath(
str, p1, p-p1);
344 if ((0x2000 <= c && c <= 0x2FFF) || (0xF900 <= c && c <= 0xFAFF) ||
345 (0x2F800 <= c && c <= 0x2FAFF)) {
347 rb_str_append_normalized_ospath(
str, p1, p-p1);
358 rb_str_append_normalized_ospath(
str, p1, p-p1);
365ignored_char_p(
const char *p,
const char *e,
rb_encoding *enc)
368 if (p+3 > e)
return 0;
369 switch ((
unsigned char)*p) {
371 switch ((
unsigned char)p[1]) {
373 c = (
unsigned char)p[2];
375 if (c >= 0x8c && c <= 0x8f)
return 3;
377 if (c >= 0xaa && c <= 0xae)
return 3;
380 c = (
unsigned char)p[2];
382 if (c >= 0xaa && c <= 0xaf)
return 3;
388 if ((
unsigned char)p[1] == 0xbb &&
389 (
unsigned char)p[2] == 0xbf)
396# define NORMALIZE_UTF8PATH 0
399#define apply2args(n) (rb_check_arity(argc, n, UNLIMITED_ARGUMENTS), argc-=n)
416no_gvl_apply2files(
void *
ptr)
420 for (aa->
i = 0; aa->
i < aa->
argc; aa->
i++) {
431static int utime_internal(
const char *,
void *);
447 for (aa->
i = 0; aa->
i <
argc; aa->
i++) {
458 if (
func == utime_internal) {
506stat_memsize(
const void *p)
508 return sizeof(
struct stat);
520 struct stat *nst = 0;
567 struct timespec ts1 = stat_mtimespec(get_stat(
self));
568 struct timespec ts2 = stat_mtimespec(get_stat(other));
580#define ST2UINT(val) ((val) & ~(~1UL << (sizeof(val) * CHAR_BIT - 1)))
583# define NUM2DEVT(v) NUM2UINT(v)
586# define DEVT2NUM(v) UINT2NUM(v)
588#ifndef PRI_DEVT_PREFIX
589# define PRI_DEVT_PREFIX ""
603rb_stat_dev(
VALUE self)
605 return DEVT2NUM(get_stat(
self)->st_dev);
620rb_stat_dev_major(
VALUE self)
641rb_stat_dev_minor(
VALUE self)
661rb_stat_ino(
VALUE self)
663#ifdef HAVE_STRUCT_STAT_ST_INOHIGH
669#elif SIZEOF_STRUCT_STAT_ST_INO > SIZEOF_LONG
670 return ULL2NUM(get_stat(
self)->st_ino);
672 return ULONG2NUM(get_stat(
self)->st_ino);
690rb_stat_mode(
VALUE self)
708rb_stat_nlink(
VALUE self)
710 return UINT2NUM(get_stat(
self)->st_nlink);
724rb_stat_uid(
VALUE self)
726 return UIDT2NUM(get_stat(
self)->st_uid);
740rb_stat_gid(
VALUE self)
742 return GIDT2NUM(get_stat(
self)->st_gid);
758rb_stat_rdev(
VALUE self)
760#ifdef HAVE_STRUCT_STAT_ST_RDEV
761 return DEVT2NUM(get_stat(
self)->st_rdev);
779rb_stat_rdev_major(
VALUE self)
781#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(major)
800rb_stat_rdev_minor(
VALUE self)
802#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(minor)
819rb_stat_size(
VALUE self)
821 return OFFT2NUM(get_stat(
self)->st_size);
836rb_stat_blksize(
VALUE self)
838#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
839 return ULONG2NUM(get_stat(
self)->st_blksize);
857rb_stat_blocks(
VALUE self)
859#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
860# if SIZEOF_STRUCT_STAT_ST_BLOCKS > SIZEOF_LONG
861 return ULL2NUM(get_stat(
self)->st_blocks);
863 return ULONG2NUM(get_stat(
self)->st_blocks);
875#if defined(HAVE_STRUCT_STAT_ST_ATIM)
876 ts.tv_nsec =
st->st_atim.tv_nsec;
877#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
878 ts.tv_nsec =
st->st_atimespec.tv_nsec;
879#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
880 ts.tv_nsec = (
long)
st->st_atimensec;
888stat_atime(
const struct stat *
st)
899#if defined(HAVE_STRUCT_STAT_ST_MTIM)
900 ts.tv_nsec =
st->st_mtim.tv_nsec;
901#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
902 ts.tv_nsec =
st->st_mtimespec.tv_nsec;
903#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
904 ts.tv_nsec = (
long)
st->st_mtimensec;
912stat_mtime(
const struct stat *
st)
923#if defined(HAVE_STRUCT_STAT_ST_CTIM)
924 ts.tv_nsec =
st->st_ctim.tv_nsec;
925#elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
926 ts.tv_nsec =
st->st_ctimespec.tv_nsec;
927#elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
928 ts.tv_nsec = (
long)
st->st_ctimensec;
936stat_ctime(
const struct stat *
st)
942#define HAVE_STAT_BIRTHTIME
943#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
944typedef struct stat statx_data;
946stat_birthtime(
const struct stat *
st)
948 const struct timespec *ts = &
st->st_birthtimespec;
952typedef struct stat statx_data;
953# define stat_birthtime stat_ctime
955# undef HAVE_STAT_BIRTHTIME
970rb_stat_atime(
VALUE self)
972 return stat_atime(get_stat(
self));
986rb_stat_mtime(
VALUE self)
988 return stat_mtime(get_stat(
self));
1006rb_stat_ctime(
VALUE self)
1008 return stat_ctime(get_stat(
self));
1011#if defined(HAVE_STAT_BIRTHTIME)
1037 return stat_birthtime(get_stat(
self));
1040# define rb_stat_birthtime rb_f_notimplement
1059rb_stat_inspect(
VALUE self)
1063 static const struct {
1067 {
"dev", rb_stat_dev},
1068 {
"ino", rb_stat_ino},
1069 {
"mode", rb_stat_mode},
1070 {
"nlink", rb_stat_nlink},
1071 {
"uid", rb_stat_uid},
1072 {
"gid", rb_stat_gid},
1073 {
"rdev", rb_stat_rdev},
1074 {
"size", rb_stat_size},
1075 {
"blksize", rb_stat_blksize},
1076 {
"blocks", rb_stat_blocks},
1077 {
"atime", rb_stat_atime},
1078 {
"mtime", rb_stat_mtime},
1079 {
"ctime", rb_stat_ctime},
1080#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
1095 for (
i = 0;
i <
sizeof(member)/
sizeof(member[0]);
i++) {
1103 v = (*member[
i].func)(
self);
1107 else if (
i == 0 ||
i == 6) {
1128no_gvl_fstat(
void *data)
1135fstat_without_gvl(
int fd,
struct stat *
st)
1146no_gvl_stat(
void * data)
1153stat_without_gvl(
const char *
path,
struct stat *
st)
1164#if !defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) && \
1165 defined(HAVE_STRUCT_STATX_STX_BTIME)
1168# ifdef HAVE_SYSCALL_H
1169# include <syscall.h>
1170# elif defined HAVE_SYS_SYSCALL_H
1171# include <sys/syscall.h>
1173# if defined __linux__
1174# include <linux/stat.h>
1176statx(
int dirfd,
const char *pathname,
int flags,
1177 unsigned int mask,
struct statx *statxbuf)
1179 return (
int)syscall(__NR_statx, dirfd, pathname, flags,
mask, statxbuf);
1184typedef struct no_gvl_statx_data {
1193io_blocking_statx(
void *data)
1195 no_gvl_statx_data *
arg = data;
1200no_gvl_statx(
void *data)
1202 return (
void *)io_blocking_statx(data);
1206statx_without_gvl(
const char *
path,
struct statx *stx,
unsigned int mask)
1216fstatx_without_gvl(
int fd,
struct statx *stx,
unsigned int mask)
1218 no_gvl_statx_data data = {stx, fd,
"", AT_EMPTY_PATH,
mask};
1225rb_statx(
VALUE file,
struct statx *stx,
unsigned int mask)
1234 result = fstatx_without_gvl(fptr->
fd, stx,
mask);
1246# define statx_has_birthtime(st) ((st)->stx_mask & STATX_BTIME)
1248NORETURN(
static void statx_notimplement(
const char *field_name));
1253statx_notimplement(
const char *field_name)
1256 "%s is unimplemented on this filesystem",
1261statx_birthtime(
const struct statx *stx,
VALUE fname)
1265 statx_notimplement(
"birthtime");
1270typedef struct statx statx_data;
1271# define HAVE_STAT_BIRTHTIME
1273#elif defined(HAVE_STAT_BIRTHTIME)
1274# define statx_without_gvl(path, st, mask) stat_without_gvl(path, st)
1275# define fstatx_without_gvl(fd, st, mask) fstat_without_gvl(fd, st)
1276# define statx_birthtime(st, fname) stat_birthtime(st)
1277# define statx_has_birthtime(st) 1
1278# define rb_statx(file, st, mask) rb_stat(file, st)
1280# define statx_has_birthtime(st) 0
1294 result = fstat_without_gvl(fptr->
fd,
st);
1359no_gvl_lstat(
void *
ptr)
1366lstat_without_gvl(
const char *
path,
struct stat *
st)
1405 return rb_file_s_stat(
klass, fname);
1439 return rb_io_stat(
obj);
1446#if defined(_WIN32) || !defined(HAVE_GETGROUPS)
1466 if (anum != -1 && anum != groups)
1477 while (--anum >= 0) {
1478 if (gary[anum] == gid) {
1491# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
1494#if defined(S_IXGRP) && !defined(_WIN32) && !defined(__CYGWIN__)
1495#define USE_GETEUID 1
1528 if (
st.st_uid == euid)
1530 else if (rb_group_member(
st.st_gid))
1533 if ((
int)(
st.st_mode & mode) == mode)
return 0;
1548nogvl_eaccess(
void *
ptr)
1570nogvl_access(
void *
ptr)
1620# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
1625 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1644# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
1649 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1668# define S_ISLNK(m) _S_ISLNK(m)
1671# define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
1674# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
1706# define S_ISSOCK(m) _S_ISSOCK(m)
1709# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
1712# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
1721 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1742# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
1744# define S_ISBLK(m) (0)
1751 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1770# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
1775 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1797 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1810 const char *s =
"FileTest#";
1819 rb_warning(
"%sexists? is a deprecated name, use %sexist? instead", s, s);
1820 return rb_file_exist_p(
obj, fname);
1837 if (rb_eaccess(fname,
R_OK) < 0)
return Qfalse;
1855 if (rb_access(fname,
R_OK) < 0)
return Qfalse;
1860# define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
1864# define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
1889 if (rb_stat(fname, &
st) < 0)
return Qnil;
1911 if (rb_eaccess(fname,
W_OK) < 0)
return Qfalse;
1929 if (rb_access(fname,
W_OK) < 0)
return Qfalse;
1955 if (rb_stat(fname, &
st) < 0)
return Qnil;
1981 if (rb_eaccess(fname,
X_OK) < 0)
return Qfalse;
2003 if (rb_access(fname,
X_OK) < 0)
return Qfalse;
2008# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
2028 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2048 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2049 if (
st.st_size == 0)
return Qtrue;
2068 if (rb_stat(fname, &
st) < 0)
return Qnil;
2069 if (
st.st_size == 0)
return Qnil;
2089 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2099 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2121 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2122 if (rb_group_member(
st.st_gid))
return Qtrue;
2127#if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
2129check3rdbyte(
VALUE fname,
int mode)
2133 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2134 if (
st.st_mode & mode)
return Qtrue;
2152 return check3rdbyte(fname,
S_ISUID);
2171 return check3rdbyte(fname,
S_ISGID);
2190 return check3rdbyte(fname,
S_ISVTX);
2219 struct stat st1, st2;
2221 if (rb_stat(fname1, &st1) < 0)
return Qfalse;
2222 if (rb_stat(fname2, &st2) < 0)
return Qfalse;
2223 if (st1.st_dev != st2.st_dev)
return Qfalse;
2224 if (st1.st_ino != st2.st_ino)
return Qfalse;
2246 if (rb_stat(fname, &
st) < 0) {
2255rb_file_ftype(
const struct stat *
st)
2266 t =
"characterSpecial";
2321 return rb_file_ftype(&
st);
2341 if (rb_stat(fname, &
st) < 0) {
2346 return stat_atime(&
st);
2370 return stat_atime(&
st);
2390 if (rb_stat(fname, &
st) < 0) {
2395 return stat_mtime(&
st);
2418 return stat_mtime(&
st);
2442 if (rb_stat(fname, &
st) < 0) {
2447 return stat_ctime(&
st);
2473 return stat_ctime(&
st);
2490#if defined(HAVE_STAT_BIRTHTIME)
2496 if (rb_statx(fname, &
st, STATX_BTIME) < 0) {
2501 return statx_birthtime(&
st, fname);
2504# define rb_file_s_birthtime rb_f_notimplement
2507#if defined(HAVE_STAT_BIRTHTIME)
2527 if (fstatx_without_gvl(fptr->
fd, &
st, STATX_BTIME) == -1) {
2530 return statx_birthtime(&
st, fptr->
pathv);
2533# define rb_file_birthtime rb_f_notimplement
2563chmod_internal(
const char *
path,
void *mode)
2589 return apply2files(chmod_internal,
argc,
argv, &mode);
2610#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
2618 if (
fchmod(fptr->
fd, mode) == -1) {
2626#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
2636#if defined(HAVE_LCHMOD)
2638lchmod_internal(
const char *
path,
void *mode)
2661 return apply2files(lchmod_internal,
argc,
argv, &mode);
2664#define rb_file_s_lchmod rb_f_notimplement
2691chown_internal(
const char *
path,
void *
arg)
2721 return apply2files(chown_internal,
argc,
argv, &
arg);
2765#if defined(HAVE_LCHOWN)
2767lchown_internal(
const char *
path,
void *
arg)
2793 return apply2files(lchown_internal,
argc,
argv, &
arg);
2796#define rb_file_s_lchown rb_f_notimplement
2827 if (
NIL_P(a)) e[0] = m;
2847#if defined(HAVE_UTIMES)
2850utime_internal(
const char *
path,
void *
arg)
2856#if defined(HAVE_UTIMENSAT)
2857 static int try_utimensat = 1;
2858# ifdef AT_SYMLINK_NOFOLLOW
2859 static int try_utimensat_follow = 1;
2861 const int try_utimensat_follow = 0;
2865 if (
v->follow ? try_utimensat_follow : try_utimensat) {
2866# ifdef AT_SYMLINK_NOFOLLOW
2868 flags = AT_SYMLINK_NOFOLLOW;
2874# ifdef AT_SYMLINK_NOFOLLOW
2875 try_utimensat_follow = 0;
2889 tvbuf[0].tv_sec = tsp[0].
tv_sec;
2890 tvbuf[0].tv_usec = (
int)(tsp[0].tv_nsec / 1000);
2891 tvbuf[1].tv_sec = tsp[1].
tv_sec;
2892 tvbuf[1].tv_usec = (
int)(tsp[1].tv_nsec / 1000);
2896 if (
v->follow)
return lutimes(
path, tvp);
2898 return utimes(
path, tvp);
2903#if !defined HAVE_UTIME_H && !defined HAVE_SYS_UTIME_H
2911utime_internal(
const char *
path,
void *
arg)
2921 return utime(
path, utp);
2933 args.atime = *
argv++;
2934 args.mtime = *
argv++;
2936 args.follow = follow;
2938 if (!
NIL_P(args.atime) || !
NIL_P(args.mtime)) {
2941 if (args.atime == args.mtime)
2948 return apply2files(utime_internal,
argc,
argv, &args);
2968#if defined(HAVE_UTIMES) && (defined(HAVE_LUTIMES) || (defined(HAVE_UTIMENSAT) && defined(AT_SYMLINK_NOFOLLOW)))
2987#define rb_file_s_lutime rb_f_notimplement
2990#ifdef RUBY_FUNCTION_NAME_STRING
2991# define syserr_fail2(e, s1, s2) syserr_fail2_in(RUBY_FUNCTION_NAME_STRING, e, s1, s2)
2993# define syserr_fail2_in(func, e, s1, s2) syserr_fail2(e, s1, s2)
2995#define sys_fail2(s1, s2) syserr_fail2(errno, s1, s2)
3002 const int max_pathlen = MAX_PATH;
3015#ifdef RUBY_FUNCTION_NAME_STRING
3016 rb_syserr_fail_path_in(func, e,
str);
3049#define rb_file_s_link rb_f_notimplement
3079#define rb_file_s_symlink rb_f_notimplement
3101struct readlink_arg {
3108nogvl_readlink(
void *
ptr)
3110 struct readlink_arg *ra =
ptr;
3112 return (
void *)(
VALUE)
readlink(ra->path, ra->buf, ra->size);
3118 struct readlink_arg ra;
3158#define rb_file_s_readlink rb_f_notimplement
3162unlink_internal(
const char *
path,
void *
arg)
3186 return apply2files(unlink_internal,
argc,
argv, 0);
3195no_gvl_rename(
void *
ptr)
3224#if defined __CYGWIN__
3233 if (
chmod(ra.dst, 0666) == 0 &&
3235 rename(ra.src, ra.dst) == 0)
3239 syserr_fail2(e, from, to);
3282#if defined __CYGWIN__ || defined DOSISH
3284#define DOSISH_DRIVE_LETTER
3285#define FILE_ALT_SEPARATOR '\\'
3287#ifdef FILE_ALT_SEPARATOR
3288#define isdirsep(x) ((x) == '/' || (x) == FILE_ALT_SEPARATOR)
3290static const char file_alt_separator[] = {FILE_ALT_SEPARATOR,
'\0'};
3293#define isdirsep(x) ((x) == '/')
3305# define USE_NTFS_ADS 1
3307# define USE_NTFS_ADS 0
3312#define istrailinggarbage(x) ((x) == '.' || (x) == ' ')
3314#define istrailinggarbage(x) 0
3317# define isADS(x) ((x) == ':')
3322#define Next(p, e, enc) ((p) + rb_enc_mbclen((p), (e), (enc)))
3323#define Inc(p, e, enc) ((p) = Next((p), (e), (enc)))
3325#if defined(DOSISH_UNC)
3326#define has_unc(buf) (isdirsep((buf)[0]) && isdirsep((buf)[1]))
3328#define has_unc(buf) 0
3331#ifdef DOSISH_DRIVE_LETTER
3333has_drive_letter(
const char *
buf)
3348 char *drvcwd, *oldcwd;
3359 if (
chdir(drive) == 0) {
3377 if (has_drive_letter(p)) {
3389#ifdef DOSISH_DRIVE_LETTER
3390 if (
path + 2 <= end && has_drive_letter(
path))
path += 2;
3393 return (
char *)
path;
3396#define nextdirsep rb_enc_path_next
3406#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
3407#define skipprefix rb_enc_path_skip_prefix
3409#define skipprefix(path, end, enc) (path)
3414#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
3421 return (
char *)
path;
3424#ifdef DOSISH_DRIVE_LETTER
3425 if (has_drive_letter(
path))
3426 return (
char *)(
path + 2);
3429 return (
char *)
path;
3435#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
3440 return skiproot(
path, end, enc);
3444#define strrdirsep rb_enc_path_last_separator
3449 while (
path < end) {
3451 const char *tmp =
path++;
3453 if (
path >= end)
break;
3466 while (
path < end) {
3470 if (
path >= end)
return (
char *)
last;
3476 return (
char *)
path;
3483 return chompdirsep(
path, end, enc);
3500 if (
path >= end)
return (
char *)
last;
3507 return (
char *)
path;
3511#define BUFCHECK(cond) do {\
3514 do {buflen *= 2;} while (cond);\
3515 rb_str_resize(result, buflen);\
3516 buf = RSTRING_PTR(result);\
3518 pend = buf + buflen;\
3523 p = buf = RSTRING_PTR(result),\
3524 buflen = RSTRING_LEN(result),\
3528# define SKIPPATHSEP(p) ((*(p)) ? 1 : 0)
3530# define SKIPPATHSEP(p) 1
3533#define BUFCOPY(srcptr, srclen) do { \
3534 const int skip = SKIPPATHSEP(p); \
3535 rb_str_set_len(result, p-buf+skip); \
3536 BUFCHECK(bdiff + ((srclen)+skip) >= buflen); \
3538 memcpy(p, (srcptr), (srclen)); \
3542#define WITH_ROOTDIFF(stmt) do { \
3543 long rootdiff = root - buf; \
3545 root = buf + rootdiff; \
3549copy_home_path(
VALUE result,
const char *dir)
3552#if defined DOSISH || defined __CYGWIN__
3564#if defined DOSISH || defined __CYGWIN__
3566 for (bend = (p =
buf) + dirlen; p < bend;
Inc(p, bend, enc)) {
3579 struct passwd *pwPtr;
3582 const char *pwPtr = 0;
3583 # define endpwent() ((void)0)
3597 pwPtr = getpwnam(username);
3600 dir = pwPtr =
getenv(
"HOME");
3607 dir = pwPtr->pw_dir;
3609 copy_home_path(result, dir);
3618 const char *dir =
getenv(
"HOME");
3620#if defined HAVE_PWD_H
3636# if !defined(HAVE_GETPWUID_R) && !defined(HAVE_GETPWUID)
3641 if (
NIL_P(login_name)) {
3647 if (
NIL_P(pw_dir)) {
3649 if (
NIL_P(pw_dir)) {
3663 return copy_home_path(result, dir);
3669#if NORMALIZE_UTF8PATH
3681 char *
buf, *cwdp = dir;
3687 if (direnc != fsenc) {
3696 do {buflen *= 2;}
while (dirlen > buflen);
3703 return buf + dirlen;
3709 const char *s, *b, *fend;
3710 char *
buf, *p, *pend, *root;
3711 size_t buflen, bdiff;
3719 if (s[0] ==
'~' && abs_mode == 0) {
3721 if (
isdirsep(s[1]) || s[1] ==
'\0') {
3732 BUFCHECK(bdiff + userlen >= buflen);
3744 (
int)userlen, b, fname);
3753#ifdef DOSISH_DRIVE_LETTER
3755 else if (has_drive_letter(s)) {
3768 if (!
NIL_P(dname) && !not_same_drive(dname, s[0])) {
3777 char *e = append_fspath(result, fname, getcwdofdrv(*s), &enc, fsenc);
3785 p = chompdirsep(skiproot(
buf, p, enc), p, enc);
3791 if (!
NIL_P(dname)) {
3798 char *e = append_fspath(result, fname,
ruby_getcwd(), &enc, fsenc);
3802#if defined DOSISH || defined __CYGWIN__
3810 p = chompdirsep(skiproot(
buf, p, enc), p, enc);
3823 if (p >
buf && p[-1] ==
'/')
3846 if (*(s+1) ==
'\0' ||
isdirsep(*(s+1))) {
3865#if defined DOSISH || defined __CYGWIN__
3890#if defined DOSISH || defined __CYGWIN__
3902 int n = ignored_char_p(s, fend, enc);
3921 static const char prime[] =
":$DATA";
3922 enum {prime_len =
sizeof(prime) -1};
3926 if (s > b + prime_len &&
strncasecmp(s - prime_len, prime, prime_len) == 0) {
3929 if (
isADS(*(s - (prime_len+1)))) {
3932 else if (
memchr(b,
':', s - prime_len - b)) {
3941 if (p == skiproot(
buf, p + !!*p, enc) - 1) p++;
3950 WIN32_FIND_DATAW wfd;
3953#ifdef HAVE_CYGWIN_CONV_PATH
3954 char *w32buf =
NULL;
3955 const int flags = CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
3961 int lnk_added = 0, is_symlink = 0;
3972#ifdef HAVE_CYGWIN_CONV_PATH
3973 bufsize = cygwin_conv_path(flags,
path,
NULL, 0);
3976 if (lnk_added) bufsize += 4;
3978 if (cygwin_conv_path(flags,
path, w32buf, bufsize) == 0) {
3984 if (cygwin_conv_to_win32_path(
path, w32buf) == 0) {
3988 if (is_symlink && b == w32buf) {
3992 strlcat(w32buf,
".lnk", bufsize);
4008 MultiByteToWideChar(CP_UTF8, 0,
RSTRING_PTR(tmp), -1, wstr,
len);
4010 h = FindFirstFileW(wstr, &wfd);
4012 if (
h != INVALID_HANDLE_VALUE) {
4015 len = lstrlenW(wfd.cFileName);
4017 if (lnk_added &&
len > 4 &&
4018 wcscasecmp(wfd.cFileName +
len - 4,
L".lnk") == 0) {
4019 wfd.cFileName[
len -= 4] =
L'\0';
4026 len = WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen,
NULL, 0,
NULL,
NULL);
4027 if (tmp == result) {
4029 WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, p,
len + 1,
NULL,
NULL);
4056#define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, MAXPATHLEN + 2)
4065#define expand_path(fname, dname, abs_mode, long_name, result) \
4066 str_shrink(rb_file_expand_path_internal(fname, dname, abs_mode, long_name, result))
4068#define check_expand_path_args(fname, dname) \
4069 (((fname) = rb_get_path(fname)), \
4070 (void)(NIL_P(dname) ? (dname) : ((dname) = rb_get_path(dname))))
4073file_expand_path_1(
VALUE fname)
4192realpath_rec(
long *prefixlenp,
VALUE *resolvedp,
const char *unresolved,
VALUE fallback,
4195 const char *pend = unresolved +
strlen(unresolved);
4199 while (unresolved < pend) {
4200 const char *testname = unresolved;
4202 long testnamelen = unresolved_firstsep - unresolved;
4203 const char *unresolved_nextname = unresolved_firstsep;
4204 while (unresolved_nextname < pend &&
isdirsep(*unresolved_nextname))
4205 unresolved_nextname++;
4206 unresolved = unresolved_nextname;
4207 if (testnamelen == 1 && testname[0] ==
'.') {
4209 else if (testnamelen == 2 && testname[0] ==
'.' && testname[1] ==
'.') {
4211 const char *resolved_str =
RSTRING_PTR(*resolvedp);
4212 const char *resolved_names = resolved_str + *prefixlenp;
4214 long len = lastsep ? lastsep - resolved_names : 0;
4223#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
4224 if (*prefixlenp > 1 && *prefixlenp ==
RSTRING_LEN(testpath)) {
4232 if (!
NIL_P(checkval)) {
4233 if (checkval ==
ID2SYM(resolving)) {
4247 ret = lstat_without_gvl(
RSTRING_PTR(testpath), &sbuf);
4251 if (stat_without_gvl(
RSTRING_PTR(fallback), &sbuf) == 0) {
4260 *resolvedp = testpath;
4271 const char *link_prefix, *link_names;
4272 long link_prefixlen;
4277 link_prefixlen = link_names - link_prefix;
4278 if (link_prefixlen > 0) {
4285 *prefixlenp = link_prefixlen;
4287 if (realpath_rec(prefixlenp, resolvedp, link_names, testpath,
4288 loopcheck, mode, !*unresolved_firstsep))
4298 *resolvedp = testpath;
4311 VALUE unresolved_path;
4316 char *path_names =
NULL, *basedir_names =
NULL, *curdir_names =
NULL;
4317 char *
ptr, *prefixptr =
NULL, *pend;
4322 if (!
NIL_P(basedir)) {
4328 unresolved_path =
TO_OSPATH(unresolved_path);
4331 if (
ptr != path_names) {
4336 if (!
NIL_P(basedir)) {
4339 if (
ptr != basedir_names) {
4352 pend = prefixptr + prefixlen;
4353 ptr = chompdirsep(prefixptr, pend, enc);
4355 prefixlen = ++
ptr - prefixptr;
4358#ifdef FILE_ALT_SEPARATOR
4359 while (prefixptr <
ptr) {
4360 if (*prefixptr == FILE_ALT_SEPARATOR) {
4363 Inc(prefixptr, pend, enc);
4375 if (realpath_rec(&prefixlen, &resolved, curdir_names,
Qnil, loopcheck, mode, 0))
4378 if (basedir_names) {
4379 if (realpath_rec(&prefixlen, &resolved, basedir_names,
Qnil, loopcheck, mode, 0))
4382 if (realpath_rec(&prefixlen, &resolved, path_names,
Qnil, loopcheck, mode, 1))
4385 if (origenc && origenc !=
rb_enc_get(resolved)) {
4405 VALUE unresolved_path;
4406 char *resolved_ptr =
NULL;
4411 return rb_check_realpath_emulate(basedir,
path, origenc, mode);
4416 unresolved_path = rb_file_join(
rb_assoc_new(basedir, unresolved_path));
4418 if (origenc) unresolved_path =
TO_OSPATH(unresolved_path);
4427 (
errno ==
ENOENT && rb_file_exist_p(0, unresolved_path))) {
4428 return rb_check_realpath_emulate(basedir,
path, origenc, mode);
4448 if (origenc && origenc !=
rb_enc_get(resolved)) {
4465 return rb_check_realpath_emulate(basedir,
path, origenc, mode);
4527rmext(
const char *p,
long l0,
long l1,
const char *e,
long l2,
rb_encoding *enc)
4531 const char *s, *
last;
4533 if (!e || !l2)
return 0;
4536 if (
rb_enc_ascget(e + len1, e + l2, &len2, enc) ==
'*' && len1 + len2 == l2) {
4537 if (c ==
'.')
return l0;
4547 if (l1 < l2)
return l1;
4551#if CASEFOLD_FILESYSTEM
4552#define fncomp strncasecmp
4554#define fncomp strncmp
4556 if (
fncomp(s, e, l2) == 0) {
4565 const char *p, *q, *e, *end;
4566#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
4573#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
4581#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
4585#ifdef DOSISH_DRIVE_LETTER
4586 else if (*p ==
':') {
4606 n = ntfs_tail(p, end, enc) - p;
4608 n = chompdirsep(p, end, enc) - p;
4610 for (q = p; q - p <
n && *q ==
'.'; q++);
4611 for (e = 0; q - p <
n;
Inc(q, end, enc)) {
4612 if (*q ==
'.') e = q;
4646 const char *
name, *p;
4654 enc = check_path_encoding(fext);
4708 const char *
name, *root, *p, *end;
4716 root = skiproot(
name, end, enc);
4721 if (root >
name + 1)
4730#ifdef DOSISH_DRIVE_LETTER
4732 const char *
top = skiproot(
name + 2, end, enc);
4739#ifdef DOSISH_DRIVE_LETTER
4740 if (has_drive_letter(
name) && root ==
name + 2 && p -
name == 2)
4771 while (*p && *p ==
'.') p++;
4775 const char *
last = p++, *dot =
last;
4777 if (*p ==
'.') dot = p;
4780 if (!*p ||
isADS(*p)) {
4784 if (*
last ==
'.' || dot >
last) e = dot;
4791 else if (
isADS(*p)) {
4802 if (!e || e ==
name)
4841 const char *
name, *e;
4894 return rb_file_join(
arg);
4898rb_file_join(
VALUE ary)
4902 const char *
name, *tail;
4912 check_path_encoding(tmp);
4926 if (!checked) check_path_encoding(tmp);
4977 return rb_file_join(args);
4980#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE)
4981struct truncate_arg {
4983#if defined(HAVE_TRUNCATE)
4984#define NUM2POS(n) NUM2OFFT(n)
4987#define NUM2POS(n) NUM2LONG(n)
4993nogvl_truncate(
void *
ptr)
4995 struct truncate_arg *ta =
ptr;
5005 if (chsize(tmpfd, ta->pos) < 0) {
5035 struct truncate_arg ta;
5038 ta.pos = NUM2POS(
len);
5051#define rb_file_s_truncate rb_f_notimplement
5054#if defined(HAVE_FTRUNCATE) || defined(HAVE_CHSIZE)
5055struct ftruncate_arg {
5057#if defined(HAVE_FTRUNCATE)
5058#define NUM2POS(n) NUM2OFFT(n)
5061#define NUM2POS(n) NUM2LONG(n)
5067nogvl_ftruncate(
void *
ptr)
5069 struct ftruncate_arg *fa =
ptr;
5071#ifdef HAVE_FTRUNCATE
5074 return (
VALUE)chsize(fa->fd, fa->pos);
5096 struct ftruncate_arg fa;
5098 fa.pos = NUM2POS(
len);
5112#define rb_file_truncate rb_f_notimplement
5129#include <winerror.h>
5133rb_thread_flock(
void *data)
5136 int old_errno =
errno;
5138 int *op = data, ret =
flock(op[0], op[1]);
5141 if (GetLastError() == ERROR_NOT_LOCKED) {
5200 op[1] = op1 =
NUM2INT(operation);
5212#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
5218 time.tv_usec = 100 * 1000;
5224#if defined(ERESTART)
5243 for (
i=1;
i<
n;
i++) {
5250#define CHECK(n) test_check((n), argc, argv)
5327 if (
strchr(
"bcdefgGkloOprRsSuwWxXz", cmd)) {
5331 return rb_file_blockdev_p(0,
argv[1]);
5334 return rb_file_chardev_p(0,
argv[1]);
5340 return rb_file_exist_p(0,
argv[1]);
5343 return rb_file_file_p(0,
argv[1]);
5346 return rb_file_sgid_p(0,
argv[1]);
5349 return rb_file_grpowned_p(0,
argv[1]);
5352 return rb_file_sticky_p(0,
argv[1]);
5355 return rb_file_symlink_p(0,
argv[1]);
5358 return rb_file_owned_p(0,
argv[1]);
5361 return rb_file_rowned_p(0,
argv[1]);
5364 return rb_file_pipe_p(0,
argv[1]);
5367 return rb_file_readable_p(0,
argv[1]);
5370 return rb_file_readable_real_p(0,
argv[1]);
5373 return rb_file_size_p(0,
argv[1]);
5376 return rb_file_socket_p(0,
argv[1]);
5379 return rb_file_suid_p(0,
argv[1]);
5382 return rb_file_writable_p(0,
argv[1]);
5385 return rb_file_writable_real_p(0,
argv[1]);
5388 return rb_file_executable_p(0,
argv[1]);
5391 return rb_file_executable_real_p(0,
argv[1]);
5394 return rb_file_zero_p(0,
argv[1]);
5398 if (
strchr(
"MAC", cmd)) {
5403 if (rb_stat(fname, &
st) == -1) {
5411 return stat_atime(&
st);
5413 return stat_mtime(&
st);
5415 return stat_ctime(&
st);
5421 return rb_file_identical_p(0,
argv[1],
argv[2]);
5424 if (
strchr(
"=<>", cmd)) {
5425 struct stat st1, st2;
5429 if (rb_stat(
argv[1], &st1) < 0)
return Qfalse;
5430 if (rb_stat(
argv[2], &st2) < 0)
return Qfalse;
5432 t1 = stat_mtimespec(&st1);
5433 t2 = stat_mtimespec(&st2);
5470 return stat_new_0(
klass, 0);
5540 return rb_file_ftype(get_stat(
obj));
5736 if (rb_stat_owned(
obj))
5740 if (rb_stat_grpowned(
obj))
5769 if (rb_stat_rowned(
obj))
5773 if (rb_group_member(get_stat(
obj)->
st_gid))
5829 if (rb_stat_owned(
obj))
5833 if (rb_stat_grpowned(
obj))
5862 if (rb_stat_rowned(
obj))
5866 if (rb_group_member(get_stat(
obj)->
st_gid))
5926 if (rb_stat_owned(
obj))
5930 if (rb_stat_grpowned(
obj))
5958 if (rb_stat_rowned(
obj))
5962 if (rb_group_member(get_stat(
obj)->
st_gid))
6088#if !defined HAVE_MKFIFO && defined HAVE_MKNOD && defined S_IFIFO
6089#define mkfifo(path, mode) mknod(path, (mode)&~S_IFMT|S_IFIFO, 0)
6100nogvl_mkfifo(
void *
ptr)
6102 struct mkfifo_arg *ma =
ptr;
6121 struct mkfifo_arg ma;
6138#define rb_file_s_mkfifo rb_f_notimplement
6141static VALUE rb_mFConst;
6152#ifdef DOSISH_DRIVE_LETTER
6159 if (
path[0] ==
'/')
return 1;
6164#ifndef ENABLE_PATH_CHECK
6165# if defined DOSISH || defined __CYGWIN__
6166# define ENABLE_PATH_CHECK 0
6168# define ENABLE_PATH_CHECK 1
6172#if ENABLE_PATH_CHECK
6202 && !(p && execpath && (
st.st_mode &
S_ISVTX))
6205 rb_enc_warn(enc,
"Insecure world writable dir %s in %sPATH, mode 0%"
6207 p0, (execpath ?
"" :
"LOAD_"),
st.st_mode);
6214 if (!s || s == p0)
return 1;
6222#if ENABLE_PATH_CHECK
6223#define fpath_check(path) path_check_0((path), FALSE)
6225#define fpath_check(path) 1
6231#if ENABLE_PATH_CHECK
6232 const char *p0, *p, *pend;
6235 if (!
path)
return 1;
6247 if (p0 > pend)
break;
6290 int mode = (O_RDONLY |
6291#if defined O_NONBLOCK
6293#elif defined O_NDELAY
6298 if (fd == -1)
return 0;
6307is_explicit_relative(
const char *
path)
6309 if (*
path++ !=
'.')
return 0;
6326 rb_warn(
"rb_find_file_ext_safe will be removed in Ruby 3.0");
6334 VALUE fname = *filep, load_path, tmp;
6338 if (!ext[0])
return 0;
6341 fname = file_expand_path_1(fname);
6348 if (!expanded) fname = file_expand_path_1(fname);
6350 for (
i=0; ext[
i];
i++) {
6353 *filep = copy_path_class(fname, *filep);
6362 if (!load_path)
return 0;
6369 for (j=0; ext[j]; j++) {
6378 *filep = copy_path_class(tmp, *filep);
6392 rb_warn(
"rb_find_file_safe will be removed in Ruby 3.0");
6399 VALUE tmp, load_path;
6404 tmp = file_expand_path_1(
path);
6413 path = copy_path_class(file_expand_path_1(
path),
path);
6440 return copy_path_class(tmp,
path);
6453#elif defined AMIGA || defined __amigaos__
6498#if defined(__APPLE__) && defined(HAVE_WORKING_FORK)
6499 rb_CFString_class_initialize_before_fork();
6508 define_filetest_function(
"exist?", rb_file_exist_p, 1);
6509 define_filetest_function(
"exists?", rb_file_exists_p, 1);
6510 define_filetest_function(
"readable?", rb_file_readable_p, 1);
6511 define_filetest_function(
"readable_real?", rb_file_readable_real_p, 1);
6512 define_filetest_function(
"world_readable?", rb_file_world_readable_p, 1);
6513 define_filetest_function(
"writable?", rb_file_writable_p, 1);
6514 define_filetest_function(
"writable_real?", rb_file_writable_real_p, 1);
6515 define_filetest_function(
"world_writable?", rb_file_world_writable_p, 1);
6516 define_filetest_function(
"executable?", rb_file_executable_p, 1);
6517 define_filetest_function(
"executable_real?", rb_file_executable_real_p, 1);
6518 define_filetest_function(
"file?", rb_file_file_p, 1);
6519 define_filetest_function(
"zero?", rb_file_zero_p, 1);
6520 define_filetest_function(
"empty?", rb_file_zero_p, 1);
6521 define_filetest_function(
"size?", rb_file_size_p, 1);
6522 define_filetest_function(
"size", rb_file_s_size, 1);
6523 define_filetest_function(
"owned?", rb_file_owned_p, 1);
6524 define_filetest_function(
"grpowned?", rb_file_grpowned_p, 1);
6526 define_filetest_function(
"pipe?", rb_file_pipe_p, 1);
6527 define_filetest_function(
"symlink?", rb_file_symlink_p, 1);
6528 define_filetest_function(
"socket?", rb_file_socket_p, 1);
6530 define_filetest_function(
"blockdev?", rb_file_blockdev_p, 1);
6531 define_filetest_function(
"chardev?", rb_file_chardev_p, 1);
6533 define_filetest_function(
"setuid?", rb_file_suid_p, 1);
6534 define_filetest_function(
"setgid?", rb_file_sgid_p, 1);
6535 define_filetest_function(
"sticky?", rb_file_sticky_p, 1);
6537 define_filetest_function(
"identical?", rb_file_identical_p, 2);
6635#if defined(O_NDELAY) || defined(O_NONBLOCK)
6637# define O_NONBLOCK O_NDELAY
6653#ifndef O_SHARE_DELETE
6654# define O_SHARE_DELETE 0
#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)
int rb_usascii_encindex(void)
#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)
char str[HTML_ESCAPE_MAX_LEN+1]
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)
struct no_gvl_stat_data no_gvl_stat_data
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)
int rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int _level)
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)
NORETURN(static void syserr_fail2_in(const char *, int, VALUE, VALUE))
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
VALUE rb_find_file_safe(VALUE path, int _level)
#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, VALUE)
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
VALUE rb_define_module(const char *)
VALUE rb_define_module_under(VALUE, const char *)
VALUE rb_cObject
Object class.
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_warn(const char *fmt,...)
void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt,...)
VALUE rb_eSystemCallError
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_class_inherited_p(VALUE mod, VALUE arg)
Determines if mod inherits arg.
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
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.
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_io_taint_check(VALUE)
void rb_io_check_closed(rb_io_t *)
#define GetOpenFile(obj, fp)
void rb_io_check_initialized(rb_io_t *)
size_t rb_str_capacity(VALUE str)
VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts)
struct apply_filename fn[FLEX_ARY_LEN]
int(* func)(const char *, void *)
union no_gvl_stat_data::@137 file
const struct timespec * tsp
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
MJIT_STATIC void rb_error_arity(int argc, int min, int max)
VALUE rb_readlink(VALUE path, rb_encoding *resultenc)
VALUE rb_w32_file_identical_p(VALUE fname1, VALUE fname2)