sys-filesystem-1.5.4/ 0000755 0000041 0000041 00000000000 15061232103 014542 5 ustar www-data www-data sys-filesystem-1.5.4/certs/ 0000755 0000041 0000041 00000000000 15061232103 015662 5 ustar www-data www-data sys-filesystem-1.5.4/certs/djberg96_pub.pem 0000644 0000041 0000041 00000003076 15061232103 020655 0 ustar www-data www-data -----BEGIN CERTIFICATE-----
MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MREwDwYDVQQDDAhkamJl
cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
MB4XDTE4MDMxODE1MjIwN1oXDTI4MDMxNTE1MjIwN1owPzERMA8GA1UEAwwIZGpi
ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
bTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALgfaroVM6CI06cxr0/h
A+j+pc8fgpRgBVmHFaFunq28GPC3IvW7Nvc3Y8SnAW7pP1EQIbhlwRIaQzJ93/yj
u95KpkP7tA9erypnV7dpzBkzNlX14ACaFD/6pHoXoe2ltBxk3CCyyzx70mTqJpph
75IB03ni9a8yqn8pmse+s83bFJOAqddSj009sGPcQO+QOWiNxqYv1n5EHcvj2ebO
6hN7YTmhx7aSia4qL/quc4DlIaGMWoAhvML7u1fmo53CYxkKskfN8MOecq2vfEmL
iLu+SsVVEAufMDDFMXMJlvDsviolUSGMSNRTujkyCcJoXKYYxZSNtIiyd9etI0X3
ctu0uhrFyrMZXCedutvXNjUolD5r9KGBFSWH1R9u2I3n3SAyFF2yzv/7idQHLJJq
74BMnx0FIq6fCpu5slAipvxZ3ZkZpEXZFr3cIBtO1gFvQWW7E/Y3ijliWJS1GQFq
058qERadHGu1yu1dojmFRo6W2KZvY9al2yIlbkpDrD5MYQIDAQABo3cwdTAJBgNV
HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUFZsMapgzJimzsbaBG2Tm8j5e
AzgwHQYDVR0RBBYwFIESZGpiZXJnOTZAZ21haWwuY29tMB0GA1UdEgQWMBSBEmRq
YmVyZzk2QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAW2tnYixXQtKxgGXq
/3iSWG2bLwvxS4go3srO+aRXZHrFUMlJ5W0mCxl03aazxxKTsVVpZD8QZxvK91OQ
h9zr9JBYqCLcCVbr8SkmYCi/laxIZxsNE5YI8cC8vvlLI7AMgSfPSnn/Epq1GjGY
6L1iRcEDtanGCIvjqlCXO9+BmsnCfEVehqZkQHeYczA03tpOWb6pon2wzvMKSsKH
ks0ApVdstSLz1kzzAqem/uHdG9FyXdbTAwH1G4ZPv69sQAFAOCgAqYmdnzedsQtE
1LQfaQrx0twO+CZJPcRLEESjq8ScQxWRRkfuh2VeR7cEU7L7KqT10mtUwrvw7APf
DYoeCY9KyjIBjQXfbj2ke5u1hZj94Fsq9FfbEQg8ygCgwThnmkTrrKEiMSs3alYR
ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
-----END CERTIFICATE-----
sys-filesystem-1.5.4/CHANGES.md 0000644 0000041 0000041 00000017721 15061232103 016144 0 ustar www-data www-data ## 1.5.4 - 7-Sep-2025
* Added a fallback check for 64-bit Linux in case the config info doesn't
include "64" anywhere in it. Thanks go to Chris Hofstaedtler for the
report.
## 1.5.3 - 3-Oct-2024
* Decided to unroll the changes in 1.5.2 because doing runtime compiler
checks was making more people unhappy than happy, and I already had
some misgivings about it.
* Updated the README.md to note the issues with running 32-bit Ruby with
64-bit offsets. At the moment I think this mainly only affects arch Linux.
## 1.5.2 - 30-Sep-2024
* Forgot to switch mkmf-lite from a dev dependency to a runtime dependency.
Thanks go to Thomas Langé for the spot and patch.
## 1.5.1 - 29-Sep-2024
* Add the f_type struct member to the Statvfs struct for Linux. This was added
at some point in the Linux lifecycle, though may still be blank depending on
your platform. Thanks go to Tasos Sahanidis for the patch.
* Added padding on 32-bit Statvfs struct with 64-bit offsets for Linux. Thanks
go Tasos Sahanidis again for this update.
* Bumped mkmf-lite dependency since the changes were needed to support the above.
## 1.5.0 - 8-Jun-2024
* Add support for DragonFlyBSD.
* Remove Solaris support. It's dead, Jim.
* Now assumes umount2 function is present on Linux systems, and some
corresponding refactoring of the umount method.
## 1.4.5 - 22-May-2024
* Handle the possibility that a statvs64 alias may not exist on some Linux
platforms. Thanks go to Antoine Martin for the report.
## 1.4.4 - 12-Sep-2023
* Yet another fix for 32-bit vs 64-bit linux, specifically for the Statvfs
struct. Thanks go to Josh Cooper for the spot and the patch.
## 1.4.3 - 20-Oct-2021
* Another fix for 32-bit vs 64-bit Linux since it was realized we cannot always
rely on the host architecture information. Handling for JRuby was improved
as well. Thanks go to Scott Bradnick for the spot.
* The constructor is now explicitly private. This class was never meant to
actually be instantiated.
* Updated the MANIFEST.md file.
## 1.4.2 - 22-Jul-2021
* Fixed support for 32-bit Linux. Thanks go to ciprianbadescu for the spot.
## 1.4.1 - 30-Dec-2020
* Fix an FFI function declaration bug for Big Sur and later on Mac. Thanks go
to Roman Gaufman for the spot and Martins Polakovs for testing.
* Fixed the changelog metadata URI.
* Added a .gitignore file.
## 1.4.0 - 6-Sep-2020
* The Sys::Filesystem.stat method now accepts a Pathname and Dir object as
an argument. On most platforms it will also accept a File object. Thanks
go to hirura for the patch.
* Fixed the statvfs struct layout on i686 platforms. Thanks go to
Filipovici-Andrei for the patch.
* Switched from test-unit to rspec, and updated the tests.
## 1.3.4 - 17-Mar-2020
* Properly include a LICENSE file as per the Apache-2.0 license.
## 1.3.3 - 18-Feb-2020
* Linux now uses statvfs64 under the hood. This fixes a potential issue with
32 bit systems. Thanks go to Tom Smyth for the spot.
## 1.3.2 - 8-Dec-2019
* Renamed various text files to include .rdoc extension so that github renders
them nicely.
## 1.3.1 - 15-Oct-2019
* Fixed a bug where the Statvfs and Statfs structs were not allocated properly
on Linux, which could cause issues. Thanks go to Daniele Orlandi for the spot.
* Added specs to ensure that the FFI struct size matches the C struct size.
This required adding mkmf-lite as a development dependency.
* Added a slightly more pessimistic version requirement for test-unit.
## 1.3.0 - 3-Oct-2019
* Added the mount and umount singleton methods.
* Changed an internal class variable to a frozen constant.
## 1.2.0 - 1-Jan-2019
* Changed the license to Apache-2.0.
* Added the case_sensitive? and case_insensitive? instance methods to the
Filesystem::Stat class.
* Refactored the Numeric helper methods into a single location.
* Fixed the deprecation warnings when running the tests on Windows.
* Added metadata to the gemspec.
## 1.1.9 - 26-Jan-2018
* The bytes_free and bytes_total methods were updated to use the fragment size
instead of the block size. This fixes Macs using APFS, as well as Solaris 10.
Thanks go to Mikhail Vasin for the spot.
* Removed the code specific to FreeBSD 10, which was ultimately an attempt
to address the issue now resolved by the above change.
* Updated the cert again.
## 1.1.8 - 2-Sep-2017
* The stat and mount_point methods now call to_s on the string argument
explicitly so that Pathname objects will now work with String#wincode.
* Updated some tests to avoid Fixnum warnings for Ruby 2.4.
* Updated the cert.
## 1.1.7 - 1-Aug-2016
* Fixed an issue in the stat method for MS Windows where the blocks_avail
value was not correct. Thanks go to Maxime Lapointe for the spot.
## 1.1.6 - 17-May-2016
* On versions that use setmntent or fopen, explicitly raise an error if
either of those calls return a null value.
## 1.1.5 - 5-Dec-2015
* This gem is now signed.
* The gem related tasks in the Rakefile now assume Rubygems 2.x.
* Updates to the gemspec, added cert_chain, removed rubyforge_project.
* Internal reorganization, and use of relative_require as appropriate.
* Added a sys-filesystem.rb file for convenience.
## 1.1.4 - 15-Mar-2015
* The File.mounts method no longer raises an error if a mount point
is not accessible. Thanks go to Michael Pope for the patch.
* Some internal code reorganization.
## 1.1.3 - 1-Oct-2014
* Now ignores EPERM errors when trying to find the mount point for a path.
Thanks go to petersen for the patch.
* The Filesystem.stat method now defaults to using the root path on Windows
for volume information.
## 1.1.2 - 9-May-2014
* Added the percent_used, bytes_total, bytes_free and bytes_used methods
to the Filesystem::Stat class. Thanks go to xanview for the suggestion.
* Changed File.exists? to File.exist? to avoid warnings in Ruby 2.1.x.
* The convenience methods to_mb, to_gb, etc, are now defined in Numeric
instead of Fixnum.
* Added the to_tb method for terabytes.
* Minor updates to the gem:create and gem:install Rake tasks.
## 1.1.1 - 3-Oct-2013
* Solaris now always uses statvfs64 on Solaris for better 64-bit support.
Thanks go to Jeff Shantz for the spot.
## 1.1.0 - 19-Jan-2013
* Converted the Windows source code to use FFI. Consequently, there is now
a single gem rather than separate gems for Windows and Unix.
* Revamped the Windows tests.
## 1.0.0 - 11-Jan-2012
* Converted everything from C to FFI for the Unix flavors. The Windows
source code remains untouched.
## 0.3.4 - 19-Nov-2010
* Fixed a bug where negative block counts were happening on very large
hard drives. Thanks go to Jonas Pfenniger for the spot.
* Refactored the clean task in the Rakefile.
* Some cosmetic source code changes.
## 0.3.3 - 21-May-2010
* Added a workaround for the Sys::Filesystem#block_size member to deal with
a bug in OS X. Thanks go to Josh Pasqualetto for the spot.
## 0.3.2 - 29-Dec-2009
* Source has been moved to github.
* Added the 'gem' task and removed build logic from the gemspec.
* Updated the install task.
* Minor correction to the manifest.
* Removed some junk build files that were inadvertently included in
the last gem.
## 0.3.1 - 5-Aug-2009
* Now compatible with Ruby 1.9.x.
* Changed license to Artistic 2.0
* Updated the gemspec, including the explicit addition of a license and
test-unit as a development dependency, as well as an updated description.
## 0.3.0 - 26-Feb-2009
* Added support for OS X and FreeBSD thanks to an awesome patch by Nobuyoshi
Miyokawa.
* Added the Filesystem.mount_point method that takes a file and returns
the mount point it's sitting on.
## 0.2.0 - 30-Dec-2008
* Added the Filesystem.mounts method for iterating over mount or volume
information.
## 0.1.1 - 28-Mar-2007
* Bug fix for BSD flavors. Thanks go to Jeremy Kemper and Ole Christian
Rynning for the spot.
* Bug fix for OS X (along the same lines as the BSD fix). Thanks go to
Aurelian Dehay for the spot.
* Some Rdoc improvements for the C extension.
* Tweaks to the gemspec.
* Added synopsis to the README.
## 0.1.0 - 17-Nov-2006
* Initial release. Alpha. Code is stable, but API is not.
sys-filesystem-1.5.4/lib/ 0000755 0000041 0000041 00000000000 15061232103 015310 5 ustar www-data www-data sys-filesystem-1.5.4/lib/sys-filesystem.rb 0000644 0000041 0000041 00000000101 15061232103 020625 0 ustar www-data www-data # frozen_string_literal: true
require_relative 'sys/filesystem'
sys-filesystem-1.5.4/lib/sys/ 0000755 0000041 0000041 00000000000 15061232103 016126 5 ustar www-data www-data sys-filesystem-1.5.4/lib/sys/windows/ 0000755 0000041 0000041 00000000000 15061232103 017620 5 ustar www-data www-data sys-filesystem-1.5.4/lib/sys/windows/sys/ 0000755 0000041 0000041 00000000000 15061232103 020436 5 ustar www-data www-data sys-filesystem-1.5.4/lib/sys/windows/sys/filesystem.rb 0000644 0000041 0000041 00000035206 15061232103 023155 0 ustar www-data www-data require_relative 'filesystem/constants'
require_relative 'filesystem/functions'
require_relative 'filesystem/helper'
require 'socket'
require 'win32ole'
require 'date'
require 'time'
# The Sys module serves as a namespace only.
module Sys
# The Filesystem class encapsulates information about your filesystem.
class Filesystem
include Sys::Filesystem::Constants
extend Sys::Filesystem::Functions
# Error typically raised if any of the Sys::Filesystem methods fail.
class Error < StandardError; end
private_class_method :new
# Mount objects are returned by the Sys::Filesystem.mounts method.
class Mount
# The name of the volume. This is the device mapping.
attr_reader :name
# The last time the volume was mounted. For MS Windows this equates
# to your system's boot time.
attr_reader :mount_time
# The type of mount, e.g. NTFS, UDF, etc.
attr_reader :mount_type
# The volume mount point, e.g. 'C:\'
attr_reader :mount_point
# Various comma separated options that reflect the volume's features
attr_reader :options
# Always nil on MS Windows. Provided for interface compatibility only.
attr_reader :pass_number
# Always nil on MS Windows. Provided for interface compatibility only.
attr_reader :frequency
alias fsname name
alias dir mount_point
alias opts options
alias passno pass_number
alias freq frequency
end
# Stat objects are returned by the Sys::Filesystem.stat method.
class Stat
# The path of the file system.
attr_reader :path
# The file system block size. MS Windows typically defaults to 4096.
attr_reader :block_size
# Fragment size. Meaningless at the moment.
attr_reader :fragment_size
# The total number of blocks available (used or unused) on the file
# system.
attr_reader :blocks
# The total number of unused blocks.
attr_reader :blocks_free
# The total number of unused blocks available to unprivileged processes.
attr_reader :blocks_available
# Total number of files/inodes that can be created on the file system.
# This attribute is always nil on MS Windows.
attr_reader :files
# Total number of free files/inodes that can be created on the file
# system. This attribute is always nil on MS Windows.
attr_reader :files_free
# Total number of available files/inodes for unprivileged processes
# that can be created on the file system. This attribute is always
# nil on MS Windows.
attr_reader :files_available
# The file system volume id.
attr_reader :filesystem_id
# A bit mask of file system flags.
attr_reader :flags
# The maximum length of a file name permitted on the file system.
attr_reader :name_max
# The file system type, e.g. NTFS, FAT, etc.
attr_reader :base_type
# The total amount of free space on the partition.
attr_reader :bytes_free
# The amount of free space available to unprivileged processes.
attr_reader :bytes_available
alias inodes files
alias inodes_free files_free
alias inodes_available files_available
# Returns the total space on the partition.
def bytes_total
blocks * block_size
end
# Returns the total amount of used space on the partition.
def bytes_used
bytes_total - bytes_free
end
# Returns the percentage of the partition that has been used.
def percent_used
100 - (100.0 * bytes_free.to_f / bytes_total.to_f)
end
end
# 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.
#--
# rubocop:disable Metrics/BlockLength
#
def self.mounts
# First call, get needed buffer size
buffer = 0.chr
length = GetLogicalDriveStringsA(buffer.size, buffer)
if length == 0
raise SystemCallError.new('GetLogicalDriveStrings', FFI.errno)
else
buffer = 0.chr * length
end
mounts = block_given? ? nil : []
# Try again with new buffer size
if GetLogicalDriveStringsA(buffer.size, buffer) == 0
raise SystemCallError.new('GetLogicalDriveStrings', FFI.errno)
end
drives = buffer.split(0.chr)
boot_time = get_boot_time
drives.each do |drive|
mount = Mount.new
volume = FFI::MemoryPointer.new(:char, MAXPATH)
fsname = FFI::MemoryPointer.new(:char, MAXPATH)
mount.instance_variable_set(:@mount_point, drive)
mount.instance_variable_set(:@mount_time, boot_time)
volume_serial_number = FFI::MemoryPointer.new(:ulong)
max_component_length = FFI::MemoryPointer.new(:ulong)
filesystem_flags = FFI::MemoryPointer.new(:ulong)
bool = GetVolumeInformationA(
drive,
volume,
volume.size,
volume_serial_number,
max_component_length,
filesystem_flags,
fsname,
fsname.size
)
# Skip unmounted floppies or cd-roms, or inaccessible drives
unless bool
if [5, 21].include?(FFI.errno) # ERROR_NOT_READY or ERROR_ACCESS_DENIED
next
else
raise SystemCallError.new('GetVolumeInformation', FFI.errno)
end
end
filesystem_flags = filesystem_flags.read_ulong
fsname = fsname.read_string
name = 0.chr * MAXPATH
if QueryDosDeviceA(drive[0, 2], name, name.size) == 0
raise SystemCallError.new('QueryDosDevice', FFI.errno)
end
mount.instance_variable_set(:@name, name.strip)
mount.instance_variable_set(:@mount_type, fsname)
mount.instance_variable_set(:@options, get_options(filesystem_flags))
if block_given?
yield mount
else
mounts << mount
end
end
mounts # Nil if the block form was used.
end
# rubocop:enable Metrics/BlockLength
# 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:\\'
#
def self.mount_point(file)
wfile = FFI::MemoryPointer.from_string(file.to_s.wincode)
if PathStripToRootW(wfile)
wfile.read_string(wfile.size).split("\000\000").first.tr(0.chr, '')
end
end
# Returns a Filesystem::Stat object that contains information about the
# +path+ file system. On Windows this will default to using the root
# path for volume information.
#
# Examples:
#
# # Regular directory
# Sys::Filesystem.stat("C:\\")
# Sys::Filesystem.stat("C:\\Documents and Settings\\some_user")
#
# # Pathname
# pathname = Pathname.new("C:\\")
# Sys::Filesystem.stat(pathname)
#
# # Dir
# dir = Dir.open("C:\\")
# Sys::Filesystem.stat(dir)
#
# Note that on Windows you cannot stat a regular file because
# Windows won't like it. It must be a directory in some form.
#
def self.stat(path)
path = path.path if path.respond_to?(:path) # Dir
path = path.to_s if path.respond_to?(:to_s) # Pathname
bytes_avail = FFI::MemoryPointer.new(:ulong_long)
bytes_free = FFI::MemoryPointer.new(:ulong_long)
total_bytes = FFI::MemoryPointer.new(:ulong_long)
mpoint = mount_point(path).to_s
mpoint << '/' unless mpoint.end_with?('/')
wpath = path.to_s.wincode
# We need this call for the 64 bit support
unless GetDiskFreeSpaceExW(wpath, bytes_avail, total_bytes, bytes_free)
raise SystemCallError.new('GetDiskFreeSpaceEx', FFI.errno)
end
bytes_avail = bytes_avail.read_ulong_long
bytes_free = bytes_free.read_ulong_long
total_bytes = total_bytes.read_ulong_long
sectors_ptr = FFI::MemoryPointer.new(:ulong_long)
bytes_ptr = FFI::MemoryPointer.new(:ulong_long)
free_ptr = FFI::MemoryPointer.new(:ulong_long)
total_ptr = FFI::MemoryPointer.new(:ulong_long)
# We need this call for the total/cluster info, which is not in the Ex call.
unless GetDiskFreeSpaceW(wpath, sectors_ptr, bytes_ptr, free_ptr, total_ptr)
raise SystemCallError.new('GetDiskFreeSpace', FFI.errno)
end
sectors_per_cluster = sectors_ptr.read_ulong_long
bytes_per_sector = bytes_ptr.read_ulong_long
free_ptr.free
total_ptr.free
block_size = sectors_per_cluster * bytes_per_sector
blocks_avail = bytes_avail / block_size
blocks_free = bytes_free / block_size
total_blocks = total_bytes / block_size
vol_name_ptr = FFI::MemoryPointer.new(:char, MAXPATH)
base_type_ptr = FFI::MemoryPointer.new(:char, MAXPATH)
vol_serial_ptr = FFI::MemoryPointer.new(:ulong)
name_max_ptr = FFI::MemoryPointer.new(:ulong)
flags_ptr = FFI::MemoryPointer.new(:ulong)
bool = GetVolumeInformationW(
mpoint.wincode,
vol_name_ptr,
vol_name_ptr.size,
vol_serial_ptr,
name_max_ptr,
flags_ptr,
base_type_ptr,
base_type_ptr.size
)
unless bool
raise SystemCallError.new('GetVolumeInformation', FFI.errno)
end
vol_serial = vol_serial_ptr.read_ulong
name_max = name_max_ptr.read_ulong
flags = flags_ptr.read_ulong
base_type = base_type_ptr.read_string(base_type_ptr.size).tr(0.chr, '')
# Lets explicitly free our pointers
vol_name_ptr.free
vol_serial_ptr.free
name_max_ptr.free
flags_ptr.free
base_type_ptr.free
sectors_ptr.free
bytes_ptr.free
stat_obj = Stat.new
stat_obj.instance_variable_set(:@path, path)
stat_obj.instance_variable_set(:@block_size, block_size)
stat_obj.instance_variable_set(:@blocks, total_blocks)
stat_obj.instance_variable_set(:@blocks_available, blocks_avail)
stat_obj.instance_variable_set(:@blocks_free, blocks_free)
stat_obj.instance_variable_set(:@name_max, name_max)
stat_obj.instance_variable_set(:@base_type, base_type)
stat_obj.instance_variable_set(:@flags, flags)
stat_obj.instance_variable_set(:@filesystem_id, vol_serial)
stat_obj.instance_variable_set(:@bytes_free, bytes_free)
stat_obj.instance_variable_set(:@bytes_available, bytes_avail)
stat_obj.freeze # Read-only object
end
# Associate a volume with a drive letter or a directory on another volume.
#
def self.mount(target, source)
targetw = target.to_s.wincode
sourcew = source.to_s.wincode
volume_namew = (0.chr * 256).wincode
unless GetVolumeNameForVolumeMountPointW(sourcew, volume_namew, volume_namew.size)
raise SystemCallError.new('GetVolumeNameForVolumeMountPoint', FFI.errno)
end
unless SetVolumeMountPointW(targetw, volume_namew)
raise SystemCallError.new('SetVolumeMountPoint', FFI.errno)
end
self
end
# Deletes a drive letter or mounted folder.
#
def self.umount(mount_point)
unless DeleteVolumeMountPoint(mount_point)
raise SystemCallError.new('DeleteVolumeMountPoint', FFI.errno)
end
self
end
# 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.
#
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
private_class_method :get_boot_time
# 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.
#
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
private_class_method :get_options
end
end
sys-filesystem-1.5.4/lib/sys/windows/sys/filesystem/ 0000755 0000041 0000041 00000000000 15061232103 022622 5 ustar www-data www-data sys-filesystem-1.5.4/lib/sys/windows/sys/filesystem/functions.rb 0000644 0000041 0000041 00000002436 15061232103 025164 0 ustar www-data www-data require 'ffi'
module Sys
class Filesystem
# Wrapper module for Windows related FFI functions.
module Functions
extend FFI::Library
ffi_lib :kernel32
# Make FFI functions private
module FFI::Library
def attach_pfunc(*args)
attach_function(*args)
private args[0]
end
end
attach_pfunc :DeleteVolumeMountPointA, [:string], :bool
attach_pfunc :GetDiskFreeSpaceW, %i[buffer_in pointer pointer pointer pointer], :bool
attach_pfunc :GetDiskFreeSpaceExW, %i[buffer_in pointer pointer pointer], :bool
attach_pfunc :GetLogicalDriveStringsA, %i[ulong pointer], :ulong
attach_pfunc :GetVolumeInformationA,
%i[buffer_in pointer ulong pointer pointer pointer pointer ulong],
:bool
attach_pfunc :GetVolumeInformationW,
%i[buffer_in pointer ulong pointer pointer pointer pointer ulong],
:bool
attach_pfunc :GetVolumeNameForVolumeMountPointW, %i[buffer_in buffer_in ulong], :bool
attach_pfunc :QueryDosDeviceA, %i[buffer_in buffer_out ulong], :ulong
attach_pfunc :SetVolumeMountPointW, %i[buffer_in buffer_in], :bool
ffi_lib :shlwapi
attach_pfunc :PathStripToRootW, [:pointer], :bool
end
end
end
sys-filesystem-1.5.4/lib/sys/windows/sys/filesystem/helper.rb 0000644 0000041 0000041 00000000472 15061232103 024431 0 ustar www-data www-data # Reopen core Ruby classes here and add some custom methods.
class String
# Convenience method for converting strings to UTF-16LE for wide character
# functions that require it.
#--
# TODO: Use a refinement.
def wincode
(tr(File::SEPARATOR, File::ALT_SEPARATOR) + 0.chr).encode('UTF-16LE')
end
end
sys-filesystem-1.5.4/lib/sys/windows/sys/filesystem/constants.rb 0000644 0000041 0000041 00000001336 15061232103 025166 0 ustar www-data www-data module Sys
class Filesystem
module Constants
MAXPATH = 260
CASE_SENSITIVE_SEARCH = 0x00000001
CASE_PRESERVED_NAMES = 0x00000002
UNICODE_ON_DISK = 0x00000004
PERSISTENT_ACLS = 0x00000008
FILE_COMPRESSION = 0x00000010
VOLUME_QUOTAS = 0x00000020
SUPPORTS_SPARSE_FILES = 0x00000040
SUPPORTS_REPARSE_POINTS = 0x00000080
SUPPORTS_REMOTE_STORAGE = 0x00000100
VOLUME_IS_COMPRESSED = 0x00008000
SUPPORTS_OBJECT_IDS = 0x00010000
SUPPORTS_ENCRYPTION = 0x00020000
NAMED_STREAMS = 0x00040000
READ_ONLY_VOLUME = 0x00080000
end
end
end
sys-filesystem-1.5.4/lib/sys/unix/ 0000755 0000041 0000041 00000000000 15061232103 017111 5 ustar www-data www-data sys-filesystem-1.5.4/lib/sys/unix/sys/ 0000755 0000041 0000041 00000000000 15061232103 017727 5 ustar www-data www-data sys-filesystem-1.5.4/lib/sys/unix/sys/filesystem.rb 0000644 0000041 0000041 00000031402 15061232103 022440 0 ustar www-data www-data require_relative 'filesystem/constants'
require_relative 'filesystem/structs'
require_relative 'filesystem/functions'
# The Sys module serves as a namespace only.
module Sys
# The Filesystem class serves as an abstract base class. Its methods
# return objects of other types. Do not instantiate.
class Filesystem
include Sys::Filesystem::Constants
include Sys::Filesystem::Structs
extend Sys::Filesystem::Functions
private_class_method :new
# Readable versions of constant names
OPT_NAMES = {
MNT_RDONLY => 'read-only',
MNT_SYNCHRONOUS => 'synchronous',
MNT_NOEXEC => 'noexec',
MNT_NOSUID => 'nosuid',
MNT_NODEV => 'nodev',
MNT_UNION => 'union',
MNT_ASYNC => 'asynchronous',
MNT_CPROTECT => 'content-protection',
MNT_EXPORTED => 'exported',
MNT_QUARANTINE => 'quarantined',
MNT_LOCAL => 'local',
MNT_QUOTA => 'quotas',
MNT_ROOTFS => 'rootfs',
MNT_DONTBROWSE => 'nobrowse',
MNT_IGNORE_OWNERSHIP => 'noowners',
MNT_AUTOMOUNTED => 'automounted',
MNT_JOURNALED => 'journaled',
MNT_NOUSERXATTR => 'nouserxattr',
MNT_DEFWRITE => 'defwrite',
MNT_NOATIME => 'noatime'
}.freeze
private_constant :OPT_NAMES
# File used to read mount informtion from.
if File.exist?('/etc/mtab')
MOUNT_FILE = '/etc/mtab'.freeze
elsif File.exist?('/etc/mnttab')
MOUNT_FILE = '/etc/mnttab'.freeze
elsif File.exist?('/proc/mounts')
MOUNT_FILE = '/proc/mounts'.freeze
else
MOUNT_FILE = 'getmntinfo'.freeze
end
private_constant :MOUNT_FILE
# The error raised if any of the Filesystem methods fail.
class Error < StandardError; end
# Stat objects are returned by the Sys::Filesystem.stat method.
class Stat
# Read-only filesystem
RDONLY = 1
# Filesystem does not support suid or sgid semantics.
NOSUID = 2
# Filesystem does not truncate file names longer than +name_max+.
NOTRUNC = 3
# The path of the filesystem.
attr_accessor :path
# The preferred system block size.
attr_accessor :block_size
# The fragment size, i.e. fundamental filesystem block size.
attr_accessor :fragment_size
# The total number of +fragment_size+ blocks in the filesystem.
attr_accessor :blocks
# The total number of free blocks in the filesystem.
attr_accessor :blocks_free
# The number of free blocks available to unprivileged processes.
attr_accessor :blocks_available
# The total number of files/inodes that can be created.
attr_accessor :files
# The total number of files/inodes on the filesystem.
attr_accessor :files_free
# The number of free files/inodes available to unprivileged processes.
attr_accessor :files_available
# The filesystem identifier.
attr_accessor :filesystem_id
# A bit mask of flags.
attr_accessor :flags
# The maximum length of a file name permitted on the filesystem.
attr_accessor :name_max
# The filesystem type, e.g. UFS.
attr_accessor :base_type
# The filesystem type
attr_accessor :filesystem_type
# The user that mounted the filesystem
attr_accessor :owner
# Count of sync reads since mount
attr_accessor :sync_reads
# Count of sync writes since mount
attr_accessor :sync_writes
# Count of async reads since mount
attr_accessor :async_reads
# Count of async writes since mount
attr_accessor :async_writes
alias inodes files
alias inodes_free files_free
alias inodes_available files_available
# Creates a new Sys::Filesystem::Stat object. This is meant for
# internal use only. Do not instantiate directly.
#
def initialize
@path = nil
@block_size = nil
@fragment_size = nil
@blocks = nil
@blocks_free = nil
@blocks_available = nil
@files = nil
@files_free = nil
@files_available = nil
@filesystem_id = nil
@flags = nil
@name_max = nil
@base_type = nil
end
# Returns the total space on the partition.
def bytes_total
blocks * fragment_size
end
# Returns the total amount of free space on the partition.
def bytes_free
blocks_free * fragment_size
end
# Returns the amount of free space available to unprivileged processes.
def bytes_available
blocks_available * fragment_size
end
# Returns the total amount of used space on the partition.
def bytes_used
bytes_total - bytes_free
end
# Returns the percentage of the partition that has been used.
def percent_used
100 - (100.0 * bytes_free.to_f / bytes_total.to_f)
end
end
# Mount objects are returned by the Sys::Filesystem.mounts method.
class Mount
# The name of the mounted resource.
attr_accessor :name
# The mount point/directory.
attr_accessor :mount_point
# The type of filesystem mount, e.g. ufs, nfs, etc.
attr_accessor :mount_type
# A list of comma separated options for the mount, e.g. nosuid, etc.
attr_accessor :options
# The time the filesystem was mounted. May be nil.
attr_accessor :mount_time
# The dump frequency in days. May be nil.
attr_accessor :dump_frequency
# The pass number of the filessytem check. May be nil.
attr_accessor :pass_number
alias fsname name
alias dir mount_point
alias opts options
alias passno pass_number
alias freq dump_frequency
# Creates a Sys::Filesystem::Mount object. This is meant for internal
# use only. Do no instantiate directly.
#
def initialize
@name = nil
@mount_point = nil
@mount_type = nil
@options = nil
@mount_time = nil
@dump_frequency = nil
@pass_number = nil
end
end
# 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)
#
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
# DragonFlyBSD has additional struct members
if RbConfig::CONFIG['host_os'] =~ /dragonfly/i
obj.owner = fs[:f_owner]
obj.filesystem_type = fs[:f_type]
obj.sync_reads = fs[:f_syncreads]
obj.async_reads = fs[:f_asyncreads]
obj.sync_writes = fs[:f_syncwrites]
obj.async_writes = fs[:f_asyncwrites]
end
obj.freeze
end
# 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
# }
#
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
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
ensure
if fp && !fp.null?
if respond_to?(:endmntent, true)
endmntent(fp)
else
fclose(fp)
end
end
end
end
array
end
# Returns the mount point of the given +file+, or itself if it cannot
# be found.
#
# Example:
#
# Sys::Filesystem.mount_point('/home/some_user') # => /home
#
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
# 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)
#
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
# Removes the attachment of the (topmost) filesystem mounted on target.
# You may also specify bitwise OR'd +flags+ to control the precise behavior.
# The possible flags on Linux are:
#
# * MNT_FORCE - Abort pending requests, may cause data loss.
# * MNT_DETACH - Lazy umount, waits until the mount point is no longer busy.
# * MNT_EXPIRE - Mark mount point as expired, but don't actually remove it until
# a second call MNT_EXPIRE call is made.
#
# * UMOUNT_NOFOLLOW - Don't dereference the target if it's a symbolic link.
#
# Note that BSD platforms may support different flags. Please see the man
# pages for details.
#
# Typically this method requires admin privileges.
#
def self.umount(target, flags = 0)
if umount_c(target, flags) != 0
raise Error, "umount function failed: #{strerror(FFI.errno)}"
end
self
end
end
end
sys-filesystem-1.5.4/lib/sys/unix/sys/filesystem/ 0000755 0000041 0000041 00000000000 15061232103 022113 5 ustar www-data www-data sys-filesystem-1.5.4/lib/sys/unix/sys/filesystem/functions.rb 0000644 0000041 0000041 00000004135 15061232103 024453 0 ustar www-data www-data # frozen_string_literal: true
require 'ffi'
module Sys
class Filesystem
# A scoped module for internal FFI functions to be used by the main code.
module Functions
extend FFI::Library
ffi_lib FFI::Library::LIBC
def self.linux64?
if RUBY_PLATFORM == 'java'
RbConfig::CONFIG['host_os'] =~ /linux/i &&
ENV_JAVA['sun.arch.data.model'].to_i == 64
else
RbConfig::CONFIG['host_os'] =~ /linux/i &&
(RbConfig::CONFIG['arch'] =~ /64/ || RbConfig::CONFIG['DEFS'] =~ /64/ || [nil].pack('P').size == 8)
end
end
private_class_method :linux64?
if linux64?
begin
attach_function(:statvfs, :statvfs64, %i[string pointer], :int)
rescue FFI::NotFoundError # Not every Linux distro has an alias
attach_function(:statvfs, %i[string pointer], :int)
end
else
attach_function(:statvfs, %i[string pointer], :int)
end
attach_function(:strerror, [:int], :string)
attach_function(:mount_c, :mount, %i[string string string ulong string], :int)
if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach|bsd|dragonfly/i
attach_function(:umount_c, :unmount, %i[string int], :int)
else
attach_function(:umount_c, :umount2, %i[string int], :int)
end
private_class_method :statvfs, :strerror, :mount_c, :umount_c
begin
attach_function(:getmntent, [:pointer], :pointer)
attach_function(:setmntent, %i[string string], :pointer)
attach_function(:endmntent, [:pointer], :int)
private_class_method :getmntent, :setmntent, :endmntent
rescue FFI::NotFoundError
if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach/i
begin
attach_function(:getmntinfo, :getmntinfo64, %i[pointer int], :int)
rescue FFI::NotFoundError
attach_function(:getmntinfo, %i[pointer int], :int) # Big Sur and later
end
else
attach_function(:getmntinfo, %i[pointer int], :int)
end
private_class_method :getmntinfo
end
end
end
end
sys-filesystem-1.5.4/lib/sys/unix/sys/filesystem/structs.rb 0000644 0000041 0000041 00000017413 15061232103 024155 0 ustar www-data www-data # frozen_string_literal: true
require 'ffi'
require 'rbconfig'
module Sys
class Filesystem
module Structs
# Used by DragonFlyBSD
class UUID < FFI::Struct
UUID_NODE_LEN = 6
layout(
:time_low, :uint32,
:time_mid, :uint16,
:time_hi_and_version, :uint16,
:clock_seq_hi_and_reserved, :uint8,
:clock_seq_low, :uint8,
:node, [:uint8, UUID_NODE_LEN]
)
end
# The Statfs struct is a subclass of FFI::Struct that corresponds to a struct statfs.
class Statfs < FFI::Struct
# Private method that will determine the layout of the struct on Linux.
def self.linux64?
if RUBY_PLATFORM == 'java'
ENV_JAVA['sun.arch.data.model'].to_i == 64
else
RbConfig::CONFIG['host_os'] =~ /linux/i &&
(RbConfig::CONFIG['arch'] =~ /64/ || RbConfig::CONFIG['DEFS'] =~ /64/ || [nil].pack('P').size == 8)
end
end
private_class_method :linux64?
# FreeBSD 12.0 MNAMELEN from 88 => 1024.
MNAMELEN =
if RbConfig::CONFIG['host_os'] =~ /freebsd(.*)/i
Regexp.last_match(1).to_f < 12.0 ? 88 : 1024
else
88
end
case RbConfig::CONFIG['host_os']
when /bsd/i
layout(
:f_version, :uint32,
:f_type, :uint32,
:f_flags, :uint64,
:f_bsize, :uint64,
:f_iosize, :int64,
:f_blocks, :uint64,
:f_bfree, :uint64,
:f_bavail, :int64,
:f_files, :uint64,
:f_ffree, :uint64,
:f_syncwrites, :uint64,
:f_asyncwrites, :uint64,
:f_syncreads, :uint64,
:f_asyncreads, :uint64,
:f_spare, [:uint64, 10],
:f_namemax, :uint32,
:f_owner, :int32,
:f_fsid, [:int32, 2],
:f_charspare, [:char, 80],
:f_fstypename, [:char, 16],
:f_mntfromname, [:char, MNAMELEN],
:f_mntonname, [:char, MNAMELEN]
)
when /linux/i
if linux64?
layout(
:f_type, :ulong,
:f_bsize, :ulong,
:f_blocks, :uint64,
:f_bfree, :uint64,
:f_bavail, :uint64,
:f_files, :uint64,
:f_ffree, :uint64,
:f_fsid, [:int, 2],
:f_namelen, :ulong,
:f_frsize, :ulong,
:f_flags, :ulong,
:f_spare, [:ulong, 4]
)
else
layout(
:f_type, :ulong,
:f_bsize, :ulong,
:f_blocks, :uint32,
:f_bfree, :uint32,
:f_bavail, :uint32,
:f_files, :uint32,
:f_ffree, :uint32,
:f_fsid, [:int, 2],
:f_namelen, :ulong,
:f_frsize, :ulong,
:f_flags, :ulong,
:f_spare, [:ulong, 4]
)
end
when /dragonfly/i
layout(
:f_spare2, :long,
:f_bsize, :long,
:f_iosize, :long,
:f_blocks, :long,
:f_bfree, :long,
:f_bavail, :long,
:f_files, :long,
:f_ffree, :long,
:f_fsid, [:int32_t, 2],
:f_owner, :uid_t,
:f_type, :int,
:f_flags, :int,
:f_syncwrites, :long,
:f_asyncwrites, :long,
:f_fstypename, [:char, 16],
:f_mntonname, [:char, 80],
:f_syncreads, :long,
:f_asyncreads, :long,
:f_spares1, :short,
:f_mntfromname, [:char, 80],
:f_spares2, :short,
:f_spare, [:long, 2]
)
else
layout(
:f_bsize, :uint32,
:f_iosize, :int32,
:f_blocks, :uint64,
:f_bfree, :uint64,
:f_bavail, :uint64,
:f_files, :uint64,
:f_ffree, :uint64,
:f_fsid, [:int32, 2],
:f_owner, :int32,
:f_type, :uint32,
:f_flags, :uint32,
:f_fssubtype, :uint32,
:f_fstypename, [:char, 16],
:f_mntonname, [:char, 1024],
:f_mntfromname, [:char, 1024],
:f_reserved, [:uint32, 8]
)
end
end
# The Statvfs struct represents struct statvfs from sys/statvfs.h.
class Statvfs < FFI::Struct
# Private method that will determine the layout of the struct on Linux.
def self.linux64?
if RUBY_PLATFORM == 'java'
ENV_JAVA['sun.arch.data.model'].to_i == 64
else
RbConfig::CONFIG['host_os'] =~ /linux/i &&
(RbConfig::CONFIG['arch'] =~ /64/ || RbConfig::CONFIG['DEFS'] =~ /64/ || [nil].pack('P').size == 8)
end
end
if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach/i
layout(
:f_bsize, :ulong,
:f_frsize, :ulong,
:f_blocks, :uint,
:f_bfree, :uint,
:f_bavail, :uint,
:f_files, :uint,
:f_ffree, :uint,
:f_favail, :uint,
:f_fsid, :ulong,
:f_flag, :ulong,
:f_namemax, :ulong
)
elsif RbConfig::CONFIG['host'] =~ /bsd/i
layout(
:f_bavail, :uint64,
:f_bfree, :uint64,
:f_blocks, :uint64,
:f_favail, :uint64,
:f_ffree, :uint64,
:f_files, :uint64,
:f_bsize, :ulong,
:f_flag, :ulong,
:f_frsize, :ulong,
:f_fsid, :ulong,
:f_namemax, :ulong
)
elsif RbConfig::CONFIG['host'] =~ /dragonfly/i
layout(
:f_bsize, :ulong,
:f_frsize, :ulong,
:f_blocks, :uint64,
:f_bfree, :uint64,
:f_bavail, :uint64,
:f_files, :uint64,
:f_ffree, :uint64,
:f_favail, :uint64,
:f_fsid, :ulong,
:f_flag, :ulong,
:f_namemax, :ulong,
:f_owner, :uid_t,
:f_type, :uint,
:f_syncreads, :uint64,
:f_syncwrites, :uint64,
:f_asyncreads, :uint64,
:f_asyncwrites, :uint64,
:f_fsid_uuid, UUID,
:f_uid_uuid, UUID
)
elsif !linux64?
layout(
:f_bsize, :ulong,
:f_frsize, :ulong,
:f_blocks, :uint,
:f_bfree, :uint,
:f_bavail, :uint,
:f_files, :uint,
:f_ffree, :uint,
:f_favail, :uint,
:f_fsid, :ulong,
:f_unused, :int,
:f_flag, :ulong,
:f_namemax, :ulong,
:f_type, :uint,
:f_spare, [:int, 5]
)
else
layout(
:f_bsize, :ulong,
:f_frsize, :ulong,
:f_blocks, :uint64,
:f_bfree, :uint64,
:f_bavail, :uint64,
:f_files, :uint64,
:f_ffree, :uint64,
:f_favail, :uint64,
:f_fsid, :ulong,
:f_flag, :ulong,
:f_namemax, :ulong,
:f_type, :uint,
:f_spare, [:int, 5]
)
end
end
# The Mntent struct represents struct mntent from sys/mount.h on Unix.
class Mntent < FFI::Struct
layout(
:mnt_fsname, :string,
:mnt_dir, :string,
:mnt_type, :string,
:mnt_opts, :string,
:mnt_freq, :int,
:mnt_passno, :int
)
end
end
end
end
sys-filesystem-1.5.4/lib/sys/unix/sys/filesystem/constants.rb 0000644 0000041 0000041 00000005477 15061232103 024471 0 ustar www-data www-data # frozen_string_literal: true
module Sys
class Filesystem
module Constants
MNT_RDONLY = 0x00000001 # read only filesystem
MNT_SYNCHRONOUS = 0x00000002 # file system written synchronously
MNT_NOEXEC = 0x00000004 # can't exec from filesystem
MNT_NOSUID = 0x00000008 # don't honor setuid bits on fs
MNT_NODEV = 0x00000010 # don't interpret special files
MNT_UNION = 0x00000020 # union with underlying filesystem
MNT_ASYNC = 0x00000040 # file system written asynchronously
MNT_CPROTECT = 0x00000080 # file system supports content protection
MNT_EXPORTED = 0x00000100 # file system is exported
MNT_QUARANTINE = 0x00000400 # file system is quarantined
MNT_LOCAL = 0x00001000 # filesystem is stored locally
MNT_QUOTA = 0x00002000 # quotas are enabled on filesystem
MNT_ROOTFS = 0x00004000 # identifies the root filesystem
MNT_DOVOLFS = 0x00008000 # FS supports volfs (deprecated)
MNT_DONTBROWSE = 0x00100000 # FS is not appropriate path to user data
MNT_IGNORE_OWNERSHIP = 0x00200000 # VFS will ignore ownership info on FS objects
MNT_AUTOMOUNTED = 0x00400000 # filesystem was mounted by automounter
MNT_JOURNALED = 0x00800000 # filesystem is journaled
MNT_NOUSERXATTR = 0x01000000 # Don't allow user extended attributes
MNT_DEFWRITE = 0x02000000 # filesystem should defer writes
MNT_MULTILABEL = 0x04000000 # MAC support for individual labels
MNT_NOATIME = 0x10000000 # disable update of file access time
MNT_NOCLUSTERR = 0x40000000 # disable cluster read
MNT_NOCLUSTERW = 0x80000000 # disable cluster write
MNT_VISFLAGMASK = (
MNT_RDONLY | MNT_SYNCHRONOUS | MNT_NOEXEC |
MNT_NOSUID | MNT_NODEV | MNT_UNION |
MNT_ASYNC | MNT_EXPORTED | MNT_QUARANTINE |
MNT_LOCAL | MNT_QUOTA |
MNT_ROOTFS | MNT_DOVOLFS | MNT_DONTBROWSE |
MNT_IGNORE_OWNERSHIP | MNT_AUTOMOUNTED | MNT_JOURNALED |
MNT_NOUSERXATTR | MNT_DEFWRITE | MNT_MULTILABEL |
MNT_NOATIME | MNT_CPROTECT
)
MS_RDONLY = 1
MS_NOSUID = 2
MS_NODEV = 4
MS_NOEXEC = 8
MS_SYNCHRONOUS = 16
MS_REMOUNT = 32
MS_MANDLOCK = 64
MS_DIRSYNC = 128
MS_NOATIME = 1024
MS_NODIRATIME = 2048
MS_BIND = 4096
MS_MOVE = 8192
MS_REC = 16384
MS_SILENT = 32768
MS_POSIXACL = 1 << 16
MS_UNBINDABLE = 1 << 17
MS_PRIVATE = 1 << 18
MS_SLAVE = 1 << 19
MS_SHARED = 1 << 20
MS_RELATIME = 1 << 21
MS_KERNMOUNT = 1 << 22
MS_I_VERSION = 1 << 23
MS_STRICTATIME = 1 << 24
MS_ACTIVE = 1 << 30
MS_NOUSER = 1 << 31
MNT_FORCE = 1
MNT_DETACH = 2
MNT_EXPIRE = 4
UMOUNT_NOFOLLOW = 8
end
end
end
sys-filesystem-1.5.4/lib/sys/filesystem.rb 0000644 0000041 0000041 00000003747 15061232103 020652 0 ustar www-data www-data # frozen_string_literal: true
require 'rbconfig'
if File::ALT_SEPARATOR
require_relative 'windows/sys/filesystem'
else
require_relative 'unix/sys/filesystem'
end
# Methods and properties universal to all platforms
# The Sys module serves as a namespace only.
module Sys
# The Filesystem class serves as an abstract base class. Its methods
# return objects of other types. Do not instantiate.
class Filesystem
# The version of the sys-filesystem library
VERSION = '1.5.4'
# Stat objects are returned by the Sys::Filesystem.stat method. Here
# we're adding universal methods.
class Stat
# Returns true if the filesystem is case sensitive for the current path.
# Typically this will be any path on MS Windows or Macs using HFS.
#
# For a root path (really any path without actual a-z characters) we
# take a best guess based on the host operating system. However, as a
# general rule, I do not recommend using this method for a root path.
#
def case_insensitive?
if path =~ /\w+/
File.identical?(path, path.swapcase)
elsif RbConfig::CONFIG['host_os'] =~ /darwin|mac|windows|mswin|mingw/i
true # Assumes HFS/APFS on Mac
else
false
end
end
# Opposite of case_insensitive?
#
def case_sensitive?
!case_insensitive?
end
end
end
end
# Reopen the Numeric class and add some convenient methods
# for converting bytes to kb, mb, and gb.
class Numeric
# call-seq:
# num.to_kb
#
# Returns +num+ in terms of kilobytes.
def to_kb
self / 1024
end
# call-seq:
# num.to_mb
#
# Returns +num+ in terms of megabytes.
def to_mb
self / 1048576
end
# call-seq:
# num.to_gb
#
# Returns +num+ in terms of gigabytes.
def to_gb
self / 1073741824
end
# call-seq:
# num.to_gb
#
# Returns +num+ in terms of terabytes.
def to_tb
self / 1099511627776
end
end
sys-filesystem-1.5.4/spec/ 0000755 0000041 0000041 00000000000 15061232103 015474 5 ustar www-data www-data sys-filesystem-1.5.4/spec/spec_helper.rb 0000644 0000041 0000041 00000000562 15061232103 020315 0 ustar www-data www-data # frozen_string_literal: true
require 'rspec'
require 'sys_filesystem_shared'
RSpec.configure do |config|
config.include_context(Sys::Filesystem)
config.filter_run_excluding(:windows) unless Gem.win_platform?
config.filter_run_excluding(:unix) if Gem.win_platform?
config.filter_run_excluding(:dragonfly) unless RbConfig::CONFIG['host_os'] =~ /dragonfly/i
end
sys-filesystem-1.5.4/spec/sys_filesystem_windows_spec.rb 0000644 0000041 0000041 00000035345 15061232103 023701 0 ustar www-data www-data # frozen_string_literal: true
####################################################################
# sys_filesystem_windows_spec.rb
#
# Specs for the Sys::Filesystem.stat method and related stuff.
# This should be run via the 'rake spec' task.
####################################################################
require 'spec_helper'
require 'sys/filesystem'
require 'pathname'
RSpec.describe Sys::Filesystem, :windows do
let(:root) { 'C:/' }
before do
@stat = described_class.stat(root)
@size = 58720256
end
example 'stat path works as expected' do
expect(@stat).to respond_to(:path)
expect(@stat.path).to eq(root)
end
example 'stat block_size works as expected' do
expect(@stat).to respond_to(:block_size)
expect(@stat.block_size).to be_a(Numeric)
end
example 'stat works with or without trailing slash on standard paths' do
expect(described_class.stat('C:/').path).to eq('C:/')
expect(described_class.stat('C:/Users').path).to eq('C:/Users')
expect(described_class.stat('C:/Users/').path).to eq('C:/Users/')
expect(described_class.stat('C:/Users/').path).to eq('C:/Users/')
end
example 'stat works with or without trailing slash on UNC paths' do
expect(described_class.stat('//127.0.0.1/C$').path).to eq('//127.0.0.1/C$')
expect(described_class.stat('//127.0.0.1/C$/').path).to eq('//127.0.0.1/C$/')
expect(described_class.stat('\\\\127.0.0.1\\C$').path).to eq('\\\\127.0.0.1\\C$')
expect(described_class.stat('\\\\127.0.0.1\\C$\\').path).to eq('\\\\127.0.0.1\\C$\\')
end
example 'stat fragment_size works as expected' do
expect(@stat).to respond_to(:fragment_size)
expect(@stat.fragment_size).to be_nil
end
example 'stat blocks works as expected' do
expect(@stat).to respond_to(:blocks)
expect(@stat.blocks).to be_a(Numeric)
end
example 'stat blocks_free works as expected' do
expect(@stat).to respond_to(:blocks_free)
expect(@stat.blocks_free).to be_a(Numeric)
end
example 'stat blocks_available works as expected' do
expect(@stat).to respond_to(:blocks_available)
expect(@stat.blocks_available).to be_a(Numeric)
end
example 'block stats return expected relative values' do
expect(@stat.blocks >= @stat.blocks_free).to be true
expect(@stat.blocks_free >= @stat.blocks_available).to be true
end
example 'stat files works as expected' do
expect(@stat).to respond_to(:files)
expect(@stat.files).to be_nil
end
example 'stat inodes is an alias for files' do
expect(@stat.method(:inodes)).to eq(@stat.method(:files))
end
example 'stat files_free works as expected' do
expect(@stat).to respond_to(:files_free)
expect(@stat.files_free).to be_nil
end
example 'stat inodes_free is an alias for files_free' do
expect(@stat).to respond_to(:inodes_free)
end
example 'stat files available works as expected' do
expect(@stat).to respond_to(:files_available)
expect(@stat.files_available).to be_nil
end
example 'stat inodes_available is an alias for files_available' do
expect(@stat.method(:inodes_available)).to eq(@stat.method(:files_available))
end
example 'stat filesystem_id works as expected' do
expect(@stat).to respond_to(:filesystem_id)
expect(@stat.filesystem_id).to be_a(Integer)
end
example 'stat flags works as expected' do
expect(@stat).to respond_to(:flags)
expect(@stat.flags).to be_a(Numeric)
end
example 'stat name_max works as expected' do
expect(@stat).to respond_to(:name_max)
expect(@stat.name_max).to be_a(Numeric)
end
example 'stat base_type works as expected' do
expect(@stat).to respond_to(:base_type)
expect(@stat.base_type).to be_a(String)
end
example 'stat bytes_total basic functionality' do
expect(@stat).to respond_to(:bytes_total)
expect(@stat.bytes_total).to be_a(Numeric)
end
example 'stat bytes_free basic functionality' do
expect(@stat).to respond_to(:bytes_free)
expect(@stat.bytes_free).to be_a(Numeric)
expect(@stat.blocks_free * @stat.block_size).to eq(@stat.bytes_free)
end
example 'stat bytes_available basic functionality' do
expect(@stat).to respond_to(:bytes_available)
expect(@stat.bytes_available).to be_a(Numeric)
expect(@stat.blocks_available * @stat.block_size).to eq(@stat.bytes_available)
end
example 'stat bytes_used basic functionality' do
expect(@stat).to respond_to(:bytes_used)
expect(@stat.bytes_used).to be_a(Numeric)
end
example 'stat percent_used basic functionality' do
expect(@stat).to respond_to(:percent_used)
expect(@stat.percent_used).to be_a(Float)
end
example 'case_insensitive returns expected result' do
expect(@stat).to respond_to(:case_insensitive?)
expect(@stat.case_insensitive?).to be(true)
end
context 'Filesystem.stat(Pathname)' do
before do
@stat_pathname = described_class.stat(Pathname.new(root))
end
example 'class returns expected value with pathname argument' do
expect(@stat_pathname.class).to eq(@stat.class)
end
example 'path returns expected value with pathname argument' do
expect(@stat_pathname.path).to eq(@stat.path)
end
example 'block_size returns expected value with pathname argument' do
expect(@stat_pathname.block_size).to eq(@stat.block_size)
end
example 'fragment_size returns expected value with pathname argument' do
expect(@stat_pathname.fragment_size).to eq(@stat.fragment_size)
end
example 'blocks returns expected value with pathname argument' do
expect(@stat_pathname.blocks).to eq(@stat.blocks)
end
example 'blocks_free returns expected value with pathname argument' do
expect(@stat_pathname.blocks_free).to eq(@stat.blocks_free)
end
example 'blocks_available returns expected value with pathname argument' do
expect(@stat_pathname.blocks_available).to eq(@stat.blocks_available)
end
example 'files returns expected value with pathname argument' do
expect(@stat_pathname.files).to eq(@stat.files)
end
example 'files_free returns expected value with pathname argument' do
expect(@stat_pathname.files_free).to eq(@stat.files_free)
end
example 'files_available returns expected value with pathname argument' do
expect(@stat_pathname.files_available).to eq(@stat.files_available)
end
example 'filesystem_id returns expected value with pathname argument' do
expect(@stat_pathname.filesystem_id).to eq(@stat.filesystem_id)
end
example 'flags returns expected value with pathname argument' do
expect(@stat_pathname.flags).to eq(@stat.flags)
end
example 'name_max returns expected value with pathname argument' do
expect(@stat_pathname.name_max).to eq(@stat.name_max)
end
example 'base_type returns expected value with pathname argument' do
expect(@stat_pathname.base_type).to eq(@stat.base_type)
end
end
context 'Filesystem.stat(Dir)' do
before do
@stat_dir = Dir.open(root){ |dir| described_class.stat(dir) }
end
example 'stat class with Dir argument works as expected' do
expect(@stat_dir.class).to eq(@stat.class)
end
example 'stat path with Dir argument works as expected' do
expect(@stat_dir.path).to eq(@stat.path)
end
example 'stat block_size with Dir argument works as expected' do
expect(@stat_dir.block_size).to eq(@stat.block_size)
end
example 'stat fragment_size with Dir argument works as expected' do
expect(@stat_dir.fragment_size).to eq(@stat.fragment_size)
end
example 'stat blocks with Dir argument works as expected' do
expect(@stat_dir.blocks).to eq(@stat.blocks)
end
example 'stat blocks_free with Dir argument works as expected' do
expect(@stat_dir.blocks_free).to eq(@stat.blocks_free)
end
example 'stat blocks_available with Dir argument works as expected' do
expect(@stat_dir.blocks_available).to eq(@stat.blocks_available)
end
example 'stat files with Dir argument works as expected' do
expect(@stat_dir.files).to eq(@stat.files)
end
example 'stat files_free with Dir argument works as expected' do
expect(@stat_dir.files_free).to eq(@stat.files_free)
end
example 'stat files_available with Dir argument works as expected' do
expect(@stat_dir.files_available).to eq(@stat.files_available)
end
example 'stat filesystem_id with Dir argument works as expected' do
expect(@stat_dir.filesystem_id).to eq(@stat.filesystem_id)
end
example 'stat flags with Dir argument works as expected' do
expect(@stat_dir.flags).to eq(@stat.flags)
end
example 'stat name_max with Dir argument works as expected' do
expect(@stat_dir.name_max).to eq(@stat.name_max)
end
example 'stat base_type with Dir argument works as expected' do
expect(@stat_dir.base_type).to eq(@stat.base_type)
end
end
context 'mount_point' do
example 'mount_point singleton method basic functionality' do
expect(described_class).to respond_to(:mount_point)
expect{ described_class.mount_point(Dir.pwd) }.not_to raise_error
expect(described_class.mount_point(Dir.pwd)).to be_a(String)
end
example 'mount_point singleton method returns expected value' do
expect(described_class.mount_point('C:\\Users\\foo')).to eq('C:\\')
expect(described_class.mount_point('//foo/bar/baz')).to eq('\\\\foo\\bar')
end
example 'mount_point works with Pathname object' do
expect{ described_class.mount_point(Pathname.new('C:/Users/foo')) }.not_to raise_error
expect(described_class.mount_point('C:\\Users\\foo')).to eq('C:\\')
expect(described_class.mount_point('//foo/bar/baz')).to eq('\\\\foo\\bar')
end
end
context 'filesystem constants are defined' do
example 'CASE_SENSITIVE_SEARCH' do
expect(Sys::Filesystem::CASE_SENSITIVE_SEARCH).not_to be_nil
end
example 'CASE_PRESERVED_NAMES' do
expect(Sys::Filesystem::CASE_PRESERVED_NAMES).not_to be_nil
end
example 'UNICODE_ON_DISK' do
expect(Sys::Filesystem::UNICODE_ON_DISK).not_to be_nil
end
example 'PERSISTENT_ACLS' do
expect(Sys::Filesystem::PERSISTENT_ACLS).not_to be_nil
end
example 'FILE_COMPRESSION' do
expect(Sys::Filesystem::FILE_COMPRESSION).not_to be_nil
end
example 'VOLUME_QUOTAS' do
expect(Sys::Filesystem::VOLUME_QUOTAS).not_to be_nil
end
example 'SUPPORTS_SPARSE_FILES' do
expect(Sys::Filesystem::SUPPORTS_SPARSE_FILES).not_to be_nil
end
example 'SUPPORTS_REPARSE_POINTS' do
expect(Sys::Filesystem::SUPPORTS_REPARSE_POINTS).not_to be_nil
end
example 'SUPPORTS_REMOTE_STORAGE' do
expect(Sys::Filesystem::SUPPORTS_REMOTE_STORAGE).not_to be_nil
end
example 'VOLUME_IS_COMPRESSED' do
expect(Sys::Filesystem::VOLUME_IS_COMPRESSED).not_to be_nil
end
example 'SUPPORTS_OBJECT_IDS' do
expect(Sys::Filesystem::SUPPORTS_OBJECT_IDS).not_to be_nil
end
example 'SUPPORTS_ENCRYPTION' do
expect(Sys::Filesystem::SUPPORTS_ENCRYPTION).not_to be_nil
end
example 'NAMED_STREAMS' do
expect(Sys::Filesystem::NAMED_STREAMS).not_to be_nil
end
example 'READ_ONLY_VOLUME' do
expect(Sys::Filesystem::READ_ONLY_VOLUME).not_to be_nil
end
end
example 'stat singleton method defaults to root path if proviced' do
expect{ described_class.stat('C://Program Files') }.not_to raise_error
end
example 'stat singleton method accepts a Pathname object' do
expect{ described_class.stat(Pathname.new('C://Program Files')) }.not_to raise_error
end
example 'stat singleton method requires a single argument' do
expect{ described_class.stat }.to raise_error(ArgumentError)
expect{ described_class.stat(Dir.pwd, Dir.pwd) }.to raise_error(ArgumentError)
end
example 'stat singleton method raises an error if path is not found' do
expect{ described_class.stat('C://Bogus//Dir') }.to raise_error(Errno::ESRCH)
end
context 'Filesystem::Mount' do
let(:mount){ described_class.mounts[0] }
before do
@array = []
end
example 'mount singleton method exists' do
expect(described_class).to respond_to(:mount)
end
example 'umount singleton method exists' do
expect(described_class).to respond_to(:umount)
end
example 'mounts singleton method basic functionality' do
expect(described_class).to respond_to(:mounts)
expect{ described_class.mounts }.not_to raise_error
expect{ described_class.mounts{} }.not_to raise_error
end
example 'mounts singleton method returns the expected value' do
expect(described_class.mounts).to be_a(Array)
expect(described_class.mounts[0]).to be_a(Sys::Filesystem::Mount)
end
example 'mounts singleton method works as expected when a block is provided' do
expect(described_class.mounts{}).to be_nil
expect{ described_class.mounts{ |mt| @array << mt } }.not_to raise_error
expect(@array[0]).to be_a(Sys::Filesystem::Mount)
end
example 'mount name works as expected' do
expect(mount).to respond_to(:name)
expect(mount.name).to be_a(String)
end
example 'mount_time works as expected' do
expect(mount).to respond_to(:mount_time)
expect(mount.mount_time).to be_a(Time)
end
example 'mount type works as expected' do
expect(mount).to respond_to(:mount_type)
expect(mount.mount_type).to be_a(String)
end
example 'mount point works as expected' do
expect(mount).to respond_to(:mount_point)
expect(mount.mount_point).to be_a(String)
end
example 'mount options works as expected' do
expect(mount).to respond_to(:options)
expect(mount.options).to be_a(String)
end
example 'mount pass_number works as expected' do
expect(mount).to respond_to(:pass_number)
expect(mount.pass_number).to be_nil
end
example 'mount frequency works as expected' do
expect(mount).to respond_to(:frequency)
expect(mount.frequency).to be_nil
end
example 'mounts singleton method does not accept any arguments' do
expect{ described_class.mounts('C:\\') }.to raise_error(ArgumentError)
end
end
example 'custom Numeric#to_kb method works as expected' do
expect(@size).to respond_to(:to_kb)
expect(@size.to_kb).to eq(57344)
end
example 'custom Numeric#to_mb method works as expected' do
expect(@size).to respond_to(:to_mb)
expect(@size.to_mb).to eq(56)
end
example 'custom Numeric#to_gb method works as expected' do
expect(@size).to respond_to(:to_gb)
expect(@size.to_gb).to eq(0)
end
context 'FFI' do
example 'internal ffi functions are not public' do
expect(described_class.methods.include?(:GetVolumeInformationA)).to be(false)
expect(described_class.instance_methods.include?(:GetVolumeInformationA)).to be(false)
end
end
end
sys-filesystem-1.5.4/spec/sys_filesystem_unix_spec.rb 0000644 0000041 0000041 00000063570 15061232103 023173 0 ustar www-data www-data # frozen_string_literal: true
####################################################################
# sys_filesystem_unix_spec.rb
#
# Specs for the Sys::Filesystem.stat method and related stuff.
# This test suite should be run via the 'rake spec' task.
####################################################################
require 'spec_helper'
require 'sys-filesystem'
require 'pathname'
RSpec.describe Sys::Filesystem, :unix do
let(:linux) { RbConfig::CONFIG['host_os'] =~ /linux/i }
let(:bsd) { RbConfig::CONFIG['host_os'] =~ /bsd|dragonfly/i }
let(:darwin) { RbConfig::CONFIG['host_os'] =~ /mac|darwin/i }
let(:root) { '/' }
before do
@stat = described_class.stat(root)
@size = 58720256
end
example 'stat path works as expected' do
expect(@stat).to respond_to(:path)
expect(@stat.path).to eq(root)
end
example 'stat block_size works as expected' do
expect(@stat).to respond_to(:block_size)
expect(@stat.block_size).to be_a(Numeric)
end
example 'stat fragment_size works as expected' do
expect(@stat).to respond_to(:fragment_size)
expect(@stat.fragment_size).to be_a(Numeric)
end
example 'stat fragment_size is a plausible value' do
expect(@stat.fragment_size).to be >= 512
expect(@stat.fragment_size).to be <= 2**16
expect(@stat.fragment_size).to be <= @stat.block_size
end
example 'stat blocks works as expected' do
expect(@stat).to respond_to(:blocks)
expect(@stat.blocks).to be_a(Numeric)
end
example 'stat blocks_free works as expected' do
expect(@stat).to respond_to(:blocks_free)
expect(@stat.blocks_free).to be_a(Numeric)
end
example 'stat blocks_available works as expected' do
expect(@stat).to respond_to(:blocks_available)
expect(@stat.blocks_available).to be_a(Numeric)
end
example 'stat files works as expected' do
expect(@stat).to respond_to(:files)
expect(@stat.files).to be_a(Numeric)
end
example 'stat inodes is an alias for files' do
expect(@stat).to respond_to(:inodes)
expect(@stat.method(:inodes)).to eq(@stat.method(:files))
end
example 'stat files tree works as expected' do
expect(@stat).to respond_to(:files_free)
expect(@stat.files_free).to be_a(Numeric)
end
example 'stat inodes_free is an alias for files_free' do
expect(@stat).to respond_to(:inodes_free)
expect(@stat.method(:inodes_free)).to eq(@stat.method(:files_free))
end
example 'stat files_available works as expected' do
expect(@stat).to respond_to(:files_available)
expect(@stat.files_available).to be_a(Numeric)
end
example 'stat inodes_available is an alias for files_available' do
expect(@stat).to respond_to(:inodes_available)
expect(@stat.method(:inodes_available)).to eq(@stat.method(:files_available))
end
example 'stat filesystem_id works as expected' do
expect(@stat).to respond_to(:filesystem_id)
expect(@stat.filesystem_id).to be_a(Integer)
end
example 'stat flags works as expected' do
expect(@stat).to respond_to(:flags)
expect(@stat.flags).to be_a(Numeric)
end
example 'stat name_max works as expected' do
expect(@stat).to respond_to(:name_max)
expect(@stat.name_max).to be_a(Numeric)
end
context 'dragonfly', :dragonfly do
example 'owner works as expected' do
expect(@stat).to respond_to(:owner)
expect(@stat.owner).to be_a(Numeric)
end
example 'filesystem_type works as expected' do
expect(@stat).to respond_to(:filesystem_type)
expect(@stat.filesystem_type).to be_a(Numeric)
end
example 'sync_reads works as expected' do
expect(@stat).to respond_to(:sync_reads)
expect(@stat.sync_reads).to be_a(Numeric)
end
example 'async_reads works as expected' do
expect(@stat).to respond_to(:async_reads)
expect(@stat.async_reads).to be_a(Numeric)
end
example 'sync_writes works as expected' do
expect(@stat).to respond_to(:sync_writes)
expect(@stat.sync_writes).to be_a(Numeric)
end
example 'async_writes works as expected' do
expect(@stat).to respond_to(:async_writes)
expect(@stat.async_writes).to be_a(Numeric)
end
end
example 'stat constants are defined' do
expect(Sys::Filesystem::Stat::RDONLY).not_to be_nil
expect(Sys::Filesystem::Stat::NOSUID).not_to be_nil
end
example 'stat bytes_total works as expected' do
expect(@stat).to respond_to(:bytes_total)
expect(@stat.bytes_total).to be_a(Numeric)
end
example 'stat bytes_free works as expected' do
expect(@stat).to respond_to(:bytes_free)
expect(@stat.bytes_free).to be_a(Numeric)
expect(@stat.blocks_free * @stat.fragment_size).to eq(@stat.bytes_free)
end
example 'stat bytes_available works as expected' do
expect(@stat).to respond_to(:bytes_available)
expect(@stat.bytes_available).to be_a(Numeric)
expect(@stat.blocks_available * @stat.fragment_size).to eq(@stat.bytes_available)
end
example 'stat bytes works as expected' do
expect(@stat).to respond_to(:bytes_used)
expect(@stat.bytes_used).to be_a(Numeric)
end
example 'stat percent_used works as expected' do
expect(@stat).to respond_to(:percent_used)
expect(@stat.percent_used).to be_a(Float)
end
example 'stat singleton method requires an argument' do
expect{ described_class.stat }.to raise_error(ArgumentError)
end
example 'stat case_insensitive method works as expected' do
expected = darwin ? true : false
expect(@stat.case_insensitive?).to eq(expected)
expect(described_class.stat(Dir.home).case_insensitive?).to eq(expected)
end
example 'stat case_sensitive method works as expected' do
expected = darwin ? false : true
expect(@stat.case_sensitive?).to eq(expected)
expect(described_class.stat(Dir.home).case_sensitive?).to eq(expected)
end
example 'numeric helper methods are defined' do
expect(@size).to respond_to(:to_kb)
expect(@size).to respond_to(:to_mb)
expect(@size).to respond_to(:to_gb)
expect(@size).to respond_to(:to_tb)
end
example 'to_kb works as expected' do
expect(@size.to_kb).to eq(57344)
end
example 'to_mb works as expected' do
expect(@size.to_mb).to eq(56)
end
example 'to_gb works as expected' do
expect(@size.to_gb).to eq(0)
end
context 'Filesystem.stat(Pathname)' do
before do
@stat_pathname = described_class.stat(Pathname.new(root))
end
example 'class returns expected value with pathname argument' do
expect(@stat_pathname.class).to eq(@stat.class)
end
example 'path returns expected value with pathname argument' do
expect(@stat_pathname.path).to eq(@stat.path)
end
example 'block_size returns expected value with pathname argument' do
expect(@stat_pathname.block_size).to eq(@stat.block_size)
end
example 'fragment_size returns expected value with pathname argument' do
expect(@stat_pathname.fragment_size).to eq(@stat.fragment_size)
end
example 'blocks returns expected value with pathname argument' do
expect(@stat_pathname.blocks).to eq(@stat.blocks)
end
example 'blocks_free returns expected value with pathname argument' do
expect(@stat_pathname.blocks_free).to eq(@stat.blocks_free)
end
example 'blocks_available returns expected value with pathname argument' do
expect(@stat_pathname.blocks_available).to eq(@stat.blocks_available)
end
example 'files returns expected value with pathname argument' do
expect(@stat_pathname.files).to eq(@stat.files)
end
example 'files_free returns expected value with pathname argument' do
expect(@stat_pathname.files_free).to eq(@stat.files_free)
end
example 'files_available returns expected value with pathname argument' do
expect(@stat_pathname.files_available).to eq(@stat.files_available)
end
example 'filesystem_id returns expected value with pathname argument' do
expect(@stat_pathname.filesystem_id).to eq(@stat.filesystem_id)
end
example 'flags returns expected value with pathname argument' do
expect(@stat_pathname.flags).to eq(@stat.flags)
end
example 'name_max returns expected value with pathname argument' do
expect(@stat_pathname.name_max).to eq(@stat.name_max)
end
example 'base_type returns expected value with pathname argument' do
expect(@stat_pathname.base_type).to eq(@stat.base_type)
end
end
context 'Filesystem.stat(File)' do
before do
@stat_file = File.open(root){ |file| described_class.stat(file) }
end
example 'class returns expected value with file argument' do
expect(@stat_file.class).to eq(@stat.class)
end
example 'path returns expected value with file argument' do
expect(@stat_file.path).to eq(@stat.path)
end
example 'block_size returns expected value with file argument' do
expect(@stat_file.block_size).to eq(@stat.block_size)
end
example 'fragment_size returns expected value with file argument' do
expect(@stat_file.fragment_size).to eq(@stat.fragment_size)
end
example 'blocks returns expected value with file argument' do
expect(@stat_file.blocks).to eq(@stat.blocks)
end
example 'blocks_free returns expected value with file argument' do
expect(@stat_file.blocks_free).to eq(@stat.blocks_free)
end
example 'blocks_available returns expected value with file argument' do
expect(@stat_file.blocks_available).to eq(@stat.blocks_available)
end
example 'files returns expected value with file argument' do
expect(@stat_file.files).to eq(@stat.files)
end
example 'files_free returns expected value with file argument' do
expect(@stat_file.files_free).to eq(@stat.files_free)
end
example 'files_available returns expected value with file argument' do
expect(@stat_file.files_available).to eq(@stat.files_available)
end
example 'filesystem_id returns expected value with file argument' do
expect(@stat_file.filesystem_id).to eq(@stat.filesystem_id)
end
example 'flags returns expected value with file argument' do
expect(@stat_file.flags).to eq(@stat.flags)
end
example 'name_max returns expected value with file argument' do
expect(@stat_file.name_max).to eq(@stat.name_max)
end
example 'base_type returns expected value with file argument' do
expect(@stat_file.base_type).to eq(@stat.base_type)
end
end
context 'Filesystem.stat(Dir)' do
before do
@stat_dir = Dir.open(root){ |dir| described_class.stat(dir) }
end
example 'class returns expected value with Dir argument' do
expect(@stat_dir.class).to eq(@stat.class)
end
example 'path returns expected value with Dir argument' do
expect(@stat_dir.path).to eq(@stat.path)
end
example 'block_size returns expected value with Dir argument' do
expect(@stat_dir.block_size).to eq(@stat.block_size)
end
example 'fragment_size returns expected value with Dir argument' do
expect(@stat_dir.fragment_size).to eq(@stat.fragment_size)
end
example 'blocks returns expected value with Dir argument' do
expect(@stat_dir.blocks).to eq(@stat.blocks)
end
example 'blocks_free returns expected value with Dir argument' do
expect(@stat_dir.blocks_free).to eq(@stat.blocks_free)
end
example 'blocks_available returns expected value with Dir argument' do
expect(@stat_dir.blocks_available).to eq(@stat.blocks_available)
end
example 'files returns expected value with Dir argument' do
expect(@stat_dir.files).to eq(@stat.files)
end
example 'files_free returns expected value with Dir argument' do
expect(@stat_dir.files_free).to eq(@stat.files_free)
end
example 'files_available returns expected value with Dir argument' do
expect(@stat_dir.files_available).to eq(@stat.files_available)
end
example 'filesystem_id returns expected value with Dir argument' do
expect(@stat_dir.filesystem_id).to eq(@stat.filesystem_id)
end
example 'flags returns expected value with Dir argument' do
expect(@stat_dir.flags).to eq(@stat.flags)
end
example 'name_max returns expected value with Dir argument' do
expect(@stat_dir.name_max).to eq(@stat.name_max)
end
example 'base_type returns expected value with Dir argument' do
expect(@stat_dir.base_type).to eq(@stat.base_type)
end
end
context 'Filesystem::Mount' do
let(:mount){ described_class.mounts[0] }
before do
@array = []
end
example 'mounts singleton method works as expected without a block' do
expect{ @array = described_class.mounts }.not_to raise_error
expect(@array[0]).to be_a(Sys::Filesystem::Mount)
end
example 'mounts singleton method works as expected with a block' do
expect{ described_class.mounts{ |m| @array << m } }.not_to raise_error
expect(@array[0]).to be_a(Sys::Filesystem::Mount)
end
example 'calling the mounts singleton method a large number of times does not cause issues' do
expect{ 1000.times{ @array = described_class.mounts } }.not_to raise_error
end
example 'mount name method works as expected' do
expect(mount).to respond_to(:name)
expect(mount.name).to be_a(String)
end
example 'mount fsname is an alias for name' do
expect(mount).to respond_to(:fsname)
expect(mount.method(:fsname)).to eq(mount.method(:name))
end
example 'mount point method works as expected' do
expect(mount).to respond_to(:mount_point)
expect(mount.mount_point).to be_a(String)
end
example 'mount dir is an alias for mount_point' do
expect(mount).to respond_to(:dir)
expect(mount.method(:dir)).to eq(mount.method(:mount_point))
end
example 'mount mount_type works as expected' do
expect(mount).to respond_to(:mount_type)
expect(mount.mount_type).to be_a(String)
end
example 'mount options works as expected' do
expect(mount).to respond_to(:options)
expect(mount.options).to be_a(String)
end
example 'mount opts is an alias for options' do
expect(mount).to respond_to(:opts)
expect(mount.method(:opts)).to eq(mount.method(:options))
end
# This method may be removed
example 'mount time works as expected' do
expect(mount).to respond_to(:mount_time)
expect(mount.mount_time).to be_nil
end
example 'mount dump_frequency works as expected' do
msg = 'dump_frequency test skipped on this platform'
skip msg if bsd || darwin
expect(mount).to respond_to(:dump_frequency)
expect(mount.dump_frequency).to be_a(Numeric)
end
example 'mount freq is an alias for dump_frequency' do
expect(mount).to respond_to(:freq)
expect(mount.method(:freq)).to eq(mount.method(:dump_frequency))
end
example 'mount pass_number works as expected' do
msg = 'pass_number test skipped on this platform'
skip msg if bsd || darwin
expect(mount).to respond_to(:pass_number)
expect(mount.pass_number).to be_a(Numeric)
end
example 'mount passno is an alias for pass_number' do
expect(mount).to respond_to(:passno)
expect(mount.method(:passno)).to eq(mount.method(:pass_number))
end
example 'mount_point singleton method works as expected' do
expect(described_class).to respond_to(:mount_point)
expect{ described_class.mount_point(Dir.pwd) }.not_to raise_error
expect(described_class.mount_point(Dir.pwd)).to be_a(String)
end
example 'mount singleton method is defined' do
expect(described_class).to respond_to(:mount)
end
example 'umount singleton method is defined' do
expect(described_class).to respond_to(:umount)
end
end
context 'FFI' do
before(:context) do
require 'mkmf-lite'
end
let(:dummy) { Class.new { extend Mkmf::Lite } }
example 'ffi functions are private' do
expect(described_class.methods.include?('statvfs')).to be false
expect(described_class.methods.include?('strerror')).to be false
end
example 'statfs struct is expected size' do
header = bsd || darwin ? 'sys/mount.h' : 'sys/statfs.h'
expect(Sys::Filesystem::Structs::Statfs.size).to eq(dummy.check_sizeof('struct statfs', header))
end
example 'statvfs struct is expected size' do
expect(Sys::Filesystem::Structs::Statvfs.size).to eq(dummy.check_sizeof('struct statvfs', 'sys/statvfs.h'))
end
example 'mntent struct is expected size' do
skip 'mnttab test skipped except on Linux' unless linux
expect(Sys::Filesystem::Structs::Mntent.size).to eq(dummy.check_sizeof('struct mntent', 'mntent.h'))
end
example 'a failed statvfs call behaves as expected' do
msg = 'statvfs() function failed: No such file or directory'
expect{ described_class.stat('/whatever') }.to raise_error(Sys::Filesystem::Error, msg)
end
example 'statvfs alias is used for statvfs64' do
expect(Sys::Filesystem::Functions.attached_functions[:statvfs]).to be_a(FFI::Function)
expect(Sys::Filesystem::Functions.attached_functions[:statvfs64]).to be_nil
end
end
describe 'linux64? method' do
let(:functions_class) { Sys::Filesystem::Functions }
# Helper method to test linux64? with mocked config
def test_linux64_with_config(host_os, pointer_size, ruby_platform = nil, java_arch = nil)
# Mock RbConfig::CONFIG
allow(RbConfig::CONFIG).to receive(:[]).and_call_original
allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return(host_os)
# When running under JRuby, we need to handle it differently
if RUBY_PLATFORM == 'java'
# Under JRuby, always mock ENV_JAVA since that's the path the code will take
if java_arch
# This is a JRuby-specific test
allow(ENV_JAVA).to receive(:[]).with('sun.arch.data.model').and_return(java_arch.to_s)
else
# This is meant to test regular Ruby logic, but under JRuby we need to mock ENV_JAVA
# to make it take the "regular Ruby" path by returning nil/empty
expected_arch = pointer_size == 8 ? '64' : '32'
allow(ENV_JAVA).to receive(:[]).with('sun.arch.data.model').and_return(expected_arch)
end
else
# Running under regular Ruby
# Determine arch and DEFS based on host_os for the new multi-check approach
if pointer_size == 8
# For 64-bit systems, make arch contain "64"
arch_value = host_os.include?('64') ? host_os : host_os + '64'
defs_value = '-DSOMETHING=1'
else
# For 32-bit systems, ensure neither arch nor DEFS contain "64"
arch_value = host_os.gsub(/64/, '32')
defs_value = '-DSOMETHING=1'
end
allow(RbConfig::CONFIG).to receive(:[]).with('arch').and_return(arch_value)
allow(RbConfig::CONFIG).to receive(:[]).with('DEFS').and_return(defs_value)
if ruby_platform == 'java'
# Mock RUBY_PLATFORM for JRuby tests
stub_const('RUBY_PLATFORM', 'java')
# Mock ENV_JAVA for JRuby
env_java_mock = double('ENV_JAVA')
allow(env_java_mock).to receive(:[]).with('sun.arch.data.model').and_return(java_arch.to_s)
stub_const('ENV_JAVA', env_java_mock)
else
# Mock the pack method for regular Ruby (last resort check)
packed_data = 'x' * pointer_size
allow_any_instance_of(Array).to receive(:pack).with('P').and_return(packed_data)
end
end
functions_class.send(:linux64?)
end
context 'with different Linux distributions on 64-bit architectures' do
let(:linux_distros) do
{
'x86_64-linux-gnu' => 'Ubuntu/Debian x86_64',
'x86_64-pc-linux-gnu' => 'Generic x86_64 Linux',
'aarch64-linux-gnu' => 'ARM64 (Raspberry Pi 4, AWS Graviton)',
's390x-linux-gnu' => 'IBM Z mainframe',
'powerpc64le-linux-gnu' => 'POWER8/9 little-endian',
'powerpc64-linux-gnu' => 'POWER8/9 big-endian',
'mips64el-linux-gnuabi64' => 'MIPS64 little-endian',
'alpha-linux-gnu' => 'DEC Alpha',
'sparc64-linux-gnu' => 'SPARC64',
'riscv64-linux-gnu' => 'RISC-V 64-bit'
}
end
it 'returns true for 64-bit Linux systems' do
linux_distros.each do |host_os, description|
result = test_linux64_with_config(host_os, 8)
expect(result).to be_truthy, "Expected linux64? to return true for #{host_os} (#{description})"
end
end
end
context 'with different Linux distributions on 32-bit architectures' do
let(:linux_32bit_distros) do
{
'i386-linux-gnu' => '32-bit x86',
'i486-linux-gnu' => '32-bit x86',
'i586-linux-gnu' => '32-bit x86',
'i686-linux-gnu' => '32-bit x86',
'arm-linux-gnueabihf' => 'ARM 32-bit hard-float',
'armv7l-linux-gnueabihf' => 'ARMv7 32-bit',
'mips-linux-gnu' => 'MIPS 32-bit',
'mipsel-linux-gnu' => 'MIPS 32-bit little-endian',
'powerpc-linux-gnu' => 'PowerPC 32-bit',
's390-linux-gnu' => 'IBM S/390 32-bit'
}
end
it 'returns false for 32-bit Linux systems' do
linux_32bit_distros.each do |host_os, description|
result = test_linux64_with_config(host_os, 4)
expect(result).to be_falsey, "Expected linux64? to return false for #{host_os} (#{description})"
end
end
end
context 'with non-Linux operating systems' do
let(:non_linux_os) do
{
'darwin21.6.0' => 'macOS',
'freebsd13.1' => 'FreeBSD',
'openbsd7.2' => 'OpenBSD',
'netbsd9.3' => 'NetBSD',
'dragonfly6.4' => 'DragonFlyBSD',
'solaris2.11' => 'Solaris',
'aix7.2.0.0' => 'AIX',
'mingw32' => 'Windows MSYS2',
'cygwin' => 'Cygwin'
}
end
it 'returns false for non-Linux systems regardless of architecture' do
non_linux_os.each do |host_os, description|
# Test both 32-bit and 64-bit scenarios
[4, 8].each do |pointer_size|
result = test_linux64_with_config(host_os, pointer_size)
expect(result).to be_falsey,
"Expected linux64? to return false for #{host_os} (#{description}) with #{pointer_size * 8}-bit pointers"
end
end
end
end
context 'with JRuby on different platforms' do
it 'returns true for 64-bit Linux on JRuby' do
result = test_linux64_with_config('x86_64-linux-gnu', nil, 'java', 64)
expect(result).to be_truthy
end
it 'returns false for 32-bit Linux on JRuby' do
result = test_linux64_with_config('i386-linux-gnu', nil, 'java', 32)
expect(result).to be_falsey
end
it 'returns false for non-Linux systems on JRuby' do
result = test_linux64_with_config('darwin21.6.0', nil, 'java', 64)
expect(result).to be_falsey
end
end
context 'edge cases' do
it 'handles case-insensitive Linux detection' do
['LINUX-gnu', 'Linux-gnu', 'linux-GNU'].each do |host_os|
result = test_linux64_with_config(host_os, 8)
expect(result).to be_truthy, "Expected linux64? to handle case-insensitive matching for #{host_os}"
end
end
it 'handles partial Linux matches in host_os string' do
['some-linux-variant', 'embedded-linux-system', 'custom-linux-build'].each do |host_os|
result = test_linux64_with_config(host_os, 8)
expect(result).to be_truthy, "Expected linux64? to match partial Linux strings for #{host_os}"
end
end
end
context 'multi-check priority order', unless: RUBY_PLATFORM == 'java' do
it 'uses arch check first when arch contains 64' do
allow(RbConfig::CONFIG).to receive(:[]).and_call_original
allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('x86_64-linux-gnu')
allow(RbConfig::CONFIG).to receive(:[]).with('arch').and_return('x86_64-linux')
allow(RbConfig::CONFIG).to receive(:[]).with('DEFS').and_return('')
# Should not need to call pack method since arch check succeeds
expect_any_instance_of(Array).not_to receive(:pack)
expect(functions_class.send(:linux64?)).to be_truthy
end
it 'uses DEFS check when arch does not contain 64 but DEFS does' do
allow(RbConfig::CONFIG).to receive(:[]).and_call_original
allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('special-linux-gnu')
allow(RbConfig::CONFIG).to receive(:[]).with('arch').and_return('special-linux')
allow(RbConfig::CONFIG).to receive(:[]).with('DEFS').and_return('-D__LP64__=1')
# Should not need to call pack method since DEFS check succeeds
expect_any_instance_of(Array).not_to receive(:pack)
expect(functions_class.send(:linux64?)).to be_truthy
end
it 'falls back to pack method when neither arch nor DEFS contain 64' do
allow(RbConfig::CONFIG).to receive(:[]).and_call_original
allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('custom-linux-gnu')
allow(RbConfig::CONFIG).to receive(:[]).with('arch').and_return('custom-linux')
allow(RbConfig::CONFIG).to receive(:[]).with('DEFS').and_return('-DSOMETHING=1')
# Should call pack method as last resort
allow_any_instance_of(Array).to receive(:pack).with('P').and_return('12345678')
expect(functions_class.send(:linux64?)).to be_truthy
end
it 'returns false when all checks fail on 32-bit' do
allow(RbConfig::CONFIG).to receive(:[]).and_call_original
allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('custom-linux-gnu')
allow(RbConfig::CONFIG).to receive(:[]).with('arch').and_return('custom-linux')
allow(RbConfig::CONFIG).to receive(:[]).with('DEFS').and_return('-DSOMETHING=1')
# Pack method returns 4 bytes (32-bit)
allow_any_instance_of(Array).to receive(:pack).with('P').and_return('1234')
expect(functions_class.send(:linux64?)).to be_falsey
end
end
end
end
sys-filesystem-1.5.4/spec/sys_filesystem_shared.rb 0000644 0000041 0000041 00000000606 15061232103 022433 0 ustar www-data www-data # frozen_string_literal: true
require 'sys-filesystem'
RSpec.shared_examples Sys::Filesystem do
example 'version number is set to the expected value' do
expect(Sys::Filesystem::VERSION).to eq('1.5.4')
expect(Sys::Filesystem::VERSION).to be_frozen
end
example 'you cannot instantiate an instance' do
expect{ described_class.new }.to raise_error(NoMethodError)
end
end
sys-filesystem-1.5.4/checksums.yaml.gz.sig 0000444 0000041 0000041 00000000600 15061232103 020605 0 ustar www-data www-data HX\툽zCGH7n@uE5~UU:ylC.1ۇڃca.0\LLAV,`IϗFD>3ؠ Ep#RTzS f0Qx?k^-C4B8]p2jKsV^/)P*#NJDدTO!{zd2A,78$Pyl\bnUɖ-r͇[}J,NQ鞻ޞ^NTX}Q9) 3l7N-ٷWwTHߵ}E,X= >e^D͂43 f> sys-filesystem-1.5.4/Rakefile 0000644 0000041 0000041 00000002316 15061232103 016211 0 ustar www-data www-data require 'rake'
require 'rake/clean'
require 'rspec/core/rake_task'
require 'rubocop/rake_task'
CLEAN.include('**/*.gem', '**/*.rbc', '**/*.rbx', '**/*.lock')
namespace :gem do
desc "Build the sys-filesystem gem"
task :create => [:clean] do
require 'rubygems/package'
spec = Gem::Specification.load('sys-filesystem.gemspec')
spec.signing_key = File.join(Dir.home, '.ssh', 'gem-private_key.pem')
Gem::Package.build(spec)
end
desc "Install the sys-filesystem gem"
task :install => [:create] do
file = Dir['*.gem'].first
sh "gem install -l #{file}"
end
end
desc "Run the example program"
task :example do
sh "ruby -Ilib -Ilib/unix -Ilib/windows examples/example_stat.rb"
end
RuboCop::RakeTask.new
namespace :rubocop do
RuboCop::RakeTask.new(:unix) do |task|
task.patterns = ['lib/sys/unix/sys/**/*.rb', 'spec/*unix*']
end
RuboCop::RakeTask.new(:windows) do |task|
task.patterns = ['lib/sys/windows/sys/**/*.rb', 'spec/*windows*']
end
end
desc "Run the test suite"
RSpec::Core::RakeTask.new(:spec) do |t|
t.verbose = false
t.rspec_opts = '-f documentation'
end
# Clean up afterwards
Rake::Task[:spec].enhance do
Rake::Task[:clean].invoke
end
task :default => :spec
sys-filesystem-1.5.4/data.tar.gz.sig 0000444 0000041 0000041 00000000600 15061232103 017355 0 ustar www-data www-data QvWfN֠<'oN̹hPL.jDb)G+`QR(P)"n{SkCN5#ˡBa(۔ ח6?Uj#."2wNJvñyA[w$6b7g>z8x\f6WvV%-