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,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 TestTarWriter < Minitest::Test
@@ -17,25 +16,25 @@ class TestTarWriter < Minitest::Test
17
16
  end
18
17
 
19
18
  def reset
20
- @data = ""
21
- @data.force_encoding("ascii-8bit") if @data.respond_to?(:force_encoding)
19
+ @data = +""
20
+ @data.force_encoding("ascii-8bit")
22
21
  end
23
22
  end
24
23
 
25
24
  def setup
26
25
  @data = "a" * 10
27
26
  @unicode = [0xc3.chr, 0xa5.chr].join * 10
28
- @unicode.force_encoding("utf-8") if @unicode.respond_to?(:force_encoding)
29
- @dummyos = DummyIO.new
30
- @os = Minitar::Writer.new(@dummyos)
27
+ @unicode.force_encoding("utf-8")
28
+ @dummy_writer = DummyIO.new
29
+ @writer = Minitar::Writer.new(@dummy_writer)
31
30
  end
32
31
 
33
32
  def teardown
34
- @os.close
33
+ @writer.close
35
34
  end
36
35
 
37
36
  def test_open_no_block
38
- writer = Minitar::Writer.open(@dummyos)
37
+ writer = Minitar::Writer.open(@dummy_writer)
39
38
  refute writer.closed?
40
39
  ensure
41
40
  writer.close
@@ -43,100 +42,76 @@ class TestTarWriter < Minitest::Test
43
42
  end
44
43
 
45
44
  def test_add_file_simple
46
- @dummyos.reset
47
-
48
- Minitar::Writer.open(@dummyos) do |os|
49
- os.add_file_simple("lib/foo/bar", mode: 0o644, size: 10) do |f|
50
- f.write "a" * 10
51
- end
52
- os.add_file_simple("lib/bar/baz", mode: 0o644, size: 100) do |f|
53
- f.write "fillme"
54
- end
45
+ Minitar::Writer.open(@dummy_writer) do |os|
46
+ os.add_file_simple("lib/foo/bar", mode: 0o644, size: 10) { _1.write "a" * 10 }
47
+ os.add_file_simple("lib/bar/baz", mode: 0o644, size: 100) { _1.write "fillme" }
55
48
  end
56
49
 
57
- assert_headers_equal(tar_file_header("lib/foo/bar", "", 0o644, 10),
58
- @dummyos.data[0, 512])
59
- assert_equal "a" * 10 + "\0" * 502, @dummyos.data[512, 512]
60
- assert_headers_equal(tar_file_header("lib/bar/baz", "", 0o644, 100),
61
- @dummyos.data[512 * 2, 512])
62
- assert_equal "fillme" + "\0" * 506, @dummyos.data[512 * 3, 512]
63
- assert_equal "\0" * 512, @dummyos.data[512 * 4, 512]
64
- assert_equal "\0" * 512, @dummyos.data[512 * 5, 512]
50
+ assert_headers_equal build_tar_file_header("lib/foo/bar", "", 0o644, 10),
51
+ @dummy_writer.data[0, 512]
52
+
53
+ assert_equal "a" * 10 + "\0" * 502, @dummy_writer.data[512, 512]
54
+
55
+ assert_headers_equal build_tar_file_header("lib/bar/baz", "", 0o644, 100),
56
+ @dummy_writer.data[512 * 2, 512]
57
+
58
+ assert_equal "fillme" + "\0" * 506, @dummy_writer.data[512 * 3, 512]
59
+ assert_equal "\0" * 512, @dummy_writer.data[512 * 4, 512]
60
+ assert_equal "\0" * 512, @dummy_writer.data[512 * 5, 512]
65
61
  end
66
62
 
67
63
  def test_write_operations_fail_after_closed
68
- @dummyos.reset
69
- @os.add_file_simple("sadd", mode: 0o644, size: 20) { |f| }
70
- @os.close
71
- assert_raises(Minitar::ClosedStream) { @os.flush }
72
- assert_raises(Minitar::ClosedStream) { @os.add_file("dfdsf", mode: 0o644) {} }
73
- assert_raises(Minitar::ClosedStream) { @os.mkdir "sdfdsf", mode: 0o644 }
74
- assert_raises(Minitar::ClosedStream) { @os.symlink "a", "b", mode: 0o644 }
64
+ @writer.add_file_simple("sadd", mode: 0o644, size: 20) {}
65
+ @writer.close
66
+ assert_raises(Minitar::ClosedStream) { @writer.flush }
67
+ assert_raises(Minitar::ClosedStream) { @writer.add_file("dfdsf", mode: 0o644) {} }
68
+ assert_raises(Minitar::ClosedStream) { @writer.mkdir "sdfdsf", mode: 0o644 }
69
+ assert_raises(Minitar::ClosedStream) { @writer.symlink "a", "b", mode: 0o644 }
75
70
  end
