sys-filesystem 0.3.4-x86-mingw32 → 1.0.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,408 +1,5 @@
1
- require 'windows/error'
2
- require 'windows/path'
3
- require 'windows/filesystem'
4
- require 'windows/volume'
5
- require 'windows/handle'
6
- require 'windows/limits'
7
- require 'socket'
8
- require 'win32ole'
9
- require 'date'
10
- require 'time'
11
-
12
- # The Sys module serves as a namespace only.
13
- module Sys
14
-
15
- # The Filesystem class encapsulates information about your filesystem.
16
- class Filesystem
17
- include Windows::Error
18
- include Windows::Handle
19
- include Windows::Limits
20
-
21
- extend Windows::Error
22
- extend Windows::FileSystem
23
- extend Windows::Volume
24
- extend Windows::Path
25
-
26
- # Error typically raised if any of the Sys::Filesystem methods fail.
27
- class Error < StandardError; end
28
-
29
- CASE_SENSITIVE_SEARCH = 0x00000001
30
- CASE_PRESERVED_NAMES = 0x00000002
31
- UNICODE_ON_DISK = 0x00000004
32
- PERSISTENT_ACLS = 0x00000008
33
- FILE_COMPRESSION = 0x00000010
34
- VOLUME_QUOTAS = 0x00000020
35
- SUPPORTS_SPARSE_FILES = 0x00000040
36
- SUPPORTS_REPARSE_POINTS = 0x00000080
37
- SUPPORTS_REMOTE_STORAGE = 0x00000100
38
- VOLUME_IS_COMPRESSED = 0x00008000
39
- SUPPORTS_OBJECT_IDS = 0x00010000
40
- SUPPORTS_ENCRYPTION = 0x00020000
41
- NAMED_STREAMS = 0x00040000
42
- READ_ONLY_VOLUME = 0x00080000
43
-
44
- # The version of the sys-filesystem library.
45
- VERSION = '0.3.4'
46
-
47
- class Mount
48
- # The name of the volume. This is the device mapping.
49
- attr_reader :name
50
-
51
- # The last time the volume was mounted. For MS Windows this equates
52
- # to your system's boot time.
53
- attr_reader :mount_time
54
-
55
- # The type of mount, e.g. NTFS, UDF, etc.
56
- attr_reader :mount_type
57
-
58
- # The volume mount point, e.g. 'C:\'
59
- attr_reader :mount_point
60
-
61
- # Various comma separated options that reflect the volume's features
62
- attr_reader :options
63
-
64
- # Always nil on MS Windows. Provided for interface compatibility only.
65
- attr_reader :pass_number
66
-
67
- # Always nil on MS Windows. Provided for interface compatibility only.
68
- attr_reader :frequency
69
-
70
- alias fsname name
71
- alias dir mount_point
72
- alias opts options
73
- alias passno pass_number
74
- alias freq frequency
75
- end
76
-
77
- class Stat
78
- # The path of the file system.
79
- attr_reader :path
80
-
81
- # The file system block size. MS Windows typically defaults to 4096.
82
- attr_reader :block_size
83
-
84
- # Fragment size. Meaningless at the moment.
85
- attr_reader :fragment_size
86
-
87
- # The total number of blocks available (used or unused) on the file
88
- # system.
89
- attr_reader :blocks
90
-
91
- # The total number of unused blocks.
92
- attr_reader :blocks_free
93
-
94
- # The total number of unused blocks available to unprivileged
95
- # processes. Identical to +blocks+ at the moment.
96
- attr_reader :blocks_available
97
-
98
- # Total number of files/inodes that can be created on the file system.
99
- # This attribute is always nil on MS Windows.
100
- attr_reader :files
101
-
102
- # Total number of free files/inodes that can be created on the file
103
- # system. This attribute is always nil on MS Windows.
104
- attr_reader :files_free
105
-
106
- # Total number of available files/inodes for unprivileged processes
107
- # that can be created on the file system. This attribute is always
108
- # nil on MS Windows.
109
- attr_reader :files_available
110
-
111
- # The file system volume id.
112
- attr_reader :filesystem_id
113
-
114
- # A bit mask of file system flags.
115
- attr_reader :flags
116
-
117
- # The maximum length of a file name permitted on the file system.
118
- attr_reader :name_max
119
-
120
- # The file system type, e.g. NTFS, FAT, etc.
121
- attr_reader :base_type
122
-
123
- alias inodes files
124
- alias inodes_free files_free
125
- alias inodes_available files_available
126
- end
127
-
128
- # Yields a Filesystem::Mount object for each volume on your system in
129
- # block form. Returns an array of Filesystem::Mount objects in non-block
130
- # form.
131
- #
132
- # Example:
133
- #
134
- # Sys::Filesystem.mounts{ |mount|
135
- # p mt.name # => \\Device\\HarddiskVolume1
136
- # p mt.mount_point # => C:\
137
- # p mt.mount_time # => Thu Dec 18 20:12:08 -0700 2008
138
- # p mt.mount_type # => NTFS
139
- # p mt.options # => casepres,casesens,ro,unicode
140
- # p mt.pass_number # => nil
141
- # p mt.dump_freq # => nil
142
- # }
143
- #
144
- # This method is a bit of a fudge for MS Windows in the name of interface
145
- # compatibility because this method deals with volumes, not actual mount
146
- # points. But, I believe it provides the sort of information many users
147
- # want at a glance.
148
- #
149
- # The possible values for the +options+ and their meanings are as follows:
150
- #
151
- # casepres => The filesystem preserves the case of file names when it places a name on disk.
152
- # casesens => The filesystem supports case-sensitive file names.
153
- # compression => The filesystem supports file-based compression.
154
- # namedstreams => The filesystem supports named streams.
155
- # pacls => The filesystem preserves and enforces access control lists.
156
- # ro => The filesystem is read-only.
157
- # encryption => The filesystem supports the Encrypted File System (EFS).
158
- # objids => The filesystem supports object identifiers.
159
- # rpoints => The filesystem supports reparse points.
160
- # sparse => The filesystem supports sparse files.
161
- # unicode => The filesystem supports Unicode in file names as they appear on disk.
162
- # compressed => The filesystem is compressed.
163
- #
164
- def self.mounts
165
- buffer = 0.chr * MAXPATH
166
- length = GetLogicalDriveStrings(buffer.size, buffer)
167
-
168
- if length == 0
169
- raise Error, get_last_error
170
- end
171
-
172
- mounts = block_given? ? nil : []
173
-
174
- # Try again if it fails because the buffer is too small
175
- if length > buffer.size
176
- buffer = 0.chr * length
177
- if GetLogicalDriveStrings(buffer.size, buffer) == 0
178
- raise Error, get_last_error
179
- end
180
- end
181
-
182
- boot_time = get_boot_time
183
-
184
- drives = buffer.strip.split("\0")
185
-
186
- drives.each{ |drive|
187
- mount = Mount.new
188
- volume = 0.chr * MAXPATH
189
- fsname = 0.chr * MAXPATH
190
-
191
- mount.instance_variable_set(:@mount_point, drive)
192
- mount.instance_variable_set(:@mount_time, boot_time)
193
-
194
- volume_serial_number = [0].pack('L')
195
- max_component_length = [0].pack('L')
196
- filesystem_flags = [0].pack('L')
197
-
198
- bool = GetVolumeInformation(
199
- drive,
200
- volume,
201
- volume.size,
202
- volume_serial_number,
203
- max_component_length,
204
- filesystem_flags,
205
- fsname,
206
- fsname.size
207
- )
208
-
209
- # Skip unmounted floppies or cd-roms
210
- unless bool
211
- errnum = GetLastError()
212
- if errnum == ERROR_NOT_READY
213
- next
214
- else
215
- raise Error, get_last_error(errnum)
216
- end
217
- end
218
-
219
- filesystem_flags = filesystem_flags.unpack('L')[0]
220
-
221
- name = 0.chr * MAXPATH
222
-
223
- if QueryDosDevice(drive[0,2], name, name.size) == 0
224
- raise Error, get_last_error
225
- end
226
-
227
- mount.instance_variable_set(:@name, name.strip)
228
- mount.instance_variable_set(:@mount_type, fsname.strip)
229
- mount.instance_variable_set(:@options, get_options(filesystem_flags))
230
-
231
- if block_given?
232
- yield mount
233
- else
234
- mounts << mount
235
- end
236
- }
237
-
238
- mounts # Nil if the block form was used.
239
- end
240
-
241
- # Returns the mount point for the given +file+. For MS Windows this
242
- # means the root of the path.
243
- #
244
- # Example:
245
- #
246
- # File.mount_point("C:\\Documents and Settings") # => "C:\\'
247
- #
248
- def self.mount_point(file)
249
- file = file.tr(File::SEPARATOR, File::ALT_SEPARATOR)
250
- PathStripToRoot(file)
251
- file[/^[^\0]*/]
252
- end
253
-
254
- # Returns a Filesystem::Stat object that contains information about the
255
- # +path+ file system.
256
- #
257
- # Examples:
258
- #
259
- # File.stat("C:\\")
260
- # File.stat("C:\\Documents and Settings\\some_user")
261
- #
262
- def self.stat(path)
263
- bytes_avail = [0].pack('Q')
264
- bytes_free = [0].pack('Q')
265
- total_bytes = [0].pack('Q')
266
-
267
- unless GetDiskFreeSpaceEx(path, bytes_avail, total_bytes, bytes_free)
268
- raise Error, get_last_error
269
- end
270
-
271
- bytes_avail = bytes_avail.unpack('Q').first
272
- bytes_free = bytes_free.unpack('Q').first
273
- total_bytes = total_bytes.unpack('Q').first
274
-
275
- sectors = [0].pack('Q')
276
- bytes = [0].pack('Q')
277
- free = [0].pack('Q')
278
- total = [0].pack('Q')
279
-
280
- unless GetDiskFreeSpace(path, sectors, bytes, free, total)
281
- raise Error, get_last_error
282
- end
283
-
284
- sectors = sectors.unpack('Q').first
285
- bytes = bytes.unpack('Q').first
286
- free = free.unpack('Q').first
287
- total = total.unpack('Q').first
288
-
289
- block_size = sectors * bytes
290
- blocks_avail = total_bytes / block_size
291
- blocks_free = bytes_free / block_size
292
-
293
- vol_name = 0.chr * 260
294
- base_type = 0.chr * 260
295
- vol_serial = [0].pack('L')
296
- name_max = [0].pack('L')
297
- flags = [0].pack('L')
298
-
299
- bool = GetVolumeInformation(
300
- path,
301
- vol_name,
302
- vol_name.size,
303
- vol_serial,
304
- name_max,
305
- flags,
306
- base_type,
307
- base_type.size
308
- )
309
-
310
- unless bool
311
- raise Error, get_last_error
312
- end
313
-
314
- vol_serial = vol_serial.unpack('L').first
315
- name_max = name_max.unpack('L').first
316
- flags = flags.unpack('L').first
317
- base_type = base_type[/^[^\0]*/]
318
-
319
- stat_obj = Stat.new
320
- stat_obj.instance_variable_set(:@path, path)
321
- stat_obj.instance_variable_set(:@block_size, block_size)
322
- stat_obj.instance_variable_set(:@blocks, blocks_avail)
323
- stat_obj.instance_variable_set(:@blocks_available, blocks_avail)
324
- stat_obj.instance_variable_set(:@blocks_free, blocks_free)
325
- stat_obj.instance_variable_set(:@name_max, name_max)
326
- stat_obj.instance_variable_set(:@base_type, base_type)
327
- stat_obj.instance_variable_set(:@flags, flags)
328
- stat_obj.instance_variable_set(:@filesystem_id, vol_serial)
329
-
330
- stat_obj.freeze # Read-only object
331
- end
332
-
333
- private
334
-
335
- # This method is used to get the boot time of the system, which is used
336
- # for the mount_time attribute within the File.mounts method.
337
- #
338
- def self.get_boot_time
339
- host = Socket.gethostname
340
- cs = "winmgmts://#{host}/root/cimv2"
341
- begin
342
- wmi = WIN32OLE.connect(cs)
343
- rescue WIN32OLERuntimeError => e
344
- raise Error, e
345
- else
346
- query = 'select LastBootupTime from Win32_OperatingSystem'
347
- results = wmi.ExecQuery(query)
348
- results.each{ |ole|
349
- time_array = Time.parse(ole.LastBootupTime.split('.').first)
350
- return Time.mktime(*time_array)
351
- }
352
- end
353
- end
354
-
355
- # Private method that converts filesystem flags into a comma separated
356
- # list of strings. The presentation is meant as a rough analogue to the
357
- # way options are presented for Unix filesystems.
358
- #
359
- def self.get_options(flags)
360
- str = ""
361
- str << " casepres" if CASE_PRESERVED_NAMES & flags > 0
362
- str << " casesens" if CASE_SENSITIVE_SEARCH & flags > 0
363
- str << " compression" if FILE_COMPRESSION & flags > 0
364
- str << " namedstreams" if NAMED_STREAMS & flags > 0
365
- str << " pacls" if PERSISTENT_ACLS & flags > 0
366
- str << " ro" if READ_ONLY_VOLUME & flags > 0
367
- str << " encryption" if SUPPORTS_ENCRYPTION & flags > 0
368
- str << " objids" if SUPPORTS_OBJECT_IDS & flags > 0
369
- str << " rpoints" if SUPPORTS_REPARSE_POINTS & flags > 0
370
- str << " sparse" if SUPPORTS_SPARSE_FILES & flags > 0
371
- str << " unicode" if UNICODE_ON_DISK & flags > 0
372
- str << " compressed" if VOLUME_IS_COMPRESSED & flags > 0
373
-
374
- str.tr!(' ', ',')
375
- str = str[1..-1] # Ignore the first comma
376
- str
377
- end
378
-
379
- end
380
- end
381
-
382
- # Some convenient methods for converting bytes to kb, mb, and gb.
383
- #
384
- class Fixnum
385
- # call-seq:
386
- # <tt>fix</tt>.to_kb
387
- #
388
- # Returns +fix+ in terms of kilobytes.
389
- def to_kb
390
- self / 1024
391
- end
392
-
393
- # call-seq:
394
- # <tt>fix</tt>.to_mb
395
- #
396
- # Returns +fix+ in terms of megabytes.
397
- def to_mb
398
- self / 1048576
399
- end
400
-
401
- # call-seq:
402
- # <tt>fix</tt>.to_gb
403
- #
404
- # Returns +fix+ in terms of gigabytes.
405
- def to_gb
406
- self / 1073741824
407
- end
408
- end
1
+ if File::ALT_SEPARATOR
2
+ require 'windows/sys/filesystem'
3
+ else
4
+ require 'unix/sys/filesystem'
5
+ end