Objects of class File::Stat encapsulate common status
information for File objects. The information is recorded at
the moment the File::Stat object is created; changes made to
the file after that point will not be reflected. File::Stat
objects are returned by IO#stat, File::stat,
File#lstat, and File::lstat. Many of these
methods return platform-specific values, and not all values are meaningful
on all systems. See also Kernel#test.
Create a File::Stat object for the given file name (raising an exception if the file doesn't exist).
static VALUE
rb_stat_init(obj, fname)
VALUE obj, fname;
{
struct stat st, *nst;
SafeStringValue(fname);
if (stat(StringValueCStr(fname), &st) == -1) {
rb_sys_fail(RSTRING(fname)->ptr);
}
if (DATA_PTR(obj)) {
free(DATA_PTR(obj));
DATA_PTR(obj) = NULL;
}
nst = ALLOC(struct stat);
*nst = st;
DATA_PTR(obj) = nst;
return Qnil;
}
Compares File::Stat objects by comparing their respective
modification times.
f1 = File.new("f1", "w") sleep 1 f2 = File.new("f2", "w") f1.stat <=> f2.stat #=> -1
static VALUE
rb_stat_cmp(self, other)
VALUE self, other;
{
if (rb_obj_is_kind_of(other, rb_obj_class(self))) {
time_t t1 = get_stat(self)->st_mtime;
time_t t2 = get_stat(other)->st_mtime;
if (t1 == t2)
return INT2FIX(0);
else if (t1 < t2)
return INT2FIX(-1);
else
return INT2FIX(1);
}
return Qnil;
}
Returns the last access time for this file as an object of class
Time.
File.stat("testfile").atime #=> Wed Dec 31 18:00:00 CST 1969
static VALUE
rb_stat_atime(self)
VALUE self;
{
return rb_time_new(get_stat(self)->st_atime, 0);
}
Returns the native file system's block size. Will return
nil on platforms that don't support this information.
File.stat("testfile").blksize #=> 4096
static VALUE
rb_stat_blksize(self)
VALUE self;
{
#ifdef HAVE_ST_BLKSIZE
return ULONG2NUM(get_stat(self)->st_blksize);
#else
return Qnil;
#endif
}
Returns true if the file is a block device, false
if it isn't or if the operating system doesn't support this
feature.
File.stat("testfile").blockdev? #=> false File.stat("/dev/hda1").blockdev? #=> true
static VALUE
rb_stat_b(obj)
VALUE obj;
{
#ifdef S_ISBLK
if (S_ISBLK(get_stat(obj)->st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns the number of native file system blocks allocated for this file, or
nil if the operating system doesn't support this feature.
File.stat("testfile").blocks #=> 2
static VALUE
rb_stat_blocks(self)
VALUE self;
{
#ifdef HAVE_ST_BLOCKS
return ULONG2NUM(get_stat(self)->st_blocks);
#else
return Qnil;
#endif
}
Returns true if the file is a character device,
false if it isn't or if the operating system doesn't
support this feature.
File.stat("/dev/tty").chardev? #=> true
static VALUE
rb_stat_c(obj)
VALUE obj;
{
if (S_ISCHR(get_stat(obj)->st_mode)) return Qtrue;
return Qfalse;
}
Returns the change time for stat (that is, the time directory information about the file was changed, not the file itself).
File.stat("testfile").ctime #=> Wed Apr 09 08:53:14 CDT 2003
static VALUE
rb_stat_ctime(self)
VALUE self;
{
return rb_time_new(get_stat(self)->st_ctime, 0);
}
Returns an integer representing the device on which stat resides.
File.stat("testfile").dev #=> 774
static VALUE
rb_stat_dev(self)
VALUE self;
{
return INT2NUM(get_stat(self)->st_dev);
}
Returns the major part of File_Stat#dev or nil.
File.stat("/dev/fd1").dev_major #=> 2 File.stat("/dev/tty").dev_major #=> 5
static VALUE
rb_stat_dev_major(self)
VALUE self;
{
#if defined(major)
long dev = get_stat(self)->st_dev;
return ULONG2NUM(major(dev));
#else
return Qnil;
#endif
}
Returns the minor part of File_Stat#dev or nil.
File.stat("/dev/fd1").dev_minor #=> 1 File.stat("/dev/tty").dev_minor #=> 0
static VALUE
rb_stat_dev_minor(self)
VALUE self;
{
#if defined(minor)
long dev = get_stat(self)->st_dev;
return ULONG2NUM(minor(dev));
#else
return Qnil;
#endif
}
Returns true if stat is a directory,
false otherwise.
File.stat("testfile").directory? #=> false File.stat(".").directory? #=> true
static VALUE
rb_stat_d(obj)
VALUE obj;
{
if (S_ISDIR(get_stat(obj)->st_mode)) return Qtrue;
return Qfalse;
}
Returns true if stat is executable or if the
operating system doesn't distinguish executable files from
nonexecutable files. The tests are made using the effective owner of the
process.
File.stat("testfile").executable? #=> false
static VALUE
rb_stat_x(obj)
VALUE obj;
{
struct stat *st = get_stat(obj);
#ifdef USE_GETEUID
if (geteuid() == 0) {
return st->st_mode & S_IXUGO ? Qtrue : Qfalse;
}
#endif
#ifdef S_IXUSR
if (rb_stat_owned(obj))
return st->st_mode & S_IXUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IXGRP
if (rb_stat_grpowned(obj))
return st->st_mode & S_IXGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IXOTH
if (!(st->st_mode & S_IXOTH)) return Qfalse;
#endif
return Qtrue;
}
Same as executable?, but tests using the real owner of the
process.
static VALUE
rb_stat_X(obj)
VALUE obj;
{
struct stat *st = get_stat(obj);
#ifdef USE_GETEUID
if (getuid() == 0) {
return st->st_mode & S_IXUGO ? Qtrue : Qfalse;
}
#endif
#ifdef S_IXUSR
if (rb_stat_rowned(obj))
return st->st_mode & S_IXUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IXGRP
if (group_member(get_stat(obj)->st_gid))
return st->st_mode & S_IXGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IXOTH
if (!(st->st_mode & S_IXOTH)) return Qfalse;
#endif
return Qtrue;
}
Returns true if stat is a regular file (not a device
file, pipe, socket, etc.).
File.stat("testfile").file? #=> true
static VALUE
rb_stat_f(obj)
VALUE obj;
{
if (S_ISREG(get_stat(obj)->st_mode)) return Qtrue;
return Qfalse;
}
Identifies the type of stat. The return string is one of:
“file'', “directory'',
“characterSpecial'',
“blockSpecial'', “fifo'',
“link'', “socket'', or
“unknown''.
File.stat("/dev/tty").ftype #=> "characterSpecial"
static VALUE
rb_stat_ftype(obj)
VALUE obj;
{
return rb_file_ftype(get_stat(obj));
}
Returns the numeric group id of the owner of stat.
File.stat("testfile").gid #=> 500
static VALUE
rb_stat_gid(self)
VALUE self;
{
return UINT2NUM(get_stat(self)->st_gid);
}
Returns true if the effective group id of the process is the same as the
group id of stat. On Windows NT, returns false.
File.stat("testfile").grpowned? #=> true File.stat("/etc/passwd").grpowned? #=> false
static VALUE
rb_stat_grpowned(obj)
VALUE obj;
{
#ifndef _WIN32
if (group_member(get_stat(obj)->st_gid)) return Qtrue;
#endif
return Qfalse;
}
Returns the inode number for stat.
File.stat("testfile").ino #=> 1083669
static VALUE
rb_stat_ino(self)
VALUE self;
{
#ifdef HUGE_ST_INO
return ULL2NUM(get_stat(self)->st_ino);
#else
return ULONG2NUM(get_stat(self)->st_ino);
#endif
}
Produce a nicely formatted description of stat.
File.stat("/etc/passwd").inspect
#=> "#<File::Stat dev=0xe000005, ino=1078078, mode=0100644,
nlink=1, uid=0, gid=0, rdev=0x0, size=1374, blksize=4096,
blocks=8, atime=Wed Dec 10 10:16:12 CST 2003,
mtime=Fri Sep 12 15:41:41 CDT 2003,
ctime=Mon Oct 27 11:20:27 CST 2003>"
static VALUE
rb_stat_inspect(self)
VALUE self;
{
VALUE str;
int i;
static const struct {
const char *name;
VALUE (*func)_((VALUE));
} member[] = {
{"dev", rb_stat_dev},
{"ino", rb_stat_ino},
{"mode", rb_stat_mode},
{"nlink", rb_stat_nlink},
{"uid", rb_stat_uid},
{"gid", rb_stat_gid},
{"rdev", rb_stat_rdev},
{"size", rb_stat_size},
{"blksize", rb_stat_blksize},
{"blocks", rb_stat_blocks},
{"atime", rb_stat_atime},
{"mtime", rb_stat_mtime},
{"ctime", rb_stat_ctime},
};
str = rb_str_buf_new2("#<");
rb_str_buf_cat2(str, rb_obj_classname(self));
rb_str_buf_cat2(str, " ");
for (i = 0; i < sizeof(member)/sizeof(member[0]); i++) {
VALUE v;
if (i > 0) {
rb_str_buf_cat2(str, ", ");
}
rb_str_buf_cat2(str, member[i].name);
rb_str_buf_cat2(str, "=");
v = (*member[i].func)(self);
if (i == 2) { /* mode */
char buf[32];
sprintf(buf, "0%lo", NUM2ULONG(v));
rb_str_buf_cat2(str, buf);
}
else if (i == 0 || i == 6) { /* dev/rdev */
char buf[32];
sprintf(buf, "0x%lx", NUM2ULONG(v));
rb_str_buf_cat2(str, buf);
}
else {
rb_str_append(str, rb_inspect(v));
}
}
rb_str_buf_cat2(str, ">");
OBJ_INFECT(str, self);
return str;
}
Returns an integer representing the permission bits of stat. The
meaning of the bits is platform dependent; on Unix systems, see
stat(2).
File.chmod(0644, "testfile") #=> 1 s = File.stat("testfile") sprintf("%o", s.mode) #=> "100644"
static VALUE
rb_stat_mode(self)
VALUE self;
{
#ifdef __BORLANDC__
return UINT2NUM((unsigned short)(get_stat(self)->st_mode));
#else
return UINT2NUM(get_stat(self)->st_mode);
#endif
}
Returns the modification time of stat.
File.stat("testfile").mtime #=> Wed Apr 09 08:53:14 CDT 2003
static VALUE
rb_stat_mtime(self)
VALUE self;
{
return rb_time_new(get_stat(self)->st_mtime, 0);
}
Returns the number of hard links to stat.
File.stat("testfile").nlink #=> 1 File.link("testfile", "testfile.bak") #=> 0 File.stat("testfile").nlink #=> 2
static VALUE
rb_stat_nlink(self)
VALUE self;
{
return UINT2NUM(get_stat(self)->st_nlink);
}
Returns true if the effective user id of the process is the
same as the owner of stat.
File.stat("testfile").owned? #=> true File.stat("/etc/passwd").owned? #=> false
static VALUE
rb_stat_owned(obj)
VALUE obj;
{
if (get_stat(obj)->st_uid == geteuid()) return Qtrue;
return Qfalse;
}
Returns true if the operating system supports pipes and
stat is a pipe; false otherwise.
static VALUE
rb_stat_p(obj)
VALUE obj;
{
#ifdef S_IFIFO
if (S_ISFIFO(get_stat(obj)->st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns an integer representing the device type on which stat
resides. Returns nil if the operating system doesn't
support this feature.
File.stat("/dev/fd1").rdev #=> 513 File.stat("/dev/tty").rdev #=> 1280
static VALUE
rb_stat_rdev(self)
VALUE self;
{
#ifdef HAVE_ST_RDEV
return ULONG2NUM(get_stat(self)->st_rdev);
#else
return Qnil;
#endif
}
Returns the major part of File_Stat#rdev or nil.
File.stat("/dev/fd1").rdev_major #=> 2 File.stat("/dev/tty").rdev_major #=> 5
static VALUE
rb_stat_rdev_major(self)
VALUE self;
{
#if defined(HAVE_ST_RDEV) && defined(major)
long rdev = get_stat(self)->st_rdev;
return ULONG2NUM(major(rdev));
#else
return Qnil;
#endif
}
Returns the minor part of File_Stat#rdev or nil.
File.stat("/dev/fd1").rdev_minor #=> 1 File.stat("/dev/tty").rdev_minor #=> 0
static VALUE
rb_stat_rdev_minor(self)
VALUE self;
{
#if defined(HAVE_ST_RDEV) && defined(minor)
long rdev = get_stat(self)->st_rdev;
return ULONG2NUM(minor(rdev));
#else
return Qnil;
#endif
}
Returns true if stat is readable by the effective
user id of this process.
File.stat("testfile").readable? #=> true
static VALUE
rb_stat_r(obj)
VALUE obj;
{
struct stat *st = get_stat(obj);
#ifdef USE_GETEUID
if (geteuid() == 0) return Qtrue;
#endif
#ifdef S_IRUSR
if (rb_stat_owned(obj))
return st->st_mode & S_IRUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IRGRP
if (rb_stat_grpowned(obj))
return st->st_mode & S_IRGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IROTH
if (!(st->st_mode & S_IROTH)) return Qfalse;
#endif
return Qtrue;
}
Returns true if stat is readable by the real user id
of this process.
File.stat("testfile").readable_real? #=> true
static VALUE
rb_stat_R(obj)
VALUE obj;
{
struct stat *st = get_stat(obj);
#ifdef USE_GETEUID
if (getuid() == 0) return Qtrue;
#endif
#ifdef S_IRUSR
if (rb_stat_rowned(obj))
return st->st_mode & S_IRUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IRGRP
if (group_member(get_stat(obj)->st_gid))
return st->st_mode & S_IRGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IROTH
if (!(st->st_mode & S_IROTH)) return Qfalse;
#endif
return Qtrue;
}
Returns true if stat has the set-group-id permission
bit set, false if it doesn't or if the operating system
doesn't support this feature.
File.stat("/usr/sbin/lpc").setgid? #=> true
static VALUE
rb_stat_sgid(obj)
VALUE obj;
{
#ifdef S_ISGID
if (get_stat(obj)->st_mode & S_ISGID) return Qtrue;
#endif
return Qfalse;
}
Returns true if stat has the set-user-id permission
bit set, false if it doesn't or if the operating system
doesn't support this feature.
File.stat("/bin/su").setuid? #=> true
static VALUE
rb_stat_suid(obj)
VALUE obj;
{
#ifdef S_ISUID
if (get_stat(obj)->st_mode & S_ISUID) return Qtrue;
#endif
return Qfalse;
}
Returns the size of stat in bytes.
File.stat("testfile").size #=> 66
static VALUE
rb_stat_size(self)
VALUE self;
{
return OFFT2NUM(get_stat(self)->st_size);
}
Returns the size of stat in bytes.
File.stat("testfile").size #=> 66
static VALUE
rb_stat_s(obj)
VALUE obj;
{
off_t size = get_stat(obj)->st_size;
if (size == 0) return Qnil;
return OFFT2NUM(size);
}
Returns true if stat is a socket, false
if it isn't or if the operating system doesn't support this
feature.
File.stat("testfile").socket? #=> false
static VALUE
rb_stat_S(obj)
VALUE obj;
{
#ifdef S_ISSOCK
if (S_ISSOCK(get_stat(obj)->st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns true if stat has its sticky bit set,
false if it doesn't or if the operating system doesn't
support this feature.
File.stat("testfile").sticky? #=> false
static VALUE
rb_stat_sticky(obj)
VALUE obj;
{
#ifdef S_ISVTX
if (get_stat(obj)->st_mode & S_ISVTX) return Qtrue;
#endif
return Qfalse;
}
Returns true if stat is a symbolic link,
false if it isn't or if the operating system doesn't
support this feature. As File::stat automatically follows
symbolic links, symlink? will always be false for
an object returned by File::stat.
File.symlink("testfile", "alink") #=> 0 File.stat("alink").symlink? #=> false File.lstat("alink").symlink? #=> true
static VALUE
rb_stat_l(obj)
VALUE obj;
{
#ifdef S_ISLNK
if (S_ISLNK(get_stat(obj)->st_mode)) return Qtrue;
#endif
return Qfalse;
}
Returns the numeric user id of the owner of stat.
File.stat("testfile").uid #=> 501
static VALUE
rb_stat_uid(self)
VALUE self;
{
return UINT2NUM(get_stat(self)->st_uid);
}
Returns true if stat is writable by the effective
user id of this process.
File.stat("testfile").writable? #=> true
static VALUE
rb_stat_w(obj)
VALUE obj;
{
struct stat *st = get_stat(obj);
#ifdef USE_GETEUID
if (geteuid() == 0) return Qtrue;
#endif
#ifdef S_IWUSR
if (rb_stat_owned(obj))
return st->st_mode & S_IWUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IWGRP
if (rb_stat_grpowned(obj))
return st->st_mode & S_IWGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IWOTH
if (!(st->st_mode & S_IWOTH)) return Qfalse;
#endif
return Qtrue;
}
Returns true if stat is writable by the real user id
of this process.
File.stat("testfile").writable_real? #=> true
static VALUE
rb_stat_W(obj)
VALUE obj;
{
struct stat *st = get_stat(obj);
#ifdef USE_GETEUID
if (getuid() == 0) return Qtrue;
#endif
#ifdef S_IWUSR
if (rb_stat_rowned(obj))
return st->st_mode & S_IWUSR ? Qtrue : Qfalse;
#endif
#ifdef S_IWGRP
if (group_member(get_stat(obj)->st_gid))
return st->st_mode & S_IWGRP ? Qtrue : Qfalse;
#endif
#ifdef S_IWOTH
if (!(st->st_mode & S_IWOTH)) return Qfalse;
#endif
return Qtrue;
}