win32-file-stat 1.5.1 → 1.5.2
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 +4 -4
- data/CHANGES +154 -148
- data/MANIFEST +10 -10
- data/README +94 -93
- data/Rakefile +31 -31
- data/lib/win32/file/stat.rb +994 -984
- data/lib/win32/file/windows/constants.rb +94 -94
- data/lib/win32/file/windows/functions.rb +68 -67
- data/lib/win32/file/windows/helper.rb +13 -13
- data/lib/win32/file/windows/structs.rb +190 -190
- data/test/test_file_stat.rb +677 -677
- data/win32-file-stat.gemspec +27 -27
- metadata +13 -13
@@ -1,94 +1,94 @@
|
|
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
|
-
|
91
|
-
FileStreamInformation = 22
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
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
|
+
|
91
|
+
FileStreamInformation = 22
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -1,67 +1,68 @@
|
|
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 :pointer, :ptr
|
16
|
-
typedef :buffer_in, :buf_in
|
17
|
-
typedef :string, :str
|
18
|
-
typedef :long, :ntstatus
|
19
|
-
|
20
|
-
if RUBY_PLATFORM == 'java' && ENV_JAVA['sun.arch.data.model'] == '64'
|
21
|
-
typedef :ulong_long, :handle
|
22
|
-
else
|
23
|
-
typedef :uintptr_t, :handle
|
24
|
-
end
|
25
|
-
|
26
|
-
ffi_convention :stdcall
|
27
|
-
|
28
|
-
ffi_lib :kernel32
|
29
|
-
|
30
|
-
attach_pfunc :CloseHandle, [:handle], :bool
|
31
|
-
attach_pfunc :CreateFile, :CreateFileW, [:buf_in, :dword, :dword, :ptr, :dword, :dword, :handle], :handle
|
32
|
-
attach_pfunc :FindFirstFile, :FindFirstFileW, [:buf_in, :ptr], :handle
|
33
|
-
attach_pfunc :FindClose, [:handle], :bool
|
34
|
-
attach_pfunc :GetCurrentProcess, [], :handle
|
35
|
-
attach_pfunc :GetDiskFreeSpace, :GetDiskFreeSpaceW, [:buf_in, :ptr, :ptr, :ptr, :ptr], :bool
|
36
|
-
attach_pfunc :GetDriveType, :GetDriveTypeW, [:buf_in], :uint
|
37
|
-
attach_pfunc :GetFileInformationByHandle, [:handle, :ptr], :bool
|
38
|
-
attach_pfunc :GetFileType, [:handle], :dword
|
39
|
-
attach_pfunc :
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
attach_pfunc :
|
45
|
-
attach_pfunc :
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
attach_pfunc :
|
51
|
-
attach_pfunc :
|
52
|
-
attach_pfunc :
|
53
|
-
attach_pfunc :
|
54
|
-
attach_pfunc :
|
55
|
-
attach_pfunc :
|
56
|
-
attach_pfunc :
|
57
|
-
attach_pfunc :
|
58
|
-
attach_pfunc :
|
59
|
-
attach_pfunc :
|
60
|
-
attach_pfunc :
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
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 :pointer, :ptr
|
16
|
+
typedef :buffer_in, :buf_in
|
17
|
+
typedef :string, :str
|
18
|
+
typedef :long, :ntstatus
|
19
|
+
|
20
|
+
if RUBY_PLATFORM == 'java' && ENV_JAVA['sun.arch.data.model'] == '64'
|
21
|
+
typedef :ulong_long, :handle
|
22
|
+
else
|
23
|
+
typedef :uintptr_t, :handle
|
24
|
+
end
|
25
|
+
|
26
|
+
ffi_convention :stdcall
|
27
|
+
|
28
|
+
ffi_lib :kernel32
|
29
|
+
|
30
|
+
attach_pfunc :CloseHandle, [:handle], :bool
|
31
|
+
attach_pfunc :CreateFile, :CreateFileW, [:buf_in, :dword, :dword, :ptr, :dword, :dword, :handle], :handle
|
32
|
+
attach_pfunc :FindFirstFile, :FindFirstFileW, [:buf_in, :ptr], :handle
|
33
|
+
attach_pfunc :FindClose, [:handle], :bool
|
34
|
+
attach_pfunc :GetCurrentProcess, [], :handle
|
35
|
+
attach_pfunc :GetDiskFreeSpace, :GetDiskFreeSpaceW, [:buf_in, :ptr, :ptr, :ptr, :ptr], :bool
|
36
|
+
attach_pfunc :GetDriveType, :GetDriveTypeW, [:buf_in], :uint
|
37
|
+
attach_pfunc :GetFileInformationByHandle, [:handle, :ptr], :bool
|
38
|
+
attach_pfunc :GetFileType, [:handle], :dword
|
39
|
+
attach_pfunc :GetNamedPipeInfo, [:handle, :ptr, :ptr, :ptr, :ptr], :bool
|
40
|
+
attach_pfunc :OpenProcessToken, [:handle, :dword, :ptr], :bool
|
41
|
+
|
42
|
+
ffi_lib :shlwapi
|
43
|
+
|
44
|
+
attach_pfunc :PathGetDriveNumber, :PathGetDriveNumberW, [:buf_in], :int
|
45
|
+
attach_pfunc :PathIsUNC, :PathIsUNCW, [:buf_in], :bool
|
46
|
+
attach_pfunc :PathStripToRoot, :PathStripToRootW, [:ptr], :bool
|
47
|
+
|
48
|
+
ffi_lib :advapi32
|
49
|
+
|
50
|
+
attach_pfunc :ConvertSidToStringSid, :ConvertSidToStringSidA, [:ptr, :ptr], :bool
|
51
|
+
attach_pfunc :ConvertStringSidToSid, :ConvertStringSidToSidA, [:ptr, :ptr], :bool
|
52
|
+
attach_pfunc :GetFileSecurity, :GetFileSecurityW, [:buf_in, :int, :ptr, :dword, :ptr], :bool
|
53
|
+
attach_pfunc :GetSecurityDescriptorOwner, [:ptr, :ptr, :ptr], :bool
|
54
|
+
attach_pfunc :GetSecurityDescriptorGroup, [:ptr, :ptr, :ptr], :bool
|
55
|
+
attach_pfunc :GetTokenInformation, [:handle, :int, :ptr, :dword, :ptr], :bool
|
56
|
+
attach_pfunc :DuplicateToken, [:handle, :dword, :ptr], :bool
|
57
|
+
attach_pfunc :MapGenericMask, [:ptr, :ptr], :void
|
58
|
+
attach_pfunc :AccessCheck, [:ptr, :handle, :dword, :ptr, :ptr, :ptr, :ptr, :ptr], :bool
|
59
|
+
attach_pfunc :BuildTrusteeWithSid, :BuildTrusteeWithSidW, [:ptr, :ptr], :void
|
60
|
+
attach_pfunc :GetSecurityDescriptorDacl, [:ptr, :ptr, :ptr, :ptr], :bool
|
61
|
+
attach_pfunc :GetEffectiveRightsFromAcl, :GetEffectiveRightsFromAclW, [:ptr, :ptr, :ptr], :dword
|
62
|
+
|
63
|
+
ffi_lib :ntdll
|
64
|
+
|
65
|
+
attach_pfunc :NtQueryInformationFile, [:handle, :pointer, :pointer, :ulong, :int], :ntstatus
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -1,13 +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
|
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
|
@@ -1,190 +1,190 @@
|
|
1
|
-
require_relative '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 LowHighLarge < FFI::Struct
|
13
|
-
layout(:LowPart, :ulong, :HighPart, :long)
|
14
|
-
end
|
15
|
-
|
16
|
-
class LARGE_INTEGER < FFI::Union
|
17
|
-
layout(:u, LowHighLarge, :QuadPart, :long_long)
|
18
|
-
end
|
19
|
-
|
20
|
-
class FILE_STREAM_INFORMATION < FFI::Struct
|
21
|
-
layout(
|
22
|
-
:NextEntryOffset, :ulong,
|
23
|
-
:StreamNameLength, :ulong,
|
24
|
-
:StreamSize, LARGE_INTEGER,
|
25
|
-
:StreamAllocateSize, LARGE_INTEGER,
|
26
|
-
:StreamName, [:uchar, 256]
|
27
|
-
)
|
28
|
-
end
|
29
|
-
|
30
|
-
class IO_STATUS_BLOCK < FFI::Struct
|
31
|
-
layout(
|
32
|
-
:union, Class.new(FFI::Union){ layout(:Status, :long, :Pointer, :pointer) },
|
33
|
-
:Information, :uintptr_t
|
34
|
-
)
|
35
|
-
end
|
36
|
-
|
37
|
-
class LowHigh < FFI::Struct
|
38
|
-
layout(:LowPart, :ulong, :HighPart, :ulong)
|
39
|
-
end
|
40
|
-
|
41
|
-
class ULARGE_INTEGER < FFI::Union
|
42
|
-
layout(:u, LowHigh, :QuadPart, :ulong_long)
|
43
|
-
end
|
44
|
-
|
45
|
-
class FILETIME < FFI::Struct
|
46
|
-
layout(:dwLowDateTime, :ulong, :dwHighDateTime, :ulong)
|
47
|
-
end
|
48
|
-
|
49
|
-
class BY_HANDLE_FILE_INFORMATION < FFI::Struct
|
50
|
-
include Windows::Stat::Constants
|
51
|
-
|
52
|
-
layout(
|
53
|
-
:dwFileAttributes, :ulong,
|
54
|
-
:ftCreationTime, FILETIME,
|
55
|
-
:ftLastAccessTime, FILETIME,
|
56
|
-
:ftLastWriteTime, FILETIME,
|
57
|
-
:dwVolumeSerialNumber, :ulong,
|
58
|
-
:nFileSizeHigh, :ulong,
|
59
|
-
:nFileSizeLow, :ulong,
|
60
|
-
:nNumberOfLinks, :ulong,
|
61
|
-
:nFileIndexHigh, :ulong,
|
62
|
-
:nFileIndexLow, :ulong
|
63
|
-
)
|
64
|
-
|
65
|
-
# Return the atime as a number
|
66
|
-
def atime
|
67
|
-
date = ULARGE_INTEGER.new
|
68
|
-
date[:u][:LowPart] = self[:ftLastAccessTime][:dwLowDateTime]
|
69
|
-
date[:u][:HighPart] = self[:ftLastAccessTime][:dwHighDateTime]
|
70
|
-
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
71
|
-
end
|
72
|
-
|
73
|
-
# Return the ctime as a number
|
74
|
-
def ctime
|
75
|
-
date = ULARGE_INTEGER.new
|
76
|
-
date[:u][:LowPart] = self[:ftCreationTime][:dwLowDateTime]
|
77
|
-
date[:u][:HighPart] = self[:ftCreationTime][:dwHighDateTime]
|
78
|
-
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
79
|
-
end
|
80
|
-
|
81
|
-
# Return the mtime as a number
|
82
|
-
def mtime
|
83
|
-
date = ULARGE_INTEGER.new
|
84
|
-
date[:u][:LowPart] = self[:ftLastWriteTime][:dwLowDateTime]
|
85
|
-
date[:u][:HighPart] = self[:ftLastWriteTime][:dwHighDateTime]
|
86
|
-
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
87
|
-
end
|
88
|
-
|
89
|
-
# Return the size as a single number
|
90
|
-
def size
|
91
|
-
(self[:nFileSizeHigh] * (MAXDWORD + 1)) + self[:nFileSizeLow]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
class WIN32_FIND_DATA < FFI::Struct
|
96
|
-
include Windows::Stat::Constants
|
97
|
-
|
98
|
-
layout(
|
99
|
-
:dwFileAttributes, :ulong,
|
100
|
-
:ftCreationTime, FILETIME,
|
101
|
-
:ftLastAccessTime, FILETIME,
|
102
|
-
:ftLastWriteTime, FILETIME,
|
103
|
-
:nFileSizeHigh, :ulong,
|
104
|
-
:nFileSizeLow, :ulong,
|
105
|
-
:dwReserved0, :ulong,
|
106
|
-
:dwReserved1, :ulong,
|
107
|
-
:cFileName, [:uint8, MAX_PATH*2],
|
108
|
-
:cAlternateFileName, [:uint8, 28]
|
109
|
-
)
|
110
|
-
|
111
|
-
# Return the atime as a number
|
112
|
-
def atime
|
113
|
-
date = ULARGE_INTEGER.new
|
114
|
-
date[:u][:LowPart] = self[:ftLastAccessTime][:dwLowDateTime]
|
115
|
-
date[:u][:HighPart] = self[:ftLastAccessTime][:dwHighDateTime]
|
116
|
-
return 0 if date[:QuadPart]==0
|
117
|
-
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
118
|
-
end
|
119
|
-
|
120
|
-
# Return the ctime as a number
|
121
|
-
def ctime
|
122
|
-
date = ULARGE_INTEGER.new
|
123
|
-
date[:u][:LowPart] = self[:ftCreationTime][:dwLowDateTime]
|
124
|
-
date[:u][:HighPart] = self[:ftCreationTime][:dwHighDateTime]
|
125
|
-
return 0 if date[:QuadPart]==0
|
126
|
-
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
127
|
-
end
|
128
|
-
|
129
|
-
# Return the mtime as a number
|
130
|
-
def mtime
|
131
|
-
date = ULARGE_INTEGER.new
|
132
|
-
date[:u][:LowPart] = self[:ftLastWriteTime][:dwLowDateTime]
|
133
|
-
date[:u][:HighPart] = self[:ftLastWriteTime][:dwHighDateTime]
|
134
|
-
return 0 if date[:QuadPart]==0
|
135
|
-
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
136
|
-
end
|
137
|
-
|
138
|
-
# Return the size as a single number
|
139
|
-
def size
|
140
|
-
(self[:nFileSizeHigh] * (MAXDWORD + 1)) + self[:nFileSizeLow]
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
class SID_AND_ATTRIBUTES < FFI::Struct
|
145
|
-
layout(:Sid, :pointer, :Attributes, :ulong)
|
146
|
-
end
|
147
|
-
|
148
|
-
class TOKEN_GROUP < FFI::Struct
|
149
|
-
layout(
|
150
|
-
:GroupCount, :ulong,
|
151
|
-
:Groups, [SID_AND_ATTRIBUTES, 128]
|
152
|
-
)
|
153
|
-
end
|
154
|
-
|
155
|
-
class GENERIC_MAPPING < FFI::Struct
|
156
|
-
layout(
|
157
|
-
:GenericRead, :ulong,
|
158
|
-
:GenericWrite, :ulong,
|
159
|
-
:GenericExecute, :ulong,
|
160
|
-
:GenericAll, :ulong
|
161
|
-
)
|
162
|
-
end
|
163
|
-
|
164
|
-
class LUID_AND_ATTRIBUTES < FFI::Struct
|
165
|
-
layout(
|
166
|
-
:Luid, LowHigh,
|
167
|
-
:Attributes, :ulong
|
168
|
-
)
|
169
|
-
end
|
170
|
-
|
171
|
-
class PRIVILEGE_SET < FFI::Struct
|
172
|
-
layout(
|
173
|
-
:PrivilegeCount, :ulong,
|
174
|
-
:Control, :ulong,
|
175
|
-
:Privilege, [LUID_AND_ATTRIBUTES, 1]
|
176
|
-
)
|
177
|
-
end
|
178
|
-
|
179
|
-
class TRUSTEE < FFI::Struct
|
180
|
-
layout(
|
181
|
-
:pMultipleTrustee, :pointer,
|
182
|
-
:MultipleTrusteeOperation, :ulong,
|
183
|
-
:TrusteeForm, :ulong,
|
184
|
-
:TrusteeType, :ulong,
|
185
|
-
:ptstrName, :pointer
|
186
|
-
)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
1
|
+
require_relative '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 LowHighLarge < FFI::Struct
|
13
|
+
layout(:LowPart, :ulong, :HighPart, :long)
|
14
|
+
end
|
15
|
+
|
16
|
+
class LARGE_INTEGER < FFI::Union
|
17
|
+
layout(:u, LowHighLarge, :QuadPart, :long_long)
|
18
|
+
end
|
19
|
+
|
20
|
+
class FILE_STREAM_INFORMATION < FFI::Struct
|
21
|
+
layout(
|
22
|
+
:NextEntryOffset, :ulong,
|
23
|
+
:StreamNameLength, :ulong,
|
24
|
+
:StreamSize, LARGE_INTEGER,
|
25
|
+
:StreamAllocateSize, LARGE_INTEGER,
|
26
|
+
:StreamName, [:uchar, 256]
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
class IO_STATUS_BLOCK < FFI::Struct
|
31
|
+
layout(
|
32
|
+
:union, Class.new(FFI::Union){ layout(:Status, :long, :Pointer, :pointer) },
|
33
|
+
:Information, :uintptr_t
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
class LowHigh < FFI::Struct
|
38
|
+
layout(:LowPart, :ulong, :HighPart, :ulong)
|
39
|
+
end
|
40
|
+
|
41
|
+
class ULARGE_INTEGER < FFI::Union
|
42
|
+
layout(:u, LowHigh, :QuadPart, :ulong_long)
|
43
|
+
end
|
44
|
+
|
45
|
+
class FILETIME < FFI::Struct
|
46
|
+
layout(:dwLowDateTime, :ulong, :dwHighDateTime, :ulong)
|
47
|
+
end
|
48
|
+
|
49
|
+
class BY_HANDLE_FILE_INFORMATION < FFI::Struct
|
50
|
+
include Windows::Stat::Constants
|
51
|
+
|
52
|
+
layout(
|
53
|
+
:dwFileAttributes, :ulong,
|
54
|
+
:ftCreationTime, FILETIME,
|
55
|
+
:ftLastAccessTime, FILETIME,
|
56
|
+
:ftLastWriteTime, FILETIME,
|
57
|
+
:dwVolumeSerialNumber, :ulong,
|
58
|
+
:nFileSizeHigh, :ulong,
|
59
|
+
:nFileSizeLow, :ulong,
|
60
|
+
:nNumberOfLinks, :ulong,
|
61
|
+
:nFileIndexHigh, :ulong,
|
62
|
+
:nFileIndexLow, :ulong
|
63
|
+
)
|
64
|
+
|
65
|
+
# Return the atime as a number
|
66
|
+
def atime
|
67
|
+
date = ULARGE_INTEGER.new
|
68
|
+
date[:u][:LowPart] = self[:ftLastAccessTime][:dwLowDateTime]
|
69
|
+
date[:u][:HighPart] = self[:ftLastAccessTime][:dwHighDateTime]
|
70
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
71
|
+
end
|
72
|
+
|
73
|
+
# Return the ctime as a number
|
74
|
+
def ctime
|
75
|
+
date = ULARGE_INTEGER.new
|
76
|
+
date[:u][:LowPart] = self[:ftCreationTime][:dwLowDateTime]
|
77
|
+
date[:u][:HighPart] = self[:ftCreationTime][:dwHighDateTime]
|
78
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
79
|
+
end
|
80
|
+
|
81
|
+
# Return the mtime as a number
|
82
|
+
def mtime
|
83
|
+
date = ULARGE_INTEGER.new
|
84
|
+
date[:u][:LowPart] = self[:ftLastWriteTime][:dwLowDateTime]
|
85
|
+
date[:u][:HighPart] = self[:ftLastWriteTime][:dwHighDateTime]
|
86
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
87
|
+
end
|
88
|
+
|
89
|
+
# Return the size as a single number
|
90
|
+
def size
|
91
|
+
(self[:nFileSizeHigh] * (MAXDWORD + 1)) + self[:nFileSizeLow]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class WIN32_FIND_DATA < FFI::Struct
|
96
|
+
include Windows::Stat::Constants
|
97
|
+
|
98
|
+
layout(
|
99
|
+
:dwFileAttributes, :ulong,
|
100
|
+
:ftCreationTime, FILETIME,
|
101
|
+
:ftLastAccessTime, FILETIME,
|
102
|
+
:ftLastWriteTime, FILETIME,
|
103
|
+
:nFileSizeHigh, :ulong,
|
104
|
+
:nFileSizeLow, :ulong,
|
105
|
+
:dwReserved0, :ulong,
|
106
|
+
:dwReserved1, :ulong,
|
107
|
+
:cFileName, [:uint8, MAX_PATH*2],
|
108
|
+
:cAlternateFileName, [:uint8, 28]
|
109
|
+
)
|
110
|
+
|
111
|
+
# Return the atime as a number
|
112
|
+
def atime
|
113
|
+
date = ULARGE_INTEGER.new
|
114
|
+
date[:u][:LowPart] = self[:ftLastAccessTime][:dwLowDateTime]
|
115
|
+
date[:u][:HighPart] = self[:ftLastAccessTime][:dwHighDateTime]
|
116
|
+
return 0 if date[:QuadPart]==0
|
117
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
118
|
+
end
|
119
|
+
|
120
|
+
# Return the ctime as a number
|
121
|
+
def ctime
|
122
|
+
date = ULARGE_INTEGER.new
|
123
|
+
date[:u][:LowPart] = self[:ftCreationTime][:dwLowDateTime]
|
124
|
+
date[:u][:HighPart] = self[:ftCreationTime][:dwHighDateTime]
|
125
|
+
return 0 if date[:QuadPart]==0
|
126
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
127
|
+
end
|
128
|
+
|
129
|
+
# Return the mtime as a number
|
130
|
+
def mtime
|
131
|
+
date = ULARGE_INTEGER.new
|
132
|
+
date[:u][:LowPart] = self[:ftLastWriteTime][:dwLowDateTime]
|
133
|
+
date[:u][:HighPart] = self[:ftLastWriteTime][:dwHighDateTime]
|
134
|
+
return 0 if date[:QuadPart]==0
|
135
|
+
date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
|
136
|
+
end
|
137
|
+
|
138
|
+
# Return the size as a single number
|
139
|
+
def size
|
140
|
+
(self[:nFileSizeHigh] * (MAXDWORD + 1)) + self[:nFileSizeLow]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class SID_AND_ATTRIBUTES < FFI::Struct
|
145
|
+
layout(:Sid, :pointer, :Attributes, :ulong)
|
146
|
+
end
|
147
|
+
|
148
|
+
class TOKEN_GROUP < FFI::Struct
|
149
|
+
layout(
|
150
|
+
:GroupCount, :ulong,
|
151
|
+
:Groups, [SID_AND_ATTRIBUTES, 128]
|
152
|
+
)
|
153
|
+
end
|
154
|
+
|
155
|
+
class GENERIC_MAPPING < FFI::Struct
|
156
|
+
layout(
|
157
|
+
:GenericRead, :ulong,
|
158
|
+
:GenericWrite, :ulong,
|
159
|
+
:GenericExecute, :ulong,
|
160
|
+
:GenericAll, :ulong
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
164
|
+
class LUID_AND_ATTRIBUTES < FFI::Struct
|
165
|
+
layout(
|
166
|
+
:Luid, LowHigh,
|
167
|
+
:Attributes, :ulong
|
168
|
+
)
|
169
|
+
end
|
170
|
+
|
171
|
+
class PRIVILEGE_SET < FFI::Struct
|
172
|
+
layout(
|
173
|
+
:PrivilegeCount, :ulong,
|
174
|
+
:Control, :ulong,
|
175
|
+
:Privilege, [LUID_AND_ATTRIBUTES, 1]
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
class TRUSTEE < FFI::Struct
|
180
|
+
layout(
|
181
|
+
:pMultipleTrustee, :pointer,
|
182
|
+
:MultipleTrusteeOperation, :ulong,
|
183
|
+
:TrusteeForm, :ulong,
|
184
|
+
:TrusteeType, :ulong,
|
185
|
+
:ptstrName, :pointer
|
186
|
+
)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|