1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
#!/usr/bin/env ruby
require 'minitar'
require 'minitest_helper'
require 'base64'
require 'zlib'
class TestTarInput < Minitest::Test
TEST_TGZ = Base64.decode64(<<-EOS).freeze
H4sIAKJpllQAA0tJLEnUK0ks0kuvYqAVMDAwMDMxUQDR5mbmYNrACMIHA2MjIwUDc3NzEzMz
QxMDAwUDQ2NTczMGBQOauQgJlBYDfQ90SiKQkZmHWx1QWVoaHnMgXlGA00MEyHdzMMzOnBbC
wPz28n2uJgOR44Xrq7tsHc/utNe/9FdihkmH3pZ7+zOTRFREzkzYJ99iHHDn4n0/Wb3E8Ceq
S0uOdSyMMg9Z+WVvX0vJucxs77vrvZf2arWcvHP9wa1Yp9lRnJmC59/P9+43PXum+tj7Ga+8
rtT+u3d941e765Y/bOrnvpv8X6jtz+wKqyk/v3n8P5xlO3l/1dn9q9Zotpy5funw/Of77Y/5
LVltz7ToTl7dXf5ppmf3n9p+PPxz/sz/qjZn9yf9Y4R7I2Ft3tqfPTUMGgMYlEMSpGXmpBrT
2A5Qvjc1xZ3/DTDyv5GJmfFo/qcHCMnILFYAIlA6UDDWU+DlGmgXjYJRMApGwSgYBaNgFIyC
UTAKRsEoGAWjYBSMglEwCkbBKBgFo2AUjIJRMApGwSgYBaNgFIwCUgAAGnyo6wAoAAA=
EOS
FILETIMES = Time.utc(2004).to_i
TEST_CONTENTS = {
'data.tar.gz' => { :size => 210, :mode => 0o644 },
'file3' => { :size => 18, :mode => 0o755 }
}.freeze
TEST_DATA_CONTENTS = {
'data/' => { :size => 0, :mode => 0o755 },
'data/__dir__/' => { :size => 0, :mode => 0o755 },
'data/file1' => { :size => 16, :mode => 0o644 },
'data/file2' => { :size => 16, :mode => 0o644 }
}.freeze
def setup
FileUtils.mkdir_p('data__')
end
def teardown
FileUtils.rm_rf('data__')
end
def test_open_no_block
reader = Zlib::GzipReader.new(StringIO.new(TEST_TGZ))
input = Minitar::Input.open(reader)
refute input.closed?
ensure
input.close
assert input.closed?
end
def test_each_works
reader = Zlib::GzipReader.new(StringIO.new(TEST_TGZ))
Minitar::Input.open(reader) do |stream|
outer = 0
stream.each.with_index do |entry, i|
assert_kind_of(Minitar::Reader::EntryStream, entry)
assert TEST_CONTENTS.key?(entry.name)
assert_equal(TEST_CONTENTS[entry.name][:size], entry.size, entry.name)
assert_modes_equal(TEST_CONTENTS[entry.name][:mode],
entry.mode, entry.name)
assert_equal(FILETIMES, entry.mtime, 'entry.mtime')
if i.zero?
data_reader = Zlib::GzipReader.new(StringIO.new(entry.read))
Minitar::Input.open(data_reader) do |is2|
inner = 0
is2.each_with_index do |entry2, _j|
assert_kind_of(Minitar::Reader::EntryStream, entry2)
assert TEST_DATA_CONTENTS.key?(entry2.name)
assert_equal(TEST_DATA_CONTENTS[entry2.name][:size], entry2.size,
entry2.name)
assert_modes_equal(TEST_DATA_CONTENTS[entry2.name][:mode],
entry2.mode, entry2.name)
assert_equal(FILETIMES, entry2.mtime, entry2.name)
inner += 1
end
assert_equal(4, inner)
end
end
outer += 1
end
assert_equal(2, outer)
end
end
def test_extract_entry_works
reader = Zlib::GzipReader.new(StringIO.new(TEST_TGZ))
Minitar::Input.open(reader) do |stream|
outer_count = 0
stream.each_with_index do |entry, i|
stream.extract_entry('data__', entry)
name = File.join('data__', entry.name)
assert TEST_CONTENTS.key?(entry.name)
if entry.directory?
assert(File.directory?(name))
else
assert(File.file?(name))
assert_equal(TEST_CONTENTS[entry.name][:size], File.stat(name).size)
end
assert_modes_equal(TEST_CONTENTS[entry.name][:mode],
File.stat(name).mode, entry.name)
if i.zero?
begin
ff = File.open(name, 'rb')
data_reader = Zlib::GzipReader.new(ff)
Minitar::Input.open(data_reader) do |is2|
is2.each_with_index do |entry2, _j|
is2.extract_entry('data__', entry2)
name2 = File.join('data__', entry2.name)
assert TEST_DATA_CONTENTS.key?(entry2.name)
if entry2.directory?
assert(File.directory?(name2))
else
assert(File.file?(name2))
assert_equal(TEST_DATA_CONTENTS[entry2.name][:size],
File.stat(name2).size)
end
assert_modes_equal(TEST_DATA_CONTENTS[entry2.name][:mode],
File.stat(name2).mode, name2)
end
end
ensure
ff.close unless ff.closed?
end
end
outer_count += 1
end
assert_equal(2, outer_count)
end
end
def test_extract_entry_breaks_symlinks
return if Minitar.windows?
IO.respond_to?(:write) &&
IO.write('data__/file4', '') ||
File.open('data__/file4', 'w') { |f| f.write '' }
File.symlink('data__/file4', 'data__/file3')
File.symlink('data__/file4', 'data__/data')
Minitar.unpack(Zlib::GzipReader.new(StringIO.new(TEST_TGZ)), 'data__')
Minitar.unpack(Zlib::GzipReader.new(File.open('data__/data.tar.gz', 'rb')),
'data__')
refute File.symlink?('data__/file3')
refute File.symlink?('data__/data')
end
RELATIVE_DIRECTORY_TGZ = Base64.decode64 <<-EOS
H4sICIIoKVgCA2JhZC1kaXIudGFyANPT0y8sTy0qqWSgHTAwMDAzMVEA0eZmpmDawAjChwEFQ2MDQyMg
MDUzVDAwNDY0N2VQMGCgAygtLkksAjolEcjIzMOtDqgsLQ2/J0H+gNOjYBSMglEwyAEA2LchrwAGAAA=
EOS
def test_extract_entry_fails_with_relative_directory
reader = Zlib::GzipReader.new(StringIO.new(RELATIVE_DIRECTORY_TGZ))
Minitar::Input.open(reader) do |stream|
stream.each do |entry|
assert_raises Archive::Tar::Minitar::SecureRelativePathError do
stream.extract_entry('data__', entry)
end
end
end
end
NON_STRICT_OCTAL_TGZ = Base64.decode64(<<-EOS).freeze
H4sIAEk55FsAA0tJLEnUK0ks0kuvYqAVMDAwMDMxUQDR5mbmYNrACMjX0zMH
AzMDUwUDIG1iZmZoYmCgYGBobGpuxqBgQDMXIYHSYqDvgU5KBDIy83CrAypL
S8NjjgEYKMDpIQLkuzkYZmdOC2Fgfnv5PleTgcjxwvXVXbaOZ3fa61/6KzHD
pENvy739mUkiKiJnJuyTbzEOuHPxvp+sXmL4E9WlJcc6FkaZh6z8srevpeRc
Zrb33fXeS3u1Wk7euf7gVqzT7CjOTMHz7+d795uePVN97P2MV15Xav/du77x
q911yx829XPfTf4v1PZndoXVlJ/fPP4fzrKdvL/q7P5VazRbzly/dHj+8/32
x/yWrLZnWnQnr+4u/zTTs/tPbT8e/jl/5n9Vm7P7k/4xwr2RsDZv7c+eGgaN
AQzKIQnSMnNSjWlsByjfm5pi5n8DGDAyQsv/RiZmxqP5nx4gJCOzWAGIQOlA
wVhPgZdroF00CkbBKBgFo2AUjIJRMApGwSgYBaNgFIyCUTAKRsEoGAWjYBSM
glEwCkbBKBgFo2AUjIJRMApIAQD0DyzXACgAAA==
EOS
def test_extract_with_non_strict_octal
reader = Zlib::GzipReader.new(StringIO.new(NON_STRICT_OCTAL_TGZ))
assert_raises(ArgumentError) do
Minitar.unpack(reader, 'data__')
end
end
OCTAL_WRAPPED_BY_SPACE_TGZ = Base64.decode64(<<-EOS).freeze
H4sIAOQg5FsAA0tJLEnUK0ks0kuvYqAVMDAwMDMxUQDR5mbmYNrACMhXgAJj
IyMFA3NzcxMzM0MTAwMFA0NjU3MzBgUDmrkICZQWA30PdFIikJGZh1sdUFla
Gh5zDMBAAU4PESDfzcEwO3NaCAPz28v3uZoMRI4Xrq/usnU8u9Ne/9JfiRkm
HXpb7u3PTBJRETkzYZ98i3HAnYv3/WT1EsOfqC4tOdaxMMo8ZOWXvX0tJecy
s73vrvde2qvVcvLO9Qe3Yp1mR3FmCp5/P9+73/Tsmepj72e88rpS++/e9Y1f
7a5b/rCpn/tu8n+htj+zK6ym/Pzm8f9wlu3k/VVn969ao9ly5vqlw/Of77c/
5rdktT3Tojt5dXf5p5me3X9q+/Hwz/kz/6vanN2f9I8R7o2EtXlrf/bUMGgM
YFAOSZCWmZNqTGM7QPne1BQz/xvAAEb+NzIxMx7N//QAIRmZxQpABEoHCsZ6
CrxcA+2iUTAKRsEoGAWjYBSMglEwCkbBKBgFo2AUjIJRMApGwSgYBaNgFIyC
UTAKRsEoGAWjYBSMglFACgAAuUHUvwAoAAA=
EOS
def test_extract_octal_wrapped_by_space
reader = Zlib::GzipReader.new(StringIO.new(OCTAL_WRAPPED_BY_SPACE_TGZ))
header = Archive::Tar::Minitar::PosixHeader.from_stream(reader)
assert_equal(210, header.size)
reader = Zlib::GzipReader.new(StringIO.new(OCTAL_WRAPPED_BY_SPACE_TGZ))
Minitar.unpack(reader, 'data__', [])
end
def test_fsync_false
outer = 0
Minitar.unpack(Zlib::GzipReader.new(StringIO.new(TEST_TGZ)), 'data__', [], :fsync => false) do |_label, _path, _stats|
outer += 1
end
assert_equal(6, outer)
end
end
|