sys-filesystem 1.4.5 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 867cb33509a3fa99a58dbf3e0ee69107470a3cecebe4efc2346f49ec1dc1cea6
4
- data.tar.gz: 9b1de11209f227d00584c021323b3de75db44e399823941bbad5bf9dd407cab2
3
+ metadata.gz: e69ef4806a64a956dfd3b1eb629a17654d7b14a5a8ed8468113f8ee045287682
4
+ data.tar.gz: 54182b67d58e77fc0c4b0dc8c96aa7ab64f5c7759943e966abd77d1ba212bfb8
5
5
  SHA512:
6
- metadata.gz: 29b4307434bda5a5447b45675a447d90421c104ba138f296c932272d6054c1cd81d4a3ddd68bdd9b099c30b012409a66ca9befd0275491d448fc2ae6f2184825
7
- data.tar.gz: 5a6ee063a349093b3b0161814ce6f3b56af683d2a87960ab26d2975530bce91b4a1b31b1f2af1949fb315589116ef8ce5896a95802739a3e85573b436d6c5b6e
6
+ metadata.gz: 496090ea1ac8ef0b3d3fe55489b3e3f7eeb39f0406135ebdc3dfc650c0ea16c2e010a8eafb8ffb47e837b4be79217311c1d0e7cd71bb0c3ee81d189a8b7e54ca
7
+ data.tar.gz: fa6242583cf58ea04fa2fc2581030fcc53e62c7871852ffd3105caa8e363685b1521a056ee0a292327a75c497720dd934c23bd7d58d9687157c8265eeac64833
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGES.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 1.5.0 - 8-Jun-2024
2
+ * Add support for DragonFlyBSD.
3
+ * Remove Solaris support. It's dead, Jim.
4
+ * Now assumes umount2 function is present on Linux systems, and some
5
+ corresponding refactoring of the umount method.
6
+
1
7
  ## 1.4.5 - 22-May-2024
2
8
  * Handle the possibility that a statvs64 alias may not exist on some Linux
3
9
  platforms. Thanks go to Antoine Martin for the report.
data/README.md CHANGED
@@ -78,7 +78,7 @@ Apache-2.0
78
78
 
79
79
  ## Copyright
80
80
 
81
- (C) 2003-2020 Daniel J. Berger
81
+ (C) 2003-2024 Daniel J. Berger
82
82
  All Rights Reserved
83
83
 
84
84
  ## Warranty
@@ -16,7 +16,7 @@ module Sys
16
16
  # return objects of other types. Do not instantiate.
17
17
  class Filesystem
18
18
  # The version of the sys-filesystem library
19
- VERSION = '1.4.5'
19
+ VERSION = '1.5.0'
20
20
 
21
21
  # Stat objects are returned by the Sys::Filesystem.stat method. Here
22
22
  # we're adding universal methods.
@@ -25,6 +25,8 @@ module Sys
25
25
  MNT_DEFWRITE = 0x02000000 # filesystem should defer writes
26
26
  MNT_MULTILABEL = 0x04000000 # MAC support for individual labels
27
27
  MNT_NOATIME = 0x10000000 # disable update of file access time
28
+ MNT_NOCLUSTERR = 0x40000000 # disable cluster read
29
+ MNT_NOCLUSTERW = 0x80000000 # disable cluster write
28
30
 
