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(VALUE obj, VALUE fname) { struct stat st, *nst; rb_secure(2); FilePathValue(fname); if (stat(StringValueCStr(fname), &st) == -1) { rb_sys_fail(RSTRING_PTR(fname)); } if (DATA_PTR(obj)) { xfree(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(VALUE self, VALUE other) { if (rb_obj_is_kind_of(other, rb_obj_class(self))) { struct timespec ts1 = stat_mtimespec(get_stat(self)); struct timespec ts2 = stat_mtimespec(get_stat(other)); if (ts1.tv_sec == ts2.tv_sec) { if (ts1.tv_nsec == ts2.tv_nsec) return INT2FIX(0); if (ts1.tv_nsec < ts2.tv_nsec) return INT2FIX(-1); return INT2FIX(1); } if (ts1.tv_sec < ts2.tv_sec) return INT2FIX(-1); 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(VALUE self) { return stat_atime(get_stat(self)); }
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(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(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(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(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(VALUE self) { return stat_ctime(get_stat(self)); }
Returns an integer representing the device on which stat resides.
File.stat("testfile").dev #=> 774
static VALUE rb_stat_dev(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(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(VALUE self) { #if defined(minor) long dev = get_stat(self)->st_dev; return ULONG2NUM(minor(dev)); #else return Qnil; #endif }
Returns true
if the named file is a directory,
false
otherwise.
File.directory?(".")
static VALUE rb_stat_d(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(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(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(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(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(VALUE self) { return GIDT2NUM(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(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(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(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}, }; struct stat* st; Data_Get_Struct(self, struct stat, st); if (!st) { return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self)); } 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 */ rb_str_catf(str, "0%lo", NUM2ULONG(v)); } else if (i == 0 || i == 6) { /* dev/rdev */ rb_str_catf(str, "0x%lx", NUM2ULONG(v)); } 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(VALUE self) { return UINT2NUM(ST2UINT(get_stat(self)->st_mode)); }
Returns the modification time of stat.
File.stat("testfile").mtime #=> Wed Apr 09 08:53:14 CDT 2003
static VALUE rb_stat_mtime(VALUE self) { return stat_mtime(get_stat(self)); }
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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(VALUE self) { return UIDT2NUM(get_stat(self)->st_uid); }
If stat is readable by others, returns an integer representing the
file permission bits of stat. Returns nil
otherwise.
The meaning of the bits is platform dependent; on Unix systems, see
stat(2)
.
m = File.stat("/etc/passwd").world_readable? # => 420 sprintf("%o", m) # => "644"
static VALUE rb_stat_wr(VALUE obj) { #ifdef S_IROTH if ((get_stat(obj)->st_mode & (S_IROTH)) == S_IROTH) { return UINT2NUM(get_stat(obj)->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } else { return Qnil; } #endif }
If stat is writable by others, returns an integer representing the
file permission bits of stat. Returns nil
otherwise.
The meaning of the bits is platform dependent; on Unix systems, see
stat(2)
.
m = File.stat("/tmp").world_writable? # => 511 sprintf("%o", m) # => "777"
static VALUE rb_stat_ww(VALUE obj) { #ifdef S_IROTH if ((get_stat(obj)->st_mode & (S_IWOTH)) == S_IWOTH) { return UINT2NUM(get_stat(obj)->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } else { return Qnil; } #endif }
Returns true
if stat is writable by the effective
user id of this process.
File.stat("testfile").writable? #=> true
static VALUE rb_stat_w(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(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; }