sys-filesystem 1.4.3 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b00e624e22bd699630d63b34f90be7758f82630a069f7db2a61e2139cb55888
4
- data.tar.gz: 59add440f0203bade0430b2acd410e785b4ab0de416f272755a72db9276aa767
3
+ metadata.gz: 867cb33509a3fa99a58dbf3e0ee69107470a3cecebe4efc2346f49ec1dc1cea6
4
+ data.tar.gz: 9b1de11209f227d00584c021323b3de75db44e399823941bbad5bf9dd407cab2
5
5
  SHA512:
6
- metadata.gz: eb24f3c965a15d090fd7fff5800cc4c1829a7ddc7f2cbc4e943bb7e57ae92749a6abfccfecd94e8522287e9700916fc22f57af164afa413459321fa9460ba9a3
7
- data.tar.gz: d5d30e84e01f370ac62b77251f2c80c07964a99bebfa0cc30252237bc33830198d3a065c28a546c230327b1b951d45d95bc309f75276d17d7e1e8968ade216f2
6
+ metadata.gz: 29b4307434bda5a5447b45675a447d90421c104ba138f296c932272d6054c1cd81d4a3ddd68bdd9b099c30b012409a66ca9befd0275491d448fc2ae6f2184825
7
+ data.tar.gz: 5a6ee063a349093b3b0161814ce6f3b56af683d2a87960ab26d2975530bce91b4a1b31b1f2af1949fb315589116ef8ce5896a95802739a3e85573b436d6c5b6e
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGES.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 1.4.5 - 22-May-2024
2
+ * Handle the possibility that a statvs64 alias may not exist on some Linux
3
+ platforms. Thanks go to Antoine Martin for the report.
4
+
5
+ ## 1.4.4 - 12-Sep-2023
6
+ * Yet another fix for 32-bit vs 64-bit linux, specifically for the Statvfs
7
+ struct. Thanks go to Josh Cooper for the spot and the patch.
8
+
1
9
  ## 1.4.3 - 20-Oct-2021
2
10
  * Another fix for 32-bit vs 64-bit Linux since it was realized we cannot always
3
11
  rely on the host architecture information. Handling for JRuby was improved
data/Rakefile CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'rake'
2
2
  require 'rake/clean'
3
3
  require 'rspec/core/rake_task'
4
+ require 'rubocop/rake_task'
4
5
 
5
6
  CLEAN.include('**/*.gem', '**/*.rbc', '**/*.rbx', '**/*.lock')
6
7
 
@@ -25,6 +26,18 @@ task :example do
25
26
  sh "ruby -Ilib -Ilib/unix -Ilib/windows examples/example_stat.rb"
26
27
  end
27
28
 
29
+ RuboCop::RakeTask.new
30
+
31
+ namespace :rubocop do
32
+ RuboCop::RakeTask.new(:unix) do |task|
33
+ task.patterns = ['lib/sys/unix/sys/**/*.rb', 'spec/*unix*']
34
+ end
35
+
36
+ RuboCop::RakeTask.new(:windows) do |task|
37
+ task.patterns = ['lib/sys/windows/sys/**/*.rb', 'spec/*windows*']
38
+ end
39
+ end
40
+
28
41
  desc "Run the test suite"
29
42
  RSpec::Core::RakeTask.new(:spec)
30
43
 
@@ -1,9 +1,4 @@
1
- module Sys
2
- class Filesystem
3
- # The version of the sys-filesystem library
4
- VERSION = '1.4.3'.freeze
5
- end
6
- end
1
+ # frozen_string_literal: true
7
2
 
8
3
  require 'rbconfig'
9
4
 
@@ -13,10 +8,18 @@ else
13
8
  require_relative 'unix/sys/filesystem'
14
9
  end
15
10
 
16
- # Methods universal to all platforms
11
+ # Methods and properties universal to all platforms
17
12
 
13
+ # The Sys module serves as a namespace only.
18
14
  module Sys
15
+ # The Filesystem class serves as an abstract base class. Its methods
16
+ # return objects of other types. Do not instantiate.
19
17
  class Filesystem