29
31
  MNT_VISFLAGMASK = (
30
32
  MNT_RDONLY | MNT_SYNCHRONOUS | MNT_NOEXEC |
@@ -20,13 +20,9 @@ module Sys
20
20
  end
21
21
  end
22
22
 
23
- def self.solaris?
24
- RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i
25
- end
26
-
27
23
  private_class_method :linux64?
28
24
 
29
- if linux64? || solaris?
25
+ if linux64?
30
26
  begin
31
27
  attach_function(:statvfs, :statvfs64, %i[string pointer], :int)
32
28
  rescue FFI::NotFoundError # Not every Linux distro has an alias
@@ -39,29 +35,19 @@ module Sys
39
35
  attach_function(:strerror, [:int], :string)
40
36
  attach_function(:mount_c, :mount, %i[string string string ulong string], :int)
41
37
 
42
- begin
43
- attach_function(:umount_c, :umount, [:string], :int)
44
- rescue FFI::NotFoundError
45
- if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach|bsd/i
46
- attach_function(:umount_c, :unmount, [:string], :int)
47
- end
38
+ if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach|bsd|dragonfly/i
39
+ attach_function(:umount_c, :unmount, %i[string int], :int)
40
+ else
41
+ attach_function(:umount_c, :umount2, %i[string int], :int)
48
42
  end
49
43
 
50
44
  private_class_method :statvfs, :strerror, :mount_c, :umount_c
51
45
 
52
46
  begin
53
- if RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i
54
- attach_function(:fopen, %i[string string], :pointer)
55
- attach_function(:fclose, [:pointer], :int)
56
- attach_function(:getmntent, %i[pointer pointer], :int)
57
- private_class_method :fopen, :fclose, :getmntent
58
- else
59
- attach_function(:getmntent, [:pointer], :pointer)
60
- attach_function(:setmntent, %i[string string], :pointer)
61
- attach_function(:endmntent, [:pointer], :int)
62
- attach_function(:umount2, %i[string int], :int)
63
- private_class_method :getmntent, :setmntent, :endmntent, :umount2
64
- end
47
+ attach_function(:getmntent, [:pointer], :pointer)
48
+ attach_function(:setmntent, %i[string string], :pointer)
49
+ attach_function(:endmntent, [:pointer], :int)
50
+ private_class_method :getmntent, :setmntent, :endmntent
65
51
  rescue FFI::NotFoundError
66
52
  if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach/i
67
53
  begin
@@ -6,6 +6,20 @@ require 'rbconfig'
6
6
  module Sys
7
7
  class Filesystem
8
8
  module Structs
9
+ # Used by DragonFlyBSD
10
+ class UUID < FFI::Struct
11
+ UUID_NODE_LEN = 6
12
+
13
+ layout(
14
+ :time_low, :uint32,
15
+ :time_mid, :uint16,
16
+ :time_hi_and_version, :uint16,
17
+ :clock_seq_hi_and_reserved, :uint8,
18
+ :clock_seq_low, :uint8,
19
+ :node, [:uint8, UUID_NODE_LEN]
20
+ )
21
+ end
22
+
9
23
  # The Statfs struct is a subclass of FFI::Struct that corresponds to a struct statfs.
10
24
  class Statfs < FFI::Struct
11
25
  # Private method that will determine the layout of the struct on Linux.
@@ -86,6 +100,31 @@ module Sys
86
100
  :f_spare, [:ulong, 4]
87
101
  )
88
102
  end
103
+ when /dragonfly/i
104
+ layout(
105
+ :f_spare2, :long,
106
+ :f_bsize, :long,
107
+ :f_iosize, :long,
108
+ :f_blocks, :long,
109
+ :f_bfree, :long,
110
+ :f_bavail, :long,
111
+ :f_files, :long,
112
+ :f_ffree, :long,
113
+ :f_fsid, [:int32_t, 2],
114
+ :f_owner, :uid_t,
115
+ :f_type, :int,
116
+ :f_flags, :int,
117
+ :f_syncwrites, :long,
118
+ :f_asyncwrites, :long,
119
+ :f_fstypename, [:char, 16],
120
+ :f_mntonname, [:char, 80],
121
+ :f_syncreads, :long,
122
+ :f_asyncreads, :long,
123
+ :f_spares1, :short,
124
+ :f_mntfromname, [:char, 80],
125
+ :f_spares2, :short,
126
+ :f_spare, [:long,2]
127
+ )
89
128
  else
