123456789_123456789_123456789_123456789_123456789_

Class: File::Stat

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
self, ::Comparable
Inherits: Object
Defined in: file.c,
file.c

Overview

Objects of class Stat encapsulate common status information for ::File objects. The information is recorded at the moment the Stat object is created; changes made to the file after that point will not be reflected. Stat objects are returned by IO#stat, stat, #lstat, and lstat. Many of these methods return platform-specific values, and not all values are meaningful on all systems. See also Kernel.test.

Class Method Summary

  • .new(file_name) ⇒ Stat constructor

    Create a Stat object for the given file name (raising an exception if the file doesn’t exist).

Instance Attribute Summary

  • #blockdev? ⇒ Boolean readonly

    Returns true if the file is a block device, false if it isn’t or if the operating system doesn’t support this feature.

  • #chardev? ⇒ Boolean readonly

    Returns true if the file is a character device, false if it isn’t or if the operating system doesn’t support this feature.

  • #directory? ⇒ Boolean readonly

    Returns true if stat is a directory, false otherwise.

  • #executable? ⇒ Boolean readonly

    Returns true if stat is executable or if the operating system doesn’t distinguish executable files from nonexecutable files.

  • #executable_real? ⇒ Boolean readonly

    Same as #executable?, but tests using the real owner of the process.

  • #file? ⇒ Boolean readonly

    Returns true if stat is a regular file (not a device file, pipe, socket, etc.).

  • #grpowned? ⇒ Boolean readonly

    Returns true if the effective group id of the process is the same as the group id of stat.

  • #owned? ⇒ Boolean readonly

    Returns true if the effective user id of the process is the same as the owner of stat.

  • #pipe? ⇒ Boolean readonly

    Returns true if the operating system supports pipes and stat is a pipe; false otherwise.

  • #readable? ⇒ Boolean readonly

    Returns true if stat is readable by the effective user id of this process.

  • #readable_real? ⇒ Boolean readonly

    Returns true if stat is readable by the real user id of this process.

  • #setgid? ⇒ Boolean readonly

    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.

  • #setuid? ⇒ Boolean readonly

    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.

  • #size ⇒ Integer readonly

    Returns the size of stat in bytes.

  • #size? ⇒ Boolean readonly

    Returns nil if stat is a zero-length file, the size of the file otherwise.

  • #socket? ⇒ Boolean readonly

    Returns true if stat is a socket, false if it isn’t or if the operating system doesn’t support this feature.

  • #sticky? ⇒ Boolean readonly

    Returns true if stat has its sticky bit set, false if it doesn’t or if the operating system doesn’t support this feature.

  • #symlink? ⇒ Boolean readonly

    Returns true if stat is a symbolic link, false if it isn’t or if the operating system doesn’t support this feature.

  • #world_readable? ⇒ Boolean readonly

    If stat is readable by others, returns an integer representing the file permission bits of stat.

  • #world_writable? ⇒ Boolean readonly

    If stat is writable by others, returns an integer representing the file permission bits of stat.

  • #writable? ⇒ Boolean readonly

    Returns true if stat is writable by the effective user id of this process.

  • #writable_real? ⇒ Boolean readonly

    Returns true if stat is writable by the real user id of this process.

  • #zero? ⇒ Boolean readonly

    Returns true if stat is a zero-length file; false otherwise.

Instance Method Summary

::Comparable - Included

#<

Compares two objects based on the receiver’s #<=> method, returning true if it returns a value less than 0.

#<=

Compares two objects based on the receiver’s #<=> method, returning true if it returns a value less than or equal to 0.

#==

Compares two objects based on the receiver’s #<=> method, returning true if it returns 0.

#>

Compares two objects based on the receiver’s #<=> method, returning true if it returns a value greater than 0.

#>=

Compares two objects based on the receiver’s #<=> method, returning true if it returns a value greater than or equal to 0.

#between?

Returns false if obj #<=> min is less than zero or if obj #<=> max is greater than zero, true otherwise.

#clamp

In (min, max) form, returns min if obj #<=> min is less than zero, max if obj #<=> max is greater than zero, and obj otherwise.

Constructor Details

.new(file_name) ⇒ Stat

Create a Stat object for the given file name (raising an exception if the file doesn’t exist).

[ GitHub ]

  
# File 'file.c', line 5675

