win32-file-stat 1.2.3
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.
- data/CHANGES +32 -0
- data/MANIFEST +11 -0
- data/README +64 -0
- data/install.rb +12 -0
- data/lib/win32/file/stat.rb +552 -0
- data/test/sometestfile.exe +1 -0
- data/test/sometestfile.txt +1 -0
- data/test/tc_file_stat.rb +312 -0
- data/win32-file-stat.gemspec +24 -0
- metadata +65 -0
data/CHANGES
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
== 1.2.3 - 4-Nov-2006
|
2
|
+
* Bug fix for file sizes over 4gb.
|
3
|
+
|
4
|
+
== 1.2.2 - 13-May-2006
|
5
|
+
* Yet another blksize bug fix.
|
6
|
+
* Minor tweak to the pretty_print method with regards to handling nil values.
|
7
|
+
* Bumped the minimum required windows-pr version to 0.4.0 in the gemspec.
|
8
|
+
|
9
|
+
== 1.2.1 - 12-May-2006
|
10
|
+
* Fixed a bug with regards to the block count where the constructor would die
|
11
|
+
with a FloatDomainError if the blksize returned 0 or nil. It now defaults
|
12
|
+
to nil in that event.
|
13
|
+
|
14
|
+
== 1.2.0 - 23-Apr-2006
|
15
|
+
* Removed the attribute setters. From now on this class provides readonly
|
16
|
+
methods. Use the win32-file package for attribute setters.
|
17
|
+
* Added the content_indexed? alias for the indexed? method.
|
18
|
+
* Corresponding test suite changes.
|
19
|
+
* Fixed the pp issue by writing a custom pretty_print method.
|
20
|
+
|
21
|
+
== 1.1.0 - 15-Apr-2006
|
22
|
+
* Added the chardev?, dev_major, dev_minor directory?, file?, executable?,
|
23
|
+
executable_real?, ftype, grpowned?, owned?, pipe?, readable?, readable_real?,
|
24
|
+
rdev_major, rdev_minor, setgid?, setuid?, size?, socket?, sticky?, symlink?,
|
25
|
+
writable?, writable_real? and zero? methods. Note that not all of these
|
26
|
+
methods return meaningful values and were merely added to match the current
|
27
|
+
spec. See documentation for details.
|
28
|
+
* Added a VERSION constant.
|
29
|
+
* Some optimization in the constructor.
|
30
|
+
|
31
|
+
== 1.0.0 - 13-Apr-2006
|
32
|
+
* Initial release
|
data/MANIFEST
ADDED
data/README
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
= Description
|
2
|
+
A redefinition of the File::Stat class for MS Windows.
|
3
|
+
|
4
|
+
= Prerequisites
|
5
|
+
Ruby 1.8.0 or later.
|
6
|
+
windows-pr 0.4.0 or later.
|
7
|
+
|
8
|
+
= Installation, pure Ruby
|
9
|
+
== Manual Installation
|
10
|
+
ruby test/tc_file_stat.rb (optional)
|
11
|
+
ruby install.rb
|
12
|
+
|
13
|
+
== Gem Installation
|
14
|
+
=== Local
|
15
|
+
ruby test/tc_file_stat.rb (Unix, optional)
|
16
|
+
gem install win32-file-stat-<version>.gem
|
17
|
+
=== Remote
|
18
|
+
gem install win32-file-stat
|
19
|
+
|
20
|
+
= Synopsis
|
21
|
+
require 'win32/file/stat'
|
22
|
+
|
23
|
+
stat = File::Stat.new('file.txt')
|
24
|
+
stat.size
|
25
|
+
stat.readonly?
|
26
|
+
stat.hidden?
|
27
|
+
|
28
|
+
= Differences between Ruby's File::Stat and this version:
|
29
|
+
* The File::Stat#blksize method returns a meaningful value.
|
30
|
+
* The File::Stat#blockdev method works more accurately.
|
31
|
+
* The File::Stat#blocks method returns a meaningful value.
|
32
|
+
* The File::Stat#dev method returns a drive letter, not a number.
|
33
|
+
* The File::Stat#executable? method works properly.
|
34
|
+
* The File::Stat#executable_real? returns the same value as
|
35
|
+
File::Stat#executable? (which now works properly).
|
36
|
+
* The File::Stat#file? method works properly.
|
37
|
+
* The File::Stat#ftype method works more accurately.
|
38
|
+
* The File::Stat#pipe method works properly.
|
39
|
+
* The File::Stat#size method handles file sizes greater than 2 gigabytes
|
40
|
+
correctly.
|
41
|
+
* The File::Stat#socket method works more accurately.
|
42
|
+
* Allows you to get file attributes specific to MS Windows, e.g. archive,
|
43
|
+
hidden, etc.
|
44
|
+
* The pp (pretty print) output has been customized.
|
45
|
+
|
46
|
+
= Known issues or bugs
|
47
|
+
None that I'm aware of. Please report any bugs you find on the project page
|
48
|
+
at http://www.rubyforge.org/projects/win32utils.
|
49
|
+
|
50
|
+
= Miscellaneous
|
51
|
+
I had to require 'pp' explicitly in order to deal with the fact that pp.rb
|
52
|
+
has a builtin pretty_print method for File::Stat. If I didn't do this
|
53
|
+
you would end up using the pretty_print in pp.rb, which would break.
|
54
|
+
|
55
|
+
= License
|
56
|
+
Ruby's
|
57
|
+
|
58
|
+
= Warranty
|
59
|
+
This package is provided "as is" and without any express or
|
60
|
+
implied warranties, including, without limitation, the implied
|
61
|
+
warranties of merchantability and fitness for a particular purpose.
|
62
|
+
|
63
|
+
= Author
|
64
|
+
Daniel J. Berger
|
data/install.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'ftools'
|
3
|
+
include Config
|
4
|
+
|
5
|
+
sitelibdir = CONFIG['sitelibdir']
|
6
|
+
installdir = sitelibdir + '/win32/file'
|
7
|
+
basedir = File.dirname(installdir)
|
8
|
+
file = 'lib\win32\file\stat.rb'
|
9
|
+
|
10
|
+
Dir.mkdir(basedir) unless File.exists?(basedir)
|
11
|
+
Dir.mkdir(installdir) unless File.exists?(installdir)
|
12
|
+
File.copy(file, installdir, true)
|
@@ -0,0 +1,552 @@
|
|
1
|
+
require 'windows/msvcrt/buffer'
|
2
|
+
require 'windows/msvcrt/file'
|
3
|
+
require 'windows/filesystem'
|
4
|
+
require 'windows/device_io'
|
5
|
+
require 'windows/path'
|
6
|
+
require 'windows/file'
|
7
|
+
require 'windows/error'
|
8
|
+
require 'windows/handle'
|
9
|
+
require 'pp'
|
10
|
+
|
11
|
+
class File::Stat
|
12
|
+
include Windows::MSVCRT::Buffer
|
13
|
+
include Windows::MSVCRT::File
|
14
|
+
include Windows::DeviceIO
|
15
|
+
include Windows::FileSystem
|
16
|
+
include Windows::Path
|
17
|
+
include Windows::File
|
18
|
+
include Windows::Error
|
19
|
+
include Windows::Handle
|
20
|
+
include Comparable
|
21
|
+
|
22
|
+
VERSION = '1.2.3'
|
23
|
+
|
24
|
+
# Defined in Ruby's win32.h. Not meant for public consumption.
|
25
|
+
S_IWGRP = 0020
|
26
|
+
S_IWOTH = 0002
|
27
|
+
|
28
|
+
attr_reader :dev_major, :dev_minor, :rdev_major, :rdev_minor
|
29
|
+
|
30
|
+
# Creates and returns a File::Stat object, which encapsulate common status
|
31
|
+
# information for File objects on MS Windows sytems. The information is
|
32
|
+
# recorded at the moment the File::Stat object is created; changes made to
|
33
|
+
# the file after that point will not be reflected.
|
34
|
+
#
|
35
|
+
def initialize(file)
|
36
|
+
@file = file
|
37
|
+
|
38
|
+
@blockdev = false
|
39
|
+
@file_type = get_file_type(file) # May update @blockdev
|
40
|
+
|
41
|
+
@chardev = @file_type == FILE_TYPE_CHAR
|
42
|
+
|
43
|
+
stat_buf = [0,0,0,0,0,0,0,0,0,0,0,0,0].pack('ISSssssIIQQQQ')
|
44
|
+
|
45
|
+
# The stat64 function doesn't seem to like character devices
|
46
|
+
if stat64(file, stat_buf) != 0
|
47
|
+
raise ArgumentError, get_last_error unless @chardev
|
48
|
+
end
|
49
|
+
|
50
|
+
# Some bytes skipped (padding for struct alignment)
|
51
|
+
@dev = stat_buf[0, 4].unpack('I').first # Drive number
|
52
|
+
@ino = stat_buf[4, 2].unpack('S').first # Meaningless
|
53
|
+
@mode = stat_buf[6, 2].unpack('S').first # File mode bit mask
|
54
|
+
@nlink = stat_buf[8, 2].unpack('s').first # Always 1
|
55
|
+
@uid = stat_buf[10, 2].unpack('s').first # Always 0
|
56
|
+
@gid = stat_buf[12, 2].unpack('s').first # Always 0
|
57
|
+
@rdev = stat_buf[16, 4].unpack('I').first # Same as dev
|
58
|
+
@size = stat_buf[24, 8].unpack('Q').first # Size of file in bytes
|
59
|
+
@atime = Time.at(stat_buf[32, 8].unpack('Q').first) # Access time
|
60
|
+
@mtime = Time.at(stat_buf[40, 8].unpack('Q').first) # Modification time
|
61
|
+
@ctime = Time.at(stat_buf[48, 8].unpack('Q').first) # Creation time
|
62
|
+
|
63
|
+
@mode = 33188 if @chardev
|
64
|
+
|
65
|
+
attr = GetFileAttributes(file)
|
66
|
+
|
67
|
+
if attr == INVALID_FILE_ATTRIBUTES
|
68
|
+
raise ArgumentError, get_last_error
|
69
|
+
end
|
70
|
+
|
71
|
+
@blksize = get_blksize(file)
|
72
|
+
|
73
|
+
# This is a reasonable guess
|
74
|
+
case @blksize
|
75
|
+
when nil
|
76
|
+
@blocks = nil
|
77
|
+
when 0
|
78
|
+
@blocks = 0
|
79
|
+
else
|
80
|
+
@blocks = (@size.to_f / @blksize.to_f).ceil
|
81
|
+
end
|
82
|
+
|
83
|
+
@readonly = attr & FILE_ATTRIBUTE_READONLY > 0
|
84
|
+
@hidden = attr & FILE_ATTRIBUTE_HIDDEN > 0
|
85
|
+
@system = attr & FILE_ATTRIBUTE_SYSTEM > 0
|
86
|
+
@archive = attr & FILE_ATTRIBUTE_ARCHIVE > 0
|
87
|
+
@directory = attr & FILE_ATTRIBUTE_DIRECTORY > 0
|
88
|
+
@encrypted = attr & FILE_ATTRIBUTE_ENCRYPTED > 0
|
89
|
+
@normal = attr & FILE_ATTRIBUTE_NORMAL > 0
|
90
|
+
@temporary = attr & FILE_ATTRIBUTE_TEMPORARY > 0
|
91
|
+
@sparse = attr & FILE_ATTRIBUTE_SPARSE_FILE > 0
|
92
|
+
@reparse_point = attr & FILE_ATTRIBUTE_REPARSE_POINT > 0
|
93
|
+
@compressed = attr & FILE_ATTRIBUTE_COMPRESSED > 0
|
94
|
+
@offline = attr & FILE_ATTRIBUTE_OFFLINE > 0
|
95
|
+
@indexed = attr & ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED > 0
|
96
|
+
|
97
|
+
@executable = GetBinaryType(file, '')
|
98
|
+
@regular = @file_type == FILE_TYPE_DISK
|
99
|
+
@pipe = @file_type == FILE_TYPE_PIPE
|
100
|
+
|
101
|
+
# Not supported and/or meaningless
|
102
|
+
@dev_major = nil
|
103
|
+
@dev_minor = nil
|
104
|
+
@grpowned = true
|
105
|
+
@owned = true
|
106
|
+
@readable = true
|
107
|
+
@readable_real = true
|
108
|
+
@rdev_major = nil
|
109
|
+
@rdev_minor = nil
|
110
|
+
@setgid = false
|
111
|
+
@setuid = false
|
112
|
+
@sticky = false
|
113
|
+
@symlink = false
|
114
|
+
@writable = true
|
115
|
+
@writable_real = true
|
116
|
+
end
|
117
|
+
|
118
|
+
## Comparable
|
119
|
+
|
120
|
+
# Compares two File::Stat objects. Comparsion is based on mtime only.
|
121
|
+
#
|
122
|
+
def <=>(other)
|
123
|
+
@mtime.to_i <=> other.mtime.to_i
|
124
|
+
end
|
125
|
+
|
126
|
+
## Miscellaneous
|
127
|
+
|
128
|
+
def blockdev?
|
129
|
+
@blockdev
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns whether or not the file is a character device.
|
133
|
+
#
|
134
|
+
def chardev?
|
135
|
+
@chardev
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns whether or not the file is executable. Generally speaking, this
|
139
|
+
# means .bat, .cmd, .com, and .exe files.
|
140
|
+
#
|
141
|
+
def executable?
|
142
|
+
@executable
|
143
|
+
end
|
144
|
+
|
145
|
+
alias :executable_real? :executable?
|
146
|
+
|
147
|
+
# Returns whether or not the file is a regular file, as opposed to a pipe,
|
148
|
+
# socket, etc.
|
149
|
+
#
|
150
|
+
def file?
|
151
|
+
@regular
|
152
|
+
end
|
153
|
+
|
154
|
+
# Identifies the type of file. The return string is one of: file,
|
155
|
+
# directory, characterSpecial, socket or unknown.
|
156
|
+
#
|
157
|
+
def ftype
|
158
|
+
return 'directory' if directory?
|
159
|
+
case @file_type
|
160
|
+
when FILE_TYPE_CHAR
|
161
|
+
'characterSpecial'
|
162
|
+
when FILE_TYPE_DISK
|
163
|
+
'file'
|
164
|
+
when FILE_TYPE_PIPE
|
165
|
+
'socket'
|
166
|
+
else
|
167
|
+
if blockdev?
|
168
|
+
'blockSpecial'
|
169
|
+
else
|
170
|
+
'unknown'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Meaningless on Windows.
|
176
|
+
#
|
177
|
+
def grpowned?
|
178
|
+
@grpowned
|
179
|
+
end
|
180
|
+
|
181
|
+
# Always true on Windows
|
182
|
+
def owned?
|
183
|
+
@owned
|
184
|
+
end
|
185
|
+
|
186
|
+
# Returns whether or not the file is a pipe.
|
187
|
+
#
|
188
|
+
def pipe?
|
189
|
+
@pipe
|
190
|
+
end
|
191
|
+
|
192
|
+
alias :socket? :pipe?
|
193
|
+
|
194
|
+
# Meaningless on Windows
|
195
|
+
#
|
196
|
+
def readable?
|
197
|
+
@readable
|
198
|
+
end
|
199
|
+
|
200
|
+
# Meaningless on Windows
|
201
|
+
#
|
202
|
+
def readable_real?
|
203
|
+
@readable_real
|
204
|
+
end
|
205
|
+
|
206
|
+
# Meaningless on Windows
|
207
|
+
#
|
208
|
+
def setgid?
|
209
|
+
@setgid
|
210
|
+
end
|
211
|
+
|
212
|
+
# Meaningless on Windows
|
213
|
+
#
|
214
|
+
def setuid?
|
215
|
+
@setuid
|
216
|
+
end
|
217
|
+
|
218
|
+
# Returns nil if statfile is a zero-length file; otherwise, returns the
|
219
|
+
# file size. Usable as a condition in tests.
|
220
|
+
#
|
221
|
+
def size?
|
222
|
+
@size > 0 ? @size : nil
|
223
|
+
end
|
224
|
+
|
225
|
+
# Meaningless on Windows.
|
226
|
+
#
|
227
|
+
def sticky?
|
228
|
+
@sticky
|
229
|
+
end
|
230
|
+
|
231
|
+
# Meaningless on Windows at the moment. This may change in the future.
|
232
|
+
#
|
233
|
+
def symlink?
|
234
|
+
@symlink
|
235
|
+
end
|
236
|
+
|
237
|
+
# Meaningless on Windows.
|
238
|
+
#
|
239
|
+
def writable?
|
240
|
+
@writable
|
241
|
+
end
|
242
|
+
|
243
|
+
# Meaningless on Windows.
|
244
|
+
#
|
245
|
+
def writable_real?
|
246
|
+
@writable_real
|
247
|
+
end
|
248
|
+
|
249
|
+
# Returns whether or not the file size is zero.
|
250
|
+
#
|
251
|
+
def zero?
|
252
|
+
@size == 0
|
253
|
+
end
|
254
|
+
|
255
|
+
## Attribute members
|
256
|
+
|
257
|
+
# Returns whether or not the file is an archive file.
|
258
|
+
#
|
259
|
+
def archive?
|
260
|
+
@archive
|
261
|
+
end
|
262
|
+
|
263
|
+
# Returns whether or not the file is compressed.
|
264
|
+
#
|
265
|
+
def compressed?
|
266
|
+
@compressed
|
267
|
+
end
|
268
|
+
|
269
|
+
# Returns whether or not the file is a directory.
|
270
|
+
#
|
271
|
+
def directory?
|
272
|
+
@directory
|
273
|
+
end
|
274
|
+
|
275
|
+
# Returns whether or not the file in encrypted.
|
276
|
+
#
|
277
|
+
def encrypted?
|
278
|
+
@encrypted
|
279
|
+
end
|
280
|
+
|
281
|
+
# Returns whether or not the file is hidden.
|
282
|
+
#
|
283
|
+
def hidden?
|
284
|
+
@hidden
|
285
|
+
end
|
286
|
+
|
287
|
+
# Returns whether or not the file is content indexed.
|
288
|
+
#
|
289
|
+
def indexed?
|
290
|
+
@indexed
|
291
|
+
end
|
292
|
+
alias :content_indexed? :indexed?
|
293
|
+
|
294
|
+
# Returns whether or not the file is 'normal'. This is only true if
|
295
|
+
# virtually all other attributes are false.
|
296
|
+
#
|
297
|
+
def normal?
|
298
|
+
@normal
|
299
|
+
end
|
300
|
+
|
301
|
+
# Returns whether or not the file is offline.
|
302
|
+
#
|
303
|
+
def offline?
|
304
|
+
@offline
|
305
|
+
end
|
306
|
+
|
307
|
+
# Returns whether or not the file is readonly.
|
308
|
+
#
|
309
|
+
def readonly?
|
310
|
+
@readonly
|
311
|
+
end
|
312
|
+
|
313
|
+
alias :read_only? :readonly?
|
314
|
+
|
315
|
+
# Returns whether or not the file is a reparse point.
|
316
|
+
#
|
317
|
+
def reparse_point?
|
318
|
+
@reparse_point
|
319
|
+
end
|
320
|
+
|
321
|
+
# Returns whether or not the file is a sparse file. In most cases a sparse
|
322
|
+
# file is an image file.
|
323
|
+
#
|
324
|
+
def sparse?
|
325
|
+
@sparse
|
326
|
+
end
|
327
|
+
|
328
|
+
# Returns whether or not the file is a system file.
|
329
|
+
#
|
330
|
+
def system?
|
331
|
+
@system
|
332
|
+
end
|
333
|
+
|
334
|
+
# Returns whether or not the file is being used for temporary storage.
|
335
|
+
#
|
336
|
+
def temporary?
|
337
|
+
@temporary
|
338
|
+
end
|
339
|
+
|
340
|
+
## Standard stat members
|
341
|
+
|
342
|
+
# Returns a Time object containing the last access time.
|
343
|
+
#
|
344
|
+
def atime
|
345
|
+
@atime
|
346
|
+
end
|
347
|
+
|
348
|
+
# Returns the file system's block size, or nil if it cannot be determined.
|
349
|
+
#
|
350
|
+
def blksize
|
351
|
+
@blksize
|
352
|
+
end
|
353
|
+
|
354
|
+
# Returns the number of blocks used by the file, where a block is defined
|
355
|
+
# as size divided by blksize, rounded up.
|
356
|
+
#
|
357
|
+
# :no-doc:
|
358
|
+
# This is a fudge. A search of the internet reveals different ways people
|
359
|
+
# have defined st_blocks on MS Windows.
|
360
|
+
#
|
361
|
+
def blocks
|
362
|
+
@blocks
|
363
|
+
end
|
364
|
+
|
365
|
+
# Returns a Time object containing the time that the file status associated
|
366
|
+
# with the file was changed.
|
367
|
+
#
|
368
|
+
def ctime
|
369
|
+
@ctime
|
370
|
+
end
|
371
|
+
|
372
|
+
# Drive letter (A-Z) of the disk containing the file. If the path is a
|
373
|
+
# UNC path then the drive number (probably -1) is returned instead.
|
374
|
+
#
|
375
|
+
def dev
|
376
|
+
if PathIsUNC(@file)
|
377
|
+
@dev
|
378
|
+
else
|
379
|
+
(@dev + ?A).chr + ':'
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
# Group ID. Always 0.
|
384
|
+
#
|
385
|
+
def gid
|
386
|
+
@gid
|
387
|
+
end
|
388
|
+
|
389
|
+
# Inode number. Meaningless on NTFS.
|
390
|
+
#
|
391
|
+
def ino
|
392
|
+
@ino
|
393
|
+
end
|
394
|
+
|
395
|
+
# Bit mask for file-mode information.
|
396
|
+
#
|
397
|
+
# :no-doc:
|
398
|
+
# This was taken from rb_win32_stat() in win32.c. I'm not entirely
|
399
|
+
# sure what the point is.
|
400
|
+
#
|
401
|
+
def mode
|
402
|
+
@mode &= ~(S_IWGRP | S_IWOTH)
|
403
|
+
end
|
404
|
+
|
405
|
+
# Returns a Time object containing the modification time.
|
406
|
+
#
|
407
|
+
def mtime
|
408
|
+
@mtime
|
409
|
+
end
|
410
|
+
|
411
|
+
# Drive number of the disk containing the file.
|
412
|
+
#
|
413
|
+
def rdev
|
414
|
+
@rdev
|
415
|
+
end
|
416
|
+
|
417
|
+
# Always 1
|
418
|
+
#
|
419
|
+
def nlink
|
420
|
+
@nlink
|
421
|
+
end
|
422
|
+
|
423
|
+
# Returns the size of the file, in bytes.
|
424
|
+
#
|
425
|
+
def size
|
426
|
+
@size
|
427
|
+
end
|
428
|
+
|
429
|
+
# User ID. Always 0.
|
430
|
+
#
|
431
|
+
def uid
|
432
|
+
@uid
|
433
|
+
end
|
434
|
+
|
435
|
+
# Returns a stringified version of a File::Stat object.
|
436
|
+
#
|
437
|
+
def inspect
|
438
|
+
members = %w/
|
439
|
+
archive? atime blksize blocks compressed? ctime dev encrypted? gid
|
440
|
+
hidden? indexed? ino mode mtime rdev nlink normal? offline? readonly?
|
441
|
+
reparse_point? size sparse? system? temporary? uid
|
442
|
+
/
|
443
|
+
str = "#<#{self.class}"
|
444
|
+
members.sort.each{ |mem|
|
445
|
+
if mem == 'mode'
|
446
|
+
str << " #{mem}=" << sprintf("0%o", send(mem.intern))
|
447
|
+
elsif mem[-1].chr == '?'
|
448
|
+
str << " #{mem.chop}=" << send(mem.intern).to_s
|
449
|
+
else
|
450
|
+
str << " #{mem}=" << send(mem.intern).to_s
|
451
|
+
end
|
452
|
+
}
|
453
|
+
str
|
454
|
+
end
|
455
|
+
|
456
|
+
# A custom pretty print method. This was necessary not only to handle
|
457
|
+
# the additional attributes, but to work around an error caused by the
|
458
|
+
# builtin method for the current File::Stat class (see pp.rb).
|
459
|
+
#
|
460
|
+
def pretty_print(q)
|
461
|
+
members = %w/
|
462
|
+
archive? atime blksize blocks compressed? ctime dev encrypted? gid
|
463
|
+
hidden? indexed? ino mode mtime rdev nlink normal? offline? readonly?
|
464
|
+
reparse_point? size sparse? system? temporary? uid
|
465
|
+
/
|
466
|
+
|
467
|
+
q.object_group(self){
|
468
|
+
q.breakable
|
469
|
+
members.each{ |mem|
|
470
|
+
q.group{
|
471
|
+
q.text("#{mem}".ljust(15) + "=> ")
|
472
|
+
if mem == 'mode'
|
473
|
+
q.text(sprintf("0%o", send(mem.intern)))
|
474
|
+
else
|
475
|
+
val = self.send(mem.intern)
|
476
|
+
if val.nil?
|
477
|
+
q.text('nil')
|
478
|
+
else
|
479
|
+
q.text(val.to_s)
|
480
|
+
end
|
481
|
+
end
|
482
|
+
}
|
483
|
+
q.comma_breakable unless mem == members.last
|
484
|
+
}
|
485
|
+
}
|
486
|
+
end
|
487
|
+
|
488
|
+
private
|
489
|
+
|
490
|
+
# Returns the file system's block size.
|
491
|
+
#
|
492
|
+
def get_blksize(file)
|
493
|
+
size = nil
|
494
|
+
|
495
|
+
sectors = [0].pack('L')
|
496
|
+
bytes = [0].pack('L')
|
497
|
+
free = [0].pack('L')
|
498
|
+
total = [0].pack('L')
|
499
|
+
|
500
|
+
# If there's a drive letter it must contain a trailing backslash.
|
501
|
+
# The dup is necessary here because, for some odd reason, the function
|
502
|
+
# appears to modify the argument passed in.
|
503
|
+
if PathStripToRoot(file.dup)
|
504
|
+
file += "\\" unless file[-1].chr == "\\"
|
505
|
+
else
|
506
|
+
file = 0 # Default to root drive
|
507
|
+
end
|
508
|
+
|
509
|
+
# Don't check for an error here. Just default to nil.
|
510
|
+
if GetDiskFreeSpace(file, sectors, bytes, free, total)
|
511
|
+
size = sectors.unpack('L').first * bytes.unpack('L').first
|
512
|
+
end
|
513
|
+
|
514
|
+
size
|
515
|
+
end
|
516
|
+
|
517
|
+
# Returns the file's type (as a numeric).
|
518
|
+
#
|
519
|
+
def get_file_type(file)
|
520
|
+
handle = CreateFile(
|
521
|
+
file,
|
522
|
+
0,
|
523
|
+
0,
|
524
|
+
0,
|
525
|
+
OPEN_EXISTING,
|
526
|
+
FILE_FLAG_BACKUP_SEMANTICS, # Need this for directories
|
527
|
+
0
|
528
|
+
)
|
529
|
+
|
530
|
+
if handle == INVALID_HANDLE_VALUE
|
531
|
+
raise ArgumentError, get_last_error
|
532
|
+
end
|
533
|
+
|
534
|
+
file_type = GetFileType(handle)
|
535
|
+
error = GetLastError()
|
536
|
+
|
537
|
+
CloseHandle(handle)
|
538
|
+
|
539
|
+
if error == 0
|
540
|
+
if file_type == FILE_TYPE_DISK || file_type == FILE_TYPE_UNKNOWN
|
541
|
+
@blockdev = true
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
file_type
|
546
|
+
end
|
547
|
+
|
548
|
+
# Verifies that a value is either true or false
|
549
|
+
def check_bool(val)
|
550
|
+
raise TypeError unless val == true || val == false
|
551
|
+
end
|
552
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
This is a test
|
@@ -0,0 +1 @@
|
|
1
|
+
This is a test
|
@@ -0,0 +1,312 @@
|
|
1
|
+
#####################################################################
|
2
|
+
# tc_file_stat.rb
|
3
|
+
#
|
4
|
+
# Test case for stat related methods of win32-file.
|
5
|
+
#####################################################################
|
6
|
+
base = File.basename(Dir.pwd)
|
7
|
+
|
8
|
+
if base == 'test' || base =~ /win32-file-stat/
|
9
|
+
Dir.chdir('..') if base == 'test'
|
10
|
+
$LOAD_PATH.unshift(Dir.pwd + '/lib')
|
11
|
+
Dir.chdir('test') rescue nil
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'test/unit'
|
15
|
+
require 'win32/file/stat'
|
16
|
+
|
17
|
+
class TC_Win32_File_Stat < Test::Unit::TestCase
|
18
|
+
include Windows::File
|
19
|
+
def setup
|
20
|
+
@file = 'sometestfile.txt'
|
21
|
+
@exe = 'sometestfile.exe'
|
22
|
+
@dir = Dir.pwd
|
23
|
+
@stat = File::Stat.new(@file)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_version
|
27
|
+
assert_equal('1.2.3', File::Stat::VERSION)
|
28
|
+
end
|
29
|
+
|
30
|
+
# One or more tests will fail if the archive attribute on @file is not set.
|
31
|
+
def test_archive
|
32
|
+
assert_respond_to(@stat, :archive?)
|
33
|
+
assert_nothing_raised{ @stat.archive? }
|
34
|
+
assert(@stat.archive?)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_atime
|
38
|
+
assert_respond_to(@stat, :atime)
|
39
|
+
assert_kind_of(Time, @stat.atime)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_blksize
|
43
|
+
assert_respond_to(@stat, :blksize)
|
44
|
+
assert_equal(4096, @stat.blksize)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_blockdev
|
48
|
+
assert_respond_to(@stat, :blockdev?)
|
49
|
+
assert_equal(true, @stat.blockdev?)
|
50
|
+
assert_equal(false, File::Stat.new('NUL').blockdev?)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_blocks
|
54
|
+
assert_respond_to(@stat, :blocks)
|
55
|
+
assert_equal(1, @stat.blocks)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_chardev
|
59
|
+
assert_respond_to(@stat, :chardev?)
|
60
|
+
assert_nothing_raised{ File::Stat.new("NUL").chardev? }
|
61
|
+
assert_equal(true, File::Stat.new("NUL").chardev?)
|
62
|
+
assert_equal(false, File::Stat.new("C:\\").chardev?)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_comparison
|
66
|
+
assert_respond_to(@stat, :<=>)
|
67
|
+
assert_nothing_raised{ @stat <=> File::Stat.new(@exe) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_compressed
|
71
|
+
assert_respond_to(@stat, :compressed?)
|
72
|
+
assert_nothing_raised{ @stat.compressed? }
|
73
|
+
assert_equal(false, @stat.compressed?)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_ctime
|
77
|
+
assert_respond_to(@stat, :ctime)
|
78
|
+
assert_kind_of(Time, @stat.ctime)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Assumes you've installed on C: drive.
|
82
|
+
def test_dev
|
83
|
+
assert_respond_to(@stat, :dev)
|
84
|
+
assert_equal('C:', @stat.dev)
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_dev_major
|
88
|
+
assert_respond_to(@stat, :dev_major)
|
89
|
+
assert_nil(@stat.dev_major)
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_dev_minor
|
93
|
+
assert_respond_to(@stat, :dev_minor)
|
94
|
+
assert_nil(@stat.dev_minor)
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_directory
|
98
|
+
assert_respond_to(@stat, :directory?)
|
99
|
+
assert_equal(false, @stat.directory?)
|
100
|
+
assert_equal(true, File::Stat.new("C:\\").directory?)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_executable
|
104
|
+
assert_respond_to(@stat, :executable?)
|
105
|
+
assert_equal(false, @stat.executable?)
|
106
|
+
assert_equal(true, File::Stat.new(@exe).executable?)
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_executable_real
|
110
|
+
assert_respond_to(@stat, :executable_real?)
|
111
|
+
assert_equal(false, @stat.executable_real?)
|
112
|
+
assert_equal(true, File::Stat.new(@exe).executable_real?)
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_file
|
116
|
+
assert_respond_to(@stat, :file?)
|
117
|
+
assert_equal(true, @stat.file?)
|
118
|
+
assert_equal(true, File::Stat.new(@exe).file?)
|
119
|
+
assert_equal(true, File::Stat.new(Dir.pwd).file?)
|
120
|
+
assert_equal(false, File::Stat.new('NUL').file?)
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_ftype
|
124
|
+
assert_respond_to(@stat, :ftype)
|
125
|
+
assert_equal('file', @stat.ftype)
|
126
|
+
assert_equal('characterSpecial', File::Stat.new('NUL').ftype)
|
127
|
+
assert_equal('directory', File::Stat.new(Dir.pwd).ftype)
|
128
|
+
end
|
129
|
+
|
130
|
+
def encrypted
|
131
|
+
assert_respond_to(@stat, :encrypted?)
|
132
|
+
assert_nothing_raised{ @stat.encrypted? }
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_gid
|
136
|
+
assert_respond_to(@stat, :gid)
|
137
|
+
assert_equal(0, @stat.gid)
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_grpowned
|
141
|
+
assert_respond_to(@stat, :grpowned?)
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_hidden
|
145
|
+
assert_respond_to(@stat, :hidden?)
|
146
|
+
assert_nothing_raised{ @stat.hidden? }
|
147
|
+
assert_equal(false, @stat.hidden?)
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_indexed
|
151
|
+
assert_respond_to(@stat, :indexed?)
|
152
|
+
assert_respond_to(@stat, :content_indexed?) # alias
|
153
|
+
assert_nothing_raised{ @stat.indexed? }
|
154
|
+
assert(@stat.indexed?)
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_ino
|
158
|
+
assert_respond_to(@stat, :ino)
|
159
|
+
assert_equal(0, @stat.ino)
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_inspect
|
163
|
+
assert_respond_to(@stat, :inspect)
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_mode
|
167
|
+
assert_respond_to(@stat, :mode)
|
168
|
+
assert_equal(33188, File::Stat.new(@file).mode)
|
169
|
+
assert_equal(33261, File::Stat.new(@exe).mode)
|
170
|
+
assert_equal(16877, File::Stat.new(@dir).mode)
|
171
|
+
|
172
|
+
SetFileAttributes(@file, 1) # Set to readonly.
|
173
|
+
assert_equal(33060, File::Stat.new(@file).mode)
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_mtime
|
177
|
+
assert_respond_to(@stat, :mtime)
|
178
|
+
assert_kind_of(Time, @stat.mtime)
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_nlink
|
182
|
+
assert_respond_to(@stat, :nlink)
|
183
|
+
assert_equal(1, @stat.nlink)
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_normal
|
187
|
+
assert_respond_to(@stat, :normal?)
|
188
|
+
assert_nothing_raised{ @stat.normal? }
|
189
|
+
assert(@stat.normal?)
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_offline
|
193
|
+
assert_respond_to(@stat, :offline?)
|
194
|
+
assert_nothing_raised{ @stat.offline? }
|
195
|
+
assert_equal(false, @stat.offline?)
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_pipe
|
199
|
+
assert_respond_to(@stat, :pipe?)
|
200
|
+
assert_equal(false, @stat.pipe?)
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_readable
|
204
|
+
assert_respond_to(@stat, :readable?)
|
205
|
+
assert_equal(true, @stat.readable?)
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_readable_real
|
209
|
+
assert_respond_to(@stat, :readable_real?)
|
210
|
+
assert_equal(true, @stat.readable_real?)
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_readonly
|
214
|
+
assert_respond_to(@stat, :readonly?)
|
215
|
+
assert_nothing_raised{ @stat.readonly? }
|
216
|
+
assert_equal(false, @stat.readonly?)
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_reparse_point
|
220
|
+
assert_respond_to(@stat, :reparse_point?)
|
221
|
+
assert_nothing_raised{ @stat.reparse_point? }
|
222
|
+
assert_equal(false, @stat.reparse_point?)
|
223
|
+
end
|
224
|
+
|
225
|
+
# Assumes you've installed on C: drive.
|
226
|
+
def test_rdev
|
227
|
+
msg = "ignore failure if Ruby is not installed on C: drive"
|
228
|
+
assert_respond_to(@stat, :rdev)
|
229
|
+
assert_equal(2, @stat.rdev, msg)
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_setgid
|
233
|
+
assert_respond_to(@stat, :setgid?)
|
234
|
+
assert_equal(false, @stat.setgid?)
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_setuid
|
238
|
+
assert_respond_to(@stat, :setuid?)
|
239
|
+
assert_equal(false, @stat.setuid?)
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_size
|
243
|
+
assert_respond_to(@stat, :size)
|
244
|
+
assert_equal(16, @stat.size)
|
245
|
+
end
|
246
|
+
|
247
|
+
def test_size_bool
|
248
|
+
assert_respond_to(@stat, :size?)
|
249
|
+
assert_equal(16, @stat.size?)
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_socket
|
253
|
+
assert_respond_to(@stat, :socket?)
|
254
|
+
assert_equal(false, @stat.socket?)
|
255
|
+
end
|
256
|
+
|
257
|
+
def test_sparse
|
258
|
+
assert_respond_to(@stat, :sparse?)
|
259
|
+
assert_nothing_raised{ @stat.sparse? }
|
260
|
+
assert_equal(false, @stat.sparse?)
|
261
|
+
end
|
262
|
+
|
263
|
+
def test_sticky
|
264
|
+
assert_respond_to(@stat, :sticky?)
|
265
|
+
assert_equal(false, @stat.sticky?)
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_symlink
|
269
|
+
assert_respond_to(@stat, :symlink?)
|
270
|
+
assert_equal(false, @stat.symlink?)
|
271
|
+
end
|
272
|
+
|
273
|
+
def test_system
|
274
|
+
assert_respond_to(@stat, :system?)
|
275
|
+
assert_nothing_raised{ @stat.system? }
|
276
|
+
assert_equal(false, @stat.system?)
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_temporary
|
280
|
+
assert_respond_to(@stat, :temporary?)
|
281
|
+
assert_nothing_raised{ @stat.temporary? }
|
282
|
+
assert_equal(false, @stat.temporary?)
|
283
|
+
end
|
284
|
+
|
285
|
+
def test_uid
|
286
|
+
assert_respond_to(@stat, :uid)
|
287
|
+
assert_equal(0, @stat.uid)
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_writable
|
291
|
+
assert_respond_to(@stat, :writable?)
|
292
|
+
assert_equal(true, @stat.writable?)
|
293
|
+
end
|
294
|
+
|
295
|
+
def test_writable_real
|
296
|
+
assert_respond_to(@stat, :writable_real?)
|
297
|
+
assert_equal(true, @stat.writable_real?)
|
298
|
+
end
|
299
|
+
|
300
|
+
def test_zero
|
301
|
+
assert_respond_to(@stat, :zero?)
|
302
|
+
assert_equal(false, @stat.zero?)
|
303
|
+
end
|
304
|
+
|
305
|
+
def teardown
|
306
|
+
SetFileAttributes(@file, 8) # Set file back to normal
|
307
|
+
@file = nil
|
308
|
+
@exe = nil
|
309
|
+
@dir = nil
|
310
|
+
@stat = nil
|
311
|
+
end
|
312
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
spec = Gem::Specification.new do |gem|
|
4
|
+
gem.name = "win32-file-stat"
|
5
|
+
gem.version = "1.2.3"
|
6
|
+
gem.author = "Daniel J. Berger"
|
7
|
+
gem.email = "djberg96@gmail.com"
|
8
|
+
gem.homepage = "http://www.rubyforge.org/projects/win32utils"
|
9
|
+
gem.platform = Gem::Platform::RUBY
|
10
|
+
gem.summary = "A File::Stat class tailored to MS Windows"
|
11
|
+
gem.description = "A File::Stat class tailored to MS Windows"
|
12
|
+
gem.test_file = "test/tc_file_stat.rb"
|
13
|
+
gem.has_rdoc = true
|
14
|
+
gem.files = Dir['lib/win32/file/*.rb'] + Dir['[A-Z]*'] + Dir['test/*']
|
15
|
+
gem.files.reject! { |fn| fn.include? "CVS" }
|
16
|
+
gem.require_path = "lib"
|
17
|
+
gem.extra_rdoc_files = ["README", "CHANGES"]
|
18
|
+
gem.add_dependency("windows-pr", ">= 0.4.0")
|
19
|
+
end
|
20
|
+
|
21
|
+
if $0 == __FILE__
|
22
|
+
Gem.manage_gems
|
23
|
+
Gem::Builder.new(spec).build
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: win32-file-stat
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.2.3
|
7
|
+
date: 2006-11-04 00:00:00 -07:00
|
8
|
+
summary: A File::Stat class tailored to MS Windows
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: djberg96@gmail.com
|
12
|
+
homepage: http://www.rubyforge.org/projects/win32utils
|
13
|
+
rubyforge_project:
|
14
|
+
description: A File::Stat class tailored to MS Windows
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Daniel J. Berger
|
31
|
+
files:
|
32
|
+
- lib/win32/file/stat.rb
|
33
|
+
- CHANGES
|
34
|
+
- install.rb
|
35
|
+
- lib
|
36
|
+
- MANIFEST
|
37
|
+
- README
|
38
|
+
- test
|
39
|
+
- win32-file-stat.gemspec
|
40
|
+
- test/sometestfile.exe
|
41
|
+
- test/sometestfile.txt
|
42
|
+
- test/tc_file_stat.rb
|
43
|
+
test_files:
|
44
|
+
- test/tc_file_stat.rb
|
45
|
+
rdoc_options: []
|
46
|
+
|
47
|
+
extra_rdoc_files:
|
48
|
+
- README
|
49
|
+
- CHANGES
|
50
|
+
executables: []
|
51
|
+
|
52
|
+
extensions: []
|
53
|
+
|
54
|
+
requirements: []
|
55
|
+
|
56
|
+
dependencies:
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: windows-pr
|
59
|
+
version_requirement:
|
60
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 0.4.0
|
65
|
+
version:
|