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;
}
Commenting is here to help enhance the documentation. For example, sample code, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.