blob: dc2803895d708d2c6b623e8652fc06b99ea18b6f [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
Georg Brandl38c6a222006-05-10 16:26:03 +000029membercount = 12
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äbeld2201442007-04-20 14:49:02 +0000228
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000229class ReadStreamTest(ReadTest):
230 sep = "|"
231
232 def test(self):
233 """Test member extraction, and for StreamError when
234 seeking backwards.
235 """
236 ReadTest.test(self)
237 tarinfo = self.tar.getmembers()[0]
238 f = self.tar.extractfile(tarinfo)
239 self.assertRaises(tarfile.StreamError, f.read)
240
241 def test_stream(self):
242 """Compare the normal tar and the stream tar.
243 """
244 stream = self.tar
245 tar = tarfile.open(tarname(), 'r')
246
247 while 1:
248 t1 = tar.next()
249 t2 = stream.next()
250 if t1 is None:
251 break
252 self.assert_(t2 is not None, "stream.next() failed.")
253
254 if t2.islnk() or t2.issym():
255 self.assertRaises(tarfile.StreamError, stream.extractfile, t2)
256 continue
257 v1 = tar.extractfile(t1)
258 v2 = stream.extractfile(t2)
259 if v1 is None:
260 continue
261 self.assert_(v2 is not None, "stream.extractfile() failed")
262 self.assert_(v1.read() == v2.read(), "stream extraction failed")
263
Tim Peters02494762006-05-26 14:02:05 +0000264 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000265 stream.close()
266
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000267class ReadDetectTest(ReadTest):
268
269 def setUp(self):
270 self.tar = tarfile.open(tarname(self.comp), self.mode)
271
272class ReadDetectFileobjTest(ReadTest):
273
274 def setUp(self):
275 name = tarname(self.comp)
Tim Peters12087ba2006-05-15 20:44:10 +0000276 self.tar = tarfile.open(name, mode=self.mode,
277 fileobj=open(name, "rb"))
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000278
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000279class ReadAsteriskTest(ReadTest):
280
281 def setUp(self):
282 mode = self.mode + self.sep + "*"
283 self.tar = tarfile.open(tarname(self.comp), mode)
284
285class ReadStreamAsteriskTest(ReadStreamTest):
286
287 def setUp(self):
288 mode = self.mode + self.sep + "*"
289 self.tar = tarfile.open(tarname(self.comp), mode)
290
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000291class ReadFileobjTest(BaseTest):
292
293 def test_fileobj_with_offset(self):
294 # Skip the first member and store values from the second member
295 # of the testtar.
296 self.tar.next()
297 t = self.tar.next()
298 name = t.name
299 offset = t.offset
300 data = self.tar.extractfile(t).read()
301 self.tar.close()
302
303 # Open the testtar and seek to the offset of the second member.
304 if self.comp == "gz":
305 _open = gzip.GzipFile
306 elif self.comp == "bz2":
307 _open = bz2.BZ2File
308 else:
309 _open = open
310 fobj = _open(tarname(self.comp), "rb")
311 fobj.seek(offset)
312
313 # Test if the tarfile starts with the second member.
314 self.tar = tarfile.open(tarname(self.comp), "r:", fileobj=fobj)
315 t = self.tar.next()
316 self.assertEqual(t.name, name)
317 # Read to the end of fileobj and test if seeking back to the
318 # beginning works.
319 self.tar.getmembers()
320 self.assertEqual(self.tar.extractfile(t).read(), data,
321 "seek back did not work")
322
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000323class WriteTest(BaseTest):
324 mode = 'w'
325
326 def setUp(self):
327 mode = self.mode + self.sep + self.comp
328 self.src = tarfile.open(tarname(self.comp), 'r')
Martin v. Löwisc234a522004-08-22 21:28:33 +0000329 self.dstname = tmpname()
330 self.dst = tarfile.open(self.dstname, mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000331
332 def tearDown(self):
333 self.src.close()
334 self.dst.close()
335
336 def test_posix(self):
337 self.dst.posix = 1
338 self._test()
339
340 def test_nonposix(self):
341 self.dst.posix = 0
342 self._test()
343
Martin v. Löwisc234a522004-08-22 21:28:33 +0000344 def test_small(self):
345 self.dst.add(os.path.join(os.path.dirname(__file__),"cfgparser.1"))
346 self.dst.close()
347 self.assertNotEqual(os.stat(self.dstname).st_size, 0)
348
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000349 def _test(self):
350 for tarinfo in self.src:
351 if not tarinfo.isreg():
352 continue
353 f = self.src.extractfile(tarinfo)
Georg Brandl38c6a222006-05-10 16:26:03 +0000354 if self.dst.posix and len(tarinfo.name) > tarfile.LENGTH_NAME and "/" not in tarinfo.name:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000355 self.assertRaises(ValueError, self.dst.addfile,
356 tarinfo, f)
357 else:
358 self.dst.addfile(tarinfo, f)
359
Lars Gustäbel12e087a2006-12-23 18:13:57 +0000360 def test_add_self(self):
361 dstname = os.path.abspath(self.dstname)
362
363 self.assertEqual(self.dst.name, dstname, "archive name must be absolute")
364
365 self.dst.add(dstname)
366 self.assertEqual(self.dst.getnames(), [], "added the archive to itself")
367
368 cwd = os.getcwd()
369 os.chdir(dirname())
370 self.dst.add(dstname)
371 os.chdir(cwd)
372 self.assertEqual(self.dst.getnames(), [], "added the archive to itself")
373
Georg Brandlee23f4b2006-10-24 16:54:23 +0000374
375class Write100Test(BaseTest):
376 # The name field in a tar header stores strings of at most 100 chars.
377 # If a string is shorter than 100 chars it has to be padded with '\0',
378 # which implies that a string of exactly 100 chars is stored without
379 # a trailing '\0'.
380
381 def setUp(self):
382 self.name = "01234567890123456789012345678901234567890123456789"
383 self.name += "01234567890123456789012345678901234567890123456789"
384
385 self.tar = tarfile.open(tmpname(), "w")
386 t = tarfile.TarInfo(self.name)
387 self.tar.addfile(t)
388 self.tar.close()
389
390 self.tar = tarfile.open(tmpname())
391
392 def tearDown(self):
393 self.tar.close()
394
395 def test(self):
396 self.assertEqual(self.tar.getnames()[0], self.name,
397 "failed to store 100 char filename")
398
399
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000400class WriteSize0Test(BaseTest):
401 mode = 'w'
402
403 def setUp(self):
404 self.tmpdir = dirname()
405 self.dstname = tmpname()
406 self.dst = tarfile.open(self.dstname, "w")
407
408 def tearDown(self):
409 self.dst.close()
410
411 def test_file(self):
412 path = os.path.join(self.tmpdir, "file")
Tim Peters02494762006-05-26 14:02:05 +0000413 f = open(path, "w")
414 f.close()
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000415 tarinfo = self.dst.gettarinfo(path)
416 self.assertEqual(tarinfo.size, 0)
Tim Peters02494762006-05-26 14:02:05 +0000417 f = open(path, "w")
418 f.write("aaa")
419 f.close()
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000420 tarinfo = self.dst.gettarinfo(path)
421 self.assertEqual(tarinfo.size, 3)
422
423 def test_directory(self):
424 path = os.path.join(self.tmpdir, "directory")
Tim Peters4ccc0b72006-05-15 21:32:25 +0000425 if os.path.exists(path):
426 # This shouldn't be necessary, but is <wink> if a previous
427 # run was killed in mid-stream.
428 shutil.rmtree(path)
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000429 os.mkdir(path)
430 tarinfo = self.dst.gettarinfo(path)
431 self.assertEqual(tarinfo.size, 0)
432
433 def test_symlink(self):
434 if hasattr(os, "symlink"):
435 path = os.path.join(self.tmpdir, "symlink")
436 os.symlink("link_target", path)
437 tarinfo = self.dst.gettarinfo(path)
438 self.assertEqual(tarinfo.size, 0)
439
440
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000441class WriteStreamTest(WriteTest):
442 sep = '|'
443
Neal Norwitz7443b802006-08-21 18:43:51 +0000444 def test_padding(self):
445 self.dst.close()
446
447 if self.comp == "gz":
448 f = gzip.GzipFile(self.dstname)
449 s = f.read()
450 f.close()
451 elif self.comp == "bz2":
452 f = bz2.BZ2Decompressor()
453 s = file(self.dstname).read()
454 s = f.decompress(s)
455 self.assertEqual(len(f.unused_data), 0, "trailing data")
456 else:
457 f = file(self.dstname)
458 s = f.read()
459 f.close()
460
461 self.assertEqual(s.count("\0"), tarfile.RECORDSIZE,
462 "incorrect zero padding")
463
464
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000465class WriteGNULongTest(unittest.TestCase):
466 """This testcase checks for correct creation of GNU Longname
467 and Longlink extensions.
468
469 It creates a tarfile and adds empty members with either
470 long names, long linknames or both and compares the size
471 of the tarfile with the expected size.
472
473 It checks for SF bug #812325 in TarFile._create_gnulong().
474
475 While I was writing this testcase, I noticed a second bug
476 in the same method:
477 Long{names,links} weren't null-terminated which lead to
478 bad tarfiles when their length was a multiple of 512. This
479 is tested as well.
480 """
481
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000482 def _length(self, s):
483 blocks, remainder = divmod(len(s) + 1, 512)
484 if remainder:
485 blocks += 1
486 return blocks * 512
487
488 def _calc_size(self, name, link=None):
489 # initial tar header
490 count = 512
491
492 if len(name) > tarfile.LENGTH_NAME:
493 # gnu longname extended header + longname
494 count += 512
495 count += self._length(name)
496
497 if link is not None and len(link) > tarfile.LENGTH_LINK:
498 # gnu longlink extended header + longlink
499 count += 512
500 count += self._length(link)
501
502 return count
503
504 def _test(self, name, link=None):
505 tarinfo = tarfile.TarInfo(name)
506 if link:
507 tarinfo.linkname = link
508 tarinfo.type = tarfile.LNKTYPE
509
Georg Brandl25f58f62006-12-06 22:21:23 +0000510 tar = tarfile.open(tmpname(), "w")
511 tar.posix = False
512 tar.addfile(tarinfo)
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000513
514 v1 = self._calc_size(name, link)
Georg Brandl25f58f62006-12-06 22:21:23 +0000515 v2 = tar.offset
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000516 self.assertEqual(v1, v2, "GNU longname/longlink creation failed")
517
Georg Brandl25f58f62006-12-06 22:21:23 +0000518 tar.close()
519
520 tar = tarfile.open(tmpname())
521 member = tar.next()
522 self.failIf(member is None, "unable to read longname member")
523 self.assert_(tarinfo.name == member.name and \
524 tarinfo.linkname == member.linkname, \
525 "unable to read longname member")
526
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000527 def test_longname_1023(self):
528 self._test(("longnam/" * 127) + "longnam")
529
530 def test_longname_1024(self):
531 self._test(("longnam/" * 127) + "longname")
532
533 def test_longname_1025(self):
534 self._test(("longnam/" * 127) + "longname_")
535
536 def test_longlink_1023(self):
537 self._test("name", ("longlnk/" * 127) + "longlnk")
538
539 def test_longlink_1024(self):
540 self._test("name", ("longlnk/" * 127) + "longlink")
541
542 def test_longlink_1025(self):
543 self._test("name", ("longlnk/" * 127) + "longlink_")
544
545 def test_longnamelink_1023(self):
546 self._test(("longnam/" * 127) + "longnam",
547 ("longlnk/" * 127) + "longlnk")
548
549 def test_longnamelink_1024(self):
550 self._test(("longnam/" * 127) + "longname",
551 ("longlnk/" * 127) + "longlink")
552
553 def test_longnamelink_1025(self):
554 self._test(("longnam/" * 127) + "longname_",
555 ("longlnk/" * 127) + "longlink_")
556
Georg Brandl38c6a222006-05-10 16:26:03 +0000557class ReadGNULongTest(unittest.TestCase):
558
559 def setUp(self):
560 self.tar = tarfile.open(tarname())
561
562 def tearDown(self):
563 self.tar.close()
564
565 def test_1471427(self):
566 """Test reading of longname (bug #1471427).
567 """
568 name = "test/" * 20 + "0-REGTYPE"
569 try:
570 tarinfo = self.tar.getmember(name)
571 except KeyError:
572 tarinfo = None
573 self.assert_(tarinfo is not None, "longname not found")
574 self.assert_(tarinfo.type != tarfile.DIRTYPE, "read longname as dirtype")
575
576 def test_read_name(self):
577 name = ("0-LONGNAME-" * 10)[:101]
578 try:
579 tarinfo = self.tar.getmember(name)
580 except KeyError:
581 tarinfo = None
582 self.assert_(tarinfo is not None, "longname not found")
583
584 def test_read_link(self):
585 link = ("1-LONGLINK-" * 10)[:101]
586 name = ("0-LONGNAME-" * 10)[:101]
587 try:
588 tarinfo = self.tar.getmember(link)
589 except KeyError:
590 tarinfo = None
591 self.assert_(tarinfo is not None, "longlink not found")
592 self.assert_(tarinfo.linkname == name, "linkname wrong")
593
594 def test_truncated_longname(self):
Tim Peters02494762006-05-26 14:02:05 +0000595 f = open(tarname())
596 fobj = StringIO.StringIO(f.read(1024))
597 f.close()
Georg Brandl38c6a222006-05-10 16:26:03 +0000598 tar = tarfile.open(name="foo.tar", fileobj=fobj)
599 self.assert_(len(tar.getmembers()) == 0, "")
Tim Peters02494762006-05-26 14:02:05 +0000600 tar.close()
Georg Brandl38c6a222006-05-10 16:26:03 +0000601
602
Neal Norwitza4f651a2004-07-20 22:07:44 +0000603class ExtractHardlinkTest(BaseTest):
604
605 def test_hardlink(self):
606 """Test hardlink extraction (bug #857297)
607 """
608 # Prevent errors from being caught
609 self.tar.errorlevel = 1
610
611 self.tar.extract("0-REGTYPE", dirname())
612 try:
613 # Extract 1-LNKTYPE which is a hardlink to 0-REGTYPE
614 self.tar.extract("1-LNKTYPE", dirname())
615 except EnvironmentError, e:
616 import errno
617 if e.errno == errno.ENOENT:
618 self.fail("hardlink not extracted properly")
619
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000620class CreateHardlinkTest(BaseTest):
621 """Test the creation of LNKTYPE (hardlink) members in an archive.
622 In this respect tarfile.py mimics the behaviour of GNU tar: If
623 a file has a st_nlink > 1, it will be added a REGTYPE member
624 only the first time.
625 """
626
627 def setUp(self):
628 self.tar = tarfile.open(tmpname(), "w")
629
630 self.foo = os.path.join(dirname(), "foo")
631 self.bar = os.path.join(dirname(), "bar")
632
633 if os.path.exists(self.foo):
634 os.remove(self.foo)
635 if os.path.exists(self.bar):
636 os.remove(self.bar)
637
Tim Peters02494762006-05-26 14:02:05 +0000638 f = open(self.foo, "w")
639 f.write("foo")
640 f.close()
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000641 self.tar.add(self.foo)
642
643 def test_add_twice(self):
644 # If st_nlink == 1 then the same file will be added as
645 # REGTYPE every time.
646 tarinfo = self.tar.gettarinfo(self.foo)
647 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
648 "add file as regular failed")
649
650 def test_add_hardlink(self):
651 # If st_nlink > 1 then the same file will be added as
652 # LNKTYPE.
653 os.link(self.foo, self.bar)
654 tarinfo = self.tar.gettarinfo(self.foo)
655 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
656 "add file as hardlink failed")
657
658 tarinfo = self.tar.gettarinfo(self.bar)
659 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
660 "add file as hardlink failed")
661
662 def test_dereference_hardlink(self):
663 self.tar.dereference = True
664 os.link(self.foo, self.bar)
665 tarinfo = self.tar.gettarinfo(self.bar)
666 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
667 "dereferencing hardlink failed")
668
Neal Norwitza4f651a2004-07-20 22:07:44 +0000669
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000670# Gzip TestCases
671class ReadTestGzip(ReadTest):
672 comp = "gz"
673class ReadStreamTestGzip(ReadStreamTest):
674 comp = "gz"
675class WriteTestGzip(WriteTest):
676 comp = "gz"
677class WriteStreamTestGzip(WriteStreamTest):
678 comp = "gz"
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000679class ReadDetectTestGzip(ReadDetectTest):
680 comp = "gz"
681class ReadDetectFileobjTestGzip(ReadDetectFileobjTest):
682 comp = "gz"
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000683class ReadAsteriskTestGzip(ReadAsteriskTest):
684 comp = "gz"
685class ReadStreamAsteriskTestGzip(ReadStreamAsteriskTest):
686 comp = "gz"
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000687class ReadFileobjTestGzip(ReadFileobjTest):
688 comp = "gz"
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000689
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +0000690# Filemode test cases
691
692class FileModeTest(unittest.TestCase):
693 def test_modes(self):
694 self.assertEqual(tarfile.filemode(0755), '-rwxr-xr-x')
695 self.assertEqual(tarfile.filemode(07111), '---s--s--t')
696
Lars Gustäbelf9a2c632006-12-27 10:36:58 +0000697class OpenFileobjTest(BaseTest):
Lars Gustäbelf9a2c632006-12-27 10:36:58 +0000698
699 def test_opener(self):
Lars Gustäbel9319e432007-04-20 20:10:59 +0000700 # Test for SF bug #1496501.
Lars Gustäbelf9a2c632006-12-27 10:36:58 +0000701 fobj = StringIO.StringIO("foo\n")
702 try:
Lars Gustäbel9319e432007-04-20 20:10:59 +0000703 tarfile.open("", mode="r", fileobj=fobj)
Lars Gustäbelf9a2c632006-12-27 10:36:58 +0000704 except tarfile.ReadError:
705 self.assertEqual(fobj.tell(), 0, "fileobj's position has moved")
Tim Peters8ceefc52004-10-25 03:19:41 +0000706
Lars Gustäbela9bad982007-08-28 12:33:15 +0000707 def test_no_name_argument(self):
708 fobj = open(testtar, "rb")
709 tar = tarfile.open(fileobj=fobj, mode="r")
710 self.assertEqual(tar.name, os.path.abspath(fobj.name))
711
712 def test_no_name_attribute(self):
713 data = open(testtar, "rb").read()
714 fobj = StringIO.StringIO(data)
715 self.assertRaises(AttributeError, getattr, fobj, "name")
716 tar = tarfile.open(fileobj=fobj, mode="r")
717 self.assertEqual(tar.name, None)
718
719 def test_empty_name_attribute(self):
720 data = open(testtar, "rb").read()
721 fobj = StringIO.StringIO(data)
722 fobj.name = ""
723 tar = tarfile.open(fileobj=fobj, mode="r")
724 self.assertEqual(tar.name, None)
725
Lars Gustäbel9319e432007-04-20 20:10:59 +0000726
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000727if bz2:
728 # Bzip2 TestCases
729 class ReadTestBzip2(ReadTestGzip):
730 comp = "bz2"
731 class ReadStreamTestBzip2(ReadStreamTestGzip):
732 comp = "bz2"
733 class WriteTestBzip2(WriteTest):
734 comp = "bz2"
735 class WriteStreamTestBzip2(WriteStreamTestGzip):
736 comp = "bz2"
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000737 class ReadDetectTestBzip2(ReadDetectTest):
738 comp = "bz2"
739 class ReadDetectFileobjTestBzip2(ReadDetectFileobjTest):
740 comp = "bz2"
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000741 class ReadAsteriskTestBzip2(ReadAsteriskTest):
742 comp = "bz2"
743 class ReadStreamAsteriskTestBzip2(ReadStreamAsteriskTest):
744 comp = "bz2"
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000745 class ReadFileobjTestBzip2(ReadFileobjTest):
746 comp = "bz2"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000747
748# If importing gzip failed, discard the Gzip TestCases.
749if not gzip:
750 del ReadTestGzip
751 del ReadStreamTestGzip
752 del WriteTestGzip
753 del WriteStreamTestGzip
754
Neal Norwitz996acf12003-02-17 14:51:41 +0000755def test_main():
Tim Peters02494762006-05-26 14:02:05 +0000756 # Create archive.
757 f = open(tarname(), "rb")
758 fguts = f.read()
759 f.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000760 if gzip:
761 # create testtar.tar.gz
Tim Peters02494762006-05-26 14:02:05 +0000762 tar = gzip.open(tarname("gz"), "wb")
763 tar.write(fguts)
764 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000765 if bz2:
766 # create testtar.tar.bz2
Tim Peters02494762006-05-26 14:02:05 +0000767 tar = bz2.BZ2File(tarname("bz2"), "wb")
768 tar.write(fguts)
769 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000770
Walter Dörwald21d3a322003-05-01 17:45:56 +0000771 tests = [
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +0000772 FileModeTest,
Lars Gustäbelf9a2c632006-12-27 10:36:58 +0000773 OpenFileobjTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000774 ReadTest,
775 ReadStreamTest,
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000776 ReadDetectTest,
777 ReadDetectFileobjTest,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000778 ReadAsteriskTest,
779 ReadStreamAsteriskTest,
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000780 ReadFileobjTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000781 WriteTest,
Georg Brandlee23f4b2006-10-24 16:54:23 +0000782 Write100Test,
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000783 WriteSize0Test,
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000784 WriteStreamTest,
785 WriteGNULongTest,
Georg Brandl38c6a222006-05-10 16:26:03 +0000786 ReadGNULongTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000787 ]
788
Neal Norwitza4f651a2004-07-20 22:07:44 +0000789 if hasattr(os, "link"):
790 tests.append(ExtractHardlinkTest)
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000791 tests.append(CreateHardlinkTest)
Neal Norwitza4f651a2004-07-20 22:07:44 +0000792
Walter Dörwald21d3a322003-05-01 17:45:56 +0000793 if gzip:
794 tests.extend([
795 ReadTestGzip, ReadStreamTestGzip,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000796 WriteTestGzip, WriteStreamTestGzip,
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000797 ReadDetectTestGzip, ReadDetectFileobjTestGzip,
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000798 ReadAsteriskTestGzip, ReadStreamAsteriskTestGzip,
799 ReadFileobjTestGzip
Walter Dörwald21d3a322003-05-01 17:45:56 +0000800 ])
801
802 if bz2:
803 tests.extend([
804 ReadTestBzip2, ReadStreamTestBzip2,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000805 WriteTestBzip2, WriteStreamTestBzip2,
Georg Brandl49c8f4c2006-05-15 19:30:35 +0000806 ReadDetectTestBzip2, ReadDetectFileobjTestBzip2,
Lars Gustäbel7cc9c8b2007-12-01 21:06:06 +0000807 ReadAsteriskTestBzip2, ReadStreamAsteriskTestBzip2,
808 ReadFileobjTestBzip2
Walter Dörwald21d3a322003-05-01 17:45:56 +0000809 ])
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000810 try:
Walter Dörwald21d3a322003-05-01 17:45:56 +0000811 test_support.run_unittest(*tests)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000812 finally:
813 if gzip:
814 os.remove(tarname("gz"))
815 if bz2:
Tim Peters4e306172006-05-27 14:13:13 +0000816 os.remove(tarname("bz2"))
Brett Cannon455ea532003-06-12 08:01:06 +0000817 if os.path.exists(dirname()):
818 shutil.rmtree(dirname())
819 if os.path.exists(tmpname()):
820 os.remove(tmpname())
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000821
Neal Norwitz996acf12003-02-17 14:51:41 +0000822if __name__ == "__main__":
823 test_main()