90
129
  layout(
91
130
  :f_bsize, :uint32,
@@ -148,22 +187,27 @@ module Sys
148
187
  :f_fsid, :ulong,
149
188
  :f_namemax, :ulong
150
189
  )
151
- elsif RbConfig::CONFIG['host'] =~ /sunos|solaris/i
190
+ elsif RbConfig::CONFIG['host'] =~ /dragonfly/i
152
191
  layout(
153
192
  :f_bsize, :ulong,
154
193
  :f_frsize, :ulong,
155
- :f_blocks, :uint64_t,
156
- :f_bfree, :uint64_t,
157
- :f_bavail, :uint64_t,
158
- :f_files, :uint64_t,
159
- :f_ffree, :uint64_t,
160
- :f_favail, :uint64_t,
194
+ :f_blocks, :uint64,
195
+ :f_bfree, :uint64,
196
+ :f_bavail, :uint64,
197
+ :f_files, :uint64,
198
+ :f_ffree, :uint64,
199
+ :f_favail, :uint64,
161
200
  :f_fsid, :ulong,
162
- :f_basetype, [:char, 16],
163
201
  :f_flag, :ulong,
164
202
  :f_namemax, :ulong,
165
- :f_fstr, [:char, 32],
166
- :f_filler, [:ulong, 16]
203
+ :f_owner, :uid_t,
204
+ :f_type, :uint,
205
+ :f_syncreads, :uint64,
206
+ :f_syncwrites, :uint64,
207
+ :f_asyncreads, :uint64,
208
+ :f_asyncwrites, :uint64,
209
+ :f_fsid_uuid, UUID,
210
+ :f_uid_uuid, UUID
167
211
  )
168
212
  elsif !linux64?
