sys-filesystem 0.3.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,7 @@
1
+ == 1.0.0 - ???
2
+ * Converted everything from C to FFI for the Unix flavors. The Windows
3
+ source code remains untouched.
4
+
1
5
  == 0.3.4 - 19-Nov-2010
2
6
  * Fixed a bug where negative block counts were happening on very large
3
7
  hard drives. Thanks go to Jonas Pfenniger for the spot.
data/MANIFEST CHANGED
@@ -4,10 +4,9 @@
4
4
  * README
5
5
  * sys-fileystem.gemspec
6
6
  * examples/example_stat.rb
7
- * doc/sys-filesystem.txt
8
- * ext/extconf.rb
9
- * ext/sys/filesystem.c
10
7
  * lib/sys/filesystem.rb
8
+ * lib/unix/sys/filesystem.rb
9
+ * lib/windows/sys/filesystem.rb
11
10
  * test/test_sys_filesystem.rb
12
11
  * test/test_sys_filesystem_unix
13
12
  * test/test_sys_filesystem_windows
data/Rakefile CHANGED
@@ -1,36 +1,15 @@
1
1
  require 'rake'
2
2
  require 'rake/clean'
3
3
  require 'rake/testtask'
4
- include Config
5
4
 
6
- CLEAN.include(
7
- '**/*.gem', # Gem files
8
- '**/*.rbc', # Rubinius
9
- '**/*.o', # C object file
10
- '**/*.log', # Ruby extension build log
11
- '**/Makefile', # C Makefile
12
- '**/conftest.dSYM', # OS X build directory
13
- "**/*.#{CONFIG['DLEXT']}" # C shared object
14
- )
15
-
16
- desc "Build the sys-filesystem library on UNIX systems (but don't install it)"
17
- task :build => [:clean] do
18
- unless CONFIG['host_os'] =~ /mswin32|mingw|cygwin|windows|dos/i
19
- file = 'filesystem.' + CONFIG['DLEXT']
20
- Dir.chdir('ext') do
21
- ruby 'extconf.rb'
22
- sh 'make'
23
- mv file, 'sys'
24
- end
25
- end
26
- end
5
+ CLEAN.include('**/*.gem', '**/*.rbc', '**/*.rbx')
27
6
 
28
7
  desc "Run the test suite"
29
8
  Rake::TestTask.new("test") do |t|
30
- unless CONFIG['host_os'] =~ /mswin32|mingw|cygwin|windows|dos/i
31
- task :test => :build
32
- t.libs << 'ext'
33
- t.libs.delete('lib')
9
+ if File::ALT_SEPARATOR
10
+ t.libs << 'lib/windows'
11
+ else
12
+ t.libs << 'lib/unix'
34
13
  end
35
14
 
36
15
  t.warning = true
@@ -38,36 +17,23 @@ Rake::TestTask.new("test") do |t|
38
17
  t.test_files = FileList['test/test_sys_filesystem.rb']
39
18
  end
40
19
 
41
- task :test do
42
- Rake.application[:clean].execute
43
- end
44
-
45
20
  desc "Run the example program"
46
- task :example => [:build] do |t|
47
- Dir.chdir('examples') do
48
- Dir.mkdir('sys') unless File.exists?('sys')
49
- end
50
-
51
- FileUtils.cp('ext/sys/filesystem.' + CONFIG['DLEXT'], 'examples/sys')
52
-
53
- Dir.chdir('examples') do
54
- ruby 'example_stat.rb'
55
- end
21
+ task :example do |t|
22
+ sh "ruby -Ilib -Ilib/unix -Ilib/windows examples/example_stat.rb"
56
23
  end
57
24
 
58
25
  namespace :gem do
59
26
  desc "Build the sys-filesystem gem"
60
- task :create => [:clean] do |t|
27
+ task :create do |t|
61
28
  spec = eval(IO.read('sys-filesystem.gemspec'))
62
29
 
63
- if Config::CONFIG['host_os'] =~ /mswin32|mingw|cygwin|windows|dos/i
64
- spec.files -= Dir['ext/**/*']
65
- spec.platform = Gem::Platform::CURRENT
30
+ if File::ALT_SEPARATOR
66
31
  spec.add_dependency('windows-pr', '>= 1.0.5')
32
+ spec.platform = Gem::Platform::CURRENT
33
+ spec.platform.cpu = 'universal'
34
+ spec.platform.version = nil
67
35
  else
