recls-ruby 2.13.0.1 → 2.13.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/recls/version.rb +2 -2
- data/lib/recls/ximpl/windows.rb +170 -54
- data/test/unit/tc_recls_entry.rb +18 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0da3b80a1f5ba1babc0fdfbd56abf30433e53d39f2996fe2661d0142ad4b386d
|
4
|
+
data.tar.gz: 47fca376aac5eb7559fe2b7e014b8a79d23bc828fcbd999b75ce133a52a4e255
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1c79afd72e02b47c8c9ce9291c08d1c825e96e5e66a826a36a004c08774b82e77aa5610edc0c986ebfa28b10c95f5baea75ed9bdfba12ac35a36a377fd7b747
|
7
|
+
data.tar.gz: dcdfee4db3cddd95879d7faf833def2daea1cdc8d91809981dfbbb3703dacc37ce77b4c1671b33dafb60d7ec446ffee6afe3a389b5de97d4063b157c5ace4b63
|
data/lib/recls/version.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Purpose: Version for recls library
|
5
5
|
#
|
6
6
|
# Created: 14th February 2014
|
7
|
-
# Updated:
|
7
|
+
# Updated: 2nd April 2024
|
8
8
|
#
|
9
9
|
# Author: Matthew Wilson
|
10
10
|
#
|
@@ -43,7 +43,7 @@
|
|
43
43
|
module Recls
|
44
44
|
|
45
45
|
# Current version of the recls.Ruby library
|
46
|
-
VERSION = '2.13.
|
46
|
+
VERSION = '2.13.1'
|
47
47
|
|
48
48
|
private
|
49
49
|
# @!visibility private
|
data/lib/recls/ximpl/windows.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Purpose: Windows-specific constructs for the recls library.
|
5
5
|
#
|
6
6
|
# Created: 19th February 2014
|
7
|
-
# Updated:
|
7
|
+
# Updated: 2nd June 2024
|
8
8
|
#
|
9
9
|
# Author: Matthew Wilson
|
10
10
|
#
|
@@ -37,7 +37,14 @@
|
|
37
37
|
# ######################################################################## #
|
38
38
|
|
39
39
|
|
40
|
-
|
40
|
+
if RUBY_VERSION >= '2'
|
41
|
+
|
42
|
+
require 'fiddle'
|
43
|
+
require 'fiddle/import'
|
44
|
+
else
|
45
|
+
|
46
|
+
require 'Win32API'
|
47
|
+
end
|
41
48
|
|
42
49
|
|
43
50
|
=begin
|
@@ -49,46 +56,136 @@ module Recls
|
|
49
56
|
module Ximpl # :nodoc: all
|
50
57
|
|
51
58
|
# @!visibility private
|
52
|
-
|
59
|
+
module Kernel32
|
60
|
+
|
61
|
+
MAX_PATH = 260
|
62
|
+
NULL = 0x00000000
|
63
|
+
OPEN_EXISTING = 0x00000003
|
64
|
+
end # module Kernel32
|
65
|
+
|
66
|
+
if RUBY_VERSION >= '2'
|
67
|
+
|
68
|
+
module Kernel32
|
69
|
+
extend Fiddle::Importer
|
70
|
+
|
71
|
+
dlload 'kernel32.dll'
|
72
|
+
|
73
|
+
typealias 'BOOL', 'int'
|
74
|
+
typealias 'DWORD', 'unsigned long'
|
75
|
+
typealias 'HANDLE', 'void*'
|
76
|
+
|
77
|
+
BY_HANDLE_FILE_INFORMATION = struct [
|
78
|
+
'DWORD dwFileAttributes',
|
79
|
+
'DWORD ftCreationTime_0',
|
80
|
+
'DWORD ftCreationTime_1',
|
81
|
+
'DWORD ftLastAccessTime_0',
|
82
|
+
'DWORD ftLastAccessTime_1',
|
83
|
+
'DWORD ftLastWriteTime_0',
|
84
|
+
'DWORD ftLastWriteTime_1',
|
85
|
+
'DWORD dwVolumeSerialNumber',
|
86
|
+
'DWORD nFileSizeHigh',
|
87
|
+
'DWORD nFileSizeLow',
|
88
|
+
'DWORD nNumberOfLinks',
|
89
|
+
'DWORD nFileIndexHigh',
|
90
|
+
'DWORD nFileIndexLow',
|
91
|
+
]
|
92
|
+
|
93
|
+
extern 'BOOL CloseHandle(HANDLE)'
|
94
|
+
extern 'HANDLE CreateFileA(const char*, DWORD, DWORD, void*, DWORD, DWORD, HANDLE)'
|
95
|
+
extern 'DWORD GetFileAttributesA(const char*)'
|
96
|
+
extern 'BOOL GetFileInformationByHandle(HANDLE, BY_HANDLE_FILE_INFORMATION*)'
|
97
|
+
extern 'DWORD GetShortPathNameA(const char*, char*, DWORD)'
|
98
|
+
|
99
|
+
INVALID_HANDLE_VALUE = Fiddle::Pointer[-1]
|
100
|
+
end # module Kernel32
|
101
|
+
|
102
|
+
module Kernel32
|
103
|
+
def self.get_file_attributes(path)
|
104
|
+
|
105
|
+
attributes = GetFileAttributesA(path)
|
106
|
+
|
107
|
+
(0xFFFFFFFF == attributes) ? 0 : attributes
|
108
|
+
end
|
53
109
|
|
54
|
-
|
55
|
-
GetFileAttributes = Win32API.new('kernel32', 'GetFileAttributes', [ 'P' ], 'I')
|
56
|
-
GetFileInformationByHandle = Win32API.new('kernel32', 'GetFileInformationByHandle', [ 'L', 'P' ], 'I')
|
57
|
-
GetShortPathName = Win32API.new('kernel32', 'GetShortPathName', [ 'P', 'P', 'L' ], 'L')
|
58
|
-
CreateFile = Win32API.new('kernel32', 'CreateFile', [ 'P', 'L', 'L', 'L', 'L', 'L', 'L' ], 'L')
|
59
|
-
CloseHandle = Win32API.new('kernel32', 'CloseHandle', [ 'L' ], 'L')
|
60
|
-
FILE_ATTRIBUTE_READONLY = 0x00000001
|
61
|
-
FILE_ATTRIBUTE_HIDDEN = 0x00000002
|
62
|
-
FILE_ATTRIBUTE_SYSTEM = 0x00000004
|
63
|
-
FILE_ATTRIBUTE_DIRECTORY = 0x00000010
|
64
|
-
FILE_ATTRIBUTE_ARCHIVE = 0x00000020
|
65
|
-
FILE_ATTRIBUTE_DEVICE = 0x00000040
|
66
|
-
FILE_ATTRIBUTE_NORMAL = 0x00000080
|
67
|
-
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
|
68
|
-
FILE_ATTRIBUTE_COMPRESSED = 0x00000800
|
69
|
-
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
|
110
|
+
def self.get_short_path_name(path)
|
70
111
|
|
71
|
-
|
72
|
-
FILE_FLAG_OVERLAPPED = 0x40000000
|
73
|
-
NULL = 0x00000000
|
74
|
-
INVALID_HANDLE_VALUE = 0xFFFFFFFF
|
112
|
+
buff = ' ' * MAX_PATH
|
75
113
|
|
76
|
-
|
114
|
+
buf = Fiddle::Pointer[buff]
|
77
115
|
|
78
|
-
|
116
|
+
n = GetShortPathNameA(path, buf, buf.size)
|
79
117
|
|
80
|
-
|
81
|
-
|
118
|
+
(0 == n) ? nil : buff[0...n]
|
119
|
+
end
|
82
120
|
|
83
|
-
|
84
|
-
|
121
|
+
def self.get_stat_shared(path)
|
122
|
+
|
123
|
+
volume_id = 0
|
124
|
+
file_index = 0
|
125
|
+
num_links = 0
|
85
126
|
|
86
|
-
|
87
|
-
|
88
|
-
|
127
|
+
hFile = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL)
|
128
|
+
|
129
|
+
if INVALID_HANDLE_VALUE != hFile
|
130
|
+
|
131
|
+
begin
|
132
|
+
bhfi = BY_HANDLE_FILE_INFORMATION.malloc
|
133
|
+
|
134
|
+
if GetFileInformationByHandle(hFile, bhfi)
|
135
|
+
|
136
|
+
volume_id = bhfi.dwVolumeSerialNumber
|
137
|
+
file_index = (bhfi.nFileIndexHigh << 32) | bhfi.nFileIndexLow
|
138
|
+
num_links = bhfi.nNumberOfLinks
|
139
|
+
end
|
140
|
+
ensure
|
141
|
+
|
142
|
+
CloseHandle(hFile)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
[ volume_id, file_index, num_links ]
|
147
|
+
end
|
148
|
+
end # module Kernel32
|
149
|
+
else
|
150
|
+
|
151
|
+
module Kernel32
|
152
|
+
|
153
|
+
CloseHandle = Win32API.new('kernel32', 'CloseHandle', [ 'L' ], 'L')
|
154
|
+
CreateFile = Win32API.new('kernel32', 'CreateFile', [ 'P', 'L', 'L', 'L', 'L', 'L', 'L' ], 'L')
|
155
|
+
GetFileAttributes = Win32API.new('kernel32', 'GetFileAttributes', [ 'P' ], 'I')
|
156
|
+
GetFileInformationByHandle = Win32API.new('kernel32', 'GetFileInformationByHandle', [ 'L', 'P' ], 'I')
|
157
|
+
GetShortPathName = Win32API.new('kernel32', 'GetShortPathName', [ 'P', 'P', 'L' ], 'L')
|
158
|
+
|
159
|
+
INVALID_HANDLE_VALUE = -1
|
160
|
+
|
161
|
+
BHFI_pack_string = 'LQQQLLLLLL'
|
162
|
+
end # module Kernel32
|
163
|
+
|
164
|
+
module Kernel32
|
165
|
+
def self.get_file_attributes(path)
|
166
|
+
|
167
|
+
attributes = GetFileAttributes.call(path)
|
168
|
+
|
169
|
+
(0xFFFFFFFF == attributes) ? 0 : attributes
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.get_short_path_name(path)
|
173
|
+
|
174
|
+
buff = ' ' * MAX_PATH
|
175
|
+
|
176
|
+
n = GetShortPathName.call(path, buff, buff.length)
|
177
|
+
|
178
|
+
(0 == n) ? nil : buff[0...n]
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.get_stat_shared(path)
|
182
|
+
|
183
|
+
volume_id = 0
|
184
|
+
file_index = 0
|
185
|
+
num_links = 0
|
186
|
+
|
187
|
+
hFile = CreateFile.call(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL)
|
89
188
|
|
90
|
-
# for some reason not forcing this new string causes 'can't modify frozen string (TypeError)' (in Ruby 1.8.x)
|
91
|
-
hFile = CreateFile.call("#{path}", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
|
92
189
|
if INVALID_HANDLE_VALUE != hFile
|
93
190
|
|
94
191
|
begin
|
@@ -99,15 +196,43 @@ module Recls
|
|
99
196
|
|
100
197
|
bhfi = bhfi.unpack(BHFI_pack_string)
|
101
198
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
else
|
199
|
+
volume_id = bhfi[4]
|
200
|
+
file_index = (bhfi[8] << 32) | bhfi[9]
|
201
|
+
num_links = bhfi[7]
|
106
202
|
end
|
107
203
|
ensure
|
204
|
+
|
108
205
|
CloseHandle.call(hFile)
|
109
206
|
end
|
110
207
|
end
|
208
|
+
|
209
|
+
[ volume_id, file_index, num_links ]
|
210
|
+
end
|
211
|
+
end # module Kernel32
|
212
|
+
end
|
213
|
+
|
214
|
+
# @!visibility private
|
215
|
+
class FileStat < File::Stat # :nodoc:
|
216
|
+
|
217
|
+
private
|
218
|
+
FILE_ATTRIBUTE_READONLY = 0x00000001
|
219
|
+
FILE_ATTRIBUTE_HIDDEN = 0x00000002
|
220
|
+
FILE_ATTRIBUTE_SYSTEM = 0x00000004
|
221
|
+
FILE_ATTRIBUTE_DIRECTORY = 0x00000010
|
222
|
+
FILE_ATTRIBUTE_ARCHIVE = 0x00000020
|
223
|
+
FILE_ATTRIBUTE_DEVICE = 0x00000040
|
224
|
+
FILE_ATTRIBUTE_NORMAL = 0x00000080
|
225
|
+
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
|
226
|
+
FILE_ATTRIBUTE_COMPRESSED = 0x00000800
|
227
|
+
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
|
228
|
+
|
229
|
+
# @!visibility private
|
230
|
+
class ByHandleInformation # :nodoc:
|
231
|
+
|
232
|
+
# @!visibility private
|
233
|
+
def initialize(path) # :nodoc:
|
234
|
+
|
235
|
+
@volume_id, @file_index, @num_links = Kernel32.get_stat_shared(path)
|
111
236
|
end
|
112
237
|
|
113
238
|
# @!visibility private
|
@@ -129,27 +254,18 @@ module Recls
|
|
129
254
|
# @!visibility private
|
130
255
|
def initialize(path) # :nodoc:
|
131
256
|
|
132
|
-
|
133
|
-
|
134
|
-
# for some reason not forcing this new string causes 'can't modify frozen string (TypeError)'
|
135
|
-
attributes = GetFileAttributes.call("#{path}")
|
257
|
+
path = path.to_str
|
136
258
|
|
137
|
-
|
259
|
+
@path = path
|
138
260
|
|
139
|
-
|
140
|
-
else
|
141
|
-
|
142
|
-
@attributes = attributes
|
143
|
-
end
|
261
|
+
@attributes = Kernel32.get_file_attributes(path)
|
144
262
|
|
145
263
|
super(path)
|
146
264
|
|
147
265
|
@by_handle_information = ByHandleInformation.new(path)
|
148
266
|
|
149
|
-
|
150
|
-
|
151
|
-
n = GetShortPathName.call("#{path}", buff, buff.length)
|
152
|
-
@short_path = (0 == n) ? nil : buff[0...n]
|
267
|
+
@short_path = Kernel32.get_short_path_name(path)
|
268
|
+
|
153
269
|
end
|
154
270
|
|
155
271
|
public
|
@@ -165,7 +281,7 @@ module Recls
|
|
165
281
|
# @!visibility private
|
166
282
|
def hidden? # :nodoc:
|
167
283
|
|
168
|
-
|
284
|
+
has_attribute_? FILE_ATTRIBUTE_HIDDEN
|
169
285
|
end
|
170
286
|
|
171
287
|
# Windows-specific attributes
|
@@ -215,7 +331,7 @@ module Recls
|
|
215
331
|
|
216
332
|
public
|
217
333
|
# @!visibility private
|
218
|
-
def
|
334
|
+
def self.stat(path) # :nodoc:
|
219
335
|
|
220
336
|
Recls::Ximpl::FileStat.new(path)
|
221
337
|
end
|
data/test/unit/tc_recls_entry.rb
CHANGED
@@ -19,7 +19,7 @@ class Test_Recls_entry < Test::Unit::TestCase
|
|
19
19
|
|
20
20
|
def setup
|
21
21
|
|
22
|
-
@cwd = Dir.pwd
|
22
|
+
@cwd = Dir.pwd.freeze
|
23
23
|
end
|
24
24
|
|
25
25
|
def test_entry_does_not_mark_directory
|
@@ -51,5 +51,22 @@ class Test_Recls_entry < Test::Unit::TestCase
|
|
51
51
|
|
52
52
|
assert_not_equal cwd.object_id, cwd2.object_id
|
53
53
|
end
|
54
|
+
|
55
|
+
if Recls.windows?
|
56
|
+
|
57
|
+
def test_entry_file_short_name
|
58
|
+
|
59
|
+
cwd = Recls.stat @cwd
|
60
|
+
|
61
|
+
if cwd.file_short_name
|
62
|
+
|
63
|
+
if cwd.file_full_name != cwd.file_short_name
|
64
|
+
|
65
|
+
assert cwd.file_short_name =~ /^.{0,8}\..{0,3}$/, "'#{cwd.file_short_name}' does not match expected 8.3 form"
|
66
|
+
assert_equal cwd.file_short_name.upcase, cwd.file_short_name, "'#{cwd.file_short_name}' is not uppercase as expected"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
54
71
|
end
|
55
72
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: recls-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.13.
|
4
|
+
version: 2.13.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Wilson
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: xqsr3
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
version: '0.31'
|
27
27
|
description: 'RECursive LS for Ruby
|
28
28
|
|
29
|
-
'
|
29
|
+
'
|
30
30
|
email: matthew@synesis.com.au
|
31
31
|
executables: []
|
32
32
|
extensions: []
|
@@ -83,7 +83,7 @@ homepage: http://github.com/synesissoftware/recls.Ruby
|
|
83
83
|
licenses:
|
84
84
|
- BSD-3-Clause
|
85
85
|
metadata: {}
|
86
|
-
post_install_message:
|
86
|
+
post_install_message:
|
87
87
|
rdoc_options: []
|
88
88
|
require_paths:
|
89
89
|
- lib
|
@@ -98,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
98
|
- !ruby/object:Gem::Version
|
99
99
|
version: '0'
|
100
100
|
requirements: []
|
101
|
-
rubygems_version: 3.
|
102
|
-
signing_key:
|
101
|
+
rubygems_version: 3.3.7
|
102
|
+
signing_key:
|
103
103
|
specification_version: 4
|
104
104
|
summary: recls.Ruby
|
105
105
|
test_files: []
|