blob: 146bbb717b5013504436bc2a108218efdb2e2d5b [file] [log] [blame]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001#!/usr/bin/env python
2# -*- coding: iso-8859-1 -*-
3#-------------------------------------------------------------------
4# tarfile.py
5#-------------------------------------------------------------------
6# Copyright (C) 2002 Lars Gustäbel <lars@gustaebel.de>
7# All rights reserved.
8#
9# Permission is hereby granted, free of charge, to any person
10# obtaining a copy of this software and associated documentation
11# files (the "Software"), to deal in the Software without
12# restriction, including without limitation the rights to use,
13# copy, modify, merge, publish, distribute, sublicense, and/or sell
14# copies of the Software, and to permit persons to whom the
15# Software is furnished to do so, subject to the following
16# conditions:
17#
18# The above copyright notice and this permission notice shall be
19# included in all copies or substantial portions of the Software.
20#
21# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28# OTHER DEALINGS IN THE SOFTWARE.
29#
30"""Read from and write to tar format archives.
31"""
32
33__version__ = "$Revision$"
34# $Source$
35
Thomas Wouters477c8d52006-05-27 19:21:47 +000036version = "0.8.0"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000037__author__ = "Lars Gustäbel (lars@gustaebel.de)"
38__date__ = "$Date$"
39__cvsid__ = "$Id$"
40__credits__ = "Gustavo Niemeyer, Niels Gustäbel, Richard Townsend."
41
42#---------
43# Imports
44#---------
45import sys
46import os
47import shutil
48import stat
49import errno
50import time
51import struct
Thomas Wouters89f507f2006-12-13 04:49:30 +000052import copy
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000053
Jack Jansencfc49022003-03-07 13:37:32 +000054if sys.platform == 'mac':
55 # This module needs work for MacOS9, especially in the area of pathname
56 # handling. In many places it is assumed a simple substitution of / by the
57 # local os.path.sep is good enough to convert pathnames, but this does not
58 # work with the mac rooted:path:name versus :nonrooted:path:name syntax
59 raise ImportError, "tarfile does not work for platform==mac"
60
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000061try:
62 import grp, pwd
63except ImportError:
64 grp = pwd = None
65
66# from tarfile import *
67__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"]
68
Guido van Rossum8f78fe92006-08-24 04:03:53 +000069from __builtin__ import open as _open # Since 'open' is TarFile.open
70
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000071#---------------------------------------------------------
72# tar constants
73#---------------------------------------------------------
74NUL = "\0" # the null character
75BLOCKSIZE = 512 # length of processing blocks
76RECORDSIZE = BLOCKSIZE * 20 # length of records
77MAGIC = "ustar" # magic tar string
78VERSION = "00" # version number
79
80LENGTH_NAME = 100 # maximum length of a filename
81LENGTH_LINK = 100 # maximum length of a linkname
82LENGTH_PREFIX = 155 # maximum length of the prefix field
Guido van Rossume2a383d2007-01-15 16:59:06 +000083MAXSIZE_MEMBER = 077777777777 # maximum size of a file (11 octal digits)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000084
85REGTYPE = "0" # regular file
86AREGTYPE = "\0" # regular file
87LNKTYPE = "1" # link (inside tarfile)
88SYMTYPE = "2" # symbolic link
89CHRTYPE = "3" # character special device
90BLKTYPE = "4" # block special device
91DIRTYPE = "5" # directory
92FIFOTYPE = "6" # fifo special device
93CONTTYPE = "7" # contiguous file
94
95GNUTYPE_LONGNAME = "L" # GNU tar extension for longnames
96GNUTYPE_LONGLINK = "K" # GNU tar extension for longlink
97GNUTYPE_SPARSE = "S" # GNU tar extension for sparse file
98
99#---------------------------------------------------------
100# tarfile constants
101#---------------------------------------------------------
102SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, # file types that tarfile
103 SYMTYPE, DIRTYPE, FIFOTYPE, # can cope with.
104 CONTTYPE, CHRTYPE, BLKTYPE,
105 GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
106 GNUTYPE_SPARSE)
107
108REGULAR_TYPES = (REGTYPE, AREGTYPE, # file types that somehow
109 CONTTYPE, GNUTYPE_SPARSE) # represent regular files
110
111#---------------------------------------------------------
112# Bits used in the mode field, values in octal.
113#---------------------------------------------------------
114S_IFLNK = 0120000 # symbolic link
115S_IFREG = 0100000 # regular file
116S_IFBLK = 0060000 # block device
117S_IFDIR = 0040000 # directory
118S_IFCHR = 0020000 # character device
119S_IFIFO = 0010000 # fifo
120
121TSUID = 04000 # set UID on execution
122TSGID = 02000 # set GID on execution
123TSVTX = 01000 # reserved
124
125TUREAD = 0400 # read by owner
126TUWRITE = 0200 # write by owner
127TUEXEC = 0100 # execute/search by owner
128TGREAD = 0040 # read by group
129TGWRITE = 0020 # write by group
130TGEXEC = 0010 # execute/search by group
131TOREAD = 0004 # read by other
132TOWRITE = 0002 # write by other
133TOEXEC = 0001 # execute/search by other
134
135#---------------------------------------------------------
136# Some useful functions
137#---------------------------------------------------------
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000138
Thomas Wouters477c8d52006-05-27 19:21:47 +0000139def stn(s, length):
140 """Convert a python string to a null-terminated string buffer.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000141 """
Thomas Wouters89f507f2006-12-13 04:49:30 +0000142 return s[:length] + (length - len(s)) * NUL
Thomas Wouters477c8d52006-05-27 19:21:47 +0000143
144def nti(s):
145 """Convert a number field to a python number.
146 """
147 # There are two possible encodings for a number field, see
148 # itn() below.
149 if s[0] != chr(0200):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000150 try:
151 n = int(s.rstrip(NUL + " ") or "0", 8)
152 except ValueError:
153 raise HeaderError("invalid header")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000154 else:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000155 n = 0
Thomas Wouters477c8d52006-05-27 19:21:47 +0000156 for i in xrange(len(s) - 1):
157 n <<= 8
158 n += ord(s[i + 1])
159 return n
160
161def itn(n, digits=8, posix=False):
162 """Convert a python number to a number field.
163 """
164 # POSIX 1003.1-1988 requires numbers to be encoded as a string of
165 # octal digits followed by a null-byte, this allows values up to
166 # (8**(digits-1))-1. GNU tar allows storing numbers greater than
167 # that if necessary. A leading 0200 byte indicates this particular
168 # encoding, the following digits-1 bytes are a big-endian
169 # representation. This allows values up to (256**(digits-1))-1.
170 if 0 <= n < 8 ** (digits - 1):
171 s = "%0*o" % (digits - 1, n) + NUL
172 else:
173 if posix:
174 raise ValueError("overflow in number field")
175
176 if n < 0:
177 # XXX We mimic GNU tar's behaviour with negative numbers,
178 # this could raise OverflowError.
179 n = struct.unpack("L", struct.pack("l", n))[0]
180
181 s = ""
182 for i in xrange(digits - 1):
183 s = chr(n & 0377) + s
184 n >>= 8
185 s = chr(0200) + s
186 return s
187
188def calc_chksums(buf):
189 """Calculate the checksum for a member's header by summing up all
190 characters except for the chksum field which is treated as if
191 it was filled with spaces. According to the GNU tar sources,
192 some tars (Sun and NeXT) calculate chksum with signed char,
193 which will be different if there are chars in the buffer with
194 the high bit set. So we calculate two checksums, unsigned and
195 signed.
196 """
197 unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512]))
198 signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512]))
199 return unsigned_chksum, signed_chksum
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000200
201def copyfileobj(src, dst, length=None):
202 """Copy length bytes from fileobj src to fileobj dst.
203 If length is None, copy the entire content.
204 """
205 if length == 0:
206 return
207 if length is None:
208 shutil.copyfileobj(src, dst)
209 return
210
211 BUFSIZE = 16 * 1024
212 blocks, remainder = divmod(length, BUFSIZE)
213 for b in xrange(blocks):
214 buf = src.read(BUFSIZE)
215 if len(buf) < BUFSIZE:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000216 raise IOError("end of file reached")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000217 dst.write(buf)
218
219 if remainder != 0:
220 buf = src.read(remainder)
221 if len(buf) < remainder:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000222 raise IOError("end of file reached")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000223 dst.write(buf)
224 return
225
226filemode_table = (
Andrew M. Kuchling8bc462f2004-10-20 11:48:42 +0000227 ((S_IFLNK, "l"),
228 (S_IFREG, "-"),
229 (S_IFBLK, "b"),
230 (S_IFDIR, "d"),
231 (S_IFCHR, "c"),
232 (S_IFIFO, "p")),
233
234 ((TUREAD, "r"),),
235 ((TUWRITE, "w"),),
236 ((TUEXEC|TSUID, "s"),
237 (TSUID, "S"),
238 (TUEXEC, "x")),
239
240 ((TGREAD, "r"),),
241 ((TGWRITE, "w"),),
242 ((TGEXEC|TSGID, "s"),
243 (TSGID, "S"),
244 (TGEXEC, "x")),
245
246 ((TOREAD, "r"),),
247 ((TOWRITE, "w"),),
248 ((TOEXEC|TSVTX, "t"),
249 (TSVTX, "T"),
250 (TOEXEC, "x"))
251)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000252
253def filemode(mode):
254 """Convert a file's mode to a string of the form
255 -rwxrwxrwx.
256 Used by TarFile.list()
257 """
Andrew M. Kuchling8bc462f2004-10-20 11:48:42 +0000258 perm = []
259 for table in filemode_table:
260 for bit, char in table:
261 if mode & bit == bit:
262 perm.append(char)
263 break
264 else:
265 perm.append("-")
266 return "".join(perm)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000267
268if os.sep != "/":
269 normpath = lambda path: os.path.normpath(path).replace(os.sep, "/")
270else:
271 normpath = os.path.normpath
272
273class TarError(Exception):
274 """Base exception."""
275 pass
276class ExtractError(TarError):
277 """General exception for extract errors."""
278 pass
279class ReadError(TarError):
280 """Exception for unreadble tar archives."""
281 pass
282class CompressionError(TarError):
283 """Exception for unavailable compression methods."""
284 pass
285class StreamError(TarError):
286 """Exception for unsupported operations on stream-like TarFiles."""
287 pass
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000288class HeaderError(TarError):
289 """Exception for invalid headers."""
290 pass
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000291
292#---------------------------
293# internal stream interface
294#---------------------------
295class _LowLevelFile:
296 """Low-level file object. Supports reading and writing.
297 It is used instead of a regular file object for streaming
298 access.
299 """
300
301 def __init__(self, name, mode):
302 mode = {
303 "r": os.O_RDONLY,
304 "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
305 }[mode]
306 if hasattr(os, "O_BINARY"):
307 mode |= os.O_BINARY
308 self.fd = os.open(name, mode)
309
310 def close(self):
311 os.close(self.fd)
312
313 def read(self, size):
314 return os.read(self.fd, size)
315
316 def write(self, s):
317 os.write(self.fd, s)
318
319class _Stream:
320 """Class that serves as an adapter between TarFile and
321 a stream-like object. The stream-like object only
322 needs to have a read() or write() method and is accessed
323 blockwise. Use of gzip or bzip2 compression is possible.
324 A stream-like object could be for example: sys.stdin,
325 sys.stdout, a socket, a tape device etc.
326
327 _Stream is intended to be used only internally.
328 """
329
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000330 def __init__(self, name, mode, comptype, fileobj, bufsize):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000331 """Construct a _Stream object.
332 """
333 self._extfileobj = True
334 if fileobj is None:
335 fileobj = _LowLevelFile(name, mode)
336 self._extfileobj = False
337
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000338 if comptype == '*':
339 # Enable transparent compression detection for the
340 # stream interface
341 fileobj = _StreamProxy(fileobj)
342 comptype = fileobj.getcomptype()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000343
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000344 self.name = name or ""
345 self.mode = mode
346 self.comptype = comptype
347 self.fileobj = fileobj
348 self.bufsize = bufsize
349 self.buf = ""
Guido van Rossume2a383d2007-01-15 16:59:06 +0000350 self.pos = 0
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000351 self.closed = False
352
353 if comptype == "gz":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000354 try:
355 import zlib
356 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000357 raise CompressionError("zlib module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000358 self.zlib = zlib
359 self.crc = zlib.crc32("")
360 if mode == "r":
361 self._init_read_gz()
362 else:
363 self._init_write_gz()
364
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000365 if comptype == "bz2":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000366 try:
367 import bz2
368 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000369 raise CompressionError("bz2 module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000370 if mode == "r":
371 self.dbuf = ""
372 self.cmp = bz2.BZ2Decompressor()
373 else:
374 self.cmp = bz2.BZ2Compressor()
375
376 def __del__(self):
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000377 if hasattr(self, "closed") and not self.closed:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000378 self.close()
379
380 def _init_write_gz(self):
381 """Initialize for writing with gzip compression.
382 """
383 self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED,
384 -self.zlib.MAX_WBITS,
385 self.zlib.DEF_MEM_LEVEL,
386 0)
Guido van Rossume2a383d2007-01-15 16:59:06 +0000387 timestamp = struct.pack("<L", int(time.time()))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000388 self.__write("\037\213\010\010%s\002\377" % timestamp)
389 if self.name.endswith(".gz"):
390 self.name = self.name[:-3]
391 self.__write(self.name + NUL)
392
393 def write(self, s):
394 """Write string s to the stream.
395 """
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000396 if self.comptype == "gz":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000397 self.crc = self.zlib.crc32(s, self.crc)
398 self.pos += len(s)
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000399 if self.comptype != "tar":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000400 s = self.cmp.compress(s)
401 self.__write(s)
402
403 def __write(self, s):
404 """Write string s to the stream if a whole new block
405 is ready to be written.
406 """
407 self.buf += s
408 while len(self.buf) > self.bufsize:
409 self.fileobj.write(self.buf[:self.bufsize])
410 self.buf = self.buf[self.bufsize:]
411
412 def close(self):
413 """Close the _Stream object. No operation should be
414 done on it afterwards.
415 """
416 if self.closed:
417 return
418
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000419 if self.mode == "w" and self.comptype != "tar":
Martin v. Löwisc234a522004-08-22 21:28:33 +0000420 self.buf += self.cmp.flush()
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000421
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000422 if self.mode == "w" and self.buf:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000423 self.fileobj.write(self.buf)
424 self.buf = ""
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000425 if self.comptype == "gz":
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000426 # The native zlib crc is an unsigned 32-bit integer, but
427 # the Python wrapper implicitly casts that to a signed C
428 # long. So, on a 32-bit box self.crc may "look negative",
429 # while the same crc on a 64-bit box may "look positive".
430 # To avoid irksome warnings from the `struct` module, force
431 # it to look positive on all boxes.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000432 self.fileobj.write(struct.pack("<L", self.crc & 0xffffffff))
433 self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFF))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000434
435 if not self._extfileobj:
436 self.fileobj.close()
437
438 self.closed = True
439
440 def _init_read_gz(self):
441 """Initialize for reading a gzip compressed fileobj.
442 """
443 self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS)
444 self.dbuf = ""
445
446 # taken from gzip.GzipFile with some alterations
447 if self.__read(2) != "\037\213":
Thomas Wouters477c8d52006-05-27 19:21:47 +0000448 raise ReadError("not a gzip file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000449 if self.__read(1) != "\010":
Thomas Wouters477c8d52006-05-27 19:21:47 +0000450 raise CompressionError("unsupported compression method")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000451
452 flag = ord(self.__read(1))
453 self.__read(6)
454
455 if flag & 4:
456 xlen = ord(self.__read(1)) + 256 * ord(self.__read(1))
457 self.read(xlen)
458 if flag & 8:
459 while True:
460 s = self.__read(1)
461 if not s or s == NUL:
462 break
463 if flag & 16:
464 while True:
465 s = self.__read(1)
466 if not s or s == NUL:
467 break
468 if flag & 2:
469 self.__read(2)
470
471 def tell(self):
472 """Return the stream's file pointer position.
473 """
474 return self.pos
475
476 def seek(self, pos=0):
477 """Set the stream's file pointer to pos. Negative seeking
478 is forbidden.
479 """
480 if pos - self.pos >= 0:
481 blocks, remainder = divmod(pos - self.pos, self.bufsize)
482 for i in xrange(blocks):
483 self.read(self.bufsize)
484 self.read(remainder)
485 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000486 raise StreamError("seeking backwards is not allowed")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000487 return self.pos
488
489 def read(self, size=None):
490 """Return the next size number of bytes from the stream.
491 If size is not defined, return all bytes of the stream
492 up to EOF.
493 """
494 if size is None:
495 t = []
496 while True:
497 buf = self._read(self.bufsize)
498 if not buf:
499 break
500 t.append(buf)
501 buf = "".join(t)
502 else:
503 buf = self._read(size)
504 self.pos += len(buf)
505 return buf
506
507 def _read(self, size):
508 """Return size bytes from the stream.
509 """
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000510 if self.comptype == "tar":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000511 return self.__read(size)
512
513 c = len(self.dbuf)
514 t = [self.dbuf]
515 while c < size:
516 buf = self.__read(self.bufsize)
517 if not buf:
518 break
519 buf = self.cmp.decompress(buf)
520 t.append(buf)
521 c += len(buf)
522 t = "".join(t)
523 self.dbuf = t[size:]
524 return t[:size]
525
526 def __read(self, size):
527 """Return size bytes from stream. If internal buffer is empty,
528 read another block from the stream.
529 """
530 c = len(self.buf)
531 t = [self.buf]
532 while c < size:
533 buf = self.fileobj.read(self.bufsize)
534 if not buf:
535 break
536 t.append(buf)
537 c += len(buf)
538 t = "".join(t)
539 self.buf = t[size:]
540 return t[:size]
541# class _Stream
542
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000543class _StreamProxy(object):
544 """Small proxy class that enables transparent compression
545 detection for the Stream interface (mode 'r|*').
546 """
547
548 def __init__(self, fileobj):
549 self.fileobj = fileobj
550 self.buf = self.fileobj.read(BLOCKSIZE)
551
552 def read(self, size):
553 self.read = self.fileobj.read
554 return self.buf
555
556 def getcomptype(self):
557 if self.buf.startswith("\037\213\010"):
558 return "gz"
559 if self.buf.startswith("BZh91"):
560 return "bz2"
561 return "tar"
562
563 def close(self):
564 self.fileobj.close()
565# class StreamProxy
566
Thomas Wouters477c8d52006-05-27 19:21:47 +0000567class _BZ2Proxy(object):
568 """Small proxy class that enables external file object
569 support for "r:bz2" and "w:bz2" modes. This is actually
570 a workaround for a limitation in bz2 module's BZ2File
571 class which (unlike gzip.GzipFile) has no support for
572 a file object argument.
573 """
574
575 blocksize = 16 * 1024
576
577 def __init__(self, fileobj, mode):
578 self.fileobj = fileobj
579 self.mode = mode
580 self.init()
581
582 def init(self):
583 import bz2
584 self.pos = 0
585 if self.mode == "r":
586 self.bz2obj = bz2.BZ2Decompressor()
587 self.fileobj.seek(0)
588 self.buf = ""
589 else:
590 self.bz2obj = bz2.BZ2Compressor()
591
592 def read(self, size):
593 b = [self.buf]
594 x = len(self.buf)
595 while x < size:
596 try:
597 raw = self.fileobj.read(self.blocksize)
598 data = self.bz2obj.decompress(raw)
599 b.append(data)
600 except EOFError:
601 break
602 x += len(data)
603 self.buf = "".join(b)
604
605 buf = self.buf[:size]
606 self.buf = self.buf[size:]
607 self.pos += len(buf)
608 return buf
609
610 def seek(self, pos):
611 if pos < self.pos:
612 self.init()
613 self.read(pos - self.pos)
614
615 def tell(self):
616 return self.pos
617
618 def write(self, data):
619 self.pos += len(data)
620 raw = self.bz2obj.compress(data)
621 self.fileobj.write(raw)
622
623 def close(self):
624 if self.mode == "w":
625 raw = self.bz2obj.flush()
626 self.fileobj.write(raw)
627 self.fileobj.close()
628# class _BZ2Proxy
629
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000630#------------------------
631# Extraction file object
632#------------------------
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000633class _FileInFile(object):
634 """A thin wrapper around an existing file object that
635 provides a part of its data as an individual file
636 object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000637 """
638
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000639 def __init__(self, fileobj, offset, size, sparse=None):
640 self.fileobj = fileobj
641 self.offset = offset
642 self.size = size
643 self.sparse = sparse
644 self.position = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000645
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000646 def tell(self):
647 """Return the current file position.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000648 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000649 return self.position
650
651 def seek(self, position):
652 """Seek to a position in the file.
653 """
654 self.position = position
655
656 def read(self, size=None):
657 """Read data from the file.
658 """
659 if size is None:
660 size = self.size - self.position
661 else:
662 size = min(size, self.size - self.position)
663
664 if self.sparse is None:
665 return self.readnormal(size)
666 else:
667 return self.readsparse(size)
668
669 def readnormal(self, size):
670 """Read operation for regular files.
671 """
672 self.fileobj.seek(self.offset + self.position)
673 self.position += size
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000674 return self.fileobj.read(size)
675
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000676 def readsparse(self, size):
677 """Read operation for sparse files.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000678 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000679 data = []
680 while size > 0:
681 buf = self.readsparsesection(size)
682 if not buf:
683 break
684 size -= len(buf)
685 data.append(buf)
686 return "".join(data)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000687
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000688 def readsparsesection(self, size):
689 """Read a single section of a sparse file.
690 """
691 section = self.sparse.find(self.position)
692
693 if section is None:
694 return ""
695
696 size = min(size, section.offset + section.size - self.position)
697
698 if isinstance(section, _data):
699 realpos = section.realpos + self.position - section.offset
700 self.fileobj.seek(self.offset + realpos)
701 self.position += size
702 return self.fileobj.read(size)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000703 else:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000704 self.position += size
705 return NUL * size
706#class _FileInFile
707
708
709class ExFileObject(object):
710 """File-like object for reading an archive member.
711 Is returned by TarFile.extractfile().
712 """
713 blocksize = 1024
714
715 def __init__(self, tarfile, tarinfo):
716 self.fileobj = _FileInFile(tarfile.fileobj,
717 tarinfo.offset_data,
718 tarinfo.size,
719 getattr(tarinfo, "sparse", None))
720 self.name = tarinfo.name
721 self.mode = "r"
722 self.closed = False
723 self.size = tarinfo.size
724
725 self.position = 0
726 self.buffer = ""
727
728 def read(self, size=None):
729 """Read at most size bytes from the file. If size is not
730 present or None, read all data until EOF is reached.
731 """
732 if self.closed:
733 raise ValueError("I/O operation on closed file")
734
735 buf = ""
736 if self.buffer:
737 if size is None:
738 buf = self.buffer
739 self.buffer = ""
740 else:
741 buf = self.buffer[:size]
742 self.buffer = self.buffer[size:]
743
744 if size is None:
745 buf += self.fileobj.read()
746 else:
747 buf += self.fileobj.read(size - len(buf))
748
749 self.position += len(buf)
750 return buf
751
752 def readline(self, size=-1):
753 """Read one entire line from the file. If size is present
754 and non-negative, return a string with at most that
755 size, which may be an incomplete line.
756 """
757 if self.closed:
758 raise ValueError("I/O operation on closed file")
759
760 if "\n" in self.buffer:
761 pos = self.buffer.find("\n") + 1
762 else:
763 buffers = [self.buffer]
764 while True:
765 buf = self.fileobj.read(self.blocksize)
766 buffers.append(buf)
767 if not buf or "\n" in buf:
768 self.buffer = "".join(buffers)
769 pos = self.buffer.find("\n") + 1
770 if pos == 0:
771 # no newline found.
772 pos = len(self.buffer)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000773 break
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000774
775 if size != -1:
776 pos = min(size, pos)
777
778 buf = self.buffer[:pos]
779 self.buffer = self.buffer[pos:]
780 self.position += len(buf)
781 return buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000782
783 def readlines(self):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000784 """Return a list with all remaining lines.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000785 """
786 result = []
787 while True:
788 line = self.readline()
789 if not line: break
790 result.append(line)
791 return result
792
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000793 def tell(self):
794 """Return the current file position.
795 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000796 if self.closed:
797 raise ValueError("I/O operation on closed file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000798
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000799 return self.position
800
801 def seek(self, pos, whence=os.SEEK_SET):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000802 """Seek to a position in the file.
803 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000804 if self.closed:
805 raise ValueError("I/O operation on closed file")
806
807 if whence == os.SEEK_SET:
808 self.position = min(max(pos, 0), self.size)
809 elif whence == os.SEEK_CUR:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000810 if pos < 0:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000811 self.position = max(self.position + pos, 0)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000812 else:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000813 self.position = min(self.position + pos, self.size)
814 elif whence == os.SEEK_END:
815 self.position = max(min(self.size + pos, self.size), 0)
816 else:
817 raise ValueError("Invalid argument")
818
819 self.buffer = ""
820 self.fileobj.seek(self.position)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000821
822 def close(self):
823 """Close the file object.
824 """
825 self.closed = True
Martin v. Löwisdf241532005-03-03 08:17:42 +0000826
827 def __iter__(self):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000828 """Get an iterator over the file's lines.
Martin v. Löwisdf241532005-03-03 08:17:42 +0000829 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000830 while True:
831 line = self.readline()
832 if not line:
833 break
834 yield line
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000835#class ExFileObject
836
837#------------------
838# Exported Classes
839#------------------
840class TarInfo(object):
841 """Informational class which holds the details about an
842 archive member given by a tar header block.
843 TarInfo objects are returned by TarFile.getmember(),
844 TarFile.getmembers() and TarFile.gettarinfo() and are
845 usually created internally.
846 """
847
848 def __init__(self, name=""):
849 """Construct a TarInfo object. name is the optional name
850 of the member.
851 """
Thomas Wouters477c8d52006-05-27 19:21:47 +0000852 self.name = name # member name (dirnames must end with '/')
853 self.mode = 0666 # file permissions
854 self.uid = 0 # user id
855 self.gid = 0 # group id
856 self.size = 0 # file size
857 self.mtime = 0 # modification time
858 self.chksum = 0 # header checksum
859 self.type = REGTYPE # member type
860 self.linkname = "" # link name
861 self.uname = "user" # user name
862 self.gname = "group" # group name
863 self.devmajor = 0 # device major number
864 self.devminor = 0 # device minor number
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000865
Thomas Wouters477c8d52006-05-27 19:21:47 +0000866 self.offset = 0 # the tar header starts here
867 self.offset_data = 0 # the file's data starts here
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000868
869 def __repr__(self):
870 return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self))
871
Guido van Rossum75b64e62005-01-16 00:16:11 +0000872 @classmethod
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000873 def frombuf(cls, buf):
874 """Construct a TarInfo object from a 512 byte string buffer.
875 """
Thomas Wouters477c8d52006-05-27 19:21:47 +0000876 if len(buf) != BLOCKSIZE:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000877 raise HeaderError("truncated header")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000878 if buf.count(NUL) == BLOCKSIZE:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000879 raise HeaderError("empty header")
880
881 chksum = nti(buf[148:156])
882 if chksum not in calc_chksums(buf):
883 raise HeaderError("bad checksum")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000884
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000885 tarinfo = cls()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000886 tarinfo.buf = buf
887 tarinfo.name = buf[0:100].rstrip(NUL)
888 tarinfo.mode = nti(buf[100:108])
889 tarinfo.uid = nti(buf[108:116])
890 tarinfo.gid = nti(buf[116:124])
891 tarinfo.size = nti(buf[124:136])
892 tarinfo.mtime = nti(buf[136:148])
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000893 tarinfo.chksum = chksum
Thomas Wouters477c8d52006-05-27 19:21:47 +0000894 tarinfo.type = buf[156:157]
895 tarinfo.linkname = buf[157:257].rstrip(NUL)
896 tarinfo.uname = buf[265:297].rstrip(NUL)
897 tarinfo.gname = buf[297:329].rstrip(NUL)
898 tarinfo.devmajor = nti(buf[329:337])
899 tarinfo.devminor = nti(buf[337:345])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000900 prefix = buf[345:500].rstrip(NUL)
901
902 if prefix and not tarinfo.issparse():
903 tarinfo.name = prefix + "/" + tarinfo.name
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000904
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000905 return tarinfo
906
Thomas Wouters477c8d52006-05-27 19:21:47 +0000907 def tobuf(self, posix=False):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000908 """Return a tar header as a string of 512 byte blocks.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000909 """
Thomas Wouters89f507f2006-12-13 04:49:30 +0000910 buf = ""
911 type = self.type
912 prefix = ""
913
914 if self.name.endswith("/"):
915 type = DIRTYPE
916
917 if type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
918 # Prevent "././@LongLink" from being normalized.
919 name = self.name
920 else:
921 name = normpath(self.name)
922
923 if type == DIRTYPE:
924 # directories should end with '/'
925 name += "/"
926
927 linkname = self.linkname
928 if linkname:
929 # if linkname is empty we end up with a '.'
930 linkname = normpath(linkname)
931
932 if posix:
933 if self.size > MAXSIZE_MEMBER:
934 raise ValueError("file is too large (>= 8 GB)")
935
936 if len(self.linkname) > LENGTH_LINK:
937 raise ValueError("linkname is too long (>%d)" % (LENGTH_LINK))
938
939 if len(name) > LENGTH_NAME:
940 prefix = name[:LENGTH_PREFIX + 1]
941 while prefix and prefix[-1] != "/":
942 prefix = prefix[:-1]
943
944 name = name[len(prefix):]
945 prefix = prefix[:-1]
946
947 if not prefix or len(name) > LENGTH_NAME:
948 raise ValueError("name is too long")
949
950 else:
951 if len(self.linkname) > LENGTH_LINK:
952 buf += self._create_gnulong(self.linkname, GNUTYPE_LONGLINK)
953
954 if len(name) > LENGTH_NAME:
955 buf += self._create_gnulong(name, GNUTYPE_LONGNAME)
956
Thomas Wouters477c8d52006-05-27 19:21:47 +0000957 parts = [
Thomas Wouters89f507f2006-12-13 04:49:30 +0000958 stn(name, 100),
Thomas Wouters477c8d52006-05-27 19:21:47 +0000959 itn(self.mode & 07777, 8, posix),
960 itn(self.uid, 8, posix),
961 itn(self.gid, 8, posix),
962 itn(self.size, 12, posix),
963 itn(self.mtime, 12, posix),
964 " ", # checksum field
Thomas Wouters89f507f2006-12-13 04:49:30 +0000965 type,
Thomas Wouters477c8d52006-05-27 19:21:47 +0000966 stn(self.linkname, 100),
967 stn(MAGIC, 6),
968 stn(VERSION, 2),
969 stn(self.uname, 32),
970 stn(self.gname, 32),
971 itn(self.devmajor, 8, posix),
972 itn(self.devminor, 8, posix),
Thomas Wouters89f507f2006-12-13 04:49:30 +0000973 stn(prefix, 155)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000974 ]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000975
Thomas Wouters89f507f2006-12-13 04:49:30 +0000976 buf += struct.pack("%ds" % BLOCKSIZE, "".join(parts))
977 chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
978 buf = buf[:-364] + "%06o\0" % chksum + buf[-357:]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000979 self.buf = buf
980 return buf
981
Thomas Wouters89f507f2006-12-13 04:49:30 +0000982 def _create_gnulong(self, name, type):
983 """Create a GNU longname/longlink header from name.
984 It consists of an extended tar header, with the length
985 of the longname as size, followed by data blocks,
986 which contain the longname as a null terminated string.
987 """
988 name += NUL
989
990 tarinfo = self.__class__()
991 tarinfo.name = "././@LongLink"
992 tarinfo.type = type
993 tarinfo.mode = 0
994 tarinfo.size = len(name)
995
996 # create extended header
997 buf = tarinfo.tobuf()
998 # create name blocks
999 buf += name
1000 blocks, remainder = divmod(len(name), BLOCKSIZE)
1001 if remainder > 0:
1002 buf += (BLOCKSIZE - remainder) * NUL
1003 return buf
1004
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001005 def isreg(self):
1006 return self.type in REGULAR_TYPES
1007 def isfile(self):
1008 return self.isreg()
1009 def isdir(self):
1010 return self.type == DIRTYPE
1011 def issym(self):
1012 return self.type == SYMTYPE
1013 def islnk(self):
1014 return self.type == LNKTYPE
1015 def ischr(self):
1016 return self.type == CHRTYPE
1017 def isblk(self):
1018 return self.type == BLKTYPE
1019 def isfifo(self):
1020 return self.type == FIFOTYPE
1021 def issparse(self):
1022 return self.type == GNUTYPE_SPARSE
1023 def isdev(self):
1024 return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
1025# class TarInfo
1026
1027class TarFile(object):
1028 """The TarFile Class provides an interface to tar archives.
1029 """
1030
1031 debug = 0 # May be set from 0 (no msgs) to 3 (all msgs)
1032
1033 dereference = False # If true, add content of linked file to the
1034 # tar file, else the link.
1035
1036 ignore_zeros = False # If true, skips empty or invalid blocks and
1037 # continues processing.
1038
1039 errorlevel = 0 # If 0, fatal errors only appear in debug
1040 # messages (if debug >= 0). If > 0, errors
1041 # are passed to the caller as exceptions.
1042
Martin v. Löwis75b9da42004-08-18 13:57:44 +00001043 posix = False # If True, generates POSIX.1-1990-compliant
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001044 # archives (no GNU extensions!)
1045
1046 fileobject = ExFileObject
1047
1048 def __init__(self, name=None, mode="r", fileobj=None):
1049 """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
1050 read from an existing archive, 'a' to append data to an existing
1051 file or 'w' to create a new file overwriting an existing one. `mode'
1052 defaults to 'r'.
1053 If `fileobj' is given, it is used for reading or writing data. If it
1054 can be determined, `mode' is overridden by `fileobj's mode.
1055 `fileobj' is not closed, when TarFile is closed.
1056 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001057 self.name = os.path.abspath(name)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001058
1059 if len(mode) > 1 or mode not in "raw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001060 raise ValueError("mode must be 'r', 'a' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001061 self._mode = mode
1062 self.mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]
1063
1064 if not fileobj:
Thomas Wouterscf297e42007-02-23 15:07:44 +00001065 if self._mode == "a" and not os.path.exists(self.name):
1066 # Create nonexistent files in append mode.
1067 self._mode = "w"
1068 self.mode = "wb"
Guido van Rossum8f78fe92006-08-24 04:03:53 +00001069 fileobj = _open(self.name, self.mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001070 self._extfileobj = False
1071 else:
1072 if self.name is None and hasattr(fileobj, "name"):
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001073 self.name = os.path.abspath(fileobj.name)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001074 if hasattr(fileobj, "mode"):
1075 self.mode = fileobj.mode
1076 self._extfileobj = True
1077 self.fileobj = fileobj
1078
1079 # Init datastructures
Thomas Wouters477c8d52006-05-27 19:21:47 +00001080 self.closed = False
1081 self.members = [] # list of members as TarInfo objects
1082 self._loaded = False # flag if all members have been read
Guido van Rossume2a383d2007-01-15 16:59:06 +00001083 self.offset = 0 # current position in the archive file
Thomas Wouters477c8d52006-05-27 19:21:47 +00001084 self.inodes = {} # dictionary caching the inodes of
1085 # archive members already added
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001086
1087 if self._mode == "r":
1088 self.firstmember = None
1089 self.firstmember = self.next()
1090
1091 if self._mode == "a":
1092 # Move to the end of the archive,
1093 # before the first empty block.
1094 self.firstmember = None
1095 while True:
1096 try:
1097 tarinfo = self.next()
1098 except ReadError:
1099 self.fileobj.seek(0)
1100 break
1101 if tarinfo is None:
Thomas Wouterscf297e42007-02-23 15:07:44 +00001102 if self.offset > 0:
1103 self.fileobj.seek(- BLOCKSIZE, 1)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001104 break
1105
1106 if self._mode in "aw":
1107 self._loaded = True
1108
1109 #--------------------------------------------------------------------------
1110 # Below are the classmethods which act as alternate constructors to the
1111 # TarFile class. The open() method is the only one that is needed for
1112 # public use; it is the "super"-constructor and is able to select an
1113 # adequate "sub"-constructor for a particular compression using the mapping
1114 # from OPEN_METH.
1115 #
1116 # This concept allows one to subclass TarFile without losing the comfort of
1117 # the super-constructor. A sub-constructor is registered and made available
1118 # by adding it to the mapping in OPEN_METH.
1119
Guido van Rossum75b64e62005-01-16 00:16:11 +00001120 @classmethod
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001121 def open(cls, name=None, mode="r", fileobj=None, bufsize=20*512):
1122 """Open a tar archive for reading, writing or appending. Return
1123 an appropriate TarFile class.
1124
1125 mode:
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001126 'r' or 'r:*' open for reading with transparent compression
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001127 'r:' open for reading exclusively uncompressed
1128 'r:gz' open for reading with gzip compression
1129 'r:bz2' open for reading with bzip2 compression
Thomas Wouterscf297e42007-02-23 15:07:44 +00001130 'a' or 'a:' open for appending, creating the file if necessary
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001131 'w' or 'w:' open for writing without compression
1132 'w:gz' open for writing with gzip compression
1133 'w:bz2' open for writing with bzip2 compression
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001134
1135 'r|*' open a stream of tar blocks with transparent compression
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001136 'r|' open an uncompressed stream of tar blocks for reading
1137 'r|gz' open a gzip compressed stream of tar blocks
1138 'r|bz2' open a bzip2 compressed stream of tar blocks
1139 'w|' open an uncompressed stream for writing
1140 'w|gz' open a gzip compressed stream for writing
1141 'w|bz2' open a bzip2 compressed stream for writing
1142 """
1143
1144 if not name and not fileobj:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001145 raise ValueError("nothing to open")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001146
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001147 if mode in ("r", "r:*"):
1148 # Find out which *open() is appropriate for opening the file.
1149 for comptype in cls.OPEN_METH:
1150 func = getattr(cls, cls.OPEN_METH[comptype])
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001151 if fileobj is not None:
1152 saved_pos = fileobj.tell()
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001153 try:
1154 return func(name, "r", fileobj)
1155 except (ReadError, CompressionError):
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001156 if fileobj is not None:
1157 fileobj.seek(saved_pos)
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001158 continue
Thomas Wouters477c8d52006-05-27 19:21:47 +00001159 raise ReadError("file could not be opened successfully")
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001160
1161 elif ":" in mode:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001162 filemode, comptype = mode.split(":", 1)
1163 filemode = filemode or "r"
1164 comptype = comptype or "tar"
1165
1166 # Select the *open() function according to
1167 # given compression.
1168 if comptype in cls.OPEN_METH:
1169 func = getattr(cls, cls.OPEN_METH[comptype])
1170 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001171 raise CompressionError("unknown compression type %r" % comptype)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001172 return func(name, filemode, fileobj)
1173
1174 elif "|" in mode:
1175 filemode, comptype = mode.split("|", 1)
1176 filemode = filemode or "r"
1177 comptype = comptype or "tar"
1178
1179 if filemode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001180 raise ValueError("mode must be 'r' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001181
1182 t = cls(name, filemode,
1183 _Stream(name, filemode, comptype, fileobj, bufsize))
1184 t._extfileobj = False
1185 return t
1186
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001187 elif mode in "aw":
1188 return cls.taropen(name, mode, fileobj)
1189
Thomas Wouters477c8d52006-05-27 19:21:47 +00001190 raise ValueError("undiscernible mode")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001191
Guido van Rossum75b64e62005-01-16 00:16:11 +00001192 @classmethod
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001193 def taropen(cls, name, mode="r", fileobj=None):
1194 """Open uncompressed tar archive name for reading or writing.
1195 """
1196 if len(mode) > 1 or mode not in "raw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001197 raise ValueError("mode must be 'r', 'a' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001198 return cls(name, mode, fileobj)
1199
Guido van Rossum75b64e62005-01-16 00:16:11 +00001200 @classmethod
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001201 def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9):
1202 """Open gzip compressed tar archive name for reading or writing.
1203 Appending is not allowed.
1204 """
1205 if len(mode) > 1 or mode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001206 raise ValueError("mode must be 'r' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001207
1208 try:
1209 import gzip
Neal Norwitz4ec68242003-04-11 03:05:56 +00001210 gzip.GzipFile
1211 except (ImportError, AttributeError):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001212 raise CompressionError("gzip module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001213
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001214 if fileobj is None:
Guido van Rossum8f78fe92006-08-24 04:03:53 +00001215 fileobj = _open(name, mode + "b")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001216
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001217 try:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001218 t = cls.taropen(name, mode,
1219 gzip.GzipFile(name, mode, compresslevel, fileobj))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001220 except IOError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001221 raise ReadError("not a gzip file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001222 t._extfileobj = False
1223 return t
1224
Guido van Rossum75b64e62005-01-16 00:16:11 +00001225 @classmethod
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001226 def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9):
1227 """Open bzip2 compressed tar archive name for reading or writing.
1228 Appending is not allowed.
1229 """
1230 if len(mode) > 1 or mode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001231 raise ValueError("mode must be 'r' or 'w'.")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001232
1233 try:
1234 import bz2
1235 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001236 raise CompressionError("bz2 module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001237
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001238 if fileobj is not None:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001239 fileobj = _BZ2Proxy(fileobj, mode)
1240 else:
1241 fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001242
1243 try:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001244 t = cls.taropen(name, mode, fileobj)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001245 except IOError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001246 raise ReadError("not a bzip2 file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001247 t._extfileobj = False
1248 return t
1249
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001250 # All *open() methods are registered here.
1251 OPEN_METH = {
1252 "tar": "taropen", # uncompressed tar
1253 "gz": "gzopen", # gzip compressed tar
1254 "bz2": "bz2open" # bzip2 compressed tar
1255 }
1256
1257 #--------------------------------------------------------------------------
1258 # The public methods which TarFile provides:
1259
1260 def close(self):
1261 """Close the TarFile. In write-mode, two finishing zero blocks are
1262 appended to the archive.
1263 """
1264 if self.closed:
1265 return
1266
1267 if self._mode in "aw":
1268 self.fileobj.write(NUL * (BLOCKSIZE * 2))
1269 self.offset += (BLOCKSIZE * 2)
1270 # fill up the end with zero-blocks
1271 # (like option -b20 for tar does)
1272 blocks, remainder = divmod(self.offset, RECORDSIZE)
1273 if remainder > 0:
1274 self.fileobj.write(NUL * (RECORDSIZE - remainder))
1275
1276 if not self._extfileobj:
1277 self.fileobj.close()
1278 self.closed = True
1279
1280 def getmember(self, name):
1281 """Return a TarInfo object for member `name'. If `name' can not be
1282 found in the archive, KeyError is raised. If a member occurs more
1283 than once in the archive, its last occurence is assumed to be the
1284 most up-to-date version.
1285 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001286 tarinfo = self._getmember(name)
1287 if tarinfo is None:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001288 raise KeyError("filename %r not found" % name)
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001289 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001290
1291 def getmembers(self):
1292 """Return the members of the archive as a list of TarInfo objects. The
1293 list has the same order as the members in the archive.
1294 """
1295 self._check()
1296 if not self._loaded: # if we want to obtain a list of
1297 self._load() # all members, we first have to
1298 # scan the whole archive.
1299 return self.members
1300
1301 def getnames(self):
1302 """Return the members of the archive as a list of their names. It has
1303 the same order as the list returned by getmembers().
1304 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001305 return [tarinfo.name for tarinfo in self.getmembers()]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001306
1307 def gettarinfo(self, name=None, arcname=None, fileobj=None):
1308 """Create a TarInfo object for either the file `name' or the file
1309 object `fileobj' (using os.fstat on its file descriptor). You can
1310 modify some of the TarInfo's attributes before you add it using
1311 addfile(). If given, `arcname' specifies an alternative name for the
1312 file in the archive.
1313 """
1314 self._check("aw")
1315
1316 # When fileobj is given, replace name by
1317 # fileobj's real name.
1318 if fileobj is not None:
1319 name = fileobj.name
1320
1321 # Building the name of the member in the archive.
1322 # Backward slashes are converted to forward slashes,
1323 # Absolute paths are turned to relative paths.
1324 if arcname is None:
1325 arcname = name
1326 arcname = normpath(arcname)
1327 drv, arcname = os.path.splitdrive(arcname)
1328 while arcname[0:1] == "/":
1329 arcname = arcname[1:]
1330
1331 # Now, fill the TarInfo object with
1332 # information specific for the file.
1333 tarinfo = TarInfo()
1334
1335 # Use os.stat or os.lstat, depending on platform
1336 # and if symlinks shall be resolved.
1337 if fileobj is None:
1338 if hasattr(os, "lstat") and not self.dereference:
1339 statres = os.lstat(name)
1340 else:
1341 statres = os.stat(name)
1342 else:
1343 statres = os.fstat(fileobj.fileno())
1344 linkname = ""
1345
1346 stmd = statres.st_mode
1347 if stat.S_ISREG(stmd):
1348 inode = (statres.st_ino, statres.st_dev)
Neal Norwitzb0e32e22005-10-20 04:50:13 +00001349 if not self.dereference and \
1350 statres.st_nlink > 1 and inode in self.inodes:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001351 # Is it a hardlink to an already
1352 # archived file?
1353 type = LNKTYPE
1354 linkname = self.inodes[inode]
1355 else:
1356 # The inode is added only if its valid.
1357 # For win32 it is always 0.
1358 type = REGTYPE
1359 if inode[0]:
1360 self.inodes[inode] = arcname
1361 elif stat.S_ISDIR(stmd):
1362 type = DIRTYPE
1363 if arcname[-1:] != "/":
1364 arcname += "/"
1365 elif stat.S_ISFIFO(stmd):
1366 type = FIFOTYPE
1367 elif stat.S_ISLNK(stmd):
1368 type = SYMTYPE
1369 linkname = os.readlink(name)
1370 elif stat.S_ISCHR(stmd):
1371 type = CHRTYPE
1372 elif stat.S_ISBLK(stmd):
1373 type = BLKTYPE
1374 else:
1375 return None
1376
1377 # Fill the TarInfo object with all
1378 # information we can get.
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001379 tarinfo.name = arcname
1380 tarinfo.mode = stmd
1381 tarinfo.uid = statres.st_uid
1382 tarinfo.gid = statres.st_gid
1383 if stat.S_ISREG(stmd):
Martin v. Löwis61d77e02004-08-20 06:35:46 +00001384 tarinfo.size = statres.st_size
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001385 else:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001386 tarinfo.size = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001387 tarinfo.mtime = statres.st_mtime
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001388 tarinfo.type = type
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001389 tarinfo.linkname = linkname
1390 if pwd:
1391 try:
1392 tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
1393 except KeyError:
1394 pass
1395 if grp:
1396 try:
1397 tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
1398 except KeyError:
1399 pass
1400
1401 if type in (CHRTYPE, BLKTYPE):
1402 if hasattr(os, "major") and hasattr(os, "minor"):
1403 tarinfo.devmajor = os.major(statres.st_rdev)
1404 tarinfo.devminor = os.minor(statres.st_rdev)
1405 return tarinfo
1406
1407 def list(self, verbose=True):
1408 """Print a table of contents to sys.stdout. If `verbose' is False, only
1409 the names of the members are printed. If it is True, an `ls -l'-like
1410 output is produced.
1411 """
1412 self._check()
1413
1414 for tarinfo in self:
1415 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001416 print(filemode(tarinfo.mode), end=' ')
1417 print("%s/%s" % (tarinfo.uname or tarinfo.uid,
1418 tarinfo.gname or tarinfo.gid), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001419 if tarinfo.ischr() or tarinfo.isblk():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001420 print("%10s" % ("%d,%d" \
1421 % (tarinfo.devmajor, tarinfo.devminor)), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001422 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001423 print("%10d" % tarinfo.size, end=' ')
1424 print("%d-%02d-%02d %02d:%02d:%02d" \
1425 % time.localtime(tarinfo.mtime)[:6], end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001426
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001427 print(tarinfo.name, end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001428
1429 if verbose:
1430 if tarinfo.issym():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001431 print("->", tarinfo.linkname, end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001432 if tarinfo.islnk():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001433 print("link to", tarinfo.linkname, end=' ')
1434 print()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001435
1436 def add(self, name, arcname=None, recursive=True):
1437 """Add the file `name' to the archive. `name' may be any type of file
1438 (directory, fifo, symbolic link, etc.). If given, `arcname'
1439 specifies an alternative name for the file in the archive.
1440 Directories are added recursively by default. This can be avoided by
1441 setting `recursive' to False.
1442 """
1443 self._check("aw")
1444
1445 if arcname is None:
1446 arcname = name
1447
1448 # Skip if somebody tries to archive the archive...
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001449 if self.name is not None and os.path.abspath(name) == self.name:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001450 self._dbg(2, "tarfile: Skipped %r" % name)
1451 return
1452
1453 # Special case: The user wants to add the current
1454 # working directory.
1455 if name == ".":
1456 if recursive:
1457 if arcname == ".":
1458 arcname = ""
1459 for f in os.listdir("."):
1460 self.add(f, os.path.join(arcname, f))
1461 return
1462
1463 self._dbg(1, name)
1464
1465 # Create a TarInfo object from the file.
1466 tarinfo = self.gettarinfo(name, arcname)
1467
1468 if tarinfo is None:
1469 self._dbg(1, "tarfile: Unsupported type %r" % name)
1470 return
1471
1472 # Append the tar header and data to the archive.
1473 if tarinfo.isreg():
Guido van Rossum8f78fe92006-08-24 04:03:53 +00001474 f = _open(name, "rb")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001475 self.addfile(tarinfo, f)
1476 f.close()
1477
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001478 elif tarinfo.isdir():
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001479 self.addfile(tarinfo)
1480 if recursive:
1481 for f in os.listdir(name):
1482 self.add(os.path.join(name, f), os.path.join(arcname, f))
1483
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001484 else:
1485 self.addfile(tarinfo)
1486
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001487 def addfile(self, tarinfo, fileobj=None):
1488 """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
1489 given, tarinfo.size bytes are read from it and added to the archive.
1490 You can create TarInfo objects using gettarinfo().
1491 On Windows platforms, `fileobj' should always be opened with mode
1492 'rb' to avoid irritation about the file size.
1493 """
1494 self._check("aw")
1495
Thomas Wouters89f507f2006-12-13 04:49:30 +00001496 tarinfo = copy.copy(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001497
Thomas Wouters89f507f2006-12-13 04:49:30 +00001498 buf = tarinfo.tobuf(self.posix)
1499 self.fileobj.write(buf)
1500 self.offset += len(buf)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001501
1502 # If there's data to follow, append it.
1503 if fileobj is not None:
1504 copyfileobj(fileobj, self.fileobj, tarinfo.size)
1505 blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
1506 if remainder > 0:
1507 self.fileobj.write(NUL * (BLOCKSIZE - remainder))
1508 blocks += 1
1509 self.offset += blocks * BLOCKSIZE
1510
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001511 self.members.append(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001512
Martin v. Löwis00a73e72005-03-04 19:40:34 +00001513 def extractall(self, path=".", members=None):
1514 """Extract all members from the archive to the current working
1515 directory and set owner, modification time and permissions on
1516 directories afterwards. `path' specifies a different directory
1517 to extract to. `members' is optional and must be a subset of the
1518 list returned by getmembers().
1519 """
1520 directories = []
1521
1522 if members is None:
1523 members = self
1524
1525 for tarinfo in members:
1526 if tarinfo.isdir():
1527 # Extract directory with a safe mode, so that
1528 # all files below can be extracted as well.
1529 try:
1530 os.makedirs(os.path.join(path, tarinfo.name), 0777)
1531 except EnvironmentError:
1532 pass
1533 directories.append(tarinfo)
1534 else:
1535 self.extract(tarinfo, path)
1536
1537 # Reverse sort directories.
1538 directories.sort(lambda a, b: cmp(a.name, b.name))
1539 directories.reverse()
1540
1541 # Set correct owner, mtime and filemode on directories.
1542 for tarinfo in directories:
1543 path = os.path.join(path, tarinfo.name)
1544 try:
1545 self.chown(tarinfo, path)
1546 self.utime(tarinfo, path)
1547 self.chmod(tarinfo, path)
Guido van Rossumb940e112007-01-10 16:19:56 +00001548 except ExtractError as e:
Martin v. Löwis00a73e72005-03-04 19:40:34 +00001549 if self.errorlevel > 1:
1550 raise
1551 else:
1552 self._dbg(1, "tarfile: %s" % e)
1553
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001554 def extract(self, member, path=""):
1555 """Extract a member from the archive to the current working directory,
1556 using its full name. Its file information is extracted as accurately
1557 as possible. `member' may be a filename or a TarInfo object. You can
1558 specify a different directory using `path'.
1559 """
1560 self._check("r")
1561
1562 if isinstance(member, TarInfo):
1563 tarinfo = member
1564 else:
1565 tarinfo = self.getmember(member)
1566
Neal Norwitza4f651a2004-07-20 22:07:44 +00001567 # Prepare the link target for makelink().
1568 if tarinfo.islnk():
1569 tarinfo._link_target = os.path.join(path, tarinfo.linkname)
1570
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001571 try:
1572 self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
Guido van Rossumb940e112007-01-10 16:19:56 +00001573 except EnvironmentError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001574 if self.errorlevel > 0:
1575 raise
1576 else:
1577 if e.filename is None:
1578 self._dbg(1, "tarfile: %s" % e.strerror)
1579 else:
1580 self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
Guido van Rossumb940e112007-01-10 16:19:56 +00001581 except ExtractError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001582 if self.errorlevel > 1:
1583 raise
1584 else:
1585 self._dbg(1, "tarfile: %s" % e)
1586
1587 def extractfile(self, member):
1588 """Extract a member from the archive as a file object. `member' may be
1589 a filename or a TarInfo object. If `member' is a regular file, a
1590 file-like object is returned. If `member' is a link, a file-like
1591 object is constructed from the link's target. If `member' is none of
1592 the above, None is returned.
1593 The file-like object is read-only and provides the following
1594 methods: read(), readline(), readlines(), seek() and tell()
1595 """
1596 self._check("r")
1597
1598 if isinstance(member, TarInfo):
1599 tarinfo = member
1600 else:
1601 tarinfo = self.getmember(member)
1602
1603 if tarinfo.isreg():
1604 return self.fileobject(self, tarinfo)
1605
1606 elif tarinfo.type not in SUPPORTED_TYPES:
1607 # If a member's type is unknown, it is treated as a
1608 # regular file.
1609 return self.fileobject(self, tarinfo)
1610
1611 elif tarinfo.islnk() or tarinfo.issym():
1612 if isinstance(self.fileobj, _Stream):
1613 # A small but ugly workaround for the case that someone tries
1614 # to extract a (sym)link as a file-object from a non-seekable
1615 # stream of tar blocks.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001616 raise StreamError("cannot extract (sym)link as file object")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001617 else:
Georg Brandl7eb4b7d2005-07-22 21:49:32 +00001618 # A (sym)link's file object is its target's file object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001619 return self.extractfile(self._getmember(tarinfo.linkname,
1620 tarinfo))
1621 else:
1622 # If there's no data associated with the member (directory, chrdev,
1623 # blkdev, etc.), return None instead of a file object.
1624 return None
1625
1626 def _extract_member(self, tarinfo, targetpath):
1627 """Extract the TarInfo object tarinfo to a physical
1628 file called targetpath.
1629 """
1630 # Fetch the TarInfo object for the given name
1631 # and build the destination pathname, replacing
1632 # forward slashes to platform specific separators.
1633 if targetpath[-1:] == "/":
1634 targetpath = targetpath[:-1]
1635 targetpath = os.path.normpath(targetpath)
1636
1637 # Create all upper directories.
1638 upperdirs = os.path.dirname(targetpath)
1639 if upperdirs and not os.path.exists(upperdirs):
Thomas Woutersb2137042007-02-01 18:02:27 +00001640 os.makedirs(upperdirs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001641
1642 if tarinfo.islnk() or tarinfo.issym():
1643 self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
1644 else:
1645 self._dbg(1, tarinfo.name)
1646
1647 if tarinfo.isreg():
1648 self.makefile(tarinfo, targetpath)
1649 elif tarinfo.isdir():
1650 self.makedir(tarinfo, targetpath)
1651 elif tarinfo.isfifo():
1652 self.makefifo(tarinfo, targetpath)
1653 elif tarinfo.ischr() or tarinfo.isblk():
1654 self.makedev(tarinfo, targetpath)
1655 elif tarinfo.islnk() or tarinfo.issym():
1656 self.makelink(tarinfo, targetpath)
1657 elif tarinfo.type not in SUPPORTED_TYPES:
1658 self.makeunknown(tarinfo, targetpath)
1659 else:
1660 self.makefile(tarinfo, targetpath)
1661
1662 self.chown(tarinfo, targetpath)
1663 if not tarinfo.issym():
1664 self.chmod(tarinfo, targetpath)
1665 self.utime(tarinfo, targetpath)
1666
1667 #--------------------------------------------------------------------------
1668 # Below are the different file methods. They are called via
1669 # _extract_member() when extract() is called. They can be replaced in a
1670 # subclass to implement other functionality.
1671
1672 def makedir(self, tarinfo, targetpath):
1673 """Make a directory called targetpath.
1674 """
1675 try:
1676 os.mkdir(targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00001677 except EnvironmentError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001678 if e.errno != errno.EEXIST:
1679 raise
1680
1681 def makefile(self, tarinfo, targetpath):
1682 """Make a file called targetpath.
1683 """
1684 source = self.extractfile(tarinfo)
Guido van Rossum8f78fe92006-08-24 04:03:53 +00001685 target = _open(targetpath, "wb")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001686 copyfileobj(source, target)
1687 source.close()
1688 target.close()
1689
1690 def makeunknown(self, tarinfo, targetpath):
1691 """Make a file from a TarInfo object with an unknown type
1692 at targetpath.
1693 """
1694 self.makefile(tarinfo, targetpath)
1695 self._dbg(1, "tarfile: Unknown file type %r, " \
1696 "extracted as regular file." % tarinfo.type)
1697
1698 def makefifo(self, tarinfo, targetpath):
1699 """Make a fifo called targetpath.
1700 """
1701 if hasattr(os, "mkfifo"):
1702 os.mkfifo(targetpath)
1703 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001704 raise ExtractError("fifo not supported by system")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001705
1706 def makedev(self, tarinfo, targetpath):
1707 """Make a character or block device called targetpath.
1708 """
1709 if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001710 raise ExtractError("special devices not supported by system")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001711
1712 mode = tarinfo.mode
1713 if tarinfo.isblk():
1714 mode |= stat.S_IFBLK
1715 else:
1716 mode |= stat.S_IFCHR
1717
1718 os.mknod(targetpath, mode,
1719 os.makedev(tarinfo.devmajor, tarinfo.devminor))
1720
1721 def makelink(self, tarinfo, targetpath):
1722 """Make a (symbolic) link called targetpath. If it cannot be created
1723 (platform limitation), we try to make a copy of the referenced file
1724 instead of a link.
1725 """
1726 linkpath = tarinfo.linkname
1727 try:
1728 if tarinfo.issym():
1729 os.symlink(linkpath, targetpath)
1730 else:
Neal Norwitza4f651a2004-07-20 22:07:44 +00001731 # See extract().
1732 os.link(tarinfo._link_target, targetpath)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001733 except AttributeError:
1734 if tarinfo.issym():
1735 linkpath = os.path.join(os.path.dirname(tarinfo.name),
1736 linkpath)
1737 linkpath = normpath(linkpath)
1738
1739 try:
1740 self._extract_member(self.getmember(linkpath), targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00001741 except (EnvironmentError, KeyError) as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001742 linkpath = os.path.normpath(linkpath)
1743 try:
1744 shutil.copy2(linkpath, targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00001745 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001746 raise IOError("link could not be created")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001747
1748 def chown(self, tarinfo, targetpath):
1749 """Set owner of targetpath according to tarinfo.
1750 """
1751 if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
1752 # We have to be root to do so.
1753 try:
1754 g = grp.getgrnam(tarinfo.gname)[2]
1755 except KeyError:
1756 try:
1757 g = grp.getgrgid(tarinfo.gid)[2]
1758 except KeyError:
1759 g = os.getgid()
1760 try:
1761 u = pwd.getpwnam(tarinfo.uname)[2]
1762 except KeyError:
1763 try:
1764 u = pwd.getpwuid(tarinfo.uid)[2]
1765 except KeyError:
1766 u = os.getuid()
1767 try:
1768 if tarinfo.issym() and hasattr(os, "lchown"):
1769 os.lchown(targetpath, u, g)
1770 else:
Andrew MacIntyre7970d202003-02-19 12:51:34 +00001771 if sys.platform != "os2emx":
1772 os.chown(targetpath, u, g)
Guido van Rossumb940e112007-01-10 16:19:56 +00001773 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001774 raise ExtractError("could not change owner")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001775
1776 def chmod(self, tarinfo, targetpath):
1777 """Set file permissions of targetpath according to tarinfo.
1778 """
Jack Jansen834eff62003-03-07 12:47:06 +00001779 if hasattr(os, 'chmod'):
1780 try:
1781 os.chmod(targetpath, tarinfo.mode)
Guido van Rossumb940e112007-01-10 16:19:56 +00001782 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001783 raise ExtractError("could not change mode")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001784
1785 def utime(self, tarinfo, targetpath):
1786 """Set modification time of targetpath according to tarinfo.
1787 """
Jack Jansen834eff62003-03-07 12:47:06 +00001788 if not hasattr(os, 'utime'):
Tim Petersf9347782003-03-07 15:36:41 +00001789 return
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001790 if sys.platform == "win32" and tarinfo.isdir():
1791 # According to msdn.microsoft.com, it is an error (EACCES)
1792 # to use utime() on directories.
1793 return
1794 try:
1795 os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
Guido van Rossumb940e112007-01-10 16:19:56 +00001796 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001797 raise ExtractError("could not change modification time")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001798
1799 #--------------------------------------------------------------------------
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001800 def next(self):
1801 """Return the next member of the archive as a TarInfo object, when
1802 TarFile is opened for reading. Return None if there is no more
1803 available.
1804 """
1805 self._check("ra")
1806 if self.firstmember is not None:
1807 m = self.firstmember
1808 self.firstmember = None
1809 return m
1810
1811 # Read the next block.
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00001812 self.fileobj.seek(self.offset)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001813 while True:
1814 buf = self.fileobj.read(BLOCKSIZE)
1815 if not buf:
1816 return None
Thomas Wouters477c8d52006-05-27 19:21:47 +00001817
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001818 try:
1819 tarinfo = TarInfo.frombuf(buf)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001820
Thomas Wouters477c8d52006-05-27 19:21:47 +00001821 # Set the TarInfo object's offset to the current position of the
1822 # TarFile and set self.offset to the position where the data blocks
1823 # should begin.
1824 tarinfo.offset = self.offset
1825 self.offset += BLOCKSIZE
1826
1827 tarinfo = self.proc_member(tarinfo)
1828
Guido van Rossumb940e112007-01-10 16:19:56 +00001829 except HeaderError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001830 if self.ignore_zeros:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001831 self._dbg(2, "0x%X: %s" % (self.offset, e))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001832 self.offset += BLOCKSIZE
1833 continue
1834 else:
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00001835 if self.offset == 0:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001836 raise ReadError(str(e))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001837 return None
1838 break
1839
Thomas Wouters477c8d52006-05-27 19:21:47 +00001840 # Some old tar programs represent a directory as a regular
1841 # file with a trailing slash.
1842 if tarinfo.isreg() and tarinfo.name.endswith("/"):
1843 tarinfo.type = DIRTYPE
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001844
Thomas Wouters477c8d52006-05-27 19:21:47 +00001845 # Directory names should have a '/' at the end.
1846 if tarinfo.isdir():
1847 tarinfo.name += "/"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001848
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001849 self.members.append(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001850 return tarinfo
1851
1852 #--------------------------------------------------------------------------
Thomas Wouters477c8d52006-05-27 19:21:47 +00001853 # The following are methods that are called depending on the type of a
1854 # member. The entry point is proc_member() which is called with a TarInfo
1855 # object created from the header block from the current offset. The
1856 # proc_member() method can be overridden in a subclass to add custom
1857 # proc_*() methods. A proc_*() method MUST implement the following
1858 # operations:
1859 # 1. Set tarinfo.offset_data to the position where the data blocks begin,
1860 # if there is data that follows.
1861 # 2. Set self.offset to the position where the next member's header will
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001862 # begin.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001863 # 3. Return tarinfo or another valid TarInfo object.
1864 def proc_member(self, tarinfo):
1865 """Choose the right processing method for tarinfo depending
1866 on its type and call it.
1867 """
1868 if tarinfo.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
1869 return self.proc_gnulong(tarinfo)
1870 elif tarinfo.type == GNUTYPE_SPARSE:
1871 return self.proc_sparse(tarinfo)
1872 else:
1873 return self.proc_builtin(tarinfo)
1874
1875 def proc_builtin(self, tarinfo):
1876 """Process a builtin type member or an unknown member
1877 which will be treated as a regular file.
1878 """
1879 tarinfo.offset_data = self.offset
1880 if tarinfo.isreg() or tarinfo.type not in SUPPORTED_TYPES:
1881 # Skip the following data blocks.
1882 self.offset += self._block(tarinfo.size)
1883 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001884
1885 def proc_gnulong(self, tarinfo):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001886 """Process the blocks that hold a GNU longname
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001887 or longlink member.
1888 """
1889 buf = ""
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001890 count = tarinfo.size
1891 while count > 0:
1892 block = self.fileobj.read(BLOCKSIZE)
1893 buf += block
1894 self.offset += BLOCKSIZE
1895 count -= BLOCKSIZE
1896
Thomas Wouters477c8d52006-05-27 19:21:47 +00001897 # Fetch the next header and process it.
1898 b = self.fileobj.read(BLOCKSIZE)
1899 t = TarInfo.frombuf(b)
1900 t.offset = self.offset
1901 self.offset += BLOCKSIZE
1902 next = self.proc_member(t)
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00001903
Thomas Wouters477c8d52006-05-27 19:21:47 +00001904 # Patch the TarInfo object from the next header with
1905 # the longname information.
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00001906 next.offset = tarinfo.offset
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001907 if tarinfo.type == GNUTYPE_LONGNAME:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001908 next.name = buf.rstrip(NUL)
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00001909 elif tarinfo.type == GNUTYPE_LONGLINK:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001910 next.linkname = buf.rstrip(NUL)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001911
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00001912 return next
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001913
1914 def proc_sparse(self, tarinfo):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001915 """Process a GNU sparse header plus extra headers.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001916 """
Thomas Wouters477c8d52006-05-27 19:21:47 +00001917 buf = tarinfo.buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001918 sp = _ringbuffer()
1919 pos = 386
Guido van Rossume2a383d2007-01-15 16:59:06 +00001920 lastpos = 0
1921 realpos = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001922 # There are 4 possible sparse structs in the
1923 # first header.
1924 for i in xrange(4):
1925 try:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001926 offset = nti(buf[pos:pos + 12])
1927 numbytes = nti(buf[pos + 12:pos + 24])
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001928 except ValueError:
1929 break
1930 if offset > lastpos:
1931 sp.append(_hole(lastpos, offset - lastpos))
1932 sp.append(_data(offset, numbytes, realpos))
1933 realpos += numbytes
1934 lastpos = offset + numbytes
1935 pos += 24
1936
1937 isextended = ord(buf[482])
Thomas Wouters477c8d52006-05-27 19:21:47 +00001938 origsize = nti(buf[483:495])
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001939
1940 # If the isextended flag is given,
1941 # there are extra headers to process.
1942 while isextended == 1:
1943 buf = self.fileobj.read(BLOCKSIZE)
1944 self.offset += BLOCKSIZE
1945 pos = 0
1946 for i in xrange(21):
1947 try:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001948 offset = nti(buf[pos:pos + 12])
1949 numbytes = nti(buf[pos + 12:pos + 24])
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001950 except ValueError:
1951 break
1952 if offset > lastpos:
1953 sp.append(_hole(lastpos, offset - lastpos))
1954 sp.append(_data(offset, numbytes, realpos))
1955 realpos += numbytes
1956 lastpos = offset + numbytes
1957 pos += 24
1958 isextended = ord(buf[504])
1959
1960 if lastpos < origsize:
1961 sp.append(_hole(lastpos, origsize - lastpos))
1962
1963 tarinfo.sparse = sp
1964
1965 tarinfo.offset_data = self.offset
1966 self.offset += self._block(tarinfo.size)
1967 tarinfo.size = origsize
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00001968
Thomas Wouters477c8d52006-05-27 19:21:47 +00001969 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001970
1971 #--------------------------------------------------------------------------
1972 # Little helper methods:
1973
1974 def _block(self, count):
1975 """Round up a byte count by BLOCKSIZE and return it,
1976 e.g. _block(834) => 1024.
1977 """
1978 blocks, remainder = divmod(count, BLOCKSIZE)
1979 if remainder:
1980 blocks += 1
1981 return blocks * BLOCKSIZE
1982
1983 def _getmember(self, name, tarinfo=None):
1984 """Find an archive member by name from bottom to top.
1985 If tarinfo is given, it is used as the starting point.
1986 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001987 # Ensure that all members have been loaded.
1988 members = self.getmembers()
1989
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001990 if tarinfo is None:
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001991 end = len(members)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001992 else:
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001993 end = members.index(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001994
1995 for i in xrange(end - 1, -1, -1):
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001996 if name == members[i].name:
1997 return members[i]
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00001998
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001999 def _load(self):
2000 """Read through the entire archive file and look for readable
2001 members.
2002 """
2003 while True:
2004 tarinfo = self.next()
2005 if tarinfo is None:
2006 break
2007 self._loaded = True
2008
2009 def _check(self, mode=None):
2010 """Check if TarFile is still open, and if the operation's mode
2011 corresponds to TarFile's mode.
2012 """
2013 if self.closed:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002014 raise IOError("%s is closed" % self.__class__.__name__)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002015 if mode is not None and self._mode not in mode:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002016 raise IOError("bad operation for mode %r" % self._mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002017
2018 def __iter__(self):
2019 """Provide an iterator object.
2020 """
2021 if self._loaded:
2022 return iter(self.members)
2023 else:
2024 return TarIter(self)
2025
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002026 def _dbg(self, level, msg):
2027 """Write debugging output to sys.stderr.
2028 """
2029 if level <= self.debug:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002030 print(msg, file=sys.stderr)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002031# class TarFile
2032
2033class TarIter:
2034 """Iterator Class.
2035
2036 for tarinfo in TarFile(...):
2037 suite...
2038 """
2039
2040 def __init__(self, tarfile):
2041 """Construct a TarIter object.
2042 """
2043 self.tarfile = tarfile
Martin v. Löwis637431b2005-03-03 23:12:42 +00002044 self.index = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002045 def __iter__(self):
2046 """Return iterator object.
2047 """
2048 return self
2049 def next(self):
2050 """Return the next item using TarFile's next() method.
2051 When all members have been read, set TarFile as _loaded.
2052 """
Martin v. Löwis637431b2005-03-03 23:12:42 +00002053 # Fix for SF #1100429: Under rare circumstances it can
2054 # happen that getmembers() is called during iteration,
2055 # which will cause TarIter to stop prematurely.
2056 if not self.tarfile._loaded:
2057 tarinfo = self.tarfile.next()
2058 if not tarinfo:
2059 self.tarfile._loaded = True
2060 raise StopIteration
2061 else:
2062 try:
2063 tarinfo = self.tarfile.members[self.index]
2064 except IndexError:
2065 raise StopIteration
2066 self.index += 1
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002067 return tarinfo
2068
2069# Helper classes for sparse file support
2070class _section:
2071 """Base class for _data and _hole.
2072 """
2073 def __init__(self, offset, size):
2074 self.offset = offset
2075 self.size = size
2076 def __contains__(self, offset):
2077 return self.offset <= offset < self.offset + self.size
2078
2079class _data(_section):
2080 """Represent a data section in a sparse file.
2081 """
2082 def __init__(self, offset, size, realpos):
2083 _section.__init__(self, offset, size)
2084 self.realpos = realpos
2085
2086class _hole(_section):
2087 """Represent a hole section in a sparse file.
2088 """
2089 pass
2090
2091class _ringbuffer(list):
2092 """Ringbuffer class which increases performance
2093 over a regular list.
2094 """
2095 def __init__(self):
2096 self.idx = 0
2097 def find(self, offset):
2098 idx = self.idx
2099 while True:
2100 item = self[idx]
2101 if offset in item:
2102 break
2103 idx += 1
2104 if idx == len(self):
2105 idx = 0
2106 if idx == self.idx:
2107 # End of File
2108 return None
2109 self.idx = idx
2110 return item
2111
2112#---------------------------------------------
2113# zipfile compatible TarFile class
2114#---------------------------------------------
2115TAR_PLAIN = 0 # zipfile.ZIP_STORED
2116TAR_GZIPPED = 8 # zipfile.ZIP_DEFLATED
2117class TarFileCompat:
2118 """TarFile class compatible with standard module zipfile's
2119 ZipFile class.
2120 """
2121 def __init__(self, file, mode="r", compression=TAR_PLAIN):
2122 if compression == TAR_PLAIN:
2123 self.tarfile = TarFile.taropen(file, mode)
2124 elif compression == TAR_GZIPPED:
2125 self.tarfile = TarFile.gzopen(file, mode)
2126 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002127 raise ValueError("unknown compression constant")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002128 if mode[0:1] == "r":
2129 members = self.tarfile.getmembers()
Raymond Hettingera1d09e22005-09-11 16:34:05 +00002130 for m in members:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002131 m.filename = m.name
2132 m.file_size = m.size
2133 m.date_time = time.gmtime(m.mtime)[:6]
2134 def namelist(self):
2135 return map(lambda m: m.name, self.infolist())
2136 def infolist(self):
2137 return filter(lambda m: m.type in REGULAR_TYPES,
2138 self.tarfile.getmembers())
2139 def printdir(self):
2140 self.tarfile.list()
2141 def testzip(self):
2142 return
2143 def getinfo(self, name):
2144 return self.tarfile.getmember(name)
2145 def read(self, name):
2146 return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
2147 def write(self, filename, arcname=None, compress_type=None):
2148 self.tarfile.add(filename, arcname)
2149 def writestr(self, zinfo, bytes):
Raymond Hettingera6172712004-12-31 19:15:26 +00002150 try:
2151 from cStringIO import StringIO
2152 except ImportError:
2153 from StringIO import StringIO
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002154 import calendar
2155 zinfo.name = zinfo.filename
2156 zinfo.size = zinfo.file_size
2157 zinfo.mtime = calendar.timegm(zinfo.date_time)
Raymond Hettingera6172712004-12-31 19:15:26 +00002158 self.tarfile.addfile(zinfo, StringIO(bytes))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002159 def close(self):
2160 self.tarfile.close()
2161#class TarFileCompat
2162
2163#--------------------
2164# exported functions
2165#--------------------
2166def is_tarfile(name):
2167 """Return True if name points to a tar archive that we
2168 are able to handle, else return False.
2169 """
2170 try:
2171 t = open(name)
2172 t.close()
2173 return True
2174 except TarError:
2175 return False
2176
2177open = TarFile.open