18
+ # The version of the sys-filesystem library
19
+ VERSION = '1.4.5'
20
+
21
+ # Stat objects are returned by the Sys::Filesystem.stat method. Here
22
+ # we're adding universal methods.
20
23
  class Stat
21
24
  # Returns true if the filesystem is case sensitive for the current path.
22
25
  # Typically this will be any path on MS Windows or Macs using HFS.
@@ -26,14 +29,12 @@ module Sys
26
29
  # general rule, I do not recommend using this method for a root path.
27
30
  #
28
31
  def case_insensitive?
29
- if path !~ /\w+/
30
- if RbConfig::CONFIG['host_os'] =~ /darwin|mac|windows|mswin|mingw/i
31
- true # Assumes HFS
32
- else
33
- false
34
- end
35
- else
32
+ if path =~ /\w+/
36
33
  File.identical?(path, path.swapcase)
34
+ elsif RbConfig::CONFIG['host_os'] =~ /darwin|mac|windows|mswin|mingw/i
35
+ true # Assumes HFS/APFS on Mac
36
+ else
37
+ false
37
38
  end
38
39
  end
39
40
 
@@ -46,8 +47,8 @@ module Sys
46
47
  end
47
48
  end
48
49
 
49
- # Some convenient methods for converting bytes to kb, mb, and gb.
50
- #
50
+ # Reopen the Numeric class and add some convenient methods
51
+ # for converting bytes to kb, mb, and gb.
51
52
  class Numeric
52
53
  # call-seq:
53
54
  # <tt>num</tt>.to_kb
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sys
2
4
  class Filesystem
3
5
  module Constants
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ffi'
2
4
 
3
5
  module Sys
4
6
  class Filesystem
7
+ # A scoped module for internal FFI functions to be used by the main code.
5
8
  module Functions
6
9
  extend FFI::Library
7
10
 
@@ -9,19 +12,26 @@ module Sys
9
12
 
10
13
  def self.linux64?
11
14
  if RUBY_PLATFORM == 'java'
12
- ENV_JAVA['sun.arch.data.model'].to_i == 64
15
+ RbConfig::CONFIG['host_os'] =~ /linux/i &&
16
+ ENV_JAVA['sun.arch.data.model'].to_i == 64
13
17
  else
14
18
  RbConfig::CONFIG['host_os'] =~ /linux/i &&
15
19
  (RbConfig::CONFIG['arch'] =~ /64/ || RbConfig::CONFIG['DEFS'] =~ /64/)
16
20
  end
17
21
  end
18
22
 
23
+ def self.solaris?
24
+ RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i
25
+ end
26
+
19
27
  private_class_method :linux64?
20
28
 
21
- if RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i
22
- attach_function(:statvfs, :statvfs64, %i[string pointer], :int)
23
- elsif linux64?
24
- attach_function(:statvfs, :statvfs64, %i[string pointer], :int)
29
+ if linux64? || solaris?
30
+ begin
31
+ attach_function(:statvfs, :statvfs64, %i[string pointer], :int)
32
+ rescue FFI::NotFoundError # Not every Linux distro has an alias
33
+ attach_function(:statvfs, %i[string pointer], :int)
34
+ end
25
35
  else
26
36
  attach_function(:statvfs, %i[string pointer], :int)
27
37
  end
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ffi'
2
4
  require 'rbconfig'
3
5
 
4
6
  module Sys
5
7
  class Filesystem
6
8
  module Structs
9
+ # The Statfs struct is a subclass of FFI::Struct that corresponds to a struct statfs.
7
10
  class Statfs < FFI::Struct
8
-
11
+ # Private method that will determine the layout of the struct on Linux.
9
12
  def self.linux64?
10
13
  if RUBY_PLATFORM == 'java'
11
14
  ENV_JAVA['sun.arch.data.model'].to_i == 64
@@ -20,92 +23,103 @@ module Sys
20
23
  # FreeBSD 12.0 MNAMELEN from 88 => 1024.
21
24
  MNAMELEN =
22
25
  if RbConfig::CONFIG['host_os'] =~ /freebsd(.*)/i
23
- $1.to_f < 12.0 ? 88 : 1024
26
+ Regexp.last_match(1).to_f < 12.0 ? 88 : 1024
24
27
  else
