class Sys::Filesystem

The Filesystem class serves as an abstract base class. Its methods return objects of other types. Do not instantiate.

The Filesystem class encapsulates information about your filesystem.

Constants

MOUNT_FILE
OPT_NAMES

Readable versions of constant names

VERSION

The version of the sys-filesystem library

Public Class Methods

mount(source, target, fstype = 'ext2', flags = 0, data = nil) click to toggle source

Attach the filesystem specified by source to the location (a directory or file) specified by the pathname in target.

Note that the source is often a pathname referring to a device, but can also be the pathname of a directory or file, or a dummy string.

By default this method will assume 'ext2' as the filesystem type, but you should update this as needed.

Typically requires admin privileges.

Example:

Sys::Filesystem.mount('/dev/loop0', '/home/you/tmp', 'ext4', Sys::Filesystem::MNT_RDONLY)
# File lib/sys/unix/sys/filesystem.rb, line 420
def self.mount(source, target, fstype = 'ext2', flags = 0, data = nil)
  if mount_c(source, target, fstype, flags, data) != 0
    raise Error, 'mount() function failed: ' + strerror(FFI.errno)
  end

  self
end
mount_point(file) click to toggle source

Returns the mount point of the given file, or itself if it cannot be found.

Example:

Sys::Filesystem.mount_point('/home/some_user') # => /home
# File lib/sys/unix/sys/filesystem.rb, line 386
def self.mount_point(file)
  dev = File.stat(file).dev
  val = file

  mounts.each do |mnt|
    mp = mnt.mount_point
    begin
      if File.stat(mp).dev == dev
        val = mp
        break
      end
    rescue Errno::EACCES
      next
    end
  end

  val
end
mounts() { |freeze| ... } click to toggle source

In block form, yields a Sys::Filesystem::Mount object for each mounted filesytem on the host. Otherwise it returns an array of Mount objects.

Example:

Sys::Filesystem.mounts{ |fs|

p fs.name        # => '/dev/dsk/c0t0d0s0'
p fs.mount_time  # => Thu Dec 11 15:07:23 -0700 2008
p fs.mount_type  # => 'ufs'
p fs.mount_point # => '/'
p fs.options     # => local, noowner, nosuid

}

# File lib/sys/unix/sys/filesystem.rb, line 269
def self.mounts
  array = block_given? ? nil : []

  if respond_to?(:getmntinfo, true)
    buf = FFI::MemoryPointer.new(:pointer)

    num = getmntinfo(buf, 2)

    if num == 0
      raise Error, 'getmntinfo() function failed: ' + strerror(FFI.errno)
    end

    ptr = buf.get_pointer(0)

    num.times do
      mnt = Statfs.new(ptr)
      obj = Sys::Filesystem::Mount.new
      obj.name = mnt[:f_mntfromname].to_s
      obj.mount_point = mnt[:f_mntonname].to_s
      obj.mount_type = mnt[:f_fstypename].to_s

      string = ''
      flags = mnt[:f_flags] & MNT_VISFLAGMASK

      OPT_NAMES.each do |key, val|
        if flags & key > 0
          if string.empty?
            string << val
          else
            string << ", #{val}"
          end
        end
        flags &= ~key
      end

      obj.options = string

      if block_given?
        yield obj.freeze
      else
        array << obj.freeze
      end

      ptr += Statfs.size
    end
  else
    begin
      if respond_to?(:setmntent, true)
        method_name = 'setmntent'
        fp = setmntent(MOUNT_FILE, 'r')
      else
        method_name = 'fopen'
        fp = fopen(MOUNT_FILE, 'r')
      end

      if fp.null?
        raise SystemCallError.new(method_name, FFI.errno)
      end

      if RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i
        mt = Mnttab.new
        while getmntent(fp, mt) == 0
          obj = Sys::Filesystem::Mount.new
          obj.name = mt[:mnt_special].to_s
          obj.mount_point = mt[:mnt_mountp].to_s
          obj.mount_type = mt[:mnt_fstype].to_s
          obj.options = mt[:mnt_mntopts].to_s
          obj.mount_time = Time.at(Integer(mt[:mnt_time]))

          if block_given?
            yield obj.freeze
          else
            array << obj.freeze
          end
        end
      else
        while ptr = getmntent(fp)
          break if ptr.null?
          mt = Mntent.new(ptr)

          obj = Sys::Filesystem::Mount.new
          obj.name = mt[:mnt_fsname]
          obj.mount_point = mt[:mnt_dir]
          obj.mount_type = mt[:mnt_type]
          obj.options = mt[:mnt_opts]
          obj.mount_time = nil
          obj.dump_frequency = mt[:mnt_freq]
          obj.pass_number = mt[:mnt_passno]

          if block_given?
            yield obj.freeze
          else
            array << obj.freeze
          end
        end
      end
    ensure
      if fp && !fp.null?
        if respond_to?(:endmntent, true)
          endmntent(fp)
        else
          fclose(fp)
        end
      end
    end
  end

  array
