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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +285 -0
  3. data/CONTRIBUTING.md +273 -0
  4. data/CONTRIBUTORS.md +27 -0
  5. data/LICENCE.md +39 -0
  6. data/Manifest.txt +29 -6
  7. data/README.md +70 -0
  8. data/Rakefile +74 -19
  9. data/SECURITY.md +64 -0
  10. data/docs/ruby.txt +3 -3
  11. data/lib/minitar/input.rb +69 -56
  12. data/lib/minitar/output.rb +34 -22
  13. data/lib/minitar/pax_header.rb +111 -0
  14. data/lib/minitar/posix_header.rb +96 -57
  15. data/lib/minitar/reader.rb +65 -70
  16. data/lib/minitar/version.rb +5 -0
  17. data/lib/minitar/writer.rb +50 -88
  18. data/lib/minitar.rb +60 -64
  19. data/licenses/bsdl.txt +20 -0
  20. data/licenses/dco.txt +34 -0
  21. data/licenses/ruby.txt +52 -0
  22. data/test/fixtures/issue_46.tar.gz +0 -0
  23. data/test/fixtures/issue_62.tar.gz +0 -0
  24. data/test/fixtures/tar_input.tgz +0 -0
  25. data/test/fixtures/test_input_non_strict_octal.tgz +0 -0
  26. data/test/fixtures/test_input_relative.tgz +0 -0
  27. data/test/fixtures/test_input_space_octal.tgz +0 -0
  28. data/test/fixtures/test_minitar.tar.gz +0 -0
  29. data/test/minitest_helper.rb +12 -1
  30. data/test/support/minitar_test_helpers/fixtures.rb +38 -0
  31. data/test/support/minitar_test_helpers/header.rb +130 -0
  32. data/test/support/minitar_test_helpers/tarball.rb +324 -0
  33. data/test/support/minitar_test_helpers.rb +36 -0
  34. data/test/test_filename_boundary_conditions.rb +74 -0
  35. data/test/test_gnu_tar_compatibility.rb +92 -0
  36. data/test/test_integration_pack_unpack_cycle.rb +38 -0
  37. data/test/test_issue_46.rb +5 -23
  38. data/test/test_issue_62.rb +50 -0
  39. data/test/test_minitar.rb +168 -39
  40. data/test/test_pax_header.rb +104 -0
  41. data/test/test_pax_support.rb +66 -0
  42. data/test/test_tar_header.rb +289 -75
  43. data/test/test_tar_input.rb +14 -61
  44. data/test/test_tar_output.rb +7 -9
  45. data/test/test_tar_reader.rb +17 -18
  46. data/test/test_tar_writer.rb +105 -126
  47. metadata +95 -89
  48. data/Contributing.md +0 -94
  49. data/History.md +0 -236
  50. data/Licence.md +0 -15
  51. data/README.rdoc +0 -92
  52. data/test/support/tar_test_helpers.rb +0 -134
  53. /data/{Code-of-Conduct.md → CODE_OF_CONDUCT.md} +0 -0
