blob: 810b76be53242394c9a3de05dcbc6507fb797fb4 [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
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001431@unittest.skipUnless(hasattr(os, "link"), "Missing hardlink implementation")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001432class HardlinkTest(unittest.TestCase):
1433 # Test the creation of LNKTYPE (hardlink) members in an archive.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001434
1435 def setUp(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001436 self.foo = os.path.join(TEMPDIR, "foo")
1437 self.bar = os.path.join(TEMPDIR, "bar")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001438
Antoine Pitrou95f55602010-09-23 18:36:46 +00001439 with open(self.foo, "wb") as fobj:
1440 fobj.write(b"foo")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001441
Guido van Rossumd8faa362007-04-27 19:54:29 +00001442 os.link(self.foo, self.bar)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001443
Guido van Rossumd8faa362007-04-27 19:54:29 +00001444 self.tar = tarfile.open(tmpname, "w")
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001445 self.tar.add(self.foo)
1446
Guido van Rossumd8faa362007-04-27 19:54:29 +00001447 def tearDown(self):
Hirokazu Yamamotoaf079d42008-09-21 11:50:03 +00001448 self.tar.close()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001449 support.unlink(self.foo)
1450 support.unlink(self.bar)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001451
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001452 def test_add_twice(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001453 # The same name will be added as a REGTYPE every
1454 # time regardless of st_nlink.
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001455 tarinfo = self.tar.gettarinfo(self.foo)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001456 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001457 "add file as regular failed")
1458
1459 def test_add_hardlink(self):
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001460 tarinfo = self.tar.gettarinfo(self.bar)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001461 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001462 "add file as hardlink failed")
1463
1464 def test_dereference_hardlink(self):
1465 self.tar.dereference = True
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001466 tarinfo = self.tar.gettarinfo(self.bar)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001467 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001468 "dereferencing hardlink failed")
1469
Neal Norwitza4f651a2004-07-20 22:07:44 +00001470
Guido van Rossumd8faa362007-04-27 19:54:29 +00001471class PaxWriteTest(GNUWriteTest):
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001472
Guido van Rossumd8faa362007-04-27 19:54:29 +00001473 def _test(self, name, link=None):
1474 # See GNUWriteTest.
1475 tarinfo = tarfile.TarInfo(name)
1476 if link:
1477 tarinfo.linkname = link
1478 tarinfo.type = tarfile.LNKTYPE
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +00001479
Guido van Rossumd8faa362007-04-27 19:54:29 +00001480 tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001481 try:
1482 tar.addfile(tarinfo)
1483 finally:
1484 tar.close()
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +00001485
Guido van Rossumd8faa362007-04-27 19:54:29 +00001486 tar = tarfile.open(tmpname)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001487 try:
1488 if link:
1489 l = tar.getmembers()[0].linkname
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001490 self.assertEqual(link, l, "PAX longlink creation failed")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001491 else:
1492 n = tar.getmembers()[0].name
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001493 self.assertEqual(name, n, "PAX longname creation failed")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001494 finally:
1495 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001496
Guido van Rossume7ba4952007-06-06 23:52:48 +00001497 def test_pax_global_header(self):
1498 pax_headers = {
Guido van Rossum9cbfffd2007-06-07 00:54:15 +00001499 "foo": "bar",
1500 "uid": "0",
1501 "mtime": "1.23",
Guido van Rossuma0557702007-08-07 23:19:53 +00001502 "test": "\xe4\xf6\xfc",
1503 "\xe4\xf6\xfc": "test"}
Guido van Rossume7ba4952007-06-06 23:52:48 +00001504
Benjamin Peterson886af962010-03-21 23:13:07 +00001505 tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT,
Guido van Rossume7ba4952007-06-06 23:52:48 +00001506 pax_headers=pax_headers)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001507 try:
1508 tar.addfile(tarfile.TarInfo("test"))
1509 finally:
1510 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001511
1512 # Test if the global header was written correctly.
1513 tar = tarfile.open(tmpname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001514 try:
1515 self.assertEqual(tar.pax_headers, pax_headers)
1516 self.assertEqual(tar.getmembers()[0].pax_headers, pax_headers)
1517 # Test if all the fields are strings.
1518 for key, val in tar.pax_headers.items():
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001519 self.assertIsNot(type(key), bytes)
1520 self.assertIsNot(type(val), bytes)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001521 if key in tarfile.PAX_NUMBER_FIELDS:
1522 try:
1523 tarfile.PAX_NUMBER_FIELDS[key](val)
1524 except (TypeError, ValueError):
1525 self.fail("unable to convert pax header field")
1526 finally:
1527 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001528
1529 def test_pax_extended_header(self):
1530 # The fields from the pax header have priority over the
1531 # TarInfo.
Guido van Rossum9cbfffd2007-06-07 00:54:15 +00001532 pax_headers = {"path": "foo", "uid": "123"}
Guido van Rossume7ba4952007-06-06 23:52:48 +00001533
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001534 tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT,
1535 encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001536 try:
1537 t = tarfile.TarInfo()
1538 t.name = "\xe4\xf6\xfc" # non-ASCII
1539 t.uid = 8**8 # too large
1540 t.pax_headers = pax_headers
1541 tar.addfile(t)
1542 finally:
1543 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001544
1545 tar = tarfile.open(tmpname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001546 try:
1547 t = tar.getmembers()[0]
1548 self.assertEqual(t.pax_headers, pax_headers)
1549 self.assertEqual(t.name, "foo")
1550 self.assertEqual(t.uid, 123)
1551 finally:
1552 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001553
1554
1555class UstarUnicodeTest(unittest.TestCase):
Guido van Rossume7ba4952007-06-06 23:52:48 +00001556
1557 format = tarfile.USTAR_FORMAT
1558
1559 def test_iso8859_1_filename(self):
1560 self._test_unicode_filename("iso8859-1")
1561
1562 def test_utf7_filename(self):
1563 self._test_unicode_filename("utf7")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001564
1565 def test_utf8_filename(self):
Marc-André Lemburg8f36af72011-02-25 15:42:01 +00001566 self._test_unicode_filename("utf-8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001567
Guido van Rossumd8faa362007-04-27 19:54:29 +00001568 def _test_unicode_filename(self, encoding):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001569 tar = tarfile.open(tmpname, "w", format=self.format,
1570 encoding=encoding, errors="strict")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001571 try:
1572 name = "\xe4\xf6\xfc"
1573 tar.addfile(tarfile.TarInfo(name))
1574 finally:
1575 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001576
1577 tar = tarfile.open(tmpname, encoding=encoding)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001578 try:
1579 self.assertEqual(tar.getmembers()[0].name, name)
1580 finally:
1581 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001582
1583 def test_unicode_filename_error(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001584 tar = tarfile.open(tmpname, "w", format=self.format,
1585 encoding="ascii", errors="strict")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001586 try:
1587 tarinfo = tarfile.TarInfo()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001588
Antoine Pitrou95f55602010-09-23 18:36:46 +00001589 tarinfo.name = "\xe4\xf6\xfc"
1590 self.assertRaises(UnicodeError, tar.addfile, tarinfo)
Guido van Rossume7ba4952007-06-06 23:52:48 +00001591
Antoine Pitrou95f55602010-09-23 18:36:46 +00001592 tarinfo.name = "foo"
1593 tarinfo.uname = "\xe4\xf6\xfc"
1594 self.assertRaises(UnicodeError, tar.addfile, tarinfo)
1595 finally:
1596 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001597
1598 def test_unicode_argument(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001599 tar = tarfile.open(tarname, "r",
1600 encoding="iso8859-1", errors="strict")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001601 try:
1602 for t in tar:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001603 self.assertIs(type(t.name), str)
1604 self.assertIs(type(t.linkname), str)
1605 self.assertIs(type(t.uname), str)
1606 self.assertIs(type(t.gname), str)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001607 finally:
1608 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001609
Guido van Rossume7ba4952007-06-06 23:52:48 +00001610 def test_uname_unicode(self):
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001611 t = tarfile.TarInfo("foo")
1612 t.uname = "\xe4\xf6\xfc"
1613 t.gname = "\xe4\xf6\xfc"
Guido van Rossumd8faa362007-04-27 19:54:29 +00001614
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001615 tar = tarfile.open(tmpname, mode="w", format=self.format,
1616 encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001617 try:
1618 tar.addfile(t)
1619 finally:
1620 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001621
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001622 tar = tarfile.open(tmpname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001623 try:
Guido van Rossume7ba4952007-06-06 23:52:48 +00001624 t = tar.getmember("foo")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001625 self.assertEqual(t.uname, "\xe4\xf6\xfc")
1626 self.assertEqual(t.gname, "\xe4\xf6\xfc")
1627
1628 if self.format != tarfile.PAX_FORMAT:
Antoine Pitrouab58b5f2010-09-23 19:39:35 +00001629 tar.close()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001630 tar = tarfile.open(tmpname, encoding="ascii")
1631 t = tar.getmember("foo")
1632 self.assertEqual(t.uname, "\udce4\udcf6\udcfc")
1633 self.assertEqual(t.gname, "\udce4\udcf6\udcfc")
1634 finally:
1635 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001636
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001637
Guido van Rossume7ba4952007-06-06 23:52:48 +00001638class GNUUnicodeTest(UstarUnicodeTest):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001639
Guido van Rossume7ba4952007-06-06 23:52:48 +00001640 format = tarfile.GNU_FORMAT
Guido van Rossumd8faa362007-04-27 19:54:29 +00001641
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001642 def test_bad_pax_header(self):
1643 # Test for issue #8633. GNU tar <= 1.23 creates raw binary fields
1644 # without a hdrcharset=BINARY header.
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001645 for encoding, name in (
1646 ("utf-8", "pax/bad-pax-\udce4\udcf6\udcfc"),
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001647 ("iso8859-1", "pax/bad-pax-\xe4\xf6\xfc"),):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001648 with tarfile.open(tarname, encoding=encoding,
1649 errors="surrogateescape") as tar:
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001650 try:
1651 t = tar.getmember(name)
1652 except KeyError:
1653 self.fail("unable to read bad GNU tar pax header")
1654
Guido van Rossumd8faa362007-04-27 19:54:29 +00001655
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001656class PAXUnicodeTest(UstarUnicodeTest):
1657
1658 format = tarfile.PAX_FORMAT
1659
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001660 # PAX_FORMAT ignores encoding in write mode.
1661 test_unicode_filename_error = None
1662
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001663 def test_binary_header(self):
1664 # Test a POSIX.1-2008 compatible header with a hdrcharset=BINARY field.
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001665 for encoding, name in (
1666 ("utf-8", "pax/hdrcharset-\udce4\udcf6\udcfc"),
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001667 ("iso8859-1", "pax/hdrcharset-\xe4\xf6\xfc"),):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001668 with tarfile.open(tarname, encoding=encoding,
1669 errors="surrogateescape") as tar:
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001670 try:
1671 t = tar.getmember(name)
1672 except KeyError:
1673 self.fail("unable to read POSIX.1-2008 binary header")
1674
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001675
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001676class AppendTestBase:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001677 # Test append mode (cp. patch #1652681).
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001678
Guido van Rossumd8faa362007-04-27 19:54:29 +00001679 def setUp(self):
1680 self.tarname = tmpname
1681 if os.path.exists(self.tarname):
Tim Goldene0bd2c52014-05-06 13:24:26 +01001682 support.unlink(self.tarname)
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001683
Guido van Rossumd8faa362007-04-27 19:54:29 +00001684 def _create_testtar(self, mode="w:"):
Antoine Pitrou95f55602010-09-23 18:36:46 +00001685 with tarfile.open(tarname, encoding="iso8859-1") as src:
1686 t = src.getmember("ustar/regtype")
1687 t.name = "foo"
Lars Gustäbel7a919e92012-05-05 18:15:03 +02001688 with src.extractfile(t) as f:
Antoine Pitroue1eca4e2010-10-29 23:49:49 +00001689 with tarfile.open(self.tarname, mode) as tar:
1690 tar.addfile(t, f)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001691
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001692 def test_append_compressed(self):
1693 self._create_testtar("w:" + self.suffix)
1694 self.assertRaises(tarfile.ReadError, tarfile.open, tmpname, "a")
1695
1696class AppendTest(AppendTestBase, unittest.TestCase):
1697 test_append_compressed = None
1698
1699 def _add_testfile(self, fileobj=None):
1700 with tarfile.open(self.tarname, "a", fileobj=fileobj) as tar:
1701 tar.addfile(tarfile.TarInfo("bar"))
1702
Guido van Rossumd8faa362007-04-27 19:54:29 +00001703 def _test(self, names=["bar"], fileobj=None):
Antoine Pitrou95f55602010-09-23 18:36:46 +00001704 with tarfile.open(self.tarname, fileobj=fileobj) as tar:
1705 self.assertEqual(tar.getnames(), names)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001706
1707 def test_non_existing(self):
1708 self._add_testfile()
1709 self._test()
1710
1711 def test_empty(self):
Lars Gustäbel9520a432009-11-22 18:48:49 +00001712 tarfile.open(self.tarname, "w:").close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001713 self._add_testfile()
1714 self._test()
1715
1716 def test_empty_fileobj(self):
Lars Gustäbel9520a432009-11-22 18:48:49 +00001717 fobj = io.BytesIO(b"\0" * 1024)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001718 self._add_testfile(fobj)
1719 fobj.seek(0)
1720 self._test(fileobj=fobj)
1721
1722 def test_fileobj(self):
1723 self._create_testtar()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001724 with open(self.tarname, "rb") as fobj:
1725 data = fobj.read()
Guido van Rossum34d19282007-08-09 01:03:29 +00001726 fobj = io.BytesIO(data)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001727 self._add_testfile(fobj)
1728 fobj.seek(0)
1729 self._test(names=["foo", "bar"], fileobj=fobj)
1730
1731 def test_existing(self):
1732 self._create_testtar()
1733 self._add_testfile()
1734 self._test(names=["foo", "bar"])
1735
Lars Gustäbel9520a432009-11-22 18:48:49 +00001736 # Append mode is supposed to fail if the tarfile to append to
1737 # does not end with a zero block.
1738 def _test_error(self, data):
Antoine Pitrou95f55602010-09-23 18:36:46 +00001739 with open(self.tarname, "wb") as fobj:
1740 fobj.write(data)
Lars Gustäbel9520a432009-11-22 18:48:49 +00001741 self.assertRaises(tarfile.ReadError, self._add_testfile)
1742
1743 def test_null(self):
1744 self._test_error(b"")
1745
1746 def test_incomplete(self):
1747 self._test_error(b"\0" * 13)
1748
1749 def test_premature_eof(self):
1750 data = tarfile.TarInfo("foo").tobuf()
1751 self._test_error(data)
1752
1753 def test_trailing_garbage(self):
1754 data = tarfile.TarInfo("foo").tobuf()
1755 self._test_error(data + b"\0" * 13)
1756
1757 def test_invalid(self):
1758 self._test_error(b"a" * 512)
1759
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001760class GzipAppendTest(GzipTest, AppendTestBase, unittest.TestCase):
1761 pass
1762
1763class Bz2AppendTest(Bz2Test, AppendTestBase, unittest.TestCase):
1764 pass
1765
1766class LzmaAppendTest(LzmaTest, AppendTestBase, unittest.TestCase):
1767 pass
1768
Guido van Rossumd8faa362007-04-27 19:54:29 +00001769
1770class LimitsTest(unittest.TestCase):
1771
1772 def test_ustar_limits(self):
1773 # 100 char name
1774 tarinfo = tarfile.TarInfo("0123456789" * 10)
Guido van Rossume7ba4952007-06-06 23:52:48 +00001775 tarinfo.tobuf(tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001776
1777 # 101 char name that cannot be stored
1778 tarinfo = tarfile.TarInfo("0123456789" * 10 + "0")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001779 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001780
1781 # 256 char name with a slash at pos 156
1782 tarinfo = tarfile.TarInfo("123/" * 62 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001783 tarinfo.tobuf(tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001784
1785 # 256 char name that cannot be stored
1786 tarinfo = tarfile.TarInfo("1234567/" * 31 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001787 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001788
1789 # 512 char name
1790 tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001791 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001792
1793 # 512 char linkname
1794 tarinfo = tarfile.TarInfo("longlink")
1795 tarinfo.linkname = "123/" * 126 + "longname"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001796 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001797
1798 # uid > 8 digits
1799 tarinfo = tarfile.TarInfo("name")
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001800 tarinfo.uid = 0o10000000
Guido van Rossume7ba4952007-06-06 23:52:48 +00001801 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001802
1803 def test_gnu_limits(self):
1804 tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001805 tarinfo.tobuf(tarfile.GNU_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001806
1807 tarinfo = tarfile.TarInfo("longlink")
1808 tarinfo.linkname = "123/" * 126 + "longname"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001809 tarinfo.tobuf(tarfile.GNU_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001810
1811 # uid >= 256 ** 7
1812 tarinfo = tarfile.TarInfo("name")
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001813 tarinfo.uid = 0o4000000000000000000
Guido van Rossume7ba4952007-06-06 23:52:48 +00001814 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.GNU_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001815
1816 def test_pax_limits(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001817 tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001818 tarinfo.tobuf(tarfile.PAX_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001819
1820 tarinfo = tarfile.TarInfo("longlink")
1821 tarinfo.linkname = "123/" * 126 + "longname"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001822 tarinfo.tobuf(tarfile.PAX_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001823
1824 tarinfo = tarfile.TarInfo("name")
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001825 tarinfo.uid = 0o4000000000000000000
Guido van Rossume7ba4952007-06-06 23:52:48 +00001826 tarinfo.tobuf(tarfile.PAX_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001827
1828
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001829class MiscTest(unittest.TestCase):
1830
1831 def test_char_fields(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001832 self.assertEqual(tarfile.stn("foo", 8, "ascii", "strict"),
1833 b"foo\0\0\0\0\0")
1834 self.assertEqual(tarfile.stn("foobar", 3, "ascii", "strict"),
1835 b"foo")
1836 self.assertEqual(tarfile.nts(b"foo\0\0\0\0\0", "ascii", "strict"),
1837 "foo")
1838 self.assertEqual(tarfile.nts(b"foo\0bar\0", "ascii", "strict"),
1839 "foo")
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001840
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001841 def test_read_number_fields(self):
1842 # Issue 13158: Test if GNU tar specific base-256 number fields
1843 # are decoded correctly.
1844 self.assertEqual(tarfile.nti(b"0000001\x00"), 1)
1845 self.assertEqual(tarfile.nti(b"7777777\x00"), 0o7777777)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001846 self.assertEqual(tarfile.nti(b"\x80\x00\x00\x00\x00\x20\x00\x00"),
1847 0o10000000)
1848 self.assertEqual(tarfile.nti(b"\x80\x00\x00\x00\xff\xff\xff\xff"),
1849 0xffffffff)
1850 self.assertEqual(tarfile.nti(b"\xff\xff\xff\xff\xff\xff\xff\xff"),
1851 -1)
1852 self.assertEqual(tarfile.nti(b"\xff\xff\xff\xff\xff\xff\xff\x9c"),
1853 -100)
1854 self.assertEqual(tarfile.nti(b"\xff\x00\x00\x00\x00\x00\x00\x00"),
1855 -0x100000000000000)
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001856
1857 def test_write_number_fields(self):
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001858 self.assertEqual(tarfile.itn(1), b"0000001\x00")
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001859 self.assertEqual(tarfile.itn(0o7777777), b"7777777\x00")
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001860 self.assertEqual(tarfile.itn(0o10000000),
1861 b"\x80\x00\x00\x00\x00\x20\x00\x00")
1862 self.assertEqual(tarfile.itn(0xffffffff),
1863 b"\x80\x00\x00\x00\xff\xff\xff\xff")
1864 self.assertEqual(tarfile.itn(-1),
1865 b"\xff\xff\xff\xff\xff\xff\xff\xff")
1866 self.assertEqual(tarfile.itn(-100),
1867 b"\xff\xff\xff\xff\xff\xff\xff\x9c")
1868 self.assertEqual(tarfile.itn(-0x100000000000000),
1869 b"\xff\x00\x00\x00\x00\x00\x00\x00")
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001870
1871 def test_number_field_limits(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001872 with self.assertRaises(ValueError):
1873 tarfile.itn(-1, 8, tarfile.USTAR_FORMAT)
1874 with self.assertRaises(ValueError):
1875 tarfile.itn(0o10000000, 8, tarfile.USTAR_FORMAT)
1876 with self.assertRaises(ValueError):
1877 tarfile.itn(-0x10000000001, 6, tarfile.GNU_FORMAT)
1878 with self.assertRaises(ValueError):
1879 tarfile.itn(0x10000000000, 6, tarfile.GNU_FORMAT)
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001880
1881
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001882class CommandLineTest(unittest.TestCase):
1883
Serhiy Storchaka255493c2014-02-05 20:54:43 +02001884 def tarfilecmd(self, *args, **kwargs):
1885 rc, out, err = script_helper.assert_python_ok('-m', 'tarfile', *args,
1886 **kwargs)
Antoine Pitrou3b7b1e52013-11-24 01:55:05 +01001887 return out.replace(os.linesep.encode(), b'\n')
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001888
1889 def tarfilecmd_failure(self, *args):
1890 return script_helper.assert_python_failure('-m', 'tarfile', *args)
1891
1892 def make_simple_tarfile(self, tar_name):
1893 files = [support.findfile('tokenize_tests.txt'),
1894 support.findfile('tokenize_tests-no-coding-cookie-'
1895 'and-utf8-bom-sig-only.txt')]
1896 self.addCleanup(support.unlink, tar_name)
1897 with tarfile.open(tar_name, 'w') as tf:
1898 for tardata in files:
1899 tf.add(tardata, arcname=os.path.basename(tardata))
1900
1901 def test_test_command(self):
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02001902 for tar_name in testtarnames:
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001903 for opt in '-t', '--test':
1904 out = self.tarfilecmd(opt, tar_name)
1905 self.assertEqual(out, b'')
1906
1907 def test_test_command_verbose(self):
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02001908 for tar_name in testtarnames:
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001909 for opt in '-v', '--verbose':
1910 out = self.tarfilecmd(opt, '-t', tar_name)
1911 self.assertIn(b'is a tar archive.\n', out)
1912
1913 def test_test_command_invalid_file(self):
1914 zipname = support.findfile('zipdir.zip')
1915 rc, out, err = self.tarfilecmd_failure('-t', zipname)
1916 self.assertIn(b' is not a tar archive.', err)
1917 self.assertEqual(out, b'')
1918 self.assertEqual(rc, 1)
1919
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02001920 for tar_name in testtarnames:
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001921 with self.subTest(tar_name=tar_name):
1922 with open(tar_name, 'rb') as f:
1923 data = f.read()
1924 try:
1925 with open(tmpname, 'wb') as f:
1926 f.write(data[:511])
1927 rc, out, err = self.tarfilecmd_failure('-t', tmpname)
1928 self.assertEqual(out, b'')
1929 self.assertEqual(rc, 1)
1930 finally:
1931 support.unlink(tmpname)
1932
1933 def test_list_command(self):
Serhiy Storchaka255493c2014-02-05 20:54:43 +02001934 for tar_name in testtarnames:
1935 with support.captured_stdout() as t:
1936 with tarfile.open(tar_name, 'r') as tf:
1937 tf.list(verbose=False)
1938 expected = t.getvalue().encode('ascii', 'backslashreplace')
1939 for opt in '-l', '--list':
1940 out = self.tarfilecmd(opt, tar_name,
1941 PYTHONIOENCODING='ascii')
1942 self.assertEqual(out, expected)
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001943
1944 def test_list_command_verbose(self):
Serhiy Storchaka255493c2014-02-05 20:54:43 +02001945 for tar_name in testtarnames:
1946 with support.captured_stdout() as t:
1947 with tarfile.open(tar_name, 'r') as tf:
1948 tf.list(verbose=True)
1949 expected = t.getvalue().encode('ascii', 'backslashreplace')
1950 for opt in '-v', '--verbose':
1951 out = self.tarfilecmd(opt, '-l', tar_name,
1952 PYTHONIOENCODING='ascii')
1953 self.assertEqual(out, expected)
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001954
1955 def test_list_command_invalid_file(self):
1956 zipname = support.findfile('zipdir.zip')
1957 rc, out, err = self.tarfilecmd_failure('-l', zipname)
1958 self.assertIn(b' is not a tar archive.', err)
1959 self.assertEqual(out, b'')
1960 self.assertEqual(rc, 1)
1961
1962 def test_create_command(self):
1963 files = [support.findfile('tokenize_tests.txt'),
1964 support.findfile('tokenize_tests-no-coding-cookie-'
1965 'and-utf8-bom-sig-only.txt')]
1966 for opt in '-c', '--create':
1967 try:
1968 out = self.tarfilecmd(opt, tmpname, *files)
1969 self.assertEqual(out, b'')
1970 with tarfile.open(tmpname) as tar:
1971 tar.getmembers()
1972 finally:
1973 support.unlink(tmpname)
1974
1975 def test_create_command_verbose(self):
1976 files = [support.findfile('tokenize_tests.txt'),
1977 support.findfile('tokenize_tests-no-coding-cookie-'
1978 'and-utf8-bom-sig-only.txt')]
1979 for opt in '-v', '--verbose':
1980 try:
1981 out = self.tarfilecmd(opt, '-c', tmpname, *files)
1982 self.assertIn(b' file created.', out)
1983 with tarfile.open(tmpname) as tar:
1984 tar.getmembers()
1985 finally:
1986 support.unlink(tmpname)
1987
1988 def test_create_command_dotless_filename(self):
1989 files = [support.findfile('tokenize_tests.txt')]
1990 try:
1991 out = self.tarfilecmd('-c', dotlessname, *files)
1992 self.assertEqual(out, b'')
1993 with tarfile.open(dotlessname) as tar:
1994 tar.getmembers()
1995 finally:
1996 support.unlink(dotlessname)
1997
1998 def test_create_command_dot_started_filename(self):
1999 tar_name = os.path.join(TEMPDIR, ".testtar")
2000 files = [support.findfile('tokenize_tests.txt')]
2001 try:
2002 out = self.tarfilecmd('-c', tar_name, *files)
2003 self.assertEqual(out, b'')
2004 with tarfile.open(tar_name) as tar:
2005 tar.getmembers()
2006 finally:
2007 support.unlink(tar_name)
2008
2009 def test_extract_command(self):
2010 self.make_simple_tarfile(tmpname)
2011 for opt in '-e', '--extract':
2012 try:
2013 with support.temp_cwd(tarextdir):
2014 out = self.tarfilecmd(opt, tmpname)
2015 self.assertEqual(out, b'')
2016 finally:
2017 support.rmtree(tarextdir)
2018
2019 def test_extract_command_verbose(self):
2020 self.make_simple_tarfile(tmpname)
2021 for opt in '-v', '--verbose':
2022 try:
2023 with support.temp_cwd(tarextdir):
2024 out = self.tarfilecmd(opt, '-e', tmpname)
2025 self.assertIn(b' file is extracted.', out)
2026 finally:
2027 support.rmtree(tarextdir)
2028
2029 def test_extract_command_different_directory(self):
2030 self.make_simple_tarfile(tmpname)
2031 try:
2032 with support.temp_cwd(tarextdir):
2033 out = self.tarfilecmd('-e', tmpname, 'spamdir')
2034 self.assertEqual(out, b'')
2035 finally:
2036 support.rmtree(tarextdir)
2037
2038 def test_extract_command_invalid_file(self):
2039 zipname = support.findfile('zipdir.zip')
2040 with support.temp_cwd(tarextdir):
2041 rc, out, err = self.tarfilecmd_failure('-e', zipname)
2042 self.assertIn(b' is not a tar archive.', err)
2043 self.assertEqual(out, b'')
2044 self.assertEqual(rc, 1)
2045
2046
Lars Gustäbel01385812010-03-03 12:08:54 +00002047class ContextManagerTest(unittest.TestCase):
2048
2049 def test_basic(self):
2050 with tarfile.open(tarname) as tar:
2051 self.assertFalse(tar.closed, "closed inside runtime context")
2052 self.assertTrue(tar.closed, "context manager failed")
2053
2054 def test_closed(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002055 # The __enter__() method is supposed to raise OSError
Lars Gustäbel01385812010-03-03 12:08:54 +00002056 # if the TarFile object is already closed.
2057 tar = tarfile.open(tarname)
2058 tar.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002059 with self.assertRaises(OSError):
Lars Gustäbel01385812010-03-03 12:08:54 +00002060 with tar:
2061 pass
2062
2063 def test_exception(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002064 # Test if the OSError exception is passed through properly.
Lars Gustäbel01385812010-03-03 12:08:54 +00002065 with self.assertRaises(Exception) as exc:
2066 with tarfile.open(tarname) as tar:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002067 raise OSError
2068 self.assertIsInstance(exc.exception, OSError,
Lars Gustäbel01385812010-03-03 12:08:54 +00002069 "wrong exception raised in context manager")
2070 self.assertTrue(tar.closed, "context manager failed")
2071
2072 def test_no_eof(self):
2073 # __exit__() must not write end-of-archive blocks if an
2074 # exception was raised.
2075 try:
2076 with tarfile.open(tmpname, "w") as tar:
2077 raise Exception
2078 except:
2079 pass
2080 self.assertEqual(os.path.getsize(tmpname), 0,
2081 "context manager wrote an end-of-archive block")
2082 self.assertTrue(tar.closed, "context manager failed")
2083
2084 def test_eof(self):
2085 # __exit__() must write end-of-archive blocks, i.e. call
2086 # TarFile.close() if there was no error.
2087 with tarfile.open(tmpname, "w"):
2088 pass
2089 self.assertNotEqual(os.path.getsize(tmpname), 0,
2090 "context manager wrote no end-of-archive block")
2091
2092 def test_fileobj(self):
2093 # Test that __exit__() did not close the external file
2094 # object.
Antoine Pitrou95f55602010-09-23 18:36:46 +00002095 with open(tmpname, "wb") as fobj:
2096 try:
2097 with tarfile.open(fileobj=fobj, mode="w") as tar:
2098 raise Exception
2099 except:
2100 pass
2101 self.assertFalse(fobj.closed, "external file object was closed")
2102 self.assertTrue(tar.closed, "context manager failed")
Lars Gustäbel01385812010-03-03 12:08:54 +00002103
2104
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002105@unittest.skipIf(hasattr(os, "link"), "requires os.link to be missing")
2106class LinkEmulationTest(ReadTest, unittest.TestCase):
Lars Gustäbel1b512722010-06-03 12:45:16 +00002107
2108 # Test for issue #8741 regression. On platforms that do not support
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002109 # symbolic or hard links tarfile tries to extract these types of members
2110 # as the regular files they point to.
Lars Gustäbel1b512722010-06-03 12:45:16 +00002111 def _test_link_extraction(self, name):
2112 self.tar.extract(name, TEMPDIR)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002113 with open(os.path.join(TEMPDIR, name), "rb") as f:
2114 data = f.read()
Lars Gustäbel1b512722010-06-03 12:45:16 +00002115 self.assertEqual(md5sum(data), md5_regtype)
2116
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002117 # See issues #1578269, #8879, and #17689 for some history on these skips
Brian Curtind40e6f72010-07-08 21:39:08 +00002118 @unittest.skipIf(hasattr(os.path, "islink"),
2119 "Skip emulation - has os.path.islink but not os.link")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002120 def test_hardlink_extraction1(self):
2121 self._test_link_extraction("ustar/lnktype")
2122
Brian Curtind40e6f72010-07-08 21:39:08 +00002123 @unittest.skipIf(hasattr(os.path, "islink"),
2124 "Skip emulation - has os.path.islink but not os.link")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002125 def test_hardlink_extraction2(self):
2126 self._test_link_extraction("./ustar/linktest2/lnktype")
2127
Brian Curtin74e45612010-07-09 15:58:59 +00002128 @unittest.skipIf(hasattr(os, "symlink"),
2129 "Skip emulation if symlink exists")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002130 def test_symlink_extraction1(self):
2131 self._test_link_extraction("ustar/symtype")
2132
Brian Curtin74e45612010-07-09 15:58:59 +00002133 @unittest.skipIf(hasattr(os, "symlink"),
2134 "Skip emulation if symlink exists")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002135 def test_symlink_extraction2(self):
2136 self._test_link_extraction("./ustar/linktest2/symtype")
2137
2138
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002139class Bz2PartialReadTest(Bz2Test, unittest.TestCase):
Lars Gustäbel42e00912009-03-22 20:34:29 +00002140 # Issue5068: The _BZ2Proxy.read() method loops forever
2141 # on an empty or partial bzipped file.
2142
2143 def _test_partial_input(self, mode):
2144 class MyBytesIO(io.BytesIO):
2145 hit_eof = False
2146 def read(self, n):
2147 if self.hit_eof:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002148 raise AssertionError("infinite loop detected in "
2149 "tarfile.open()")
Lars Gustäbel42e00912009-03-22 20:34:29 +00002150 self.hit_eof = self.tell() == len(self.getvalue())
2151 return super(MyBytesIO, self).read(n)
Lars Gustäbel9520a432009-11-22 18:48:49 +00002152 def seek(self, *args):
2153 self.hit_eof = False
2154 return super(MyBytesIO, self).seek(*args)
Lars Gustäbel42e00912009-03-22 20:34:29 +00002155
2156 data = bz2.compress(tarfile.TarInfo("foo").tobuf())
2157 for x in range(len(data) + 1):
Lars Gustäbel9520a432009-11-22 18:48:49 +00002158 try:
2159 tarfile.open(fileobj=MyBytesIO(data[:x]), mode=mode)
2160 except tarfile.ReadError:
2161 pass # we have no interest in ReadErrors
Lars Gustäbel42e00912009-03-22 20:34:29 +00002162
2163 def test_partial_input(self):
2164 self._test_partial_input("r")
2165
2166 def test_partial_input_bz2(self):
2167 self._test_partial_input("r:bz2")
2168
2169
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002170def setUpModule():
Antoine Pitrou95f55602010-09-23 18:36:46 +00002171 support.unlink(TEMPDIR)
Antoine Pitrou941ee882009-11-11 20:59:38 +00002172 os.makedirs(TEMPDIR)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002173
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02002174 global testtarnames
2175 testtarnames = [tarname]
Antoine Pitrou95f55602010-09-23 18:36:46 +00002176 with open(tarname, "rb") as fobj:
2177 data = fobj.read()
Neal Norwitza4f651a2004-07-20 22:07:44 +00002178
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002179 # Create compressed tarfiles.
2180 for c in GzipTest, Bz2Test, LzmaTest:
2181 if c.open:
2182 support.unlink(c.tarname)
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02002183 testtarnames.append(c.tarname)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002184 with c.open(c.tarname, "wb") as tar:
2185 tar.write(data)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002186
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002187def tearDownModule():
2188 if os.path.exists(TEMPDIR):
Tim Goldene0bd2c52014-05-06 13:24:26 +01002189 support.rmtree(TEMPDIR)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002190
Neal Norwitz996acf12003-02-17 14:51:41 +00002191if __name__ == "__main__":
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002192 unittest.main()