static VALUE
rb_stat_init(VALUE obj, VALUE fname)
{
    struct stat st;

    FilePathValue(fname);
    fname = rb_str_encode_ospath(fname);
    if (STAT(StringValueCStr(fname), &st) == -1) {
        rb_sys_fail_path(fname);
    }

    struct rb_stat *rb_st;
    TypedData_Get_Struct(obj, struct rb_stat, &stat_data_type, rb_st);

    rb_st->stat = st;
    rb_st->initialized = true;

    return Qnil;
}

Instance Attribute Details

#blockdev?Boolean (readonly)

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
[ GitHub ]

  
# File 'file.c', line 5827

static VALUE
rb_stat_b(VALUE obj)
{
#ifdef S_ISBLK
    if (S_ISBLK(get_stat(obj)->st_mode)) return Qtrue;

#endif
    return Qfalse;
}

#chardev?Boolean (readonly)

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
[ GitHub ]

  
# File 'file.c', line 5849

static VALUE
rb_stat_c(VALUE obj)
{
    if (S_ISCHR(get_stat(obj)->st_mode)) return Qtrue;

    return Qfalse;
}

#directory?Boolean (readonly)

Returns true if stat is a directory, false otherwise.

File.stat("testfile").directory?   #=> false
File.stat(".").directory?          #=> true
[ GitHub ]

  
# File 'file.c', line 5742

static VALUE
rb_stat_d(VALUE obj)
{
    if (S_ISDIR(get_stat(obj)->st_mode)) return Qtrue;
    return Qfalse;
}

#executable?Boolean (readonly)

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
[ GitHub ]

  
# File 'file.c', line 6099

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;
}

#executable_real?Boolean (readonly)

Same as #executable?, but tests using the real owner of the process.

[ GitHub ]

  
# File 'file.c', line 6131

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;
}

#file?Boolean (readonly)

Returns true if stat is a regular file (not a device file, pipe, socket, etc.).

File.stat("testfile").file?   #=> true
[ GitHub ]

  
# File 'file.c', line 6166

static VALUE
rb_stat_f(VALUE obj)
{
    if (S_ISREG(get_stat(obj)->st_mode)) return Qtrue;
    return Qfalse;
}

#grpowned?Boolean (readonly)

Returns true if the effective group id of the process is the same as the group id of stat. On Windows, returns false.

File.stat("testfile").grpowned?      #=> true
File.stat("/etc/passwd").grpowned?   #=> false
[ GitHub ]

  
# File 'file.c', line 5895

static VALUE
rb_stat_grpowned(VALUE obj)
{
#ifndef _WIN32
    if (rb_group_member(get_stat(obj)->st_gid)) return Qtrue;
#endif
    return Qfalse;
}

#owned?Boolean (readonly)

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
[ GitHub ]

  
# File 'file.c', line 5869

static VALUE
rb_stat_owned(VALUE obj)
{
    if (get_stat(obj)->st_uid == geteuid()) return Qtrue;
    return Qfalse;
}

#pipe?Boolean (readonly)

Returns true if the operating system supports pipes and stat is a pipe; false otherwise.

[ GitHub ]

  
# File 'file.c', line 5757

static VALUE
rb_stat_p(VALUE obj)
{
#ifdef S_IFIFO
    if (S_ISFIFO(get_stat(obj)->st_mode)) return Qtrue;

#endif
    return Qfalse;
}

#readable?Boolean (readonly)

Returns true if stat is readable by the effective user id of this process.

File.stat("testfile").readable?   #=> true
[ GitHub ]

  
# File 'file.c', line 5915

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;
}

#readable_real?Boolean (readonly)

Returns true if stat is readable by the real user id of this process.

File.stat("testfile").readable_real?   #=> true
[ GitHub ]

  
# File 'file.c', line 5948

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;
}

#setgid?Boolean (readonly)

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
[ GitHub ]

  
# File 'file.c', line 6244

static VALUE
rb_stat_sgid(VALUE obj)
{
#ifdef S_ISGID
    if (get_stat(obj)->st_mode & S_ISGID) return Qtrue;
#endif
    return Qfalse;
}

#setuid?Boolean (readonly)

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
[ GitHub ]

  
# File 'file.c', line 6223

static VALUE
rb_stat_suid(VALUE obj)
{
#ifdef S_ISUID
    if (get_stat(obj)->st_mode & S_ISUID) return Qtrue;
#endif
    return Qfalse;
}

#sizeInteger (readonly)

Returns the size of stat in bytes.