25
28
  88
26
29
  end
27
30
 
28
- if RbConfig::CONFIG['host_os'] =~ /bsd/i
29
- layout(
30
- :f_version, :uint32,
31
- :f_type, :uint32,
32
- :f_flags, :uint64,
33
- :f_bsize, :uint64,
34
- :f_iosize, :int64,
35
- :f_blocks, :uint64,
36
- :f_bfree, :uint64,
37
- :f_bavail, :int64,
38
- :f_files, :uint64,
39
- :f_ffree, :uint64,
40
- :f_syncwrites, :uint64,
41
- :f_asyncwrites, :uint64,
42
- :f_syncreads, :uint64,
43
- :f_asyncreads, :uint64,
44
- :f_spare, [:uint64, 10],
45
- :f_namemax, :uint32,
46
- :f_owner, :int32,
47
- :f_fsid, [:int32, 2],
48
- :f_charspare, [:char, 80],
49
- :f_fstypename, [:char, 16],
50
- :f_mntfromname, [:char, MNAMELEN],
51
- :f_mntonname, [:char, MNAMELEN]
52
- )
53
- elsif RbConfig::CONFIG['host_os'] =~ /linux/i
54
- if linux64?
31
+ case RbConfig::CONFIG['host_os']
32
+ when /bsd/i
55
33
  layout(
56
- :f_type, :ulong,
57
- :f_bsize, :ulong,
34
+ :f_version, :uint32,
35
+ :f_type, :uint32,
36
+ :f_flags, :uint64,
37
+ :f_bsize, :uint64,
38
+ :f_iosize, :int64,
58
39
  :f_blocks, :uint64,
59
40
  :f_bfree, :uint64,
60
- :f_bavail, :uint64,
41
+ :f_bavail, :int64,
61
42
  :f_files, :uint64,
62
43
  :f_ffree, :uint64,
63
- :f_fsid, [:int, 2],
64
- :f_namelen, :ulong,
65
- :f_frsize, :ulong,
66
- :f_flags, :ulong,
67
- :f_spare, [:ulong, 4]
44
+ :f_syncwrites, :uint64,
45
+ :f_asyncwrites, :uint64,
46
+ :f_syncreads, :uint64,
47
+ :f_asyncreads, :uint64,
48
+ :f_spare, [:uint64, 10],
49
+ :f_namemax, :uint32,
50
+ :f_owner, :int32,
51
+ :f_fsid, [:int32, 2],
52
+ :f_charspare, [:char, 80],
53
+ :f_fstypename, [:char, 16],
54
+ :f_mntfromname, [:char, MNAMELEN],
55
+ :f_mntonname, [:char, MNAMELEN]
68
56
  )
57
+ when /linux/i
58
+ if linux64?
59
+ layout(
60
+ :f_type, :ulong,
61
+ :f_bsize, :ulong,
62
+ :f_blocks, :uint64,
63
+ :f_bfree, :uint64,
64
+ :f_bavail, :uint64,
65
+ :f_files, :uint64,
66
+ :f_ffree, :uint64,
67
+ :f_fsid, [:int, 2],
68
+ :f_namelen, :ulong,
69
+ :f_frsize, :ulong,
70
+ :f_flags, :ulong,
71
+ :f_spare, [:ulong, 4]
72
+ )
73
+ else
74
+ layout(
75
+ :f_type, :ulong,
76
+ :f_bsize, :ulong,
77
+ :f_blocks, :uint32,
78
+ :f_bfree, :uint32,
79
+ :f_bavail, :uint32,
80
+ :f_files, :uint32,
81
+ :f_ffree, :uint32,
82
+ :f_fsid, [:int, 2],
83
+ :f_namelen, :ulong,
84
+ :f_frsize, :ulong,
85
+ :f_flags, :ulong,
86
+ :f_spare, [:ulong, 4]
87
+ )
88
+ end
69
89
  else
