blob: a9797aeb992c4ddb9c745208573334bc5fd8f279 [file] [log] [blame]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001import sys
2import os
3import shutil
Brett Cannon455ea532003-06-12 08:01:06 +00004import tempfile
Georg Brandl38c6a222006-05-10 16:26:03 +00005import StringIO
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00006
7import unittest
8import tarfile
9
10from test import test_support
11
12# Check for our compression modules.
13try:
14 import gzip
Neal Norwitzae323192003-04-14 01:18:32 +000015 gzip.GzipFile
16except (ImportError, AttributeError):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000017 gzip = None
18try:
19 import bz2
20except ImportError:
21 bz2 = None
22
23def path(path):
24 return test_support.findfile(path)
25
Brett Cannon455ea532003-06-12 08:01:06 +000026testtar = path("testtar.tar")
27tempdir = os.path.join(tempfile.gettempdir(), "testtar" + os.extsep + "dir")
28tempname = test_support.TESTFN
Lars Gustäbel08303db2008-02-11 18:36:07 +000029membercount = 13
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000030
31def tarname(comp=""):
32 if not comp:
33 return testtar
Brett Cannon43e559a2003-06-12 19:16:58 +000034 return os.path.join(tempdir, "%s%s%s" % (testtar, os.extsep, comp))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000035
36def dirname():
37 if not os.path.exists(tempdir):
38 os.mkdir(tempdir)
39 return tempdir
40
41def tmpname():
42 return tempname
43
44
45class BaseTest(unittest.TestCase):
46 comp = ''
47 mode = 'r'
48 sep = ':'
49
50 def setUp(self):
51 mode = self.mode + self.sep + self.comp
52 self.tar = tarfile.open(tarname(self.comp), mode)
53
54 def tearDown(self):
55 self.tar.close()
56
57class ReadTest(BaseTest):
58
59 def test(self):
60 """Test member extraction.
61 """
62 members = 0
63 for tarinfo in self.tar:
64 members += 1
65 if not tarinfo.isreg():
66 continue
67 f = self.tar.extractfile(tarinfo)
68 self.assert_(len(f.read()) == tarinfo.size,
69 "size read does not match expected size")
70 f.close()
71
72 self.assert_(members == membercount,
73 "could not find all members")
74
75 def test_sparse(self):
76 """Test sparse member extraction.
77 """
78 if self.sep != "|":
79 f1 = self.tar.extractfile("S-SPARSE")
Jack Jansen149a8992003-03-07 13:27:53 +000080 f2 = self.tar.extractfile("S-SPARSE-WITH-NULLS")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000081 self.assert_(f1.read() == f2.read(),
82 "_FileObject failed on sparse file member")
83
84 def test_readlines(self):
85 """Test readlines() method of _FileObject.
86 """
87 if self.sep != "|":
Jack Jansen149a8992003-03-07 13:27:53 +000088 filename = "0-REGTYPE-TEXT"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000089 self.tar.extract(filename, dirname())
Tim Peters02494762006-05-26 14:02:05 +000090 f = open(os.path.join(dirname(), filename), "rU")
91 lines1 = f.readlines()
92 f.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000093 lines2 = self.tar.extractfile(filename).readlines()
94 self.assert_(lines1 == lines2,
95 "_FileObject.readline() does not work correctly")
96
Martin v. Löwisdf241532005-03-03 08:17:42 +000097 def test_iter(self):
98 # Test iteration over ExFileObject.
99 if self.sep != "|":
100 filename = "0-REGTYPE-TEXT"
101 self.tar.extract(filename, dirname())
Tim Peters02494762006-05-26 14:02:05 +0000102 f = open(os.path.join(dirname(), filename), "rU")
103 lines1 = f.readlines()
104 f.close()
Martin v. Löwisdf241532005-03-03 08:17:42 +0000105 lines2 = [line for line in self.tar.extractfile(filename)]
106 self.assert_(lines1 == lines2,
107 "ExFileObject iteration does not work correctly")
108
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000109 def test_seek(self):
110 """Test seek() method of _FileObject, incl. random reading.
111 """
112 if self.sep != "|":
Lars Gustäbelaedb92e2006-12-23 16:51:47 +0000113 filename = "0-REGTYPE-TEXT"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000114 self.tar.extract(filename, dirname())
Tim Peters02494762006-05-26 14:02:05 +0000115 f = open(os.path.join(dirname(), filename), "rb")
116 data = f.read()
117 f.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000118
119 tarinfo = self.tar.getmember(filename)
120 fobj = self.tar.extractfile(tarinfo)
121
122 text = fobj.read()
123 fobj.seek(0)
124 self.assert_(0 == fobj.tell(),
125 "seek() to file's start failed")
126 fobj.seek(2048, 0)
127 self.assert_(2048 == fobj.tell(),
128 "seek() to absolute position failed")
129 fobj.seek(-1024, 1)
130 self.assert_(1024 == fobj.tell(),
131 "seek() to negative relative position failed")
132 fobj.seek(1024, 1)
133 self.assert_(2048 == fobj.tell(),
134 "seek() to positive relative position failed")
135 s = fobj.read(10)
136 self.assert_(s == data[2048:2058],
137 "read() after seek failed")
138 fobj.seek(0, 2)
139 self.assert_(tarinfo.size == fobj.tell(),
140 "seek() to file's end failed")
141 self.assert_(fobj.read() == "",
142 "read() at file's end did not return empty string")
143 fobj.seek(-tarinfo.size, 2)
144 self.assert_(0 == fobj.tell(),
145 "relative seek() to file's start failed")
146 fobj.seek(512)
147 s1 = fobj.readlines()
148 fobj.seek(512)
149 s2 = fobj.readlines()
150 self.assert_(s1 == s2,
151 "readlines() after seek failed")
Lars Gustäbelaedb92e2006-12-23 16:51:47 +0000152 fobj.seek(0)
153 self.assert_(len(fobj.readline()) == fobj.tell(),
154 "tell() after readline() failed")
155 fobj.seek(512)
156 self.assert_(len(fobj.readline()) + 512 == fobj.tell(),
157 "tell() after seek() and readline() failed")
158 fobj.seek(0)
159 line = fobj.readline()
160 self.assert_(fobj.read() == data[len(line):],
161 "read() after readline() failed")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000162 fobj.close()
163
Neal Norwitzf3396542005-10-28 05:52:22 +0000164 def test_old_dirtype(self):
165 """Test old style dirtype member (bug #1336623).
166 """
167 # Old tars create directory members using a REGTYPE
168 # header with a "/" appended to the filename field.
169
170 # Create an old tar style directory entry.
171 filename = tmpname()
172 tarinfo = tarfile.TarInfo("directory/")
173 tarinfo.type = tarfile.REGTYPE
174
Tim Petersb1f32512006-05-26 13:39:17 +0000175 fobj = open(filename, "w")
Neal Norwitzf3396542005-10-28 05:52:22 +0000176 fobj.write(tarinfo.tobuf())
177 fobj.close()
178
179 try:
180 # Test if it is still a directory entry when
181 # read back.
182 tar = tarfile.open(filename)
183 tarinfo = tar.getmembers()[0]
184 tar.close()
185
186 self.assert_(tarinfo.type == tarfile.DIRTYPE)
187 self.assert_(tarinfo.name.endswith("/"))
188 finally:
189 try:
190 os.unlink(filename)
191 except:
192 pass
193
Lars Gustäbeld2201442007-04-20 14:49:02 +0000194 def test_dirtype(self):
195 for tarinfo in self.tar:
196 if tarinfo.isdir():
197 self.assert_(tarinfo.name.endswith("/"))
198 self.assert_(not tarinfo.name[:-1].endswith("/"))
199
Lars Gustäbele5f9e582008-01-04 14:44:23 +0000200 def test_extractall(self):
201 # Test if extractall() correctly restores directory permissions
202 # and times (see issue1735).
203 if sys.platform == "win32":
204 # Win32 has no support for utime() on directories or
205 # fine grained permissions.
206 return
207
208 fobj = StringIO.StringIO()
209 tar = tarfile.open(fileobj=fobj, mode="w:")
210 for name in ("foo", "foo/bar"):
211 tarinfo = tarfile.TarInfo(name)
212 tarinfo.type = tarfile.DIRTYPE
213 tarinfo.mtime = 07606136617
214 tarinfo.mode = 0755
215 tar.addfile(tarinfo)
216 tar.close()
217 fobj.seek(0)
218
219 TEMPDIR = os.path.join(dirname(), "extract-test")
220 tar = tarfile.open(fileobj=fobj)
221 tar.extractall(TEMPDIR)
222 for tarinfo in tar.getmembers():
223 path = os.path.join(TEMPDIR, tarinfo.name)
224 self.assertEqual(tarinfo.mode, os.stat(path).st_mode & 0777)
225 self.assertEqual(tarinfo.mtime, os.path.getmtime(path))
226 tar.close()
227
Lars Gustäbel08303db2008-02-11 18:36:07 +0000228 def test_star(self):
229 try:
230 self.tar.getmember("7-STAR")
231 except KeyError:
232 self.fail("finding 7-STAR member failed (mangled prefix?)")
233
Lars Gustäbeld2201442007-04-20 14:49:02 +0000234
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000235class ReadStreamTest(ReadTest):
236 sep = "|"
237
238 def test(self):
239 """Test member extraction, and for StreamError when
240 seeking backwards.
241 """
242 ReadTest.test(self)
243 tarinfo = self.tar.getmembers()[0]
244 f = self.tar.extractfile(tarinfo)
245 self.assertRaises(tarfile.StreamError, f.read)
246
247 def test_stream(self):
248 """Compare the normal tar and the stream tar.
249 """
250 stream = self.tar
251 tar = tarfile.open(tarname(), 'r')
252
253 while 1:
254 t1 = tar.next()
255 t2 = stream.next()
256 if t1 is None:
257 break
258 self.assert_(t2 is not None, "stream.next() failed.")
259
260 if t2.islnk() or t2.issym():
261 self.assertRaises(tarfile.StreamError, stream.extractfile, t2)
262 continue
263 v1 = tar.extractfile(t1)
264 v2 = stream.extractfile(t2)
265 if v1 is None:
266 continue
267 self.assert_(v2 is not None, "stream.extractfile() failed")
268 self.assert_(v1.read() == v2.read(), "stream extraction failed")
269
Tim Peters02494762006-05-26 14:02:05 +0000270 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000271 stream.close()
272
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000273class ReadDetectTest(ReadTest):
274
275 def setUp(self):
276 self.tar = tarfile.open(tarname(self.comp), self.mode)
277
278class ReadDetectFileobjTest(ReadTest):
279
280 def setUp(self):
281 name = tarname(self.comp)
Tim Peters12087ba2006-05-15 20:44:10 +0000282 self.tar = tarfile.open(name, mode=self.mode,
283 fileobj=open(name, "rb"))
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000284
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000285class ReadAsteriskTest(ReadTest):
286
287 def setUp(self):
288 mode = self.mode + self.sep + "*"
289 self.tar = tarfile.open(tarname(self.comp), mode)
290
291class ReadStreamAsteriskTest(ReadStreamTest):
292
293 def setUp(self):
294 mode = self.mode + self.sep + "*"
295 self.tar = tarfile.open(tarname(self.comp), mode)
296
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000297class ReadFileobjTest(BaseTest):
298
299 def test_fileobj_with_offset(self):
300 # Skip the first member and store values from the second member
301 # of the testtar.
302 self.tar.next()
303 t = self.tar.next()
304 name = t.name
305 offset = t.offset
306 data = self.tar.extractfile(t).read()
307 self.tar.close()
308
309 # Open the testtar and seek to the offset of the second member.
310 if self.comp == "gz":
311 _open = gzip.GzipFile
312 elif self.comp == "bz2":
313 _open = bz2.BZ2File
314 else:
315 _open = open
316 fobj = _open(tarname(self.comp), "rb")
317 fobj.seek(offset)
318
319 # Test if the tarfile starts with the second member.
320 self.tar = tarfile.open(tarname(self.comp), "r:", fileobj=fobj)
321 t = self.tar.next()
322 self.assertEqual(t.name, name)
323 # Read to the end of fileobj and test if seeking back to the
324 # beginning works.
325 self.tar.getmembers()
326 self.assertEqual(self.tar.extractfile(t).read(), data,
327 "seek back did not work")
328
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000329class WriteTest(BaseTest):
330 mode = 'w'
331
332 def setUp(self):
333 mode = self.mode + self.sep + self.comp
334 self.src = tarfile.open(tarname(self.comp), 'r')
Martin v. Löwisc234a522004-08-22 21:28:33 +0000335 self.dstname = tmpname()
336 self.dst = tarfile.open(self.dstname, mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000337
338 def tearDown(self):
339 self.src.close()
340 self.dst.close()
341
342 def test_posix(self):
343 self.dst.posix = 1
344 self._test()
345
346 def test_nonposix(self):
347 self.dst.posix = 0
348 self._test()
349
Martin v. Löwisc234a522004-08-22 21:28:33 +0000350 def test_small(self):
351 self.dst.add(os.path.join(os.path.dirname(__file__),"cfgparser.1"))
352 self.dst.close()
353 self.assertNotEqual(os.stat(self.dstname).st_size, 0)
354
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000355 def _test(self):
356 for tarinfo in self.src:
357 if not tarinfo.isreg():
358 continue
359 f = self.src.extractfile(tarinfo)
Georg Brandl38c6a222006-05-10 16:26:03 +0000360 if self.dst.posix and len(tarinfo.name) > tarfile.LENGTH_NAME and "/" not in tarinfo.name:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000361 self.assertRaises(ValueError, self.dst.addfile,
362 tarinfo, f)
363 else:
364 self.dst.addfile(tarinfo, f)
365
Lars Gustäbel12e087a2006-12-23 18:13:57 +0000366 def test_add_self(self):
367 dstname = os.path.abspath(self.dstname)
368
369 self.assertEqual(self.dst.name, dstname, "archive name must be absolute")
370
371 self.dst.add(dstname)
372 self.assertEqual(self.dst.getnames(), [], "added the archive to itself")
373
374 cwd = os.getcwd()
375 os.chdir(dirname())
376 self.dst.add(dstname)
377 os.chdir(cwd)
378 self.assertEqual(self.dst.getnames(), [], "added the archive to itself")
379
Georg Brandlee23f4b2006-10-24 16:54:23 +0000380
381class Write100Test(BaseTest):
382 # The name field in a tar header stores strings of at most 100 chars.
383 # If a string is shorter than 100 chars it has to be padded with '\0',
384 # which implies that a string of exactly 100 chars is stored without
385 # a trailing '\0'.
386
387 def setUp(self):
388 self.name = "01234567890123456789012345678901234567890123456789"
389 self.name += "01234567890123456789012345678901234567890123456789"
390
391 self.tar = tarfile.open(tmpname(), "w")
392 t = tarfile.TarInfo(self.name)
393 self.tar.addfile(t)
394 self.tar.close()
395
396 self.tar = tarfile.open(tmpname())
397
398 def tearDown(self):
399 self.tar.close()
400
401 def test(self):
402 self.assertEqual(self.tar.getnames()[0], self.name,
403 "failed to store 100 char filename")
404
405
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000406class WriteSize0Test(BaseTest):
407 mode = 'w'
408
409 def setUp(self):
410 self.tmpdir = dirname()
411 self.dstname = tmpname()
412 self.dst = tarfile.open(self.dstname, "w")
413
414 def tearDown(self):
415 self.dst.close()
416
417 def test_file(self):
418 path = os.path.join(self.tmpdir, "file")
Tim Peters02494762006-05-26 14:02:05 +0000419 f = open(path, "w")
420 f.close()
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000421 tarinfo = self.dst.gettarinfo(path)
422 self.assertEqual(tarinfo.size, 0)
Tim Peters02494762006-05-26 14:02:05 +0000423 f = open(path, "w")
424 f.write("aaa")
425 f.close()
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000426 tarinfo = self.dst.gettarinfo(path)
427 self.assertEqual(tarinfo.size, 3)
428
429 def test_directory(self):
430 path = os.path.join(self.tmpdir, "directory")
Tim Peters4ccc0b72006-05-15 21:32:25 +0000431 if os.path.exists(path):
432 # This shouldn't be necessary, but is <wink> if a previous
433 # run was killed in mid-stream.
434 shutil.rmtree(path)
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000435 os.mkdir(path)
436 tarinfo = self.dst.gettarinfo(path)
437 self.assertEqual(tarinfo.size, 0)
438
439 def test_symlink(self):
440 if hasattr(os, "symlink"):
441 path = os.path.join(self.tmpdir, "symlink")
442 os.symlink("link_target", path)
443 tarinfo = self.dst.gettarinfo(path)
444 self.assertEqual(tarinfo.size, 0)
445
446
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000447class WriteStreamTest(WriteTest):
448 sep = '|'
449
Neal Norwitz7443b802006-08-21 18:43:51 +0000450 def test_padding(self):
451 self.dst.close()
452
453 if self.comp == "gz":
454 f = gzip.GzipFile(self.dstname)
455 s = f.read()
456 f.close()
457 elif self.comp == "bz2":
458 f = bz2.BZ2Decompressor()
459 s = file(self.dstname).read()
460 s = f.decompress(s)
461 self.assertEqual(len(f.unused_data), 0, "trailing data")
462 else:
463 f = file(self.dstname)
464 s = f.read()
465 f.close()
466
467 self.assertEqual(s.count("\0"), tarfile.RECORDSIZE,
468 "incorrect zero padding")
469
470
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000471class WriteGNULongTest(unittest.TestCase):
472 """This testcase checks for correct creation of GNU Longname
473 and Longlink extensions.
474
475 It creates a tarfile and adds empty members with either
476 long names, long linknames or both and compares the size
477 of the tarfile with the expected size.
478
479 It checks for SF bug #812325 in TarFile._create_gnulong().
480
481 While I was writing this testcase, I noticed a second bug
482 in the same method:
483 Long{names,links} weren't null-terminated which lead to
484 bad tarfiles when their length was a multiple of 512. This
485 is tested as well.
486 """
487
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000488 def _length(self, s):
489 blocks, remainder = divmod(len(s) + 1, 512)
490 if remainder:
491 blocks += 1
492 return blocks * 512
493
494 def _calc_size(self, name, link=None):
495 # initial tar header
496 count = 512
497
498 if len(name) > tarfile.LENGTH_NAME:
499 # gnu longname extended header + longname
500 count += 512
501 count += self._length(name)
502
503 if link is not None and len(link) > tarfile.LENGTH_LINK:
504 # gnu longlink extended header + longlink
505 count += 512
506 count += self._length(link)
507
508 return count
509
510 def _test(self, name, link=None):
511 tarinfo = tarfile.TarInfo(name)
512 if link:
513 tarinfo.linkname = link
514 tarinfo.type = tarfile.LNKTYPE
515
Georg Brandl25f58f62006-12-06 22:21:23 +0000516 tar = tarfile.open(tmpname(), "w")
517 tar.posix = False
518 tar.addfile(tarinfo)
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000519
520 v1 = self._calc_size(name, link)
Georg Brandl25f58f62006-12-06 22:21:23 +0000521 v2 = tar.offset
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000522 self.assertEqual(v1, v2, "GNU longname/longlink creation failed")
523
Georg Brandl25f58f62006-12-06 22:21:23 +0000524 tar.close()
525
526 tar = tarfile.open(tmpname())
527 member = tar.next()
528 self.failIf(member is None, "unable to read longname member")
529 self.assert_(tarinfo.name == member.name and \
530 tarinfo.linkname == member.linkname, \
531 "unable to read longname member")
532
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000533 def test_longname_1023(self):
534 self._test(("longnam/" * 127) + "longnam")
535
536 def test_longname_1024(self):
537 self._test(("longnam/" * 127) + "longname")
538
539 def test_longname_1025(self):
540 self._test(("longnam/" * 127) + "longname_")
541
542 def test_longlink_1023(self):
543 self._test("name", ("longlnk/" * 127) + "longlnk")
544
545 def test_longlink_1024(self):
546 self._test("name", ("longlnk/" * 127) + "longlink")
547
548 def test_longlink_1025(self):
549 self._test("name", ("longlnk/" * 127) + "longlink_")
550
551 def test_longnamelink_1023(self):
552 self._test(("longnam/" * 127) + "longnam",
553 ("longlnk/" * 127) + "longlnk")
554
555 def test_longnamelink_1024(self):
556 self._test(("longnam/" * 127) + "longname",
557 ("longlnk/" * 127) + "longlink")
558
559 def test_longnamelink_1025(self):
560 self._test(("longnam/" * 127) + "longname_",
561 ("longlnk/" * 127) + "longlink_")
562
Georg Brandl38c6a222006-05-10 16:26:03 +0000563class ReadGNULongTest(unittest.TestCase):
564
565 def setUp(self):
566 self.tar = tarfile.open(tarname())
567
568 def tearDown(self):
569 self.tar.close()
570
571 def test_1471427(self):
572 """Test reading of longname (bug #1471427).
573 """
574 name = "test/" * 20 + "0-REGTYPE"
575 try:
576 tarinfo = self.tar.getmember(name)
577 except KeyError:
578 tarinfo = None
579 self.assert_(tarinfo is not None, "longname not found")
580 self.assert_(tarinfo.type != tarfile.DIRTYPE, "read longname as dirtype")
581
582 def test_read_name(self):
583 name = ("0-LONGNAME-" * 10)[:101]
584 try:
585 tarinfo = self.tar.getmember(name)
586 except KeyError:
587 tarinfo = None
588 self.assert_(tarinfo is not None, "longname not found")
589
590 def test_read_link(self):
591 link = ("1-LONGLINK-" * 10)[:101]
592 name = ("0-LONGNAME-" * 10)[:101]
593 try:
594 tarinfo = self.tar.getmember(link)
595 except KeyError:
596 tarinfo = None
597 self.assert_(tarinfo is not None, "longlink not found")
598 self.assert_(tarinfo.linkname == name, "linkname wrong")
599
600 def test_truncated_longname(self):
Tim Peters02494762006-05-26 14:02:05 +0000601 f = open(tarname())
602 fobj = StringIO.StringIO(f.read(1024))
603 f.close()
Georg Brandl38c6a222006-05-10 16:26:03 +0000604 tar = tarfile.open(name="foo.tar", fileobj=fobj)
605 self.assert_(len(tar.getmembers()) == 0, "")
Tim Peters02494762006-05-26 14:02:05 +0000606 tar.close()
Georg Brandl38c6a222006-05-10 16:26:03 +0000607
608
Neal Norwitza4f651a2004-07-20 22:07:44 +0000609class ExtractHardlinkTest(BaseTest):
610
611 def test_hardlink(self):
612 """Test hardlink extraction (bug #857297)
613 """
614 # Prevent errors from being caught
615 self.tar.errorlevel = 1
616
617 self.tar.extract("0-REGTYPE", dirname())
618 try:
619 # Extract 1-LNKTYPE which is a hardlink to 0-REGTYPE
620 self.tar.extract("1-LNKTYPE", dirname())
621 except EnvironmentError, e:
622 import errno
623 if e.errno == errno.ENOENT:
624 self.fail("hardlink not extracted properly")
625
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000626class CreateHardlinkTest(BaseTest):
627 """Test the creation of LNKTYPE (hardlink) members in an archive.
628 In this respect tarfile.py mimics the behaviour of GNU tar: If
629 a file has a st_nlink > 1, it will be added a REGTYPE member
630 only the first time.
631 """
632
633 def setUp(self):
634 self.tar = tarfile.open(tmpname(), "w")
635
636 self.foo = os.path.join(dirname(), "foo")
637 self.bar = os.path.join(dirname(), "bar")
638
639 if os.path.exists(self.foo):
640 os.remove(self.foo)
641 if os.path.exists(self.bar):
642 os.remove(self.bar)
643
Tim Peters02494762006-05-26 14:02:05 +0000644 f = open(self.foo, "w")
645 f.write("foo")
646 f.close()
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000647 self.tar.add(self.foo)
648
649 def test_add_twice(self):
650 # If st_nlink == 1 then the same file will be added as
651 # REGTYPE every time.
652 tarinfo = self.tar.gettarinfo(self.foo)
653 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
654 "add file as regular failed")
655
656 def test_add_hardlink(self):
657 # If st_nlink > 1 then the same file will be added as
658 # LNKTYPE.
659 os.link(self.foo, self.bar)
660 tarinfo = self.tar.gettarinfo(self.foo)
661 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
662 "add file as hardlink failed")
663
664 tarinfo = self.tar.gettarinfo(self.bar)
665 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
666 "add file as hardlink failed")
667
668 def test_dereference_hardlink(self):
669 self.tar.dereference = True
670 os.link(self.foo, self.bar)
671 tarinfo = self.tar.gettarinfo(self.bar)
672 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
673 "dereferencing hardlink failed")
674
Neal Norwitza4f651a2004-07-20 22:07:44 +0000675
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000676# Gzip TestCases
677class ReadTestGzip(ReadTest):
678 comp = "gz"
679class ReadStreamTestGzip(ReadStreamTest):
680 comp = "gz"
681class WriteTestGzip(WriteTest):
682 comp = "gz"
683class WriteStreamTestGzip(WriteStreamTest):
684 comp = "gz"
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000685class ReadDetectTestGzip(ReadDetectTest):
686 comp = "gz"
687class ReadDetectFileobjTestGzip(ReadDetectFileobjTest):
688 comp = "gz"
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000689class ReadAsteriskTestGzip(ReadAsteriskTest):
690 comp = "gz"
691class ReadStreamAsteriskTestGzip(ReadStreamAsteriskTest):
692 comp = "gz"
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000693class ReadFileobjTestGzip(ReadFileobjTest):
694 comp = "gz"
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000695
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +0000696# Filemode test cases
697
698class FileModeTest(unittest.TestCase):
699 def test_modes(self):
700 self.assertEqual(tarfile.filemode(0755), '-rwxr-xr-x')
701 self.assertEqual(tarfile.filemode(07111), '---s--s--t')
702
Lars Gustäbelf9a2c632006-12-27 10:36:58 +0000703class OpenFileobjTest(BaseTest):
Lars Gustäbelf9a2c632006-12-27 10:36:58 +0000704
705 def test_opener(self):
Lars Gustäbel9319e432007-04-20 20:10:59 +0000706 # Test for SF bug #1496501.
Lars Gustäbelf9a2c632006-12-27 10:36:58 +0000707 fobj = StringIO.StringIO("foo\n")
708 try:
Lars Gustäbel9319e432007-04-20 20:10:59 +0000709 tarfile.open("", mode="r", fileobj=fobj)
Lars Gustäbelf9a2c632006-12-27 10:36:58 +0000710 except tarfile.ReadError:
711 self.assertEqual(fobj.tell(), 0, "fileobj's position has moved")
Tim Peters8ceefc52004-10-25 03:19:41 +0000712
Lars Gustäbela9bad982007-08-28 12:33:15 +0000713 def test_no_name_argument(self):
714 fobj = open(testtar, "rb")
715 tar = tarfile.open(fileobj=fobj, mode="r")
716 self.assertEqual(tar.name, os.path.abspath(fobj.name))
717
718 def test_no_name_attribute(self):
719 data = open(testtar, "rb").read()
720 fobj = StringIO.StringIO(data)
721 self.assertRaises(AttributeError, getattr, fobj, "name")
722 tar = tarfile.open(fileobj=fobj, mode="r")
723 self.assertEqual(tar.name, None)
724
725 def test_empty_name_attribute(self):
726 data = open(testtar, "rb").read()
727 fobj = StringIO.StringIO(data)
728 fobj.name = ""
729 tar = tarfile.open(fileobj=fobj, mode="r")
730 self.assertEqual(tar.name, None)
731
Lars Gustäbel9319e432007-04-20 20:10:59 +0000732
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000733if bz2:
734 # Bzip2 TestCases
735 class ReadTestBzip2(ReadTestGzip):
736 comp = "bz2"
737 class ReadStreamTestBzip2(ReadStreamTestGzip):
738 comp = "bz2"
739 class WriteTestBzip2(WriteTest):
740 comp = "bz2"
741 class WriteStreamTestBzip2(WriteStreamTestGzip):
742 comp = "bz2"
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000743 class ReadDetectTestBzip2(ReadDetectTest):
744 comp = "bz2"
745 class ReadDetectFileobjTestBzip2(ReadDetectFileobjTest):
746 comp = "bz2"
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000747 class ReadAsteriskTestBzip2(ReadAsteriskTest):
748 comp = "bz2"
749 class ReadStreamAsteriskTestBzip2(ReadStreamAsteriskTest):
750 comp = "bz2"
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000751 class ReadFileobjTestBzip2(ReadFileobjTest):
752 comp = "bz2"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000753
754# If importing gzip failed, discard the Gzip TestCases.
755if not gzip:
756 del ReadTestGzip
757 del ReadStreamTestGzip
758 del WriteTestGzip
759 del WriteStreamTestGzip
760
Neal Norwitz996acf12003-02-17 14:51:41 +0000761def test_main():
Tim Peters02494762006-05-26 14:02:05 +0000762 # Create archive.
763 f = open(tarname(), "rb")
764 fguts = f.read()
765 f.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000766 if gzip:
767 # create testtar.tar.gz
Tim Peters02494762006-05-26 14:02:05 +0000768 tar = gzip.open(tarname("gz"), "wb")
769 tar.write(fguts)
770 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000771 if bz2:
772 # create testtar.tar.bz2
Tim Peters02494762006-05-26 14:02:05 +0000773 tar = bz2.BZ2File(tarname("bz2"), "wb")
774 tar.write(fguts)
775 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000776
Walter Dörwald21d3a322003-05-01 17:45:56 +0000777 tests = [
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +0000778 FileModeTest,
Lars Gustäbelf9a2c632006-12-27 10:36:58 +0000779 OpenFileobjTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000780 ReadTest,
781 ReadStreamTest,
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000782 ReadDetectTest,
783 ReadDetectFileobjTest,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000784 ReadAsteriskTest,
785 ReadStreamAsteriskTest,
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000786 ReadFileobjTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000787 WriteTest,
Georg Brandlee23f4b2006-10-24 16:54:23 +0000788 Write100Test,
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000789 WriteSize0Test,
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000790 WriteStreamTest,
791 WriteGNULongTest,
Georg Brandl38c6a222006-05-10 16:26:03 +0000792 ReadGNULongTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000793 ]
794
Neal Norwitza4f651a2004-07-20 22:07:44 +0000795 if hasattr(os, "link"):
796 tests.append(ExtractHardlinkTest)
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000797 tests.append(CreateHardlinkTest)
Neal Norwitza4f651a2004-07-20 22:07:44 +0000798
Walter Dörwald21d3a322003-05-01 17:45:56 +0000799 if gzip:
800 tests.extend([
801 ReadTestGzip, ReadStreamTestGzip,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000802 WriteTestGzip, WriteStreamTestGzip,
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000803 ReadDetectTestGzip, ReadDetectFileobjTestGzip,
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000804 ReadAsteriskTestGzip, ReadStreamAsteriskTestGzip,
805 ReadFileobjTestGzip
Walter Dörwald21d3a322003-05-01 17:45:56 +0000806 ])
807
808 if bz2:
809 tests.extend([
810 ReadTestBzip2, ReadStreamTestBzip2,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000811 WriteTestBzip2, WriteStreamTestBzip2,
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000812 ReadDetectTestBzip2, ReadDetectFileobjTestBzip2,
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000813 ReadAsteriskTestBzip2, ReadStreamAsteriskTestBzip2,
814 ReadFileobjTestBzip2
Walter Dörwald21d3a322003-05-01 17:45:56 +0000815 ])
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000816 try:
Walter Dörwald21d3a322003-05-01 17:45:56 +0000817 test_support.run_unittest(*tests)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000818 finally:
819 if gzip:
820 os.remove(tarname("gz"))
821 if bz2:
Tim Peters4e306172006-05-27 14:13:13 +0000822 os.remove(tarname("bz2"))
Brett Cannon455ea532003-06-12 08:01:06 +0000823 if os.path.exists(dirname()):
824 shutil.rmtree(dirname())
825 if os.path.exists(tmpname()):
826 os.remove(tmpname())
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000827
Neal Norwitz996acf12003-02-17 14:51:41 +0000828if __name__ == "__main__":
829 test_main()