class File::Stat
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.
Public Class Methods
static VALUE
rb_stat_init(VALUE obj, VALUE fname)
{
struct stat st, *nst;
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (STAT(StringValueCStr(fname), &st) == -1) {
rb_sys_fail_path(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;
} Create a File::Stat object for the given file name (raising an exception if the file doesn’t exist).
Открытые методы экземпляра
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;
} Сравнивает объекты File::Stat путем сравнения их соответствующих времен последней модификации.
Возвращается nil, если other_stat не является объектом File::Stat
f1 = File.new("f1", "w")
sleep 1
f2 = File.new("f2", "w")
f1.stat <=> f2.stat #=> -1
static VALUE
rb_stat_atime(VALUE self)
{
return stat_atime(get_stat(self));
} Возвращает время последнего доступа к этому файлу в виде объекта класса Time.
File.stat("testfile").atime #=> Wed Dec 31 18:00:00 CST 1969
static VALUE
rb_stat_birthtime(VALUE self)
{
return stat_birthtime(get_stat(self));
} Возвращает время создания для stat.
Если платформа не имеет времени создания, вызывает NotImplementedError.
File.write("testfile", "foo")
sleep 10
File.write("testfile", "bar")
sleep 10
File.chmod(0644, "testfile")
sleep 10
File.read("testfile")
File.stat("testfile").birthtime #=> 2014-02-24 11:19:17 +0900
File.stat("testfile").mtime #=> 2014-02-24 11:19:27 +0900
File.stat("testfile").ctime #=> 2014-02-24 11:19:37 +0900
File.stat("testfile").atime #=> 2014-02-24 11:19:47 +0900
static VALUE
rb_stat_blksize(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
return ULONG2NUM(get_stat(self)->st_blksize);
#else
return Qnil;
#endif
} Возвращает размер блока собственной файловой системы. Возвратит nil на платформах, которые не поддерживают эту информацию.
File.stat("testfile").blksize #=> 4096
static VALUE
rb_stat_b(VALUE obj)
{
#ifdef S_ISBLK
if (S_ISBLK(get_stat(obj)->st_mode)) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если файл является блочным устройством, false, если нет, или если операционная система не поддерживает эту функцию.
File.stat("testfile").blockdev? #=> false
File.stat("/dev/hda1").blockdev? #=> true
static VALUE
rb_stat_blocks(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
# if SIZEOF_STRUCT_STAT_ST_BLOCKS > SIZEOF_LONG
return ULL2NUM(get_stat(self)->st_blocks);
# else
return ULONG2NUM(get_stat(self)->st_blocks);
# endif
#else
return Qnil;
#endif
} Возвращает количество выделенных блоков собственной файловой системы для этого файла или nil, если операционная система не поддерживает эту функцию.
File.stat("testfile").blocks #=> 2
static VALUE
rb_stat_c(VALUE obj)
{
if (S_ISCHR(get_stat(obj)->st_mode)) return Qtrue;
return Qfalse;
} Возвращает true, если файл является символьным устройством, false, если нет, или если операционная система не поддерживает эту функцию.
File.stat("/dev/tty").chardev? #=> true
static VALUE
rb_stat_ctime(VALUE self)
{
return stat_ctime(get_stat(self));
} Возвращает время изменения для stat (то есть время, когда изменялась информация о каталоге файла, а не сам файл).
Обратите внимание, что в Windows (NTFS) возвращает время создания.
File.stat("testfile").ctime #=> Wed Apr 09 08:53:14 CDT 2003
static VALUE
rb_stat_dev(VALUE self)
{
#if SIZEOF_STRUCT_STAT_ST_DEV <= SIZEOF_DEV_T
return DEVT2NUM(get_stat(self)->st_dev);
#elif SIZEOF_STRUCT_STAT_ST_DEV <= SIZEOF_LONG
return ULONG2NUM(get_stat(self)->st_dev);
#else
return ULL2NUM(get_stat(self)->st_dev);
#endif
} Возвращает целое число, представляющее устройство, на котором находится stat.
File.stat("testfile").dev #=> 774
static VALUE
rb_stat_dev_major(VALUE self)
{
#if defined(major)
return UINT2NUM(major(get_stat(self)->st_dev));
#else
return Qnil;
#endif
} Возвращает старшую часть File_Stat#dev или nil.
File.stat("/dev/fd1").dev_major #=> 2
File.stat("/dev/tty").dev_major #=> 5
static VALUE
rb_stat_dev_minor(VALUE self)
{
#if defined(minor)
return UINT2NUM(minor(get_stat(self)->st_dev));
#else
return Qnil;
#endif
} Возвращает младшую часть File_Stat#dev или nil.
File.stat("/dev/fd1").dev_minor #=> 1
File.stat("/dev/tty").dev_minor #=> 0
static VALUE
rb_stat_d(VALUE obj)
{
if (S_ISDIR(get_stat(obj)->st_mode)) return Qtrue;
return Qfalse;
} Возвращает true, если указанный файл является каталогом или символической ссылкой, указывающей на каталог, и false в противном случае.
file_name может быть объектом IO.
File.directory?(".")
static VALUE
rb_stat_x(VALUE obj)
{
struct stat *st = get_stat(obj);
#ifdef USE_GETEUID
if (geteuid() == 0) {
return RBOOL(st->st_mode & S_IXUGO);
}
#endif
#ifdef S_IXUSR
if (rb_stat_owned(obj))
return RBOOL(st->st_mode & S_IXUSR);
#endif
#ifdef S_IXGRP
if (rb_stat_grpowned(obj))
return RBOOL(st->st_mode & S_IXGRP);
#endif
#ifdef S_IXOTH
if (!(st->st_mode & S_IXOTH)) return Qfalse;
#endif
return Qtrue;
} Возвращает true, если stat является исполняемым, или если операционная система не различает исполняемые файлы и неисполняемые файлы. Тесты проводятся с использованием эффективного владельца процесса.
File.stat("testfile").executable? #=> false
static VALUE
rb_stat_X(VALUE obj)
{
struct stat *st = get_stat(obj);
#ifdef USE_GETEUID
if (getuid() == 0) {
return RBOOL(st->st_mode & S_IXUGO);
}
#endif
#ifdef S_IXUSR
if (rb_stat_rowned(obj))
return RBOOL(st->st_mode & S_IXUSR);
#endif
#ifdef S_IXGRP
if (rb_group_member(get_stat(obj)->st_gid))
return RBOOL(st->st_mode & S_IXGRP);
#endif
#ifdef S_IXOTH
if (!(st->st_mode & S_IXOTH)) return Qfalse;
#endif
return Qtrue;
} То же, что и executable?, но тестирование с использованием реального владельца процесса.
static VALUE
rb_stat_f(VALUE obj)
{
if (S_ISREG(get_stat(obj)->st_mode)) return Qtrue;
return Qfalse;
} Возвращает true, если stat является обычным файлом (не файлом устройства, каналом, сокетом и т. д.).
File.stat("testfile").file? #=> true
static VALUE
rb_stat_ftype(VALUE obj)
{
return rb_file_ftype(get_stat(obj));
} Идентифицирует тип stat. Возвращаемая строка является одной из: “file”, “directory”, “characterSpecial”, “blockSpecial”, “fifo”, “link”, “socket” или “unknown”.
File.stat("/dev/tty").ftype #=> "characterSpecial"
static VALUE
rb_stat_gid(VALUE self)
{
return GIDT2NUM(get_stat(self)->st_gid);
} Возвращает числовой идентификатор группы владельца stat.
File.stat("testfile").gid #=> 500
static VALUE
rb_stat_grpowned(VALUE obj)
{
#ifndef _WIN32
if (rb_group_member(get_stat(obj)->st_gid)) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если эффективный идентификатор группы процесса совпадает с идентификатором группы stat. В Windows NT возвращает false.
File.stat("testfile").grpowned? #=> true
File.stat("/etc/passwd").grpowned? #=> false
static VALUE
rb_stat_ino(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_INOHIGH
/* assume INTEGER_PACK_LSWORD_FIRST and st_inohigh is just next of st_ino */
return rb_integer_unpack(&get_stat(self)->st_ino, 2,
SIZEOF_STRUCT_STAT_ST_INO, 0,
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER|
INTEGER_PACK_2COMP);
#elif SIZEOF_STRUCT_STAT_ST_INO > SIZEOF_LONG
return ULL2NUM(get_stat(self)->st_ino);
#else
return ULONG2NUM(get_stat(self)->st_ino);
#endif
} Возвращает номер индексного дескриптора для stat.
File.stat("testfile").ino #=> 1083669
static VALUE
rb_stat_inspect(VALUE self)
{
VALUE str;
size_t 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},
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
{"birthtime", rb_stat_birthtime},
#endif
};
struct stat* st;
TypedData_Get_Struct(self, struct stat, &stat_data_type, 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", (unsigned long)NUM2ULONG(v));
}
else if (i == 0 || i == 6) { /* dev/rdev */
rb_str_catf(str, "0x%"PRI_DEVT_PREFIX"x", NUM2DEVT(v));
}
else {
rb_str_append(str, rb_inspect(v));
}
}
rb_str_buf_cat2(str, ">");
return str;
} Создает хорошо отформатированное описание 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,
# birthtime=Mon Aug 04 08:13:49 CDT 2003>"
static VALUE
rb_stat_mode(VALUE self)
{
return UINT2NUM(ST2UINT(get_stat(self)->st_mode));
} Возвращает целое число, представляющее биты разрешений stat. Значение битов зависит от платформы; в системах Unix см. stat(2).
File.chmod(0644, "testfile") #=> 1
s = File.stat("testfile")
sprintf("%o", s.mode) #=> "100644"
static VALUE
rb_stat_mtime(VALUE self)
{
return stat_mtime(get_stat(self));
} Возвращает время последней модификации stat.
File.stat("testfile").mtime #=> Wed Apr 09 08:53:14 CDT 2003
static VALUE
rb_stat_nlink(VALUE self)
{
/* struct stat::st_nlink is nlink_t in POSIX. Not the case for Windows. */
const struct stat *ptr = get_stat(self);
if (sizeof(ptr->st_nlink) <= sizeof(int)) {
return UINT2NUM((unsigned)ptr->st_nlink);
}
else if (sizeof(ptr->st_nlink) == sizeof(long)) {
return ULONG2NUM((unsigned long)ptr->st_nlink);
}
else if (sizeof(ptr->st_nlink) == sizeof(LONG_LONG)) {
return ULL2NUM((unsigned LONG_LONG)ptr->st_nlink);
}
else {
rb_bug(":FIXME: don't know what to do");
}
} Возвращает количество жестких ссылок на stat.
File.stat("testfile").nlink #=> 1
File.link("testfile", "testfile.bak") #=> 0
File.stat("testfile").nlink #=> 2
static VALUE
rb_stat_owned(VALUE obj)
{
if (get_stat(obj)->st_uid == geteuid()) return Qtrue;
return Qfalse;
} Возвращает true, если эффективному идентификатору пользователя процесса соответствует владелец stat.
File.stat("testfile").owned? #=> true
File.stat("/etc/passwd").owned? #=> false
static VALUE
rb_stat_p(VALUE obj)
{
#ifdef S_IFIFO
if (S_ISFIFO(get_stat(obj)->st_mode)) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если операционная система поддерживает каналы и stat является каналом; false в противном случае.
static VALUE
rb_stat_rdev(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_RDEV
# if SIZEOF_STRUCT_STAT_ST_RDEV <= SIZEOF_DEV_T
return DEVT2NUM(get_stat(self)->st_rdev);
# elif SIZEOF_STRUCT_STAT_ST_RDEV <= SIZEOF_LONG
return ULONG2NUM(get_stat(self)->st_rdev);
# else
return ULL2NUM(get_stat(self)->st_rdev);
# endif
#else
return Qnil;
#endif
} Возвращает целое число, представляющее тип устройства, на котором находится stat. Возвращает nil, если операционная система не поддерживает эту функцию.
File.stat("/dev/fd1").rdev #=> 513
File.stat("/dev/tty").rdev #=> 1280
static VALUE
rb_stat_rdev_major(VALUE self)
{
#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(major)
return UINT2NUM(major(get_stat(self)->st_rdev));
#else
return Qnil;
#endif
} Возвращает старшую часть номера устройства или nil.
File.stat("/dev/fd1").rdev_major #=> 2
File.stat("/dev/tty").rdev_major #=> 5
static VALUE
rb_stat_rdev_minor(VALUE self)
{
#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(minor)
return UINT2NUM(minor(get_stat(self)->st_rdev));
#else
return Qnil;
#endif
} Возвращает младшую часть номера устройства или nil.
File.stat("/dev/fd1").rdev_minor #=> 1
File.stat("/dev/tty").rdev_minor #=> 0
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 RBOOL(st->st_mode & S_IRUSR);
#endif
#ifdef S_IRGRP
if (rb_stat_grpowned(obj))
return RBOOL(st->st_mode & S_IRGRP);
#endif
#ifdef S_IROTH
if (!(st->st_mode & S_IROTH)) return Qfalse;
#endif
return Qtrue;
} Возвращает true, если stat доступен для чтения эффективным идентификатором пользователя этого процесса.
File.stat("testfile").readable? #=> 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 RBOOL(st->st_mode & S_IRUSR);
#endif
#ifdef S_IRGRP
if (rb_group_member(get_stat(obj)->st_gid))
return RBOOL(st->st_mode & S_IRGRP);
#endif
#ifdef S_IROTH
if (!(st->st_mode & S_IROTH)) return Qfalse;
#endif
return Qtrue;
} Возвращает true, если stat доступен для чтения реальным идентификатором пользователя этого процесса.
File.stat("testfile").readable_real? #=> true
static VALUE
rb_stat_sgid(VALUE obj)
{
#ifdef S_ISGID
if (get_stat(obj)->st_mode & S_ISGID) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если у stat установлен бит разрешения set-group-id, false в противном случае или если операционная система не поддерживает эту функцию.
File.stat("/usr/sbin/lpc").setgid? #=> true
static VALUE
rb_stat_suid(VALUE obj)
{
#ifdef S_ISUID
if (get_stat(obj)->st_mode & S_ISUID) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если у stat установлен бит разрешения set-user-id, false в противном случае или если операционная система не поддерживает эту функцию.
File.stat("/bin/su").setuid? #=> true
static VALUE
rb_stat_size(VALUE self)
{
return OFFT2NUM(get_stat(self)->st_size);
} Возвращает размер stat в байтах.
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);
} Возвращает размер файла, если stat — файл нулевой длины, в противном случае.
File.stat("testfile").size? #=> 66
File.stat("/dev/null").size? #=> nil
static VALUE
rb_stat_S(VALUE obj)
{
#ifdef S_ISSOCK
if (S_ISSOCK(get_stat(obj)->st_mode)) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если stat — сокет, false в противном случае или если операционная система не поддерживает эту функцию.
File.stat("testfile").socket? #=> false
static VALUE
rb_stat_sticky(VALUE obj)
{
#ifdef S_ISVTX
if (get_stat(obj)->st_mode & S_ISVTX) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если у stat установлен бит "sticky", false в противном случае или если операционная система не поддерживает эту функцию.
File.stat("testfile").sticky? #=> false
static VALUE
rb_stat_l(VALUE obj)
{
#ifdef S_ISLNK
if (S_ISLNK(get_stat(obj)->st_mode)) return Qtrue;
#endif
return Qfalse;
} Возвращает true, если stat — символическая ссылка, false в противном случае или если операционная система не поддерживает эту функцию. Так как File::stat автоматически следует за символическими ссылками, symlink? всегда будет true для объекта, возвращённого File::stat.
File.symlink("testfile", "alink") #=> 0
File.stat("alink").symlink? #=> false
File.lstat("alink").symlink? #=> true
static VALUE
rb_stat_uid(VALUE self)
{
return UIDT2NUM(get_stat(self)->st_uid);
} Возвращает числовой идентификатор пользователя владельца stat.
File.stat("testfile").uid #=> 501
static VALUE
rb_stat_wr(VALUE obj)
{
#ifdef S_IROTH
struct stat *st = get_stat(obj);
if ((st->st_mode & (S_IROTH)) == S_IROTH) {
return UINT2NUM(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
}
else {
return Qnil;
}
#endif
} Если stat доступен для чтения другими пользователями, возвращает целое число, представляющее биты разрешений файла stat. Возвращает nil в противном случае. Значение битов зависит от платформы; в системах Unix см. stat(2).
m = File.stat("/etc/passwd").world_readable? #=> 420
sprintf("%o", m) #=> "644"
static VALUE
rb_stat_ww(VALUE obj)
{
#ifdef S_IROTH
struct stat *st = get_stat(obj);
if ((st->st_mode & (S_IWOTH)) == S_IWOTH) {
return UINT2NUM(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
}
else {
return Qnil;
}
#endif
} Если stat доступен для записи другими пользователями, возвращает целое число, представляющее биты разрешений файла stat. Возвращает nil в противном случае. Значение битов зависит от платформы; в системах Unix см. stat(2).
m = File.stat("/tmp").world_writable? #=> 511
sprintf("%o", m) #=> "777"
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 RBOOL(st->st_mode & S_IWUSR);
#endif
#ifdef S_IWGRP
if (rb_stat_grpowned(obj))
return RBOOL(st->st_mode & S_IWGRP);
#endif
#ifdef S_IWOTH
if (!(st->st_mode & S_IWOTH)) return Qfalse;
#endif
return Qtrue;
} Возвращает true, если stat доступен для записи эффективному идентификатору пользователя этого процесса.
File.stat("testfile").writable? #=> 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 RBOOL(st->st_mode & S_IWUSR);
#endif
#ifdef S_IWGRP
if (rb_group_member(get_stat(obj)->st_gid))
return RBOOL(st->st_mode & S_IWGRP);
#endif
#ifdef S_IWOTH
if (!(st->st_mode & S_IWOTH)) return Qfalse;
#endif
return Qtrue;
} Возвращает true, если stat доступен для записи реальному идентификатору пользователя этого процесса.
File.stat("testfile").writable_real? #=> true
static VALUE
rb_stat_z(VALUE obj)
{
if (get_stat(obj)->st_size == 0) return Qtrue;
return Qfalse;
} Возвращает true, если stat — файл нулевой длины; false в противном случае.
File.stat("testfile").zero? #=> false
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.