File.stat("testfile").size   #=> 66
[ GitHub ]

  
# File 'file.c', line 826

static VALUE
rb_stat_size(VALUE self)
{
    return OFFT2NUM(get_stat(self)->st_size);
}

#size?Boolean (readonly)

Returns nil if stat is a zero-length file, the size of the file otherwise.

File.stat("testfile").size?   #=> 66
File.stat(File::NULL).size?   #=> nil
[ GitHub ]

  
# File 'file.c', line 6203

static VALUE
rb_stat_s(VALUE obj)
{
    rb_off_t size = get_stat(obj)->st_size;

    if (size == 0) return Qnil;
    return OFFT2NUM(size);
}

#socket?Boolean (readonly)

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
[ GitHub ]

  
# File 'file.c', line 5804

static VALUE
rb_stat_S(VALUE obj)
{
#ifdef S_ISSOCK
    if (S_ISSOCK(get_stat(obj)->st_mode)) return Qtrue;

#endif
    return Qfalse;
}

#sticky?Boolean (readonly)

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
[ GitHub ]

  
# File 'file.c', line 6265

static VALUE
rb_stat_sticky(VALUE obj)
{
#ifdef S_ISVTX
    if (get_stat(obj)->st_mode & S_ISVTX) return Qtrue;
#endif
    return Qfalse;
}

#symlink?Boolean (readonly)

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
[ GitHub ]

  
# File 'file.c', line 5783

static VALUE
rb_stat_l(VALUE obj)
{
#ifdef S_ISLNK
    if (S_ISLNK(get_stat(obj)->st_mode)) return Qtrue;
#endif
    return Qfalse;
}

#world_readable?Boolean (readonly)

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"
[ GitHub ]

  
# File 'file.c', line 5983

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));
    }
#endif
    return Qnil;
}

#world_writable?Boolean (readonly)

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"
[ GitHub ]

  
# File 'file.c', line 6074

static VALUE
rb_stat_ww(VALUE obj)
{
#ifdef S_IWOTH
    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));
    }
#endif
    return Qnil;
}

#writable?Boolean (readonly)

Returns true if stat is writable by the effective user id of this process.

File.stat("testfile").writable?   #=> true
[ GitHub ]

  
# File 'file.c', line 6006

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;
}

#writable_real?Boolean (readonly)

Returns true if stat is writable by the real user id of this process.

File.stat("testfile").writable_real?   #=> true
[ GitHub ]

  
# File 'file.c', line 6039

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;
}

#zero?Boolean (readonly)

Returns true if stat is a zero-length file; false otherwise.

File.stat("testfile").zero?   #=> false
[ GitHub ]

  
# File 'file.c', line 6184

static VALUE
rb_stat_z(VALUE obj)
{
    if (get_stat(obj)->st_size == 0) return Qtrue;
    return Qfalse;
}

Instance Method Details

#<=>(other_stat) ⇒ 1, ...

Compares Stat objects by comparing their respective modification times.

nil is returned if other_stat is not a Stat object

f1 = File.new("f1", "w")
sleep 1
f2 = File.new("f2", "w")
f1.stat <=> f2.stat   #=> -1
[ GitHub ]

  
# File 'file.c', line 545

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;
}

#atimeTime

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
[ GitHub ]

  
# File 'file.c', line 980

static VALUE
rb_stat_atime(VALUE self)
{
    return stat_atime(get_stat(self));
}

#birthtimeTime

Returns the birth time for stat.

If the platform doesn’t have birthtime, raises ::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
[ GitHub ]

  
# File 'file.c', line 1045

static VALUE
rb_stat_birthtime(VALUE self)
{
    return stat_birthtime(get_stat(self));
}

#blksizeInteger?

Returns the native file system’s block size. Will return nil on platforms that don’t support this information.

File.stat("testfile").blksize   #=> 4096
[ GitHub ]

  
# File 'file.c', line 843

static VALUE
rb_stat_blksize(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    return ULONG2NUM(get_stat(self)->st_blksize);
#else
    return Qnil;
#endif
}

#blocksInteger?

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
[ GitHub ]

  
# File 'file.c', line 864

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
}

#ctimeTime

Returns the change time for stat (that is, the time directory information about the file was changed, not the file itself).

Note that on Windows (NTFS), returns creation time (birth time).

File.stat("testfile").ctime   #=> Wed Apr 09 08:53:14 CDT 2003
[ GitHub ]

  
# File 'file.c', line 1016