end
stat(path) click to toggle source

Returns a Sys::Filesystem::Stat object containing information about the path on the filesystem.

Examples:

# path
Sys::Filesystem.stat("path")

# Pathname
pathname = Pathname.new("path")
Sys::Filesystem.stat(pathname)

# File
file = File.open("file", "r")
Sys::Filesystem.stat(file)

# Dir
dir = Dir.open("/")
Sys::Filesystem.stat(dir)
# File lib/sys/unix/sys/filesystem.rb, line 220
def self.stat(path)
  path = path.path if path.respond_to?(:path) # File, Dir
  path = path.to_s if path.respond_to?(:to_s) # Pathname

  fs = Statvfs.new

  if statvfs(path, fs) < 0
    raise Error, 'statvfs() function failed: ' + strerror(FFI.errno)
  end

  obj = Sys::Filesystem::Stat.new
  obj.path = path
  obj.block_size = fs[:f_bsize]
  obj.fragment_size = fs[:f_frsize]
  obj.blocks = fs[:f_blocks]
  obj.blocks_free = fs[:f_bfree]
  obj.blocks_available = fs[:f_bavail]
  obj.files = fs[:f_files]
  obj.files_free = fs[:f_ffree]
  obj.files_available = fs[:f_favail]
  obj.filesystem_id = fs[:f_fsid]
  obj.flags = fs[:f_flag]
  obj.name_max = fs[:f_namemax]

  # OSX does things a little differently
  if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach/i
    obj.block_size /= 256
  end

  if fs.members.include?(:f_basetype)
    obj.base_type = fs[:f_basetype].to_s
  end

  obj.freeze
end
umount(target, flags = nil) click to toggle source

Removes the attachment of the (topmost) filesystem mounted on target. Additional flags may be provided for operating systems that support the umount2 function. Otherwise this argument is ignored.

Typically requires admin privileges.

# File lib/sys/unix/sys/filesystem.rb, line 434
def self.umount(target, flags = nil)
  if flags && respond_to?(:umount2)
    function = 'umount2'
    rv = umount2_c(target, flags)
  else
    function = 'umount'
    rv = umount_c(target)
  end

  if rv != 0
    raise Error, "#{function} function failed: " + strerror(FFI.errno)
  end

  self
end

Private Class Methods

get_boot_time() click to toggle source

This method is used to get the boot time of the system, which is used for the mount_time attribute within the File.mounts method.

# File lib/sys/windows/sys/filesystem.rb, line 405
def self.get_boot_time
  host = Socket.gethostname
  cs = "winmgmts://#{host}/root/cimv2"
  begin
    wmi = WIN32OLE.connect(cs)
  rescue WIN32OLERuntimeError => e
    raise Error, e
  else
    query = 'select LastBootupTime from Win32_OperatingSystem'
    ole = wmi.ExecQuery(query).ItemIndex(0)
    time_array = Time.parse(ole.LastBootupTime.split('.').first)
    Time.mktime(*time_array)
  end
end
get_options(flags) click to toggle source

Private method that converts filesystem flags into a comma separated list of strings. The presentation is meant as a rough analogue to the way options are presented for Unix filesystems.

# File lib/sys/windows/sys/filesystem.rb, line 426
def self.get_options(flags)
  str = ''
  str << ' casepres' if CASE_PRESERVED_NAMES & flags > 0
  str << ' casesens' if CASE_SENSITIVE_SEARCH & flags > 0
  str << ' compression' if FILE_COMPRESSION & flags > 0
  str << ' namedstreams' if NAMED_STREAMS & flags > 0
  str << ' pacls' if PERSISTENT_ACLS & flags > 0
  str << ' ro' if READ_ONLY_VOLUME & flags > 0
  str << ' encryption' if SUPPORTS_ENCRYPTION & flags > 0
  str << ' objids' if SUPPORTS_OBJECT_IDS & flags > 0
  str << ' rpoints' if SUPPORTS_REPARSE_POINTS & flags > 0
  str << ' sparse' if SUPPORTS_SPARSE_FILES & flags > 0
  str << ' unicode' if UNICODE_ON_DISK & flags > 0
  str << ' compressed' if VOLUME_IS_COMPRESSED & flags > 0

  str.tr!(' ', ',')
  str[1..-1] # Ignore the first comma
end