minitar 1.0.2 → 1.1.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 +4 -4
- data/CHANGELOG.md +285 -0
- data/CONTRIBUTING.md +273 -0
- data/CONTRIBUTORS.md +27 -0
- data/LICENCE.md +39 -0
- data/Manifest.txt +29 -6
- data/README.md +70 -0
- data/Rakefile +74 -19
- data/SECURITY.md +64 -0
- data/docs/ruby.txt +3 -3
- data/lib/minitar/input.rb +69 -56
- data/lib/minitar/output.rb +34 -22
- data/lib/minitar/pax_header.rb +111 -0
- data/lib/minitar/posix_header.rb +96 -57
- data/lib/minitar/reader.rb +65 -70
- data/lib/minitar/version.rb +5 -0
- data/lib/minitar/writer.rb +50 -88
- data/lib/minitar.rb +60 -64
- data/licenses/bsdl.txt +20 -0
- data/licenses/dco.txt +34 -0
- data/licenses/ruby.txt +52 -0
- data/test/fixtures/issue_46.tar.gz +0 -0
- data/test/fixtures/issue_62.tar.gz +0 -0
- data/test/fixtures/tar_input.tgz +0 -0
- data/test/fixtures/test_input_non_strict_octal.tgz +0 -0
- data/test/fixtures/test_input_relative.tgz +0 -0
- data/test/fixtures/test_input_space_octal.tgz +0 -0
- data/test/fixtures/test_minitar.tar.gz +0 -0
- data/test/minitest_helper.rb +12 -1
- data/test/support/minitar_test_helpers/fixtures.rb +38 -0
- data/test/support/minitar_test_helpers/header.rb +130 -0
- data/test/support/minitar_test_helpers/tarball.rb +324 -0
- data/test/support/minitar_test_helpers.rb +36 -0
- data/test/test_filename_boundary_conditions.rb +74 -0
- data/test/test_gnu_tar_compatibility.rb +92 -0
- data/test/test_integration_pack_unpack_cycle.rb +38 -0
- data/test/test_issue_46.rb +5 -23
- data/test/test_issue_62.rb +50 -0
- data/test/test_minitar.rb +168 -39
- data/test/test_pax_header.rb +104 -0
- data/test/test_pax_support.rb +66 -0
- data/test/test_tar_header.rb +289 -75
- data/test/test_tar_input.rb +14 -61
- data/test/test_tar_output.rb +7 -9
- data/test/test_tar_reader.rb +17 -18
- data/test/test_tar_writer.rb +105 -126
- metadata +95 -89
- data/Contributing.md +0 -94
- data/History.md +0 -236
- data/Licence.md +0 -15
- data/README.rdoc +0 -92
- data/test/support/tar_test_helpers.rb +0 -134
- /data/{Code-of-Conduct.md → CODE_OF_CONDUCT.md} +0 -0
data/test/test_tar_header.rb
CHANGED
@@ -1,110 +1,324 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "minitest_helper"
|
2
4
|
|
3
5
|
class TestTarHeader < Minitest::Test
|
4
6
|
def test_arguments_are_checked
|
5
|
-
|
6
|
-
assert_raises(ArgumentError) {
|
7
|
-
|
8
|
-
}
|
9
|
-
assert_raises(ArgumentError) {
|
10
|
-
ph.new(name: "", size: "", prefix: "")
|
11
|
-
}
|
12
|
-
assert_raises(ArgumentError) {
|
13
|
-
ph.new(name: "", prefix: "", mode: "")
|
14
|
-
}
|
15
|
-
assert_raises(ArgumentError) {
|
16
|
-
ph.new(prefix: "", size: "", mode: "")
|
17
|
-
}
|
7
|
+
assert_raises(ArgumentError) { new(name: "", size: "", mode: "") }
|
8
|
+
assert_raises(ArgumentError) { new(name: "", size: "", prefix: "") }
|
9
|
+
assert_raises(ArgumentError) { new(name: "", prefix: "", mode: "") }
|
10
|
+
assert_raises(ArgumentError) { new(prefix: "", size: "", mode: "") }
|
18
11
|
end
|
19
12
|
|
20
13
|
def test_basic_headers
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
assert_headers_equal(tar_dir_header("bla", "", 0o12345),
|
39
|
-
Minitar::PosixHeader.new(header).to_s)
|
14
|
+
assert_headers_equal build_tar_file_header("bla", "", 0o12345, 10),
|
15
|
+
new(
|
16
|
+
name: "bla",
|
17
|
+
mode: 0o12345,
|
18
|
+
size: 10,
|
19
|
+
prefix: "",
|
20
|
+
typeflag: "0"
|
21
|
+
)
|
22
|
+
|
23
|
+
assert_headers_equal build_tar_dir_header("bla", "", 0o12345),
|
24
|
+
new(
|
25
|
+
name: "bla",
|
26
|
+
mode: 0o12345,
|
27
|
+
size: 0,
|
28
|
+
prefix: "",
|
29
|
+
typeflag: "5"
|
30
|
+
)
|
40
31
|
end
|
41
32
|
|
42
33
|
def test_long_name_works
|
43
|
-
|
44
|
-
name: "a" * 100, mode: 0o12345, size: 10, prefix: ""
|
45
|
-
|
46
|
-
assert_headers_equal(
|
47
|
-
|
48
|
-
header = {
|
49
|
-
name: "a" * 100, mode: 0o12345, size: 10, prefix: "bb" * 60
|
50
|
-
}
|
51
|
-
assert_headers_equal(tar_file_header("a" * 100, "bb" * 60, 0o12345, 10),
|
52
|
-
Minitar::PosixHeader.new(header).to_s)
|
34
|
+
assert_headers_equal build_tar_file_header("a" * 100, "", 0o12345, 10),
|
35
|
+
new(name: "a" * 100, mode: 0o12345, size: 10, prefix: "")
|
36
|
+
|
37
|
+
assert_headers_equal build_tar_file_header("a" * 100, "bb" * 60, 0o12345, 10),
|
38
|
+
new(name: "a" * 100, mode: 0o12345, size: 10, prefix: "bb" * 60)
|
53
39
|
end
|
54
40
|
|
55
41
|
def test_from_stream
|
56
|
-
header =
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
assert_equal
|
61
|
-
assert_equal
|
62
|
-
assert_equal
|
63
|
-
assert_equal "
|
42
|
+
header = from_stream(
|
43
|
+
build_tar_file_header("a" * 100, "", 0o12345, 10)
|
44
|
+
)
|
45
|
+
|
46
|
+
assert_equal "a" * 100, header.name
|
47
|
+
assert_equal 0o12345, header.mode
|
48
|
+
assert_equal 10, header.size
|
49
|
+
assert_equal "", header.prefix
|
50
|
+
assert_equal "ustar", header.magic
|
64
51
|
end
|
65
52
|
|
66
53
|
def test_from_stream_with_evil_name
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
assert_equal "a ", h.name
|
54
|
+
assert_equal "a ", from_stream(
|
55
|
+
build_tar_file_header("a \0" + "\0" * 97, "", 0o12345, 10)
|
56
|
+
).name
|
71
57
|
end
|
72
58
|
|
73
59
|
def test_valid_with_valid_header
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
assert(h.valid?)
|
60
|
+
assert from_stream(
|
61
|
+
build_tar_file_header("a" * 100, "", 0o12345, 10)
|
62
|
+
).valid?
|
79
63
|
end
|
80
64
|
|
81
65
|
def test_from_stream_with_no_strict_octal
|
82
|
-
header = tar_file_header("a" * 100, "", 0o12345, -1213)
|
83
|
-
io = StringIO.new(header)
|
84
|
-
|
85
66
|
assert_raises(ArgumentError) do
|
86
|
-
|
67
|
+
from_stream(
|
68
|
+
build_tar_file_header("a" * 100, "", 0o12345, -1213)
|
69
|
+
)
|
87
70
|
end
|
88
71
|
end
|
89
72
|
|
90
73
|
def test_from_stream_with_octal_wrapped_by_spaces
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
74
|
+
assert_equal 651, from_stream(
|
75
|
+
update_header_checksum(
|
76
|
+
build_raw_header(
|
77
|
+
0,
|
78
|
+
asciiz("a" * 100, 100),
|
79
|
+
asciiz("", 155),
|
80
|
+
" 1213\0",
|
81
|
+
z(octal(0o12345, 7))
|
82
|
+
)
|
83
|
+
)
|
84
|
+
).size
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_valid_with_invalid_header
|
88
|
+
refute from_stream("invalid").valid?
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_setting_long_name_assigns_complete_path
|
92
|
+
header = new(
|
93
|
+
name: "short.txt",
|
94
|
+
mode: 0o644,
|
95
|
+
size: 100,
|
96
|
+
prefix: "some/directory/path"
|
97
|
+
)
|
98
|
+
|
99
|
+
complete_path = "some/directory/path/very_long_filename_that_exceeds_one_hundred_characters_and_needs_gnu_extension.txt"
|
100
|
+
header.long_name = complete_path
|
101
|
+
|
102
|
+
assert_equal complete_path, header.name
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_setting_long_name_clears_prefix_field
|
106
|
+
header = new(
|
107
|
+
name: "short.txt",
|
108
|
+
mode: 0o644,
|
109
|
+
size: 100,
|
110
|
+
prefix: "some/directory/path"
|
111
|
+
)
|
112
|
+
|
113
|
+
complete_path = "some/directory/path/very_long_filename_that_exceeds_one_hundred_characters_and_needs_gnu_extension.txt"
|
114
|
+
header.long_name = complete_path
|
115
|
+
|
116
|
+
assert_equal "", header.prefix
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_setting_long_name_with_nested_directories
|
120
|
+
header = new(
|
121
|
+
name: "file.txt",
|
122
|
+
mode: 0o644,
|
123
|
+
size: 50,
|
124
|
+
prefix: "old/prefix"
|
125
|
+
)
|
126
|
+
|
127
|
+
complete_path = "deep/nested/directory/structure/with/very_long_filename_that_needs_gnu_long_name_extension_support.txt"
|
128
|
+
header.long_name = complete_path
|
129
|
+
|
130
|
+
assert_equal complete_path, header.name
|
131
|
+
assert_equal "", header.prefix
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_setting_long_name_with_empty_prefix
|
135
|
+
header = new(
|
136
|
+
name: "file.txt",
|
137
|
+
mode: 0o644,
|
138
|
+
size: 50,
|
139
|
+
prefix: ""
|
140
|
+
)
|
141
|
+
|
142
|
+
complete_path = "very_long_filename_that_exceeds_one_hundred_characters_and_definitely_needs_gnu_extension_support.txt"
|
143
|
+
header.long_name = complete_path
|
144
|
+
|
145
|
+
assert_equal complete_path, header.name
|
146
|
+
assert_equal "", header.prefix
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_gnu_long_names_extension_is_detected
|
150
|
+
assert new(
|
151
|
+
name: Minitar::PosixHeader::GNU_EXT_LONG_LINK,
|
152
|
+
mode: 0o644,
|
153
|
+
size: 150,
|
154
|
+
prefix: "",
|
155
|
+
typeflag: "L"
|
156
|
+
).long_name?
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_setting_long_name_with_very_long_path
|
160
|
+
header = new(
|
161
|
+
name: "file.txt",
|
162
|
+
mode: 0o644,
|
163
|
+
size: 100,
|
164
|
+
prefix: "old/prefix"
|
165
|
+
)
|
166
|
+
|
167
|
+
long_dir = "very_long_directory_name_that_exceeds_normal_limits" * 5
|
168
|
+
complete_path = "#{long_dir}/extremely_long_filename_with_many_characters.txt"
|
169
|
+
header.long_name = complete_path
|
170
|
+
|
171
|
+
assert_equal complete_path, header.name
|
172
|
+
assert_equal "", header.prefix
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_setting_long_name_with_single_filename_no_directories
|
176
|
+
header = new(
|
177
|
+
name: "short.txt",
|
178
|
+
mode: 0o644,
|
179
|
+
size: 100,
|
180
|
+
prefix: "some/existing/prefix"
|
181
|
+
)
|
182
|
+
|
183
|
+
complete_path = "extremely_long_single_filename_without_any_directory_structure_that_exceeds_one_hundred_characters.txt"
|
184
|
+
header.long_name = complete_path
|
185
|
+
|
186
|
+
assert_equal complete_path, header.name
|
187
|
+
assert_equal "", header.prefix
|
188
|
+
end
|
96
189
|
|
97
|
-
|
190
|
+
def test_setting_long_name_preserves_other_header_fields
|
191
|
+
header = new(
|
192
|
+
name: "short.txt",
|
193
|
+
mode: 0o755,
|
194
|
+
size: 12345,
|
195
|
+
prefix: "old/prefix",
|
196
|
+
uid: 1000,
|
197
|
+
gid: 1000,
|
198
|
+
mtime: 1234567890,
|
199
|
+
typeflag: "0",
|
200
|
+
linkname: "some_link"
|
201
|
+
)
|
202
|
+
|
203
|
+
complete_path = "new/very_long_path/that_exceeds_one_hundred_characters_and_needs_gnu_extension_support.txt"
|
204
|
+
header.long_name = complete_path
|
205
|
+
|
206
|
+
assert_equal complete_path, header.name
|
207
|
+
assert_equal "", header.prefix
|
208
|
+
|
209
|
+
assert_equal 0o755, header.mode
|
210
|
+
assert_equal 12345, header.size
|
211
|
+
assert_equal 1000, header.uid
|
212
|
+
assert_equal 1000, header.gid
|
213
|
+
assert_equal 1234567890, header.mtime
|
214
|
+
assert_equal "0", header.typeflag
|
215
|
+
assert_equal "some_link", header.linkname
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_setting_name_with_empty_string
|
219
|
+
header = new(
|
220
|
+
name: "short.txt",
|
221
|
+
mode: 0o644,
|
222
|
+
size: 100,
|
223
|
+
prefix: "some/prefix"
|
224
|
+
)
|
225
|
+
|
226
|
+
assert_raises(ArgumentError) do
|
227
|
+
header.name = ""
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_setting_long_name_with_empty_string
|
232
|
+
header = new(
|
233
|
+
name: "short.txt",
|
234
|
+
mode: 0o644,
|
235
|
+
size: 100,
|
236
|
+
prefix: "some/prefix"
|
237
|
+
)
|
238
|
+
|
239
|
+
assert_raises(ArgumentError) do
|
240
|
+
header.long_name = ""
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_new_with_empty_string
|
245
|
+
assert_raises(ArgumentError) do
|
246
|
+
new(
|
247
|
+
name: "",
|
248
|
+
mode: 0o644,
|
249
|
+
size: 100,
|
250
|
+
prefix: "some/prefix"
|
251
|
+
)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_parse_numeric_field_octal
|
256
|
+
ph = Minitar::PosixHeader
|
257
|
+
assert_equal 123, ph.send(:parse_numeric_field, "173")
|
258
|
+
assert_equal 0, ph.send(:parse_numeric_field, "0")
|
259
|
+
assert_equal 511, ph.send(:parse_numeric_field, "777")
|
260
|
+
end
|
261
|
+
|
262
|
+
def test_parse_numeric_field_octal_with_spaces
|
263
|
+
ph = Minitar::PosixHeader
|
264
|
+
assert_equal 123, ph.send(:parse_numeric_field, " 173 ")
|
265
|
+
assert_equal 0, ph.send(:parse_numeric_field, " ")
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_parse_numeric_field_binary_positive_number
|
269
|
+
binary_data = [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0x9A].pack("C*")
|
270
|
+
|
271
|
+
header = build_raw_header(
|
272
|
+
0,
|
273
|
+
asciiz("large_file.bin", 100),
|
274
|
+
asciiz("", 155),
|
275
|
+
binary_data,
|
276
|
+
z(octal(0o12345, 7))
|
277
|
+
)
|
278
|
+
header = update_header_checksum(header)
|
98
279
|
io = StringIO.new(header)
|
99
|
-
|
280
|
+
h = Minitar::PosixHeader.from_stream(io)
|
100
281
|
|
101
|
-
|
282
|
+
expected_size = 0x123456789A
|
283
|
+
assert_equal expected_size, h.size
|
102
284
|
end
|
103
285
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
286
|
+
def test_parse_numeric_field_binary_negative_number
|
287
|
+
binary_data = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF].pack("C*")
|
288
|
+
|
289
|
+
header = build_raw_header(
|
290
|
+
0,
|
291
|
+
asciiz("negative_size.bin", 100),
|
292
|
+
asciiz("", 155),
|
293
|
+
binary_data,
|
294
|
+
z(octal(0o12345, 7))
|
295
|
+
)
|
296
|
+
|
297
|
+
header = update_header_checksum(header)
|
298
|
+
io = StringIO.new(header)
|
299
|
+
h = Minitar::PosixHeader.from_stream(io)
|
107
300
|
|
108
|
-
|
301
|
+
expected_size = -1
|
302
|
+
assert_equal expected_size, h.size
|
109
303
|
end
|
304
|
+
|
305
|
+
def test_parse_numeric_field_invalid
|
306
|
+
ph = Minitar::PosixHeader
|
307
|
+
assert_raises(ArgumentError) do
|
308
|
+
ph.send(:parse_numeric_field, "invalid")
|
309
|
+
end
|
310
|
+
assert_raises(ArgumentError) do
|
311
|
+
ph.send(:parse_numeric_field, "\x01\x02\x03") # Invalid binary format
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
private
|
316
|
+
|
317
|
+
def from_stream(stream) =
|
318
|
+
stream
|
319
|
+
.then { _1.is_a?(String) ? StringIO.new(_1) : _1 }
|
320
|
+
.then { Minitar::PosixHeader.from_stream(_1) }
|
321
|
+
|
322
|
+
def new(header_hash) =
|
323
|
+
Minitar::PosixHeader.new(header_hash)
|
110
324
|
end
|
data/test/test_tar_input.rb
CHANGED
@@ -1,23 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "minitar"
|
4
3
|
require "minitest_helper"
|
5
|
-
require "base64"
|
6
|
-
require "zlib"
|
7
4
|
|
8
5
|
class TestTarInput < Minitest::Test
|
9
|
-
TEST_TGZ = Base64.decode64(<<~EOS).freeze
|
10
|
-
H4sIAKJpllQAA0tJLEnUK0ks0kuvYqAVMDAwMDMxUQDR5mbmYNrACMIHA2MjIwUDc3NzEzMz
|
11
|
-
QxMDAwUDQ2NTczMGBQOauQgJlBYDfQ90SiKQkZmHWx1QWVoaHnMgXlGA00MEyHdzMMzOnBbC
|
12
|
-
wPz28n2uJgOR44Xrq7tsHc/utNe/9FdihkmH3pZ7+zOTRFREzkzYJ99iHHDn4n0/Wb3E8Ceq
|
13
|
-
S0uOdSyMMg9Z+WVvX0vJucxs77vrvZf2arWcvHP9wa1Yp9lRnJmC59/P9+43PXum+tj7Ga+8
|
14
|
-
rtT+u3d941e765Y/bOrnvpv8X6jtz+wKqyk/v3n8P5xlO3l/1dn9q9Zotpy5funw/Of77Y/5
|
15
|
-
LVltz7ToTl7dXf5ppmf3n9p+PPxz/sz/qjZn9yf9Y4R7I2Ft3tqfPTUMGgMYlEMSpGXmpBrT
|
16
|
-
2A5Qvjc1xZ3/DTDyv5GJmfFo/qcHCMnILFYAIlA6UDDWU+DlGmgXjYJRMApGwSgYBaNgFIyC
|
17
|
-
UTAKRsEoGAWjYBSMglEwCkbBKBgFo2AUjIJRMApGwSgYBaNgFIwCUgAAGnyo6wAoAAA=
|
18
|
-
EOS
|
19
|
-
FILETIMES = Time.utc(2004).to_i
|
20
|
-
|
21
6
|
TEST_CONTENTS = {
|
22
7
|
"data.tar.gz" => {size: 210, mode: 0o644},
|
23
8
|
"file3" => {size: 18, mode: 0o755}
|
@@ -31,16 +16,17 @@ class TestTarInput < Minitest::Test
|
|
31
16
|
}.freeze
|
32
17
|
|
33
18
|
def setup
|
19
|
+
@reader = open_fixture("tar_input")
|
34
20
|
FileUtils.mkdir_p("data__")
|
35
21
|
end
|
36
22
|
|
37
23
|
def teardown
|
24
|
+
@reader&.close unless @reader&.closed?
|
38
25
|
FileUtils.rm_rf("data__")
|
39
26
|
end
|
40
27
|
|
41
28
|
def test_open_no_block
|
42
|
-
|
43
|
-
input = Minitar::Input.open(reader)
|
29
|
+
input = Minitar::Input.open(@reader)
|
44
30
|
refute input.closed?
|
45
31
|
ensure
|
46
32
|
input.close
|
@@ -48,8 +34,7 @@ class TestTarInput < Minitest::Test
|
|
48
34
|
end
|
49
35
|
|
50
36
|
def test_each_works
|
51
|
-
|
52
|
-
Minitar::Input.open(reader) do |stream|
|
37
|
+
Minitar::Input.open(@reader) do |stream|
|
53
38
|
outer = 0
|
54
39
|
stream.each.with_index do |entry, i|
|
55
40
|
assert_kind_of Minitar::Reader::EntryStream, entry
|
@@ -58,7 +43,7 @@ class TestTarInput < Minitest::Test
|
|
58
43
|
assert_equal TEST_CONTENTS[entry.name][:size], entry.size, entry.name
|
59
44
|
assert_modes_equal(TEST_CONTENTS[entry.name][:mode],
|
60
45
|
entry.mode, entry.name)
|
61
|
-
assert_equal
|
46
|
+
assert_equal TIME_2004, entry.mtime, "entry.mtime"
|
62
47
|
|
63
48
|
if i.zero?
|
64
49
|
data_reader = Zlib::GzipReader.new(StringIO.new(entry.read))
|
@@ -71,7 +56,7 @@ class TestTarInput < Minitest::Test
|
|
71
56
|
entry2.name)
|
72
57
|
assert_modes_equal(TEST_DATA_CONTENTS[entry2.name][:mode],
|
73
58
|
entry2.mode, entry2.name)
|
74
|
-
assert_equal
|
59
|
+
assert_equal TIME_2004, entry2.mtime, entry2.name
|
75
60
|
inner += 1
|
76
61
|
end
|
77
62
|
assert_equal 4, inner
|
@@ -86,8 +71,7 @@ class TestTarInput < Minitest::Test
|
|
86
71
|
end
|
87
72
|
|
88
73
|
def test_extract_entry_works
|
89
|
-
|
90
|
-
Minitar::Input.open(reader) do |stream|
|
74
|
+
Minitar::Input.open(@reader) do |stream|
|
91
75
|
outer_count = 0
|
92
76
|
stream.each_with_index do |entry, i|
|
93
77
|
stream.extract_entry("data__", entry)
|
@@ -150,7 +134,7 @@ class TestTarInput < Minitest::Test
|
|
150
134
|
File.symlink("data__/file4", "data__/file3")
|
151
135
|
File.symlink("data__/file4", "data__/data")
|
152
136
|
|
153
|
-
Minitar.unpack(
|
137
|
+
Minitar.unpack(@reader, "data__")
|
154
138
|
Minitar.unpack(Zlib::GzipReader.new(File.open("data__/data.tar.gz", "rb")),
|
155
139
|
"data__")
|
156
140
|
|
@@ -158,13 +142,8 @@ class TestTarInput < Minitest::Test
|
|
158
142
|
refute File.symlink?("data__/data")
|
159
143
|
end
|
160
144
|
|
161
|
-
RELATIVE_DIRECTORY_TGZ = Base64.decode64 <<~EOS
|
162
|
-
H4sICIIoKVgCA2JhZC1kaXIudGFyANPT0y8sTy0qqWSgHTAwMDAzMVEA0eZmpmDawAjChwEFQ2MDQyMg
|
163
|
-
MDUzVDAwNDY0N2VQMGCgAygtLkksAjolEcjIzMOtDqgsLQ2/J0H+gNOjYBSMglEwyAEA2LchrwAGAAA=
|
164
|
-
EOS
|
165
|
-
|
166
145
|
def test_extract_entry_fails_with_relative_directory
|
167
|
-
reader =
|
146
|
+
reader = open_fixture("test_input_relative")
|
168
147
|
Minitar::Input.open(reader) do |stream|
|
169
148
|
stream.each do |entry|
|
170
149
|
assert_raises Minitar::SecureRelativePathError do
|
@@ -174,52 +153,26 @@ class TestTarInput < Minitest::Test
|
|
174
153
|
end
|
175
154
|
end
|
176
155
|
|
177
|
-
NON_STRICT_OCTAL_TGZ = Base64.decode64(<<~EOS).freeze
|
178
|
-
H4sIAEk55FsAA0tJLEnUK0ks0kuvYqAVMDAwMDMxUQDR5mbmYNrACMjX0zMH
|
179
|
-
AzMDUwUDIG1iZmZoYmCgYGBobGpuxqBgQDMXIYHSYqDvgU5KBDIy83CrAypL
|
180
|
-
S8NjjgEYKMDpIQLkuzkYZmdOC2Fgfnv5PleTgcjxwvXVXbaOZ3fa61/6KzHD
|
181
|
-
pENvy739mUkiKiJnJuyTbzEOuHPxvp+sXmL4E9WlJcc6FkaZh6z8srevpeRc
|
182
|
-
Zrb33fXeS3u1Wk7euf7gVqzT7CjOTMHz7+d795uePVN97P2MV15Xav/du77x
|
183
|
-
q911yx829XPfTf4v1PZndoXVlJ/fPP4fzrKdvL/q7P5VazRbzly/dHj+8/32
|
184
|
-
x/yWrLZnWnQnr+4u/zTTs/tPbT8e/jl/5n9Vm7P7k/4xwr2RsDZv7c+eGgaN
|
185
|
-
AQzKIQnSMnNSjWlsByjfm5pi5n8DGDAyQsv/RiZmxqP5nx4gJCOzWAGIQOlA
|
186
|
-
wVhPgZdroF00CkbBKBgFo2AUjIJRMApGwSgYBaNgFIyCUTAKRsEoGAWjYBSM
|
187
|
-
glEwCkbBKBgFo2AUjIJRMApIAQD0DyzXACgAAA==
|
188
|
-
EOS
|
189
|
-
|
190
156
|
def test_extract_with_non_strict_octal
|
191
|
-
reader =
|
157
|
+
reader = open_fixture("test_input_non_strict_octal")
|
192
158
|
|
193
159
|
assert_raises(ArgumentError) do
|
194
160
|
Minitar.unpack(reader, "data__")
|
195
161
|
end
|
196
162
|
end
|
197
163
|
|
198
|
-
OCTAL_WRAPPED_BY_SPACE_TGZ = Base64.decode64(<<~EOS).freeze
|
199
|
-
H4sIAOQg5FsAA0tJLEnUK0ks0kuvYqAVMDAwMDMxUQDR5mbmYNrACMhXgAJj
|
200
|
-
IyMFA3NzcxMzM0MTAwMFA0NjU3MzBgUDmrkICZQWA30PdFIikJGZh1sdUFla
|
201
|
-
Gh5zDMBAAU4PESDfzcEwO3NaCAPz28v3uZoMRI4Xrq/usnU8u9Ne/9JfiRkm
|
202
|
-
HXpb7u3PTBJRETkzYZ98i3HAnYv3/WT1EsOfqC4tOdaxMMo8ZOWXvX0tJecy
|
203
|
-
s73vrvde2qvVcvLO9Qe3Yp1mR3FmCp5/P9+73/Tsmepj72e88rpS++/e9Y1f
|
204
|
-
7a5b/rCpn/tu8n+htj+zK6ym/Pzm8f9wlu3k/VVn969ao9ly5vqlw/Of77c/
|
205
|
-
5rdktT3Tojt5dXf5p5me3X9q+/Hwz/kz/6vanN2f9I8R7o2EtXlrf/bUMGgM
|
206
|
-
YFAOSZCWmZNqTGM7QPne1BQz/xvAAEb+NzIxMx7N//QAIRmZxQpABEoHCsZ6
|
207
|
-
CrxcA+2iUTAKRsEoGAWjYBSMglEwCkbBKBgFo2AUjIJRMApGwSgYBaNgFIyC
|
208
|
-
UTAKRsEoGAWjYBSMglFACgAAuUHUvwAoAAA=
|
209
|
-
EOS
|
210
|
-
|
211
164
|
def test_extract_octal_wrapped_by_space
|
212
|
-
reader =
|
165
|
+
reader = open_fixture("test_input_space_octal")
|
213
166
|
header = Minitar::PosixHeader.from_stream(reader)
|
214
167
|
assert_equal 210, header.size
|
215
168
|
|
216
|
-
reader =
|
169
|
+
reader = open_fixture("test_input_space_octal")
|
217
170
|
Minitar.unpack(reader, "data__", [])
|
218
171
|
end
|
219
172
|
|
220
173
|
def test_fsync_false
|
221
174
|
outer = 0
|
222
|
-
Minitar.unpack(
|
175
|
+
Minitar.unpack(@reader, "data__", [], fsync: false) do |_label, _path, _stats|
|
223
176
|
outer += 1
|
224
177
|
end
|
225
178
|
assert_equal 6, outer
|
data/test/test_tar_output.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "minitar"
|
4
3
|
require "minitest_helper"
|
5
4
|
|
6
5
|
class TestTarOutput < Minitest::Test
|
@@ -31,13 +30,12 @@ class TestTarOutput < Minitest::Test
|
|
31
30
|
|
32
31
|
def test_file_looks_good
|
33
32
|
Minitar::Output.open(@tarfile) do |os|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
33
|
+
NAMES.each do |name|
|
34
|
+
filename = File.join("data__", name)
|
35
|
+
stat = File.stat(filename)
|
36
|
+
opts = {size: stat.size, mode: 0o644}
|
37
|
+
os.tar.add_file_simple(name, opts) do |ss|
|
38
|
+
File.open(filename, "rb") { |ff| ss.write(ff.read(4096)) until ff.eof? }
|
41
39
|
end
|
42
40
|
end
|
43
41
|
end
|
data/test/test_tar_reader.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "minitar"
|
4
3
|
require "minitest_helper"
|
5
4
|
|
6
5
|
class TestTarReader < Minitest::Test
|
7
6
|
def test_open_no_block
|
8
|
-
str =
|
9
|
-
str +=
|
10
|
-
str +=
|
7
|
+
str = build_tar_file_header("lib/foo", "", 0o10644, 10) + "\0" * 512
|
8
|
+
str += build_tar_file_header("bar", "baz", 0o644, 0)
|
9
|
+
str += build_tar_dir_header("foo", "bar", 0o12345)
|
11
10
|
str += "\0" * 1024
|
12
11
|
|
13
12
|
reader = Minitar::Reader.open(StringIO.new(str))
|
@@ -18,10 +17,10 @@ class TestTarReader < Minitest::Test
|
|
18
17
|
end
|
19
18
|
|
20
19
|
def test_multiple_entries
|
21
|
-
str =
|
22
|
-
str +=
|
23
|
-
str +=
|
24
|
-
str +=
|
20
|
+
str = build_tar_file_header("lib/foo", "", 0o10644, 10) + "\0" * 512
|
21
|
+
str += build_tar_file_header("bar", "baz", 0o644, 0)
|
22
|
+
str += build_tar_dir_header("foo", "bar", 0o12345)
|
23
|
+
str += build_tar_file_header("src/", "", 0o755, 0) # "file" with a trailing slash
|
25
24
|
str += "\0" * 1024
|
26
25
|
names = %w[lib/foo bar foo src/]
|
27
26
|
prefixes = ["", "baz", "bar", ""]
|
@@ -52,7 +51,7 @@ class TestTarReader < Minitest::Test
|
|
52
51
|
|
53
52
|
def test_rewind_entry_works
|
54
53
|
content = ("a".."z").to_a.join(" ")
|
55
|
-
str =
|
54
|
+
str = build_tar_file_header("lib/foo", "", 0o10644, content.bytesize) +
|
56
55
|
content + "\0" * (512 - content.bytesize)
|
57
56
|
str << "\0" * 1024
|
58
57
|
Minitar::Reader.new(StringIO.new(str)) do |is|
|
@@ -68,7 +67,7 @@ class TestTarReader < Minitest::Test
|
|
68
67
|
|
69
68
|
def test_rewind_works
|
70
69
|
content = ("a".."z").to_a.join(" ")
|
71
|
-
str =
|
70
|
+
str = build_tar_file_header("lib/foo", "", 0o10644, content.bytesize) +
|
72
71
|
content + "\0" * (512 - content.bytesize)
|
73
72
|
str << "\0" * 1024
|
74
73
|
Minitar::Reader.new(StringIO.new(str)) do |is|
|
@@ -85,8 +84,8 @@ class TestTarReader < Minitest::Test
|
|
85
84
|
end
|
86
85
|
|
87
86
|
def test_read_works
|
88
|
-
contents = ("a".."z").inject("") { |a, e| a << e * 100 }
|
89
|
-
str =
|
87
|
+
contents = ("a".."z").inject(+"") { |a, e| a << e * 100 }
|
88
|
+
str = build_tar_file_header("lib/foo", "", 0o10644, contents.bytesize) + contents
|
90
89
|
str += "\0" * (512 - (str.bytesize % 512))
|
91
90
|
Minitar::Reader.new(StringIO.new(str)) do |is|
|
92
91
|
is.each_entry do |entry|
|
@@ -120,7 +119,7 @@ class TestTarReader < Minitest::Test
|
|
120
119
|
end
|
121
120
|
|
122
121
|
def test_eof_works
|
123
|
-
str =
|
122
|
+
str = build_tar_file_header("bar", "baz", 0o644, 0)
|
124
123
|
Minitar::Reader.new(StringIO.new(str)) do |is|
|
125
124
|
is.each_entry do |entry|
|
126
125
|
assert_kind_of Minitar::Reader::EntryStream, entry
|
@@ -132,7 +131,7 @@ class TestTarReader < Minitest::Test
|
|
132
131
|
assert entry.eof?
|
133
132
|
end
|
134
133
|
end
|
135
|
-
str =
|
134
|
+
str = build_tar_dir_header("foo", "bar", 0o12345)
|
136
135
|
Minitar::Reader.new(StringIO.new(str)) do |is|
|
137
136
|
is.each_entry do |entry|
|
138
137
|
assert_kind_of Minitar::Reader::EntryStream, entry
|
@@ -144,9 +143,9 @@ class TestTarReader < Minitest::Test
|
|
144
143
|
assert entry.eof?
|
145
144
|
end
|
146
145
|
end
|
147
|
-
str =
|
148
|
-
str +=
|
149
|
-
str +=
|
146
|
+
str = build_tar_dir_header("foo", "bar", 0o12345)
|
147
|
+
str += build_tar_file_header("bar", "baz", 0o644, 0)
|
148
|
+
str += build_tar_file_header("bar", "baz", 0o644, 0)
|
150
149
|
Minitar::Reader.new(StringIO.new(str)) do |is|
|
151
150
|
is.each_entry do |entry|
|
152
151
|
assert_kind_of Minitar::Reader::EntryStream, entry
|