70
90
  layout(
71
- :f_type, :ulong,
72
- :f_bsize, :ulong,
73
- :f_blocks, :uint32,
74
- :f_bfree, :uint32,
75
- :f_bavail, :uint32,
76
- :f_files, :uint32,
77
- :f_ffree, :uint32,
78
- :f_fsid, [:int, 2],
79
- :f_namelen, :ulong,
80
- :f_frsize, :ulong,
81
- :f_flags, :ulong,
82
- :f_spare, [:ulong, 4]
91
+ :f_bsize, :uint32,
92
+ :f_iosize, :int32,
93
+ :f_blocks, :uint64,
94
+ :f_bfree, :uint64,
95
+ :f_bavail, :uint64,
96
+ :f_files, :uint64,
97
+ :f_ffree, :uint64,
98
+ :f_fsid, [:int32, 2],
99
+ :f_owner, :int32,
100
+ :f_type, :uint32,
101
+ :f_flags, :uint32,
102
+ :f_fssubtype, :uint32,
103
+ :f_fstypename, [:char, 16],
104
+ :f_mntonname, [:char, 1024],
105
+ :f_mntfromname, [:char, 1024],
106
+ :f_reserved, [:uint32, 8]
83
107
  )
84
- end
85
- else
86
- layout(
87
- :f_bsize, :uint32,
88
- :f_iosize, :int32,
89
- :f_blocks, :uint64,
90
- :f_bfree, :uint64,
91
- :f_bavail, :uint64,
92
- :f_files, :uint64,
93
- :f_ffree, :uint64,
94
- :f_fsid, [:int32, 2],
95
- :f_owner, :int32,
96
- :f_type, :uint32,
97
- :f_flags, :uint32,
98
- :f_fssubtype, :uint32,
99
- :f_fstypename, [:char, 16],
100
- :f_mntonname, [:char, 1024],
101
- :f_mntfromname, [:char, 1024],
102
- :f_reserved, [:uint32, 8]
103
- )
104
108
  end
105
109
  end
106
110
 
107
111
  # The Statvfs struct represents struct statvfs from sys/statvfs.h.
108
112
  class Statvfs < FFI::Struct
113
+ # Private method that will determine the layout of the struct on Linux.
114
+ def self.linux64?
115
+ if RUBY_PLATFORM == 'java'
116
+ ENV_JAVA['sun.arch.data.model'].to_i == 64
117
+ else
118
+ RbConfig::CONFIG['host_os'] =~ /linux/i &&
119
+ (RbConfig::CONFIG['arch'] =~ /64/ || RbConfig::CONFIG['DEFS'] =~ /64/)
120
+ end
121
+ end
122
+
109
123
  if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach/i
110
124
  layout(
111
125
  :f_bsize, :ulong,
@@ -151,7 +165,7 @@ module Sys
151
165
  :f_fstr, [:char, 32],
152
166
  :f_filler, [:ulong, 16]
153
167
  )