76
71
 
77
72
  def test_file_name_is_split_correctly
78
- # test insane file lengths, and: a{100}/b{155}, etc
79
- @dummyos.reset
80
- names = [
81
- "#{"a" * 155}/#{"b" * 100}",
82
- "#{"a" * 151}/#{"qwer/" * 19}bla",
83
- "/#{"a" * 49}/#{"b" * 50}",
84
- "#{"a" * 49}/#{"b" * 50}x",
85
- "#{"a" * 49}x/#{"b" * 50}"
86
- ]
87
- o_names = [
88
- "b" * 100,
89
- "#{"qwer/" * 19}bla",
90
- "b" * 50,
91
- "#{"b" * 50}x",
92
- "b" * 50
93
- ]
94
- o_prefixes = [
95
- "a" * 155,
96
- "a" * 151,
97
- "/#{"a" * 49}",
98
- "a" * 49,
99
- "#{"a" * 49}x"
100
- ]
101
- names.each do |name|
102
- @os.add_file_simple(name, mode: 0o644, size: 10) {}
73
+ # test extreme file lengths, and: a{100}/b{155}, etc
74
+ names = {
75
+ "#{"a" * 155}/#{"b" * 100}" => {name: "b" * 100, prefix: "a" * 155},
76
+ "#{"a" * 151}/#{"qwer/" * 19}bla" => {name: "#{"qwer/" * 19}bla", prefix: "a" * 151},
77
+ "/#{"a" * 49}/#{"b" * 50}" => {name: "b" * 50, prefix: "/#{"a" * 49}"},
78
+ "#{"a" * 49}/#{"b" * 50}x" => {name: "#{"b" * 50}x", prefix: "a" * 49},
79
+ "#{"a" * 49}x/#{"b" * 50}" => {name: "b" * 50, prefix: "#{"a" * 49}x"}
80
+ }
81
+
82
+ names.each_key do |name|
83
+ @writer.add_file_simple(name, mode: 0o644, size: 10) {}
103
84
  end
104
- names.each_index do |i|
105
- assert_headers_equal(
106
- tar_file_header(o_names[i], o_prefixes[i], 0o644, 10),
107
- @dummyos.data[2 * i * 512, 512]
108
- )
85
+
86
+ names.each_key.with_index do |key, index|
87
+ name, prefix = names[key][:name], names[key][:prefix]
88
+
89
+ assert_headers_equal build_tar_file_header(name, prefix, 0o644, 10),
90
+ @dummy_writer.data[2 * index * 512, 512]
109
91
  end
110
92
  end
111
93
 
112
94
  def test_file_name_is_long
113
- @dummyos.reset
114
-
115
- @os.add_file_simple(File.join("a" * 152, "b" * 10, "c" * 92),
116
- mode: 0o644, size: 10) {}
117
- @os.add_file_simple(File.join("d" * 162, "e" * 10),
118
- mode: 0o644, size: 10) {}
119
- @os.add_file_simple(File.join("f" * 10, "g" * 110),
120
- mode: 0o644, size: 10) {}
95
+ @writer.add_file_simple(File.join("a" * 152, "b" * 10, "c" * 92), mode: 0o644, size: 10) {}
96
+ @writer.add_file_simple(File.join("d" * 162, "e" * 10), mode: 0o644, size: 10) {}
97
+ @writer.add_file_simple(File.join("f" * 10, "g" * 110), mode: 0o644, size: 10) {}
121
98
  # Issue #6.
122
- @os.add_file_simple("a" * 114, mode: 0o644, size: 10) {}
99
+ @writer.add_file_simple("a" * 114, mode: 0o644, size: 10) {}
123
100
 
124
101
  # "././@LongLink", a file name, its actual header, its data, ...
125
102
  4.times do |i|
126
- assert_equal(Minitar::PosixHeader::GNU_EXT_LONG_LINK,
127
- @dummyos.data[4 * i * 512, 32].rstrip)
103
+ assert_equal Minitar::PosixHeader::GNU_EXT_LONG_LINK,
104
+ @dummy_writer.data[4 * i * 512, 32].rstrip
128
105
  end