68
- spec.extensions = ['ext/extconf.rb']
69
- spec.files -= Dir['lib/**/*']
70
- spec.extra_rdoc_files << 'ext/sys/filesystem.c'
36
+ spec.add_dependency('ffi', '>= 1.0.0')
71
37
  end
72
38
 
73
39
  Gem::Builder.new(spec).build
@@ -0,0 +1,5 @@
1
+ if File::ALT_SEPARATOR
2
+ require 'windows/sys/filesystem'
3
+ else
4
+ require 'unix/sys/filesystem'
5
+ end
@@ -0,0 +1,561 @@
1
+ require 'ffi'
2
+ require 'rbconfig'
3
+
4
+ # The Sys module serves as a namespace only.
5
+ module Sys
6
+ # The Filesystem class serves as an abstract base class. Its methods
7
+ # return objects of other types. Do not instantiate.
8
+ class Filesystem
9
+ extend FFI::Library
10
+ ffi_lib(FFI::Library::LIBC)
11
+
12
+ # The version of the sys-filesystem library.
13
+ VERSION = '1.0.0'
14
+
15
+ private
16
+
17
+ attach_function(:statvfs, [:string, :pointer], :int)
18
+ attach_function(:strerror, [:int], :string)
19
+
20
+ private_class_method :statvfs, :strerror
21
+
22
+ begin
23
+ if RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i
24
+ attach_function(:fopen, [:string, :string], :pointer)
25
+ attach_function(:fclose, [:pointer], :int)
26
+ attach_function(:getmntent, [:pointer, :pointer], :int)
27
+ private_class_method :fopen, :fclose, :getmntent
28
+ else
29
+ attach_function(:getmntent, [:pointer], :pointer)
30
+ attach_function(:setmntent, [:string, :string], :pointer)
31
+ attach_function(:endmntent, [:pointer], :int)
32
+ private_class_method :getmntent, :setmntent, :endmntent
33
+ end
34
+ rescue FFI::NotFoundError
35
+ if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach/i
36
+ attach_function(:getmntinfo, :getmntinfo64, [:pointer, :int], :int)
37
+ else
38
+ attach_function(:getmntinfo, [:pointer, :int], :int)
39
+ end
40
+ private_class_method :getmntinfo
41
+ end
42
+
43
+ MNT_RDONLY = 0x00000001 # read only filesystem
44
+ MNT_SYNCHRONOUS = 0x00000002 # file system written synchronously
45
+ MNT_NOEXEC = 0x00000004 # can't exec from filesystem
46
+ MNT_NOSUID = 0x00000008 # don't honor setuid bits on fs
47
+ MNT_NODEV = 0x00000010 # don't interpret special files
48
+ MNT_UNION = 0x00000020 # union with underlying filesystem
49
+ MNT_ASYNC = 0x00000040 # file system written asynchronously
50
+ MNT_CPROTECT = 0x00000080 # file system supports content protection
51
+ MNT_EXPORTED = 0x00000100 # file system is exported
52
+ MNT_QUARANTINE = 0x00000400 # file system is quarantined
53
+ MNT_LOCAL = 0x00001000 # filesystem is stored locally
54
+ MNT_QUOTA = 0x00002000 # quotas are enabled on filesystem
55
+ MNT_ROOTFS = 0x00004000 # identifies the root filesystem
56
+ MNT_DOVOLFS = 0x00008000 # FS supports volfs (deprecated)
57
+ MNT_DONTBROWSE = 0x00100000 # FS is not appropriate path to user data
58
+ MNT_IGNORE_OWNERSHIP = 0x00200000 # VFS will ignore ownership info on FS objects
59
+ MNT_AUTOMOUNTED = 0x00400000 # filesystem was mounted by automounter
60
+ MNT_JOURNALED = 0x00800000 # filesystem is journaled
61
+ MNT_NOUSERXATTR = 0x01000000 # Don't allow user extended attributes
62
+ MNT_DEFWRITE = 0x02000000 # filesystem should defer writes
63
+ MNT_MULTILABEL = 0x04000000 # MAC support for individual labels
64
+ MNT_NOATIME = 0x10000000 # disable update of file access time
65
+
66
+ MNT_VISFLAGMASK = (
67
+ MNT_RDONLY | MNT_SYNCHRONOUS | MNT_NOEXEC |
68
+ MNT_NOSUID | MNT_NODEV | MNT_UNION |
69
+ MNT_ASYNC | MNT_EXPORTED | MNT_QUARANTINE |
70
+ MNT_LOCAL | MNT_QUOTA |
71
+ MNT_ROOTFS | MNT_DOVOLFS | MNT_DONTBROWSE |
72
+ MNT_IGNORE_OWNERSHIP | MNT_AUTOMOUNTED | MNT_JOURNALED |
73
+ MNT_NOUSERXATTR | MNT_DEFWRITE | MNT_MULTILABEL |
74
+ MNT_NOATIME | MNT_CPROTECT
75
+ )
76
+
77
+ @@opt_names = {
78
+ MNT_RDONLY => 'read-only',
79
+ MNT_SYNCHRONOUS => 'synchronous',
80
+ MNT_NOEXEC => 'noexec',
81
+ MNT_NOSUID => 'nosuid',
82
+ MNT_NODEV => 'nodev',
83
+ MNT_UNION => 'union',
84
+ MNT_ASYNC => 'asynchronous',
85
+ MNT_CPROTECT => 'content-protection',
86
+ MNT_EXPORTED => 'exported',
87
+ MNT_QUARANTINE => 'quarantined',
88
+ MNT_LOCAL => 'local',
89
+ MNT_QUOTA => 'quotas',
90
+ MNT_ROOTFS => 'rootfs',
91
+ MNT_DONTBROWSE => 'nobrowse',
92
+ MNT_IGNORE_OWNERSHIP => 'noowners',
93
+ MNT_AUTOMOUNTED => 'automounted',
94
+ MNT_JOURNALED => 'journaled',
95
+ MNT_NOUSERXATTR => 'nouserxattr',
96
+ MNT_DEFWRITE => 'defwrite',
97
+ MNT_NOATIME => 'noatime'
98
+ }
99
+
100
+ # File used to read mount informtion from.
101
+ if File.exists?('/etc/mtab')
102
+ MOUNT_FILE = '/etc/mtab'
103
+ elsif File.exists?('/etc/mnttab')
104
+ MOUNT_FILE = '/etc/mnttab'
105
+ else
106
+ MOUNT_FILE = 'getmntinfo'
107
+ end
108
+
109
+ class Statfs < FFI::Struct
110
+ if RbConfig::CONFIG['host_os'] =~ /bsd/i
111
+ layout(
112
+ :f_version, :uint32,
113
+ :f_type, :uint32,
114
+ :f_flags, :uint64,
115
+ :f_bsize, :uint64,
116
+ :f_iosize, :int64,
117
+ :f_blocks, :uint64,
118
+ :f_bfree, :uint64,
119
+ :f_bavail, :int64,
120
+ :f_files, :uint64,
121
+ :f_ffree, :uint64,
122
+ :f_syncwrites, :uint64,
123
+ :f_asyncwrites, :uint64,
124
+ :f_syncreads, :uint64,
125
+ :f_asyncreads, :uint64,
126
+ :f_spare, [:uint64, 10],
127
+ :f_namemax, :uint32,
128
+ :f_owner, :int32,
129
+ :f_fsid, [:int32, 2],
130
+ :f_charspare, [:char, 80],
131
+ :f_fstypename, [:char, 16],
132
+ :f_mntfromname, [:char, 88],
133
+ :f_mntonname, [:char, 88]
134
+ )
135
+ else
136
+ layout(
137
+ :f_bsize, :uint32,
138
+ :f_iosize, :int32,
139
+ :f_blocks, :uint64,
140
+ :f_bfree, :uint64,
141
+ :f_bavail, :uint64,
142
+ :f_files, :uint64,
143
+ :f_ffree, :uint64,
144
+ :f_fsid, [:int32, 2],
145
+ :f_owner, :int32,
146
+ :f_type, :uint32,
147
+ :f_flags, :uint32,
148
+ :f_fssubtype, :uint32,
149
+ :f_fstypename, [:char, 16],
150
+ :f_mntonname, [:char, 1024],
151
+ :f_mntfromname, [:char, 1024],
152
+ :f_reserved, [:uint32, 8]
153
+ )
154
+ end
155
+ end
156
+
157
+ # The Statvfs struct represents struct statvfs from sys/statvfs.h.
158
+ class Statvfs < FFI::Struct
159
+ if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach/i
160
+ layout(
161
+ :f_bsize, :ulong,
162
+ :f_frsize, :ulong,
163
+ :f_blocks, :uint,
164
+ :f_bfree, :uint,
165
+ :f_bavail, :uint,
166
+ :f_files, :uint,
167
+ :f_ffree, :uint,
168
+ :f_favail, :uint,
169
+ :f_fsid, :ulong,
170
+ :f_flag, :ulong,
171
+ :f_namemax, :ulong
172
+ )
173
+ elsif RbConfig::CONFIG['host'] =~ /bsd/i
174
+ layout(
175
+ :f_bavail, :uint64,
176
+ :f_bfree, :uint64,
177
+ :f_blocks, :uint64,
178
+ :f_favail, :uint64,
179
+ :f_ffree, :uint64,
180
+ :f_files, :uint64,
181
+ :f_bsize, :ulong,
182
+ :f_flag, :ulong,
183
+ :f_frsize, :ulong,
184
+ :f_fsid, :ulong,
185
+ :f_namemax, :ulong
186
+ )
187
+ elsif RbConfig::CONFIG['host'] =~ /sunos|solaris/i
188
+ layout(
189
+ :f_bsize, :ulong,
190
+ :f_frsize, :ulong,
191
+ :f_blocks, :ulong_t,
192
+ :f_bfree, :ulong_t,
193
+ :f_bavail, :ulong_t,
194
+ :f_files, :ulong_t,
195
+ :f_ffree, :ulong_t,
196
+ :f_favail, :ulong_t,
197
+ :f_fsid, :ulong,
198
+ :f_basetype, [:char, 16],
199
+ :f_flag, :uint32,
200
+ :f_namemax, :uint32,
201
+ :f_fstr, [:char, 32],
202
+ :f_filler, [:uint32, 16]
203
+ )
204
+ else
205
+ layout(
206
+ :f_bsize, :ulong,
207
+ :f_frsize, :ulong,
208
+ :f_blocks, :ulong,
209
+ :f_bfree, :ulong,
210
+ :f_bavail, :ulong,
211
+ :f_files, :ulong,
212
+ :f_ffree, :ulong,
213
+ :f_favail, :ulong,
214
+ :f_fsid, :ulong,
215
+ :f_flag, :ulong,
216
+ :f_namemax, :ulong,
217
+ :f_ftype, :ulong,
218
+ :f_basetype, [:char, 16],
219
+ :f_str, [:char, 16]
220
+ )
221
+ end
222
+ end
223
+
224
+ # The Mnttab struct represents struct mnnttab from sys/mnttab.h on Solaris.
225
+ class Mnttab < FFI::Struct
226
+ layout(
227
+ :mnt_special, :string,
228
+ :mnt_mountp, :string,
229
+ :mnt_fstype, :string,
230
+ :mnt_mntopts, :string,
231
+ :mnt_time, :string
232
+ )
233
+ end
234
+
235
+ # The Mntent struct represents struct mntent from sys/mount.h on Unix.
236
+ class Mntent < FFI::Struct
237
+ layout(
238
+ :mnt_fsname, :string,
239
+ :mnt_dir, :string,
240
+ :mnt_type, :string,
241
+ :mnt_opts, :string,
242
+ :mnt_freq, :int,
243
+ :mnt_passno, :int
244
+ )
245
+ end
246
+
247
+ public
248
+
249
+ # The error raised if any of the Filesystem methods fail.
250
+ class Error < StandardError; end
251
+
252
+ # Stat objects are returned by the Sys::Filesystem.stat method.
253
+ class Stat
254
+ # Read-only filesystem
255
+ RDONLY = 1
256
+
257
+ # Filesystem does not support suid or sgid semantics.
258
+ NOSUID = 2
259
+
260
+ # Filesystem does not truncate file names longer than +name_max+.
261
+ NOTRUNC = 3
262
+
263
+ # The path of the filesystem.
264
+ attr_accessor :path
265
+
266
+ # The preferred system block size.
267
+ attr_accessor :block_size
268
+
269
+ # The fragment size, i.e. fundamental filesystem block size.
270
+ attr_accessor :fragment_size
271
+
272
+ # The total number of +fragment_size+ blocks in the filesystem.
273
+ attr_accessor :blocks
274
+
275
+ # The total number of free blocks in the filesystem.
276
+ attr_accessor :blocks_free
277
+
278
+ # The number of free blocks available to unprivileged processes.
279
+ attr_accessor :blocks_available
280
+
281
+ # The total number of files/inodes that can be created.
282
+ attr_accessor :files
283
+
284
+ # The total number of files/inodes on the filesystem.
285
+ attr_accessor :files_free
286
+
287
+ # The number of free files/inodes available to unprivileged processes.
288
+ attr_accessor :files_available
289
+
290
+ # The filesystem identifier.
291
+ attr_accessor :filesystem_id
292
+
293
+ # A bit mask of flags.
294
+ attr_accessor :flags
295
+
296
+ # The maximum length of a file name permitted on the filesystem.
297
+ attr_accessor :name_max
298
+
299
+ # The filesystem type, e.g. UFS.
300
+ attr_accessor :base_type
301
+
302
+ alias inodes files
303
+ alias inodes_free files_free
304
+ alias inodes_available files_available
305
+
306
+ # Creates a new Sys::Filesystem::Stat object. This is meant for
307
+ # internal use only. Do not instantiate directly.
308
+ #
309
+ def initialize
310
+ @path = nil
311
+ @block_size = nil
312
+ @fragment_size = nil
313
+ @blocks = nil
314
+ @blocks_free = nil
315
+ @blocks_available = nil
316
+ @files = nil
317
+ @files_free = nil
318
+ @files_available = nil
319
+ @filesystem_id = nil
320
+ @flags = nil
321
+ @name_max = nil
322
+ @base_type = nil
323
+ end
324
+ end
325
+
326
+ # Mount objects are returned by the Sys::Filesystem.mounts method.
327
+ class Mount
328
+ # The name of the mounted resource.
329
+ attr_accessor :name
330
+
331
+ # The mount point/directory.
332
+ attr_accessor :mount_point
333
+
334
+ # The type of filesystem mount, e.g. ufs, nfs, etc.
335
+ attr_accessor :mount_type
336
+
337
+ # A list of comma separated options for the mount, e.g. nosuid, etc.
338
+ attr_accessor :options
339
+
340
+ # The time the filesystem was mounted. May be nil.
341
+ attr_accessor :mount_time
342
+
343
+ # The dump frequency in days. May be nil.
344
+ attr_accessor :dump_frequency
345
+
346
+ # The pass number of the filessytem check. May be nil.
347
+ attr_accessor :pass_number
348
+
349
+ alias fsname name
350
+ alias dir mount_point
351
+ alias opts options
352
+ alias passno pass_number
353
+ alias freq dump_frequency
354
+
355
+ # Creates a Sys::Filesystem::Mount object. This is meant for internal
356
+ # use only. Do no instantiate directly.
357
+ #
358
+ def initialize
359
+ @name = nil
360
+ @mount_point = nil
361
+ @mount_type = nil
362
+ @options = nil
363
+ @mount_time = nil
364
+ @dump_frequency = nil
365
+ @pass_number = nil
366
+ end
367
+ end
368
+
369
+ # Returns a Sys::Filesystem::Stat object containing information about the
370
+ # +path+ on the filesystem.
371
+ #
372
+ def self.stat(path)
373
+ fs = Statvfs.new
374
+
375
+ if statvfs(path, fs) < 0
376
+ raise Error, 'statvfs() function failed: ' + strerror(FFI.errno)
377
+ end
378
+
379
+ obj = Sys::Filesystem::Stat.new
380
+ obj.path = path
381
+ obj.block_size = fs[:f_bsize]
382
+ obj.fragment_size = fs[:f_frsize]
383
+ obj.blocks = fs[:f_blocks]
384
+ obj.blocks_free = fs[:f_bfree]
385
+ obj.blocks_available = fs[:f_bavail]
386
+ obj.files = fs[:f_files]
387
+ obj.files_free = fs[:f_ffree]
388
+ obj.files_available = fs[:f_favail]
389
+ obj.filesystem_id = fs[:f_fsid]
390
+ obj.flags = fs[:f_flag]
391
+ obj.name_max = fs[:f_namemax]
392
+
393
+ # OSX does things a little differently
394
+ if RbConfig::CONFIG['host_os'] =~ /darwin|osx|mach/i
395
+ obj.block_size /= 256
396
+ end
397
+
398
+ if fs.members.include?(:f_basetype)
399
+ obj.base_type = fs[:f_basetype].to_s
400
+ end
401
+
402
+ obj.freeze
403
+ end
404
+
405
+ # In block form, yields a Sys::Filesystem::Mount object for each mounted
406
+ # filesytem on the host. Otherwise it returns an array of Mount objects.
407
+ #
408
+ # Example:
409
+ #
410
+ # Sys::Filesystem.mounts{ |fs|
411
+ # p fs.name # => '/dev/dsk/c0t0d0s0'
412
+ # p fs.mount_time # => Thu Dec 11 15:07:23 -0700 2008
413
+ # p fs.mount_type # => 'ufs'
414
+ # p fs.mount_point # => '/'
415
+ # p fs.options # => local, noowner, nosuid
416
+ # }
417
+ #
418
+ def self.mounts
419
+ array = block_given? ? nil : []
420
+
421
+ if respond_to?(:getmntinfo, true)
422
+ buf = FFI::MemoryPointer.new(:pointer)
423
+
424
+ num = getmntinfo(buf, 2)
425
+
426
+ if num == 0
427
+ raise Error, 'getmntinfo() function failed: ' + strerror(FFI.errno)
428
+ end
429
+
430
+ ptr = buf.get_pointer(0)
431
+
432
+ num.times{ |i|
433
+ mnt = Statfs.new(ptr)
434
+ obj = Sys::Filesystem::Mount.new
435
+ obj.name = mnt[:f_mntfromname].to_s
436
+ obj.mount_point = mnt[:f_mntonname].to_s
437
+ obj.mount_type = mnt[:f_fstypename].to_s
438
+
439
+ string = ""
440
+ flags = mnt[:f_flags] & MNT_VISFLAGMASK
441
+
442
+ @@opt_names.each{ |key,val|
443
+ if flags & key > 0
444
+ if string.empty?
445
+ string << val
446
+ else
447
+ string << ", #{val}"
448
+ end
449
+ end
450
+ flags &= ~key
451
+ }
452
+
453
+ obj.options = string
454
+
455
+ if block_given?
456
+ yield obj.freeze
457
+ else
458
+ array << obj.freeze
459
+ end
460
+
461
+ ptr += Statfs.size
462
+ }
463
+ else
464
+ begin
465
+ if respond_to?(:setmntent, true)
466
+ fp = setmntent(MOUNT_FILE, 'r')
467
+ else
468
+ fp = fopen(MOUNT_FILE, 'r')
469
+ end
470
+
471
+ if RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i
472
+ mt = Mnttab.new
473
+ while getmntent(fp, mt) == 0
474
+ obj = Sys::Filesystem::Mount.new
475
+ obj.name = mt[:mnt_special].to_s
476
+ obj.mount_point = mt[:mnt_mountp].to_s
477
+ obj.mount_type = mt[:mnt_fstype].to_s
478
+ obj.options = mt[:mnt_mntopts].to_s
479
+ obj.mount_time = Time.at(Integer(mt[:mnt_time]))
480
+
481
+ if block_given?
482
+ yield obj.freeze
483
+ else
484
+ array << obj.freeze
485
+ end
486
+ end
487
+ else
488
+ while ptr = getmntent(fp)
489
+ break if ptr.null?
490
+ mt = Mntent.new(ptr)
491
+
492
+ obj = Sys::Filesystem::Mount.new
493
+ obj.name = mt[:mnt_fsname]
494
+ obj.mount_point = mt[:mnt_dir]
495
+ obj.mount_type = mt[:mnt_type]
496
+ obj.options = mt[:mnt_opts]
497
+ obj.mount_time = nil
498
+ obj.dump_frequency = mt[:mnt_freq]
499
+ obj.pass_number = mt[:mnt_passno]
500
+
501
+ if block_given?
502
+ yield obj.freeze
503
+ else
504
+ array << obj.freeze
505
+ end
506
+ end
507
+ end
508
+ ensure
509
+ if fp && !fp.null?
510
+ if respond_to?(:endmntent, true)
511
+ endmntent(fp)
512
+ else
513
+ fclose(fp)
514
+ end
515
+ end
516
+ end
517
+ end
518
+
519
+ array
520
+ end
521
+
522
+ # Returns the mount point of the given +file+, or itself if it cannot
523
+ # be found.
524
+ #
525
+ # Example:
526
+ #
527
+ # Sys::Filesystem.mount_point('/home/some_user') # => /home
528
+ #
529
+ def self.mount_point(file)
530
+ dev = File.stat(file).dev
531
+ val = file
532
+
533
+ self.mounts.each{ |mnt|
534
+ mp = mnt.mount_point
535
+ if File.stat(mp).dev == dev
536
+ val = mp
537
+ break
538
+ end
539
+ }
540
+
541
+ val
542
+ end
543
+ end
544
+ end
545
+
546
+ class Fixnum
547
+ # Converts a number to kilobytes.
548
+ def to_kb
549
+ self / 1024
550
+ end
551
+
552
+ # Converts a number to megabytes.
553
+ def to_mb
554
+ self / 1048576
555
+ end
556
+
557
+ # Converts a number to gigabytes.
558
+ def to_gb
559
+ self / 1073741824
560
+ end
561
+ end