static VALUE
rb_stat_ctime(VALUE self)
{
    return stat_ctime(get_stat(self));
}

#devInteger

Returns an integer representing the device on which stat resides.

File.stat("testfile").dev   #=> 774
[ GitHub ]

  
# File 'file.c', line 584

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
}

#dev_majorInteger

Returns the major part of File_Stat#dev or nil.

File.stat("/dev/fd1").dev_major   #=> 2
File.stat("/dev/tty").dev_major   #=> 5
[ GitHub ]

  
# File 'file.c', line 607

static VALUE
rb_stat_dev_major(VALUE self)
{
#if defined(major)
    return UINT2NUM(major(get_stat(self)->st_dev));
#else
    return Qnil;
#endif
}

#dev_minorInteger

Returns the minor part of File_Stat#dev or nil.

File.stat("/dev/fd1").dev_minor   #=> 1
File.stat("/dev/tty").dev_minor   #=> 0
[ GitHub ]

  
# File 'file.c', line 628

static VALUE
rb_stat_dev_minor(VALUE self)
{
#if defined(minor)
    return UINT2NUM(minor(get_stat(self)->st_dev));
#else
    return Qnil;
#endif
}

#ftypeString

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"
[ GitHub ]

  
# File 'file.c', line 5725

static VALUE
rb_stat_ftype(VALUE obj)
{
    return rb_file_ftype(get_stat(obj));
}

#gidInteger

Returns the numeric group id of the owner of stat.

File.stat("testfile").gid   #=> 500
[ GitHub ]

  
# File 'file.c', line 741

static VALUE
rb_stat_gid(VALUE self)
{
    return GIDT2NUM(get_stat(self)->st_gid);
}

#initialize_copy(orig)

This method is for internal use only.
[ GitHub ]

  
# File 'file.c', line 5696

static VALUE
rb_stat_init_copy(VALUE copy, VALUE orig)
{
    if (!OBJ_INIT_COPY(copy, orig)) return copy;

    struct rb_stat *orig_rb_st;
    TypedData_Get_Struct(orig, struct rb_stat, &stat_data_type, orig_rb_st);

    struct rb_stat *copy_rb_st;
    TypedData_Get_Struct(copy, struct rb_stat, &stat_data_type, copy_rb_st);

    *copy_rb_st = *orig_rb_st;
    return copy;
}

#inoInteger

Returns the inode number for stat.

File.stat("testfile").ino   #=> 1083669
[ GitHub ]

  
# File 'file.c', line 648

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
}

#inspectString

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,
   #    birthtime=Mon Aug 04 08:13:49 CDT 2003>"
[ GitHub ]

  
# File 'file.c', line 1069

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 rb_stat* rb_st;
    TypedData_Get_Struct(self, struct rb_stat, &stat_data_type, rb_st);
    if (!rb_st->initialized) {
        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;
}

#modeInteger

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"
[ GitHub ]

  
# File 'file.c', line 677

static VALUE
rb_stat_mode(VALUE self)
{
    return UINT2NUM(ST2UINT(get_stat(self)->st_mode));
}

#mtimeTime

Returns the modification time of stat.

File.stat("testfile").mtime   #=> Wed Apr 09 08:53:14 CDT 2003
[ GitHub ]

  
# File 'file.c', line 996

static VALUE
rb_stat_mtime(VALUE self)
{
    return stat_mtime(get_stat(self));
}

#rdevInteger?

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
[ GitHub ]

  
# File 'file.c', line 759

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
}

#rdev_majorInteger

Returns the major part of File_Stat#rdev or nil.

File.stat("/dev/fd1").rdev_major   #=> 2
File.stat("/dev/tty").rdev_major   #=> 5
[ GitHub ]

  
# File 'file.c', line 786

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
}

#rdev_minorInteger

Returns the minor part of File_Stat#rdev or nil.

File.stat("/dev/fd1").rdev_minor   #=> 1
File.stat("/dev/tty").rdev_minor   #=> 0
[ GitHub ]

  
# File 'file.c', line 807

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
}

#uidInteger

Returns the numeric user id of the owner of stat.

File.stat("testfile").uid   #=> 501
[ GitHub ]

  
# File 'file.c', line 725

static VALUE
rb_stat_uid(VALUE self)
{
    return UIDT2NUM(get_stat(self)->st_uid);
}