FileTest implements file test operations similar to those used
in File::Stat. It exists as a standalone module, and its
methods are also insinuated into the File class. (Note that
this is not done by inclusion: the interpreter cheats).
Returns true if the named file is a block device.
static VALUE
test_b(obj, fname)
VALUE obj, fname;
{
#ifndef S_ISBLK
# ifdef S_IFBLK
# define S_ISBLK(m) ((m & S_IFMT) == S_IFBLK)
# else
# define S_ISBLK(m) (0) /* anytime false */
# endif
#endif
#ifdef S_ISBLK
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISBLK(st.st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns true if the named file is a character device.
static VALUE
test_c(obj, fname)
VALUE obj, fname;
{
#ifndef S_ISCHR
# define S_ISCHR(m) ((m & S_IFMT) == S_IFCHR)
#endif
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISCHR(st.st_mode)) return Qtrue;
return Qfalse;
}
Returns true if the named file is a directory,
false otherwise.
File.directory?(".")
static VALUE
test_d(obj, fname)
VALUE obj, fname;
{
#ifndef S_ISDIR
# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
#endif
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISDIR(st.st_mode)) return Qtrue;
return Qfalse;
}
Returns true if the named file is executable by the effective
user id of this process.
static VALUE
test_x(obj, fname)
VALUE obj, fname;
{
SafeStringValue(fname);
if (eaccess(StringValueCStr(fname), X_OK) < 0) return Qfalse;
return Qtrue;
}
Returns true if the named file is executable by the real user
id of this process.
static VALUE
test_X(obj, fname)
VALUE obj, fname;
{
SafeStringValue(fname);
if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse;
return Qtrue;
}
Return true if the named file exists.
static VALUE
test_e(obj, fname)
VALUE obj, fname;
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
return Qtrue;
}
Return true if the named file exists.
static VALUE
test_e(obj, fname)
VALUE obj, fname;
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
return Qtrue;
}
Returns true if the named file exists and is a regular file.
static VALUE
test_f(obj, fname)
VALUE obj, fname;
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISREG(st.st_mode)) return Qtrue;
return Qfalse;
}
Returns true if the named file exists and the effective group
id of the calling process is the owner of the file. Returns
false on Windows.
static VALUE
test_grpowned(obj, fname)
VALUE obj, fname;
{
#ifndef _WIN32
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (group_member(st.st_gid)) return Qtrue;
#endif
return Qfalse;
}
Returns true if the named files are identical.
open("a", "w") {} p File.identical?("a", "a") #=> true p File.identical?("a", "./a") #=> true File.link("a", "b") p File.identical?("a", "b") #=> true File.symlink("a", "c") p File.identical?("a", "c") #=> true open("d", "w") {} p File.identical?("a", "d") #=> false
static VALUE
test_identical(obj, fname1, fname2)
VALUE obj, fname1, fname2;
{
#ifndef DOSISH
struct stat st1, st2;
if (rb_stat(fname1, &st1) < 0) return Qfalse;
if (rb_stat(fname2, &st2) < 0) return Qfalse;
if (st1.st_dev != st2.st_dev) return Qfalse;
if (st1.st_ino != st2.st_ino) return Qfalse;
#else
#ifdef _WIN32
BY_HANDLE_FILE_INFORMATION st1, st2;
HANDLE f1 = 0, f2 = 0;
#endif
rb_secure(2);
#ifdef _WIN32
f1 = w32_io_info(&fname1, &st1);
if (f1 == INVALID_HANDLE_VALUE) return Qfalse;
f2 = w32_io_info(&fname2, &st2);
if (f1) CloseHandle(f1);
if (f2 == INVALID_HANDLE_VALUE) return Qfalse;
if (f2) CloseHandle(f2);
if (st1.dwVolumeSerialNumber == st2.dwVolumeSerialNumber &&
st1.nFileIndexHigh == st2.nFileIndexHigh &&
st1.nFileIndexLow == st2.nFileIndexLow)
return Qtrue;
if (!f1 || !f2) return Qfalse;
if (rb_w32_iswin95()) return Qfalse;
#else
SafeStringValue(fname1);
fname1 = rb_str_new4(fname1);
SafeStringValue(fname2);
if (access(RSTRING(fname1)->ptr, 0)) return Qfalse;
if (access(RSTRING(fname2)->ptr, 0)) return Qfalse;
#endif
fname1 = rb_file_expand_path(fname1, Qnil);
fname2 = rb_file_expand_path(fname2, Qnil);
if (RSTRING(fname1)->len != RSTRING(fname2)->len) return Qfalse;
if (rb_memcicmp(RSTRING(fname1)->ptr, RSTRING(fname2)->ptr, RSTRING(fname1)->len))
return Qfalse;
#endif
return Qtrue;
}
Returns true if the named file exists and the effective used
id of the calling process is the owner of the file.
static VALUE
test_owned(obj, fname)
VALUE obj, fname;
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (st.st_uid == geteuid()) return Qtrue;
return Qfalse;
}
Returns true if the named file is a pipe.
static VALUE
test_p(obj, fname)
VALUE obj, fname;
{
#ifdef S_IFIFO
# ifndef S_ISFIFO
# define S_ISFIFO(m) ((m & S_IFMT) == S_IFIFO)
# endif
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISFIFO(st.st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns true if the named file is readable by the effective
user id of this process.
static VALUE
test_r(obj, fname)
VALUE obj, fname;
{
SafeStringValue(fname);
if (eaccess(StringValueCStr(fname), R_OK) < 0) return Qfalse;
return Qtrue;
}
Returns true if the named file is readable by the real user id
of this process.
static VALUE
test_R(obj, fname)
VALUE obj, fname;
{
SafeStringValue(fname);
if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse;
return Qtrue;
}
Returns true if the named file has the setgid bit set.
static VALUE
test_sgid(obj, fname)
VALUE obj, fname;
{
#ifdef S_ISGID
return check3rdbyte(fname, S_ISGID);
#else
return Qfalse;
#endif
}
Returns true if the named file has the setuid bit set.
static VALUE
test_suid(obj, fname)
VALUE obj, fname;
{
#ifdef S_ISUID
return check3rdbyte(fname, S_ISUID);
#else
return Qfalse;
#endif
}
Returns the size of file_name.
static VALUE
rb_file_s_size(klass, fname)
VALUE klass, fname;
{
struct stat st;
if (rb_stat(fname, &st) < 0)
rb_sys_fail(StringValueCStr(fname));
return OFFT2NUM(st.st_size);
}
Returns nil if file_name doesn't exist or has
zero size, the size of the file otherwise.
static VALUE
test_s(obj, fname)
VALUE obj, fname;
{
struct stat st;
if (rb_stat(fname, &st) < 0) return Qnil;
if (st.st_size == 0) return Qnil;
return OFFT2NUM(st.st_size);
}
Returns true if the named file is a socket.
static VALUE
test_S(obj, fname)
VALUE obj, fname;
{
#ifndef S_ISSOCK
# ifdef _S_ISSOCK
# define S_ISSOCK(m) _S_ISSOCK(m)
# elif defined __BORLANDC__
# ifdef _S_IFSOCK
# define S_ISSOCK(m) (((unsigned short)(m) & S_IFMT) == _S_IFSOCK)
# else
# ifdef S_IFSOCK
# define S_ISSOCK(m) (((unsigned short)(m) & S_IFMT) == S_IFSOCK)
# endif
# endif
# else
# ifdef _S_IFSOCK
# define S_ISSOCK(m) ((m & S_IFMT) == _S_IFSOCK)
# else
# ifdef S_IFSOCK
# define S_ISSOCK(m) ((m & S_IFMT) == S_IFSOCK)
# endif
# endif
# endif
#endif
#ifdef S_ISSOCK
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISSOCK(st.st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns true if the named file has the sticky bit set.
static VALUE
test_sticky(obj, fname)
VALUE obj, fname;
{
#ifdef S_ISVTX
return check3rdbyte(fname, S_ISVTX);
#else
return Qnil;
#endif
}
Returns true if the named file is a symbolic link.
static VALUE
test_l(obj, fname)
VALUE obj, fname;
{
#ifndef S_ISLNK
# ifdef _S_ISLNK
# define S_ISLNK(m) _S_ISLNK(m)
# elif defined __BORLANDC__
# ifdef _S_IFLNK
# define S_ISLNK(m) (((unsigned short)(m) & S_IFMT) == _S_IFLNK)
# else
# ifdef S_IFLNK
# define S_ISLNK(m) (((unsigned short)(m) & S_IFMT) == S_IFLNK)
# endif
# endif
# else
# ifdef _S_IFLNK
# define S_ISLNK(m) ((m & S_IFMT) == _S_IFLNK)
# else
# ifdef S_IFLNK
# define S_ISLNK(m) ((m & S_IFMT) == S_IFLNK)
# endif
# endif
# endif
#endif
#ifdef S_ISLNK
struct stat st;
SafeStringValue(fname);
if (lstat(StringValueCStr(fname), &st) < 0) return Qfalse;
if (S_ISLNK(st.st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns true if the named file is writable by the effective
user id of this process.
static VALUE
test_w(obj, fname)
VALUE obj, fname;
{
SafeStringValue(fname);
if (eaccess(StringValueCStr(fname), W_OK) < 0) return Qfalse;
return Qtrue;
}