blob: d828979c4728ee59a7591d50b71dcf8a8c84fe98 [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
288
289class GzipListTest(GzipTest, ListTest):
290 pass
291
292
293class Bz2ListTest(Bz2Test, ListTest):
294 pass
295
296
297class LzmaListTest(LzmaTest, ListTest):
298 pass
299
300
Lars Gustäbel9520a432009-11-22 18:48:49 +0000301class CommonReadTest(ReadTest):
302
303 def test_empty_tarfile(self):
304 # Test for issue6123: Allow opening empty archives.
305 # This test checks if tarfile.open() is able to open an empty tar
306 # archive successfully. Note that an empty tar archive is not the
307 # same as an empty file!
Antoine Pitrou95f55602010-09-23 18:36:46 +0000308 with tarfile.open(tmpname, self.mode.replace("r", "w")):
309 pass
Lars Gustäbel9520a432009-11-22 18:48:49 +0000310 try:
311 tar = tarfile.open(tmpname, self.mode)
312 tar.getnames()
313 except tarfile.ReadError:
314 self.fail("tarfile.open() failed on empty archive")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000315 else:
316 self.assertListEqual(tar.getmembers(), [])
317 finally:
318 tar.close()
Lars Gustäbel9520a432009-11-22 18:48:49 +0000319
Serhiy Storchakaf22fe0f2014-01-13 19:08:00 +0200320 def test_non_existent_tarfile(self):
321 # Test for issue11513: prevent non-existent gzipped tarfiles raising
322 # multiple exceptions.
323 with self.assertRaisesRegex(FileNotFoundError, "xxx"):
324 tarfile.open("xxx", self.mode)
325
Lars Gustäbel9520a432009-11-22 18:48:49 +0000326 def test_null_tarfile(self):
327 # Test for issue6123: Allow opening empty archives.
328 # This test guarantees that tarfile.open() does not treat an empty
329 # file as an empty tar archive.
Antoine Pitrou95f55602010-09-23 18:36:46 +0000330 with open(tmpname, "wb"):
331 pass
Lars Gustäbel9520a432009-11-22 18:48:49 +0000332 self.assertRaises(tarfile.ReadError, tarfile.open, tmpname, self.mode)
333 self.assertRaises(tarfile.ReadError, tarfile.open, tmpname)
334
335 def test_ignore_zeros(self):
336 # Test TarFile's ignore_zeros option.
Lars Gustäbel9520a432009-11-22 18:48:49 +0000337 for char in (b'\0', b'a'):
338 # Test if EOFHeaderError ('\0') and InvalidHeaderError ('a')
339 # are ignored correctly.
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300340 with self.open(tmpname, "w") as fobj:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000341 fobj.write(char * 1024)
342 fobj.write(tarfile.TarInfo("foo").tobuf())
Lars Gustäbel9520a432009-11-22 18:48:49 +0000343
344 tar = tarfile.open(tmpname, mode="r", ignore_zeros=True)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000345 try:
346 self.assertListEqual(tar.getnames(), ["foo"],
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300347 "ignore_zeros=True should have skipped the %r-blocks" %
348 char)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000349 finally:
350 tar.close()
Lars Gustäbel9520a432009-11-22 18:48:49 +0000351
352
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300353class MiscReadTestBase(CommonReadTest):
Thomas Woutersed03b412007-08-28 21:37:11 +0000354 def test_no_name_argument(self):
Antoine Pitrou95f55602010-09-23 18:36:46 +0000355 with open(self.tarname, "rb") as fobj:
356 tar = tarfile.open(fileobj=fobj, mode=self.mode)
357 self.assertEqual(tar.name, os.path.abspath(fobj.name))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000358
Thomas Woutersed03b412007-08-28 21:37:11 +0000359 def test_no_name_attribute(self):
Antoine Pitrou95f55602010-09-23 18:36:46 +0000360 with open(self.tarname, "rb") as fobj:
361 data = fobj.read()
Thomas Woutersed03b412007-08-28 21:37:11 +0000362 fobj = io.BytesIO(data)
363 self.assertRaises(AttributeError, getattr, fobj, "name")
364 tar = tarfile.open(fileobj=fobj, mode=self.mode)
365 self.assertEqual(tar.name, None)
366
367 def test_empty_name_attribute(self):
Antoine Pitrou95f55602010-09-23 18:36:46 +0000368 with open(self.tarname, "rb") as fobj:
369 data = fobj.read()
Thomas Woutersed03b412007-08-28 21:37:11 +0000370 fobj = io.BytesIO(data)
371 fobj.name = ""
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000372 with tarfile.open(fileobj=fobj, mode=self.mode) as tar:
373 self.assertEqual(tar.name, None)
Thomas Woutersed03b412007-08-28 21:37:11 +0000374
Serhiy Storchaka53ad0cd2014-01-18 15:35:37 +0200375 def test_illegal_mode_arg(self):
376 with open(tmpname, 'wb'):
377 pass
378 with self.assertRaisesRegex(ValueError, 'mode must be '):
379 tar = self.taropen(tmpname, 'q')
380 with self.assertRaisesRegex(ValueError, 'mode must be '):
381 tar = self.taropen(tmpname, 'rw')
382 with self.assertRaisesRegex(ValueError, 'mode must be '):
383 tar = self.taropen(tmpname, '')
384
Christian Heimesd8654cf2007-12-02 15:22:16 +0000385 def test_fileobj_with_offset(self):
386 # Skip the first member and store values from the second member
387 # of the testtar.
388 tar = tarfile.open(self.tarname, mode=self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000389 try:
390 tar.next()
391 t = tar.next()
392 name = t.name
393 offset = t.offset
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200394 with tar.extractfile(t) as f:
395 data = f.read()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000396 finally:
397 tar.close()
Christian Heimesd8654cf2007-12-02 15:22:16 +0000398
399 # Open the testtar and seek to the offset of the second member.
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300400 with self.open(self.tarname) as fobj:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000401 fobj.seek(offset)
Christian Heimesd8654cf2007-12-02 15:22:16 +0000402
Antoine Pitrou95f55602010-09-23 18:36:46 +0000403 # Test if the tarfile starts with the second member.
404 tar = tar.open(self.tarname, mode="r:", fileobj=fobj)
405 t = tar.next()
406 self.assertEqual(t.name, name)
407 # Read to the end of fileobj and test if seeking back to the
408 # beginning works.
409 tar.getmembers()
410 self.assertEqual(tar.extractfile(t).read(), data,
411 "seek back did not work")
412 tar.close()
Christian Heimesd8654cf2007-12-02 15:22:16 +0000413
Guido van Rossumd8faa362007-04-27 19:54:29 +0000414 def test_fail_comp(self):
415 # For Gzip and Bz2 Tests: fail with a ReadError on an uncompressed file.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000416 self.assertRaises(tarfile.ReadError, tarfile.open, tarname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000417 with open(tarname, "rb") as fobj:
418 self.assertRaises(tarfile.ReadError, tarfile.open,
419 fileobj=fobj, mode=self.mode)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000420
421 def test_v7_dirtype(self):
422 # Test old style dirtype member (bug #1336623):
423 # Old V7 tars create directory members using an AREGTYPE
424 # header with a "/" appended to the filename field.
425 tarinfo = self.tar.getmember("misc/dirtype-old-v7")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300426 self.assertEqual(tarinfo.type, tarfile.DIRTYPE,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000427 "v7 dirtype failed")
428
Christian Heimes126d29a2008-02-11 22:57:17 +0000429 def test_xstar_type(self):
430 # The xstar format stores extra atime and ctime fields inside the
431 # space reserved for the prefix field. The prefix field must be
432 # ignored in this case, otherwise it will mess up the name.
433 try:
434 self.tar.getmember("misc/regtype-xstar")
435 except KeyError:
436 self.fail("failed to find misc/regtype-xstar (mangled prefix?)")
437
Guido van Rossumd8faa362007-04-27 19:54:29 +0000438 def test_check_members(self):
439 for tarinfo in self.tar:
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300440 self.assertEqual(int(tarinfo.mtime), 0o7606136617,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000441 "wrong mtime for %s" % tarinfo.name)
442 if not tarinfo.name.startswith("ustar/"):
443 continue
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300444 self.assertEqual(tarinfo.uname, "tarfile",
Guido van Rossumd8faa362007-04-27 19:54:29 +0000445 "wrong uname for %s" % tarinfo.name)
446
447 def test_find_members(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300448 self.assertEqual(self.tar.getmembers()[-1].name, "misc/eof",
Guido van Rossumd8faa362007-04-27 19:54:29 +0000449 "could not find all members")
450
Brian Curtin74e45612010-07-09 15:58:59 +0000451 @unittest.skipUnless(hasattr(os, "link"),
452 "Missing hardlink implementation")
Brian Curtin3b4499c2010-12-28 14:31:47 +0000453 @support.skip_unless_symlink
Guido van Rossumd8faa362007-04-27 19:54:29 +0000454 def test_extract_hardlink(self):
455 # Test hardlink extraction (e.g. bug #857297).
Serhiy Storchaka88339c42012-12-30 20:16:30 +0200456 with tarfile.open(tarname, errorlevel=1, encoding="iso8859-1") as tar:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000457 tar.extract("ustar/regtype", TEMPDIR)
Tim Goldene0bd2c52014-05-06 13:24:26 +0100458 self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/regtype"))
Neal Norwitzf3396542005-10-28 05:52:22 +0000459
Serhiy Storchaka88339c42012-12-30 20:16:30 +0200460 tar.extract("ustar/lnktype", TEMPDIR)
Tim Goldene0bd2c52014-05-06 13:24:26 +0100461 self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/lnktype"))
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000462 with open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb") as f:
463 data = f.read()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000464 self.assertEqual(md5sum(data), md5_regtype)
Neal Norwitzf3396542005-10-28 05:52:22 +0000465
Serhiy Storchaka88339c42012-12-30 20:16:30 +0200466 tar.extract("ustar/symtype", TEMPDIR)
Tim Goldene0bd2c52014-05-06 13:24:26 +0100467 self.addCleanup(support.unlink, os.path.join(TEMPDIR, "ustar/symtype"))
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000468 with open(os.path.join(TEMPDIR, "ustar/symtype"), "rb") as f:
469 data = f.read()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000470 self.assertEqual(md5sum(data), md5_regtype)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000471
Christian Heimesfaf2f632008-01-06 16:59:19 +0000472 def test_extractall(self):
473 # Test if extractall() correctly restores directory permissions
474 # and times (see issue1735).
Christian Heimesfaf2f632008-01-06 16:59:19 +0000475 tar = tarfile.open(tarname, encoding="iso8859-1")
Martin v. Löwisbe647e22010-11-01 22:08:46 +0000476 DIR = os.path.join(TEMPDIR, "extractall")
477 os.mkdir(DIR)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000478 try:
479 directories = [t for t in tar if t.isdir()]
Martin v. Löwisbe647e22010-11-01 22:08:46 +0000480 tar.extractall(DIR, directories)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000481 for tarinfo in directories:
Martin v. Löwisbe647e22010-11-01 22:08:46 +0000482 path = os.path.join(DIR, tarinfo.name)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000483 if sys.platform != "win32":
484 # Win32 has no support for fine grained permissions.
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300485 self.assertEqual(tarinfo.mode & 0o777,
486 os.stat(path).st_mode & 0o777)
Victor Stinner26bfb5a2010-10-29 10:59:08 +0000487 def format_mtime(mtime):
488 if isinstance(mtime, float):
489 return "{} ({})".format(mtime, mtime.hex())
490 else:
491 return "{!r} (int)".format(mtime)
Victor Stinner14d8fe72010-10-29 11:02:06 +0000492 file_mtime = os.path.getmtime(path)
Victor Stinner26bfb5a2010-10-29 10:59:08 +0000493 errmsg = "tar mtime {0} != file time {1} of path {2!a}".format(
494 format_mtime(tarinfo.mtime),
495 format_mtime(file_mtime),
496 path)
497 self.assertEqual(tarinfo.mtime, file_mtime, errmsg)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000498 finally:
499 tar.close()
Tim Goldene0bd2c52014-05-06 13:24:26 +0100500 support.rmtree(DIR)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000501
Martin v. Löwis16f344d2010-11-01 21:39:13 +0000502 def test_extract_directory(self):
503 dirtype = "ustar/dirtype"
Martin v. Löwisbe647e22010-11-01 22:08:46 +0000504 DIR = os.path.join(TEMPDIR, "extractdir")
505 os.mkdir(DIR)
506 try:
507 with tarfile.open(tarname, encoding="iso8859-1") as tar:
508 tarinfo = tar.getmember(dirtype)
509 tar.extract(tarinfo, path=DIR)
510 extracted = os.path.join(DIR, dirtype)
511 self.assertEqual(os.path.getmtime(extracted), tarinfo.mtime)
512 if sys.platform != "win32":
513 self.assertEqual(os.stat(extracted).st_mode & 0o777, 0o755)
514 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +0100515 support.rmtree(DIR)
Martin v. Löwis16f344d2010-11-01 21:39:13 +0000516
Lars Gustäbelb7f09232009-11-23 15:48:33 +0000517 def test_init_close_fobj(self):
518 # Issue #7341: Close the internal file object in the TarFile
519 # constructor in case of an error. For the test we rely on
520 # the fact that opening an empty file raises a ReadError.
521 empty = os.path.join(TEMPDIR, "empty")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000522 with open(empty, "wb") as fobj:
523 fobj.write(b"")
Lars Gustäbelb7f09232009-11-23 15:48:33 +0000524
525 try:
526 tar = object.__new__(tarfile.TarFile)
527 try:
528 tar.__init__(empty)
529 except tarfile.ReadError:
530 self.assertTrue(tar.fileobj.closed)
531 else:
532 self.fail("ReadError not raised")
533 finally:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000534 support.unlink(empty)
Lars Gustäbelb7f09232009-11-23 15:48:33 +0000535
Serhiy Storchaka263fab92013-05-09 14:22:26 +0300536 def test_parallel_iteration(self):
537 # Issue #16601: Restarting iteration over tarfile continued
538 # from where it left off.
539 with tarfile.open(self.tarname) as tar:
540 for m1, m2 in zip(tar, tar):
541 self.assertEqual(m1.offset, m2.offset)
542 self.assertEqual(m1.get_info(), m2.get_info())
543
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300544class MiscReadTest(MiscReadTestBase, unittest.TestCase):
545 test_fail_comp = None
Guido van Rossumd8faa362007-04-27 19:54:29 +0000546
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300547class GzipMiscReadTest(GzipTest, MiscReadTestBase, unittest.TestCase):
Serhiy Storchakaf22fe0f2014-01-13 19:08:00 +0200548 pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000549
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300550class Bz2MiscReadTest(Bz2Test, MiscReadTestBase, unittest.TestCase):
551 def test_no_name_argument(self):
552 self.skipTest("BZ2File have no name attribute")
553
554class LzmaMiscReadTest(LzmaTest, MiscReadTestBase, unittest.TestCase):
555 def test_no_name_argument(self):
556 self.skipTest("LZMAFile have no name attribute")
557
558
559class StreamReadTest(CommonReadTest, unittest.TestCase):
560
561 prefix="r|"
Guido van Rossumd8faa362007-04-27 19:54:29 +0000562
Lars Gustäbeldd071042011-02-23 11:42:22 +0000563 def test_read_through(self):
564 # Issue #11224: A poorly designed _FileInFile.read() method
565 # caused seeking errors with stream tar files.
566 for tarinfo in self.tar:
567 if not tarinfo.isreg():
568 continue
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200569 with self.tar.extractfile(tarinfo) as fobj:
570 while True:
571 try:
572 buf = fobj.read(512)
573 except tarfile.StreamError:
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300574 self.fail("simple read-through using "
575 "TarFile.extractfile() failed")
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200576 if not buf:
577 break
Lars Gustäbeldd071042011-02-23 11:42:22 +0000578
Guido van Rossumd8faa362007-04-27 19:54:29 +0000579 def test_fileobj_regular_file(self):
580 tarinfo = self.tar.next() # get "regtype" (can't use getmember)
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200581 with self.tar.extractfile(tarinfo) as fobj:
582 data = fobj.read()
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300583 self.assertEqual(len(data), tarinfo.size,
584 "regular file extraction failed")
585 self.assertEqual(md5sum(data), md5_regtype,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000586 "regular file extraction failed")
587
588 def test_provoke_stream_error(self):
589 tarinfos = self.tar.getmembers()
Lars Gustäbel7a919e92012-05-05 18:15:03 +0200590 with self.tar.extractfile(tarinfos[0]) as f: # read the first member
591 self.assertRaises(tarfile.StreamError, f.read)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000592
Guido van Rossumd8faa362007-04-27 19:54:29 +0000593 def test_compare_members(self):
594 tar1 = tarfile.open(tarname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000595 try:
596 tar2 = self.tar
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000597
Antoine Pitrou95f55602010-09-23 18:36:46 +0000598 while True:
599 t1 = tar1.next()
600 t2 = tar2.next()
601 if t1 is None:
602 break
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300603 self.assertIsNotNone(t2, "stream.next() failed.")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000604
Antoine Pitrou95f55602010-09-23 18:36:46 +0000605 if t2.islnk() or t2.issym():
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300606 with self.assertRaises(tarfile.StreamError):
607 tar2.extractfile(t2)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000608 continue
Guido van Rossumd8faa362007-04-27 19:54:29 +0000609
Antoine Pitrou95f55602010-09-23 18:36:46 +0000610 v1 = tar1.extractfile(t1)
611 v2 = tar2.extractfile(t2)
612 if v1 is None:
613 continue
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300614 self.assertIsNotNone(v2, "stream.extractfile() failed")
615 self.assertEqual(v1.read(), v2.read(),
616 "stream extraction failed")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000617 finally:
618 tar1.close()
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000619
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300620class GzipStreamReadTest(GzipTest, StreamReadTest):
621 pass
Thomas Wouters89f507f2006-12-13 04:49:30 +0000622
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300623class Bz2StreamReadTest(Bz2Test, StreamReadTest):
624 pass
Thomas Wouterscf297e42007-02-23 15:07:44 +0000625
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300626class LzmaStreamReadTest(LzmaTest, StreamReadTest):
627 pass
628
629
630class DetectReadTest(TarTest, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000631 def _testfunc_file(self, name, mode):
632 try:
Antoine Pitrou95f55602010-09-23 18:36:46 +0000633 tar = tarfile.open(name, mode)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000634 except tarfile.ReadError as e:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000635 self.fail()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000636 else:
637 tar.close()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000638
Guido van Rossumd8faa362007-04-27 19:54:29 +0000639 def _testfunc_fileobj(self, name, mode):
640 try:
Antoine Pitrou605c2932010-09-23 20:15:14 +0000641 with open(name, "rb") as f:
642 tar = tarfile.open(name, mode, fileobj=f)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000643 except tarfile.ReadError as e:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000644 self.fail()
Antoine Pitrou95f55602010-09-23 18:36:46 +0000645 else:
646 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000647
648 def _test_modes(self, testfunc):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300649 if self.suffix:
650 with self.assertRaises(tarfile.ReadError):
651 tarfile.open(tarname, mode="r:" + self.suffix)
652 with self.assertRaises(tarfile.ReadError):
653 tarfile.open(tarname, mode="r|" + self.suffix)
654 with self.assertRaises(tarfile.ReadError):
655 tarfile.open(self.tarname, mode="r:")
656 with self.assertRaises(tarfile.ReadError):
657 tarfile.open(self.tarname, mode="r|")
658 testfunc(self.tarname, "r")
659 testfunc(self.tarname, "r:" + self.suffix)
660 testfunc(self.tarname, "r:*")
661 testfunc(self.tarname, "r|" + self.suffix)
662 testfunc(self.tarname, "r|*")
Lars Gustäbel0a9dd2f2011-12-10 20:38:14 +0100663
Guido van Rossumd8faa362007-04-27 19:54:29 +0000664 def test_detect_file(self):
665 self._test_modes(self._testfunc_file)
666
667 def test_detect_fileobj(self):
668 self._test_modes(self._testfunc_fileobj)
669
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300670class GzipDetectReadTest(GzipTest, DetectReadTest):
671 pass
672
673class Bz2DetectReadTest(Bz2Test, DetectReadTest):
Lars Gustäbeled1ac582011-12-06 12:56:38 +0100674 def test_detect_stream_bz2(self):
675 # Originally, tarfile's stream detection looked for the string
676 # "BZh91" at the start of the file. This is incorrect because
677 # the '9' represents the blocksize (900kB). If the file was
678 # compressed using another blocksize autodetection fails.
Lars Gustäbeled1ac582011-12-06 12:56:38 +0100679 with open(tarname, "rb") as fobj:
680 data = fobj.read()
681
682 # Compress with blocksize 100kB, the file starts with "BZh11".
683 with bz2.BZ2File(tmpname, "wb", compresslevel=1) as fobj:
684 fobj.write(data)
685
686 self._testfunc_file(tmpname, "r|*")
687
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300688class LzmaDetectReadTest(LzmaTest, DetectReadTest):
689 pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000690
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300691
692class MemberReadTest(ReadTest, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000693
694 def _test_member(self, tarinfo, chksum=None, **kwargs):
695 if chksum is not None:
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300696 with self.tar.extractfile(tarinfo) as f:
697 self.assertEqual(md5sum(f.read()), chksum,
698 "wrong md5sum for %s" % tarinfo.name)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000699
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000700 kwargs["mtime"] = 0o7606136617
Guido van Rossumd8faa362007-04-27 19:54:29 +0000701 kwargs["uid"] = 1000
702 kwargs["gid"] = 100
703 if "old-v7" not in tarinfo.name:
704 # V7 tar can't handle alphabetic owners.
705 kwargs["uname"] = "tarfile"
706 kwargs["gname"] = "tarfile"
707 for k, v in kwargs.items():
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300708 self.assertEqual(getattr(tarinfo, k), v,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000709 "wrong value in %s field of %s" % (k, tarinfo.name))
710
711 def test_find_regtype(self):
712 tarinfo = self.tar.getmember("ustar/regtype")
713 self._test_member(tarinfo, size=7011, chksum=md5_regtype)
714
715 def test_find_conttype(self):
716 tarinfo = self.tar.getmember("ustar/conttype")
717 self._test_member(tarinfo, size=7011, chksum=md5_regtype)
718
719 def test_find_dirtype(self):
720 tarinfo = self.tar.getmember("ustar/dirtype")
721 self._test_member(tarinfo, size=0)
722
723 def test_find_dirtype_with_size(self):
724 tarinfo = self.tar.getmember("ustar/dirtype-with-size")
725 self._test_member(tarinfo, size=255)
726
727 def test_find_lnktype(self):
728 tarinfo = self.tar.getmember("ustar/lnktype")
729 self._test_member(tarinfo, size=0, linkname="ustar/regtype")
730
731 def test_find_symtype(self):
732 tarinfo = self.tar.getmember("ustar/symtype")
733 self._test_member(tarinfo, size=0, linkname="regtype")
734
735 def test_find_blktype(self):
736 tarinfo = self.tar.getmember("ustar/blktype")
737 self._test_member(tarinfo, size=0, devmajor=3, devminor=0)
738
739 def test_find_chrtype(self):
740 tarinfo = self.tar.getmember("ustar/chrtype")
741 self._test_member(tarinfo, size=0, devmajor=1, devminor=3)
742
743 def test_find_fifotype(self):
744 tarinfo = self.tar.getmember("ustar/fifotype")
745 self._test_member(tarinfo, size=0)
746
747 def test_find_sparse(self):
748 tarinfo = self.tar.getmember("ustar/sparse")
749 self._test_member(tarinfo, size=86016, chksum=md5_sparse)
750
Lars Gustäbel9cbdd752010-10-29 09:08:19 +0000751 def test_find_gnusparse(self):
752 tarinfo = self.tar.getmember("gnu/sparse")
753 self._test_member(tarinfo, size=86016, chksum=md5_sparse)
754
755 def test_find_gnusparse_00(self):
756 tarinfo = self.tar.getmember("gnu/sparse-0.0")
757 self._test_member(tarinfo, size=86016, chksum=md5_sparse)
758
759 def test_find_gnusparse_01(self):
760 tarinfo = self.tar.getmember("gnu/sparse-0.1")
761 self._test_member(tarinfo, size=86016, chksum=md5_sparse)
762
763 def test_find_gnusparse_10(self):
764 tarinfo = self.tar.getmember("gnu/sparse-1.0")
765 self._test_member(tarinfo, size=86016, chksum=md5_sparse)
766
Guido van Rossumd8faa362007-04-27 19:54:29 +0000767 def test_find_umlauts(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300768 tarinfo = self.tar.getmember("ustar/umlauts-"
769 "\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000770 self._test_member(tarinfo, size=7011, chksum=md5_regtype)
771
772 def test_find_ustar_longname(self):
773 name = "ustar/" + "12345/" * 39 + "1234567/longname"
Benjamin Peterson577473f2010-01-19 00:09:57 +0000774 self.assertIn(name, self.tar.getnames())
Guido van Rossumd8faa362007-04-27 19:54:29 +0000775
776 def test_find_regtype_oldv7(self):
777 tarinfo = self.tar.getmember("misc/regtype-old-v7")
778 self._test_member(tarinfo, size=7011, chksum=md5_regtype)
779
780 def test_find_pax_umlauts(self):
Antoine Pitrouab58b5f2010-09-23 19:39:35 +0000781 self.tar.close()
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300782 self.tar = tarfile.open(self.tarname, mode=self.mode,
783 encoding="iso8859-1")
784 tarinfo = self.tar.getmember("pax/umlauts-"
785 "\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000786 self._test_member(tarinfo, size=7011, chksum=md5_regtype)
787
788
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300789class LongnameTest:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000790
791 def test_read_longname(self):
792 # Test reading of longname (bug #1471427).
Guido van Rossume7ba4952007-06-06 23:52:48 +0000793 longname = self.subdir + "/" + "123/" * 125 + "longname"
Guido van Rossumd8faa362007-04-27 19:54:29 +0000794 try:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000795 tarinfo = self.tar.getmember(longname)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000796 except KeyError:
797 self.fail("longname not found")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300798 self.assertNotEqual(tarinfo.type, tarfile.DIRTYPE,
799 "read longname as dirtype")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000800
801 def test_read_longlink(self):
802 longname = self.subdir + "/" + "123/" * 125 + "longname"
803 longlink = self.subdir + "/" + "123/" * 125 + "longlink"
804 try:
805 tarinfo = self.tar.getmember(longlink)
806 except KeyError:
807 self.fail("longlink not found")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300808 self.assertEqual(tarinfo.linkname, longname, "linkname wrong")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000809
810 def test_truncated_longname(self):
811 longname = self.subdir + "/" + "123/" * 125 + "longname"
812 tarinfo = self.tar.getmember(longname)
813 offset = tarinfo.offset
814 self.tar.fileobj.seek(offset)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000815 fobj = io.BytesIO(self.tar.fileobj.read(3 * 512))
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300816 with self.assertRaises(tarfile.ReadError):
817 tarfile.open(name="foo.tar", fileobj=fobj)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000818
Guido van Rossume7ba4952007-06-06 23:52:48 +0000819 def test_header_offset(self):
820 # Test if the start offset of the TarInfo object includes
821 # the preceding extended header.
822 longname = self.subdir + "/" + "123/" * 125 + "longname"
823 offset = self.tar.getmember(longname).offset
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000824 with open(tarname, "rb") as fobj:
825 fobj.seek(offset)
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300826 tarinfo = tarfile.TarInfo.frombuf(fobj.read(512),
827 "iso8859-1", "strict")
Antoine Pitroue1eca4e2010-10-29 23:49:49 +0000828 self.assertEqual(tarinfo.type, self.longnametype)
Guido van Rossume7ba4952007-06-06 23:52:48 +0000829
Guido van Rossumd8faa362007-04-27 19:54:29 +0000830
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300831class GNUReadTest(LongnameTest, ReadTest, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000832
833 subdir = "gnu"
Guido van Rossume7ba4952007-06-06 23:52:48 +0000834 longnametype = tarfile.GNUTYPE_LONGNAME
Guido van Rossumd8faa362007-04-27 19:54:29 +0000835
Lars Gustäbel9cbdd752010-10-29 09:08:19 +0000836 # Since 3.2 tarfile is supposed to accurately restore sparse members and
837 # produce files with holes. This is what we actually want to test here.
838 # Unfortunately, not all platforms/filesystems support sparse files, and
839 # even on platforms that do it is non-trivial to make reliable assertions
840 # about holes in files. Therefore, we first do one basic test which works
841 # an all platforms, and after that a test that will work only on
842 # platforms/filesystems that prove to support sparse files.
843 def _test_sparse_file(self, name):
844 self.tar.extract(name, TEMPDIR)
845 filename = os.path.join(TEMPDIR, name)
846 with open(filename, "rb") as fobj:
847 data = fobj.read()
848 self.assertEqual(md5sum(data), md5_sparse,
849 "wrong md5sum for %s" % name)
850
851 if self._fs_supports_holes():
852 s = os.stat(filename)
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300853 self.assertLess(s.st_blocks * 512, s.st_size)
Lars Gustäbel9cbdd752010-10-29 09:08:19 +0000854
855 def test_sparse_file_old(self):
856 self._test_sparse_file("gnu/sparse")
857
858 def test_sparse_file_00(self):
859 self._test_sparse_file("gnu/sparse-0.0")
860
861 def test_sparse_file_01(self):
862 self._test_sparse_file("gnu/sparse-0.1")
863
864 def test_sparse_file_10(self):
865 self._test_sparse_file("gnu/sparse-1.0")
866
867 @staticmethod
868 def _fs_supports_holes():
869 # Return True if the platform knows the st_blocks stat attribute and
870 # uses st_blocks units of 512 bytes, and if the filesystem is able to
871 # store holes in files.
Victor Stinner9c3de4a2011-08-17 20:49:41 +0200872 if sys.platform.startswith("linux"):
Lars Gustäbel9cbdd752010-10-29 09:08:19 +0000873 # Linux evidentially has 512 byte st_blocks units.
874 name = os.path.join(TEMPDIR, "sparse-test")
875 with open(name, "wb") as fobj:
876 fobj.seek(4096)
877 fobj.truncate()
878 s = os.stat(name)
Tim Goldene0bd2c52014-05-06 13:24:26 +0100879 support.unlink(name)
Lars Gustäbel9cbdd752010-10-29 09:08:19 +0000880 return s.st_blocks == 0
881 else:
882 return False
Guido van Rossumd8faa362007-04-27 19:54:29 +0000883
884
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300885class PaxReadTest(LongnameTest, ReadTest, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000886
887 subdir = "pax"
Guido van Rossume7ba4952007-06-06 23:52:48 +0000888 longnametype = tarfile.XHDTYPE
Guido van Rossumd8faa362007-04-27 19:54:29 +0000889
Guido van Rossume7ba4952007-06-06 23:52:48 +0000890 def test_pax_global_headers(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000891 tar = tarfile.open(tarname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000892 try:
893 tarinfo = tar.getmember("pax/regtype1")
894 self.assertEqual(tarinfo.uname, "foo")
895 self.assertEqual(tarinfo.gname, "bar")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300896 self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"),
897 "\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
Guido van Rossume7ba4952007-06-06 23:52:48 +0000898
Antoine Pitrou95f55602010-09-23 18:36:46 +0000899 tarinfo = tar.getmember("pax/regtype2")
900 self.assertEqual(tarinfo.uname, "")
901 self.assertEqual(tarinfo.gname, "bar")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300902 self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"),
903 "\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000904
Antoine Pitrou95f55602010-09-23 18:36:46 +0000905 tarinfo = tar.getmember("pax/regtype3")
906 self.assertEqual(tarinfo.uname, "tarfile")
907 self.assertEqual(tarinfo.gname, "tarfile")
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300908 self.assertEqual(tarinfo.pax_headers.get("VENDOR.umlauts"),
909 "\xc4\xd6\xdc\xe4\xf6\xfc\xdf")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000910 finally:
911 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +0000912
913 def test_pax_number_fields(self):
914 # All following number fields are read from the pax header.
915 tar = tarfile.open(tarname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +0000916 try:
917 tarinfo = tar.getmember("pax/regtype4")
918 self.assertEqual(tarinfo.size, 7011)
919 self.assertEqual(tarinfo.uid, 123)
920 self.assertEqual(tarinfo.gid, 123)
921 self.assertEqual(tarinfo.mtime, 1041808783.0)
922 self.assertEqual(type(tarinfo.mtime), float)
923 self.assertEqual(float(tarinfo.pax_headers["atime"]), 1041808783.0)
924 self.assertEqual(float(tarinfo.pax_headers["ctime"]), 1041808783.0)
925 finally:
926 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000927
928
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300929class WriteTestBase(TarTest):
Georg Brandlf08a9dd2008-06-10 16:57:31 +0000930 # Put all write tests in here that are supposed to be tested
931 # in all possible mode combinations.
932
933 def test_fileobj_no_close(self):
934 fobj = io.BytesIO()
935 tar = tarfile.open(fileobj=fobj, mode=self.mode)
936 tar.addfile(tarfile.TarInfo("foo"))
937 tar.close()
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300938 self.assertFalse(fobj.closed, "external fileobjs must never closed")
Serhiy Storchaka9fbec7a2014-01-18 15:53:05 +0200939 # Issue #20238: Incomplete gzip output with mode="w:gz"
940 data = fobj.getvalue()
941 del tar
942 support.gc_collect()
943 self.assertFalse(fobj.closed)
944 self.assertEqual(data, fobj.getvalue())
Georg Brandlf08a9dd2008-06-10 16:57:31 +0000945
946
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300947class WriteTest(WriteTestBase, unittest.TestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000948
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300949 prefix = "w:"
Guido van Rossumd8faa362007-04-27 19:54:29 +0000950
951 def test_100_char_name(self):
952 # The name field in a tar header stores strings of at most 100 chars.
953 # If a string is shorter than 100 chars it has to be padded with '\0',
954 # which implies that a string of exactly 100 chars is stored without
955 # a trailing '\0'.
956 name = "0123456789" * 10
957 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000958 try:
959 t = tarfile.TarInfo(name)
960 tar.addfile(t)
961 finally:
962 tar.close()
Thomas Wouterscf297e42007-02-23 15:07:44 +0000963
Guido van Rossumd8faa362007-04-27 19:54:29 +0000964 tar = tarfile.open(tmpname)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000965 try:
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300966 self.assertEqual(tar.getnames()[0], name,
Antoine Pitrou95f55602010-09-23 18:36:46 +0000967 "failed to store 100 char filename")
968 finally:
969 tar.close()
Thomas Wouters89f507f2006-12-13 04:49:30 +0000970
Guido van Rossumd8faa362007-04-27 19:54:29 +0000971 def test_tar_size(self):
972 # Test for bug #1013882.
973 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000974 try:
975 path = os.path.join(TEMPDIR, "file")
976 with open(path, "wb") as fobj:
977 fobj.write(b"aaa")
978 tar.add(path)
979 finally:
980 tar.close()
Serhiy Storchaka8b562922013-06-17 15:38:50 +0300981 self.assertGreater(os.path.getsize(tmpname), 0,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000982 "tarfile is empty")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000983
Guido van Rossumd8faa362007-04-27 19:54:29 +0000984 # The test_*_size tests test for bug #1167128.
985 def test_file_size(self):
986 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +0000987 try:
988 path = os.path.join(TEMPDIR, "file")
989 with open(path, "wb"):
990 pass
991 tarinfo = tar.gettarinfo(path)
992 self.assertEqual(tarinfo.size, 0)
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000993
Antoine Pitrou95f55602010-09-23 18:36:46 +0000994 with open(path, "wb") as fobj:
995 fobj.write(b"aaa")
996 tarinfo = tar.gettarinfo(path)
997 self.assertEqual(tarinfo.size, 3)
998 finally:
999 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001000
1001 def test_directory_size(self):
1002 path = os.path.join(TEMPDIR, "directory")
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001003 os.mkdir(path)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001004 try:
1005 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001006 try:
1007 tarinfo = tar.gettarinfo(path)
1008 self.assertEqual(tarinfo.size, 0)
1009 finally:
1010 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001011 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001012 support.rmdir(path)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001013
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001014 @unittest.skipUnless(hasattr(os, "link"),
1015 "Missing hardlink implementation")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001016 def test_link_size(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001017 link = os.path.join(TEMPDIR, "link")
1018 target = os.path.join(TEMPDIR, "link_target")
1019 with open(target, "wb") as fobj:
1020 fobj.write(b"aaa")
1021 os.link(target, link)
1022 try:
1023 tar = tarfile.open(tmpname, self.mode)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001024 try:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001025 # Record the link target in the inodes list.
1026 tar.gettarinfo(target)
1027 tarinfo = tar.gettarinfo(link)
1028 self.assertEqual(tarinfo.size, 0)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001029 finally:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001030 tar.close()
1031 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001032 support.unlink(target)
1033 support.unlink(link)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001034
Brian Curtin3b4499c2010-12-28 14:31:47 +00001035 @support.skip_unless_symlink
Guido van Rossumd8faa362007-04-27 19:54:29 +00001036 def test_symlink_size(self):
Brian Curtind40e6f72010-07-08 21:39:08 +00001037 path = os.path.join(TEMPDIR, "symlink")
1038 os.symlink("link_target", path)
1039 try:
1040 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001041 try:
1042 tarinfo = tar.gettarinfo(path)
1043 self.assertEqual(tarinfo.size, 0)
1044 finally:
1045 tar.close()
Brian Curtind40e6f72010-07-08 21:39:08 +00001046 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001047 support.unlink(path)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001048
1049 def test_add_self(self):
1050 # Test for #1257255.
1051 dstname = os.path.abspath(tmpname)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001052 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001053 try:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001054 self.assertEqual(tar.name, dstname,
1055 "archive name must be absolute")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001056 tar.add(dstname)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001057 self.assertEqual(tar.getnames(), [],
1058 "added the archive to itself")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001059
Antoine Pitrou95f55602010-09-23 18:36:46 +00001060 cwd = os.getcwd()
1061 os.chdir(TEMPDIR)
1062 tar.add(dstname)
1063 os.chdir(cwd)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001064 self.assertEqual(tar.getnames(), [],
1065 "added the archive to itself")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001066 finally:
1067 tar.close()
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001068
Guido van Rossum486364b2007-06-30 05:01:58 +00001069 def test_exclude(self):
1070 tempdir = os.path.join(TEMPDIR, "exclude")
1071 os.mkdir(tempdir)
1072 try:
1073 for name in ("foo", "bar", "baz"):
1074 name = os.path.join(tempdir, name)
Victor Stinnerbf816222011-06-30 23:25:47 +02001075 support.create_empty_file(name)
Guido van Rossum486364b2007-06-30 05:01:58 +00001076
Benjamin Peterson886af962010-03-21 23:13:07 +00001077 exclude = os.path.isfile
Guido van Rossum486364b2007-06-30 05:01:58 +00001078
1079 tar = tarfile.open(tmpname, self.mode, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001080 try:
1081 with support.check_warnings(("use the filter argument",
1082 DeprecationWarning)):
1083 tar.add(tempdir, arcname="empty_dir", exclude=exclude)
1084 finally:
1085 tar.close()
Guido van Rossum486364b2007-06-30 05:01:58 +00001086
1087 tar = tarfile.open(tmpname, "r")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001088 try:
1089 self.assertEqual(len(tar.getmembers()), 1)
1090 self.assertEqual(tar.getnames()[0], "empty_dir")
1091 finally:
1092 tar.close()
Guido van Rossum486364b2007-06-30 05:01:58 +00001093 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001094 support.rmtree(tempdir)
Guido van Rossum486364b2007-06-30 05:01:58 +00001095
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001096 def test_filter(self):
1097 tempdir = os.path.join(TEMPDIR, "filter")
1098 os.mkdir(tempdir)
1099 try:
1100 for name in ("foo", "bar", "baz"):
1101 name = os.path.join(tempdir, name)
Victor Stinnerbf816222011-06-30 23:25:47 +02001102 support.create_empty_file(name)
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001103
1104 def filter(tarinfo):
1105 if os.path.basename(tarinfo.name) == "bar":
1106 return
1107 tarinfo.uid = 123
1108 tarinfo.uname = "foo"
1109 return tarinfo
1110
1111 tar = tarfile.open(tmpname, self.mode, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001112 try:
1113 tar.add(tempdir, arcname="empty_dir", filter=filter)
1114 finally:
1115 tar.close()
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001116
Raymond Hettingera63a3122011-01-26 20:34:14 +00001117 # Verify that filter is a keyword-only argument
1118 with self.assertRaises(TypeError):
1119 tar.add(tempdir, "empty_dir", True, None, filter)
1120
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001121 tar = tarfile.open(tmpname, "r")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001122 try:
1123 for tarinfo in tar:
1124 self.assertEqual(tarinfo.uid, 123)
1125 self.assertEqual(tarinfo.uname, "foo")
1126 self.assertEqual(len(tar.getmembers()), 3)
1127 finally:
1128 tar.close()
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001129 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001130 support.rmtree(tempdir)
Lars Gustäbel049d2aa2009-09-12 10:44:00 +00001131
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001132 # Guarantee that stored pathnames are not modified. Don't
1133 # remove ./ or ../ or double slashes. Still make absolute
1134 # pathnames relative.
1135 # For details see bug #6054.
1136 def _test_pathname(self, path, cmp_path=None, dir=False):
1137 # Create a tarfile with an empty member named path
1138 # and compare the stored name with the original.
1139 foo = os.path.join(TEMPDIR, "foo")
1140 if not dir:
Victor Stinnerbf816222011-06-30 23:25:47 +02001141 support.create_empty_file(foo)
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001142 else:
1143 os.mkdir(foo)
1144
1145 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001146 try:
1147 tar.add(foo, arcname=path)
1148 finally:
1149 tar.close()
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001150
1151 tar = tarfile.open(tmpname, "r")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001152 try:
1153 t = tar.next()
1154 finally:
1155 tar.close()
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001156
1157 if not dir:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001158 support.unlink(foo)
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001159 else:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001160 support.rmdir(foo)
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001161
1162 self.assertEqual(t.name, cmp_path or path.replace(os.sep, "/"))
1163
Senthil Kumaranbe5dbeb2011-04-30 06:09:51 +08001164
1165 @support.skip_unless_symlink
Senthil Kumaran123932f2011-04-28 15:38:12 +08001166 def test_extractall_symlinks(self):
1167 # Test if extractall works properly when tarfile contains symlinks
1168 tempdir = os.path.join(TEMPDIR, "testsymlinks")
1169 temparchive = os.path.join(TEMPDIR, "testsymlinks.tar")
1170 os.mkdir(tempdir)
1171 try:
1172 source_file = os.path.join(tempdir,'source')
1173 target_file = os.path.join(tempdir,'symlink')
1174 with open(source_file,'w') as f:
1175 f.write('something\n')
1176 os.symlink(source_file, target_file)
1177 tar = tarfile.open(temparchive,'w')
1178 tar.add(source_file)
1179 tar.add(target_file)
1180 tar.close()
1181 # Let's extract it to the location which contains the symlink
1182 tar = tarfile.open(temparchive,'r')
1183 # this should not raise OSError: [Errno 17] File exists
1184 try:
1185 tar.extractall(path=tempdir)
1186 except OSError:
1187 self.fail("extractall failed with symlinked files")
1188 finally:
1189 tar.close()
1190 finally:
Tim Goldene0bd2c52014-05-06 13:24:26 +01001191 support.unlink(temparchive)
1192 support.rmtree(tempdir)
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001193
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001194 def test_pathnames(self):
1195 self._test_pathname("foo")
1196 self._test_pathname(os.path.join("foo", ".", "bar"))
1197 self._test_pathname(os.path.join("foo", "..", "bar"))
1198 self._test_pathname(os.path.join(".", "foo"))
1199 self._test_pathname(os.path.join(".", "foo", "."))
1200 self._test_pathname(os.path.join(".", "foo", ".", "bar"))
1201 self._test_pathname(os.path.join(".", "foo", "..", "bar"))
1202 self._test_pathname(os.path.join(".", "foo", "..", "bar"))
1203 self._test_pathname(os.path.join("..", "foo"))
1204 self._test_pathname(os.path.join("..", "foo", ".."))
1205 self._test_pathname(os.path.join("..", "foo", ".", "bar"))
1206 self._test_pathname(os.path.join("..", "foo", "..", "bar"))
1207
1208 self._test_pathname("foo" + os.sep + os.sep + "bar")
1209 self._test_pathname("foo" + os.sep + os.sep, "foo", dir=True)
1210
1211 def test_abs_pathnames(self):
1212 if sys.platform == "win32":
1213 self._test_pathname("C:\\foo", "foo")
1214 else:
1215 self._test_pathname("/foo", "foo")
1216 self._test_pathname("///foo", "foo")
1217
1218 def test_cwd(self):
1219 # Test adding the current working directory.
1220 cwd = os.getcwd()
1221 os.chdir(TEMPDIR)
1222 try:
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001223 tar = tarfile.open(tmpname, self.mode)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001224 try:
1225 tar.add(".")
1226 finally:
1227 tar.close()
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001228
1229 tar = tarfile.open(tmpname, "r")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001230 try:
1231 for t in tar:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001232 if t.name != ".":
1233 self.assertTrue(t.name.startswith("./"), t.name)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001234 finally:
1235 tar.close()
Lars Gustäbelbfdfdda2009-08-28 19:59:59 +00001236 finally:
1237 os.chdir(cwd)
1238
Serhiy Storchakac2d01422014-01-18 16:14:10 +02001239 def test_open_nonwritable_fileobj(self):
1240 for exctype in OSError, EOFError, RuntimeError:
1241 class BadFile(io.BytesIO):
1242 first = True
1243 def write(self, data):
1244 if self.first:
1245 self.first = False
1246 raise exctype
1247
1248 f = BadFile()
1249 with self.assertRaises(exctype):
1250 tar = tarfile.open(tmpname, self.mode, fileobj=f,
1251 format=tarfile.PAX_FORMAT,
1252 pax_headers={'non': 'empty'})
1253 self.assertFalse(f.closed)
1254
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001255class GzipWriteTest(GzipTest, WriteTest):
1256 pass
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001257
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001258class Bz2WriteTest(Bz2Test, WriteTest):
1259 pass
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001260
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001261class LzmaWriteTest(LzmaTest, WriteTest):
1262 pass
1263
1264
1265class StreamWriteTest(WriteTestBase, unittest.TestCase):
1266
1267 prefix = "w|"
1268 decompressor = None
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001269
Guido van Rossumd8faa362007-04-27 19:54:29 +00001270 def test_stream_padding(self):
1271 # Test for bug #1543303.
1272 tar = tarfile.open(tmpname, self.mode)
1273 tar.close()
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001274 if self.decompressor:
1275 dec = self.decompressor()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001276 with open(tmpname, "rb") as fobj:
1277 data = fobj.read()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001278 data = dec.decompress(data)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001279 self.assertFalse(dec.unused_data, "found trailing data")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001280 else:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001281 with self.open(tmpname) as fobj:
Antoine Pitrou95f55602010-09-23 18:36:46 +00001282 data = fobj.read()
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001283 self.assertEqual(data.count(b"\0"), tarfile.RECORDSIZE,
1284 "incorrect zero padding")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001285
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001286 @unittest.skipUnless(sys.platform != "win32" and hasattr(os, "umask"),
1287 "Missing umask implementation")
Lars Gustäbeld6eb70b2010-04-29 15:37:02 +00001288 def test_file_mode(self):
1289 # Test for issue #8464: Create files with correct
1290 # permissions.
Lars Gustäbeld6eb70b2010-04-29 15:37:02 +00001291 if os.path.exists(tmpname):
Tim Goldene0bd2c52014-05-06 13:24:26 +01001292 support.unlink(tmpname)
Lars Gustäbeld6eb70b2010-04-29 15:37:02 +00001293
1294 original_umask = os.umask(0o022)
1295 try:
1296 tar = tarfile.open(tmpname, self.mode)
1297 tar.close()
1298 mode = os.stat(tmpname).st_mode & 0o777
1299 self.assertEqual(mode, 0o644, "wrong file permissions")
1300 finally:
1301 os.umask(original_umask)
1302
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001303class GzipStreamWriteTest(GzipTest, StreamWriteTest):
1304 pass
1305
1306class Bz2StreamWriteTest(Bz2Test, StreamWriteTest):
1307 decompressor = bz2.BZ2Decompressor if bz2 else None
1308
1309class LzmaStreamWriteTest(LzmaTest, StreamWriteTest):
1310 decompressor = lzma.LZMADecompressor if lzma else None
1311
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001312
Guido van Rossumd8faa362007-04-27 19:54:29 +00001313class GNUWriteTest(unittest.TestCase):
1314 # This testcase checks for correct creation of GNU Longname
1315 # and Longlink extended headers (cp. bug #812325).
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001316
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001317 def _length(self, s):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001318 blocks = len(s) // 512 + 1
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001319 return blocks * 512
1320
1321 def _calc_size(self, name, link=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001322 # Initial tar header
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001323 count = 512
1324
1325 if len(name) > tarfile.LENGTH_NAME:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001326 # GNU longname extended header + longname
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001327 count += 512
1328 count += self._length(name)
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001329 if link is not None and len(link) > tarfile.LENGTH_LINK:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001330 # GNU longlink extended header + longlink
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001331 count += 512
1332 count += self._length(link)
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001333 return count
1334
1335 def _test(self, name, link=None):
1336 tarinfo = tarfile.TarInfo(name)
1337 if link:
1338 tarinfo.linkname = link
1339 tarinfo.type = tarfile.LNKTYPE
1340
Guido van Rossumd8faa362007-04-27 19:54:29 +00001341 tar = tarfile.open(tmpname, "w")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001342 try:
1343 tar.format = tarfile.GNU_FORMAT
1344 tar.addfile(tarinfo)
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001345
Antoine Pitrou95f55602010-09-23 18:36:46 +00001346 v1 = self._calc_size(name, link)
1347 v2 = tar.offset
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001348 self.assertEqual(v1, v2, "GNU longname/longlink creation failed")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001349 finally:
1350 tar.close()
Thomas Wouters89f507f2006-12-13 04:49:30 +00001351
Guido van Rossumd8faa362007-04-27 19:54:29 +00001352 tar = tarfile.open(tmpname)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001353 try:
1354 member = tar.next()
1355 self.assertIsNotNone(member,
1356 "unable to read longname member")
1357 self.assertEqual(tarinfo.name, member.name,
1358 "unable to read longname member")
1359 self.assertEqual(tarinfo.linkname, member.linkname,
1360 "unable to read longname member")
1361 finally:
1362 tar.close()
Thomas Wouters89f507f2006-12-13 04:49:30 +00001363
Neal Norwitz0662f8a2004-07-20 21:54:18 +00001364 def test_longname_1023(self):
1365 self._test(("longnam/" * 127) + "longnam")
1366
1367 def test_longname_1024(self):
1368 self._test(("longnam/" * 127) + "longname")
1369
1370 def test_longname_1025(self):
1371 self._test(("longnam/" * 127) + "longname_")
1372
1373 def test_longlink_1023(self):
1374 self._test("name", ("longlnk/" * 127) + "longlnk")
1375
1376 def test_longlink_1024(self):
1377 self._test("name", ("longlnk/" * 127) + "longlink")
1378
1379 def test_longlink_1025(self):
1380 self._test("name", ("longlnk/" * 127) + "longlink_")
1381
1382 def test_longnamelink_1023(self):
1383 self._test(("longnam/" * 127) + "longnam",
1384 ("longlnk/" * 127) + "longlnk")
1385
1386 def test_longnamelink_1024(self):
1387 self._test(("longnam/" * 127) + "longname",
1388 ("longlnk/" * 127) + "longlink")
1389
1390 def test_longnamelink_1025(self):
1391 self._test(("longnam/" * 127) + "longname_",
1392 ("longlnk/" * 127) + "longlink_")
1393
Guido van Rossumd8faa362007-04-27 19:54:29 +00001394
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001395@unittest.skipUnless(hasattr(os, "link"), "Missing hardlink implementation")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001396class HardlinkTest(unittest.TestCase):
1397 # Test the creation of LNKTYPE (hardlink) members in an archive.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001398
1399 def setUp(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001400 self.foo = os.path.join(TEMPDIR, "foo")
1401 self.bar = os.path.join(TEMPDIR, "bar")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001402
Antoine Pitrou95f55602010-09-23 18:36:46 +00001403 with open(self.foo, "wb") as fobj:
1404 fobj.write(b"foo")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001405
Guido van Rossumd8faa362007-04-27 19:54:29 +00001406 os.link(self.foo, self.bar)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001407
Guido van Rossumd8faa362007-04-27 19:54:29 +00001408 self.tar = tarfile.open(tmpname, "w")
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001409 self.tar.add(self.foo)
1410
Guido van Rossumd8faa362007-04-27 19:54:29 +00001411 def tearDown(self):
Hirokazu Yamamotoaf079d42008-09-21 11:50:03 +00001412 self.tar.close()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001413 support.unlink(self.foo)
1414 support.unlink(self.bar)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001415
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001416 def test_add_twice(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001417 # The same name will be added as a REGTYPE every
1418 # time regardless of st_nlink.
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001419 tarinfo = self.tar.gettarinfo(self.foo)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001420 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001421 "add file as regular failed")
1422
1423 def test_add_hardlink(self):
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001424 tarinfo = self.tar.gettarinfo(self.bar)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001425 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001426 "add file as hardlink failed")
1427
1428 def test_dereference_hardlink(self):
1429 self.tar.dereference = True
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001430 tarinfo = self.tar.gettarinfo(self.bar)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001431 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001432 "dereferencing hardlink failed")
1433
Neal Norwitza4f651a2004-07-20 22:07:44 +00001434
Guido van Rossumd8faa362007-04-27 19:54:29 +00001435class PaxWriteTest(GNUWriteTest):
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001436
Guido van Rossumd8faa362007-04-27 19:54:29 +00001437 def _test(self, name, link=None):
1438 # See GNUWriteTest.
1439 tarinfo = tarfile.TarInfo(name)
1440 if link:
1441 tarinfo.linkname = link
1442 tarinfo.type = tarfile.LNKTYPE
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +00001443
Guido van Rossumd8faa362007-04-27 19:54:29 +00001444 tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001445 try:
1446 tar.addfile(tarinfo)
1447 finally:
1448 tar.close()
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +00001449
Guido van Rossumd8faa362007-04-27 19:54:29 +00001450 tar = tarfile.open(tmpname)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001451 try:
1452 if link:
1453 l = tar.getmembers()[0].linkname
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001454 self.assertEqual(link, l, "PAX longlink creation failed")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001455 else:
1456 n = tar.getmembers()[0].name
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001457 self.assertEqual(name, n, "PAX longname creation failed")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001458 finally:
1459 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001460
Guido van Rossume7ba4952007-06-06 23:52:48 +00001461 def test_pax_global_header(self):
1462 pax_headers = {
Guido van Rossum9cbfffd2007-06-07 00:54:15 +00001463 "foo": "bar",
1464 "uid": "0",
1465 "mtime": "1.23",
Guido van Rossuma0557702007-08-07 23:19:53 +00001466 "test": "\xe4\xf6\xfc",
1467 "\xe4\xf6\xfc": "test"}
Guido van Rossume7ba4952007-06-06 23:52:48 +00001468
Benjamin Peterson886af962010-03-21 23:13:07 +00001469 tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT,
Guido van Rossume7ba4952007-06-06 23:52:48 +00001470 pax_headers=pax_headers)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001471 try:
1472 tar.addfile(tarfile.TarInfo("test"))
1473 finally:
1474 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001475
1476 # Test if the global header was written correctly.
1477 tar = tarfile.open(tmpname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001478 try:
1479 self.assertEqual(tar.pax_headers, pax_headers)
1480 self.assertEqual(tar.getmembers()[0].pax_headers, pax_headers)
1481 # Test if all the fields are strings.
1482 for key, val in tar.pax_headers.items():
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001483 self.assertIsNot(type(key), bytes)
1484 self.assertIsNot(type(val), bytes)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001485 if key in tarfile.PAX_NUMBER_FIELDS:
1486 try:
1487 tarfile.PAX_NUMBER_FIELDS[key](val)
1488 except (TypeError, ValueError):
1489 self.fail("unable to convert pax header field")
1490 finally:
1491 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001492
1493 def test_pax_extended_header(self):
1494 # The fields from the pax header have priority over the
1495 # TarInfo.
Guido van Rossum9cbfffd2007-06-07 00:54:15 +00001496 pax_headers = {"path": "foo", "uid": "123"}
Guido van Rossume7ba4952007-06-06 23:52:48 +00001497
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001498 tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT,
1499 encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001500 try:
1501 t = tarfile.TarInfo()
1502 t.name = "\xe4\xf6\xfc" # non-ASCII
1503 t.uid = 8**8 # too large
1504 t.pax_headers = pax_headers
1505 tar.addfile(t)
1506 finally:
1507 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001508
1509 tar = tarfile.open(tmpname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001510 try:
1511 t = tar.getmembers()[0]
1512 self.assertEqual(t.pax_headers, pax_headers)
1513 self.assertEqual(t.name, "foo")
1514 self.assertEqual(t.uid, 123)
1515 finally:
1516 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001517
1518
1519class UstarUnicodeTest(unittest.TestCase):
Guido van Rossume7ba4952007-06-06 23:52:48 +00001520
1521 format = tarfile.USTAR_FORMAT
1522
1523 def test_iso8859_1_filename(self):
1524 self._test_unicode_filename("iso8859-1")
1525
1526 def test_utf7_filename(self):
1527 self._test_unicode_filename("utf7")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001528
1529 def test_utf8_filename(self):
Marc-André Lemburg8f36af72011-02-25 15:42:01 +00001530 self._test_unicode_filename("utf-8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001531
Guido van Rossumd8faa362007-04-27 19:54:29 +00001532 def _test_unicode_filename(self, encoding):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001533 tar = tarfile.open(tmpname, "w", format=self.format,
1534 encoding=encoding, errors="strict")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001535 try:
1536 name = "\xe4\xf6\xfc"
1537 tar.addfile(tarfile.TarInfo(name))
1538 finally:
1539 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001540
1541 tar = tarfile.open(tmpname, encoding=encoding)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001542 try:
1543 self.assertEqual(tar.getmembers()[0].name, name)
1544 finally:
1545 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001546
1547 def test_unicode_filename_error(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001548 tar = tarfile.open(tmpname, "w", format=self.format,
1549 encoding="ascii", errors="strict")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001550 try:
1551 tarinfo = tarfile.TarInfo()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001552
Antoine Pitrou95f55602010-09-23 18:36:46 +00001553 tarinfo.name = "\xe4\xf6\xfc"
1554 self.assertRaises(UnicodeError, tar.addfile, tarinfo)
Guido van Rossume7ba4952007-06-06 23:52:48 +00001555
Antoine Pitrou95f55602010-09-23 18:36:46 +00001556 tarinfo.name = "foo"
1557 tarinfo.uname = "\xe4\xf6\xfc"
1558 self.assertRaises(UnicodeError, tar.addfile, tarinfo)
1559 finally:
1560 tar.close()
Guido van Rossume7ba4952007-06-06 23:52:48 +00001561
1562 def test_unicode_argument(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001563 tar = tarfile.open(tarname, "r",
1564 encoding="iso8859-1", errors="strict")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001565 try:
1566 for t in tar:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001567 self.assertIs(type(t.name), str)
1568 self.assertIs(type(t.linkname), str)
1569 self.assertIs(type(t.uname), str)
1570 self.assertIs(type(t.gname), str)
Antoine Pitrou95f55602010-09-23 18:36:46 +00001571 finally:
1572 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001573
Guido van Rossume7ba4952007-06-06 23:52:48 +00001574 def test_uname_unicode(self):
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001575 t = tarfile.TarInfo("foo")
1576 t.uname = "\xe4\xf6\xfc"
1577 t.gname = "\xe4\xf6\xfc"
Guido van Rossumd8faa362007-04-27 19:54:29 +00001578
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001579 tar = tarfile.open(tmpname, mode="w", format=self.format,
1580 encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001581 try:
1582 tar.addfile(t)
1583 finally:
1584 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001585
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001586 tar = tarfile.open(tmpname, encoding="iso8859-1")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001587 try:
Guido van Rossume7ba4952007-06-06 23:52:48 +00001588 t = tar.getmember("foo")
Antoine Pitrou95f55602010-09-23 18:36:46 +00001589 self.assertEqual(t.uname, "\xe4\xf6\xfc")
1590 self.assertEqual(t.gname, "\xe4\xf6\xfc")
1591
1592 if self.format != tarfile.PAX_FORMAT:
Antoine Pitrouab58b5f2010-09-23 19:39:35 +00001593 tar.close()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001594 tar = tarfile.open(tmpname, encoding="ascii")
1595 t = tar.getmember("foo")
1596 self.assertEqual(t.uname, "\udce4\udcf6\udcfc")
1597 self.assertEqual(t.gname, "\udce4\udcf6\udcfc")
1598 finally:
1599 tar.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001600
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001601
Guido van Rossume7ba4952007-06-06 23:52:48 +00001602class GNUUnicodeTest(UstarUnicodeTest):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001603
Guido van Rossume7ba4952007-06-06 23:52:48 +00001604 format = tarfile.GNU_FORMAT
Guido van Rossumd8faa362007-04-27 19:54:29 +00001605
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001606 def test_bad_pax_header(self):
1607 # Test for issue #8633. GNU tar <= 1.23 creates raw binary fields
1608 # without a hdrcharset=BINARY header.
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001609 for encoding, name in (
1610 ("utf-8", "pax/bad-pax-\udce4\udcf6\udcfc"),
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001611 ("iso8859-1", "pax/bad-pax-\xe4\xf6\xfc"),):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001612 with tarfile.open(tarname, encoding=encoding,
1613 errors="surrogateescape") as tar:
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001614 try:
1615 t = tar.getmember(name)
1616 except KeyError:
1617 self.fail("unable to read bad GNU tar pax header")
1618
Guido van Rossumd8faa362007-04-27 19:54:29 +00001619
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001620class PAXUnicodeTest(UstarUnicodeTest):
1621
1622 format = tarfile.PAX_FORMAT
1623
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001624 # PAX_FORMAT ignores encoding in write mode.
1625 test_unicode_filename_error = None
1626
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001627 def test_binary_header(self):
1628 # Test a POSIX.1-2008 compatible header with a hdrcharset=BINARY field.
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001629 for encoding, name in (
1630 ("utf-8", "pax/hdrcharset-\udce4\udcf6\udcfc"),
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001631 ("iso8859-1", "pax/hdrcharset-\xe4\xf6\xfc"),):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001632 with tarfile.open(tarname, encoding=encoding,
1633 errors="surrogateescape") as tar:
Lars Gustäbel1465cc22010-05-17 18:02:50 +00001634 try:
1635 t = tar.getmember(name)
1636 except KeyError:
1637 self.fail("unable to read POSIX.1-2008 binary header")
1638
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001639
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001640class AppendTestBase:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001641 # Test append mode (cp. patch #1652681).
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001642
Guido van Rossumd8faa362007-04-27 19:54:29 +00001643 def setUp(self):
1644 self.tarname = tmpname
1645 if os.path.exists(self.tarname):
Tim Goldene0bd2c52014-05-06 13:24:26 +01001646 support.unlink(self.tarname)
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001647
Guido van Rossumd8faa362007-04-27 19:54:29 +00001648 def _create_testtar(self, mode="w:"):
Antoine Pitrou95f55602010-09-23 18:36:46 +00001649 with tarfile.open(tarname, encoding="iso8859-1") as src:
1650 t = src.getmember("ustar/regtype")
1651 t.name = "foo"
Lars Gustäbel7a919e92012-05-05 18:15:03 +02001652 with src.extractfile(t) as f:
Antoine Pitroue1eca4e2010-10-29 23:49:49 +00001653 with tarfile.open(self.tarname, mode) as tar:
1654 tar.addfile(t, f)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001655
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001656 def test_append_compressed(self):
1657 self._create_testtar("w:" + self.suffix)
1658 self.assertRaises(tarfile.ReadError, tarfile.open, tmpname, "a")
1659
1660class AppendTest(AppendTestBase, unittest.TestCase):
1661 test_append_compressed = None
1662
1663 def _add_testfile(self, fileobj=None):
1664 with tarfile.open(self.tarname, "a", fileobj=fileobj) as tar:
1665 tar.addfile(tarfile.TarInfo("bar"))
1666
Guido van Rossumd8faa362007-04-27 19:54:29 +00001667 def _test(self, names=["bar"], fileobj=None):
Antoine Pitrou95f55602010-09-23 18:36:46 +00001668 with tarfile.open(self.tarname, fileobj=fileobj) as tar:
1669 self.assertEqual(tar.getnames(), names)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001670
1671 def test_non_existing(self):
1672 self._add_testfile()
1673 self._test()
1674
1675 def test_empty(self):
Lars Gustäbel9520a432009-11-22 18:48:49 +00001676 tarfile.open(self.tarname, "w:").close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001677 self._add_testfile()
1678 self._test()
1679
1680 def test_empty_fileobj(self):
Lars Gustäbel9520a432009-11-22 18:48:49 +00001681 fobj = io.BytesIO(b"\0" * 1024)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001682 self._add_testfile(fobj)
1683 fobj.seek(0)
1684 self._test(fileobj=fobj)
1685
1686 def test_fileobj(self):
1687 self._create_testtar()
Antoine Pitrou95f55602010-09-23 18:36:46 +00001688 with open(self.tarname, "rb") as fobj:
1689 data = fobj.read()
Guido van Rossum34d19282007-08-09 01:03:29 +00001690 fobj = io.BytesIO(data)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001691 self._add_testfile(fobj)
1692 fobj.seek(0)
1693 self._test(names=["foo", "bar"], fileobj=fobj)
1694
1695 def test_existing(self):
1696 self._create_testtar()
1697 self._add_testfile()
1698 self._test(names=["foo", "bar"])
1699
Lars Gustäbel9520a432009-11-22 18:48:49 +00001700 # Append mode is supposed to fail if the tarfile to append to
1701 # does not end with a zero block.
1702 def _test_error(self, data):
Antoine Pitrou95f55602010-09-23 18:36:46 +00001703 with open(self.tarname, "wb") as fobj:
1704 fobj.write(data)
Lars Gustäbel9520a432009-11-22 18:48:49 +00001705 self.assertRaises(tarfile.ReadError, self._add_testfile)
1706
1707 def test_null(self):
1708 self._test_error(b"")
1709
1710 def test_incomplete(self):
1711 self._test_error(b"\0" * 13)
1712
1713 def test_premature_eof(self):
1714 data = tarfile.TarInfo("foo").tobuf()
1715 self._test_error(data)
1716
1717 def test_trailing_garbage(self):
1718 data = tarfile.TarInfo("foo").tobuf()
1719 self._test_error(data + b"\0" * 13)
1720
1721 def test_invalid(self):
1722 self._test_error(b"a" * 512)
1723
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001724class GzipAppendTest(GzipTest, AppendTestBase, unittest.TestCase):
1725 pass
1726
1727class Bz2AppendTest(Bz2Test, AppendTestBase, unittest.TestCase):
1728 pass
1729
1730class LzmaAppendTest(LzmaTest, AppendTestBase, unittest.TestCase):
1731 pass
1732
Guido van Rossumd8faa362007-04-27 19:54:29 +00001733
1734class LimitsTest(unittest.TestCase):
1735
1736 def test_ustar_limits(self):
1737 # 100 char name
1738 tarinfo = tarfile.TarInfo("0123456789" * 10)
Guido van Rossume7ba4952007-06-06 23:52:48 +00001739 tarinfo.tobuf(tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001740
1741 # 101 char name that cannot be stored
1742 tarinfo = tarfile.TarInfo("0123456789" * 10 + "0")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001743 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001744
1745 # 256 char name with a slash at pos 156
1746 tarinfo = tarfile.TarInfo("123/" * 62 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001747 tarinfo.tobuf(tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001748
1749 # 256 char name that cannot be stored
1750 tarinfo = tarfile.TarInfo("1234567/" * 31 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001751 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001752
1753 # 512 char name
1754 tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001755 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001756
1757 # 512 char linkname
1758 tarinfo = tarfile.TarInfo("longlink")
1759 tarinfo.linkname = "123/" * 126 + "longname"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001760 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001761
1762 # uid > 8 digits
1763 tarinfo = tarfile.TarInfo("name")
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001764 tarinfo.uid = 0o10000000
Guido van Rossume7ba4952007-06-06 23:52:48 +00001765 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.USTAR_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001766
1767 def test_gnu_limits(self):
1768 tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001769 tarinfo.tobuf(tarfile.GNU_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001770
1771 tarinfo = tarfile.TarInfo("longlink")
1772 tarinfo.linkname = "123/" * 126 + "longname"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001773 tarinfo.tobuf(tarfile.GNU_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001774
1775 # uid >= 256 ** 7
1776 tarinfo = tarfile.TarInfo("name")
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001777 tarinfo.uid = 0o4000000000000000000
Guido van Rossume7ba4952007-06-06 23:52:48 +00001778 self.assertRaises(ValueError, tarinfo.tobuf, tarfile.GNU_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001779
1780 def test_pax_limits(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001781 tarinfo = tarfile.TarInfo("123/" * 126 + "longname")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001782 tarinfo.tobuf(tarfile.PAX_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001783
1784 tarinfo = tarfile.TarInfo("longlink")
1785 tarinfo.linkname = "123/" * 126 + "longname"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001786 tarinfo.tobuf(tarfile.PAX_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001787
1788 tarinfo = tarfile.TarInfo("name")
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001789 tarinfo.uid = 0o4000000000000000000
Guido van Rossume7ba4952007-06-06 23:52:48 +00001790 tarinfo.tobuf(tarfile.PAX_FORMAT)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001791
1792
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001793class MiscTest(unittest.TestCase):
1794
1795 def test_char_fields(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001796 self.assertEqual(tarfile.stn("foo", 8, "ascii", "strict"),
1797 b"foo\0\0\0\0\0")
1798 self.assertEqual(tarfile.stn("foobar", 3, "ascii", "strict"),
1799 b"foo")
1800 self.assertEqual(tarfile.nts(b"foo\0\0\0\0\0", "ascii", "strict"),
1801 "foo")
1802 self.assertEqual(tarfile.nts(b"foo\0bar\0", "ascii", "strict"),
1803 "foo")
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001804
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001805 def test_read_number_fields(self):
1806 # Issue 13158: Test if GNU tar specific base-256 number fields
1807 # are decoded correctly.
1808 self.assertEqual(tarfile.nti(b"0000001\x00"), 1)
1809 self.assertEqual(tarfile.nti(b"7777777\x00"), 0o7777777)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001810 self.assertEqual(tarfile.nti(b"\x80\x00\x00\x00\x00\x20\x00\x00"),
1811 0o10000000)
1812 self.assertEqual(tarfile.nti(b"\x80\x00\x00\x00\xff\xff\xff\xff"),
1813 0xffffffff)
1814 self.assertEqual(tarfile.nti(b"\xff\xff\xff\xff\xff\xff\xff\xff"),
1815 -1)
1816 self.assertEqual(tarfile.nti(b"\xff\xff\xff\xff\xff\xff\xff\x9c"),
1817 -100)
1818 self.assertEqual(tarfile.nti(b"\xff\x00\x00\x00\x00\x00\x00\x00"),
1819 -0x100000000000000)
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001820
1821 def test_write_number_fields(self):
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001822 self.assertEqual(tarfile.itn(1), b"0000001\x00")
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001823 self.assertEqual(tarfile.itn(0o7777777), b"7777777\x00")
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001824 self.assertEqual(tarfile.itn(0o10000000),
1825 b"\x80\x00\x00\x00\x00\x20\x00\x00")
1826 self.assertEqual(tarfile.itn(0xffffffff),
1827 b"\x80\x00\x00\x00\xff\xff\xff\xff")
1828 self.assertEqual(tarfile.itn(-1),
1829 b"\xff\xff\xff\xff\xff\xff\xff\xff")
1830 self.assertEqual(tarfile.itn(-100),
1831 b"\xff\xff\xff\xff\xff\xff\xff\x9c")
1832 self.assertEqual(tarfile.itn(-0x100000000000000),
1833 b"\xff\x00\x00\x00\x00\x00\x00\x00")
Lars Gustäbelac3d1372011-10-14 12:46:40 +02001834
1835 def test_number_field_limits(self):
Serhiy Storchaka8b562922013-06-17 15:38:50 +03001836 with self.assertRaises(ValueError):
1837 tarfile.itn(-1, 8, tarfile.USTAR_FORMAT)
1838 with self.assertRaises(ValueError):
1839 tarfile.itn(0o10000000, 8, tarfile.USTAR_FORMAT)
1840 with self.assertRaises(ValueError):
1841 tarfile.itn(-0x10000000001, 6, tarfile.GNU_FORMAT)
1842 with self.assertRaises(ValueError):
1843 tarfile.itn(0x10000000000, 6, tarfile.GNU_FORMAT)
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001844
1845
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001846class CommandLineTest(unittest.TestCase):
1847
Serhiy Storchaka255493c2014-02-05 20:54:43 +02001848 def tarfilecmd(self, *args, **kwargs):
1849 rc, out, err = script_helper.assert_python_ok('-m', 'tarfile', *args,
1850 **kwargs)
Antoine Pitrou3b7b1e52013-11-24 01:55:05 +01001851 return out.replace(os.linesep.encode(), b'\n')
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001852
1853 def tarfilecmd_failure(self, *args):
1854 return script_helper.assert_python_failure('-m', 'tarfile', *args)
1855
1856 def make_simple_tarfile(self, tar_name):
1857 files = [support.findfile('tokenize_tests.txt'),
1858 support.findfile('tokenize_tests-no-coding-cookie-'
1859 'and-utf8-bom-sig-only.txt')]
1860 self.addCleanup(support.unlink, tar_name)
1861 with tarfile.open(tar_name, 'w') as tf:
1862 for tardata in files:
1863 tf.add(tardata, arcname=os.path.basename(tardata))
1864
1865 def test_test_command(self):
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02001866 for tar_name in testtarnames:
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001867 for opt in '-t', '--test':
1868 out = self.tarfilecmd(opt, tar_name)
1869 self.assertEqual(out, b'')
1870
1871 def test_test_command_verbose(self):
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02001872 for tar_name in testtarnames:
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001873 for opt in '-v', '--verbose':
1874 out = self.tarfilecmd(opt, '-t', tar_name)
1875 self.assertIn(b'is a tar archive.\n', out)
1876
1877 def test_test_command_invalid_file(self):
1878 zipname = support.findfile('zipdir.zip')
1879 rc, out, err = self.tarfilecmd_failure('-t', zipname)
1880 self.assertIn(b' is not a tar archive.', err)
1881 self.assertEqual(out, b'')
1882 self.assertEqual(rc, 1)
1883
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02001884 for tar_name in testtarnames:
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001885 with self.subTest(tar_name=tar_name):
1886 with open(tar_name, 'rb') as f:
1887 data = f.read()
1888 try:
1889 with open(tmpname, 'wb') as f:
1890 f.write(data[:511])
1891 rc, out, err = self.tarfilecmd_failure('-t', tmpname)
1892 self.assertEqual(out, b'')
1893 self.assertEqual(rc, 1)
1894 finally:
1895 support.unlink(tmpname)
1896
1897 def test_list_command(self):
Serhiy Storchaka255493c2014-02-05 20:54:43 +02001898 for tar_name in testtarnames:
1899 with support.captured_stdout() as t:
1900 with tarfile.open(tar_name, 'r') as tf:
1901 tf.list(verbose=False)
1902 expected = t.getvalue().encode('ascii', 'backslashreplace')
1903 for opt in '-l', '--list':
1904 out = self.tarfilecmd(opt, tar_name,
1905 PYTHONIOENCODING='ascii')
1906 self.assertEqual(out, expected)
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001907
1908 def test_list_command_verbose(self):
Serhiy Storchaka255493c2014-02-05 20:54:43 +02001909 for tar_name in testtarnames:
1910 with support.captured_stdout() as t:
1911 with tarfile.open(tar_name, 'r') as tf:
1912 tf.list(verbose=True)
1913 expected = t.getvalue().encode('ascii', 'backslashreplace')
1914 for opt in '-v', '--verbose':
1915 out = self.tarfilecmd(opt, '-l', tar_name,
1916 PYTHONIOENCODING='ascii')
1917 self.assertEqual(out, expected)
Serhiy Storchakad27b4552013-11-24 01:53:29 +02001918
1919 def test_list_command_invalid_file(self):
1920 zipname = support.findfile('zipdir.zip')
1921 rc, out, err = self.tarfilecmd_failure('-l', zipname)
1922 self.assertIn(b' is not a tar archive.', err)
1923 self.assertEqual(out, b'')
1924 self.assertEqual(rc, 1)
1925
1926 def test_create_command(self):
1927 files = [support.findfile('tokenize_tests.txt'),
1928 support.findfile('tokenize_tests-no-coding-cookie-'
1929 'and-utf8-bom-sig-only.txt')]
1930 for opt in '-c', '--create':
1931 try:
1932 out = self.tarfilecmd(opt, tmpname, *files)
1933 self.assertEqual(out, b'')
1934 with tarfile.open(tmpname) as tar:
1935 tar.getmembers()
1936 finally:
1937 support.unlink(tmpname)
1938
1939 def test_create_command_verbose(self):
1940 files = [support.findfile('tokenize_tests.txt'),
1941 support.findfile('tokenize_tests-no-coding-cookie-'
1942 'and-utf8-bom-sig-only.txt')]
1943 for opt in '-v', '--verbose':
1944 try:
1945 out = self.tarfilecmd(opt, '-c', tmpname, *files)
1946 self.assertIn(b' file created.', out)
1947 with tarfile.open(tmpname) as tar:
1948 tar.getmembers()
1949 finally:
1950 support.unlink(tmpname)
1951
1952 def test_create_command_dotless_filename(self):
1953 files = [support.findfile('tokenize_tests.txt')]
1954 try:
1955 out = self.tarfilecmd('-c', dotlessname, *files)
1956 self.assertEqual(out, b'')
1957 with tarfile.open(dotlessname) as tar:
1958 tar.getmembers()
1959 finally:
1960 support.unlink(dotlessname)
1961
1962 def test_create_command_dot_started_filename(self):
1963 tar_name = os.path.join(TEMPDIR, ".testtar")
1964 files = [support.findfile('tokenize_tests.txt')]
1965 try:
1966 out = self.tarfilecmd('-c', tar_name, *files)
1967 self.assertEqual(out, b'')
1968 with tarfile.open(tar_name) as tar:
1969 tar.getmembers()
1970 finally:
1971 support.unlink(tar_name)
1972
1973 def test_extract_command(self):
1974 self.make_simple_tarfile(tmpname)
1975 for opt in '-e', '--extract':
1976 try:
1977 with support.temp_cwd(tarextdir):
1978 out = self.tarfilecmd(opt, tmpname)
1979 self.assertEqual(out, b'')
1980 finally:
1981 support.rmtree(tarextdir)
1982
1983 def test_extract_command_verbose(self):
1984 self.make_simple_tarfile(tmpname)
1985 for opt in '-v', '--verbose':
1986 try:
1987 with support.temp_cwd(tarextdir):
1988 out = self.tarfilecmd(opt, '-e', tmpname)
1989 self.assertIn(b' file is extracted.', out)
1990 finally:
1991 support.rmtree(tarextdir)
1992
1993 def test_extract_command_different_directory(self):
1994 self.make_simple_tarfile(tmpname)
1995 try:
1996 with support.temp_cwd(tarextdir):
1997 out = self.tarfilecmd('-e', tmpname, 'spamdir')
1998 self.assertEqual(out, b'')
1999 finally:
2000 support.rmtree(tarextdir)
2001
2002 def test_extract_command_invalid_file(self):
2003 zipname = support.findfile('zipdir.zip')
2004 with support.temp_cwd(tarextdir):
2005 rc, out, err = self.tarfilecmd_failure('-e', zipname)
2006 self.assertIn(b' is not a tar archive.', err)
2007 self.assertEqual(out, b'')
2008 self.assertEqual(rc, 1)
2009
2010
Lars Gustäbel01385812010-03-03 12:08:54 +00002011class ContextManagerTest(unittest.TestCase):
2012
2013 def test_basic(self):
2014 with tarfile.open(tarname) as tar:
2015 self.assertFalse(tar.closed, "closed inside runtime context")
2016 self.assertTrue(tar.closed, "context manager failed")
2017
2018 def test_closed(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002019 # The __enter__() method is supposed to raise OSError
Lars Gustäbel01385812010-03-03 12:08:54 +00002020 # if the TarFile object is already closed.
2021 tar = tarfile.open(tarname)
2022 tar.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002023 with self.assertRaises(OSError):
Lars Gustäbel01385812010-03-03 12:08:54 +00002024 with tar:
2025 pass
2026
2027 def test_exception(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002028 # Test if the OSError exception is passed through properly.
Lars Gustäbel01385812010-03-03 12:08:54 +00002029 with self.assertRaises(Exception) as exc:
2030 with tarfile.open(tarname) as tar:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002031 raise OSError
2032 self.assertIsInstance(exc.exception, OSError,
Lars Gustäbel01385812010-03-03 12:08:54 +00002033 "wrong exception raised in context manager")
2034 self.assertTrue(tar.closed, "context manager failed")
2035
2036 def test_no_eof(self):
2037 # __exit__() must not write end-of-archive blocks if an
2038 # exception was raised.
2039 try:
2040 with tarfile.open(tmpname, "w") as tar:
2041 raise Exception
2042 except:
2043 pass
2044 self.assertEqual(os.path.getsize(tmpname), 0,
2045 "context manager wrote an end-of-archive block")
2046 self.assertTrue(tar.closed, "context manager failed")
2047
2048 def test_eof(self):
2049 # __exit__() must write end-of-archive blocks, i.e. call
2050 # TarFile.close() if there was no error.
2051 with tarfile.open(tmpname, "w"):
2052 pass
2053 self.assertNotEqual(os.path.getsize(tmpname), 0,
2054 "context manager wrote no end-of-archive block")
2055
2056 def test_fileobj(self):
2057 # Test that __exit__() did not close the external file
2058 # object.
Antoine Pitrou95f55602010-09-23 18:36:46 +00002059 with open(tmpname, "wb") as fobj:
2060 try:
2061 with tarfile.open(fileobj=fobj, mode="w") as tar:
2062 raise Exception
2063 except:
2064 pass
2065 self.assertFalse(fobj.closed, "external file object was closed")
2066 self.assertTrue(tar.closed, "context manager failed")
Lars Gustäbel01385812010-03-03 12:08:54 +00002067
2068
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002069@unittest.skipIf(hasattr(os, "link"), "requires os.link to be missing")
2070class LinkEmulationTest(ReadTest, unittest.TestCase):
Lars Gustäbel1b512722010-06-03 12:45:16 +00002071
2072 # Test for issue #8741 regression. On platforms that do not support
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002073 # symbolic or hard links tarfile tries to extract these types of members
2074 # as the regular files they point to.
Lars Gustäbel1b512722010-06-03 12:45:16 +00002075 def _test_link_extraction(self, name):
2076 self.tar.extract(name, TEMPDIR)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002077 with open(os.path.join(TEMPDIR, name), "rb") as f:
2078 data = f.read()
Lars Gustäbel1b512722010-06-03 12:45:16 +00002079 self.assertEqual(md5sum(data), md5_regtype)
2080
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002081 # See issues #1578269, #8879, and #17689 for some history on these skips
Brian Curtind40e6f72010-07-08 21:39:08 +00002082 @unittest.skipIf(hasattr(os.path, "islink"),
2083 "Skip emulation - has os.path.islink but not os.link")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002084 def test_hardlink_extraction1(self):
2085 self._test_link_extraction("ustar/lnktype")
2086
Brian Curtind40e6f72010-07-08 21:39:08 +00002087 @unittest.skipIf(hasattr(os.path, "islink"),
2088 "Skip emulation - has os.path.islink but not os.link")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002089 def test_hardlink_extraction2(self):
2090 self._test_link_extraction("./ustar/linktest2/lnktype")
2091
Brian Curtin74e45612010-07-09 15:58:59 +00002092 @unittest.skipIf(hasattr(os, "symlink"),
2093 "Skip emulation if symlink exists")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002094 def test_symlink_extraction1(self):
2095 self._test_link_extraction("ustar/symtype")
2096
Brian Curtin74e45612010-07-09 15:58:59 +00002097 @unittest.skipIf(hasattr(os, "symlink"),
2098 "Skip emulation if symlink exists")
Lars Gustäbel1b512722010-06-03 12:45:16 +00002099 def test_symlink_extraction2(self):
2100 self._test_link_extraction("./ustar/linktest2/symtype")
2101
2102
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002103class Bz2PartialReadTest(Bz2Test, unittest.TestCase):
Lars Gustäbel42e00912009-03-22 20:34:29 +00002104 # Issue5068: The _BZ2Proxy.read() method loops forever
2105 # on an empty or partial bzipped file.
2106
2107 def _test_partial_input(self, mode):
2108 class MyBytesIO(io.BytesIO):
2109 hit_eof = False
2110 def read(self, n):
2111 if self.hit_eof:
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002112 raise AssertionError("infinite loop detected in "
2113 "tarfile.open()")
Lars Gustäbel42e00912009-03-22 20:34:29 +00002114 self.hit_eof = self.tell() == len(self.getvalue())
2115 return super(MyBytesIO, self).read(n)
Lars Gustäbel9520a432009-11-22 18:48:49 +00002116 def seek(self, *args):
2117 self.hit_eof = False
2118 return super(MyBytesIO, self).seek(*args)
Lars Gustäbel42e00912009-03-22 20:34:29 +00002119
2120 data = bz2.compress(tarfile.TarInfo("foo").tobuf())
2121 for x in range(len(data) + 1):
Lars Gustäbel9520a432009-11-22 18:48:49 +00002122 try:
2123 tarfile.open(fileobj=MyBytesIO(data[:x]), mode=mode)
2124 except tarfile.ReadError:
2125 pass # we have no interest in ReadErrors
Lars Gustäbel42e00912009-03-22 20:34:29 +00002126
2127 def test_partial_input(self):
2128 self._test_partial_input("r")
2129
2130 def test_partial_input_bz2(self):
2131 self._test_partial_input("r:bz2")
2132
2133
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002134def setUpModule():
Antoine Pitrou95f55602010-09-23 18:36:46 +00002135 support.unlink(TEMPDIR)
Antoine Pitrou941ee882009-11-11 20:59:38 +00002136 os.makedirs(TEMPDIR)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002137
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02002138 global testtarnames
2139 testtarnames = [tarname]
Antoine Pitrou95f55602010-09-23 18:36:46 +00002140 with open(tarname, "rb") as fobj:
2141 data = fobj.read()
Neal Norwitza4f651a2004-07-20 22:07:44 +00002142
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002143 # Create compressed tarfiles.
2144 for c in GzipTest, Bz2Test, LzmaTest:
2145 if c.open:
2146 support.unlink(c.tarname)
Serhiy Storchaka5e8c8092013-11-24 02:30:59 +02002147 testtarnames.append(c.tarname)
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002148 with c.open(c.tarname, "wb") as tar:
2149 tar.write(data)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002150
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002151def tearDownModule():
2152 if os.path.exists(TEMPDIR):
Tim Goldene0bd2c52014-05-06 13:24:26 +01002153 support.rmtree(TEMPDIR)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002154
Neal Norwitz996acf12003-02-17 14:51:41 +00002155if __name__ == "__main__":
Serhiy Storchaka8b562922013-06-17 15:38:50 +03002156 unittest.main()