blob: 01d1a922ee69cab7264665aafc5186d404754267 [file] [log] [blame]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001import sys
2import os
Lars Gustäbelb506dc32007-08-07 18:36:16 +00003import io
Guido van Rossuma8add0e2007-05-14 22:03:55 +00004from hashlib import md5
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00005
6import unittest
7import tarfile
8
Serhiy Storchakad27b4552013-11-24 01:53:29 +02009from test import support, script_helper
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000010
11# Check for our compression modules.
12try:
13 import gzip
Brett Cannon260fbe82013-07-04 18:16:15 -040014except ImportError:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000015 gzip = None
16try:
17 import bz2
Brett Cannon260fbe82013-07-04 18:16:15 -040018except ImportError:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000019 bz2 = None
Lars Gustäbel0a9dd2f2011-12-10 20:38:14 +010020try:
21 import lzma
Brett Cannon260fbe82013-07-04 18:16:15 -040022except ImportError:
Lars Gustäbel0a9dd2f2011-12-10 20:38:14 +010023 lzma = None
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000024
Guido van Rossumd8faa362007-04-27 19:54:29 +000025def md5sum(data):
Guido van Rossuma8add0e2007-05-14 22:03:55 +000026 return md5(data).hexdigest()
Guido van Rossumd8faa362007-04-27 19:54:29 +000027
Antoine Pitrouab58b5f2010-09-23 19:39:35 +000028TEMPDIR = os.path.abspath(support.TESTFN) + "-tardir"
Serhiy Storchakad27b4552013-11-24 01:53:29 +020029tarextdir = TEMPDIR + '-extract-test'
Antoine Pitrou941ee882009-11-11 20:59:38 +000030tarname = support.findfile("testtar.tar")
Guido van Rossumd8faa362007-04-27 19:54:29 +000031gzipname = os.path.join(TEMPDIR, "testtar.tar.gz")
32bz2name = os.path.join(TEMPDIR, "testtar.tar.bz2")
Lars Gustäbel0a9dd2f2011-12-10 20:38:14 +010033xzname = os.path.join(TEMPDIR, "testtar.tar.xz")
Guido van Rossumd8faa362007-04-27 19:54:29 +000034tmpname = os.path.join(TEMPDIR, "tmp.tar")
Serhiy Storchakad27b4552013-11-24 01:53:29 +020035dotlessname = os.path.join(TEMPDIR, "testtar")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000036
Guido van Rossumd8faa362007-04-27 19:54:29 +000037md5_regtype = "65f477c818ad9e15f7feab0c6d37742f"
38md5_sparse = "a54fbc4ca4f4399a90e1b27164012fc6"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000039
40
Serhiy Storchaka8b562922013-06-17 15:38:50 +030041class TarTest:
Guido van Rossumd8faa362007-04-27 19:54:29 +000042 tarname = tarname
Serhiy Storchaka8b562922013-06-17 15:38:50 +030043 suffix = ''
44 open = io.FileIO
Serhiy Storchaka53ad0cd2014-01-18 15:35:37 +020045 taropen = tarfile.TarFile.taropen
Serhiy Storchaka8b562922013-06-17 15:38:50 +030046
47 @property
48 def mode(self):
49 return self.prefix + self.suffix
50
51@support.requires_gzip
52class GzipTest:
53 tarname = gzipname
54 suffix = 'gz'
55 open = gzip.GzipFile if gzip else None
Serhiy Storchaka53ad0cd2014-01-18 15:35:37 +020056 taropen = tarfile.TarFile.gzopen
Serhiy Storchaka8b562922013-06-17 15:38:50 +030057
58@support.requires_bz2
59class Bz2Test:
60 tarname = bz2name
61 suffix = 'bz2'
62 open = bz2.BZ2File if bz2 else None
Serhiy Storchaka53ad0cd2014-01-18 15:35:37 +020063 taropen = tarfile.TarFile.bz2open
Serhiy Storchaka8b562922013-06-17 15:38:50 +030064
65@support.requires_lzma
66class LzmaTest:
67 tarname = xzname
68 suffix = 'xz'
69 open = lzma.LZMAFile if lzma else None
Serhiy Storchaka53ad0cd2014-01-18 15:35:37 +020070 taropen = tarfile.TarFile.xzopen
Serhiy Storchaka8b562922013-06-17 15:38:50 +030071
72
73class ReadTest(TarTest):
74
75 prefix = "r:"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000076
77 def setUp(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +030078 self.tar = tarfile.open(self.tarname, mode=self.mode,
79 encoding="iso8859-1")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000080
81 def tearDown(self):
82 self.tar.close()
83
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000084
Serhiy Storchaka8b562922013-06-17 15:38:50 +030085class UstarReadTest(ReadTest, unittest.TestCase):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000086
Guido van Rossumd8faa362007-04-27 19:54:29 +000087 def test_fileobj_regular_file(self):
88 tarinfo = self.tar.getmember("ustar/regtype")
Lars Gustäbel7a919e92012-05-05 18:15:03 +020089 with self.tar.extractfile(tarinfo) as fobj:
Antoine Pitroue1eca4e2010-10-29 23:49:49 +000090 data = fobj.read()
Serhiy Storchaka8b562922013-06-17 15:38:50 +030091 self.assertEqual(len(data), tarinfo.size,
92 "regular file extraction failed")
93 self.assertEqual(md5sum(data), md5_regtype,
Antoine Pitroue1eca4e2010-10-29 23:49:49 +000094 "regular file extraction failed")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000095
Guido van Rossumd8faa362007-04-27 19:54:29 +000096 def test_fileobj_readlines(self):
97 self.tar.extract("ustar/regtype", TEMPDIR)
98 tarinfo = self.tar.getmember("ustar/regtype")
Antoine Pitrou95f55602010-09-23 18:36:46 +000099 with open(os.path.join(TEMPDIR, "ustar/regtype"), "r") as fobj1:
100 lines1 = fobj1.readlines()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000101
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200102 with self.tar.extractfile(tarinfo) as fobj:
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000103 fobj2 = io.TextIOWrapper(fobj)
104 lines2 = fobj2.readlines()
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300105 self.assertEqual(lines1, lines2,
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000106 "fileobj.readlines() failed")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300107 self.assertEqual(len(lines2), 114,
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000108 "fileobj.readlines() failed")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300109 self.assertEqual(lines2[83],
110 "I will gladly admit that Python is not the fastest "
111 "running scripting language.\n",
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000112 "fileobj.readlines() failed")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000113
Guido van Rossumd8faa362007-04-27 19:54:29 +0000114 def test_fileobj_iter(self):
115 self.tar.extract("ustar/regtype", TEMPDIR)
116 tarinfo = self.tar.getmember("ustar/regtype")
Victor Stinner4e86d5b2011-05-04 13:55:36 +0200117 with open(os.path.join(TEMPDIR, "ustar/regtype"), "r") as fobj1:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000118 lines1 = fobj1.readlines()
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200119 with self.tar.extractfile(tarinfo) as fobj2:
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000120 lines2 = list(io.TextIOWrapper(fobj2))
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300121 self.assertEqual(lines1, lines2,
122 "fileobj.__iter__() failed")
Martin v. Löwisdf241532005-03-03 08:17:42 +0000123
Guido van Rossumd8faa362007-04-27 19:54:29 +0000124 def test_fileobj_seek(self):
125 self.tar.extract("ustar/regtype", TEMPDIR)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000126 with open(os.path.join(TEMPDIR, "ustar/regtype"), "rb") as fobj:
127 data = fobj.read()
Neal Norwitzf3396542005-10-28 05:52:22 +0000128
Guido van Rossumd8faa362007-04-27 19:54:29 +0000129 tarinfo = self.tar.getmember("ustar/regtype")
130 fobj = self.tar.extractfile(tarinfo)
131
132 text = fobj.read()
133 fobj.seek(0)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000134 self.assertEqual(0, fobj.tell(),
Guido van Rossumd8faa362007-04-27 19:54:29 +0000135 "seek() to file's start failed")
136 fobj.seek(2048, 0)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000137 self.assertEqual(2048, fobj.tell(),
Guido van Rossumd8faa362007-04-27 19:54:29 +0000138 "seek() to absolute position failed")
139 fobj.seek(-1024, 1)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000140 self.assertEqual(1024, fobj.tell(),
Guido van Rossumd8faa362007-04-27 19:54:29 +0000141 "seek() to negative relative position failed")
142 fobj.seek(1024, 1)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000143 self.assertEqual(2048, fobj.tell(),
Guido van Rossumd8faa362007-04-27 19:54:29 +0000144 "seek() to positive relative position failed")
145 s = fobj.read(10)
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300146 self.assertEqual(s, data[2048:2058],
Guido van Rossumd8faa362007-04-27 19:54:29 +0000147 "read() after seek failed")
148 fobj.seek(0, 2)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000149 self.assertEqual(tarinfo.size, fobj.tell(),
Guido van Rossumd8faa362007-04-27 19:54:29 +0000150 "seek() to file's end failed")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300151 self.assertEqual(fobj.read(), b"",
Guido van Rossumd8faa362007-04-27 19:54:29 +0000152 "read() at file's end did not return empty string")
153 fobj.seek(-tarinfo.size, 2)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000154 self.assertEqual(0, fobj.tell(),
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000155 "relative seek() to file's end failed")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000156 fobj.seek(512)
157 s1 = fobj.readlines()
158 fobj.seek(512)
159 s2 = fobj.readlines()
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300160 self.assertEqual(s1, s2,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000161 "readlines() after seek failed")
162 fobj.seek(0)
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000163 self.assertEqual(len(fobj.readline()), fobj.tell(),
Guido van Rossumd8faa362007-04-27 19:54:29 +0000164 "tell() after readline() failed")
165 fobj.seek(512)
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300166 self.assertEqual(len(fobj.readline()) + 512, fobj.tell(),
Guido van Rossumd8faa362007-04-27 19:54:29 +0000167 "tell() after seek() and readline() failed")
168 fobj.seek(0)
169 line = fobj.readline()
Guido van Rossume61fd5b2007-07-11 12:20:59 +0000170 self.assertEqual(fobj.read(), data[len(line):],
Guido van Rossumd8faa362007-04-27 19:54:29 +0000171 "read() after readline() failed")
172 fobj.close()
173
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200174 def test_fileobj_text(self):
175 with self.tar.extractfile("ustar/regtype") as fobj:
176 fobj = io.TextIOWrapper(fobj)
177 data = fobj.read().encode("iso8859-1")
178 self.assertEqual(md5sum(data), md5_regtype)
179 try:
180 fobj.seek(100)
181 except AttributeError:
182 # Issue #13815: seek() complained about a missing
183 # flush() method.
184 self.fail("seeking failed in text mode")
185
Lars Gustäbel1b512722010-06-03 12:45:16 +0000186 # Test if symbolic and hard links are resolved by extractfile(). The
187 # test link members each point to a regular member whose data is
188 # supposed to be exported.
189 def _test_fileobj_link(self, lnktype, regtype):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300190 with self.tar.extractfile(lnktype) as a, \
191 self.tar.extractfile(regtype) as b:
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000192 self.assertEqual(a.name, b.name)
Lars Gustäbel1b512722010-06-03 12:45:16 +0000193
194 def test_fileobj_link1(self):
195 self._test_fileobj_link("ustar/lnktype", "ustar/regtype")
196
197 def test_fileobj_link2(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300198 self._test_fileobj_link("./ustar/linktest2/lnktype",
199 "ustar/linktest1/regtype")
Lars Gustäbel1b512722010-06-03 12:45:16 +0000200
201 def test_fileobj_symlink1(self):
202 self._test_fileobj_link("ustar/symtype", "ustar/regtype")
203
204 def test_fileobj_symlink2(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300205 self._test_fileobj_link("./ustar/linktest2/symtype",
206 "ustar/linktest1/regtype")
Lars Gustäbel1b512722010-06-03 12:45:16 +0000207
Lars Gustäbel1ef9eda2012-04-24 21:04:40 +0200208 def test_issue14160(self):
209 self._test_fileobj_link("symtype2", "ustar/regtype")
210
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300211class GzipUstarReadTest(GzipTest, UstarReadTest):
212 pass
213
214class Bz2UstarReadTest(Bz2Test, UstarReadTest):
215 pass
216
217class LzmaUstarReadTest(LzmaTest, UstarReadTest):
218 pass
219
Guido van Rossumd8faa362007-04-27 19:54:29 +0000220
Serhiy Storchaka3b4f1592014-02-05 20:53:36 +0200221class ListTest(ReadTest, unittest.TestCase):
222
223 # Override setUp to use default encoding (UTF-8)
224 def setUp(self):
225 self.tar = tarfile.open(self.tarname, mode=self.mode)
226
227 def test_list(self):
228 tio = io.TextIOWrapper(io.BytesIO(), 'ascii', newline='\n')
229 with support.swap_attr(sys, 'stdout', tio):
230 self.tar.list(verbose=False)
231 out = tio.detach().getvalue()
232 self.assertIn(b'ustar/conttype', out)
233 self.assertIn(b'ustar/regtype', out)
234 self.assertIn(b'ustar/lnktype', out)
235 self.assertIn(b'ustar' + (b'/12345' * 40) + b'67/longname', out)
236 self.assertIn(b'./ustar/linktest2/symtype', out)
237 self.assertIn(b'./ustar/linktest2/lnktype', out)
238 # Make sure it puts trailing slash for directory
239 self.assertIn(b'ustar/dirtype/', out)
240 self.assertIn(b'ustar/dirtype-with-size/', out)
241 # Make sure it is able to print unencodable characters
Serhiy Storchaka162c4772014-02-19 18:44:12 +0200242 def conv(b):
243 s = b.decode(self.tar.encoding, 'surrogateescape')
244 return s.encode('ascii', 'backslashreplace')
245 self.assertIn(conv(b'ustar/umlauts-\xc4\xd6\xdc\xe4\xf6\xfc\xdf'), out)
246 self.assertIn(conv(b'misc/regtype-hpux-signed-chksum-'
247 b'\xc4\xd6\xdc\xe4\xf6\xfc\xdf'), out)
248 self.assertIn(conv(b'misc/regtype-old-v7-signed-chksum-'
249 b'\xc4\xd6\xdc\xe4\xf6\xfc\xdf'), out)
250 self.assertIn(conv(b'pax/bad-pax-\xe4\xf6\xfc'), out)
251 self.assertIn(conv(b'pax/hdrcharset-\xe4\xf6\xfc'), out)
Serhiy Storchaka3b4f1592014-02-05 20:53:36 +0200252 # Make sure it prints files separated by one newline without any
253 # 'ls -l'-like accessories if verbose flag is not being used
254 # ...
255 # ustar/conttype
256 # ustar/regtype
257 # ...
258 self.assertRegex(out, br'ustar/conttype ?\r?\n'
259 br'ustar/regtype ?\r?\n')
260 # Make sure it does not print the source of link without verbose flag
261 self.assertNotIn(b'link to', out)
262 self.assertNotIn(b'->', out)
263
264 def test_list_verbose(self):
265 tio = io.TextIOWrapper(io.BytesIO(), 'ascii', newline='\n')
266 with support.swap_attr(sys, 'stdout', tio):
267 self.tar.list(verbose=True)
268 out = tio.detach().getvalue()
269 # Make sure it prints files separated by one newline with 'ls -l'-like
270 # accessories if verbose flag is being used
271 # ...
272 # ?rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/conttype
273 # ?rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/regtype
274 # ...
Serhiy Storchaka255493c2014-02-05 20:54:43 +0200275 self.assertRegex(out, (br'\?rw-r--r-- tarfile/tarfile\s+7011 '
Serhiy Storchaka3b4f1592014-02-05 20:53:36 +0200276 br'\d{4}-\d\d-\d\d\s+\d\d:\d\d:\d\d '
277 br'ustar/\w+type ?\r?\n') * 2)
278 # Make sure it prints the source of link with verbose flag
279 self.assertIn(b'ustar/symtype -> regtype', out)
280 self.assertIn(b'./ustar/linktest2/symtype -> ../linktest1/regtype', out)
281 self.assertIn(b'./ustar/linktest2/lnktype link to '
282 b'./ustar/linktest1/regtype', out)
283 self.assertIn(b'gnu' + (b'/123' * 125) + b'/longlink link to gnu' +
284 (b'/123' * 125) + b'/longname', out)
285 self.assertIn(b'pax' + (b'/123' * 125) + b'/longlink link to pax' +
286 (b'/123' * 125) + b'/longname', out)
287
Serhiy Storchakaa7eb7462014-08-21 10:01:16 +0300288 def test_list_members(self):
289 tio = io.TextIOWrapper(io.BytesIO(), 'ascii', newline='\n')
290 def members(tar):
291 for tarinfo in tar.getmembers():
292 if 'reg' in tarinfo.name:
293 yield tarinfo
294 with support.swap_attr(sys, 'stdout', tio):
295 self.tar.list(verbose=False, members=members(self.tar))
296 out = tio.detach().getvalue()
297 self.assertIn(b'ustar/regtype', out)
298 self.assertNotIn(b'ustar/conttype', out)
299
Serhiy Storchaka3b4f1592014-02-05 20:53:36 +0200300
301class GzipListTest(GzipTest, ListTest):
302 pass
303
304
305class Bz2ListTest(Bz2Test, ListTest):
306 pass
307
308
309class LzmaListTest(LzmaTest, ListTest):
310 pass
311
312
Lars Gustäbel9520a432009-11-22 18:48:49 +0000313class CommonReadTest(ReadTest):
314
315 def test_empty_tarfile(self):
316 # Test for issue6123: Allow opening empty archives.
317 # This test checks if tarfile.open() is able to open an empty tar
318 # archive successfully. Note that an empty tar archive is not the
319 # same as an empty file!
Antoine Pitrou95f55602010-09-23 18:36:46 +0000320 with tarfile.open(tmpname, self.mode.replace("r", "w")):
321 pass
Lars Gustäbel9520a432009-11-22 18:48:49 +0000322 try:
323 tar = tarfile.open(tmpname, self.mode)
324 tar.getnames()
325 except tarfile.ReadError:
326 self.fail("tarfile.open() failed on empty archive")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000327 else:
328 self.assertListEqual(tar.getmembers(), [])
329 finally:
330 tar.close()
Lars Gustäbel9520a432009-11-22 18:48:49 +0000331
Serhiy Storchakaf22fe0f2014-01-13 19:08:00 +0200332 def test_non_existent_tarfile(self):
333 # Test for issue11513: prevent non-existent gzipped tarfiles raising
334 # multiple exceptions.
335 with self.assertRaisesRegex(FileNotFoundError, "xxx"):
336 tarfile.open("xxx", self.mode)
337
Lars Gustäbel9520a432009-11-22 18:48:49 +0000338 def test_null_tarfile(self):
339 # Test for issue6123: Allow opening empty archives.
340 # This test guarantees that tarfile.open() does not treat an empty
341 # file as an empty tar archive.
Antoine Pitrou95f55602010-09-23 18:36:46 +0000342 with open(tmpname, "wb"):
343 pass
Lars Gustäbel9520a432009-11-22 18:48:49 +0000344 self.assertRaises(tarfile.ReadError, tarfile.open, tmpname, self.mode)
345 self.assertRaises(tarfile.ReadError, tarfile.open, tmpname)
346
347 def test_ignore_zeros(self):
348 # Test TarFile's ignore_zeros option.
Lars Gustäbel9520a432009-11-22 18:48:49 +0000349 for char in (b'\0', b'a'):
350 # Test if EOFHeaderError ('\0') and InvalidHeaderError ('a')
351 # are ignored correctly.
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300352 with self.open(tmpname, "w") as fobj:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000353 fobj.write(char * 1024)
354 fobj.write(tarfile.TarInfo("foo").tobuf())
Lars Gustäbel9520a432009-11-22 18:48:49 +0000355
356 tar = tarfile.open(tmpname, mode="r", ignore_zeros=True)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000357 try:
358 self.assertListEqual(tar.getnames(), ["foo"],
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300359 "ignore_zeros=True should have skipped the %r-blocks" %
360 char)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000361 finally:
362 tar.close()
Lars Gustäbel9520a432009-11-22 18:48:49 +0000363
364
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300365class MiscReadTestBase(CommonReadTest):
Serhiy Storchaka2c6a3ae2014-07-16 23:58:58 +0300366 def requires_name_attribute(self):
367 pass
368
Thomas Woutersed03b412007-08-28 21:37:11 +0000369 def test_no_name_argument(self):
Serhiy Storchaka2c6a3ae2014-07-16 23:58:58 +0300370 self.requires_name_attribute()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000371 with open(self.tarname, "rb") as fobj:
Serhiy Storchaka2c6a3ae2014-07-16 23:58:58 +0300372 self.assertIsInstance(fobj.name, str)
373 with tarfile.open(fileobj=fobj, mode=self.mode) as tar:
374 self.assertIsInstance(tar.name, str)
375 self.assertEqual(tar.name, os.path.abspath(fobj.name))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000376
Thomas Woutersed03b412007-08-28 21:37:11 +0000377 def test_no_name_attribute(self):
Antoine Pitrou95f55602010-09-23 18:36:46 +0000378 with open(self.tarname, "rb") as fobj:
379 data = fobj.read()
Thomas Woutersed03b412007-08-28 21:37:11 +0000380 fobj = io.BytesIO(data)
381 self.assertRaises(AttributeError, getattr, fobj, "name")
382 tar = tarfile.open(fileobj=fobj, mode=self.mode)
Serhiy Storchaka2c6a3ae2014-07-16 23:58:58 +0300383 self.assertIsNone(tar.name)
Thomas Woutersed03b412007-08-28 21:37:11 +0000384
385 def test_empty_name_attribute(self):
Antoine Pitrou95f55602010-09-23 18:36:46 +0000386 with open(self.tarname, "rb") as fobj:
387 data = fobj.read()
Thomas Woutersed03b412007-08-28 21:37:11 +0000388 fobj = io.BytesIO(data)
389 fobj.name = ""
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000390 with tarfile.open(fileobj=fobj, mode=self.mode) as tar:
Serhiy Storchaka2c6a3ae2014-07-16 23:58:58 +0300391 self.assertIsNone(tar.name)
392
393 def test_int_name_attribute(self):
394 # Issue 21044: tarfile.open() should handle fileobj with an integer
395 # 'name' attribute.
396 fd = os.open(self.tarname, os.O_RDONLY)
397 with open(fd, 'rb') as fobj:
398 self.assertIsInstance(fobj.name, int)
399 with tarfile.open(fileobj=fobj, mode=self.mode) as tar:
400 self.assertIsNone(tar.name)
401
402 def test_bytes_name_attribute(self):
403 self.requires_name_attribute()
404 tarname = os.fsencode(self.tarname)
405 with open(tarname, 'rb') as fobj:
406 self.assertIsInstance(fobj.name, bytes)
407 with tarfile.open(fileobj=fobj, mode=self.mode) as tar:
408 self.assertIsInstance(tar.name, bytes)
409 self.assertEqual(tar.name, os.path.abspath(fobj.name))
Thomas Woutersed03b412007-08-28 21:37:11 +0000410
Serhiy Storchaka53ad0cd2014-01-18 15:35:37 +0200411 def test_illegal_mode_arg(self):
412 with open(tmpname, 'wb'):
413 pass
414 with self.assertRaisesRegex(ValueError, 'mode must be '):
415 tar = self.taropen(tmpname, 'q')
416 with self.assertRaisesRegex(ValueError, 'mode must be '):
417 tar = self.taropen(tmpname, 'rw')
418 with self.assertRaisesRegex(ValueError, 'mode must be '):
419 tar = self.taropen(tmpname, '')
420
Christian Heimesd8654cf2007-12-02 15:22:16 +0000421 def test_fileobj_with_offset(self):
422 # Skip the first member and store values from the second member
423 # of the testtar.
424 tar = tarfile.open(self.tarname, mode=self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000425 try:
426 tar.next()
427 t = tar.next()
428 name = t.name
429 offset = t.offset
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200430 with tar.extractfile(t) as f:
431 data = f.read()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000432 finally:
433 tar.close()
Christian Heimesd8654cf2007-12-02 15:22:16 +0000434
435 # Open the testtar and seek to the offset of the second member.
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300436 with self.open(self.tarname) as fobj:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000437 fobj.seek(offset)
Christian Heimesd8654cf2007-12-02 15:22:16 +0000438
Antoine Pitrou95f55602010-09-23 18:36:46 +0000439 # Test if the tarfile starts with the second member.
440 tar = tar.open(self.tarname, mode="r:", fileobj=fobj)
441 t = tar.next()
442 self.assertEqual(t.name, name)
443 # Read to the end of fileobj and test if seeking back to the
444 # beginning works.
445 tar.getmembers()
446 self.assertEqual(tar.extractfile(t).read(), data,
447 "seek back did not work")
448 tar.close()
Christian Heimesd8654cf2007-12-02 15:22:16 +0000449
Guido van Rossumd8faa362007-04-27 19:54:29 +0000450 def test_fail_comp(self):
451 # For Gzip and Bz2 Tests: fail with a ReadError on an uncompressed file.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000452 self.assertRaises(tarfile.ReadError, tarfile.open, tarname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000453 with open(tarname, "rb") as fobj:
454 self.assertRaises(tarfile.ReadError, tarfile.open,
455 fileobj=fobj, mode=self.mode)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000456
457 def test_v7_dirtype(self):
458 # Test old style dirtype member (bug #1336623):
459 # Old V7 tars create directory members using an AREGTYPE
460 # header with a "/" appended to the filename field.
461 tarinfo = self.tar.getmember("misc/dirtype-old-v7")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300462 self.assertEqual(tarinfo.type, tarfile.DIRTYPE,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000463 "v7 dirtype failed")
464
Christian Heimes126d29a2008-02-11 22:57:17 +0000465 def test_xstar_type(self):
466 # The xstar format stores extra atime and ctime fields inside the
467 # space reserved for the prefix field. The prefix field must be
468 # ignored in this case, otherwise it will mess up the name.
469 try:
470 self.tar.getmember("misc/regtype-xstar")
471 except KeyError:
472 self.fail("failed to find misc/regtype-xstar (mangled prefix?)")
473
Guido van Rossumd8faa362007-04-27 19:54:29 +0000474 def test_check_members(self):
475 for tarinfo in self.tar:
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300476 self.assertEqual(int(tarinfo.mtime), 0o7606136617,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000477 "wrong mtime for %s" % tarinfo.name)
478 if not tarinfo.name.startswith("ustar/"):
479 continue
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300480 self.assertEqual(tarinfo.uname, "tarfile",
Guido van Rossumd8faa362007-04-27 19:54:29 +0000481 "wrong uname for %s" % tarinfo.name)
482
483 def test_find_members(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300484 self.assertEqual(self.tar.getmembers()[-1].name, "misc/eof",
Guido van Rossumd8faa362007-04-27 19:54:29 +0000485 "could not find all members")
486
Brian Curtin74e45612010-07-09 15:58:59 +0000487 @unittest.skipUnless(hasattr(os, "link"),
488 "Missing hardlink implementation")
Brian Curtin3b4499c2010-12-28 14:31:47 +0000489 @support.skip_unless_symlink
Guido van Rossumd8faa362007-04-27 19:54:29 +0000490 def test_extract_hardlink(self):
491 # Test hardlink extraction (e.g. bug #857297).
Serhiy Storchaka88339c42012-12-30 20:16:30 +0200492 with tarfile.open(tarname, errorlevel=1, encoding="iso8859-1") as tar:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000493 tar.extract("ustar/regtype", TEMPDIR)
Tim Goldene0bd2c52014-05-06 13:24:26 +0100494 self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/regtype"))
Neal Norwitzf3396542005-10-28 05:52:22 +0000495
Serhiy Storchaka88339c42012-12-30 20:16:30 +0200496 tar.extract("ustar/lnktype", TEMPDIR)
Tim Goldene0bd2c52014-05-06 13:24:26 +0100497 self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/lnktype"))
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000498 with open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb") as f:
499 data = f.read()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000500 self.assertEqual(md5sum(data), md5_regtype)
Neal Norwitzf3396542005-10-28 05:52:22 +0000501
Serhiy Storchaka88339c42012-12-30 20:16:30 +0200502 tar.extract("ustar/symtype", TEMPDIR)
Tim Goldene0bd2c52014-05-06 13:24:26 +0100503 self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/symtype"))
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000504 with open(os.path.join(TEMPDIR, "ustar/symtype"), "rb") as f:
505 data = f.read()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000506 self.assertEqual(md5sum(data), md5_regtype)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000507
Christian Heimesfaf2f632008-01-06 16:59:19 +0000508 def test_extractall(self):
509 # Test if extractall() correctly restores directory permissions
510 # and times (see issue1735).
Christian Heimesfaf2f632008-01-06 16:59:19 +0000511 tar = tarfile.open(tarname, encoding="iso8859-1")
Martin v. Löwisbe647e22010-11-01 22:08:46 +0000512 DIR = os.path.join(TEMPDIR, "extractall")
513 os.mkdir(DIR)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000514 try:
515 directories = [t for t in tar if t.isdir()]
Martin v. Löwisbe647e22010-11-01 22:08:46 +0000516 tar.extractall(DIR, directories)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000517 for tarinfo in directories:
Martin v. Löwisbe647e22010-11-01 22:08:46 +0000518 path = os.path.join(DIR, tarinfo.name)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000519 if sys.platform != "win32":
520 # Win32 has no support for fine grained permissions.
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300521 self.assertEqual(tarinfo.mode & 0o777,
522 os.stat(path).st_mode & 0o777)
Victor Stinner26bfb5a2010-10-29 10:59:08 +0000523 def format_mtime(mtime):
524 if isinstance(mtime, float):
525 return "{} ({})".format(mtime, mtime.hex())
526 else:
527 return "{!r} (int)".format(mtime)
Victor Stinner14d8fe72010-10-29 11:02:06 +0000528 file_mtime = os.path.getmtime(path)
Victor Stinner26bfb5a2010-10-29 10:59:08 +0000529 errmsg = "tar mtime {0} != file time {1} of path {2!a}".format(
530 format_mtime(tarinfo.mtime),
531 format_mtime(file_mtime),
532 path)
533 self.assertEqual(tarinfo.mtime, file_mtime, errmsg)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000534 finally:
535 tar.close()
Tim Goldene0bd2c52014-05-06 13:24:26 +0100536 support.rmtree(DIR)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000537
Martin v. Löwis16f344d2010-11-01 21:39:13 +0000538 def test_extract_directory(self):
539 dirtype = "ustar/dirtype"
Martin v. Löwisbe647e22010-11-01 22:08:46 +0000540 DIR = os.path.join(TEMPDIR, "extractdir")
541 os.mkdir(DIR)
542 try:
543 with tarfile.open(tarname, encoding="iso8859-1") as tar:
544 tarinfo = tar.getmember(dirtype)
545 tar.extract(tarinfo, path=DIR)
546 extracted = os.path.join(DIR, dirtype)
547 self.assertEqual(os.path.getmtime(extracted), tarinfo.mtime)
548 if sys.platform != "win32":
549 self.assertEqual(os.stat(extracted).st_mode & 0o777, 0o755)
550 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +0100551 support.rmtree(DIR)
Martin v. Löwis16f344d2010-11-01 21:39:13 +0000552
Lars Gustäbelb7f09232009-11-23 15:48:33 +0000553 def test_init_close_fobj(self):
554 # Issue #7341: Close the internal file object in the TarFile
555 # constructor in case of an error. For the test we rely on
556 # the fact that opening an empty file raises a ReadError.
557 empty = os.path.join(TEMPDIR, "empty")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000558 with open(empty, "wb") as fobj:
559 fobj.write(b"")
Lars Gustäbelb7f09232009-11-23 15:48:33 +0000560
561 try:
562 tar = object.__new__(tarfile.TarFile)
563 try:
564 tar.__init__(empty)
565 except tarfile.ReadError:
566 self.assertTrue(tar.fileobj.closed)
567 else:
568 self.fail("ReadError not raised")
569 finally:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000570 support.unlink(empty)
Lars Gustäbelb7f09232009-11-23 15:48:33 +0000571
Serhiy Storchaka263fab92013-05-09 14:22:26 +0300572 def test_parallel_iteration(self):
573 # Issue #16601: Restarting iteration over tarfile continued
574 # from where it left off.
575 with tarfile.open(self.tarname) as tar:
576 for m1, m2 in zip(tar, tar):
577 self.assertEqual(m1.offset, m2.offset)
578 self.assertEqual(m1.get_info(), m2.get_info())
579
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300580class MiscReadTest(MiscReadTestBase, unittest.TestCase):
581 test_fail_comp = None
Guido van Rossumd8faa362007-04-27 19:54:29 +0000582
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300583class GzipMiscReadTest(GzipTest, MiscReadTestBase, unittest.TestCase):
Serhiy Storchakaf22fe0f2014-01-13 19:08:00 +0200584 pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000585
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300586class Bz2MiscReadTest(Bz2Test, MiscReadTestBase, unittest.TestCase):
Serhiy Storchaka2c6a3ae2014-07-16 23:58:58 +0300587 def requires_name_attribute(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300588 self.skipTest("BZ2File have no name attribute")
589
590class LzmaMiscReadTest(LzmaTest, MiscReadTestBase, unittest.TestCase):
Serhiy Storchaka2c6a3ae2014-07-16 23:58:58 +0300591 def requires_name_attribute(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300592 self.skipTest("LZMAFile have no name attribute")
593
594
595class StreamReadTest(CommonReadTest, unittest.TestCase):
596
597 prefix="r|"
Guido van Rossumd8faa362007-04-27 19:54:29 +0000598
Lars Gustäbeldd071042011-02-23 11:42:22 +0000599 def test_read_through(self):
600 # Issue #11224: A poorly designed _FileInFile.read() method
601 # caused seeking errors with stream tar files.
602 for tarinfo in self.tar:
603 if not tarinfo.isreg():
604 continue
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200605 with self.tar.extractfile(tarinfo) as fobj:
606 while True:
607 try:
608 buf = fobj.read(512)
609 except tarfile.StreamError:
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300610 self.fail("simple read-through using "
611 "TarFile.extractfile() failed")
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200612 if not buf:
613 break
Lars Gustäbeldd071042011-02-23 11:42:22 +0000614
Guido van Rossumd8faa362007-04-27 19:54:29 +0000615 def test_fileobj_regular_file(self):
616 tarinfo = self.tar.next() # get "regtype" (can't use getmember)
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200617 with self.tar.extractfile(tarinfo) as fobj:
618 data = fobj.read()
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300619 self.assertEqual(len(data), tarinfo.size,
620 "regular file extraction failed")
621 self.assertEqual(md5sum(data), md5_regtype,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000622 "regular file extraction failed")
623
624 def test_provoke_stream_error(self):
625 tarinfos = self.tar.getmembers()
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200626 with self.tar.extractfile(tarinfos[0]) as f: # read the first member
627 self.assertRaises(tarfile.StreamError, f.read)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000628
Guido van Rossumd8faa362007-04-27 19:54:29 +0000629 def test_compare_members(self):
630 tar1 = tarfile.open(tarname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000631 try:
632 tar2 = self.tar
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000633
Antoine Pitrou95f55602010-09-23 18:36:46 +0000634 while True:
635 t1 = tar1.next()
636 t2 = tar2.next()
637 if t1 is None:
638 break
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300639 self.assertIsNotNone(t2, "stream.next() failed.")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000640
Antoine Pitrou95f55602010-09-23 18:36:46 +0000641 if t2.islnk() or t2.issym():
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300642 with self.assertRaises(tarfile.StreamError):
643 tar2.extractfile(t2)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000644 continue
Guido van Rossumd8faa362007-04-27 19:54:29 +0000645
Antoine Pitrou95f55602010-09-23 18:36:46 +0000646 v1 = tar1.extractfile(t1)
647 v2 = tar2.extractfile(t2)
648 if v1 is None:
649 continue
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300650 self.assertIsNotNone(v2, "stream.extractfile() failed")
651 self.assertEqual(v1.read(), v2.read(),
652 "stream extraction failed")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000653 finally:
654 tar1.close()
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000655
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300656class GzipStreamReadTest(GzipTest, StreamReadTest):
657 pass
Thomas Wouters89f507f2006-12-13 04:49:30 +0000658
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300659class Bz2StreamReadTest(Bz2Test, StreamReadTest):
660 pass
Thomas Wouterscf297e42007-02-23 15:07:44 +0000661
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300662class LzmaStreamReadTest(LzmaTest, StreamReadTest):
663 pass
664
665
666class DetectReadTest(TarTest, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000667 def _testfunc_file(self, name, mode):
668 try:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000669 tar = tarfile.open(name, mode)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000670 except tarfile.ReadError as e:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000671 self.fail()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000672 else:
673 tar.close()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000674
Guido van Rossumd8faa362007-04-27 19:54:29 +0000675 def _testfunc_fileobj(self, name, mode):
676 try:
Antoine Pitrou605c2932010-09-23 20:15:14 +0000677 with open(name, "rb") as f:
678 tar = tarfile.open(name, mode, fileobj=f)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000679 except tarfile.ReadError as e:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000680 self.fail()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000681 else:
682 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000683
684 def _test_modes(self, testfunc):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300685 if self.suffix:
686 with self.assertRaises(tarfile.ReadError):
687 tarfile.open(tarname, mode="r:" + self.suffix)
688 with self.assertRaises(tarfile.ReadError):
689 tarfile.open(tarname, mode="r|" + self.suffix)
690 with self.assertRaises(tarfile.ReadError):
691 tarfile.open(self.tarname, mode="r:")
692 with self.assertRaises(tarfile.ReadError):
693 tarfile.open(self.tarname, mode="r|")
694 testfunc(self.tarname, "r")
695 testfunc(self.tarname, "r:" + self.suffix)
696 testfunc(self.tarname, "r:*")
697 testfunc(self.tarname, "r|" + self.suffix)
698 testfunc(self.tarname, "r|*")
Lars Gustäbel0a9dd2f2011-12-10 20:38:14 +0100699
Guido van Rossumd8faa362007-04-27 19:54:29 +0000700 def test_detect_file(self):
701 self._test_modes(self._testfunc_file)
702
703 def test_detect_fileobj(self):
704 self._test_modes(self._testfunc_fileobj)
705
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300706class GzipDetectReadTest(GzipTest, DetectReadTest):
707 pass
708
709class Bz2DetectReadTest(Bz2Test, DetectReadTest):
Lars Gustäbeled1ac582011-12-06 12:56:38 +0100710 def test_detect_stream_bz2(self):
711 # Originally, tarfile's stream detection looked for the string
712 # "BZh91" at the start of the file. This is incorrect because
713 # the '9' represents the blocksize (900kB). If the file was
714 # compressed using another blocksize autodetection fails.
Lars Gustäbeled1ac582011-12-06 12:56:38 +0100715 with open(tarname, "rb") as fobj:
716 data = fobj.read()
717
718 # Compress with blocksize 100kB, the file starts with "BZh11".
719 with bz2.BZ2File(tmpname, "wb", compresslevel=1) as fobj:
720 fobj.write(data)
721
722 self._testfunc_file(tmpname, "r|*")
723
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300724class LzmaDetectReadTest(LzmaTest, DetectReadTest):
725 pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000726
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300727
728class MemberReadTest(ReadTest, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000729
730 def _test_member(self, tarinfo, chksum=None, **kwargs):
731 if chksum is not None:
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300732 with self.tar.extractfile(tarinfo) as f:
733 self.assertEqual(md5sum(f.read()), chksum,
734 "wrong md5sum for %s" % tarinfo.name)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000735
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000736 kwargs["mtime"] = 0o7606136617
Guido van Rossumd8faa362007-04-27 19:54:29 +0000737 kwargs["uid"] = 1000
738 kwargs["gid"] = 100
739 if "old-v7" not in tarinfo.name:
740 # V7 tar can't handle alphabetic owners.
741 kwargs["uname"] = "tarfile"
742 kwargs["gname"] = "tarfile"
743 for k, v in kwargs.items():
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300744 self.assertEqual(getattr(tarinfo, k), v,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000745 "wrong value in %s field of %s" % (k, tarinfo.name))
746
747 def test_find_regtype(self):
748 tarinfo = self.tar.getmember("ustar/regtype")
749 self._test_member(tarinfo, size=7011, chksum=md5_regtype)
750
751 def test_find_conttype(self):
752 tarinfo = self.tar.getmember("ustar/conttype")
753 self._test_member(tarinfo, size=7011, chksum=md5_regtype)
754
755 def test_find_dirtype(self):
756 tarinfo = self.tar.getmember("ustar/dirtype")
757 self._test_member(tarinfo, size=0)
758
759 def test_find_dirtype_with_size(self):
760 tarinfo = self.tar.getmember("ustar/dirtype-with-size")
761 self._test_member(tarinfo, size=255)
762
763 def test_find_lnktype(self):
764 tarinfo = self.tar.getmember("ustar/lnktype")
765 self._test_member(tarinfo, size=0, linkname="ustar/regtype")
766
767 def test_find_symtype(self):
768 tarinfo = self.tar.getmember("ustar/symtype")
769 self._test_member(tarinfo, size=0, linkname="regtype")
770
771 def test_find_blktype(self):
772 tarinfo = self.tar.getmember("ustar/blktype")
773 self._test_member(tarinfo, size=0, devmajor=3, devminor=0)
774
775 def test_find_chrtype(self):
776 tarinfo = self.tar.getmember("ustar/chrtype")
777 self._test_member(tarinfo, size=0, devmajor=1, devminor=3)
778
779 def test_find_fifotype(self):
780 tarinfo = self.tar.getmember("ustar/fifotype")
781 self._test_member(tarinfo, size=0)
782
783 def test_find_sparse(self):
784 tarinfo = self.tar.getmember("ustar/sparse")
785 self._test_member(tarinfo, size=86016, chksum=md5_sparse)
786
Lars Gustäbel9cbdd752010-10-29 09:08:19 +0000787 def test_find_gnusparse(self):
788 tarinfo = self.tar.getmember("gnu/sparse")
789 self._test_member(tarinfo, size=86016, chksum=md5_sparse)
790
791 def test_find_gnusparse_00(self):
792 tarinfo = self.tar.getmember("gnu/sparse-0.0")
793 self._test_member(tarinfo, size=86016, chksum=md5_sparse)
794
795 def test_find_gnusparse_01(self):
796 tarinfo = self.tar.getmember("gnu/sparse-0.1")
797 self._test_member(tarinfo, size=86016, chksum=md5_sparse)
798
799 def test_find_gnusparse_10(self):
800 tarinfo = self.tar.getmember("gnu/sparse-1.0")
801 self._test_member(tarinfo, size=86016, chksum=md5_sparse)
802
Guido van Rossumd8faa362007-04-27 19:54:29 +0000803 def test_find_umlauts(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300804 tarinfo = self.tar.getmember("ustar/umlauts-"
805 "\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000806 self._test_member(tarinfo, size=7011, chksum=md5_regtype)
807
808 def test_find_ustar_longname(self):
809 name = "ustar/" + "12345/" * 39 + "1234567/longname"
Benjamin Peterson577473f2010-01-19 00:09:57 +0000810 self.assertIn(name, self.tar.getnames())
Guido van Rossumd8faa362007-04-27 19:54:29 +0000811
812 def test_find_regtype_oldv7(self):
813 tarinfo = self.tar.getmember("misc/regtype-old-v7")
814 self._test_member(tarinfo, size=7011, chksum=md5_regtype)
815
816 def test_find_pax_umlauts(self):
Antoine Pitrouab58b5f2010-09-23 19:39:35 +0000817 self.tar.close()
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300818 self.tar = tarfile.open(self.tarname, mode=self.mode,
819 encoding="iso8859-1")
820 tarinfo = self.tar.getmember("pax/umlauts-"
821 "\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000822 self._test_member(tarinfo, size=7011, chksum=md5_regtype)
823
824
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300825class LongnameTest:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000826
827 def test_read_longname(self):
828 # Test reading of longname (bug #1471427).
Guido van Rossume7ba4952007-06-06 23:52:48 +0000829 longname = self.subdir + "/" + "123/" * 125 + "longname"
Guido van Rossumd8faa362007-04-27 19:54:29 +0000830 try:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000831 tarinfo = self.tar.getmember(longname)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000832 except KeyError:
833 self.fail("longname not found")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300834 self.assertNotEqual(tarinfo.type, tarfile.DIRTYPE,
835 "read longname as dirtype")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000836
837 def test_read_longlink(self):
838 longname = self.subdir + "/" + "123/" * 125 + "longname"
839 longlink = self.subdir + "/" + "123/" * 125 + "longlink"
840 try:
841 tarinfo = self.tar.getmember(longlink)
842 except KeyError:
843 self.fail("longlink not found")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300844 self.assertEqual(tarinfo.linkname, longname, "linkname wrong")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000845
846 def test_truncated_longname(self):
847 longname = self.subdir + "/" + "123/" * 125 + "longname"
848 tarinfo = self.tar.getmember(longname)
849 offset = tarinfo.offset
850 self.tar.fileobj.seek(offset)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000851 fobj = io.BytesIO(self.tar.fileobj.read(3 * 512))
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300852 with self.assertRaises(tarfile.ReadError):
853 tarfile.open(name="foo.tar", fileobj=fobj)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000854
Guido van Rossume7ba4952007-06-06 23:52:48 +0000855 def test_header_offset(self):
856 # Test if the start offset of the TarInfo object includes
857 # the preceding extended header.
858 longname = self.subdir + "/" + "123/" * 125 + "longname"
859 offset = self.tar.getmember(longname).offset
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000860 with open(tarname, "rb") as fobj:
861 fobj.seek(offset)
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300862 tarinfo = tarfile.TarInfo.frombuf(fobj.read(512),
863 "iso8859-1", "strict")
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000864 self.assertEqual(tarinfo.type, self.longnametype)
Guido van Rossume7ba4952007-06-06 23:52:48 +0000865
Guido van Rossumd8faa362007-04-27 19:54:29 +0000866
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300867class GNUReadTest(LongnameTest, ReadTest, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000868
869 subdir = "gnu"
Guido van Rossume7ba4952007-06-06 23:52:48 +0000870 longnametype = tarfile.GNUTYPE_LONGNAME
Guido van Rossumd8faa362007-04-27 19:54:29 +0000871
Lars Gustäbel9cbdd752010-10-29 09:08:19 +0000872 # Since 3.2 tarfile is supposed to accurately restore sparse members and
873 # produce files with holes. This is what we actually want to test here.
874 # Unfortunately, not all platforms/filesystems support sparse files, and
875 # even on platforms that do it is non-trivial to make reliable assertions
876 # about holes in files. Therefore, we first do one basic test which works
877 # an all platforms, and after that a test that will work only on
878 # platforms/filesystems that prove to support sparse files.
879 def _test_sparse_file(self, name):
880 self.tar.extract(name, TEMPDIR)
881 filename = os.path.join(TEMPDIR, name)
882 with open(filename, "rb") as fobj:
883 data = fobj.read()
884 self.assertEqual(md5sum(data), md5_sparse,
885 "wrong md5sum for %s" % name)
886
887 if self._fs_supports_holes():
888 s = os.stat(filename)
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300889 self.assertLess(s.st_blocks * 512, s.st_size)
Lars Gustäbel9cbdd752010-10-29 09:08:19 +0000890
891 def test_sparse_file_old(self):
892 self._test_sparse_file("gnu/sparse")
893
894 def test_sparse_file_00(self):
895 self._test_sparse_file("gnu/sparse-0.0")
896
897 def test_sparse_file_01(self):
898 self._test_sparse_file("gnu/sparse-0.1")
899
900 def test_sparse_file_10(self):
901 self._test_sparse_file("gnu/sparse-1.0")
902
903 @staticmethod
904 def _fs_supports_holes():
905 # Return True if the platform knows the st_blocks stat attribute and
906 # uses st_blocks units of 512 bytes, and if the filesystem is able to
907 # store holes in files.
Victor Stinner9c3de4a2011-08-17 20:49:41 +0200908 if sys.platform.startswith("linux"):
Lars Gustäbel9cbdd752010-10-29 09:08:19 +0000909 # Linux evidentially has 512 byte st_blocks units.
910 name = os.path.join(TEMPDIR, "sparse-test")
911 with open(name, "wb") as fobj:
912 fobj.seek(4096)
913 fobj.truncate()
914 s = os.stat(name)
Tim Goldene0bd2c52014-05-06 13:24:26 +0100915 support.unlink(name)
Lars Gustäbel9cbdd752010-10-29 09:08:19 +0000916 return s.st_blocks == 0
917 else:
918 return False
Guido van Rossumd8faa362007-04-27 19:54:29 +0000919
920
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300921class PaxReadTest(LongnameTest, ReadTest, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000922
923 subdir = "pax"
Guido van Rossume7ba4952007-06-06 23:52:48 +0000924 longnametype = tarfile.XHDTYPE
Guido van Rossumd8faa362007-04-27 19:54:29 +0000925
Guido van Rossume7ba4952007-06-06 23:52:48 +0000926 def test_pax_global_headers(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000927 tar = tarfile.open(tarname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000928 try:
929 tarinfo = tar.getmember("pax/regtype1")
930 self.assertEqual(tarinfo.uname, "foo")
931 self.assertEqual(tarinfo.gname, "bar")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300932 self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"),
933 "\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
Guido van Rossume7ba4952007-06-06 23:52:48 +0000934
Antoine Pitrou95f55602010-09-23 18:36:46 +0000935 tarinfo = tar.getmember("pax/regtype2")
936 self.assertEqual(tarinfo.uname, "")
937 self.assertEqual(tarinfo.gname, "bar")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300938 self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"),
939 "\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000940
Antoine Pitrou95f55602010-09-23 18:36:46 +0000941 tarinfo = tar.getmember("pax/regtype3")
942 self.assertEqual(tarinfo.uname, "tarfile")
943 self.assertEqual(tarinfo.gname, "tarfile")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300944 self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"),
945 "\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000946 finally:
947 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +0000948
949 def test_pax_number_fields(self):
950 # All following number fields are read from the pax header.
951 tar = tarfile.open(tarname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000952 try:
953 tarinfo = tar.getmember("pax/regtype4")
954 self.assertEqual(tarinfo.size, 7011)
955 self.assertEqual(tarinfo.uid, 123)
956 self.assertEqual(tarinfo.gid, 123)
957 self.assertEqual(tarinfo.mtime, 1041808783.0)
958 self.assertEqual(type(tarinfo.mtime), float)
959 self.assertEqual(float(tarinfo.pax_headers["atime"]), 1041808783.0)
960 self.assertEqual(float(tarinfo.pax_headers["ctime"]), 1041808783.0)
961 finally:
962 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000963
964
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300965class WriteTestBase(TarTest):
Georg Brandlf08a9dd2008-06-10 16:57:31 +0000966 # Put all write tests in here that are supposed to be tested
967 # in all possible mode combinations.
968
969 def test_fileobj_no_close(self):
970 fobj = io.BytesIO()
971 tar = tarfile.open(fileobj=fobj, mode=self.mode)
972 tar.addfile(tarfile.TarInfo("foo"))
973 tar.close()
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300974 self.assertFalse(fobj.closed, "external fileobjs must never closed")
Serhiy Storchaka9fbec7a2014-01-18 15:53:05 +0200975 # Issue #20238: Incomplete gzip output with mode="w:gz"
976 data = fobj.getvalue()
977 del tar
978 support.gc_collect()
979 self.assertFalse(fobj.closed)
980 self.assertEqual(data, fobj.getvalue())
Georg Brandlf08a9dd2008-06-10 16:57:31 +0000981
982
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300983class WriteTest(WriteTestBase, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000984
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300985 prefix = "w:"
Guido van Rossumd8faa362007-04-27 19:54:29 +0000986
987 def test_100_char_name(self):
988 # The name field in a tar header stores strings of at most 100 chars.
989 # If a string is shorter than 100 chars it has to be padded with '\0',
990 # which implies that a string of exactly 100 chars is stored without
991 # a trailing '\0'.
992 name = "0123456789" * 10
993 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000994 try:
995 t = tarfile.TarInfo(name)
996 tar.addfile(t)
997 finally:
998 tar.close()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000999
Guido van Rossumd8faa362007-04-27 19:54:29 +00001000 tar = tarfile.open(tmpname)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001001 try:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001002 self.assertEqual(tar.getnames()[0], name,
Antoine Pitrou95f55602010-09-23 18:36:46 +00001003 "failed to store 100 char filename")
1004 finally:
1005 tar.close()
Thomas Wouters89f507f2006-12-13 04:49:30 +00001006
Guido van Rossumd8faa362007-04-27 19:54:29 +00001007 def test_tar_size(self):
1008 # Test for bug #1013882.
1009 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001010 try:
1011 path = os.path.join(TEMPDIR, "file")
1012 with open(path, "wb") as fobj:
1013 fobj.write(b"aaa")
1014 tar.add(path)
1015 finally:
1016 tar.close()
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001017 self.assertGreater(os.path.getsize(tmpname), 0,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001018 "tarfile is empty")
Thomas Wouters89f507f2006-12-13 04:49:30 +00001019
Guido van Rossumd8faa362007-04-27 19:54:29 +00001020 # The test_*_size tests test for bug #1167128.
1021 def test_file_size(self):
1022 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001023 try:
1024 path = os.path.join(TEMPDIR, "file")
1025 with open(path, "wb"):
1026 pass
1027 tarinfo = tar.gettarinfo(path)
1028 self.assertEqual(tarinfo.size, 0)
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001029
Antoine Pitrou95f55602010-09-23 18:36:46 +00001030 with open(path, "wb") as fobj:
1031 fobj.write(b"aaa")
1032 tarinfo = tar.gettarinfo(path)
1033 self.assertEqual(tarinfo.size, 3)
1034 finally:
1035 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001036
1037 def test_directory_size(self):
1038 path = os.path.join(TEMPDIR, "directory")
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001039 os.mkdir(path)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001040 try:
1041 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001042 try:
1043 tarinfo = tar.gettarinfo(path)
1044 self.assertEqual(tarinfo.size, 0)
1045 finally:
1046 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001047 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001048 support.rmdir(path)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001049
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001050 @unittest.skipUnless(hasattr(os, "link"),
1051 "Missing hardlink implementation")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001052 def test_link_size(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001053 link = os.path.join(TEMPDIR, "link")
1054 target = os.path.join(TEMPDIR, "link_target")
1055 with open(target, "wb") as fobj:
1056 fobj.write(b"aaa")
1057 os.link(target, link)
1058 try:
1059 tar = tarfile.open(tmpname, self.mode)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001060 try:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001061 # Record the link target in the inodes list.
1062 tar.gettarinfo(target)
1063 tarinfo = tar.gettarinfo(link)
1064 self.assertEqual(tarinfo.size, 0)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001065 finally:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001066 tar.close()
1067 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001068 support.unlink(target)
1069 support.unlink(link)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001070
Brian Curtin3b4499c2010-12-28 14:31:47 +00001071 @support.skip_unless_symlink
Guido van Rossumd8faa362007-04-27 19:54:29 +00001072 def test_symlink_size(self):
Brian Curtind40e6f72010-07-08 21:39:08 +00001073 path = os.path.join(TEMPDIR, "symlink")
1074 os.symlink("link_target", path)
1075 try:
1076 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001077 try:
1078 tarinfo = tar.gettarinfo(path)
1079 self.assertEqual(tarinfo.size, 0)
1080 finally:
1081 tar.close()
Brian Curtind40e6f72010-07-08 21:39:08 +00001082 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001083 support.unlink(path)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001084
1085 def test_add_self(self):
1086 # Test for #1257255.
1087 dstname = os.path.abspath(tmpname)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001088 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001089 try:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001090 self.assertEqual(tar.name, dstname,
1091 "archive name must be absolute")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001092 tar.add(dstname)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001093 self.assertEqual(tar.getnames(), [],
1094 "added the archive to itself")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001095
Antoine Pitrou95f55602010-09-23 18:36:46 +00001096 cwd = os.getcwd()
1097 os.chdir(TEMPDIR)
1098 tar.add(dstname)
1099 os.chdir(cwd)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001100 self.assertEqual(tar.getnames(), [],
1101 "added the archive to itself")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001102 finally:
1103 tar.close()
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001104
Guido van Rossum486364b2007-06-30 05:01:58 +00001105 def test_exclude(self):
1106 tempdir = os.path.join(TEMPDIR, "exclude")
1107 os.mkdir(tempdir)
1108 try:
1109 for name in ("foo", "bar", "baz"):
1110 name = os.path.join(tempdir, name)
Victor Stinnerbf816222011-06-30 23:25:47 +02001111 support.create_empty_file(name)
Guido van Rossum486364b2007-06-30 05:01:58 +00001112
Benjamin Peterson886af962010-03-21 23:13:07 +00001113 exclude = os.path.isfile
Guido van Rossum486364b2007-06-30 05:01:58 +00001114
1115 tar = tarfile.open(tmpname, self.mode, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001116 try:
1117 with support.check_warnings(("use the filter argument",
1118 DeprecationWarning)):
1119 tar.add(tempdir, arcname="empty_dir", exclude=exclude)
1120 finally:
1121 tar.close()
Guido van Rossum486364b2007-06-30 05:01:58 +00001122
1123 tar = tarfile.open(tmpname, "r")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001124 try:
1125 self.assertEqual(len(tar.getmembers()), 1)
1126 self.assertEqual(tar.getnames()[0], "empty_dir")
1127 finally:
1128 tar.close()
Guido van Rossum486364b2007-06-30 05:01:58 +00001129 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001130 support.rmtree(tempdir)
Guido van Rossum486364b2007-06-30 05:01:58 +00001131
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001132 def test_filter(self):
1133 tempdir = os.path.join(TEMPDIR, "filter")
1134 os.mkdir(tempdir)
1135 try:
1136 for name in ("foo", "bar", "baz"):
1137 name = os.path.join(tempdir, name)
Victor Stinnerbf816222011-06-30 23:25:47 +02001138 support.create_empty_file(name)
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001139
1140 def filter(tarinfo):
1141 if os.path.basename(tarinfo.name) == "bar":
1142 return
1143 tarinfo.uid = 123
1144 tarinfo.uname = "foo"
1145 return tarinfo
1146
1147 tar = tarfile.open(tmpname, self.mode, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001148 try:
1149 tar.add(tempdir, arcname="empty_dir", filter=filter)
1150 finally:
1151 tar.close()
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001152
Raymond Hettingera63a3122011-01-26 20:34:14 +00001153 # Verify that filter is a keyword-only argument
1154 with self.assertRaises(TypeError):
1155 tar.add(tempdir, "empty_dir", True, None, filter)
1156
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001157 tar = tarfile.open(tmpname, "r")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001158 try:
1159 for tarinfo in tar:
1160 self.assertEqual(tarinfo.uid, 123)
1161 self.assertEqual(tarinfo.uname, "foo")
1162 self.assertEqual(len(tar.getmembers()), 3)
1163 finally:
1164 tar.close()
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001165 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001166 support.rmtree(tempdir)
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001167
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001168 # Guarantee that stored pathnames are not modified. Don't
1169 # remove ./ or ../ or double slashes. Still make absolute
1170 # pathnames relative.
1171 # For details see bug #6054.
1172 def _test_pathname(self, path, cmp_path=None, dir=False):
1173 # Create a tarfile with an empty member named path
1174 # and compare the stored name with the original.
1175 foo = os.path.join(TEMPDIR, "foo")
1176 if not dir:
Victor Stinnerbf816222011-06-30 23:25:47 +02001177 support.create_empty_file(foo)
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001178 else:
1179 os.mkdir(foo)
1180
1181 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001182 try:
1183 tar.add(foo, arcname=path)
1184 finally:
1185 tar.close()
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001186
1187 tar = tarfile.open(tmpname, "r")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001188 try:
1189 t = tar.next()
1190 finally:
1191 tar.close()
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001192
1193 if not dir:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001194 support.unlink(foo)
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001195 else:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001196 support.rmdir(foo)
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001197
1198 self.assertEqual(t.name, cmp_path or path.replace(os.sep, "/"))
1199
Senthil Kumaranbe5dbeb2011-04-30 06:09:51 +08001200
1201 @support.skip_unless_symlink
Senthil Kumaran123932f2011-04-28 15:38:12 +08001202 def test_extractall_symlinks(self):
1203 # Test if extractall works properly when tarfile contains symlinks
1204 tempdir = os.path.join(TEMPDIR, "testsymlinks")
1205 temparchive = os.path.join(TEMPDIR, "testsymlinks.tar")
1206 os.mkdir(tempdir)
1207 try:
1208 source_file = os.path.join(tempdir,'source')
1209 target_file = os.path.join(tempdir,'symlink')
1210 with open(source_file,'w') as f:
1211 f.write('something\n')
1212 os.symlink(source_file, target_file)
1213 tar = tarfile.open(temparchive,'w')
1214 tar.add(source_file)
1215 tar.add(target_file)
1216 tar.close()
1217 # Let's extract it to the location which contains the symlink
1218 tar = tarfile.open(temparchive,'r')
1219 # this should not raise OSError: [Errno 17] File exists
1220 try:
1221 tar.extractall(path=tempdir)
1222 except OSError:
1223 self.fail("extractall failed with symlinked files")
1224 finally:
1225 tar.close()
1226 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001227 support.unlink(temparchive)
1228 support.rmtree(tempdir)
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001229
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001230 def test_pathnames(self):
1231 self._test_pathname("foo")
1232 self._test_pathname(os.path.join("foo", ".", "bar"))
1233 self._test_pathname(os.path.join("foo", "..", "bar"))
1234 self._test_pathname(os.path.join(".", "foo"))
1235 self._test_pathname(os.path.join(".", "foo", "."))
1236 self._test_pathname(os.path.join(".", "foo", ".", "bar"))
1237 self._test_pathname(os.path.join(".", "foo", "..", "bar"))
1238 self._test_pathname(os.path.join(".", "foo", "..", "bar"))
1239 self._test_pathname(os.path.join("..", "foo"))
1240 self._test_pathname(os.path.join("..", "foo", ".."))
1241 self._test_pathname(os.path.join("..", "foo", ".", "bar"))
1242 self._test_pathname(os.path.join("..", "foo", "..", "bar"))
1243
1244 self._test_pathname("foo" + os.sep + os.sep + "bar")
1245 self._test_pathname("foo" + os.sep + os.sep, "foo", dir=True)
1246
1247 def test_abs_pathnames(self):
1248 if sys.platform == "win32":
1249 self._test_pathname("C:\\foo", "foo")
1250 else:
1251 self._test_pathname("/foo", "foo")
1252 self._test_pathname("///foo", "foo")
1253
1254 def test_cwd(self):
1255 # Test adding the current working directory.
1256 cwd = os.getcwd()
1257 os.chdir(TEMPDIR)
1258 try:
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001259 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001260 try:
1261 tar.add(".")
1262 finally:
1263 tar.close()
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001264
1265 tar = tarfile.open(tmpname, "r")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001266 try:
1267 for t in tar:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001268 if t.name != ".":
1269 self.assertTrue(t.name.startswith("./"), t.name)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001270 finally:
1271 tar.close()
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001272 finally:
1273 os.chdir(cwd)
1274
Serhiy Storchakac2d01422014-01-18 16:14:10 +02001275 def test_open_nonwritable_fileobj(self):
1276 for exctype in OSError, EOFError, RuntimeError:
1277 class BadFile(io.BytesIO):
1278 first = True
1279 def write(self, data):
1280 if self.first:
1281 self.first = False
1282 raise exctype
1283
1284 f = BadFile()
1285 with self.assertRaises(exctype):
1286 tar = tarfile.open(tmpname, self.mode, fileobj=f,
1287 format=tarfile.PAX_FORMAT,
1288 pax_headers={'non': 'empty'})
1289 self.assertFalse(f.closed)
1290
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001291class GzipWriteTest(GzipTest, WriteTest):
1292 pass
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001293
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001294class Bz2WriteTest(Bz2Test, WriteTest):
1295 pass
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001296
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001297class LzmaWriteTest(LzmaTest, WriteTest):
1298 pass
1299
1300
1301class StreamWriteTest(WriteTestBase, unittest.TestCase):
1302
1303 prefix = "w|"
1304 decompressor = None
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001305
Guido van Rossumd8faa362007-04-27 19:54:29 +00001306 def test_stream_padding(self):
1307 # Test for bug #1543303.
1308 tar = tarfile.open(tmpname, self.mode)
1309 tar.close()
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001310 if self.decompressor:
1311 dec = self.decompressor()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001312 with open(tmpname, "rb") as fobj:
1313 data = fobj.read()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001314 data = dec.decompress(data)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001315 self.assertFalse(dec.unused_data, "found trailing data")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001316 else:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001317 with self.open(tmpname) as fobj:
Antoine Pitrou95f55602010-09-23 18:36:46 +00001318 data = fobj.read()
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001319 self.assertEqual(data.count(b"\0"), tarfile.RECORDSIZE,
1320 "incorrect zero padding")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001321
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001322 @unittest.skipUnless(sys.platform != "win32" and hasattr(os, "umask"),
1323 "Missing umask implementation")
Lars Gustäbeld6eb70b2010-04-29 15:37:02 +00001324 def test_file_mode(self):
1325 # Test for issue #8464: Create files with correct
1326 # permissions.
Lars Gustäbeld6eb70b2010-04-29 15:37:02 +00001327 if os.path.exists(tmpname):
Tim Goldene0bd2c52014-05-06 13:24:26 +01001328 support.unlink(tmpname)
Lars Gustäbeld6eb70b2010-04-29 15:37:02 +00001329
1330 original_umask = os.umask(0o022)
1331 try:
1332 tar = tarfile.open(tmpname, self.mode)
1333 tar.close()
1334 mode = os.stat(tmpname).st_mode & 0o777
1335 self.assertEqual(mode, 0o644, "wrong file permissions")
1336 finally:
1337 os.umask(original_umask)
1338
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001339class GzipStreamWriteTest(GzipTest, StreamWriteTest):
1340 pass
1341
1342class Bz2StreamWriteTest(Bz2Test, StreamWriteTest):
1343 decompressor = bz2.BZ2Decompressor if bz2 else None
1344
1345class LzmaStreamWriteTest(LzmaTest, StreamWriteTest):
1346 decompressor = lzma.LZMADecompressor if lzma else None
1347
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001348
Guido van Rossumd8faa362007-04-27 19:54:29 +00001349class GNUWriteTest(unittest.TestCase):
1350 # This testcase checks for correct creation of GNU Longname
1351 # and Longlink extended headers (cp. bug #812325).
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001352
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001353 def _length(self, s):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001354 blocks = len(s) // 512 + 1
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001355 return blocks * 512
1356
1357 def _calc_size(self, name, link=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001358 # Initial tar header
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001359 count = 512
1360
1361 if len(name) > tarfile.LENGTH_NAME:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001362 # GNU longname extended header + longname
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001363 count += 512
1364 count += self._length(name)
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001365 if link is not None and len(link) > tarfile.LENGTH_LINK:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001366 # GNU longlink extended header + longlink
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001367 count += 512
1368 count += self._length(link)
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001369 return count
1370
1371 def _test(self, name, link=None):
1372 tarinfo = tarfile.TarInfo(name)
1373 if link:
1374 tarinfo.linkname = link
1375 tarinfo.type = tarfile.LNKTYPE
1376
Guido van Rossumd8faa362007-04-27 19:54:29 +00001377 tar = tarfile.open(tmpname, "w")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001378 try:
1379 tar.format = tarfile.GNU_FORMAT
1380 tar.addfile(tarinfo)
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001381
Antoine Pitrou95f55602010-09-23 18:36:46 +00001382 v1 = self._calc_size(name, link)
1383 v2 = tar.offset
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001384 self.assertEqual(v1, v2, "GNU longname/longlink creation failed")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001385 finally:
1386 tar.close()
Thomas Wouters89f507f2006-12-13 04:49:30 +00001387
Guido van Rossumd8faa362007-04-27 19:54:29 +00001388 tar = tarfile.open(tmpname)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001389 try:
1390 member = tar.next()
1391 self.assertIsNotNone(member,
1392 "unable to read longname member")
1393 self.assertEqual(tarinfo.name, member.name,
1394 "unable to read longname member")
1395 self.assertEqual(tarinfo.linkname, member.linkname,
1396 "unable to read longname member")
1397 finally:
1398 tar.close()
Thomas Wouters89f507f2006-12-13 04:49:30 +00001399
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001400 def test_longname_1023(self):
1401 self._test(("longnam/" * 127) + "longnam")
1402
1403 def test_longname_1024(self):
1404 self._test(("longnam/" * 127) + "longname")
1405
1406 def test_longname_1025(self):
1407 self._test(("longnam/" * 127) + "longname_")
1408
1409 def test_longlink_1023(self):
1410 self._test("name", ("longlnk/" * 127) + "longlnk")
1411
1412 def test_longlink_1024(self):
1413 self._test("name", ("longlnk/" * 127) + "longlink")
1414
1415 def test_longlink_1025(self):
1416 self._test("name", ("longlnk/" * 127) + "longlink_")
1417
1418 def test_longnamelink_1023(self):
1419 self._test(("longnam/" * 127) + "longnam",
1420 ("longlnk/" * 127) + "longlnk")
1421
1422 def test_longnamelink_1024(self):
1423 self._test(("longnam/" * 127) + "longname",
1424 ("longlnk/" * 127) + "longlink")
1425
1426 def test_longnamelink_1025(self):
1427 self._test(("longnam/" * 127) + "longname_",
1428 ("longlnk/" * 127) + "longlink_")
1429
Guido van Rossumd8faa362007-04-27 19:54:29 +00001430
Berker Peksag0fe63252015-02-13 21:02:12 +02001431class CreateTest(TarTest, unittest.TestCase):
1432
1433 prefix = "x:"
1434
1435 file_path = os.path.join(TEMPDIR, "spameggs42")
1436
1437 def setUp(self):
1438 support.unlink(tmpname)
1439
1440 @classmethod
1441 def setUpClass(cls):
1442 with open(cls.file_path, "wb") as fobj:
1443 fobj.write(b"aaa")
1444
1445 @classmethod
1446 def tearDownClass(cls):
1447 support.unlink(cls.file_path)
1448
1449 def test_create(self):
1450 with tarfile.open(tmpname, self.mode) as tobj:
1451 tobj.add(self.file_path)
1452
1453 with self.taropen(tmpname) as tobj:
1454 names = tobj.getnames()
1455 self.assertEqual(len(names), 1)
1456 self.assertIn('spameggs42', names[0])
1457
1458 def test_create_existing(self):
1459 with tarfile.open(tmpname, self.mode) as tobj:
1460 tobj.add(self.file_path)
1461
1462 with self.assertRaises(FileExistsError):
1463 tobj = tarfile.open(tmpname, self.mode)
1464
1465 with self.taropen(tmpname) as tobj:
1466 names = tobj.getnames()
1467 self.assertEqual(len(names), 1)
1468 self.assertIn('spameggs42', names[0])
1469
1470 def test_create_taropen(self):
1471 with self.taropen(tmpname, "x") as tobj:
1472 tobj.add(self.file_path)
1473
1474 with self.taropen(tmpname) as tobj:
1475 names = tobj.getnames()
1476 self.assertEqual(len(names), 1)
1477 self.assertIn('spameggs42', names[0])
1478
1479 def test_create_existing_taropen(self):
1480 with self.taropen(tmpname, "x") as tobj:
1481 tobj.add(self.file_path)
1482
1483 with self.assertRaises(FileExistsError):
1484 with self.taropen(tmpname, "x"):
1485 pass
1486
1487 with self.taropen(tmpname) as tobj:
1488 names = tobj.getnames()
1489 self.assertEqual(len(names), 1)
1490 self.assertIn("spameggs42", names[0])
1491
1492
1493class GzipCreateTest(GzipTest, CreateTest):
1494 pass
1495
1496
1497class Bz2CreateTest(Bz2Test, CreateTest):
1498 pass
1499
1500
1501class LzmaCreateTest(LzmaTest, CreateTest):
1502 pass
1503
1504
1505class CreateWithXModeTest(CreateTest):
1506
1507 prefix = "x"
1508
1509 test_create_taropen = None
1510 test_create_existing_taropen = None
1511
1512
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001513@unittest.skipUnless(hasattr(os, "link"), "Missing hardlink implementation")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001514class HardlinkTest(unittest.TestCase):
1515 # Test the creation of LNKTYPE (hardlink) members in an archive.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001516
1517 def setUp(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001518 self.foo = os.path.join(TEMPDIR, "foo")
1519 self.bar = os.path.join(TEMPDIR, "bar")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001520
Antoine Pitrou95f55602010-09-23 18:36:46 +00001521 with open(self.foo, "wb") as fobj:
1522 fobj.write(b"foo")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001523
Guido van Rossumd8faa362007-04-27 19:54:29 +00001524 os.link(self.foo, self.bar)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001525
Guido van Rossumd8faa362007-04-27 19:54:29 +00001526 self.tar = tarfile.open(tmpname, "w")
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001527 self.tar.add(self.foo)
1528
Guido van Rossumd8faa362007-04-27 19:54:29 +00001529 def tearDown(self):
Hirokazu Yamamotoaf079d42008-09-21 11:50:03 +00001530 self.tar.close()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001531 support.unlink(self.foo)
1532 support.unlink(self.bar)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001533
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001534 def test_add_twice(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001535 # The same name will be added as a REGTYPE every
1536 # time regardless of st_nlink.
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001537 tarinfo = self.tar.gettarinfo(self.foo)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001538 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001539 "add file as regular failed")
1540
1541 def test_add_hardlink(self):
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001542 tarinfo = self.tar.gettarinfo(self.bar)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001543 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001544 "add file as hardlink failed")
1545
1546 def test_dereference_hardlink(self):
1547 self.tar.dereference = True
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001548 tarinfo = self.tar.gettarinfo(self.bar)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001549 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001550 "dereferencing hardlink failed")
1551
Neal Norwitza4f651a2004-07-20 22:07:44 +00001552
Guido van Rossumd8faa362007-04-27 19:54:29 +00001553class PaxWriteTest(GNUWriteTest):
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001554
Guido van Rossumd8faa362007-04-27 19:54:29 +00001555 def _test(self, name, link=None):
1556 # See GNUWriteTest.
1557 tarinfo = tarfile.TarInfo(name)
1558 if link:
1559 tarinfo.linkname = link
1560 tarinfo.type = tarfile.LNKTYPE
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +00001561
Guido van Rossumd8faa362007-04-27 19:54:29 +00001562 tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001563 try:
1564 tar.addfile(tarinfo)
1565 finally:
1566 tar.close()
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +00001567
Guido van Rossumd8faa362007-04-27 19:54:29 +00001568 tar = tarfile.open(tmpname)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001569 try:
1570 if link:
1571 l = tar.getmembers()[0].linkname
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001572 self.assertEqual(link, l, "PAX longlink creation failed")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001573 else:
1574 n = tar.getmembers()[0].name
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001575 self.assertEqual(name, n, "PAX longname creation failed")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001576 finally:
1577 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001578
Guido van Rossume7ba4952007-06-06 23:52:48 +00001579 def test_pax_global_header(self):
1580 pax_headers = {
Guido van Rossum9cbfffd2007-06-07 00:54:15 +00001581 "foo": "bar",
1582 "uid": "0",
1583 "mtime": "1.23",
Guido van Rossuma0557702007-08-07 23:19:53 +00001584 "test": "\xe4\xf6\xfc",
1585 "\xe4\xf6\xfc": "test"}
Guido van Rossume7ba4952007-06-06 23:52:48 +00001586
Benjamin Peterson886af962010-03-21 23:13:07 +00001587 tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT,
Guido van Rossume7ba4952007-06-06 23:52:48 +00001588 pax_headers=pax_headers)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001589 try:
1590 tar.addfile(tarfile.TarInfo("test"))
1591 finally:
1592 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001593
1594 # Test if the global header was written correctly.
1595 tar = tarfile.open(tmpname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001596 try:
1597 self.assertEqual(tar.pax_headers, pax_headers)
1598 self.assertEqual(tar.getmembers()[0].pax_headers, pax_headers)
1599 # Test if all the fields are strings.
1600 for key, val in tar.pax_headers.items():
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001601 self.assertIsNot(type(key), bytes)
1602 self.assertIsNot(type(val), bytes)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001603 if key in tarfile.PAX_NUMBER_FIELDS:
1604 try:
1605 tarfile.PAX_NUMBER_FIELDS[key](val)
1606 except (TypeError, ValueError):
1607 self.fail("unable to convert pax header field")
1608 finally:
1609 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001610
1611 def test_pax_extended_header(self):
1612 # The fields from the pax header have priority over the
1613 # TarInfo.
Guido van Rossum9cbfffd2007-06-07 00:54:15 +00001614 pax_headers = {"path": "foo", "uid": "123"}
Guido van Rossume7ba4952007-06-06 23:52:48 +00001615
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001616 tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT,
1617 encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001618 try:
1619 t = tarfile.TarInfo()
1620 t.name = "\xe4\xf6\xfc" # non-ASCII
1621 t.uid = 8**8 # too large
1622 t.pax_headers = pax_headers
1623 tar.addfile(t)
1624 finally:
1625 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001626
1627 tar = tarfile.open(tmpname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001628 try:
1629 t = tar.getmembers()[0]
1630 self.assertEqual(t.pax_headers, pax_headers)
1631 self.assertEqual(t.name, "foo")
1632 self.assertEqual(t.uid, 123)
1633 finally:
1634 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001635
1636
1637class UstarUnicodeTest(unittest.TestCase):
Guido van Rossume7ba4952007-06-06 23:52:48 +00001638
1639 format = tarfile.USTAR_FORMAT
1640
1641 def test_iso8859_1_filename(self):
1642 self._test_unicode_filename("iso8859-1")
1643
1644 def test_utf7_filename(self):
1645 self._test_unicode_filename("utf7")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001646
1647 def test_utf8_filename(self):
Marc-André Lemburg8f36af72011-02-25 15:42:01 +00001648 self._test_unicode_filename("utf-8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001649
Guido van Rossumd8faa362007-04-27 19:54:29 +00001650 def _test_unicode_filename(self, encoding):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001651 tar = tarfile.open(tmpname, "w", format=self.format,
1652 encoding=encoding, errors="strict")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001653 try:
1654 name = "\xe4\xf6\xfc"
1655 tar.addfile(tarfile.TarInfo(name))
1656 finally:
1657 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001658
1659 tar = tarfile.open(tmpname, encoding=encoding)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001660 try:
1661 self.assertEqual(tar.getmembers()[0].name, name)
1662 finally:
1663 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001664
1665 def test_unicode_filename_error(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001666 tar = tarfile.open(tmpname, "w", format=self.format,
1667 encoding="ascii", errors="strict")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001668 try:
1669 tarinfo = tarfile.TarInfo()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001670
Antoine Pitrou95f55602010-09-23 18:36:46 +00001671 tarinfo.name = "\xe4\xf6\xfc"
1672 self.assertRaises(UnicodeError, tar.addfile, tarinfo)
Guido van Rossume7ba4952007-06-06 23:52:48 +00001673
Antoine Pitrou95f55602010-09-23 18:36:46 +00001674 tarinfo.name = "foo"
1675 tarinfo.uname = "\xe4\xf6\xfc"
1676 self.assertRaises(UnicodeError, tar.addfile, tarinfo)
1677 finally:
1678 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001679
1680 def test_unicode_argument(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001681 tar = tarfile.open(tarname, "r",
1682 encoding="iso8859-1", errors="strict")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001683 try:
1684 for t in tar:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001685 self.assertIs(type(t.name), str)
1686 self.assertIs(type(t.linkname), str)
1687 self.assertIs(type(t.uname), str)
1688 self.assertIs(type(t.gname), str)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001689 finally:
1690 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001691
Guido van Rossume7ba4952007-06-06 23:52:48 +00001692 def test_uname_unicode(self):
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001693 t = tarfile.TarInfo("foo")
1694 t.uname = "\xe4\xf6\xfc"
1695 t.gname = "\xe4\xf6\xfc"
Guido van Rossumd8faa362007-04-27 19:54:29 +00001696
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001697 tar = tarfile.open(tmpname, mode="w", format=self.format,
1698 encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001699 try:
1700 tar.addfile(t)
1701 finally:
1702 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001703
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001704 tar = tarfile.open(tmpname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001705 try:
Guido van Rossume7ba4952007-06-06 23:52:48 +00001706 t = tar.getmember("foo")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001707 self.assertEqual(t.uname, "\xe4\xf6\xfc")
1708 self.assertEqual(t.gname, "\xe4\xf6\xfc")
1709
1710 if self.format != tarfile.PAX_FORMAT:
Antoine Pitrouab58b5f2010-09-23 19:39:35 +00001711 tar.close()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001712 tar = tarfile.open(tmpname, encoding="ascii")
1713 t = tar.getmember("foo")
1714 self.assertEqual(t.uname, "\udce4\udcf6\udcfc")
1715 self.assertEqual(t.gname, "\udce4\udcf6\udcfc")
1716 finally:
1717 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001718
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001719
Guido van Rossume7ba4952007-06-06 23:52:48 +00001720class GNUUnicodeTest(UstarUnicodeTest):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001721
Guido van Rossume7ba4952007-06-06 23:52:48 +00001722 format = tarfile.GNU_FORMAT
Guido van Rossumd8faa362007-04-27 19:54:29 +00001723
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001724 def test_bad_pax_header(self):
1725 # Test for issue #8633. GNU tar <= 1.23 creates raw binary fields
1726 # without a hdrcharset=BINARY header.
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001727 for encoding, name in (
1728 ("utf-8", "pax/bad-pax-\udce4\udcf6\udcfc"),
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001729 ("iso8859-1", "pax/bad-pax-\xe4\xf6\xfc"),):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001730 with tarfile.open(tarname, encoding=encoding,
1731 errors="surrogateescape") as tar:
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001732 try:
1733 t = tar.getmember(name)
1734 except KeyError:
1735 self.fail("unable to read bad GNU tar pax header")
1736
Guido van Rossumd8faa362007-04-27 19:54:29 +00001737
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001738class PAXUnicodeTest(UstarUnicodeTest):
1739
1740 format = tarfile.PAX_FORMAT
1741
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001742 # PAX_FORMAT ignores encoding in write mode.
1743 test_unicode_filename_error = None
1744
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001745 def test_binary_header(self):
1746 # Test a POSIX.1-2008 compatible header with a hdrcharset=BINARY field.
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001747 for encoding, name in (
1748 ("utf-8", "pax/hdrcharset-\udce4\udcf6\udcfc"),
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001749 ("iso8859-1", "pax/hdrcharset-\xe4\xf6\xfc"),):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001750 with tarfile.open(tarname, encoding=encoding,
1751 errors="surrogateescape") as tar:
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001752 try:
1753 t = tar.getmember(name)
1754 except KeyError:
1755 self.fail("unable to read POSIX.1-2008 binary header")
1756
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001757
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001758class AppendTestBase:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001759 # Test append mode (cp. patch #1652681).
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001760
Guido van Rossumd8faa362007-04-27 19:54:29 +00001761 def setUp(self):
1762 self.tarname = tmpname
1763 if os.path.exists(self.tarname):
Tim Goldene0bd2c52014-05-06 13:24:26 +01001764 support.unlink(self.tarname)
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001765
Guido van Rossumd8faa362007-04-27 19:54:29 +00001766 def _create_testtar(self, mode="w:"):
Antoine Pitrou95f55602010-09-23 18:36:46 +00001767 with tarfile.open(tarname, encoding="iso8859-1") as src:
1768 t = src.getmember("ustar/regtype")
1769 t.name = "foo"
Lars Gustäbel7a919e92012-05-05 18:15:03 +02001770 with src.extractfile(t) as f:
Antoine Pitroue1eca4e2010-10-29 23:49:49 +00001771 with tarfile.open(self.tarname, mode) as tar:
1772 tar.addfile(t, f)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001773
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001774 def test_append_compressed(self):
1775 self._create_testtar("w:" + self.suffix)
1776 self.assertRaises(tarfile.ReadError, tarfile.open, tmpname, "a")
1777
1778class AppendTest(AppendTestBase, unittest.TestCase):
1779 test_append_compressed = None
1780
1781 def _add_testfile(self, fileobj=None):
1782 with tarfile.open(self.tarname, "a", fileobj=fileobj) as tar:
1783 tar.addfile(tarfile.TarInfo("bar"))
1784
Guido van Rossumd8faa362007-04-27 19:54:29 +00001785 def _test(self, names=["bar"], fileobj=None):
Antoine Pitrou95f55602010-09-23 18:36:46 +00001786 with tarfile.open(self.tarname, fileobj=fileobj) as tar:
1787 self.assertEqual(tar.getnames(), names)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001788
1789 def test_non_existing(self):
1790 self._add_testfile()
1791 self._test()
1792
1793 def test_empty(self):
Lars Gustäbel9520a432009-11-22 18:48:49 +00001794 tarfile.open(self.tarname, "w:").close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001795 self._add_testfile()
1796 self._test()
1797
1798 def test_empty_fileobj(self):
Lars Gustäbel9520a432009-11-22 18:48:49 +00001799 fobj = io.BytesIO(b"\0" * 1024)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001800 self._add_testfile(fobj)
1801 fobj.seek(0)
1802 self._test(fileobj=fobj)
1803
1804 def test_fileobj(self):
1805 self._create_testtar()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001806 with open(self.tarname, "rb") as fobj:
1807 data = fobj.read()
Guido van Rossum34d19282007-08-09 01:03:29 +00001808 fobj = io.BytesIO(data)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001809 self._add_testfile(fobj)
1810 fobj.seek(0)
1811 self._test(names=["foo", "bar"], fileobj=fobj)
1812
1813 def test_existing(self):
1814 self._create_testtar()
1815 self._add_testfile()
1816 self._test(names=["foo", "bar"])
1817
Lars Gustäbel9520a432009-11-22 18:48:49 +00001818 # Append mode is supposed to fail if the tarfile to append to
1819 # does not end with a zero block.
1820 def _test_error(self, data):
Antoine Pitrou95f55602010-09-23 18:36:46 +00001821 with open(self.tarname, "wb") as fobj:
1822 fobj.write(data)
Lars Gustäbel9520a432009-11-22 18:48:49 +00001823 self.assertRaises(tarfile.ReadError, self._add_testfile)
1824
1825 def test_null(self):
1826 self._test_error(b"")
1827
1828 def test_incomplete(self):
1829 self._test_error(b"\0" * 13)
1830
1831 def test_premature_eof(self):
1832 data = tarfile.TarInfo("foo").tobuf()
1833 self._test_error(data)
1834
1835 def test_trailing_garbage(self):
1836 data = tarfile.TarInfo("foo").tobuf()
1837 self._test_error(data + b"\0" * 13)
1838
1839 def test_invalid(self):
1840 self._test_error(b"a" * 512)
1841
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001842class GzipAppendTest(GzipTest, AppendTestBase, unittest.TestCase):
1843 pass
1844
1845class Bz2AppendTest(Bz2Test, AppendTestBase, unittest.TestCase):
1846 pass
1847
1848class LzmaAppendTest(LzmaTest, AppendTestBase, unittest.TestCase):
1849 pass
1850
Guido van Rossumd8faa362007-04-27 19:54:29 +00001851
1852class LimitsTest(unittest.TestCase):
1853
1854 def test_ustar_limits(self):
1855 # 100 char name
1856 tarinfo = tarfile.TarInfo("0123456789" * 10)
Guido van Rossume7ba4952007-06-06 23:52:48 +00001857 tarinfo.tobuf(tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001858
1859 # 101 char name that cannot be stored
1860 tarinfo = tarfile.TarInfo("0123456789" * 10 + "0")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001861 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001862
1863 # 256 char name with a slash at pos 156
1864 tarinfo = tarfile.TarInfo("123/" * 62 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001865 tarinfo.tobuf(tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001866
1867 # 256 char name that cannot be stored
1868 tarinfo = tarfile.TarInfo("1234567/" * 31 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001869 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001870
1871 # 512 char name
1872 tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001873 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001874
1875 # 512 char linkname
1876 tarinfo = tarfile.TarInfo("longlink")
1877 tarinfo.linkname = "123/" * 126 + "longname"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001878 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001879
1880 # uid > 8 digits
1881 tarinfo = tarfile.TarInfo("name")
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001882 tarinfo.uid = 0o10000000
Guido van Rossume7ba4952007-06-06 23:52:48 +00001883 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001884
1885 def test_gnu_limits(self):
1886 tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001887 tarinfo.tobuf(tarfile.GNU_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001888
1889 tarinfo = tarfile.TarInfo("longlink")
1890 tarinfo.linkname = "123/" * 126 + "longname"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001891 tarinfo.tobuf(tarfile.GNU_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001892
1893 # uid >= 256 ** 7
1894 tarinfo = tarfile.TarInfo("name")
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001895 tarinfo.uid = 0o4000000000000000000
Guido van Rossume7ba4952007-06-06 23:52:48 +00001896 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.GNU_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001897
1898 def test_pax_limits(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001899 tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001900 tarinfo.tobuf(tarfile.PAX_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001901
1902 tarinfo = tarfile.TarInfo("longlink")
1903 tarinfo.linkname = "123/" * 126 + "longname"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001904 tarinfo.tobuf(tarfile.PAX_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001905
1906 tarinfo = tarfile.TarInfo("name")
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001907 tarinfo.uid = 0o4000000000000000000
Guido van Rossume7ba4952007-06-06 23:52:48 +00001908 tarinfo.tobuf(tarfile.PAX_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001909
1910
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001911class MiscTest(unittest.TestCase):
1912
1913 def test_char_fields(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001914 self.assertEqual(tarfile.stn("foo", 8, "ascii", "strict"),
1915 b"foo\0\0\0\0\0")
1916 self.assertEqual(tarfile.stn("foobar", 3, "ascii", "strict"),
1917 b"foo")
1918 self.assertEqual(tarfile.nts(b"foo\0\0\0\0\0", "ascii", "strict"),
1919 "foo")
1920 self.assertEqual(tarfile.nts(b"foo\0bar\0", "ascii", "strict"),
1921 "foo")
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001922
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001923 def test_read_number_fields(self):
1924 # Issue 13158: Test if GNU tar specific base-256 number fields
1925 # are decoded correctly.
1926 self.assertEqual(tarfile.nti(b"0000001\x00"), 1)
1927 self.assertEqual(tarfile.nti(b"7777777\x00"), 0o7777777)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001928 self.assertEqual(tarfile.nti(b"\x80\x00\x00\x00\x00\x20\x00\x00"),
1929 0o10000000)
1930 self.assertEqual(tarfile.nti(b"\x80\x00\x00\x00\xff\xff\xff\xff"),
1931 0xffffffff)
1932 self.assertEqual(tarfile.nti(b"\xff\xff\xff\xff\xff\xff\xff\xff"),
1933 -1)
1934 self.assertEqual(tarfile.nti(b"\xff\xff\xff\xff\xff\xff\xff\x9c"),
1935 -100)
1936 self.assertEqual(tarfile.nti(b"\xff\x00\x00\x00\x00\x00\x00\x00"),
1937 -0x100000000000000)
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001938
1939 def test_write_number_fields(self):
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001940 self.assertEqual(tarfile.itn(1), b"0000001\x00")
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001941 self.assertEqual(tarfile.itn(0o7777777), b"7777777\x00")
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001942 self.assertEqual(tarfile.itn(0o10000000),
1943 b"\x80\x00\x00\x00\x00\x20\x00\x00")
1944 self.assertEqual(tarfile.itn(0xffffffff),
1945 b"\x80\x00\x00\x00\xff\xff\xff\xff")
1946 self.assertEqual(tarfile.itn(-1),
1947 b"\xff\xff\xff\xff\xff\xff\xff\xff")
1948 self.assertEqual(tarfile.itn(-100),
1949 b"\xff\xff\xff\xff\xff\xff\xff\x9c")
1950 self.assertEqual(tarfile.itn(-0x100000000000000),
1951 b"\xff\x00\x00\x00\x00\x00\x00\x00")
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001952
1953 def test_number_field_limits(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001954 with self.assertRaises(ValueError):
1955 tarfile.itn(-1, 8, tarfile.USTAR_FORMAT)
1956 with self.assertRaises(ValueError):
1957 tarfile.itn(0o10000000, 8, tarfile.USTAR_FORMAT)
1958 with self.assertRaises(ValueError):
1959 tarfile.itn(-0x10000000001, 6, tarfile.GNU_FORMAT)
1960 with self.assertRaises(ValueError):
1961 tarfile.itn(0x10000000000, 6, tarfile.GNU_FORMAT)
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001962
1963
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001964class CommandLineTest(unittest.TestCase):
1965
Serhiy Storchaka255493c2014-02-05 20:54:43 +02001966 def tarfilecmd(self, *args, **kwargs):
1967 rc, out, err = script_helper.assert_python_ok('-m', 'tarfile', *args,
1968 **kwargs)
Antoine Pitrou3b7b1e52013-11-24 01:55:05 +01001969 return out.replace(os.linesep.encode(), b'\n')
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001970
1971 def tarfilecmd_failure(self, *args):
1972 return script_helper.assert_python_failure('-m', 'tarfile', *args)
1973
1974 def make_simple_tarfile(self, tar_name):
1975 files = [support.findfile('tokenize_tests.txt'),
1976 support.findfile('tokenize_tests-no-coding-cookie-'
1977 'and-utf8-bom-sig-only.txt')]
1978 self.addCleanup(support.unlink, tar_name)
1979 with tarfile.open(tar_name, 'w') as tf:
1980 for tardata in files:
1981 tf.add(tardata, arcname=os.path.basename(tardata))
1982
1983 def test_test_command(self):
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02001984 for tar_name in testtarnames:
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001985 for opt in '-t', '--test':
1986 out = self.tarfilecmd(opt, tar_name)
1987 self.assertEqual(out, b'')
1988
1989 def test_test_command_verbose(self):
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02001990 for tar_name in testtarnames:
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001991 for opt in '-v', '--verbose':
1992 out = self.tarfilecmd(opt, '-t', tar_name)
1993 self.assertIn(b'is a tar archive.\n', out)
1994
1995 def test_test_command_invalid_file(self):
1996 zipname = support.findfile('zipdir.zip')
1997 rc, out, err = self.tarfilecmd_failure('-t', zipname)
1998 self.assertIn(b' is not a tar archive.', err)
1999 self.assertEqual(out, b'')
2000 self.assertEqual(rc, 1)
2001
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02002002 for tar_name in testtarnames:
Serhiy Storchakad27b4552013-11-24 01:53:29 +02002003 with self.subTest(tar_name=tar_name):
2004 with open(tar_name, 'rb') as f:
2005 data = f.read()
2006 try:
2007 with open(tmpname, 'wb') as f:
2008 f.write(data[:511])
2009 rc, out, err = self.tarfilecmd_failure('-t', tmpname)
2010 self.assertEqual(out, b'')
2011 self.assertEqual(rc, 1)
2012 finally:
2013 support.unlink(tmpname)
2014
2015 def test_list_command(self):
Serhiy Storchaka255493c2014-02-05 20:54:43 +02002016 for tar_name in testtarnames:
2017 with support.captured_stdout() as t:
2018 with tarfile.open(tar_name, 'r') as tf:
2019 tf.list(verbose=False)
2020 expected = t.getvalue().encode('ascii', 'backslashreplace')
2021 for opt in '-l', '--list':
2022 out = self.tarfilecmd(opt, tar_name,
2023 PYTHONIOENCODING='ascii')
2024 self.assertEqual(out, expected)
Serhiy Storchakad27b4552013-11-24 01:53:29 +02002025
2026 def test_list_command_verbose(self):
Serhiy Storchaka255493c2014-02-05 20:54:43 +02002027 for tar_name in testtarnames:
2028 with support.captured_stdout() as t:
2029 with tarfile.open(tar_name, 'r') as tf:
2030 tf.list(verbose=True)
2031 expected = t.getvalue().encode('ascii', 'backslashreplace')
2032 for opt in '-v', '--verbose':
2033 out = self.tarfilecmd(opt, '-l', tar_name,
2034 PYTHONIOENCODING='ascii')
2035 self.assertEqual(out, expected)
Serhiy Storchakad27b4552013-11-24 01:53:29 +02002036
2037 def test_list_command_invalid_file(self):
2038 zipname = support.findfile('zipdir.zip')
2039 rc, out, err = self.tarfilecmd_failure('-l', zipname)
2040 self.assertIn(b' is not a tar archive.', err)
2041 self.assertEqual(out, b'')
2042 self.assertEqual(rc, 1)
2043
2044 def test_create_command(self):
2045 files = [support.findfile('tokenize_tests.txt'),
2046 support.findfile('tokenize_tests-no-coding-cookie-'
2047 'and-utf8-bom-sig-only.txt')]
2048 for opt in '-c', '--create':
2049 try:
2050 out = self.tarfilecmd(opt, tmpname, *files)
2051 self.assertEqual(out, b'')
2052 with tarfile.open(tmpname) as tar:
2053 tar.getmembers()
2054 finally:
2055 support.unlink(tmpname)
2056
2057 def test_create_command_verbose(self):
2058 files = [support.findfile('tokenize_tests.txt'),
2059 support.findfile('tokenize_tests-no-coding-cookie-'
2060 'and-utf8-bom-sig-only.txt')]
2061 for opt in '-v', '--verbose':
2062 try:
2063 out = self.tarfilecmd(opt, '-c', tmpname, *files)
2064 self.assertIn(b' file created.', out)
2065 with tarfile.open(tmpname) as tar:
2066 tar.getmembers()
2067 finally:
2068 support.unlink(tmpname)
2069
2070 def test_create_command_dotless_filename(self):
2071 files = [support.findfile('tokenize_tests.txt')]
2072 try:
2073 out = self.tarfilecmd('-c', dotlessname, *files)
2074 self.assertEqual(out, b'')
2075 with tarfile.open(dotlessname) as tar:
2076 tar.getmembers()
2077 finally:
2078 support.unlink(dotlessname)
2079
2080 def test_create_command_dot_started_filename(self):
2081 tar_name = os.path.join(TEMPDIR, ".testtar")
2082 files = [support.findfile('tokenize_tests.txt')]
2083 try:
2084 out = self.tarfilecmd('-c', tar_name, *files)
2085 self.assertEqual(out, b'')
2086 with tarfile.open(tar_name) as tar:
2087 tar.getmembers()
2088 finally:
2089 support.unlink(tar_name)
2090
Serhiy Storchaka832dd5f2015-02-10 08:45:53 +02002091 def test_create_command_compressed(self):
2092 files = [support.findfile('tokenize_tests.txt'),
2093 support.findfile('tokenize_tests-no-coding-cookie-'
2094 'and-utf8-bom-sig-only.txt')]
2095 for filetype in (GzipTest, Bz2Test, LzmaTest):
2096 if not filetype.open:
2097 continue
2098 try:
2099 tar_name = tmpname + '.' + filetype.suffix
2100 out = self.tarfilecmd('-c', tar_name, *files)
2101 with filetype.taropen(tar_name) as tar:
2102 tar.getmembers()
2103 finally:
2104 support.unlink(tar_name)
2105
Serhiy Storchakad27b4552013-11-24 01:53:29 +02002106 def test_extract_command(self):
2107 self.make_simple_tarfile(tmpname)
2108 for opt in '-e', '--extract':
2109 try:
2110 with support.temp_cwd(tarextdir):
2111 out = self.tarfilecmd(opt, tmpname)
2112 self.assertEqual(out, b'')
2113 finally:
2114 support.rmtree(tarextdir)
2115
2116 def test_extract_command_verbose(self):
2117 self.make_simple_tarfile(tmpname)
2118 for opt in '-v', '--verbose':
2119 try:
2120 with support.temp_cwd(tarextdir):
2121 out = self.tarfilecmd(opt, '-e', tmpname)
2122 self.assertIn(b' file is extracted.', out)
2123 finally:
2124 support.rmtree(tarextdir)
2125
2126 def test_extract_command_different_directory(self):
2127 self.make_simple_tarfile(tmpname)
2128 try:
2129 with support.temp_cwd(tarextdir):
2130 out = self.tarfilecmd('-e', tmpname, 'spamdir')
2131 self.assertEqual(out, b'')
2132 finally:
2133 support.rmtree(tarextdir)
2134
2135 def test_extract_command_invalid_file(self):
2136 zipname = support.findfile('zipdir.zip')
2137 with support.temp_cwd(tarextdir):
2138 rc, out, err = self.tarfilecmd_failure('-e', zipname)
2139 self.assertIn(b' is not a tar archive.', err)
2140 self.assertEqual(out, b'')
2141 self.assertEqual(rc, 1)
2142
2143
Lars Gustäbel01385812010-03-03 12:08:54 +00002144class ContextManagerTest(unittest.TestCase):
2145
2146 def test_basic(self):
2147 with tarfile.open(tarname) as tar:
2148 self.assertFalse(tar.closed, "closed inside runtime context")
2149 self.assertTrue(tar.closed, "context manager failed")
2150
2151 def test_closed(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002152 # The __enter__() method is supposed to raise OSError
Lars Gustäbel01385812010-03-03 12:08:54 +00002153 # if the TarFile object is already closed.
2154 tar = tarfile.open(tarname)
2155 tar.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002156 with self.assertRaises(OSError):
Lars Gustäbel01385812010-03-03 12:08:54 +00002157 with tar:
2158 pass
2159
2160 def test_exception(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002161 # Test if the OSError exception is passed through properly.
Lars Gustäbel01385812010-03-03 12:08:54 +00002162 with self.assertRaises(Exception) as exc:
2163 with tarfile.open(tarname) as tar:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002164 raise OSError
2165 self.assertIsInstance(exc.exception, OSError,
Lars Gustäbel01385812010-03-03 12:08:54 +00002166 "wrong exception raised in context manager")
2167 self.assertTrue(tar.closed, "context manager failed")
2168
2169 def test_no_eof(self):
2170 # __exit__() must not write end-of-archive blocks if an
2171 # exception was raised.
2172 try:
2173 with tarfile.open(tmpname, "w") as tar:
2174 raise Exception
2175 except:
2176 pass
2177 self.assertEqual(os.path.getsize(tmpname), 0,
2178 "context manager wrote an end-of-archive block")
2179 self.assertTrue(tar.closed, "context manager failed")
2180
2181 def test_eof(self):
2182 # __exit__() must write end-of-archive blocks, i.e. call
2183 # TarFile.close() if there was no error.
2184 with tarfile.open(tmpname, "w"):
2185 pass
2186 self.assertNotEqual(os.path.getsize(tmpname), 0,
2187 "context manager wrote no end-of-archive block")
2188
2189 def test_fileobj(self):
2190 # Test that __exit__() did not close the external file
2191 # object.
Antoine Pitrou95f55602010-09-23 18:36:46 +00002192 with open(tmpname, "wb") as fobj:
2193 try:
2194 with tarfile.open(fileobj=fobj, mode="w") as tar:
2195 raise Exception
2196 except:
2197 pass
2198 self.assertFalse(fobj.closed, "external file object was closed")
2199 self.assertTrue(tar.closed, "context manager failed")
Lars Gustäbel01385812010-03-03 12:08:54 +00002200
2201
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002202@unittest.skipIf(hasattr(os, "link"), "requires os.link to be missing")
2203class LinkEmulationTest(ReadTest, unittest.TestCase):
Lars Gustäbel1b512722010-06-03 12:45:16 +00002204
2205 # Test for issue #8741 regression. On platforms that do not support
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002206 # symbolic or hard links tarfile tries to extract these types of members
2207 # as the regular files they point to.
Lars Gustäbel1b512722010-06-03 12:45:16 +00002208 def _test_link_extraction(self, name):
2209 self.tar.extract(name, TEMPDIR)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002210 with open(os.path.join(TEMPDIR, name), "rb") as f:
2211 data = f.read()
Lars Gustäbel1b512722010-06-03 12:45:16 +00002212 self.assertEqual(md5sum(data), md5_regtype)
2213
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002214 # See issues #1578269, #8879, and #17689 for some history on these skips
Brian Curtind40e6f72010-07-08 21:39:08 +00002215 @unittest.skipIf(hasattr(os.path, "islink"),
2216 "Skip emulation - has os.path.islink but not os.link")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002217 def test_hardlink_extraction1(self):
2218 self._test_link_extraction("ustar/lnktype")
2219
Brian Curtind40e6f72010-07-08 21:39:08 +00002220 @unittest.skipIf(hasattr(os.path, "islink"),
2221 "Skip emulation - has os.path.islink but not os.link")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002222 def test_hardlink_extraction2(self):
2223 self._test_link_extraction("./ustar/linktest2/lnktype")
2224
Brian Curtin74e45612010-07-09 15:58:59 +00002225 @unittest.skipIf(hasattr(os, "symlink"),
2226 "Skip emulation if symlink exists")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002227 def test_symlink_extraction1(self):
2228 self._test_link_extraction("ustar/symtype")
2229
Brian Curtin74e45612010-07-09 15:58:59 +00002230 @unittest.skipIf(hasattr(os, "symlink"),
2231 "Skip emulation if symlink exists")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002232 def test_symlink_extraction2(self):
2233 self._test_link_extraction("./ustar/linktest2/symtype")
2234
2235
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002236class Bz2PartialReadTest(Bz2Test, unittest.TestCase):
Lars Gustäbel42e00912009-03-22 20:34:29 +00002237 # Issue5068: The _BZ2Proxy.read() method loops forever
2238 # on an empty or partial bzipped file.
2239
2240 def _test_partial_input(self, mode):
2241 class MyBytesIO(io.BytesIO):
2242 hit_eof = False
2243 def read(self, n):
2244 if self.hit_eof:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002245 raise AssertionError("infinite loop detected in "
2246 "tarfile.open()")
Lars Gustäbel42e00912009-03-22 20:34:29 +00002247 self.hit_eof = self.tell() == len(self.getvalue())
2248 return super(MyBytesIO, self).read(n)
Lars Gustäbel9520a432009-11-22 18:48:49 +00002249 def seek(self, *args):
2250 self.hit_eof = False
2251 return super(MyBytesIO, self).seek(*args)
Lars Gustäbel42e00912009-03-22 20:34:29 +00002252
2253 data = bz2.compress(tarfile.TarInfo("foo").tobuf())
2254 for x in range(len(data) + 1):
Lars Gustäbel9520a432009-11-22 18:48:49 +00002255 try:
2256 tarfile.open(fileobj=MyBytesIO(data[:x]), mode=mode)
2257 except tarfile.ReadError:
2258 pass # we have no interest in ReadErrors
Lars Gustäbel42e00912009-03-22 20:34:29 +00002259
2260 def test_partial_input(self):
2261 self._test_partial_input("r")
2262
2263 def test_partial_input_bz2(self):
2264 self._test_partial_input("r:bz2")
2265
2266
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002267def setUpModule():
Antoine Pitrou95f55602010-09-23 18:36:46 +00002268 support.unlink(TEMPDIR)
Antoine Pitrou941ee882009-11-11 20:59:38 +00002269 os.makedirs(TEMPDIR)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002270
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02002271 global testtarnames
2272 testtarnames = [tarname]
Antoine Pitrou95f55602010-09-23 18:36:46 +00002273 with open(tarname, "rb") as fobj:
2274 data = fobj.read()
Neal Norwitza4f651a2004-07-20 22:07:44 +00002275
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002276 # Create compressed tarfiles.
2277 for c in GzipTest, Bz2Test, LzmaTest:
2278 if c.open:
2279 support.unlink(c.tarname)
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02002280 testtarnames.append(c.tarname)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002281 with c.open(c.tarname, "wb") as tar:
2282 tar.write(data)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002283
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002284def tearDownModule():
2285 if os.path.exists(TEMPDIR):
Tim Goldene0bd2c52014-05-06 13:24:26 +01002286 support.rmtree(TEMPDIR)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002287
Neal Norwitz996acf12003-02-17 14:51:41 +00002288if __name__ == "__main__":
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002289 unittest.main()