@@ -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
- ph = Minitar::PosixHeader
6
- assert_raises(ArgumentError) {
7
- ph.new(name: "", size: "", mode: "")
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
- header = {
22
- name: "bla",
23
- mode: 0o12345,
24
- size: 10,
25
- prefix: "",
26
- typeflag: "0"
27
- }
28
- assert_headers_equal(tar_file_header("bla", "", 0o12345, 10),
29
- Minitar::PosixHeader.new(header).to_s)
30
-
31
- header = {
32
- name: "bla",
33
- mode: 0o12345,
34
- size: 0,
35
- prefix: "",
36
- typeflag: "5"
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
- header = {
44
- name: "a" * 100, mode: 0o12345, size: 10, prefix: ""
45
- }
46
- assert_headers_equal(tar_file_header("a" * 100, "", 0o12345, 10),
47
- Minitar::PosixHeader.new(header).to_s)
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 = tar_file_header("a" * 100, "", 0o12345, 10)
57
- header = StringIO.new(header)
58
- h = Minitar::PosixHeader.from_stream(header)
59
- assert_equal "a" * 100, h.name
60
- assert_equal 0o12345, h.mode
61
- assert_equal 10, h.size
62
- assert_equal "", h.prefix
63
- assert_equal "ustar", h.magic
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
- header = tar_file_header("a \0" + "\0" * 97, "", 0o12345, 10)
68
- header = StringIO.new(header)
69
- h = Minitar::PosixHeader.from_stream header
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
- header = tar_file_header("a" * 100, "", 0o12345, 10)
75
- header = StringIO.new(header)
76
- h = Minitar::PosixHeader.from_stream header
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
- Minitar::PosixHeader.from_stream(io)
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
- header = raw_header(0,
92
- asciiz("a" * 100, 100),
93
- asciiz("", 155),
94
- " 1213\0",
95
- z(to_oct(0o12345, 7)))
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
- header = update_checksum(header)
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
- header = Minitar::PosixHeader.from_stream(io)
280
+ h = Minitar::PosixHeader.from_stream(io)
100
281
 
101
- assert_equal 651, header.size
282
+ expected_size = 0x123456789A
283
+ assert_equal expected_size, h.size
102
284
  end
103
285
 
104
- def test_valid_with_invalid_header
105
- header = StringIO.new("testing")
106
- h = Minitar::PosixHeader.from_stream header
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
- refute(h.valid?)
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
@@ -1,23 +1,8 @@
1
- #!/usr/bin/env ruby
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
- reader = Zlib::GzipReader.new(StringIO.new(TEST_TGZ))
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
- reader = Zlib::GzipReader.new(StringIO.new(TEST_TGZ))
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 FILETIMES, entry.mtime, "entry.mtime"
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 FILETIMES, entry2.mtime, entry2.name
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
- reader = Zlib::GzipReader.new(StringIO.new(TEST_TGZ))
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(Zlib::GzipReader.new(StringIO.new(TEST_TGZ)), "data__")
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 = Zlib::GzipReader.new(StringIO.new(RELATIVE_DIRECTORY_TGZ))
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 = Zlib::GzipReader.new(StringIO.new(NON_STRICT_OCTAL_TGZ))
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 = Zlib::GzipReader.new(StringIO.new(OCTAL_WRAPPED_BY_SPACE_TGZ))
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 = Zlib::GzipReader.new(StringIO.new(OCTAL_WRAPPED_BY_SPACE_TGZ))
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(Zlib::GzipReader.new(StringIO.new(TEST_TGZ)), "data__", [], fsync: false) do |_label, _path, _stats|
175
+ Minitar.unpack(@reader, "data__", [], fsync: false) do |_label, _path, _stats|
223
176
  outer += 1
224
177
  end
225
178
  assert_equal 6, outer
@@ -1,6 +1,5 @@
1
- #!/usr/bin/env ruby
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
- Dir.chdir("data__") do
35
- NAMES.each do |name|
36
- stat = File.stat(name)
37
- opts = {size: stat.size, mode: 0o644}
38
- os.tar.add_file_simple(name, opts) do |ss|
39
- File.open(name, "rb") { |ff| ss.write(ff.read(4096)) until ff.eof? }
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
@@ -1,13 +1,12 @@
1
- #!/usr/bin/env ruby
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 = tar_file_header("lib/foo", "", 0o10644, 10) + "\0" * 512
9
- str += tar_file_header("bar", "baz", 0o644, 0)
10
- str += tar_dir_header("foo", "bar", 0o12345)
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 = tar_file_header("lib/foo", "", 0o10644, 10) + "\0" * 512
22
- str += tar_file_header("bar", "baz", 0o644, 0)
23
- str += tar_dir_header("foo", "bar", 0o12345)
24
- str += tar_file_header("src/", "", 0o755, 0) # "file" with a trailing slash
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 = tar_file_header("lib/foo", "", 0o10644, content.bytesize) +
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 = tar_file_header("lib/foo", "", 0o10644, content.bytesize) +
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 = tar_file_header("lib/foo", "", 0o10644, contents.bytesize) + contents
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 = tar_file_header("bar", "baz", 0o644, 0)
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 = tar_dir_header("foo", "bar", 0o12345)
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 = tar_dir_header("foo", "bar", 0o12345)
148
- str += tar_file_header("bar", "baz", 0o644, 0)
149
- str += tar_file_header("bar", "baz", 0o644, 0)
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