169
213
  layout(
@@ -199,17 +243,6 @@ module Sys
199
243
  end
200
244
  end
201
245
 
202
- # The Mnttab struct represents struct mnnttab from sys/mnttab.h on Solaris.
203
- class Mnttab < FFI::Struct
204
- layout(
205
- :mnt_special, :string,
206
- :mnt_mountp, :string,
207
- :mnt_fstype, :string,
208
- :mnt_mntopts, :string,
209
- :mnt_time, :string
210
- )
211
- end
212
-
213
246
  # The Mntent struct represents struct mntent from sys/mount.h on Unix.
214
247
  class Mntent < FFI::Struct
215
248
  layout(
@@ -105,6 +105,27 @@ module Sys
105
105
  # The filesystem type, e.g. UFS.
106
106
  attr_accessor :base_type
107
107
 
108
+ # The filesystem ID
109
+ attr_accessor :filesystem_id
110
+
111
+ # The filesystem type
112
+ attr_accessor :filesystem_type
113
+
114
+ # The user that mounted the filesystem
115
+ attr_accessor :owner
116
+
117
+ # Count of sync reads since mount
118
+ attr_accessor :sync_reads
119
+
120
+ # Count of sync writes since mount
121
+ attr_accessor :sync_writes
122
+
123
+ # Count of async reads since mount
124
+ attr_accessor :async_reads
125
+
126
+ # Count of async writes since mount
127
+ attr_accessor :async_writes
128
+
108
129
  alias inodes files
109
130
  alias inodes_free files_free
110
131
  alias inodes_available files_available
@@ -250,6 +271,16 @@ module Sys
250
271
  obj.base_type = fs[:f_basetype].to_s
251
272
  end
252
273
 
274
+ # DragonFlyBSD has additional struct members
275
+ if RbConfig::CONFIG['host_os'] =~ /dragonfly/i
276
+ obj.owner = fs[:f_owner]
277
+ obj.filesystem_type = fs[:f_type]
278
+ obj.sync_reads= fs[:f_syncreads]
279
+ obj.async_reads= fs[:f_asyncreads]
280
+ obj.sync_writes = fs[:f_syncwrites]
281
+ obj.async_writes = fs[:f_asyncwrites]
282
+ end
283
+
253
284
  obj.freeze
254
285
  end
255
286
 
@@ -325,41 +356,23 @@ module Sys
325
356
  raise SystemCallError.new(method_name, FFI.errno)
326
357
  end
327
358
 
328
- if RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i
329
- mt = Mnttab.new
330
- while getmntent(fp, mt) == 0
331
- obj = Sys::Filesystem::Mount.new
332
- obj.name = mt[:mnt_special].to_s
333
- obj.mount_point = mt[:mnt_mountp].to_s
334
- obj.mount_type = mt[:mnt_fstype].to_s
335
- obj.options = mt[:mnt_mntopts].to_s
336
- obj.mount_time = Time.at(Integer(mt[:mnt_time]))
337
-
338
- if block_given?
339
- yield obj.freeze
340
- else
341
- array << obj.freeze
342
- end
343
- end
344
- else
345
- while ptr = getmntent(fp)
346
- break if ptr.null?
347
- mt = Mntent.new(ptr)
348
-
349
- obj = Sys::Filesystem::Mount.new
350
- obj.name = mt[:mnt_fsname]
351
- obj.mount_point = mt[:mnt_dir]
352
- obj.mount_type = mt[:mnt_type]
353
- obj.options = mt[:mnt_opts]
354
- obj.mount_time = nil
355
- obj.dump_frequency = mt[:mnt_freq]
356
- obj.pass_number = mt[:mnt_passno]
357
-
358
- if block_given?
359
- yield obj.freeze
360
- else
361
- array << obj.freeze
362
- end
359
+ while ptr = getmntent(fp)
360
+ break if ptr.null?
361
+ mt = Mntent.new(ptr)
362
+
363
+ obj = Sys::Filesystem::Mount.new
364
+ obj.name = mt[:mnt_fsname]
365
+ obj.mount_point = mt[:mnt_dir]
366
+ obj.mount_type = mt[:mnt_type]
367
+ obj.options = mt[:mnt_opts]
368
+ obj.mount_time = nil
369
+ obj.dump_frequency = mt[:mnt_freq]
370
+ obj.pass_number = mt[:mnt_passno]
371
+
372
+ if block_given?
373
+ yield obj.freeze
374
+ else
375
+ array << obj.freeze
363
376
  end
364
377
  end
365
378
  ensure
@@ -426,22 +439,24 @@ module Sys
426
439
  end
427
440
 
428
441
  # Removes the attachment of the (topmost) filesystem mounted on target.
429
- # Additional flags may be provided for operating systems that support
430
- # the umount2 function. Otherwise this argument is ignored.
442
+ # You may also specify bitwise OR'd +flags+ to control the precise behavior.
443
+ # The possible flags on Linux are:
431
444
  #
432
- # Typically requires admin privileges.
445
+ # * MNT_FORCE - Abort pending requests, may cause data loss.
446
+ # * MNT_DETACH - Lazy umount, waits until the mount point is no longer busy.
447
+ # * MNT_EXPIRE - Mark mount point as expired, but don't actually remove it until
448
+ # a second call MNT_EXPIRE call is made.
433
449
  #
434
- def self.umount(target, flags = nil)
435
- if flags && respond_to?(:umount2)
436
- function = 'umount2'
437
- rv = umount2_c(target, flags)
438
- else
439
- function = 'umount'
440
- rv = umount_c(target)
441
- end
442
-
443
- if rv != 0
444
- raise Error, "#{function} function failed: " + strerror(FFI.errno)
450
+ # * UMOUNT_NOFOLLOW - Don't dereference the target if it's a symbolic link.
451
+ #
452
+ # Note that BSD platforms may support different flags. Please see the man
453
+ # pages for details.
454
+ #
455
+ # Typically this method requires admin privileges.
456
+ #
457
+ def self.umount(target, flags = 0)
458
+ if umount_c(target, flags) != 0
459
+ raise Error, "umount function failed: #{strerror(FFI.errno)}"
445
460
  end
446
461
 
447
462
  self
data/spec/spec_helper.rb CHANGED
@@ -7,4 +7,5 @@ RSpec.configure do |config|
7
7
  config.include_context(Sys::Filesystem)
8
8
  config.filter_run_excluding(:windows) unless Gem.win_platform?
9
9
  config.filter_run_excluding(:unix) if Gem.win_platform?
10
+ config.filter_run_excluding(:dragonfly) unless RbConfig::CONFIG['host_os'] =~ /dragonfly/i
10
11
  end
@@ -4,7 +4,7 @@ require 'sys-filesystem'
4
4
 
5
5
  RSpec.shared_examples Sys::Filesystem do
6
6
  example 'version number is set to the expected value' do
7
- expect(Sys::Filesystem::VERSION).to eq('1.4.5')
7
+ expect(Sys::Filesystem::VERSION).to eq('1.5.0')
8
8
  expect(Sys::Filesystem::VERSION).to be_frozen
9
9
  end
10
10
 
@@ -11,9 +11,8 @@ require 'sys-filesystem'
11
11
  require 'pathname'
12
12
 
13
13
  RSpec.describe Sys::Filesystem, :unix => true do
14
- let(:solaris) { RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i }
15
14
  let(:linux) { RbConfig::CONFIG['host_os'] =~ /linux/i }
16
- let(:bsd) { RbConfig::CONFIG['host_os'] =~ /bsd/i }
15
+ let(:bsd) { RbConfig::CONFIG['host_os'] =~ /bsd|dragonfly/i }
17
16
  let(:darwin) { RbConfig::CONFIG['host_os'] =~ /mac|darwin/i }
18
17
  let(:root) { '/' }
19
18
 
@@ -39,7 +38,8 @@ RSpec.describe Sys::Filesystem, :unix => true do
39
38
 
40
39
  example 'stat fragment_size is a plausible value' do
41
40
  expect(@stat.fragment_size).to be >= 512
42
- expect(@stat.fragment_size).to be <= 16384
41
+ expect(@stat.fragment_size).to be <= 2**16
42
+ expect(@stat.fragment_size).to be <= @stat.block_size
43
43
  end
44
44
 
45
45
  example 'stat blocks works as expected' do
@@ -102,11 +102,36 @@ RSpec.describe Sys::Filesystem, :unix => true do
102
102
  expect(@stat.name_max).to be_a(Numeric)
103
103
  end
104
104
 
105
- example 'stat base_type works as expected' do
106
- skip 'base_type test skipped except on Solaris' unless solaris
105
+ context 'dragonfly', :dragonfly do
106
+ example 'owner works as expected' do
107
+ expect(@stat).to respond_to(:owner)
108
+ expect(@stat.owner).to be_a(Numeric)
109
+ end
110
+
111
+ example 'filesystem_type works as expected' do
112
+ expect(@stat).to respond_to(:filesystem_type)
113
+ expect(@stat.filesystem_type).to be_a(Numeric)
114
+ end
115
+
116
+ example 'sync_reads works as expected' do
117
+ expect(@stat).to respond_to(:sync_reads)
118
+ expect(@stat.sync_reads).to be_a(Numeric)
119
+ end
120
+
121
+ example 'async_reads works as expected' do
122
+ expect(@stat).to respond_to(:async_reads)
123
+ expect(@stat.async_reads).to be_a(Numeric)
124
+ end
107
125
 
108
- expect(@stat).to respond_to(:base_type)
109
- expect(@stat.base_type).to be_a(String)
126
+ example 'sync_writes works as expected' do
127
+ expect(@stat).to respond_to(:sync_writes)
128
+ expect(@stat.sync_writes).to be_a(Numeric)
129
+ end
130
+
131
+ example 'async_writes works as expected' do
132
+ expect(@stat).to respond_to(:async_writes)
133
+ expect(@stat.async_writes).to be_a(Numeric)
134
+ end
110
135
  end
111
136
 
112
137
  example 'stat constants are defined' do
@@ -114,11 +139,6 @@ RSpec.describe Sys::Filesystem, :unix => true do
114
139
  expect(Sys::Filesystem::Stat::NOSUID).not_to be_nil
115
140
  end
116
141
 
117
- example 'stat constants for solaris are defined' do
118
- skip 'NOTRUNC test skipped except on Solaris' unless solaris
119
- expect(Sys::Filesystem::Stat::NOTRUNC).not_to be_nil
120
- end
121
-
122
142
  example 'stat bytes_total works as expected' do
123
143
  expect(@stat).to respond_to(:bytes_total)
124
144
  expect(@stat.bytes_total).to be_a(Numeric)
@@ -423,15 +443,15 @@ RSpec.describe Sys::Filesystem, :unix => true do
423
443
  expect(mount.method(:opts)).to eq(mount.method(:options))
424
444
  end
425
445
 
446
+ # This method may be removed
426
447
  example 'mount time works as expected' do
427
- expected_class = solaris ? Time : NilClass
428
448
  expect(mount).to respond_to(:mount_time)
429
- expect(mount.mount_time).to be_a(expected_class)
449
+ expect(mount.mount_time).to be_nil
430
450
  end
431
451
 
432
452
  example 'mount dump_frequency works as expected' do
433
453
  msg = 'dump_frequency test skipped on this platform'
434
- skip msg if solaris || bsd || darwin
454
+ skip msg if bsd || darwin
435
455
  expect(mount).to respond_to(:dump_frequency)
436
456
  expect(mount.dump_frequency).to be_a(Numeric)
437
457
  end
@@ -443,7 +463,7 @@ RSpec.describe Sys::Filesystem, :unix => true do
443
463
 
444
464
  example 'mount pass_number works as expected' do
445
465
  msg = 'pass_number test skipped on this platform'
446
- skip msg if solaris || bsd || darwin
466
+ skip msg if bsd || darwin
447
467
  expect(mount).to respond_to(:pass_number)
448
468
  expect(mount.pass_number).to be_a(Numeric)
449
469
  end
@@ -489,11 +509,6 @@ RSpec.describe Sys::Filesystem, :unix => true do
489
509
  expect(Sys::Filesystem::Structs::Statvfs.size).to eq(dummy.check_sizeof('struct statvfs', 'sys/statvfs.h'))
490
510
  end
491
511
 
492
- example 'mnttab struct is expected size' do
493
- skip 'mnttab test skipped except on Solaris' unless solaris
494
- expect(Sys::Filesystem::Structs::Mnttab.size).to eq(dummy.check_sizeof('struct mnttab', 'sys/mnttab.h'))
495
- end
496
-
497
512
  example 'mntent struct is expected size' do
498
513
  skip 'mnttab test skipped except on Linux' unless linux
499
514
  expect(Sys::Filesystem::Structs::Mntent.size).to eq(dummy.check_sizeof('struct mntent', 'mntent.h'))
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'sys-filesystem'
5
- spec.version = '1.4.5'
5
+ spec.version = '1.5.0'
6
6
  spec.author = 'Daniel J. Berger'
7
7
  spec.email = 'djberg96@gmail.com'
8
8
  spec.homepage = 'https://github.com/djberg96/sys-filesystem'
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sys-filesystem
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.5
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Berger
@@ -35,7 +35,7 @@ cert_chain:
35
35
  ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
36
36
  WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
37
37
  -----END CERTIFICATE-----
38
- date: 2024-05-22 00:00:00.000000000 Z
38
+ date: 2024-06-09 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: ffi
metadata.gz.sig CHANGED
Binary file