minitar 0.5.4 → 0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Code-of-Conduct.md +74 -0
- data/Contributing.md +84 -0
- data/History.md +107 -0
- data/Licence.md +15 -0
- data/Manifest.txt +24 -0
- data/README.rdoc +81 -0
- data/Rakefile +46 -107
- data/docs/bsdl.txt +19 -0
- data/docs/ruby.txt +56 -0
- data/lib/archive-tar-minitar.rb +3 -0
- data/lib/archive/tar/minitar.rb +197 -889
- data/lib/archive/tar/minitar/input.rb +212 -0
- data/lib/archive/tar/minitar/output.rb +69 -0
- data/lib/archive/tar/minitar/posix_header.rb +259 -0
- data/lib/archive/tar/minitar/reader.rb +237 -0
- data/lib/archive/tar/minitar/writer.rb +297 -0
- data/lib/minitar.rb +12 -0
- data/test/minitest_helper.rb +11 -0
- data/test/support/tar_test_helpers.rb +119 -0
- data/test/test_tar_header.rb +74 -0
- data/test/test_tar_input.rb +167 -0
- data/test/test_tar_output.rb +53 -0
- data/test/test_tar_reader.rb +148 -0
- data/test/test_tar_writer.rb +190 -0
- metadata +232 -43
- data/ChangeLog +0 -17
- data/Install +0 -6
- data/README +0 -68
- data/bin/minitar +0 -27
- data/lib/archive/tar/minitar/command.rb +0 -814
- data/tests/tc_tar.rb +0 -629
- data/tests/testall.rb +0 -10
data/lib/minitar.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TarTestHelpers
|
4
|
+
Field = Struct.new(:name, :offset, :length)
|
5
|
+
def self.Field(name, length) # rubocop:disable Style/MethodName
|
6
|
+
@offset ||= 0
|
7
|
+
field = Field.new(name, @offset, length)
|
8
|
+
@offset += length
|
9
|
+
FIELDS[name] = field
|
10
|
+
FIELD_ORDER << name
|
11
|
+
field
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
FIELDS = {} # rubocop:disable Style/MutableConstant
|
17
|
+
FIELD_ORDER = [] # rubocop:disable Style/MutableConstant
|
18
|
+
|
19
|
+
Field('name', 100)
|
20
|
+
Field('mode', 8)
|
21
|
+
Field('uid', 8)
|
22
|
+
Field('gid', 8)
|
23
|
+
Field('size', 12)
|
24
|
+
Field('mtime', 12)
|
25
|
+
Field('checksum', 8)
|
26
|
+
Field('typeflag', 1)
|
27
|
+
Field('linkname', 100)
|
28
|
+
Field('magic', 6)
|
29
|
+
Field('version', 2)
|
30
|
+
Field('uname', 32)
|
31
|
+
Field('gname', 32)
|
32
|
+
Field('devmajor', 8)
|
33
|
+
Field('devminor', 8)
|
34
|
+
Field('prefix', 155)
|
35
|
+
|
36
|
+
BLANK_CHECKSUM = ' ' * 8
|
37
|
+
NULL_100 = "\0" * 100
|
38
|
+
USTAR = "ustar\0".freeze
|
39
|
+
DOUBLE_ZERO = '00'.freeze
|
40
|
+
|
41
|
+
def assert_headers_equal(expected, actual)
|
42
|
+
FIELD_ORDER.each do |field|
|
43
|
+
message = if field == 'checksum'
|
44
|
+
'Header checksums are expected to match.'
|
45
|
+
else
|
46
|
+
"Header field #{field} is expected to match."
|
47
|
+
end
|
48
|
+
|
49
|
+
offset = FIELDS[field].offset
|
50
|
+
length = FIELDS[field].length
|
51
|
+
|
52
|
+
assert_equal(expected[offset, length], actual[offset, length], message)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def assert_modes_equal(expected, actual, name)
|
57
|
+
return if Minitar.windows?
|
58
|
+
|
59
|
+
assert_equal(
|
60
|
+
mode_string(expected),
|
61
|
+
mode_string(actual),
|
62
|
+
"Mode for #{name} does not match"
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
def tar_file_header(fname, dname, mode, length)
|
67
|
+
update_checksum(header('0', fname, dname, length, mode))
|
68
|
+
end
|
69
|
+
|
70
|
+
def tar_dir_header(name, prefix, mode)
|
71
|
+
update_checksum(header('5', name, prefix, 0, mode))
|
72
|
+
end
|
73
|
+
|
74
|
+
def header(type, fname, dname, length, mode)
|
75
|
+
arr = [
|
76
|
+
asciiz(fname, 100), z(to_oct(mode, 7)), z(to_oct(nil, 7)),
|
77
|
+
z(to_oct(nil, 7)), z(to_oct(length, 11)), z(to_oct(0, 11)),
|
78
|
+
BLANK_CHECKSUM, type, NULL_100, USTAR, DOUBLE_ZERO, asciiz('', 32),
|
79
|
+
asciiz('', 32), z(to_oct(nil, 7)), z(to_oct(nil, 7)), asciiz(dname, 155)
|
80
|
+
]
|
81
|
+
h = arr.join.bytes.to_a.pack('C100C8C8C8C12C12C8CC100C6C2C32C32C8C8C155')
|
82
|
+
ret = h + "\0" * (512 - h.size)
|
83
|
+
assert_equal(512, ret.size)
|
84
|
+
ret
|
85
|
+
end
|
86
|
+
|
87
|
+
def update_checksum(header)
|
88
|
+
header[FIELDS['checksum'].offset, FIELDS['checksum'].length] =
|
89
|
+
# inject(:+) was introduced in which version?
|
90
|
+
sp(z(to_oct(header.unpack('C*').inject { |a, e| a + e }, 6)))
|
91
|
+
header
|
92
|
+
end
|
93
|
+
|
94
|
+
def to_oct(n, pad_size)
|
95
|
+
if n.nil?
|
96
|
+
"\0" * pad_size
|
97
|
+
else
|
98
|
+
"%0#{pad_size}o" % n
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def asciiz(str, length)
|
103
|
+
str + "\0" * (length - str.length)
|
104
|
+
end
|
105
|
+
|
106
|
+
def sp(s)
|
107
|
+
s + ' '
|
108
|
+
end
|
109
|
+
|
110
|
+
def z(s)
|
111
|
+
s + "\0"
|
112
|
+
end
|
113
|
+
|
114
|
+
def mode_string(value)
|
115
|
+
'%04o' % (value & 0o777)
|
116
|
+
end
|
117
|
+
|
118
|
+
Minitest::Test.send(:include, self)
|
119
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest_helper'
|
4
|
+
|
5
|
+
class TestTarHeader < Minitest::Test
|
6
|
+
def test_arguments_are_checked
|
7
|
+
ph = Archive::Tar::Minitar::PosixHeader
|
8
|
+
assert_raises(ArgumentError) {
|
9
|
+
ph.new(:name => '', :size => '', :mode => '')
|
10
|
+
}
|
11
|
+
assert_raises(ArgumentError) {
|
12
|
+
ph.new(:name => '', :size => '', :prefix => '')
|
13
|
+
}
|
14
|
+
assert_raises(ArgumentError) {
|
15
|
+
ph.new(:name => '', :prefix => '', :mode => '')
|
16
|
+
}
|
17
|
+
assert_raises(ArgumentError) {
|
18
|
+
ph.new(:prefix => '', :size => '', :mode => '')
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_basic_headers
|
23
|
+
header = {
|
24
|
+
:name => 'bla',
|
25
|
+
:mode => 0o12345,
|
26
|
+
:size => 10,
|
27
|
+
:prefix => '',
|
28
|
+
:typeflag => '0'
|
29
|
+
}
|
30
|
+
assert_headers_equal(tar_file_header('bla', '', 0o12345, 10),
|
31
|
+
Archive::Tar::Minitar::PosixHeader.new(header).to_s)
|
32
|
+
|
33
|
+
header = {
|
34
|
+
:name => 'bla',
|
35
|
+
:mode => 0o12345,
|
36
|
+
:size => 0,
|
37
|
+
:prefix => '',
|
38
|
+
:typeflag => '5'
|
39
|
+
}
|
40
|
+
assert_headers_equal(tar_dir_header('bla', '', 0o12345),
|
41
|
+
Archive::Tar::Minitar::PosixHeader.new(header).to_s)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_long_name_works
|
45
|
+
header = {
|
46
|
+
:name => 'a' * 100, :mode => 0o12345, :size => 10, :prefix => ''
|
47
|
+
}
|
48
|
+
assert_headers_equal(tar_file_header('a' * 100, '', 0o12345, 10),
|
49
|
+
Archive::Tar::Minitar::PosixHeader.new(header).to_s)
|
50
|
+
header = {
|
51
|
+
:name => 'a' * 100, :mode => 0o12345, :size => 10, :prefix => 'bb' * 60
|
52
|
+
}
|
53
|
+
assert_headers_equal(tar_file_header('a' * 100, 'bb' * 60, 0o12345, 10),
|
54
|
+
Archive::Tar::Minitar::PosixHeader.new(header).to_s)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_from_stream
|
58
|
+
header = tar_file_header('a' * 100, '', 0o12345, 10)
|
59
|
+
header = StringIO.new(header)
|
60
|
+
h = Archive::Tar::Minitar::PosixHeader.from_stream(header)
|
61
|
+
assert_equal('a' * 100, h.name)
|
62
|
+
assert_equal(0o12345, h.mode)
|
63
|
+
assert_equal(10, h.size)
|
64
|
+
assert_equal('', h.prefix)
|
65
|
+
assert_equal('ustar', h.magic)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_from_stream_with_evil_name
|
69
|
+
header = tar_file_header("a \0" + "\0" * 97, '', 0o12345, 10)
|
70
|
+
header = StringIO.new(header)
|
71
|
+
h = Archive::Tar::Minitar::PosixHeader.from_stream header
|
72
|
+
assert_equal('a ', h.name)
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'minitar'
|
4
|
+
require 'minitest_helper'
|
5
|
+
require 'base64'
|
6
|
+
require 'zlib'
|
7
|
+
|
8
|
+
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
|
+
TEST_CONTENTS = {
|
22
|
+
'data.tar.gz' => { :size => 210, :mode => 0o644 },
|
23
|
+
'file3' => { :size => 18, :mode => 0o755 }
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
TEST_DATA_CONTENTS = {
|
27
|
+
'data/' => { :size => 0, :mode => 0o755 },
|
28
|
+
'data/__dir__/' => { :size => 0, :mode => 0o755 },
|
29
|
+
'data/file1' => { :size => 16, :mode => 0o644 },
|
30
|
+
'data/file2' => { :size => 16, :mode => 0o644 }
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
def setup
|
34
|
+
FileUtils.mkdir_p('data__')
|
35
|
+
end
|
36
|
+
|
37
|
+
def teardown
|
38
|
+
FileUtils.rm_rf('data__')
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_each_works
|
42
|
+
reader = Zlib::GzipReader.new(StringIO.new(TEST_TGZ))
|
43
|
+
Minitar::Input.open(reader) do |stream|
|
44
|
+
outer = 0
|
45
|
+
stream.each.with_index do |entry, i|
|
46
|
+
assert_kind_of(Minitar::Reader::EntryStream, entry)
|
47
|
+
assert TEST_CONTENTS.key?(entry.name)
|
48
|
+
|
49
|
+
assert_equal(TEST_CONTENTS[entry.name][:size], entry.size, entry.name)
|
50
|
+
assert_modes_equal(TEST_CONTENTS[entry.name][:mode],
|
51
|
+
entry.mode, entry.name)
|
52
|
+
assert_equal(FILETIMES, entry.mtime, 'entry.mtime')
|
53
|
+
|
54
|
+
if i.zero?
|
55
|
+
data_reader = Zlib::GzipReader.new(StringIO.new(entry.read))
|
56
|
+
Minitar::Input.open(data_reader) do |is2|
|
57
|
+
inner = 0
|
58
|
+
is2.each_with_index do |entry2, _j|
|
59
|
+
assert_kind_of(Minitar::Reader::EntryStream, entry2)
|
60
|
+
assert TEST_DATA_CONTENTS.key?(entry2.name)
|
61
|
+
assert_equal(TEST_DATA_CONTENTS[entry2.name][:size], entry2.size,
|
62
|
+
entry2.name)
|
63
|
+
assert_modes_equal(TEST_DATA_CONTENTS[entry2.name][:mode],
|
64
|
+
entry2.mode, entry2.name)
|
65
|
+
assert_equal(FILETIMES, entry2.mtime, entry2.name)
|
66
|
+
inner += 1
|
67
|
+
end
|
68
|
+
assert_equal(4, inner)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
outer += 1
|
73
|
+
end
|
74
|
+
|
75
|
+
assert_equal(2, outer)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_extract_entry_works
|
80
|
+
reader = Zlib::GzipReader.new(StringIO.new(TEST_TGZ))
|
81
|
+
Minitar::Input.open(reader) do |stream|
|
82
|
+
outer_count = 0
|
83
|
+
stream.each_with_index do |entry, i|
|
84
|
+
stream.extract_entry('data__', entry)
|
85
|
+
name = File.join('data__', entry.name)
|
86
|
+
|
87
|
+
assert TEST_CONTENTS.key?(entry.name)
|
88
|
+
|
89
|
+
if entry.directory?
|
90
|
+
assert(File.directory?(name))
|
91
|
+
else
|
92
|
+
assert(File.file?(name))
|
93
|
+
|
94
|
+
assert_equal(TEST_CONTENTS[entry.name][:size], File.stat(name).size)
|
95
|
+
end
|
96
|
+
|
97
|
+
assert_modes_equal(TEST_CONTENTS[entry.name][:mode],
|
98
|
+
File.stat(name).mode, entry.name)
|
99
|
+
|
100
|
+
if i.zero?
|
101
|
+
begin
|
102
|
+
ff = File.open(name, 'rb')
|
103
|
+
data_reader = Zlib::GzipReader.new(ff)
|
104
|
+
Minitar::Input.open(data_reader) do |is2|
|
105
|
+
is2.each_with_index do |entry2, _j|
|
106
|
+
is2.extract_entry('data__', entry2)
|
107
|
+
name2 = File.join('data__', entry2.name)
|
108
|
+
|
109
|
+
assert TEST_DATA_CONTENTS.key?(entry2.name)
|
110
|
+
|
111
|
+
if entry2.directory?
|
112
|
+
assert(File.directory?(name2))
|
113
|
+
else
|
114
|
+
assert(File.file?(name2))
|
115
|
+
assert_equal(TEST_DATA_CONTENTS[entry2.name][:size],
|
116
|
+
File.stat(name2).size)
|
117
|
+
end
|
118
|
+
assert_modes_equal(TEST_DATA_CONTENTS[entry2.name][:mode],
|
119
|
+
File.stat(name2).mode, name2)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
ensure
|
123
|
+
ff.close unless ff.closed?
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
outer_count += 1
|
128
|
+
end
|
129
|
+
|
130
|
+
assert_equal(2, outer_count)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_extract_entry_breaks_symlinks
|
135
|
+
return if Minitar.windows?
|
136
|
+
|
137
|
+
IO.respond_to?(:write) &&
|
138
|
+
IO.write('data__/file4', '') ||
|
139
|
+
File.open('data__/file4', 'w') { |f| f.write '' }
|
140
|
+
|
141
|
+
File.symlink('data__/file4', 'data__/file3')
|
142
|
+
File.symlink('data__/file4', 'data__/data')
|
143
|
+
|
144
|
+
Minitar.unpack(Zlib::GzipReader.new(StringIO.new(TEST_TGZ)), 'data__')
|
145
|
+
Minitar.unpack(Zlib::GzipReader.new(File.open('data__/data.tar.gz', 'rb')),
|
146
|
+
'data__')
|
147
|
+
|
148
|
+
refute File.symlink?('data__/file3')
|
149
|
+
refute File.symlink?('data__/data')
|
150
|
+
end
|
151
|
+
|
152
|
+
RELATIVE_DIRECTORY_TGZ = Base64.decode64 <<-EOS
|
153
|
+
H4sICIIoKVgCA2JhZC1kaXIudGFyANPT0y8sTy0qqWSgHTAwMDAzMVEA0eZmpmDawAjChwEFQ2MDQyMg
|
154
|
+
MDUzVDAwNDY0N2VQMGCgAygtLkksAjolEcjIzMOtDqgsLQ2/J0H+gNOjYBSMglEwyAEA2LchrwAGAAA=
|
155
|
+
EOS
|
156
|
+
|
157
|
+
def test_extract_entry_fails_with_relative_directory
|
158
|
+
reader = Zlib::GzipReader.new(StringIO.new(RELATIVE_DIRECTORY_TGZ))
|
159
|
+
Minitar::Input.open(reader) do |stream|
|
160
|
+
stream.each do |entry|
|
161
|
+
assert_raises Archive::Tar::Minitar::SecureRelativePathError do
|
162
|
+
stream.extract_entry('data__', entry)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'minitar'
|
4
|
+
require 'minitest_helper'
|
5
|
+
|
6
|
+
class TestTarOutput < Minitest::Test
|
7
|
+
def setup
|
8
|
+
FileUtils.mkdir_p('data__')
|
9
|
+
%w(a b c).each do |filename|
|
10
|
+
name = File.join('data__', filename)
|
11
|
+
File.open(name, 'wb') { |f|
|
12
|
+
f.puts "#{name}: 123456789012345678901234567890"
|
13
|
+
}
|
14
|
+
end
|
15
|
+
@tarfile = 'data__/bla2.tar'
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
FileUtils.rm_rf('data__')
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_file_looks_good
|
23
|
+
Minitar::Output.open(@tarfile) do |os|
|
24
|
+
Dir.chdir('data__') do
|
25
|
+
%w(a b c).each do |name|
|
26
|
+
stat = File.stat(name)
|
27
|
+
opts = { :size => stat.size, :mode => 0o644 }
|
28
|
+
os.tar.add_file_simple(name, opts) do |ss|
|
29
|
+
File.open(name, 'rb') { |ff| ss.write(ff.read(4096)) until ff.eof? }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
ff = File.open(@tarfile, 'rb')
|
35
|
+
Minitar::Reader.open(ff) do |is|
|
36
|
+
ii = 0
|
37
|
+
is.each do |entry|
|
38
|
+
case ii
|
39
|
+
when 0
|
40
|
+
assert_equal('a', entry.name)
|
41
|
+
when 1
|
42
|
+
assert_equal('b', entry.name)
|
43
|
+
when 2
|
44
|
+
assert_equal('c', entry.name)
|
45
|
+
end
|
46
|
+
ii += 1
|
47
|
+
end
|
48
|
+
assert_equal(3, ii)
|
49
|
+
end
|
50
|
+
ensure
|
51
|
+
ff.close if ff
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'minitar'
|
4
|
+
require 'minitest_helper'
|
5
|
+
|
6
|
+
class TestTarReader < Minitest::Test
|
7
|
+
def test_multiple_entries
|
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)
|
11
|
+
str += "\0" * 1024
|
12
|
+
names = %w(lib/foo bar foo)
|
13
|
+
prefixes = ['', 'baz', 'bar']
|
14
|
+
modes = [0o10644, 0o644, 0o12345]
|
15
|
+
sizes = [10, 0, 0]
|
16
|
+
isdir = [false, false, true]
|
17
|
+
isfile = [true, true, false]
|
18
|
+
Minitar::Reader.new(StringIO.new(str)) do |is|
|
19
|
+
i = 0
|
20
|
+
is.each_entry do |entry|
|
21
|
+
assert_kind_of(Minitar::Reader::EntryStream, entry)
|
22
|
+
assert_equal(names[i], entry.name)
|
23
|
+
assert_equal(prefixes[i], entry.prefix)
|
24
|
+
assert_equal(sizes[i], entry.size)
|
25
|
+
assert_equal(modes[i], entry.mode)
|
26
|
+
assert_equal(isdir[i], entry.directory?)
|
27
|
+
assert_equal(isfile[i], entry.file?)
|
28
|
+
if prefixes[i] != ''
|
29
|
+
assert_equal(File.join(prefixes[i], names[i]), entry.full_name)
|
30
|
+
else
|
31
|
+
assert_equal(names[i], entry.name)
|
32
|
+
end
|
33
|
+
i += 1
|
34
|
+
end
|
35
|
+
assert_equal(names.size, i)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_rewind_entry_works
|
40
|
+
content = ('a'..'z').to_a.join(' ')
|
41
|
+
str = tar_file_header('lib/foo', '', 0o10644, content.size) + content +
|
42
|
+
"\0" * (512 - content.size)
|
43
|
+
str << "\0" * 1024
|
44
|
+
Minitar::Reader.new(StringIO.new(str)) do |is|
|
45
|
+
is.each_entry do |entry|
|
46
|
+
3.times do
|
47
|
+
entry.rewind
|
48
|
+
assert_equal(content, entry.read)
|
49
|
+
assert_equal(content.size, entry.pos)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_rewind_works
|
56
|
+
content = ('a'..'z').to_a.join(' ')
|
57
|
+
str = tar_file_header('lib/foo', '', 0o10644, content.size) + content +
|
58
|
+
"\0" * (512 - content.size)
|
59
|
+
str << "\0" * 1024
|
60
|
+
Minitar::Reader.new(StringIO.new(str)) do |is|
|
61
|
+
3.times do
|
62
|
+
is.rewind
|
63
|
+
i = 0
|
64
|
+
is.each_entry do |entry|
|
65
|
+
assert_equal(content, entry.read)
|
66
|
+
i += 1
|
67
|
+
end
|
68
|
+
assert_equal(1, i)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_read_works
|
74
|
+
contents = ('a'..'z').inject('') { |a, e| a << e * 100 }
|
75
|
+
str = tar_file_header('lib/foo', '', 0o10644, contents.size) + contents
|
76
|
+
str += "\0" * (512 - (str.size % 512))
|
77
|
+
Minitar::Reader.new(StringIO.new(str)) do |is|
|
78
|
+
is.each_entry do |entry|
|
79
|
+
assert_kind_of(Minitar::Reader::EntryStream, entry)
|
80
|
+
data = entry.read(3000) # bigger than contents.size
|
81
|
+
assert_equal(contents, data)
|
82
|
+
assert_equal(true, entry.eof?)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
Minitar::Reader.new(StringIO.new(str)) do |is|
|
86
|
+
is.each_entry do |entry|
|
87
|
+
assert_kind_of(Minitar::Reader::EntryStream, entry)
|
88
|
+
data = entry.read(100)
|
89
|
+
(entry.size - data.size).times { data << entry.getc.chr }
|
90
|
+
assert_equal(contents, data)
|
91
|
+
assert_equal(nil, entry.read(10))
|
92
|
+
assert_equal(true, entry.eof?)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
Minitar::Reader.new(StringIO.new(str)) do |is|
|
96
|
+
is.each_entry do |entry|
|
97
|
+
assert_kind_of(Minitar::Reader::EntryStream, entry)
|
98
|
+
data = entry.read
|
99
|
+
assert_equal(contents, data)
|
100
|
+
assert_equal(nil, entry.read(10))
|
101
|
+
assert_equal(nil, entry.read)
|
102
|
+
assert_equal(nil, entry.getc)
|
103
|
+
assert_equal(true, entry.eof?)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_eof_works
|
109
|
+
str = tar_file_header('bar', 'baz', 0o644, 0)
|
110
|
+
Minitar::Reader.new(StringIO.new(str)) do |is|
|
111
|
+
is.each_entry do |entry|
|
112
|
+
assert_kind_of(Minitar::Reader::EntryStream, entry)
|
113
|
+
data = entry.read
|
114
|
+
assert_equal(nil, data)
|
115
|
+
assert_equal(nil, entry.read(10))
|
116
|
+
assert_equal(nil, entry.read)
|
117
|
+
assert_equal(nil, entry.getc)
|
118
|
+
assert_equal(true, entry.eof?)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
str = tar_dir_header('foo', 'bar', 0o12345)
|
122
|
+
Minitar::Reader.new(StringIO.new(str)) do |is|
|
123
|
+
is.each_entry do |entry|
|
124
|
+
assert_kind_of(Minitar::Reader::EntryStream, entry)
|
125
|
+
data = entry.read
|
126
|
+
assert_equal(nil, data)
|
127
|
+
assert_equal(nil, entry.read(10))
|
128
|
+
assert_equal(nil, entry.read)
|
129
|
+
assert_equal(nil, entry.getc)
|
130
|
+
assert_equal(true, entry.eof?)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
str = tar_dir_header('foo', 'bar', 0o12345)
|
134
|
+
str += tar_file_header('bar', 'baz', 0o644, 0)
|
135
|
+
str += tar_file_header('bar', 'baz', 0o644, 0)
|
136
|
+
Minitar::Reader.new(StringIO.new(str)) do |is|
|
137
|
+
is.each_entry do |entry|
|
138
|
+
assert_kind_of(Minitar::Reader::EntryStream, entry)
|
139
|
+
data = entry.read
|
140
|
+
assert_equal(nil, data)
|
141
|
+
assert_equal(nil, entry.read(10))
|
142
|
+
assert_equal(nil, entry.read)
|
143
|
+
assert_equal(nil, entry.getc)
|
144
|
+
assert_equal(true, entry.eof?)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|