win32-file-stat 1.3.6 → 1.4.0
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 +7 -0
- data/CHANGES +126 -103
- data/MANIFEST +10 -7
- data/README +85 -84
- data/Rakefile +31 -26
- data/lib/win32/file/stat.rb +934 -755
- data/lib/win32/file/windows/constants.rb +92 -0
- data/lib/win32/file/windows/functions.rb +57 -0
- data/lib/win32/file/windows/helper.rb +13 -0
- data/lib/win32/file/windows/structs.rb +165 -0
- data/test/test_file_stat.rb +647 -354
- data/win32-file-stat.gemspec +28 -26
- metadata +63 -26
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module Windows
|
4
|
+
module Stat
|
5
|
+
module Constants
|
6
|
+
private
|
7
|
+
|
8
|
+
MAX_PATH = 260
|
9
|
+
MAXDWORD = 0xFFFFFFFF
|
10
|
+
|
11
|
+
# Normally just FFI::Pointer.new(-1).address, but we need JRuby to work, too.
|
12
|
+
INVALID_HANDLE_VALUE = (1<<FFI::Platform::ADDRESS_SIZE)-1
|
13
|
+
|
14
|
+
ERROR_FILE_NOT_FOUND = 2
|
15
|
+
ERROR_NO_MORE_FILES = 18
|
16
|
+
ERROR_INSUFFICIENT_BUFFER = 122
|
17
|
+
|
18
|
+
FILE_TYPE_UNKNOWN = 0x0000
|
19
|
+
FILE_TYPE_DISK = 0x0001
|
20
|
+
FILE_TYPE_CHAR = 0x0002
|
21
|
+
FILE_TYPE_PIPE = 0x0003
|
22
|
+
FILE_TYPE_REMOTE = 0x8000
|
23
|
+
|
24
|
+
FILE_ATTRIBUTE_READONLY = 0x00000001
|
25
|
+
FILE_ATTRIBUTE_HIDDEN = 0x00000002
|
26
|
+
FILE_ATTRIBUTE_SYSTEM = 0x00000004
|
27
|
+
FILE_ATTRIBUTE_DIRECTORY = 0x00000010
|
28
|
+
FILE_ATTRIBUTE_ARCHIVE = 0x00000020
|
29
|
+
FILE_ATTRIBUTE_ENCRYPTED = 0x00000040
|
30
|
+
FILE_ATTRIBUTE_NORMAL = 0x00000080
|
31
|
+
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
|
32
|
+
FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200
|
33
|
+
FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
|
34
|
+
FILE_ATTRIBUTE_COMPRESSED = 0x00000800
|
35
|
+
FILE_ATTRIBUTE_OFFLINE = 0x00001000
|
36
|
+
|
37
|
+
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000
|
38
|
+
|
39
|
+
DRIVE_REMOVABLE = 2
|
40
|
+
DRIVE_CDROM = 5
|
41
|
+
DRIVE_RAMDISK = 6
|
42
|
+
|
43
|
+
NO_ERROR = 0
|
44
|
+
|
45
|
+
OPEN_EXISTING = 3
|
46
|
+
GENERIC_READ = 0x80000000
|
47
|
+
GENERIC_WRITE = 0x40000000
|
48
|
+
GENERIC_EXECUTE = 0x20000000
|
49
|
+
|
50
|
+
FILE_SHARE_READ = 1
|
51
|
+
|
52
|
+
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
|
53
|
+
FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
|
54
|
+
IO_REPARSE_TAG_SYMLINK = 0xA000000C
|
55
|
+
|
56
|
+
OWNER_SECURITY_INFORMATION = 1
|
57
|
+
GROUP_SECURITY_INFORMATION = 2
|
58
|
+
DACL_SECURITY_INFORMATION = 4
|
59
|
+
|
60
|
+
SYNCHRONIZE = 0x00100000
|
61
|
+
STANDARD_RIGHTS_REQUIRED = 0x000F0000
|
62
|
+
|
63
|
+
FILE_READ_DATA = 0x0001
|
64
|
+
FILE_WRITE_DATA = 0x0002
|
65
|
+
FILE_APPEND_DATA = 0x0004
|
66
|
+
FILE_READ_EA = 0x0008
|
67
|
+
FILE_WRITE_EA = 0x0008
|
68
|
+
FILE_EXECUTE = 0x0020
|
69
|
+
FILE_READ_ATTRIBUTES = 0x0080
|
70
|
+
FILE_WRITE_ATTRIBUTES = 0x0100
|
71
|
+
|
72
|
+
READ_CONTROL = 0x00020000
|
73
|
+
STANDARD_RIGHTS_READ = READ_CONTROL
|
74
|
+
STANDARD_RIGHTS_WRITE = READ_CONTROL
|
75
|
+
STANDARD_RIGHTS_EXECUTE = READ_CONTROL
|
76
|
+
|
77
|
+
FILE_GENERIC_READ = (STANDARD_RIGHTS_READ|FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA|SYNCHRONIZE)
|
78
|
+
FILE_GENERIC_WRITE = (STANDARD_RIGHTS_WRITE|FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|FILE_APPEND_DATA|SYNCHRONIZE)
|
79
|
+
FILE_GENERIC_EXECUTE = (STANDARD_RIGHTS_EXECUTE|FILE_READ_ATTRIBUTES|FILE_EXECUTE|SYNCHRONIZE)
|
80
|
+
FILE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x1FF)
|
81
|
+
|
82
|
+
TOKEN_DUPLICATE = 0x0002
|
83
|
+
TOKEN_IMPERSONATE = 0x0004
|
84
|
+
TOKEN_QUERY = 0x0008
|
85
|
+
|
86
|
+
SecurityImpersonation = 2
|
87
|
+
|
88
|
+
TokenUser = 1
|
89
|
+
TokenGroups = 2
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module Windows
|
4
|
+
module Stat
|
5
|
+
module Functions
|
6
|
+
extend FFI::Library
|
7
|
+
|
8
|
+
# Wrapper method for attach_pfunc + private
|
9
|
+
def self.attach_pfunc(*args)
|
10
|
+
attach_function(*args)
|
11
|
+
private args[0]
|
12
|
+
end
|
13
|
+
|
14
|
+
typedef :ulong, :dword
|
15
|
+
typedef :uintptr_t, :handle
|
16
|
+
typedef :pointer, :ptr
|
17
|
+
typedef :buffer_in, :buf_in
|
18
|
+
typedef :string, :str
|
19
|
+
|
20
|
+
ffi_convention :stdcall
|
21
|
+
|
22
|
+
ffi_lib :kernel32
|
23
|
+
|
24
|
+
attach_pfunc :CloseHandle, [:handle], :bool
|
25
|
+
attach_pfunc :CreateFile, :CreateFileW, [:buf_in, :dword, :dword, :ptr, :dword, :dword, :handle], :handle
|
26
|
+
attach_pfunc :FindFirstFile, :FindFirstFileW, [:buf_in, :ptr], :handle
|
27
|
+
attach_pfunc :FindClose, [:handle], :bool
|
28
|
+
attach_pfunc :GetCurrentProcess, [], :handle
|
29
|
+
attach_pfunc :GetDiskFreeSpace, :GetDiskFreeSpaceW, [:buf_in, :ptr, :ptr, :ptr, :ptr], :bool
|
30
|
+
attach_pfunc :GetDriveType, :GetDriveTypeW, [:buf_in], :uint
|
31
|
+
attach_pfunc :GetFileInformationByHandle, [:handle, :ptr], :bool
|
32
|
+
attach_pfunc :GetFileType, [:handle], :dword
|
33
|
+
attach_pfunc :OpenProcessToken, [:handle, :dword, :ptr], :bool
|
34
|
+
|
35
|
+
ffi_lib :shlwapi
|
36
|
+
|
37
|
+
attach_pfunc :PathGetDriveNumber, :PathGetDriveNumberW, [:buf_in], :int
|
38
|
+
attach_pfunc :PathIsUNC, :PathIsUNCW, [:buf_in], :bool
|
39
|
+
attach_pfunc :PathStripToRoot, :PathStripToRootW, [:ptr], :bool
|
40
|
+
|
41
|
+
ffi_lib :advapi32
|
42
|
+
|
43
|
+
attach_pfunc :ConvertSidToStringSid, :ConvertSidToStringSidA, [:ptr, :ptr], :bool
|
44
|
+
attach_pfunc :ConvertStringSidToSid, :ConvertStringSidToSidA, [:ptr, :ptr], :bool
|
45
|
+
attach_pfunc :GetFileSecurity, :GetFileSecurityW, [:buf_in, :int, :ptr, :dword, :ptr], :bool
|
46
|
+
attach_pfunc :GetSecurityDescriptorOwner, [:ptr, :ptr, :ptr], :bool
|
47
|
+
attach_pfunc :GetSecurityDescriptorGroup, [:ptr, :ptr, :ptr], :bool
|
48
|
+
attach_pfunc :GetTokenInformation, [:handle, :int, :ptr, :dword, :ptr], :bool
|
49
|
+
attach_pfunc :DuplicateToken, [:handle, :dword, :ptr], :bool
|
50
|
+
attach_pfunc :MapGenericMask, [:ptr, :ptr], :void
|
51
|
+
attach_pfunc :AccessCheck, [:ptr, :handle, :dword, :ptr, :ptr, :ptr, :ptr, :ptr], :bool
|
52
|
+
attach_pfunc :BuildTrusteeWithSid, :BuildTrusteeWithSidW, [:ptr, :ptr], :void
|
53
|
+
attach_pfunc :GetSecurityDescriptorDacl, [:ptr, :ptr, :ptr, :ptr], :bool
|
54
|
+
attach_pfunc :GetEffectiveRightsFromAcl, :GetEffectiveRightsFromAclW, [:ptr, :ptr, :ptr], :dword
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class String
|
2
|
+
# Convenience method for converting strings to UTF-16LE for wide character
|
3
|
+
# functions that require it.
|
4
|
+
def wincode
|
5
|
+
(self.tr(File::SEPARATOR, File::ALT_SEPARATOR) + 0.chr).encode('UTF-16LE')
|
6
|
+
end
|
7
|
+
|
8
|
+
# Read a wide character string up until the first double null, and delete
|
9
|
+
# any remaining null characters.
|
10
|
+
def read_wide
|
11
|
+
self[/^.*?(?=\x00{2})/].delete(0.chr)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'constants')
|
2
|
+
|
3
|
+
require 'ffi'
|
4
|
+
|
5
|
+
module Windows
|
6
|
+
module Stat
|
7
|
+
module Structs
|
8
|
+
extend FFI::Library
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
class LowHigh < FFI::Struct
|
13
|
+
layout(:LowPart, :ulong, :HighPart, :ulong)
|
14
|
+
end
|
15
|
+
|
16
|
+
class ULARGE_INTEGER < FFI::Union
|
17
|
+
layout(:u, LowHigh, :QuadPart, :ulong_long)
|
18
|
+
end
|
19
|
+
|
20
|
+
class FILETIME < FFI::Struct
|
21
|
+
layout(:dwLowDateTime, :ulong, :dwHighDateTime, :ulong)
|
22
|
+
end
|
23
|
+
|
24
|
+
class BY_HANDLE_FILE_INFORMATION < FFI::Struct
|
25
|
+
include Windows::Stat::Constants
|
26
|
+
|
27
|
+
layout(
|
28
|
+
:dwFileAttributes, :ulong,
|
29
|
+
:ftCreationTime, FILETIME,
|
30
|
+
:ftLastAccessTime, FILETIME,
|
31
|
+
:ftLastWriteTime, FILETIME,
|
32
|
+
:dwVolumeSerialNumber, :ulong,
|
33
|
+
:nFileSizeHigh, :ulong,
|
34
|
+
:nFileSizeLow, :ulong,
|
35
|
+
:nNumberOfLinks, :ulong,
|
36
|
+
:nFileIndexHigh, :ulong,
|
37
|
+
:nFileIndexLow, :ulong
|
38
|
+
)
|
39
|
+
|
40
|
+
# Return the atime as a number
|
41
|
+
def atime
|
42
|
+
date = ULARGE_INTEGER.new
|
43
|
+
date[:u][:LowPart] = self[:ftLastAccessTime][:dwLowDateTime]
|
44
|
+
date[:u][:HighPart] = self[:ftLastAccessTime][:dwHighDateTime]
|
45
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return the ctime as a number
|
49
|
+
def ctime
|
50
|
+
date = ULARGE_INTEGER.new
|
51
|
+
date[:u][:LowPart] = self[:ftCreationTime][:dwLowDateTime]
|
52
|
+
date[:u][:HighPart] = self[:ftCreationTime][:dwHighDateTime]
|
53
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return the mtime as a number
|
57
|
+
def mtime
|
58
|
+
date = ULARGE_INTEGER.new
|
59
|
+
date[:u][:LowPart] = self[:ftLastWriteTime][:dwLowDateTime]
|
60
|
+
date[:u][:HighPart] = self[:ftLastWriteTime][:dwHighDateTime]
|
61
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
62
|
+
end
|
63
|
+
|
64
|
+
# Return the size as a single number
|
65
|
+
def size
|
66
|
+
(self[:nFileSizeHigh] * (MAXDWORD + 1)) + self[:nFileSizeLow]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class WIN32_FIND_DATA < FFI::Struct
|
71
|
+
include Windows::Stat::Constants
|
72
|
+
|
73
|
+
layout(
|
74
|
+
:dwFileAttributes, :ulong,
|
75
|
+
:ftCreationTime, FILETIME,
|
76
|
+
:ftLastAccessTime, FILETIME,
|
77
|
+
:ftLastWriteTime, FILETIME,
|
78
|
+
:nFileSizeHigh, :ulong,
|
79
|
+
:nFileSizeLow, :ulong,
|
80
|
+
:dwReserved0, :ulong,
|
81
|
+
:dwReserved1, :ulong,
|
82
|
+
:cFileName, [:uint8, MAX_PATH*2],
|
83
|
+
:cAlternateFileName, [:uint8, 28]
|
84
|
+
)
|
85
|
+
|
86
|
+
# Return the atime as a number
|
87
|
+
def atime
|
88
|
+
date = ULARGE_INTEGER.new
|
89
|
+
date[:u][:LowPart] = self[:ftLastAccessTime][:dwLowDateTime]
|
90
|
+
date[:u][:HighPart] = self[:ftLastAccessTime][:dwHighDateTime]
|
91
|
+
return 0 if date[:QuadPart]==0
|
92
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
93
|
+
end
|
94
|
+
|
95
|
+
# Return the ctime as a number
|
96
|
+
def ctime
|
97
|
+
date = ULARGE_INTEGER.new
|
98
|
+
date[:u][:LowPart] = self[:ftCreationTime][:dwLowDateTime]
|
99
|
+
date[:u][:HighPart] = self[:ftCreationTime][:dwHighDateTime]
|
100
|
+
return 0 if date[:QuadPart]==0
|
101
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
102
|
+
end
|
103
|
+
|
104
|
+
# Return the mtime as a number
|
105
|
+
def mtime
|
106
|
+
date = ULARGE_INTEGER.new
|
107
|
+
date[:u][:LowPart] = self[:ftLastWriteTime][:dwLowDateTime]
|
108
|
+
date[:u][:HighPart] = self[:ftLastWriteTime][:dwHighDateTime]
|
109
|
+
return 0 if date[:QuadPart]==0
|
110
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
111
|
+
end
|
112
|
+
|
113
|
+
# Return the size as a single number
|
114
|
+
def size
|
115
|
+
(self[:nFileSizeHigh] * (MAXDWORD + 1)) + self[:nFileSizeLow]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class SID_AND_ATTRIBUTES < FFI::Struct
|
120
|
+
layout(:Sid, :pointer, :Attributes, :ulong)
|
121
|
+
end
|
122
|
+
|
123
|
+
class TOKEN_GROUP < FFI::Struct
|
124
|
+
layout(
|
125
|
+
:GroupCount, :ulong,
|
126
|
+
:Groups, [SID_AND_ATTRIBUTES, 128]
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
class GENERIC_MAPPING < FFI::Struct
|
131
|
+
layout(
|
132
|
+
:GenericRead, :ulong,
|
133
|
+
:GenericWrite, :ulong,
|
134
|
+
:GenericExecute, :ulong,
|
135
|
+
:GenericAll, :ulong
|
136
|
+
)
|
137
|
+
end
|
138
|
+
|
139
|
+
class LUID_AND_ATTRIBUTES < FFI::Struct
|
140
|
+
layout(
|
141
|
+
:Luid, LowHigh,
|
142
|
+
:Attributes, :ulong
|
143
|
+
)
|
144
|
+
end
|
145
|
+
|
146
|
+
class PRIVILEGE_SET < FFI::Struct
|
147
|
+
layout(
|
148
|
+
:PrivilegeCount, :ulong,
|
149
|
+
:Control, :ulong,
|
150
|
+
:Privilege, [LUID_AND_ATTRIBUTES, 1]
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
class TRUSTEE < FFI::Struct
|
155
|
+
layout(
|
156
|
+
:pMultipleTrustee, :pointer,
|
157
|
+
:MultipleTrusteeOperation, :ulong,
|
158
|
+
:TrusteeForm, :ulong,
|
159
|
+
:TrusteeType, :ulong,
|
160
|
+
:ptstrName, :pointer
|
161
|
+
)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/test/test_file_stat.rb
CHANGED
@@ -1,354 +1,647 @@
|
|
1
|
-
#####################################################################
|
2
|
-
# test_file_stat.rb
|
3
|
-
#
|
4
|
-
# Test case for stat related methods of win32-file. You should use
|
5
|
-
# the 'rake test' task to run these tests.
|
6
|
-
#####################################################################
|
7
|
-
require '
|
8
|
-
|
9
|
-
|
10
|
-
require '
|
11
|
-
require 'win32/
|
12
|
-
|
13
|
-
class TC_Win32_File_Stat < Test::Unit::TestCase
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
end
|
1
|
+
#####################################################################
|
2
|
+
# test_file_stat.rb
|
3
|
+
#
|
4
|
+
# Test case for stat related methods of win32-file. You should use
|
5
|
+
# the 'rake test' task to run these tests.
|
6
|
+
#####################################################################
|
7
|
+
require 'etc'
|
8
|
+
require 'ffi'
|
9
|
+
require 'test-unit'
|
10
|
+
require 'win32/file/stat'
|
11
|
+
require 'win32/security'
|
12
|
+
|
13
|
+
class TC_Win32_File_Stat < Test::Unit::TestCase
|
14
|
+
extend FFI::Library
|
15
|
+
ffi_lib :kernel32
|
16
|
+
|
17
|
+
attach_function :GetDriveType, :GetDriveTypeA, [:string], :ulong
|
18
|
+
attach_function :GetFileAttributes, :GetFileAttributesA, [:string], :ulong
|
19
|
+
attach_function :SetFileAttributes, :SetFileAttributesA, [:string, :ulong], :bool
|
20
|
+
|
21
|
+
DRIVE_REMOVABLE = 2
|
22
|
+
DRIVE_CDROM = 5
|
23
|
+
DRIVE_RAMDISK = 6
|
24
|
+
|
25
|
+
def self.startup
|
26
|
+
@@block_dev = nil
|
27
|
+
|
28
|
+
'A'.upto('Z'){ |volume|
|
29
|
+
volume += ":\\"
|
30
|
+
case GetDriveType(volume)
|
31
|
+
when DRIVE_REMOVABLE, DRIVE_CDROM, DRIVE_RAMDISK
|
32
|
+
@@block_dev = volume
|
33
|
+
break
|
34
|
+
end
|
35
|
+
}
|
36
|
+
|
37
|
+
@@txt_file = File.join(File.expand_path(File.dirname(__FILE__)), 'test_file.txt')
|
38
|
+
@@exe_file = File.join(File.expand_path(File.dirname(__FILE__)), 'test_file.exe')
|
39
|
+
@@sys_file = 'C:/pagefile.sys'
|
40
|
+
@@elevated = Win32::Security.elevated_security?
|
41
|
+
@@jruby = RUBY_PLATFORM == 'java'
|
42
|
+
|
43
|
+
File.open(@@txt_file, "w"){ |fh| fh.print "This is a test\nHello" }
|
44
|
+
File.open(@@exe_file, "wb"){ |fh| fh.print "This is a test" }
|
45
|
+
end
|
46
|
+
|
47
|
+
def setup
|
48
|
+
@dir = Dir.pwd
|
49
|
+
@stat = File::Stat.new(@@txt_file)
|
50
|
+
@temp = 'win32_file_stat.tmp'
|
51
|
+
File.open(@temp, 'w'){}
|
52
|
+
@attr = GetFileAttributes(@@txt_file)
|
53
|
+
end
|
54
|
+
|
55
|
+
test "version is set to expected value" do
|
56
|
+
assert_equal('1.4.0', File::Stat::WIN32_FILE_STAT_VERSION)
|
57
|
+
end
|
58
|
+
|
59
|
+
test "constructor does not modify argument" do
|
60
|
+
expected = File.join(File.expand_path(File.dirname(__FILE__)), 'test_file.txt')
|
61
|
+
File::Stat.new(@@txt_file)
|
62
|
+
assert_equal(expected, @@txt_file)
|
63
|
+
end
|
64
|
+
|
65
|
+
test "archive? method basic functionality" do
|
66
|
+
assert_respond_to(@stat, :archive?)
|
67
|
+
assert_nothing_raised{ @stat.archive? }
|
68
|
+
end
|
69
|
+
|
70
|
+
test "archive? method returns a boolean value" do
|
71
|
+
assert_boolean(@stat.archive?)
|
72
|
+
end
|
73
|
+
|
74
|
+
test "atime method basic functionality" do
|
75
|
+
assert_respond_to(@stat, :atime)
|
76
|
+
assert_nothing_raised{ @stat.atime }
|
77
|
+
end
|
78
|
+
|
79
|
+
test "atime method returns expected value" do
|
80
|
+
assert_kind_of(Time, @stat.atime)
|
81
|
+
assert_true(@stat.atime.to_i > 0)
|
82
|
+
end
|
83
|
+
|
84
|
+
test "mtime method basic functionality" do
|
85
|
+
assert_respond_to(@stat, :mtime)
|
86
|
+
assert_nothing_raised{ @stat.mtime }
|
87
|
+
end
|
88
|
+
|
89
|
+
test "mtime method returns expected value" do
|
90
|
+
assert_kind_of(Time, @stat.mtime)
|
91
|
+
assert_true(@stat.mtime.to_i > 0)
|
92
|
+
end
|
93
|
+
|
94
|
+
test "ctime method basic functionality" do
|
95
|
+
assert_respond_to(@stat, :ctime)
|
96
|
+
assert_nothing_raised{ @stat.ctime }
|
97
|
+
end
|
98
|
+
|
99
|
+
test "ctime method returns expected value" do
|
100
|
+
assert_kind_of(Time, @stat.ctime)
|
101
|
+
assert_true(@stat.ctime.to_i > 0)
|
102
|
+
end
|
103
|
+
|
104
|
+
test "blksize basic functionality" do
|
105
|
+
assert_respond_to(@stat, :blksize)
|
106
|
+
assert_kind_of(Fixnum, @stat.blksize)
|
107
|
+
end
|
108
|
+
|
109
|
+
test "blksize returns expected value" do
|
110
|
+
assert_equal(4096, @stat.blksize)
|
111
|
+
assert_equal(4096, File::Stat.new("C:\\").blksize)
|
112
|
+
end
|
113
|
+
|
114
|
+
test "blockdev? basic functionality" do
|
115
|
+
assert_respond_to(@stat, :blockdev?)
|
116
|
+
assert_boolean(@stat.blockdev?)
|
117
|
+
end
|
118
|
+
|
119
|
+
test "blockdev? returns the expected value for a non-block device" do
|
120
|
+
assert_false(@stat.blockdev?)
|
121
|
+
assert_false(File::Stat.new('NUL').blockdev?)
|
122
|
+
end
|
123
|
+
|
124
|
+
# In unusual situations this could fail.
|
125
|
+
test "blockdev? returns the expected value for a block device" do
|
126
|
+
omit_unless(@@block_dev)
|
127
|
+
assert_true(File::Stat.new(@@block_dev).blockdev?)
|
128
|
+
end
|
129
|
+
|
130
|
+
test "blocks basic functionality" do
|
131
|
+
assert_respond_to(@stat, :blocks)
|
132
|
+
assert_kind_of(Fixnum, @stat.blocks)
|
133
|
+
end
|
134
|
+
|
135
|
+
test "blocks method returns expected value" do
|
136
|
+
assert_equal(1, @stat.blocks)
|
137
|
+
end
|
138
|
+
|
139
|
+
test "chardev? custom method basic functionality" do
|
140
|
+
assert_respond_to(@stat, :chardev?)
|
141
|
+
assert_boolean(@stat.chardev?)
|
142
|
+
end
|
143
|
+
|
144
|
+
test "chardev? custom method returns expected value" do
|
145
|
+
assert_true(File::Stat.new("NUL").chardev?)
|
146
|
+
assert_false(File::Stat.new("C:\\").chardev?)
|
147
|
+
end
|
148
|
+
|
149
|
+
test "custom comparison method basic functionality" do
|
150
|
+
assert_respond_to(@stat, :<=>)
|
151
|
+
assert_nothing_raised{ @stat <=> File::Stat.new(@@exe_file) }
|
152
|
+
end
|
153
|
+
|
154
|
+
test "custom comparison method works as expected" do
|
155
|
+
assert_equal(0, @stat <=> @stat)
|
156
|
+
end
|
157
|
+
|
158
|
+
test "compressed? basic functionality" do
|
159
|
+
assert_respond_to(@stat, :compressed?)
|
160
|
+
assert_boolean(@stat.compressed?)
|
161
|
+
end
|
162
|
+
|
163
|
+
test "compressed? returns expected value" do
|
164
|
+
assert_false(@stat.compressed?)
|
165
|
+
end
|
166
|
+
|
167
|
+
test "dev custom method basic functionality" do
|
168
|
+
assert_respond_to(@stat, :rdev)
|
169
|
+
assert_kind_of(Fixnum, @stat.rdev)
|
170
|
+
end
|
171
|
+
|
172
|
+
test "dev custom method returns expected value" do
|
173
|
+
notify "May fail on JRuby" if @@jruby
|
174
|
+
assert_equal(2, File::Stat.new("C:\\").dev)
|
175
|
+
assert_equal(-1, File::Stat.new("NUL").dev)
|
176
|
+
end
|
177
|
+
|
178
|
+
test "dev custom method accepts an optional argument" do
|
179
|
+
assert_nothing_raised{ File::Stat.new("C:\\").dev(true) }
|
180
|
+
assert_kind_of(String, File::Stat.new("C:\\").dev(true))
|
181
|
+
end
|
182
|
+
|
183
|
+
test "dev custom method with optional argument returns expected value" do
|
184
|
+
notify "May fail on JRuby" if @@jruby
|
185
|
+
assert_equal("C:", File::Stat.new("C:\\").dev(true))
|
186
|
+
assert_nil(File::Stat.new("NUL").dev(true))
|
187
|
+
end
|
188
|
+
|
189
|
+
test "dev_major defined and always returns nil" do
|
190
|
+
omit_if(@@jruby) # https://github.com/jnr/jnr-posix/issues/23
|
191
|
+
assert_respond_to(@stat, :dev_major)
|
192
|
+
assert_nil(@stat.dev_major)
|
193
|
+
end
|
194
|
+
|
195
|
+
test "dev_minor defined and always returns nil" do
|
196
|
+
omit_if(@@jruby) # https://github.com/jnr/jnr-posix/issues/23
|
197
|
+
assert_respond_to(@stat, :dev_minor)
|
198
|
+
assert_nil(@stat.dev_minor)
|
199
|
+
end
|
200
|
+
|
201
|
+
test "directory? custom method basic functionality" do
|
202
|
+
assert_respond_to(@stat, :directory?)
|
203
|
+
assert_boolean(@stat.directory?)
|
204
|
+
end
|
205
|
+
|
206
|
+
test "directory? custom method returns expected value" do
|
207
|
+
assert_false(@stat.directory?)
|
208
|
+
assert_true(File::Stat.new("C:\\").directory?)
|
209
|
+
end
|
210
|
+
|
211
|
+
test "executable? custom method basic functionality" do
|
212
|
+
assert_respond_to(@stat, :executable?)
|
213
|
+
assert_boolean(@stat.executable?)
|
214
|
+
end
|
215
|
+
|
216
|
+
test "executable? custom method returns expected value" do
|
217
|
+
assert_false(@stat.executable?)
|
218
|
+
assert_true(File::Stat.new(@@exe_file).executable?)
|
219
|
+
end
|
220
|
+
|
221
|
+
test "executable_real? is an alias for executable?" do
|
222
|
+
assert_respond_to(@stat, :executable_real?)
|
223
|
+
assert_alias_method(@stat, :executable?, :executable_real?)
|
224
|
+
end
|
225
|
+
|
226
|
+
test "file? custom method basic functionality" do
|
227
|
+
assert_respond_to(@stat, :file?)
|
228
|
+
assert_boolean(@stat.file?)
|
229
|
+
end
|
230
|
+
|
231
|
+
test "file? custom method returns expected value" do
|
232
|
+
assert_true(@stat.file?)
|
233
|
+
assert_true(File::Stat.new(@@exe_file).file?)
|
234
|
+
assert_true(File::Stat.new(Dir.pwd).file?)
|
235
|
+
assert_false(File::Stat.new('NUL').file?)
|
236
|
+
end
|
237
|
+
|
238
|
+
test "ftype custom method basic functionality" do
|
239
|
+
assert_respond_to(@stat, :ftype)
|
240
|
+
assert_kind_of(String, @stat.ftype)
|
241
|
+
end
|
242
|
+
|
243
|
+
test "ftype custom method returns expected value" do
|
244
|
+
assert_equal('file', @stat.ftype)
|
245
|
+
assert_equal('characterSpecial', File::Stat.new('NUL').ftype)
|
246
|
+
assert_equal('directory', File::Stat.new(Dir.pwd).ftype)
|
247
|
+
end
|
248
|
+
|
249
|
+
test "encrypted? basic functionality" do
|
250
|
+
assert_respond_to(@stat, :encrypted?)
|
251
|
+
assert_boolean(@stat.encrypted?)
|
252
|
+
end
|
253
|
+
|
254
|
+
test "encrypted? returns the expected value" do
|
255
|
+
assert_false(@stat.encrypted?)
|
256
|
+
end
|
257
|
+
|
258
|
+
test "gid method basic functionality" do
|
259
|
+
assert_respond_to(@stat, :gid)
|
260
|
+
assert_nothing_raised{ @stat.gid }
|
261
|
+
assert_kind_of(Fixnum, @stat.gid)
|
262
|
+
end
|
263
|
+
|
264
|
+
test "gid returns a sane result" do
|
265
|
+
assert_true(@stat.gid >= 0 && @stat.gid <= 10000)
|
266
|
+
end
|
267
|
+
|
268
|
+
test "gid returns a string argument if true argument provided" do
|
269
|
+
assert_nothing_raised{ @stat.gid(true) }
|
270
|
+
assert_match("S-1-", @stat.gid(true))
|
271
|
+
end
|
272
|
+
|
273
|
+
test "grpowned? defined and always returns true" do
|
274
|
+
assert_respond_to(@stat, :grpowned?)
|
275
|
+
end
|
276
|
+
|
277
|
+
test "hidden? basic functionality" do
|
278
|
+
assert_respond_to(@stat, :hidden?)
|
279
|
+
assert_boolean(@stat.hidden?)
|
280
|
+
end
|
281
|
+
|
282
|
+
test "hidden? returns expected value" do
|
283
|
+
assert_false(@stat.hidden?)
|
284
|
+
end
|
285
|
+
|
286
|
+
test "indexed? basic functionality" do
|
287
|
+
assert_respond_to(@stat, :indexed?)
|
288
|
+
assert_boolean(@stat.indexed?)
|
289
|
+
end
|
290
|
+
|
291
|
+
test "indexed? returns expected value" do
|
292
|
+
assert_true(@stat.indexed?)
|
293
|
+
end
|
294
|
+
|
295
|
+
test "content_indexed? is an alias for indexed?" do
|
296
|
+
assert_respond_to(@stat, :content_indexed?)
|
297
|
+
assert_alias_method(@stat, :indexed?, :content_indexed?)
|
298
|
+
end
|
299
|
+
|
300
|
+
test "ino method basic functionality" do
|
301
|
+
assert_respond_to(@stat, :ino)
|
302
|
+
assert_nothing_raised{ @stat.ino }
|
303
|
+
assert_kind_of(Numeric, @stat.ino)
|
304
|
+
end
|
305
|
+
|
306
|
+
test "ino method returns a sane value" do
|
307
|
+
assert_true(@stat.ino > 1000)
|
308
|
+
end
|
309
|
+
|
310
|
+
test "ino method returns nil on a special device" do
|
311
|
+
assert_nil(File::Stat.new("NUL").ino)
|
312
|
+
end
|
313
|
+
|
314
|
+
test "inspect custom method basic functionality" do
|
315
|
+
assert_respond_to(@stat, :inspect)
|
316
|
+
end
|
317
|
+
|
318
|
+
test "inspect string contains expected values" do
|
319
|
+
assert_match('File::Stat', @stat.inspect)
|
320
|
+
assert_match('compressed', @stat.inspect)
|
321
|
+
assert_match('normal', @stat.inspect)
|
322
|
+
end
|
323
|
+
|
324
|
+
test "mode custom method basic functionality" do
|
325
|
+
assert_respond_to(@stat, :mode)
|
326
|
+
assert_kind_of(Fixnum, @stat.mode)
|
327
|
+
end
|
328
|
+
|
329
|
+
test "mode custom method returns the expected value" do
|
330
|
+
assert_equal(33188, File::Stat.new(@@txt_file).mode)
|
331
|
+
assert_equal(33261, File::Stat.new(@@exe_file).mode)
|
332
|
+
assert_equal(16877, File::Stat.new(@dir).mode)
|
333
|
+
end
|
334
|
+
|
335
|
+
test "mode custom method returns expected value for readonly file" do
|
336
|
+
SetFileAttributes(@@txt_file, 1) # Set to readonly.
|
337
|
+
assert_equal(33060, File::Stat.new(@@txt_file).mode)
|
338
|
+
end
|
339
|
+
|
340
|
+
test "nlink basic functionality" do
|
341
|
+
assert_respond_to(@stat, :nlink)
|
342
|
+
assert_kind_of(Fixnum, @stat.nlink)
|
343
|
+
end
|
344
|
+
|
345
|
+
test "nlink returns the expected value" do
|
346
|
+
assert_equal(1, @stat.nlink)
|
347
|
+
assert_equal(1, File::Stat.new(Dir.pwd).nlink)
|
348
|
+
assert_equal(1, File::Stat.new('NUL').nlink)
|
349
|
+
end
|
350
|
+
|
351
|
+
test "normal? basic functionality" do
|
352
|
+
assert_respond_to(@stat, :normal?)
|
353
|
+
assert_boolean(@stat.normal?)
|
354
|
+
end
|
355
|
+
|
356
|
+
test "normal? returns expected value" do
|
357
|
+
assert_false(@stat.normal?)
|
358
|
+
end
|
359
|
+
|
360
|
+
test "offline? method basic functionality" do
|
361
|
+
assert_respond_to(@stat, :offline?)
|
362
|
+
assert_boolean(@stat.offline?)
|
363
|
+
end
|
364
|
+
|
365
|
+
test "offline? method returns expected value" do
|
366
|
+
assert_false(@stat.offline?)
|
367
|
+
end
|
368
|
+
|
369
|
+
test "owned? method basic functionality" do
|
370
|
+
assert_respond_to(@stat, :owned?)
|
371
|
+
assert_boolean(@stat.owned?)
|
372
|
+
end
|
373
|
+
|
374
|
+
test "owned? returns the expected results" do
|
375
|
+
if @@elevated
|
376
|
+
assert_false(@stat.owned?)
|
377
|
+
else
|
378
|
+
assert_true(@stat.owned?)
|
379
|
+
end
|
380
|
+
assert_false(File::Stat.new(@@sys_file).owned?)
|
381
|
+
end
|
382
|
+
|
383
|
+
test "pipe? custom method basic functionality" do
|
384
|
+
assert_respond_to(@stat, :pipe?)
|
385
|
+
assert_boolean(@stat.pipe?)
|
386
|
+
end
|
387
|
+
|
388
|
+
test "pipe? custom method returns expected value" do
|
389
|
+
assert_false(@stat.pipe?)
|
390
|
+
end
|
391
|
+
|
392
|
+
test "socket? is an alias for pipe?" do
|
393
|
+
assert_respond_to(@stat, :socket?)
|
394
|
+
assert_alias_method(@stat, :socket?, :pipe?)
|
395
|
+
end
|
396
|
+
|
397
|
+
test "readable? basic functionality" do
|
398
|
+
assert_respond_to(@stat, :readable?)
|
399
|
+
assert_boolean(@stat.readable?)
|
400
|
+
end
|
401
|
+
|
402
|
+
test "readable? returns expected value" do
|
403
|
+
assert_true(@stat.readable?)
|
404
|
+
assert_true(File::Stat.new(Dir.pwd).readable?)
|
405
|
+
assert_false(File::Stat.new(@@sys_file).readable?)
|
406
|
+
end
|
407
|
+
|
408
|
+
test "readable_real? basic functionality" do
|
409
|
+
assert_respond_to(@stat, :readable_real?)
|
410
|
+
assert_boolean(@stat.readable_real?)
|
411
|
+
end
|
412
|
+
|
413
|
+
test "readable_real? returns expected value" do
|
414
|
+
assert_true(@stat.readable_real?)
|
415
|
+
end
|
416
|
+
|
417
|
+
test "readonly? basic functionality" do
|
418
|
+
assert_respond_to(@stat, :readonly?)
|
419
|
+
assert_boolean(@stat.readonly?)
|
420
|
+
end
|
421
|
+
|
422
|
+
test "readonly? returns the expected value" do
|
423
|
+
assert_false(@stat.readonly?)
|
424
|
+
SetFileAttributes(@@txt_file, 1)
|
425
|
+
assert_true(File::Stat.new(@@txt_file).readonly?)
|
426
|
+
end
|
427
|
+
|
428
|
+
test "read_only? is an alias for readonly?" do
|
429
|
+
assert_respond_to(@stat, :read_only?)
|
430
|
+
assert_alias_method(@stat, :readonly?, :read_only?)
|
431
|
+
end
|
432
|
+
|
433
|
+
test "reparse_point? basic functionality" do
|
434
|
+
assert_respond_to(@stat, :reparse_point?)
|
435
|
+
assert_boolean(@stat.reparse_point?)
|
436
|
+
end
|
437
|
+
|
438
|
+
test "reparse_point returns expected value" do
|
439
|
+
assert_false(@stat.reparse_point?)
|
440
|
+
end
|
441
|
+
|
442
|
+
test "rdev basic functionality" do
|
443
|
+
assert_respond_to(@stat, :rdev)
|
444
|
+
assert_nothing_raised{ @stat.rdev }
|
445
|
+
assert_kind_of(Numeric, @stat.rdev)
|
446
|
+
end
|
447
|
+
|
448
|
+
test "rdev returns a sane value" do
|
449
|
+
assert_true(File::Stat.new("C:\\Program Files").rdev > 1000)
|
450
|
+
end
|
451
|
+
|
452
|
+
test "rdev returns nil on special files" do
|
453
|
+
assert_equal(nil, File::Stat.new("NUL").rdev)
|
454
|
+
end
|
455
|
+
|
456
|
+
# Not sure how to test properly in a generic way, but works on my local network
|
457
|
+
test "rdev works on unc path" do
|
458
|
+
omit_unless(Etc.getlogin == "djberge" && File.exists?("//scipio/users"))
|
459
|
+
assert_true(File::Stat.new("//scipio/users").rdev > 1000)
|
460
|
+
end
|
461
|
+
|
462
|
+
test "rdev_major defined and always returns nil" do
|
463
|
+
omit_if(@@jruby) # https://github.com/jnr/jnr-posix/issues/23
|
464
|
+
assert_respond_to(@stat, :rdev_major)
|
465
|
+
assert_nil(@stat.rdev_major)
|
466
|
+
end
|
467
|
+
|
468
|
+
test "rdev_minor defined and always returns nil" do
|
469
|
+
omit_if(@@jruby) # https://github.com/jnr/jnr-posix/issues/23
|
470
|
+
assert_respond_to(@stat, :rdev_minor)
|
471
|
+
assert_nil(@stat.rdev_minor)
|
472
|
+
end
|
473
|
+
|
474
|
+
test "setgid is set to false" do
|
475
|
+
assert_respond_to(@stat, :setgid?)
|
476
|
+
assert_false(@stat.setgid?)
|
477
|
+
end
|
478
|
+
|
479
|
+
test "setuid is set to false" do
|
480
|
+
assert_respond_to(@stat, :setuid?)
|
481
|
+
assert_false(@stat.setuid?)
|
482
|
+
end
|
483
|
+
|
484
|
+
test "size custom method basic functionality" do
|
485
|
+
assert_respond_to(@stat, :size)
|
486
|
+
assert_kind_of(Numeric, @stat.size)
|
487
|
+
end
|
488
|
+
|
489
|
+
test "size custom method returns expected value" do
|
490
|
+
assert_equal(21, @stat.size)
|
491
|
+
@stat = File::Stat.new(@temp)
|
492
|
+
assert_equal(0, @stat.size)
|
493
|
+
end
|
494
|
+
|
495
|
+
test "size custom method works on system files" do
|
496
|
+
assert_nothing_raised{ File::Stat.new(@@sys_file).size }
|
497
|
+
end
|
498
|
+
|
499
|
+
test "size? method basic functionality" do
|
500
|
+
assert_respond_to(@stat, :size?)
|
501
|
+
assert_kind_of(Numeric, @stat.size)
|
502
|
+
end
|
503
|
+
|
504
|
+
test "size? method returns integer if size greater than zero" do
|
505
|
+
assert_equal(21, @stat.size?)
|
506
|
+
end
|
507
|
+
|
508
|
+
test "size? method returns nil if size is zero" do
|
509
|
+
@stat = File::Stat.new(@temp)
|
510
|
+
assert_nil(@stat.size?)
|
511
|
+
end
|
512
|
+
|
513
|
+
test "sparse? basic fucntionality" do
|
514
|
+
assert_respond_to(@stat, :sparse?)
|
515
|
+
assert_boolean(@stat.sparse?)
|
516
|
+
end
|
517
|
+
|
518
|
+
test "sparse? returns expected value" do
|
519
|
+
assert_false(@stat.sparse?)
|
520
|
+
end
|
521
|
+
|
522
|
+
test "sticky is always set to false" do
|
523
|
+
assert_respond_to(@stat, :sticky?)
|
524
|
+
assert_false(@stat.sticky?)
|
525
|
+
end
|
526
|
+
|
527
|
+
test "symlink? basic functionality" do
|
528
|
+
assert_respond_to(@stat, :symlink?)
|
529
|
+
assert_boolean(@stat.symlink?)
|
530
|
+
end
|
531
|
+
|
532
|
+
test "symlink? returns expected value" do
|
533
|
+
assert_false(@stat.symlink?)
|
534
|
+
end
|
535
|
+
|
536
|
+
test "system? basic functionality" do
|
537
|
+
assert_respond_to(@stat, :system?)
|
538
|
+
assert_boolean(@stat.system?)
|
539
|
+
end
|
540
|
+
|
541
|
+
test "system? returns expected value" do
|
542
|
+
assert_false(@stat.system?)
|
543
|
+
end
|
544
|
+
|
545
|
+
test "temporary? basic functionality" do
|
546
|
+
assert_respond_to(@stat, :temporary?)
|
547
|
+
assert_boolean(@stat.temporary?)
|
548
|
+
end
|
549
|
+
|
550
|
+
test "temporary? returns expected value" do
|
551
|
+
assert_false(@stat.temporary?)
|
552
|
+
end
|
553
|
+
|
554
|
+
test "uid basic functionality" do
|
555
|
+
assert_respond_to(@stat, :uid)
|
556
|
+
assert_nothing_raised{ @stat.uid }
|
557
|
+
assert_kind_of(Fixnum, @stat.uid)
|
558
|
+
end
|
559
|
+
|
560
|
+
test "uid returns a sane result" do
|
561
|
+
assert_true(@stat.uid >= 0 && @stat.uid <= 10000)
|
562
|
+
end
|
563
|
+
|
564
|
+
test "uid returns a string argument if true argument provided" do
|
565
|
+
assert_nothing_raised{ @stat.uid(true) }
|
566
|
+
assert_match("S-1-", @stat.uid(true))
|
567
|
+
end
|
568
|
+
|
569
|
+
test "world_readable? basic functionality" do
|
570
|
+
assert_respond_to(@stat, :world_readable?)
|
571
|
+
assert_boolean(@stat.world_readable?)
|
572
|
+
end
|
573
|
+
|
574
|
+
# TODO: Find or create a file that returns true.
|
575
|
+
test "world_readable? returns expected result" do
|
576
|
+
assert_false(@stat.world_readable?)
|
577
|
+
assert_false(File::Stat.new("C:/").world_readable?)
|
578
|
+
end
|
579
|
+
|
580
|
+
test "world_writable? basic functionality" do
|
581
|
+
assert_respond_to(@stat, :world_writable?)
|
582
|
+
assert_boolean(@stat.world_writable?)
|
583
|
+
end
|
584
|
+
|
585
|
+
# TODO: Find or create a file that returns true.
|
586
|
+
test "world_writable? returns expected result" do
|
587
|
+
assert_false(@stat.world_writable?)
|
588
|
+
assert_false(File::Stat.new("C:/").world_writable?)
|
589
|
+
end
|
590
|
+
|
591
|
+
test "writable? basic functionality" do
|
592
|
+
assert_respond_to(@stat, :writable?)
|
593
|
+
assert_boolean(@stat.writable?)
|
594
|
+
end
|
595
|
+
|
596
|
+
test "writable? returns expected value" do
|
597
|
+
assert_true(@stat.writable?)
|
598
|
+
assert_true(File::Stat.new(Dir.pwd).writable?)
|
599
|
+
assert_false(File::Stat.new(@@sys_file).writable?)
|
600
|
+
end
|
601
|
+
|
602
|
+
test "writable_real? basic functionality" do
|
603
|
+
assert_respond_to(@stat, :writable_real?)
|
604
|
+
assert_boolean(@stat.writable_real?)
|
605
|
+
end
|
606
|
+
|
607
|
+
test "writable_real? returns expected value" do
|
608
|
+
assert_true(@stat.writable_real?)
|
609
|
+
end
|
610
|
+
|
611
|
+
test "zero? method basic functionality" do
|
612
|
+
assert_respond_to(@stat, :zero?)
|
613
|
+
assert_boolean(@stat.zero?)
|
614
|
+
end
|
615
|
+
|
616
|
+
test "zero? method returns expected value" do
|
617
|
+
assert_false(@stat.zero?)
|
618
|
+
@stat = File::Stat.new(@temp)
|
619
|
+
assert_true(@stat.zero?)
|
620
|
+
end
|
621
|
+
|
622
|
+
test "ffi functions are private" do
|
623
|
+
assert_not_respond_to(@stat, :CloseHandle)
|
624
|
+
assert_not_respond_to(File::Stat, :CloseHandle)
|
625
|
+
end
|
626
|
+
|
627
|
+
def teardown
|
628
|
+
SetFileAttributes(@@txt_file, @attr) # Set file back to normal
|
629
|
+
File.delete(@temp) if File.exists?(@temp)
|
630
|
+
@dir = nil
|
631
|
+
@stat = nil
|
632
|
+
@attr = nil
|
633
|
+
@temp = nil
|
634
|
+
end
|
635
|
+
|
636
|
+
def self.shutdown
|
637
|
+
File.delete(@@txt_file) if File.exists?(@@txt_file)
|
638
|
+
File.delete(@@exe_file) if File.exists?(@@exe_file)
|
639
|
+
|
640
|
+
@@block_dev = nil
|
641
|
+
@@txt_file = nil
|
642
|
+
@@exe_file = nil
|
643
|
+
@@sys_file = nil
|
644
|
+
@@elevated = nil
|
645
|
+
@@jruby = nil
|
646
|
+
end
|
647
|
+
end
|