129
106
  end
130
107
 
131
108
  def test_add_file_simple_content_with_long_name
132
- @dummyos.reset
133
-
134
109
  long_name_file_content = "where_is_all_the_content_gone"
135
110
 
136
- @os.add_file_simple("a" * 114, mode: 0o0644, data: long_name_file_content)
111
+ @writer.add_file_simple("a" * 114, mode: 0o0644, data: long_name_file_content)
137
112
 
138
- assert_equal(long_name_file_content,
139
- @dummyos.data[3 * 512, long_name_file_content.bytesize])
113
+ assert_equal long_name_file_content,
114
+ @dummy_writer.data[3 * 512, long_name_file_content.bytesize]
140
115
  end
141
116
 
142
117
  def test_add_file_content_with_long_name
@@ -157,8 +132,8 @@ class TestTarWriter < Minitest::Test
157
132
  end
158
133
  end
159
134
 
160
- assert_equal(long_name_file_content,
161
- dummyos[3 * 512, long_name_file_content.bytesize])
135
+ assert_equal long_name_file_content,
136
+ dummyos[3 * 512, long_name_file_content.bytesize]
162
137
  end
163
138
 
164
139
  def test_add_file
@@ -170,105 +145,109 @@ class TestTarWriter < Minitest::Test
170
145
  def dummyos.respond_to_missing?(meth, all)
171
146
  string.respond_to?(meth, all)
172
147
  end
148
+
173
149
  content1 = ("a".."z").to_a.join("") # 26
174
150
  content2 = ("aa".."zz").to_a.join("") # 1352
151
+
175
152
  Minitar::Writer.open(dummyos) do |os|
176
153
  os.add_file("lib/foo/bar", mode: 0o644) { |f, _opts| f.write "a" * 10 }
177
154
  os.add_file("lib/bar/baz", mode: 0o644) { |f, _opts| f.write content1 }
178
155
  os.add_file("lib/bar/baz", mode: 0o644) { |f, _opts| f.write content2 }
179
156
  os.add_file("lib/bar/baz", mode: 0o644) { |_f, _opts| }
180
157
  end