154
- elsif RbConfig::CONFIG['host'] =~ /i686/i
168
+ elsif !linux64?
155
169
  layout(
156
170
  :f_bsize, :ulong,
157
171
  :f_frsize, :ulong,
@@ -224,7 +224,7 @@ module Sys
224
224
  fs = Statvfs.new
225
225
 
226
226
  if statvfs(path, fs) < 0
227
- raise Error, 'statvfs() function failed: ' + strerror(FFI.errno)
227
+ raise Error, "statvfs() function failed: #{strerror(FFI.errno)}"
228
228
  end
229
229
 
230
230
  obj = Sys::Filesystem::Stat.new
@@ -275,7 +275,7 @@ module Sys
275
275
  num = getmntinfo(buf, 2)
276
276
 
277
277
  if num == 0
278
- raise Error, 'getmntinfo() function failed: ' + strerror(FFI.errno)
278
+ raise Error, "getmntinfo() function failed: #{strerror(FFI.errno)}"
279
279
  end
280
280
 
281
281
  ptr = buf.get_pointer(0)
@@ -419,7 +419,7 @@ module Sys
419
419
  #
420
420
  def self.mount(source, target, fstype = 'ext2', flags = 0, data = nil)
421
421
  if mount_c(source, target, fstype, flags, data) != 0
422
- raise Error, 'mount() function failed: ' + strerror(FFI.errno)
422
+ raise Error, "mount() function failed: #{strerror(FFI.errno)}"
423
423
  end
424
424
 
425
425
  self
@@ -2,6 +2,7 @@ require 'ffi'
2
2
 
3
3
  module Sys
4
4
  class Filesystem
5
+ # Wrapper module for Windows related FFI functions.
5
6
  module Functions
6
7
  extend FFI::Library
7
8
  ffi_lib :kernel32
@@ -1,6 +1,9 @@
1
+ # Reopen core Ruby classes here and add some custom methods.
1
2
  class String
2
3
  # Convenience method for converting strings to UTF-16LE for wide character
3
4
  # functions that require it.
5
+ #--
6
+ # TODO: Use a refinement.
4
7
  def wincode
5
8
  (tr(File::SEPARATOR, File::ALT_SEPARATOR) + 0.chr).encode('UTF-16LE')
6
9
  end
@@ -9,7 +9,6 @@ require 'time'
9
9
 
10
10
  # The Sys module serves as a namespace only.
11
11
  module Sys
12
-
13
12
  # The Filesystem class encapsulates information about your filesystem.
14
13
  class Filesystem
15
14
  include Sys::Filesystem::Constants
@@ -20,6 +19,7 @@ module Sys
20
19
 
21
20
  private_class_method :new
22
21
 
22
+ # Mount objects are returned by the Sys::Filesystem.mounts method.
23
23
  class Mount
24
24
  # The name of the volume. This is the device mapping.
25
25
  attr_reader :name
@@ -50,6 +50,7 @@ module Sys
50
50
  alias freq frequency
51
51
  end
52
52
 
53
+ # Stat objects are returned by the Sys::Filesystem.stat method.
53
54
  class Stat
54
55
  # The path of the file system.
55
56
  attr_reader :path
@@ -160,6 +161,8 @@ module Sys
160
161
  #--
161
162
  # I couldn't really find a good reason to use the wide functions for this
162
163
  # method. If you have one, patches welcome.
164
+ #--
165
+ # rubocop:disable Metrics/BlockLength
163
166
  #
164
167
  def self.mounts
165
168
  # First call, get needed buffer size
@@ -196,14 +199,14 @@ module Sys
196
199
  filesystem_flags = FFI::MemoryPointer.new(:ulong)
197
200
 
198
201
  bool = GetVolumeInformationA(
199
- drive,
200
- volume,
201
- volume.size,
202
- volume_serial_number,
203
- max_component_length,
204
- filesystem_flags,
205
- fsname,
206
- fsname.size
202
+ drive,
203
+ volume,
204
+ volume.size,
205
+ volume_serial_number,
206
+ max_component_length,
207
+ filesystem_flags,
208
+ fsname,
209
+ fsname.size
207
210
  )
208
211
 
209
212
  # Skip unmounted floppies or cd-roms, or inaccessible drives
@@ -237,6 +240,7 @@ module Sys
237
240
 
238
241
  mounts # Nil if the block form was used.
239
242
  end
243
+ # rubocop:enable Metrics/BlockLength
240
244
 
241
245
  # Returns the mount point for the given +file+. For MS Windows this
242
246
  # means the root of the path.
@@ -250,8 +254,6 @@ module Sys
250
254
 
251
255
  if PathStripToRootW(wfile)
252
256
  wfile.read_string(wfile.size).split("\000\000").first.tr(0.chr, '')
253
- else
254
- nil
255
257
  end
256
258
  end
257
259
 
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'sys/filesystem'
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rspec'
4
+ require 'sys_filesystem_shared'
2
5
 
3
6
  RSpec.configure do |config|
7
+ config.include_context(Sys::Filesystem)
4
8
  config.filter_run_excluding(:windows) unless Gem.win_platform?
5
9
  config.filter_run_excluding(:unix) if Gem.win_platform?
6
10
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sys-filesystem'
4
+
5
+ RSpec.shared_examples Sys::Filesystem do
6
+ example 'version number is set to the expected value' do
7
+ expect(Sys::Filesystem::VERSION).to eq('1.4.5')
8
+ expect(Sys::Filesystem::VERSION).to be_frozen
9
+ end
10
+
11
+ example 'you cannot instantiate an instance' do
12
+ expect{ described_class.new }.to raise_error(NoMethodError)
13
+ end
14
+ end