Class: Sys::Filesystem

Inherits:
Object
  • Object
show all
Extended by:
FFI::Library, Functions
Includes:
Constants
Defined in:
lib/unix/sys/filesystem.rb,
lib/windows/sys/filesystem.rb,
lib/windows/sys/filesystem/constants.rb,
lib/windows/sys/filesystem/functions.rb

Overview

The Filesystem class encapsulates information about your filesystem.

Defined Under Namespace

Modules: Constants, Functions Classes: Error, Mntent, Mnttab, Mount, Stat, Statfs, Statvfs

Constant Summary collapse

VERSION =

The version of the sys-filesystem library.

'1.1.2'

Constants included from Constants

Constants::CASE_PRESERVED_NAMES, Constants::CASE_SENSITIVE_SEARCH, Constants::FILE_COMPRESSION, Constants::MAXPATH, Constants::NAMED_STREAMS, Constants::PERSISTENT_ACLS, Constants::READ_ONLY_VOLUME, Constants::SUPPORTS_ENCRYPTION, Constants::SUPPORTS_OBJECT_IDS, Constants::SUPPORTS_REMOTE_STORAGE, Constants::SUPPORTS_REPARSE_POINTS, Constants::SUPPORTS_SPARSE_FILES, Constants::UNICODE_ON_DISK, Constants::VOLUME_IS_COMPRESSED, Constants::VOLUME_QUOTAS

Class Method Summary collapse

Class Method Details

.mount_point(file) ⇒ Object

Returns the mount point for the given file. For MS Windows this means the root of the path.

Example:

File.mount_point("C:\\Documents and Settings") # => "C:\\'


554
555
556
557
558
559
560
561
562
563
564
565
566
567
# File 'lib/unix/sys/filesystem.rb', line 554

def self.mount_point(file)
  dev = File.stat(file).dev
  val = file

  self.mounts.each{ |mnt|
    mp = mnt.mount_point
    if File.stat(mp).dev == dev
      val = mp
      break
    end
  }

  val
end

.mountsObject

Yields a Filesystem::Mount object for each volume on your system in block form. Returns an array of Filesystem::Mount objects in non-block form.

Example:

Sys::Filesystem.mounts{ |mount|
   p mt.name        # => \\Device\\HarddiskVolume1
   p mt.mount_point # => C:\
   p mt.mount_time  # => Thu Dec 18 20:12:08 -0700 2008
   p mt.mount_type  # => NTFS
   p mt.options     # => casepres,casesens,ro,unicode
   p mt.pass_number # => nil
   p mt.dump_freq   # => nil
}

This method is a bit of a fudge for MS Windows in the name of interface compatibility because this method deals with volumes, not actual mount points. But, I believe it provides the sort of information many users want at a glance.

The possible values for the options and their meanings are as follows:

casepres => The filesystem preserves the case of file names when it places a name on disk. casesens => The filesystem supports case-sensitive file names. compression => The filesystem supports file-based compression. namedstreams => The filesystem supports named streams. pacls => The filesystem preserves and enforces access control lists. ro => The filesystem is read-only. encryption => The filesystem supports the Encrypted File System (EFS). objids => The filesystem supports object identifiers. rpoints => The filesystem supports reparse points. sparse => The filesystem supports sparse files. unicode => The filesystem supports Unicode in file names as they appear on disk. compressed => The filesystem is compressed.

– I couldn’t really find a good reason to use the wide functions for this method. If you have one, patches welcome.



443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
# File 'lib/unix/sys/filesystem.rb', line 443

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{ |i|
      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{ |key,val|
        if flags & key > 0
          if string.empty?
            string << val
          else
            string << ", #{val}"
          end
        end
        flags &= ~key
      }

      obj.options = string

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

      ptr += Statfs.size
    }
  else
    begin
      if respond_to?(:setmntent, true)
        fp = setmntent(MOUNT_FILE, 'r')
      else
        fp = fopen(MOUNT_FILE, 'r')
      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) ⇒ Object

Returns a Filesystem::Stat object that contains information about the path file system.

Examples:

File.stat("C:\\")
File.stat("C:\\Documents and Settings\\some_user")


397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
# File 'lib/unix/sys/filesystem.rb', line 397

def self.stat(path)
  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