181
- assert_headers_equal(tar_file_header("lib/foo/bar", "", 0o644, 10),
182
- dummyos[0, 512])
158
+
159
+ assert_headers_equal build_tar_file_header("lib/foo/bar", "", 0o644, 10),
160
+ dummyos[0, 512]
161
+
183
162
  assert_equal %(#{"a" * 10}#{"\0" * 502}), dummyos[512, 512]
184
163
  offset = 512 * 2
164
+
185
165
  [content1, content2, ""].each do |data|
186
- assert_headers_equal(tar_file_header("lib/bar/baz", "", 0o644,
187
- data.bytesize), dummyos[offset, 512])
166
+ assert_headers_equal build_tar_file_header("lib/bar/baz", "", 0o644, data.bytesize),
167
+ dummyos[offset, 512]
168
+
188
169
  offset += 512
170
+
189
171
  until !data || data == ""
190
172
  chunk = data[0, 512]
191
173
  data[0, 512] = ""
192
- assert_equal(chunk + "\0" * (512 - chunk.bytesize),
193
- dummyos[offset, 512])
174
+
175
+ assert_equal chunk + "\0" * (512 - chunk.bytesize), dummyos[offset, 512]
194
176
  offset += 512
195
177
  end
196
178
  end
179
+
197
180
  assert_equal "\0" * 1024, dummyos[offset, 1024]
198
181
  end
199
182
 
200
183
  def test_add_file_tests_seekability
201
184
  assert_raises(Minitar::NonSeekableStream) do
202
- @os.add_file("libdfdsfd", mode: 0o644) { |f| }
185
+ @writer.add_file("libdfdsfd", mode: 0o644) { |f| }
203
186
  end
204
187
  end
205
188
 
206
189
  def test_write_header
207
- @dummyos.reset
208
- @os.add_file_simple("lib/foo/bar", mode: 0o644, size: 0) {}
209
- @os.flush
210
- assert_headers_equal(tar_file_header("lib/foo/bar", "", 0o644, 0),
211
- @dummyos.data[0, 512])
212
- @dummyos.reset
213
- @os.mkdir("lib/foo", mode: 0o644)
214
- assert_headers_equal(tar_dir_header("lib/foo", "", 0o644),
215
- @dummyos.data[0, 512])
216
- @os.mkdir("lib/bar", mode: 0o644)
217
- assert_headers_equal(tar_dir_header("lib/bar", "", 0o644),
218
- @dummyos.data[512 * 1, 512])
190
+ @writer.add_file_simple("lib/foo/bar", mode: 0o644, size: 0) {}
191
+ @writer.flush
192
+
193
+ assert_headers_equal build_tar_file_header("lib/foo/bar", "", 0o644, 0),
194
+ @dummy_writer.data[0, 512]
195
+
196
+ @dummy_writer.reset
197
+ @writer.mkdir("lib/foo", mode: 0o644)
198
+
199
+ assert_headers_equal build_tar_dir_header("lib/foo", "", 0o644),
200
+ @dummy_writer.data[0, 512]
201
+
202
+ @writer.mkdir("lib/bar", mode: 0o644)
203
+
204
+ assert_headers_equal build_tar_dir_header("lib/bar", "", 0o644),
205
+ @dummy_writer.data[512 * 1, 512]
219
206
  end
220
207
 
221
208
  def test_write_data
222
- @dummyos.reset
223
- @os.add_file_simple("lib/foo/bar", mode: 0o644, size: 10) do |f|
209
+ @writer.add_file_simple("lib/foo/bar", mode: 0o644, size: 10) do |f|
224
210
  f.write @data
225
211
  end
226
- @os.flush
227
- assert_equal(@data + ("\0" * (512 - @data.bytesize)),
228
- @dummyos.data[512, 512])
212
+ @writer.flush
213
+
214
+ assert_equal @data + ("\0" * (512 - @data.bytesize)), @dummy_writer.data[512, 512]
229
215
  end
230
216
 
231
217
  def test_write_unicode_data
232
- @dummyos.reset
233
-
234
- if @unicode.respond_to?(:bytesize)
235
- assert_equal 10, @unicode.size
236
- assert_equal 20, @unicode.bytesize
237
- @unicode.force_encoding("ascii-8bit")
238
- end
218
+ assert_equal 10, @unicode.size
219
+ assert_equal 20, @unicode.bytesize
220
+ @unicode.force_encoding("ascii-8bit")
239
221
 
240
222
  file = ["lib/foo/b", 0xc3.chr, 0xa5.chr, "r"].join
241
223
 
242
- @os.add_file_simple(file, mode: 0o644, size: 20) do |f|
224
+ @writer.add_file_simple(file, mode: 0o644, size: 20) do |f|
243
225
  f.write @unicode
244
226
  end
245
- @os.flush
246
- assert_equal(@unicode + ("\0" * (512 - @unicode.bytesize)),
247
- @dummyos.data[512, 512])
227
+ @writer.flush
228
+
229
+ assert_equal @unicode + ("\0" * (512 - @unicode.bytesize)), @dummy_writer.data[512, 512]
248
230
  end
249
231
 
250
232
  def test_file_size_is_checked
251
- @dummyos.reset
252
233
  assert_raises(Minitar::Writer::WriteBoundaryOverflow) do
253
- @os.add_file_simple("lib/foo/bar", mode: 0o644, size: 10) do |f|
234
+ @writer.add_file_simple("lib/foo/bar", mode: 0o644, size: 10) do |f|
254
235
  f.write "1" * 100
255
236
  end
256
237
  end
257
- @os.add_file_simple("lib/foo/bar", mode: 0o644, size: 10) { |f| }
238
+ @writer.add_file_simple("lib/foo/bar", mode: 0o644, size: 10) { |f| }
258
239
  end
259
240
 
260
241
  def test_symlink
261
- @dummyos.reset
262
- @os.symlink("lib/foo/bar", "lib/foo/baz", mode: 0o644)
263
- @os.flush
264
- assert_headers_equal(tar_symlink_header("lib/foo/bar", "", 0o644, "lib/foo/baz"),
265
- @dummyos.data[0, 512])
242
+ @writer.symlink("lib/foo/bar", "lib/foo/baz", mode: 0o644)
243
+ @writer.flush
244
+ assert_headers_equal build_tar_symlink_header("lib/foo/bar", "", 0o644, "lib/foo/baz"),
245
+ @dummy_writer.data[0, 512]
266
246
  end
267
247
 
268
248
  def test_symlink_target_size_is_checked
269
- @dummyos.reset
270
249
  assert_raises(Minitar::FileNameTooLong) do
271
- @os.symlink("lib/foo/bar", "x" * 101)
250
+ @writer.symlink("lib/foo/bar", "x" * 101)
272
251
  end
273
252
  end
274
253
  end