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
257rb_str_append_normalized_ospath(
VALUE str,
const char *
ptr,
long len)
261 CFStringRef s = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
263 kCFStringEncodingUTF8,
FALSE,
265 CFMutableStringRef m = CFStringCreateMutableCopy(kCFAllocatorDefault,
len, s);
268 CFStringNormalize(m, kCFStringNormalizationFormC);
269 all = CFRangeMake(0, CFStringGetLength(m));
270 CFStringGetBytes(m, all, kCFStringEncodingUTF8,
'?',
FALSE,
NULL, 0, &buflen);
272 CFStringGetBytes(m, all, kCFStringEncodingUTF8,
'?',
FALSE,
281rb_str_normalize_ospath(
const char *
ptr,
long len)
284 const char *e =
ptr +
len;
295 static const char invalid[3] =
"\xEF\xBF\xBD";
296 rb_str_append_normalized_ospath(
str, p1, p-p1);
304 if ((0x2000 <= c && c <= 0x2FFF) || (0xF900 <= c && c <= 0xFAFF) ||
305 (0x2F800 <= c && c <= 0x2FAFF)) {
307 rb_str_append_normalized_ospath(
str, p1, p-p1);
318 rb_str_append_normalized_ospath(
str, p1, p-p1);
325ignored_char_p(
const char *p,
const char *e,
rb_encoding *enc)
328 if (p+3 > e)
return 0;
329 switch ((
unsigned char)*p) {
331 switch ((
unsigned char)p[1]) {
333 c = (
unsigned char)p[2];
335 if (c >= 0x8c && c <= 0x8f)
return 3;
337 if (c >= 0xaa && c <= 0xae)
return 3;
340 c = (
unsigned char)p[2];
342 if (c >= 0xaa && c <= 0xaf)
return 3;
348 if ((
unsigned char)p[1] == 0xbb &&
349 (
unsigned char)p[2] == 0xbf)
356# define NORMALIZE_UTF8PATH 0
359#define apply2args(n) (rb_check_arity(argc, n, UNLIMITED_ARGUMENTS), argc-=n)
376no_gvl_apply2files(
void *
ptr)
380 for (aa->
i = 0; aa->
i < aa->
argc; aa->
i++) {
391static int utime_internal(
const char *,
void *);
407 for (aa->
i = 0; aa->
i <
argc; aa->
i++) {
418 if (
func == utime_internal) {
466stat_memsize(
const void *p)
468 return sizeof(
struct stat);
480 struct stat *nst = 0;
527 struct timespec ts1 = stat_mtimespec(get_stat(
self));
528 struct timespec ts2 = stat_mtimespec(get_stat(other));
540#define ST2UINT(val) ((val) & ~(~1UL << (sizeof(val) * CHAR_BIT - 1)))
543# define NUM2DEVT(v) NUM2UINT(v)
546# define DEVT2NUM(v) UINT2NUM(v)
548#ifndef PRI_DEVT_PREFIX
549# define PRI_DEVT_PREFIX ""
563rb_stat_dev(
VALUE self)
565 return DEVT2NUM(get_stat(
self)->st_dev);
580rb_stat_dev_major(
VALUE self)
601rb_stat_dev_minor(
VALUE self)
621rb_stat_ino(
VALUE self)
623#ifdef HAVE_STRUCT_STAT_ST_INOHIGH
629#elif SIZEOF_STRUCT_STAT_ST_INO > SIZEOF_LONG
630 return ULL2NUM(get_stat(
self)->st_ino);
632 return ULONG2NUM(get_stat(
self)->st_ino);
650rb_stat_mode(
VALUE self)
668rb_stat_nlink(
VALUE self)
670 return UINT2NUM(get_stat(
self)->st_nlink);
684rb_stat_uid(
VALUE self)
686 return UIDT2NUM(get_stat(
self)->st_uid);
700rb_stat_gid(
VALUE self)
702 return GIDT2NUM(get_stat(
self)->st_gid);
718rb_stat_rdev(
VALUE self)
720#ifdef HAVE_STRUCT_STAT_ST_RDEV
721 return DEVT2NUM(get_stat(
self)->st_rdev);
739rb_stat_rdev_major(
VALUE self)
741#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(major)
760rb_stat_rdev_minor(
VALUE self)
762#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(minor)
779rb_stat_size(
VALUE self)
781 return OFFT2NUM(get_stat(
self)->st_size);
796rb_stat_blksize(
VALUE self)
798#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
799 return ULONG2NUM(get_stat(
self)->st_blksize);
817rb_stat_blocks(
VALUE self)
819#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
820# if SIZEOF_STRUCT_STAT_ST_BLOCKS > SIZEOF_LONG
821 return ULL2NUM(get_stat(
self)->st_blocks);
823 return ULONG2NUM(get_stat(
self)->st_blocks);
835#if defined(HAVE_STRUCT_STAT_ST_ATIM)
836 ts.tv_nsec =
st->st_atim.tv_nsec;
837#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
838 ts.tv_nsec =
st->st_atimespec.tv_nsec;
839#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
840 ts.tv_nsec = (
long)
st->st_atimensec;
848stat_atime(
const struct stat *
st)
859#if defined(HAVE_STRUCT_STAT_ST_MTIM)
860 ts.tv_nsec =
st->st_mtim.tv_nsec;
861#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
862 ts.tv_nsec =
st->st_mtimespec.tv_nsec;
863#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
864 ts.tv_nsec = (
long)
st->st_mtimensec;
872stat_mtime(
const struct stat *
st)
883#if defined(HAVE_STRUCT_STAT_ST_CTIM)
884 ts.tv_nsec =
st->st_ctim.tv_nsec;
885#elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
886 ts.tv_nsec =
st->st_ctimespec.tv_nsec;
887#elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
888 ts.tv_nsec = (
long)
st->st_ctimensec;
896stat_ctime(
const struct stat *
st)
902#define HAVE_STAT_BIRTHTIME
903#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
904typedef struct stat statx_data;
906stat_birthtime(
const struct stat *
st)
908 const struct timespec *ts = &
st->st_birthtimespec;
912typedef struct stat statx_data;
913# define stat_birthtime stat_ctime
915# undef HAVE_STAT_BIRTHTIME
930rb_stat_atime(
VALUE self)
932 return stat_atime(get_stat(
self));
946rb_stat_mtime(
VALUE self)
948 return stat_mtime(get_stat(
self));
966rb_stat_ctime(
VALUE self)
968 return stat_ctime(get_stat(
self));
971#if defined(HAVE_STAT_BIRTHTIME)
997 return stat_birthtime(get_stat(
self));
1000# define rb_stat_birthtime rb_f_notimplement
1019rb_stat_inspect(
VALUE self)
1023 static const struct {
1027 {
"dev", rb_stat_dev},
1028 {
"ino", rb_stat_ino},
1029 {
"mode", rb_stat_mode},
1030 {
"nlink", rb_stat_nlink},
1031 {
"uid", rb_stat_uid},
1032 {
"gid", rb_stat_gid},
1033 {
"rdev", rb_stat_rdev},
1034 {
"size", rb_stat_size},
1035 {
"blksize", rb_stat_blksize},
1036 {
"blocks", rb_stat_blocks},
1037 {
"atime", rb_stat_atime},
1038 {
"mtime", rb_stat_mtime},
1039 {
"ctime", rb_stat_ctime},
1040#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
1055 for (
i = 0;
i <
sizeof(member)/
sizeof(member[0]);
i++) {
1063 v = (*member[
i].func)(
self);
1067 else if (
i == 0 ||
i == 6) {
1088no_gvl_fstat(
void *data)
1095fstat_without_gvl(
int fd,
struct stat *
st)
1106no_gvl_stat(
void * data)
1113stat_without_gvl(
const char *
path,
struct stat *
st)
1124#if !defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) && \
1125 defined(HAVE_STRUCT_STATX_STX_BTIME)
1128# ifdef HAVE_SYSCALL_H
1129# include <syscall.h>
1130# elif defined HAVE_SYS_SYSCALL_H
1131# include <sys/syscall.h>
1133# if defined __linux__
1134# include <linux/stat.h>
1136statx(
int dirfd,
const char *pathname,
int flags,
1137 unsigned int mask,
struct statx *statxbuf)
1139 return (
int)syscall(__NR_statx, dirfd, pathname, flags,
mask, statxbuf);
1144typedef struct no_gvl_statx_data {
1153io_blocking_statx(
void *data)
1155 no_gvl_statx_data *
arg = data;
1160no_gvl_statx(
void *data)
1162 return (
void *)io_blocking_statx(data);
1166statx_without_gvl(
const char *
path,
struct statx *stx,
unsigned int mask)
1176fstatx_without_gvl(
int fd,
struct statx *stx,
unsigned int mask)
1178 no_gvl_statx_data data = {stx, fd,
"", AT_EMPTY_PATH,
mask};
1185rb_statx(
VALUE file,
struct statx *stx,
unsigned int mask)
1194 result = fstatx_without_gvl(fptr->
fd, stx,
mask);
1206# define statx_has_birthtime(st) ((st)->stx_mask & STATX_BTIME)
1208NORETURN(
static void statx_notimplement(
const char *field_name));
1213statx_notimplement(
const char *field_name)
1216 "%s is unimplemented on this filesystem",
1221statx_birthtime(
const struct statx *stx,
VALUE fname)
1225 statx_notimplement(
"birthtime");
1230typedef struct statx statx_data;
1231# define HAVE_STAT_BIRTHTIME
1233#elif defined(HAVE_STAT_BIRTHTIME)
1234# define statx_without_gvl(path, st, mask) stat_without_gvl(path, st)
1235# define fstatx_without_gvl(fd, st, mask) fstat_without_gvl(fd, st)
1236# define statx_birthtime(st, fname) stat_birthtime(st)
1237# define statx_has_birthtime(st) 1
1238# define rb_statx(file, st, mask) rb_stat(file, st)
1240# define statx_has_birthtime(st) 0
1254 result = fstat_without_gvl(fptr->
fd,
st);
1319no_gvl_lstat(
void *
ptr)
1326lstat_without_gvl(
const char *
path,
struct stat *
st)
1365 return rb_file_s_stat(
klass, fname);
1399 return rb_io_stat(
obj);
1406#if defined(_WIN32) || !defined(HAVE_GETGROUPS)
1426 if (anum != -1 && anum != groups)
1437 while (--anum >= 0) {
1438 if (gary[anum] == gid) {
1451# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
1454#if defined(S_IXGRP) && !defined(_WIN32) && !defined(__CYGWIN__)
1455#define USE_GETEUID 1
1488 if (
st.st_uid == euid)
1490 else if (rb_group_member(
st.st_gid))
1493 if ((
int)(
st.st_mode & mode) == mode)
return 0;
1508nogvl_eaccess(
void *
ptr)
1530nogvl_access(
void *
ptr)
1580# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
1585 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1604# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
1609 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1628# define S_ISLNK(m) _S_ISLNK(m)
1631# define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
1634# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
1666# define S_ISSOCK(m) _S_ISSOCK(m)
1669# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
1672# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
1681 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1702# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
1704# define S_ISBLK(m) (0)
1711 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1730# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
1735 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1757 if (rb_stat(fname, &
st) < 0)
return Qfalse;
1770 const char *s =
"FileTest#";
1779 rb_warning(
"%sexists? is a deprecated name, use %sexist? instead", s, s);
1780 return rb_file_exist_p(
obj, fname);
1797 if (rb_eaccess(fname,
R_OK) < 0)
return Qfalse;
1815 if (rb_access(fname,
R_OK) < 0)
return Qfalse;
1820# define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
1824# define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
1849 if (rb_stat(fname, &
st) < 0)
return Qnil;
1871 if (rb_eaccess(fname,
W_OK) < 0)
return Qfalse;
1889 if (rb_access(fname,
W_OK) < 0)
return Qfalse;
1915 if (rb_stat(fname, &
st) < 0)
return Qnil;
1941 if (rb_eaccess(fname,
X_OK) < 0)
return Qfalse;
1963 if (rb_access(fname,
X_OK) < 0)
return Qfalse;
1968# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1988 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2008 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2009 if (
st.st_size == 0)
return Qtrue;
2028 if (rb_stat(fname, &
st) < 0)
return Qnil;
2029 if (
st.st_size == 0)
return Qnil;
2049 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2059 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2081 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2082 if (rb_group_member(
st.st_gid))
return Qtrue;
2087#if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
2089check3rdbyte(
VALUE fname,
int mode)
2093 if (rb_stat(fname, &
st) < 0)
return Qfalse;
2094 if (
st.st_mode & mode)
return Qtrue;
2112 return check3rdbyte(fname,
S_ISUID);
2131 return check3rdbyte(fname,
S_ISGID);
2150 return check3rdbyte(fname,
S_ISVTX);
2179 struct stat st1, st2;
2181 if (rb_stat(fname1, &st1) < 0)
return Qfalse;
2182 if (rb_stat(fname2, &st2) < 0)
return Qfalse;
2183 if (st1.st_dev != st2.st_dev)
return Qfalse;
2184 if (st1.st_ino != st2.st_ino)
return Qfalse;
2206 if (rb_stat(fname, &
st) < 0) {
2215rb_file_ftype(
const struct stat *
st)
2226 t =
"characterSpecial";
2281 return rb_file_ftype(&
st);
2301 if (rb_stat(fname, &
st) < 0) {
2306 return stat_atime(&
st);
2330 return stat_atime(&
st);
2350 if (rb_stat(fname, &
st) < 0) {
2355 return stat_mtime(&
st);
2378 return stat_mtime(&
st);
2402 if (rb_stat(fname, &
st) < 0) {
2407 return stat_ctime(&
st);
2433 return stat_ctime(&
st);
2450#if defined(HAVE_STAT_BIRTHTIME)
2456 if (rb_statx(fname, &
st, STATX_BTIME) < 0) {
2461 return statx_birthtime(&
st, fname);
2464# define rb_file_s_birthtime rb_f_notimplement
2467#if defined(HAVE_STAT_BIRTHTIME)
2487 if (fstatx_without_gvl(fptr->
fd, &
st, STATX_BTIME) == -1) {
2490 return statx_birthtime(&
st, fptr->
pathv);
2493# define rb_file_birthtime rb_f_notimplement
2523chmod_internal(
const char *
path,
void *mode)
2549 return apply2files(chmod_internal,
argc,
argv, &mode);
2570#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
2578 if (
fchmod(fptr->
fd, mode) == -1) {
2586#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
2596#if defined(HAVE_LCHMOD)
2598lchmod_internal(
const char *
path,
void *mode)
2621 return apply2files(lchmod_internal,
argc,
argv, &mode);
2624#define rb_file_s_lchmod rb_f_notimplement
2651chown_internal(
const char *
path,
void *
arg)
2681 return apply2files(chown_internal,
argc,
argv, &
arg);
2725#if defined(HAVE_LCHOWN)
2727lchown_internal(
const char *
path,
void *
arg)
2753 return apply2files(lchown_internal,
argc,
argv, &
arg);
2756#define rb_file_s_lchown rb_f_notimplement
2787 if (
NIL_P(a)) e[0] = m;
2807#if defined(HAVE_UTIMES)
2810utime_internal(
const char *
path,
void *
arg)
2816#if defined(HAVE_UTIMENSAT)
2817 static int try_utimensat = 1;
2818# ifdef AT_SYMLINK_NOFOLLOW
2819 static int try_utimensat_follow = 1;
2821 const int try_utimensat_follow = 0;
2825 if (
v->follow ? try_utimensat_follow : try_utimensat) {
2826# ifdef AT_SYMLINK_NOFOLLOW
2828 flags = AT_SYMLINK_NOFOLLOW;
2834# ifdef AT_SYMLINK_NOFOLLOW
2835 try_utimensat_follow = 0;
2849 tvbuf[0].tv_sec = tsp[0].
tv_sec;
2850 tvbuf[0].tv_usec = (
int)(tsp[0].tv_nsec / 1000);
2851 tvbuf[1].tv_sec = tsp[1].
tv_sec;
2852 tvbuf[1].tv_usec = (
int)(tsp[1].tv_nsec / 1000);
2856 if (
v->follow)
return lutimes(
path, tvp);
2858 return utimes(
path, tvp);
2863#if !defined HAVE_UTIME_H && !defined HAVE_SYS_UTIME_H
2871utime_internal(
const char *
path,
void *
arg)
2881 return utime(
path, utp);
2893 args.atime = *
argv++;
2894 args.mtime = *
argv++;
2896 args.follow = follow;
2898 if (!
NIL_P(args.atime) || !
NIL_P(args.mtime)) {
2901 if (args.atime == args.mtime)
2908 return apply2files(utime_internal,
argc,
argv, &args);
2928#if defined(HAVE_UTIMES) && (defined(HAVE_LUTIMES) || (defined(HAVE_UTIMENSAT) && defined(AT_SYMLINK_NOFOLLOW)))
2947#define rb_file_s_lutime rb_f_notimplement
2950#ifdef RUBY_FUNCTION_NAME_STRING
2951# define syserr_fail2(e, s1, s2) syserr_fail2_in(RUBY_FUNCTION_NAME_STRING, e, s1, s2)
2953# define syserr_fail2_in(func, e, s1, s2) syserr_fail2(e, s1, s2)
2955#define sys_fail2(s1, s2) syserr_fail2(errno, s1, s2)
2962 const int max_pathlen = MAX_PATH;
2975#ifdef RUBY_FUNCTION_NAME_STRING
2976 rb_syserr_fail_path_in(func, e,
str);
3009#define rb_file_s_link rb_f_notimplement
3039#define rb_file_s_symlink rb_f_notimplement
3061struct readlink_arg {
3068nogvl_readlink(
void *
ptr)
3070 struct readlink_arg *ra =
ptr;
3072 return (
void *)(
VALUE)
readlink(ra->path, ra->buf, ra->size);
3078 struct readlink_arg ra;
3118#define rb_file_s_readlink rb_f_notimplement
3122unlink_internal(
const char *
path,
void *
arg)
3146 return apply2files(unlink_internal,
argc,
argv, 0);
3155no_gvl_rename(
void *
ptr)
3184#if defined __CYGWIN__
3193 if (
chmod(ra.dst, 0666) == 0 &&
3195 rename(ra.src, ra.dst) == 0)
3199 syserr_fail2(e, from, to);
3242#if defined __CYGWIN__ || defined DOSISH
3244#define DOSISH_DRIVE_LETTER
3245#define FILE_ALT_SEPARATOR '\\'
3247#ifdef FILE_ALT_SEPARATOR
3248#define isdirsep(x) ((x) == '/' || (x) == FILE_ALT_SEPARATOR)
3250static const char file_alt_separator[] = {FILE_ALT_SEPARATOR,
'\0'};
3253#define isdirsep(x) ((x) == '/')
3265# define USE_NTFS_ADS 1
3267# define USE_NTFS_ADS 0
3272#define istrailinggarbage(x) ((x) == '.' || (x) == ' ')
3274#define istrailinggarbage(x) 0
3277# define isADS(x) ((x) == ':')
3282#define Next(p, e, enc) ((p) + rb_enc_mbclen((p), (e), (enc)))
3283#define Inc(p, e, enc) ((p) = Next((p), (e), (enc)))
3285#if defined(DOSISH_UNC)
3286#define has_unc(buf) (isdirsep((buf)[0]) && isdirsep((buf)[1]))
3288#define has_unc(buf) 0
3291#ifdef DOSISH_DRIVE_LETTER
3293has_drive_letter(
const char *
buf)
3308 char *drvcwd, *oldcwd;
3319 if (
chdir(drive) == 0) {
3337 if (has_drive_letter(p)) {
3349#ifdef DOSISH_DRIVE_LETTER
3350 if (
path + 2 <= end && has_drive_letter(
path))
path += 2;
3353 return (
char *)
path;
3356#define nextdirsep rb_enc_path_next
3366#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
3367#define skipprefix rb_enc_path_skip_prefix
3369#define skipprefix(path, end, enc) (path)
3374#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
3381 return (
char *)
path;
3384#ifdef DOSISH_DRIVE_LETTER
3385 if (has_drive_letter(
path))
3386 return (
char *)(
path + 2);
3389 return (
char *)
path;
3395#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
3400 return skiproot(
path, end, enc);
3404#define strrdirsep rb_enc_path_last_separator
3409 while (
path < end) {
3411 const char *tmp =
path++;
3413 if (
path >= end)
break;
3426 while (
path < end) {
3430 if (
path >= end)
return (
char *)
last;
3436 return (
char *)
path;
3443 return chompdirsep(
path, end, enc);
3460 if (
path >= end)
return (
char *)
last;
3467 return (
char *)
path;
3471#define BUFCHECK(cond) do {\
3474 do {buflen *= 2;} while (cond);\
3475 rb_str_resize(result, buflen);\
3476 buf = RSTRING_PTR(result);\
3478 pend = buf + buflen;\
3483 p = buf = RSTRING_PTR(result),\
3484 buflen = RSTRING_LEN(result),\
3488# define SKIPPATHSEP(p) ((*(p)) ? 1 : 0)
3490# define SKIPPATHSEP(p) 1
3493#define BUFCOPY(srcptr, srclen) do { \
3494 const int skip = SKIPPATHSEP(p); \
3495 rb_str_set_len(result, p-buf+skip); \
3496 BUFCHECK(bdiff + ((srclen)+skip) >= buflen); \
3498 memcpy(p, (srcptr), (srclen)); \
3502#define WITH_ROOTDIFF(stmt) do { \
3503 long rootdiff = root - buf; \
3505 root = buf + rootdiff; \
3509copy_home_path(
VALUE result,
const char *dir)
3512#if defined DOSISH || defined __CYGWIN__
3524#if defined DOSISH || defined __CYGWIN__
3526 for (bend = (p =
buf) + dirlen; p < bend;
Inc(p, bend, enc)) {
3539 struct passwd *pwPtr;
3542 const char *pwPtr = 0;
3543 # define endpwent() ((void)0)
3557 pwPtr = getpwnam(username);
3560 dir = pwPtr =
getenv(
"HOME");
3567 dir = pwPtr->pw_dir;
3569 copy_home_path(result, dir);
3578 const char *dir =
getenv(
"HOME");
3580#if defined HAVE_PWD_H
3596# if !defined(HAVE_GETPWUID_R) && !defined(HAVE_GETPWUID)
3601 if (
NIL_P(login_name)) {
3607 if (
NIL_P(pw_dir)) {
3609 if (
NIL_P(pw_dir)) {
3623 return copy_home_path(result, dir);
3629#if NORMALIZE_UTF8PATH
3641 char *
buf, *cwdp = dir;
3647 if (direnc != fsenc) {
3656 do {buflen *= 2;}
while (dirlen > buflen);
3663 return buf + dirlen;
3669 const char *s, *b, *fend;
3670 char *
buf, *p, *pend, *root;
3671 size_t buflen, bdiff;
3679 if (s[0] ==
'~' && abs_mode == 0) {
3681 if (
isdirsep(s[1]) || s[1] ==
'\0') {
3692 BUFCHECK(bdiff + userlen >= buflen);
3704 (
int)userlen, b, fname);
3713#ifdef DOSISH_DRIVE_LETTER
3715 else if (has_drive_letter(s)) {
3728 if (!
NIL_P(dname) && !not_same_drive(dname, s[0])) {
3737 char *e = append_fspath(result, fname, getcwdofdrv(*s), &enc, fsenc);
3745 p = chompdirsep(skiproot(
buf, p, enc), p, enc);
3751 if (!
NIL_P(dname)) {
3758 char *e = append_fspath(result, fname,
ruby_getcwd(), &enc, fsenc);
3762#if defined DOSISH || defined __CYGWIN__
3770 p = chompdirsep(skiproot(
buf, p, enc), p, enc);
3783 if (p >
buf && p[-1] ==
'/')
3806 if (*(s+1) ==
'\0' ||
isdirsep(*(s+1))) {
3825#if defined DOSISH || defined __CYGWIN__
3850#if defined DOSISH || defined __CYGWIN__
3862 int n = ignored_char_p(s, fend, enc);
3881 static const char prime[] =
":$DATA";
3882 enum {prime_len =
sizeof(prime) -1};
3886 if (s > b + prime_len &&
strncasecmp(s - prime_len, prime, prime_len) == 0) {
3889 if (
isADS(*(s - (prime_len+1)))) {
3892 else if (
memchr(b,
':', s - prime_len - b)) {
3901 if (p == skiproot(
buf, p + !!*p, enc) - 1) p++;
3910 WIN32_FIND_DATAW wfd;
3913#ifdef HAVE_CYGWIN_CONV_PATH
3914 char *w32buf =
NULL;
3915 const int flags = CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
3921 int lnk_added = 0, is_symlink = 0;
3932#ifdef HAVE_CYGWIN_CONV_PATH
3933 bufsize = cygwin_conv_path(flags,
path,
NULL, 0);
3936 if (lnk_added) bufsize += 4;
3938 if (cygwin_conv_path(flags,
path, w32buf, bufsize) == 0) {
3944 if (cygwin_conv_to_win32_path(
path, w32buf) == 0) {
3948 if (is_symlink && b == w32buf) {
3952 strlcat(w32buf,
".lnk", bufsize);
3968 MultiByteToWideChar(CP_UTF8, 0,
RSTRING_PTR(tmp), -1, wstr,
len);
3970 h = FindFirstFileW(wstr, &wfd);
3972 if (
h != INVALID_HANDLE_VALUE) {
3975 len = lstrlenW(wfd.cFileName);
3977 if (lnk_added &&
len > 4 &&
3978 wcscasecmp(wfd.cFileName +
len - 4,
L".lnk") == 0) {
3979 wfd.cFileName[
len -= 4] =
L'\0';
3986 len = WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen,
NULL, 0,
NULL,
NULL);
3987 if (tmp == result) {
3989 WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, p,
len + 1,
NULL,
NULL);
4016#define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, MAXPATHLEN + 2)
4025#define expand_path(fname, dname, abs_mode, long_name, result) \
4026 str_shrink(rb_file_expand_path_internal(fname, dname, abs_mode, long_name, result))
4028#define check_expand_path_args(fname, dname) \
4029 (((fname) = rb_get_path(fname)), \
4030 (void)(NIL_P(dname) ? (dname) : ((dname) = rb_get_path(dname))))
4033file_expand_path_1(
VALUE fname)
4152realpath_rec(
long *prefixlenp,
VALUE *resolvedp,
const char *unresolved,
VALUE fallback,
4155 const char *pend = unresolved +
strlen(unresolved);
4159 while (unresolved < pend) {
4160 const char *testname = unresolved;
4162 long testnamelen = unresolved_firstsep - unresolved;
4163 const char *unresolved_nextname = unresolved_firstsep;
4164 while (unresolved_nextname < pend &&
isdirsep(*unresolved_nextname))
4165 unresolved_nextname++;
4166 unresolved = unresolved_nextname;
4167 if (testnamelen == 1 && testname[0] ==
'.') {
4169 else if (testnamelen == 2 && testname[0] ==
'.' && testname[1] ==
'.') {
4171 const char *resolved_str =
RSTRING_PTR(*resolvedp);
4172 const char *resolved_names = resolved_str + *prefixlenp;
4174 long len = lastsep ? lastsep - resolved_names : 0;
4183#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
4184 if (*prefixlenp > 1 && *prefixlenp ==
RSTRING_LEN(testpath)) {
4192 if (!
NIL_P(checkval)) {
4193 if (checkval ==
ID2SYM(resolving)) {
4207 ret = lstat_without_gvl(
RSTRING_PTR(testpath), &sbuf);
4211 if (stat_without_gvl(
RSTRING_PTR(fallback), &sbuf) == 0) {
4220 *resolvedp = testpath;
4231 const char *link_prefix, *link_names;
4232 long link_prefixlen;
4237 link_prefixlen = link_names - link_prefix;
4238 if (link_prefixlen > 0) {
4245 *prefixlenp = link_prefixlen;
4247 if (realpath_rec(prefixlenp, resolvedp, link_names, testpath,
4248 loopcheck, mode, !*unresolved_firstsep))
4258 *resolvedp = testpath;
4271 VALUE unresolved_path;
4276 char *path_names =
NULL, *basedir_names =
NULL, *curdir_names =
NULL;
4277 char *
ptr, *prefixptr =
NULL, *pend;
4282 if (!
NIL_P(basedir)) {
4288 unresolved_path =
TO_OSPATH(unresolved_path);
4291 if (
ptr != path_names) {
4296 if (!
NIL_P(basedir)) {
4299 if (
ptr != basedir_names) {
4312 pend = prefixptr + prefixlen;
4313 ptr = chompdirsep(prefixptr, pend, enc);
4315 prefixlen = ++
ptr - prefixptr;
4318#ifdef FILE_ALT_SEPARATOR
4319 while (prefixptr <
ptr) {
4320 if (*prefixptr == FILE_ALT_SEPARATOR) {
4323 Inc(prefixptr, pend, enc);
4335 if (realpath_rec(&prefixlen, &resolved, curdir_names,
Qnil, loopcheck, mode, 0))
4338 if (basedir_names) {
4339 if (realpath_rec(&prefixlen, &resolved, basedir_names,
Qnil, loopcheck, mode, 0))
4342 if (realpath_rec(&prefixlen, &resolved, path_names,
Qnil, loopcheck, mode, 1))
4345 if (origenc && origenc !=
rb_enc_get(resolved)) {
4365 VALUE unresolved_path;
4366 char *resolved_ptr =
NULL;
4371 return rb_check_realpath_emulate(basedir,
path, origenc, mode);
4376 unresolved_path = rb_file_join(
rb_assoc_new(basedir, unresolved_path));
4378 if (origenc) unresolved_path =
TO_OSPATH(unresolved_path);
4387 (
errno ==
ENOENT && rb_file_exist_p(0, unresolved_path))) {
4388 return rb_check_realpath_emulate(basedir,
path, origenc, mode);
4408 if (origenc && origenc !=
rb_enc_get(resolved)) {
4425 return rb_check_realpath_emulate(basedir,
path, origenc, mode);
4487rmext(
const char *p,
long l0,
long l1,
const char *e,
long l2,
rb_encoding *enc)
4491 const char *s, *
last;
4493 if (!e || !l2)
return 0;
4496 if (
rb_enc_ascget(e + len1, e + l2, &len2, enc) ==
'*' && len1 + len2 == l2) {
4497 if (c ==
'.')
return l0;
4507 if (l1 < l2)
return l1;
4511#if CASEFOLD_FILESYSTEM
4512#define fncomp strncasecmp
4514#define fncomp strncmp
4516 if (
fncomp(s, e, l2) == 0) {
4525 const char *p, *q, *e, *end;
4526#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
4533#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
4541#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
4545#ifdef DOSISH_DRIVE_LETTER
4546 else if (*p ==
':') {
4566 n = ntfs_tail(p, end, enc) - p;
4568 n = chompdirsep(p, end, enc) - p;
4570 for (q = p; q - p <
n && *q ==
'.'; q++);
4571 for (e = 0; q - p <
n;
Inc(q, end, enc)) {
4572 if (*q ==
'.') e = q;
4606 const char *
name, *p;
4614 enc = check_path_encoding(fext);
4668 const char *
name, *root, *p, *end;
4676 root = skiproot(
name, end, enc);
4681 if (root >
name + 1)
4690#ifdef DOSISH_DRIVE_LETTER
4692 const char *
top = skiproot(
name + 2, end, enc);
4699#ifdef DOSISH_DRIVE_LETTER
4700 if (has_drive_letter(
name) && root ==
name + 2 && p -
name == 2)
4731 while (*p && *p ==
'.') p++;
4735 const char *
last = p++, *dot =
last;
4737 if (*p ==
'.') dot = p;
4740 if (!*p ||
isADS(*p)) {
4744 if (*
last ==
'.' || dot >
last) e = dot;
4751 else if (
isADS(*p)) {
4762 if (!e || e ==
name)
4801 const char *
name, *e;
4854 return rb_file_join(
arg);
4858rb_file_join(
VALUE ary)
4862 const char *
name, *tail;
4872 check_path_encoding(tmp);
4886 if (!checked) check_path_encoding(tmp);
4937 return rb_file_join(args);
4940#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE)
4941struct truncate_arg {
4943#if defined(HAVE_TRUNCATE)
4944#define NUM2POS(n) NUM2OFFT(n)
4947#define NUM2POS(n) NUM2LONG(n)
4953nogvl_truncate(
void *
ptr)
4955 struct truncate_arg *ta =
ptr;
4965 if (chsize(tmpfd, ta->pos) < 0) {
4995 struct truncate_arg ta;
4998 ta.pos = NUM2POS(
len);
5011#define rb_file_s_truncate rb_f_notimplement
5014#if defined(HAVE_FTRUNCATE) || defined(HAVE_CHSIZE)
5015struct ftruncate_arg {
5017#if defined(HAVE_FTRUNCATE)
5018#define NUM2POS(n) NUM2OFFT(n)
5021#define NUM2POS(n) NUM2LONG(n)
5027nogvl_ftruncate(
void *
ptr)
5029 struct ftruncate_arg *fa =
ptr;
5031#ifdef HAVE_FTRUNCATE
5034 return (
VALUE)chsize(fa->fd, fa->pos);
5056 struct ftruncate_arg fa;
5058 fa.pos = NUM2POS(
len);
5072#define rb_file_truncate rb_f_notimplement
5089#include <winerror.h>
5093rb_thread_flock(
void *data)
5096 int old_errno =
errno;
5098 int *op = data, ret =
flock(op[0], op[1]);
5101 if (GetLastError() == ERROR_NOT_LOCKED) {
5160 op[1] = op1 =
NUM2INT(operation);
5172#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
5178 time.tv_usec = 100 * 1000;
5184#if defined(ERESTART)
5203 for (
i=1;
i<
n;
i++) {
5210#define CHECK(n) test_check((n), argc, argv)
5287 if (
strchr(
"bcdefgGkloOprRsSuwWxXz", cmd)) {
5291 return rb_file_blockdev_p(0,
argv[1]);
5294 return rb_file_chardev_p(0,
argv[1]);
5300 return rb_file_exist_p(0,
argv[1]);
5303 return rb_file_file_p(0,
argv[1]);
5306 return rb_file_sgid_p(0,
argv[1]);
5309 return rb_file_grpowned_p(0,
argv[1]);
5312 return rb_file_sticky_p(0,
argv[1]);
5315 return rb_file_symlink_p(0,
argv[1]);
5318 return rb_file_owned_p(0,
argv[1]);
5321 return rb_file_rowned_p(0,
argv[1]);
5324 return rb_file_pipe_p(0,
argv[1]);
5327 return rb_file_readable_p(0,
argv[1]);
5330 return rb_file_readable_real_p(0,
argv[1]);
5333 return rb_file_size_p(0,
argv[1]);
5336 return rb_file_socket_p(0,
argv[1]);
5339 return rb_file_suid_p(0,
argv[1]);
5342 return rb_file_writable_p(0,
argv[1]);
5345 return rb_file_writable_real_p(0,
argv[1]);
5348 return rb_file_executable_p(0,
argv[1]);
5351 return rb_file_executable_real_p(0,
argv[1]);
5354 return rb_file_zero_p(0,
argv[1]);
5358 if (
strchr(
"MAC", cmd)) {
5363 if (rb_stat(fname, &
st) == -1) {
5371 return stat_atime(&
st);
5373 return stat_mtime(&
st);
5375 return stat_ctime(&
st);
5381 return rb_file_identical_p(0,
argv[1],
argv[2]);
5384 if (
strchr(
"=<>", cmd)) {
5385 struct stat st1, st2;
5389 if (rb_stat(
argv[1], &st1) < 0)
return Qfalse;
5390 if (rb_stat(
argv[2], &st2) < 0)
return Qfalse;
5392 t1 = stat_mtimespec(&st1);
5393 t2 = stat_mtimespec(&st2);
5430 return stat_new_0(
klass, 0);
5500 return rb_file_ftype(get_stat(
obj));
5696 if (rb_stat_owned(
obj))
5700 if (rb_stat_grpowned(
obj))
5729 if (rb_stat_rowned(
obj))
5733 if (rb_group_member(get_stat(
obj)->
st_gid))
5789 if (rb_stat_owned(
obj))
5793 if (rb_stat_grpowned(
obj))
5822 if (rb_stat_rowned(
obj))
5826 if (rb_group_member(get_stat(
obj)->
st_gid))
5886 if (rb_stat_owned(
obj))
5890 if (rb_stat_grpowned(
obj))
5918 if (rb_stat_rowned(
obj))
5922 if (rb_group_member(get_stat(
obj)->
st_gid))
6048#if !defined HAVE_MKFIFO && defined HAVE_MKNOD && defined S_IFIFO
6049#define mkfifo(path, mode) mknod(path, (mode)&~S_IFMT|S_IFIFO, 0)
6060nogvl_mkfifo(
void *
ptr)
6062 struct mkfifo_arg *ma =
ptr;
6081 struct mkfifo_arg ma;
6098#define rb_file_s_mkfifo rb_f_notimplement
6101static VALUE rb_mFConst;
6112#ifdef DOSISH_DRIVE_LETTER
6119 if (
path[0] ==
'/')
return 1;
6124#ifndef ENABLE_PATH_CHECK
6125# if defined DOSISH || defined __CYGWIN__
6126# define ENABLE_PATH_CHECK 0
6128# define ENABLE_PATH_CHECK 1
6132#if ENABLE_PATH_CHECK
6162 && !(p && execpath && (
st.st_mode &
S_ISVTX))
6165 rb_enc_warn(enc,
"Insecure world writable dir %s in %sPATH, mode 0%"
6167 p0, (execpath ?
"" :
"LOAD_"),
st.st_mode);
6174 if (!s || s == p0)
return 1;
6182#if ENABLE_PATH_CHECK
6183#define fpath_check(path) path_check_0((path), FALSE)
6185#define fpath_check(path) 1
6191#if ENABLE_PATH_CHECK
6192 const char *p0, *p, *pend;
6195 if (!
path)
return 1;
6207 if (p0 > pend)
break;
6250 int mode = (O_RDONLY |
6251#if defined O_NONBLOCK
6253#elif defined O_NDELAY
6258 if (fd == -1)
return 0;
6267is_explicit_relative(
const char *
path)
6269 if (*
path++ !=
'.')
return 0;
6286 rb_warn(
"rb_find_file_ext_safe will be removed in Ruby 3.0");
6294 VALUE fname = *filep, load_path, tmp;
6298 if (!ext[0])
return 0;
6301 fname = file_expand_path_1(fname);
6308 if (!expanded) fname = file_expand_path_1(fname);
6310 for (
i=0; ext[
i];
i++) {
6313 *filep = copy_path_class(fname, *filep);
6322 if (!load_path)
return 0;
6329 for (j=0; ext[j]; j++) {
6338 *filep = copy_path_class(tmp, *filep);
6352 rb_warn(
"rb_find_file_safe will be removed in Ruby 3.0");
6359 VALUE tmp, load_path;
6364 tmp = file_expand_path_1(
path);
6373 path = copy_path_class(file_expand_path_1(
path),
path);
6400 return copy_path_class(tmp,
path);
6413#elif defined AMIGA || defined __amigaos__
6464 define_filetest_function(
"exist?", rb_file_exist_p, 1);
6465 define_filetest_function(
"exists?", rb_file_exists_p, 1);
6466 define_filetest_function(
"readable?", rb_file_readable_p, 1);
6467 define_filetest_function(
"readable_real?", rb_file_readable_real_p, 1);
6468 define_filetest_function(
"world_readable?", rb_file_world_readable_p, 1);
6469 define_filetest_function(
"writable?", rb_file_writable_p, 1);
6470 define_filetest_function(
"writable_real?", rb_file_writable_real_p, 1);
6471 define_filetest_function(
"world_writable?", rb_file_world_writable_p, 1);
6472 define_filetest_function(
"executable?", rb_file_executable_p, 1);
6473 define_filetest_function(
"executable_real?", rb_file_executable_real_p, 1);
6474 define_filetest_function(
"file?", rb_file_file_p, 1);
6475 define_filetest_function(
"zero?", rb_file_zero_p, 1);
6476 define_filetest_function(
"empty?", rb_file_zero_p, 1);
6477 define_filetest_function(
"size?", rb_file_size_p, 1);
6478 define_filetest_function(
"size", rb_file_s_size, 1);
6479 define_filetest_function(
"owned?", rb_file_owned_p, 1);
6480 define_filetest_function(
"grpowned?", rb_file_grpowned_p, 1);
6482 define_filetest_function(
"pipe?", rb_file_pipe_p, 1);
6483 define_filetest_function(
"symlink?", rb_file_symlink_p, 1);
6484 define_filetest_function(
"socket?", rb_file_socket_p, 1);
6486 define_filetest_function(
"blockdev?", rb_file_blockdev_p, 1);
6487 define_filetest_function(
"chardev?", rb_file_chardev_p, 1);
6489 define_filetest_function(
"setuid?", rb_file_suid_p, 1);
6490 define_filetest_function(
"setgid?", rb_file_sgid_p, 1);
6491 define_filetest_function(
"sticky?", rb_file_sticky_p, 1);
6493 define_filetest_function(
"identical?", rb_file_identical_p, 2);
6591#if defined(O_NDELAY) || defined(O_NONBLOCK)
6593# define O_NONBLOCK O_NDELAY
6609#ifndef O_SHARE_DELETE
6610# 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::@136 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)