blob: a79e35ca6a22212d61c6374b19c1014afa905fda [file] [log] [blame]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001#!/usr/bin/env python
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002#-------------------------------------------------------------------
3# tarfile.py
4#-------------------------------------------------------------------
Christian Heimes9c1257e2007-11-04 11:37:22 +00005# Copyright (C) 2002 Lars Gustaebel <lars@gustaebel.de>
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00006# All rights reserved.
7#
8# Permission is hereby granted, free of charge, to any person
9# obtaining a copy of this software and associated documentation
10# files (the "Software"), to deal in the Software without
11# restriction, including without limitation the rights to use,
12# copy, modify, merge, publish, distribute, sublicense, and/or sell
13# copies of the Software, and to permit persons to whom the
14# Software is furnished to do so, subject to the following
15# conditions:
16#
17# The above copyright notice and this permission notice shall be
18# included in all copies or substantial portions of the Software.
19#
20# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27# OTHER DEALINGS IN THE SOFTWARE.
28#
29"""Read from and write to tar format archives.
30"""
31
32__version__ = "$Revision$"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000033
Guido van Rossumd8faa362007-04-27 19:54:29 +000034version = "0.9.0"
Guido van Rossum98297ee2007-11-06 21:34:58 +000035__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000036__date__ = "$Date$"
37__cvsid__ = "$Id$"
Guido van Rossum98297ee2007-11-06 21:34:58 +000038__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend."
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000039
40#---------
41# Imports
42#---------
43import sys
44import os
45import shutil
46import stat
47import errno
48import time
49import struct
Thomas Wouters89f507f2006-12-13 04:49:30 +000050import copy
Guido van Rossumd8faa362007-04-27 19:54:29 +000051import re
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000052
Jack Jansencfc49022003-03-07 13:37:32 +000053if sys.platform == 'mac':
54 # This module needs work for MacOS9, especially in the area of pathname
55 # handling. In many places it is assumed a simple substitution of / by the
56 # local os.path.sep is good enough to convert pathnames, but this does not
57 # work with the mac rooted:path:name versus :nonrooted:path:name syntax
Collin Winterce36ad82007-08-30 01:19:48 +000058 raise ImportError("tarfile does not work for platform==mac")
Jack Jansencfc49022003-03-07 13:37:32 +000059
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000060try:
61 import grp, pwd
62except ImportError:
63 grp = pwd = None
64
65# from tarfile import *
66__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"]
67
Georg Brandl1a3284e2007-12-02 09:40:06 +000068from builtins import open as _open # Since 'open' is TarFile.open
Guido van Rossum8f78fe92006-08-24 04:03:53 +000069
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000070#---------------------------------------------------------
71# tar constants
72#---------------------------------------------------------
Lars Gustäbelb506dc32007-08-07 18:36:16 +000073NUL = b"\0" # the null character
Guido van Rossumd8faa362007-04-27 19:54:29 +000074BLOCKSIZE = 512 # length of processing blocks
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000075RECORDSIZE = BLOCKSIZE * 20 # length of records
Lars Gustäbelb506dc32007-08-07 18:36:16 +000076GNU_MAGIC = b"ustar \0" # magic gnu tar string
77POSIX_MAGIC = b"ustar\x0000" # magic posix tar string
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000078
Guido van Rossumd8faa362007-04-27 19:54:29 +000079LENGTH_NAME = 100 # maximum length of a filename
80LENGTH_LINK = 100 # maximum length of a linkname
81LENGTH_PREFIX = 155 # maximum length of the prefix field
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000082
Lars Gustäbelb506dc32007-08-07 18:36:16 +000083REGTYPE = b"0" # regular file
84AREGTYPE = b"\0" # regular file
85LNKTYPE = b"1" # link (inside tarfile)
86SYMTYPE = b"2" # symbolic link
87CHRTYPE = b"3" # character special device
88BLKTYPE = b"4" # block special device
89DIRTYPE = b"5" # directory
90FIFOTYPE = b"6" # fifo special device
91CONTTYPE = b"7" # contiguous file
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000092
Lars Gustäbelb506dc32007-08-07 18:36:16 +000093GNUTYPE_LONGNAME = b"L" # GNU tar longname
94GNUTYPE_LONGLINK = b"K" # GNU tar longlink
95GNUTYPE_SPARSE = b"S" # GNU tar sparse file
Guido van Rossumd8faa362007-04-27 19:54:29 +000096
Lars Gustäbelb506dc32007-08-07 18:36:16 +000097XHDTYPE = b"x" # POSIX.1-2001 extended header
98XGLTYPE = b"g" # POSIX.1-2001 global header
99SOLARIS_XHDTYPE = b"X" # Solaris extended header
Guido van Rossumd8faa362007-04-27 19:54:29 +0000100
101USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format
102GNU_FORMAT = 1 # GNU tar format
103PAX_FORMAT = 2 # POSIX.1-2001 (pax) format
104DEFAULT_FORMAT = GNU_FORMAT
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000105
106#---------------------------------------------------------
107# tarfile constants
108#---------------------------------------------------------
Guido van Rossumd8faa362007-04-27 19:54:29 +0000109# File types that tarfile supports:
110SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE,
111 SYMTYPE, DIRTYPE, FIFOTYPE,
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000112 CONTTYPE, CHRTYPE, BLKTYPE,
113 GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
114 GNUTYPE_SPARSE)
115
Guido van Rossumd8faa362007-04-27 19:54:29 +0000116# File types that will be treated as a regular file.
117REGULAR_TYPES = (REGTYPE, AREGTYPE,
118 CONTTYPE, GNUTYPE_SPARSE)
119
120# File types that are part of the GNU tar format.
121GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
122 GNUTYPE_SPARSE)
123
124# Fields from a pax header that override a TarInfo attribute.
125PAX_FIELDS = ("path", "linkpath", "size", "mtime",
126 "uid", "gid", "uname", "gname")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000127
Guido van Rossume7ba4952007-06-06 23:52:48 +0000128# Fields in a pax header that are numbers, all other fields
129# are treated as strings.
130PAX_NUMBER_FIELDS = {
131 "atime": float,
132 "ctime": float,
133 "mtime": float,
134 "uid": int,
135 "gid": int,
136 "size": int
137}
138
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000139#---------------------------------------------------------
140# Bits used in the mode field, values in octal.
141#---------------------------------------------------------
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000142S_IFLNK = 0o120000 # symbolic link
143S_IFREG = 0o100000 # regular file
144S_IFBLK = 0o060000 # block device
145S_IFDIR = 0o040000 # directory
146S_IFCHR = 0o020000 # character device
147S_IFIFO = 0o010000 # fifo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000148
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000149TSUID = 0o4000 # set UID on execution
150TSGID = 0o2000 # set GID on execution
151TSVTX = 0o1000 # reserved
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000152
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000153TUREAD = 0o400 # read by owner
154TUWRITE = 0o200 # write by owner
155TUEXEC = 0o100 # execute/search by owner
156TGREAD = 0o040 # read by group
157TGWRITE = 0o020 # write by group
158TGEXEC = 0o010 # execute/search by group
159TOREAD = 0o004 # read by other
160TOWRITE = 0o002 # write by other
161TOEXEC = 0o001 # execute/search by other
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000162
163#---------------------------------------------------------
Guido van Rossumd8faa362007-04-27 19:54:29 +0000164# initialization
165#---------------------------------------------------------
166ENCODING = sys.getfilesystemencoding()
167if ENCODING is None:
Lars Gustäbel3741eff2007-08-21 12:17:05 +0000168 ENCODING = "ascii"
Guido van Rossumd8faa362007-04-27 19:54:29 +0000169
170#---------------------------------------------------------
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000171# Some useful functions
172#---------------------------------------------------------
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000173
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000174def stn(s, length, encoding, errors):
175 """Convert a string to a null-terminated bytes object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000176 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000177 s = s.encode(encoding, errors)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000178 return s[:length] + (length - len(s)) * NUL
Thomas Wouters477c8d52006-05-27 19:21:47 +0000179
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000180def nts(s, encoding, errors):
181 """Convert a null-terminated bytes object to a string.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000182 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000183 p = s.find(b"\0")
184 if p != -1:
185 s = s[:p]
186 return s.decode(encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000187
Thomas Wouters477c8d52006-05-27 19:21:47 +0000188def nti(s):
189 """Convert a number field to a python number.
190 """
191 # There are two possible encodings for a number field, see
192 # itn() below.
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000193 if s[0] != chr(0o200):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000194 try:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000195 n = int(nts(s, "ascii", "strict") or "0", 8)
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000196 except ValueError:
197 raise HeaderError("invalid header")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000198 else:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000199 n = 0
Guido van Rossum805365e2007-05-07 22:24:25 +0000200 for i in range(len(s) - 1):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000201 n <<= 8
202 n += ord(s[i + 1])
203 return n
204
Guido van Rossumd8faa362007-04-27 19:54:29 +0000205def itn(n, digits=8, format=DEFAULT_FORMAT):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000206 """Convert a python number to a number field.
207 """
208 # POSIX 1003.1-1988 requires numbers to be encoded as a string of
209 # octal digits followed by a null-byte, this allows values up to
210 # (8**(digits-1))-1. GNU tar allows storing numbers greater than
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000211 # that if necessary. A leading 0o200 byte indicates this particular
Thomas Wouters477c8d52006-05-27 19:21:47 +0000212 # encoding, the following digits-1 bytes are a big-endian
213 # representation. This allows values up to (256**(digits-1))-1.
214 if 0 <= n < 8 ** (digits - 1):
Lars Gustäbela280ca752007-08-28 07:34:33 +0000215 s = bytes("%0*o" % (digits - 1, n), "ascii") + NUL
Thomas Wouters477c8d52006-05-27 19:21:47 +0000216 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000217 if format != GNU_FORMAT or n >= 256 ** (digits - 1):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000218 raise ValueError("overflow in number field")
219
220 if n < 0:
221 # XXX We mimic GNU tar's behaviour with negative numbers,
222 # this could raise OverflowError.
223 n = struct.unpack("L", struct.pack("l", n))[0]
224
Guido van Rossum254348e2007-11-21 19:29:53 +0000225 s = bytearray()
Guido van Rossum805365e2007-05-07 22:24:25 +0000226 for i in range(digits - 1):
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000227 s.insert(0, n & 0o377)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000228 n >>= 8
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000229 s.insert(0, 0o200)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000230 return s
231
232def calc_chksums(buf):
233 """Calculate the checksum for a member's header by summing up all
234 characters except for the chksum field which is treated as if
235 it was filled with spaces. According to the GNU tar sources,
236 some tars (Sun and NeXT) calculate chksum with signed char,
237 which will be different if there are chars in the buffer with
238 the high bit set. So we calculate two checksums, unsigned and
239 signed.
240 """
241 unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512]))
242 signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512]))
243 return unsigned_chksum, signed_chksum
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000244
245def copyfileobj(src, dst, length=None):
246 """Copy length bytes from fileobj src to fileobj dst.
247 If length is None, copy the entire content.
248 """
249 if length == 0:
250 return
251 if length is None:
252 shutil.copyfileobj(src, dst)
253 return
254
255 BUFSIZE = 16 * 1024
256 blocks, remainder = divmod(length, BUFSIZE)
Guido van Rossum805365e2007-05-07 22:24:25 +0000257 for b in range(blocks):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000258 buf = src.read(BUFSIZE)
259 if len(buf) < BUFSIZE:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000260 raise IOError("end of file reached")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000261 dst.write(buf)
262
263 if remainder != 0:
264 buf = src.read(remainder)
265 if len(buf) < remainder:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000266 raise IOError("end of file reached")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000267 dst.write(buf)
268 return
269
270filemode_table = (
Andrew M. Kuchling8bc462f2004-10-20 11:48:42 +0000271 ((S_IFLNK, "l"),
272 (S_IFREG, "-"),
273 (S_IFBLK, "b"),
274 (S_IFDIR, "d"),
275 (S_IFCHR, "c"),
276 (S_IFIFO, "p")),
277
278 ((TUREAD, "r"),),
279 ((TUWRITE, "w"),),
280 ((TUEXEC|TSUID, "s"),
281 (TSUID, "S"),
282 (TUEXEC, "x")),
283
284 ((TGREAD, "r"),),
285 ((TGWRITE, "w"),),
286 ((TGEXEC|TSGID, "s"),
287 (TSGID, "S"),
288 (TGEXEC, "x")),
289
290 ((TOREAD, "r"),),
291 ((TOWRITE, "w"),),
292 ((TOEXEC|TSVTX, "t"),
293 (TSVTX, "T"),
294 (TOEXEC, "x"))
295)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000296
297def filemode(mode):
298 """Convert a file's mode to a string of the form
299 -rwxrwxrwx.
300 Used by TarFile.list()
301 """
Andrew M. Kuchling8bc462f2004-10-20 11:48:42 +0000302 perm = []
303 for table in filemode_table:
304 for bit, char in table:
305 if mode & bit == bit:
306 perm.append(char)
307 break
308 else:
309 perm.append("-")
310 return "".join(perm)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000311
312if os.sep != "/":
313 normpath = lambda path: os.path.normpath(path).replace(os.sep, "/")
314else:
315 normpath = os.path.normpath
316
317class TarError(Exception):
318 """Base exception."""
319 pass
320class ExtractError(TarError):
321 """General exception for extract errors."""
322 pass
323class ReadError(TarError):
324 """Exception for unreadble tar archives."""
325 pass
326class CompressionError(TarError):
327 """Exception for unavailable compression methods."""
328 pass
329class StreamError(TarError):
330 """Exception for unsupported operations on stream-like TarFiles."""
331 pass
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000332class HeaderError(TarError):
333 """Exception for invalid headers."""
334 pass
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000335
336#---------------------------
337# internal stream interface
338#---------------------------
339class _LowLevelFile:
340 """Low-level file object. Supports reading and writing.
341 It is used instead of a regular file object for streaming
342 access.
343 """
344
345 def __init__(self, name, mode):
346 mode = {
347 "r": os.O_RDONLY,
348 "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
349 }[mode]
350 if hasattr(os, "O_BINARY"):
351 mode |= os.O_BINARY
352 self.fd = os.open(name, mode)
353
354 def close(self):
355 os.close(self.fd)
356
357 def read(self, size):
358 return os.read(self.fd, size)
359
360 def write(self, s):
361 os.write(self.fd, s)
362
363class _Stream:
364 """Class that serves as an adapter between TarFile and
365 a stream-like object. The stream-like object only
366 needs to have a read() or write() method and is accessed
367 blockwise. Use of gzip or bzip2 compression is possible.
368 A stream-like object could be for example: sys.stdin,
369 sys.stdout, a socket, a tape device etc.
370
371 _Stream is intended to be used only internally.
372 """
373
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000374 def __init__(self, name, mode, comptype, fileobj, bufsize):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000375 """Construct a _Stream object.
376 """
377 self._extfileobj = True
378 if fileobj is None:
379 fileobj = _LowLevelFile(name, mode)
380 self._extfileobj = False
381
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000382 if comptype == '*':
383 # Enable transparent compression detection for the
384 # stream interface
385 fileobj = _StreamProxy(fileobj)
386 comptype = fileobj.getcomptype()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000387
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000388 self.name = name or ""
389 self.mode = mode
390 self.comptype = comptype
391 self.fileobj = fileobj
392 self.bufsize = bufsize
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000393 self.buf = b""
Guido van Rossume2a383d2007-01-15 16:59:06 +0000394 self.pos = 0
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000395 self.closed = False
396
397 if comptype == "gz":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000398 try:
399 import zlib
400 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000401 raise CompressionError("zlib module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000402 self.zlib = zlib
403 self.crc = zlib.crc32("")
404 if mode == "r":
405 self._init_read_gz()
406 else:
407 self._init_write_gz()
408
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000409 if comptype == "bz2":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000410 try:
411 import bz2
412 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000413 raise CompressionError("bz2 module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000414 if mode == "r":
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000415 self.dbuf = b""
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000416 self.cmp = bz2.BZ2Decompressor()
417 else:
418 self.cmp = bz2.BZ2Compressor()
419
420 def __del__(self):
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000421 if hasattr(self, "closed") and not self.closed:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000422 self.close()
423
424 def _init_write_gz(self):
425 """Initialize for writing with gzip compression.
426 """
427 self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED,
428 -self.zlib.MAX_WBITS,
429 self.zlib.DEF_MEM_LEVEL,
430 0)
Guido van Rossume2a383d2007-01-15 16:59:06 +0000431 timestamp = struct.pack("<L", int(time.time()))
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000432 self.__write(b"\037\213\010\010" + timestamp + b"\002\377")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000433 if self.name.endswith(".gz"):
434 self.name = self.name[:-3]
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000435 # RFC1952 says we must use ISO-8859-1 for the FNAME field.
436 self.__write(self.name.encode("iso-8859-1", "replace") + NUL)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000437
438 def write(self, s):
439 """Write string s to the stream.
440 """
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000441 if self.comptype == "gz":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000442 self.crc = self.zlib.crc32(s, self.crc)
443 self.pos += len(s)
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000444 if self.comptype != "tar":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000445 s = self.cmp.compress(s)
446 self.__write(s)
447
448 def __write(self, s):
449 """Write string s to the stream if a whole new block
450 is ready to be written.
451 """
452 self.buf += s
453 while len(self.buf) > self.bufsize:
454 self.fileobj.write(self.buf[:self.bufsize])
455 self.buf = self.buf[self.bufsize:]
456
457 def close(self):
458 """Close the _Stream object. No operation should be
459 done on it afterwards.
460 """
461 if self.closed:
462 return
463
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000464 if self.mode == "w" and self.comptype != "tar":
Martin v. Löwisc234a522004-08-22 21:28:33 +0000465 self.buf += self.cmp.flush()
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000466
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000467 if self.mode == "w" and self.buf:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000468 self.fileobj.write(self.buf)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000469 self.buf = b""
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000470 if self.comptype == "gz":
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000471 # The native zlib crc is an unsigned 32-bit integer, but
472 # the Python wrapper implicitly casts that to a signed C
473 # long. So, on a 32-bit box self.crc may "look negative",
474 # while the same crc on a 64-bit box may "look positive".
475 # To avoid irksome warnings from the `struct` module, force
476 # it to look positive on all boxes.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000477 self.fileobj.write(struct.pack("<L", self.crc & 0xffffffff))
478 self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFF))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000479
480 if not self._extfileobj:
481 self.fileobj.close()
482
483 self.closed = True
484
485 def _init_read_gz(self):
486 """Initialize for reading a gzip compressed fileobj.
487 """
488 self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000489 self.dbuf = b""
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000490
491 # taken from gzip.GzipFile with some alterations
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000492 if self.__read(2) != b"\037\213":
Thomas Wouters477c8d52006-05-27 19:21:47 +0000493 raise ReadError("not a gzip file")
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000494 if self.__read(1) != b"\010":
Thomas Wouters477c8d52006-05-27 19:21:47 +0000495 raise CompressionError("unsupported compression method")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000496
497 flag = ord(self.__read(1))
498 self.__read(6)
499
500 if flag & 4:
501 xlen = ord(self.__read(1)) + 256 * ord(self.__read(1))
502 self.read(xlen)
503 if flag & 8:
504 while True:
505 s = self.__read(1)
506 if not s or s == NUL:
507 break
508 if flag & 16:
509 while True:
510 s = self.__read(1)
511 if not s or s == NUL:
512 break
513 if flag & 2:
514 self.__read(2)
515
516 def tell(self):
517 """Return the stream's file pointer position.
518 """
519 return self.pos
520
521 def seek(self, pos=0):
522 """Set the stream's file pointer to pos. Negative seeking
523 is forbidden.
524 """
525 if pos - self.pos >= 0:
526 blocks, remainder = divmod(pos - self.pos, self.bufsize)
Guido van Rossum805365e2007-05-07 22:24:25 +0000527 for i in range(blocks):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000528 self.read(self.bufsize)
529 self.read(remainder)
530 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000531 raise StreamError("seeking backwards is not allowed")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000532 return self.pos
533
534 def read(self, size=None):
535 """Return the next size number of bytes from the stream.
536 If size is not defined, return all bytes of the stream
537 up to EOF.
538 """
539 if size is None:
540 t = []
541 while True:
542 buf = self._read(self.bufsize)
543 if not buf:
544 break
545 t.append(buf)
546 buf = "".join(t)
547 else:
548 buf = self._read(size)
549 self.pos += len(buf)
550 return buf
551
552 def _read(self, size):
553 """Return size bytes from the stream.
554 """
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000555 if self.comptype == "tar":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000556 return self.__read(size)
557
558 c = len(self.dbuf)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000559 while c < size:
560 buf = self.__read(self.bufsize)
561 if not buf:
562 break
Guido van Rossumd8faa362007-04-27 19:54:29 +0000563 try:
564 buf = self.cmp.decompress(buf)
565 except IOError:
566 raise ReadError("invalid compressed data")
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000567 self.dbuf += buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000568 c += len(buf)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000569 buf = self.dbuf[:size]
570 self.dbuf = self.dbuf[size:]
571 return buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000572
573 def __read(self, size):
574 """Return size bytes from stream. If internal buffer is empty,
575 read another block from the stream.
576 """
577 c = len(self.buf)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000578 while c < size:
579 buf = self.fileobj.read(self.bufsize)
580 if not buf:
581 break
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000582 self.buf += buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000583 c += len(buf)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000584 buf = self.buf[:size]
585 self.buf = self.buf[size:]
586 return buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000587# class _Stream
588
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000589class _StreamProxy(object):
590 """Small proxy class that enables transparent compression
591 detection for the Stream interface (mode 'r|*').
592 """
593
594 def __init__(self, fileobj):
595 self.fileobj = fileobj
596 self.buf = self.fileobj.read(BLOCKSIZE)
597
598 def read(self, size):
599 self.read = self.fileobj.read
600 return self.buf
601
602 def getcomptype(self):
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000603 if self.buf.startswith(b"\037\213\010"):
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000604 return "gz"
Lars Gustäbela280ca752007-08-28 07:34:33 +0000605 if self.buf.startswith(b"BZh91"):
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000606 return "bz2"
607 return "tar"
608
609 def close(self):
610 self.fileobj.close()
611# class StreamProxy
612
Thomas Wouters477c8d52006-05-27 19:21:47 +0000613class _BZ2Proxy(object):
614 """Small proxy class that enables external file object
615 support for "r:bz2" and "w:bz2" modes. This is actually
616 a workaround for a limitation in bz2 module's BZ2File
617 class which (unlike gzip.GzipFile) has no support for
618 a file object argument.
619 """
620
621 blocksize = 16 * 1024
622
623 def __init__(self, fileobj, mode):
624 self.fileobj = fileobj
625 self.mode = mode
Guido van Rossumd8faa362007-04-27 19:54:29 +0000626 self.name = getattr(self.fileobj, "name", None)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000627 self.init()
628
629 def init(self):
630 import bz2
631 self.pos = 0
632 if self.mode == "r":
633 self.bz2obj = bz2.BZ2Decompressor()
634 self.fileobj.seek(0)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000635 self.buf = b""
Thomas Wouters477c8d52006-05-27 19:21:47 +0000636 else:
637 self.bz2obj = bz2.BZ2Compressor()
638
639 def read(self, size):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000640 x = len(self.buf)
641 while x < size:
642 try:
643 raw = self.fileobj.read(self.blocksize)
644 data = self.bz2obj.decompress(raw)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000645 self.buf += data
Thomas Wouters477c8d52006-05-27 19:21:47 +0000646 except EOFError:
647 break
648 x += len(data)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000649
650 buf = self.buf[:size]
651 self.buf = self.buf[size:]
652 self.pos += len(buf)
653 return buf
654
655 def seek(self, pos):
656 if pos < self.pos:
657 self.init()
658 self.read(pos - self.pos)
659
660 def tell(self):
661 return self.pos
662
663 def write(self, data):
664 self.pos += len(data)
665 raw = self.bz2obj.compress(data)
666 self.fileobj.write(raw)
667
668 def close(self):
669 if self.mode == "w":
670 raw = self.bz2obj.flush()
671 self.fileobj.write(raw)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000672# class _BZ2Proxy
673
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000674#------------------------
675# Extraction file object
676#------------------------
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000677class _FileInFile(object):
678 """A thin wrapper around an existing file object that
679 provides a part of its data as an individual file
680 object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000681 """
682
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000683 def __init__(self, fileobj, offset, size, sparse=None):
684 self.fileobj = fileobj
685 self.offset = offset
686 self.size = size
687 self.sparse = sparse
688 self.position = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000689
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000690 def seekable(self):
691 if not hasattr(self.fileobj, "seekable"):
692 # XXX gzip.GzipFile and bz2.BZ2File
693 return True
694 return self.fileobj.seekable()
695
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000696 def tell(self):
697 """Return the current file position.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000698 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000699 return self.position
700
701 def seek(self, position):
702 """Seek to a position in the file.
703 """
704 self.position = position
705
706 def read(self, size=None):
707 """Read data from the file.
708 """
709 if size is None:
710 size = self.size - self.position
711 else:
712 size = min(size, self.size - self.position)
713
714 if self.sparse is None:
715 return self.readnormal(size)
716 else:
717 return self.readsparse(size)
718
719 def readnormal(self, size):
720 """Read operation for regular files.
721 """
722 self.fileobj.seek(self.offset + self.position)
723 self.position += size
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000724 return self.fileobj.read(size)
725
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000726 def readsparse(self, size):
727 """Read operation for sparse files.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000728 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000729 data = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000730 while size > 0:
731 buf = self.readsparsesection(size)
732 if not buf:
733 break
734 size -= len(buf)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000735 data += buf
736 return data
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000737
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000738 def readsparsesection(self, size):
739 """Read a single section of a sparse file.
740 """
741 section = self.sparse.find(self.position)
742
743 if section is None:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000744 return b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000745
746 size = min(size, section.offset + section.size - self.position)
747
748 if isinstance(section, _data):
749 realpos = section.realpos + self.position - section.offset
750 self.fileobj.seek(self.offset + realpos)
751 self.position += size
752 return self.fileobj.read(size)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000753 else:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000754 self.position += size
755 return NUL * size
756#class _FileInFile
757
758
759class ExFileObject(object):
760 """File-like object for reading an archive member.
761 Is returned by TarFile.extractfile().
762 """
763 blocksize = 1024
764
765 def __init__(self, tarfile, tarinfo):
766 self.fileobj = _FileInFile(tarfile.fileobj,
767 tarinfo.offset_data,
768 tarinfo.size,
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +0000769 tarinfo.sparse)
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000770 self.name = tarinfo.name
771 self.mode = "r"
772 self.closed = False
773 self.size = tarinfo.size
774
775 self.position = 0
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000776 self.buffer = b""
777
778 def readable(self):
779 return True
780
781 def writable(self):
782 return False
783
784 def seekable(self):
785 return self.fileobj.seekable()
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000786
787 def read(self, size=None):
788 """Read at most size bytes from the file. If size is not
789 present or None, read all data until EOF is reached.
790 """
791 if self.closed:
792 raise ValueError("I/O operation on closed file")
793
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000794 buf = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000795 if self.buffer:
796 if size is None:
797 buf = self.buffer
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000798 self.buffer = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000799 else:
800 buf = self.buffer[:size]
801 self.buffer = self.buffer[size:]
802
803 if size is None:
804 buf += self.fileobj.read()
805 else:
806 buf += self.fileobj.read(size - len(buf))
807
808 self.position += len(buf)
809 return buf
810
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000811 # XXX TextIOWrapper uses the read1() method.
812 read1 = read
813
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000814 def readline(self, size=-1):
815 """Read one entire line from the file. If size is present
816 and non-negative, return a string with at most that
817 size, which may be an incomplete line.
818 """
819 if self.closed:
820 raise ValueError("I/O operation on closed file")
821
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000822 pos = self.buffer.find(b"\n") + 1
823 if pos == 0:
824 # no newline found.
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000825 while True:
826 buf = self.fileobj.read(self.blocksize)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000827 self.buffer += buf
828 if not buf or b"\n" in buf:
829 pos = self.buffer.find(b"\n") + 1
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000830 if pos == 0:
831 # no newline found.
832 pos = len(self.buffer)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000833 break
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000834
835 if size != -1:
836 pos = min(size, pos)
837
838 buf = self.buffer[:pos]
839 self.buffer = self.buffer[pos:]
840 self.position += len(buf)
841 return buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000842
843 def readlines(self):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000844 """Return a list with all remaining lines.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000845 """
846 result = []
847 while True:
848 line = self.readline()
849 if not line: break
850 result.append(line)
851 return result
852
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000853 def tell(self):
854 """Return the current file position.
855 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000856 if self.closed:
857 raise ValueError("I/O operation on closed file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000858
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000859 return self.position
860
861 def seek(self, pos, whence=os.SEEK_SET):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000862 """Seek to a position in the file.
863 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000864 if self.closed:
865 raise ValueError("I/O operation on closed file")
866
867 if whence == os.SEEK_SET:
868 self.position = min(max(pos, 0), self.size)
869 elif whence == os.SEEK_CUR:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000870 if pos < 0:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000871 self.position = max(self.position + pos, 0)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000872 else:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000873 self.position = min(self.position + pos, self.size)
874 elif whence == os.SEEK_END:
875 self.position = max(min(self.size + pos, self.size), 0)
876 else:
877 raise ValueError("Invalid argument")
878
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000879 self.buffer = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000880 self.fileobj.seek(self.position)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000881
882 def close(self):
883 """Close the file object.
884 """
885 self.closed = True
Martin v. Löwisdf241532005-03-03 08:17:42 +0000886
887 def __iter__(self):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000888 """Get an iterator over the file's lines.
Martin v. Löwisdf241532005-03-03 08:17:42 +0000889 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000890 while True:
891 line = self.readline()
892 if not line:
893 break
894 yield line
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000895#class ExFileObject
896
897#------------------
898# Exported Classes
899#------------------
900class TarInfo(object):
901 """Informational class which holds the details about an
902 archive member given by a tar header block.
903 TarInfo objects are returned by TarFile.getmember(),
904 TarFile.getmembers() and TarFile.gettarinfo() and are
905 usually created internally.
906 """
907
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +0000908 __slots__ = ("name", "mode", "uid", "gid", "size", "mtime",
909 "chksum", "type", "linkname", "uname", "gname",
910 "devmajor", "devminor",
911 "offset", "offset_data", "pax_headers", "sparse",
912 "tarfile", "_sparse_structs", "_link_target")
913
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000914 def __init__(self, name=""):
915 """Construct a TarInfo object. name is the optional name
916 of the member.
917 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000918 self.name = name # member name
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000919 self.mode = 0o644 # file permissions
Thomas Wouters477c8d52006-05-27 19:21:47 +0000920 self.uid = 0 # user id
921 self.gid = 0 # group id
922 self.size = 0 # file size
923 self.mtime = 0 # modification time
924 self.chksum = 0 # header checksum
925 self.type = REGTYPE # member type
926 self.linkname = "" # link name
Guido van Rossumd8faa362007-04-27 19:54:29 +0000927 self.uname = "root" # user name
928 self.gname = "root" # group name
Thomas Wouters477c8d52006-05-27 19:21:47 +0000929 self.devmajor = 0 # device major number
930 self.devminor = 0 # device minor number
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000931
Thomas Wouters477c8d52006-05-27 19:21:47 +0000932 self.offset = 0 # the tar header starts here
933 self.offset_data = 0 # the file's data starts here
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000934
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +0000935 self.sparse = None # sparse member information
Guido van Rossumd8faa362007-04-27 19:54:29 +0000936 self.pax_headers = {} # pax header information
937
938 # In pax headers the "name" and "linkname" field are called
939 # "path" and "linkpath".
940 def _getpath(self):
941 return self.name
942 def _setpath(self, name):
943 self.name = name
944 path = property(_getpath, _setpath)
945
946 def _getlinkpath(self):
947 return self.linkname
948 def _setlinkpath(self, linkname):
949 self.linkname = linkname
950 linkpath = property(_getlinkpath, _setlinkpath)
951
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000952 def __repr__(self):
953 return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self))
954
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000955 def get_info(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000956 """Return the TarInfo's attributes as a dictionary.
957 """
958 info = {
959 "name": normpath(self.name),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000960 "mode": self.mode & 0o7777,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000961 "uid": self.uid,
962 "gid": self.gid,
963 "size": self.size,
964 "mtime": self.mtime,
965 "chksum": self.chksum,
966 "type": self.type,
967 "linkname": normpath(self.linkname) if self.linkname else "",
968 "uname": self.uname,
969 "gname": self.gname,
970 "devmajor": self.devmajor,
971 "devminor": self.devminor
972 }
973
974 if info["type"] == DIRTYPE and not info["name"].endswith("/"):
975 info["name"] += "/"
976
977 return info
978
Guido van Rossume7ba4952007-06-06 23:52:48 +0000979 def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="strict"):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000980 """Return a tar header as a string of 512 byte blocks.
981 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000982 info = self.get_info()
Guido van Rossume7ba4952007-06-06 23:52:48 +0000983
Guido van Rossumd8faa362007-04-27 19:54:29 +0000984 if format == USTAR_FORMAT:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000985 return self.create_ustar_header(info, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000986 elif format == GNU_FORMAT:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000987 return self.create_gnu_header(info, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000988 elif format == PAX_FORMAT:
Lars Gustäbel3741eff2007-08-21 12:17:05 +0000989 return self.create_pax_header(info)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000990 else:
991 raise ValueError("invalid format")
992
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000993 def create_ustar_header(self, info, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000994 """Return the object as a ustar header block.
995 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000996 info["magic"] = POSIX_MAGIC
997
998 if len(info["linkname"]) > LENGTH_LINK:
999 raise ValueError("linkname is too long")
1000
1001 if len(info["name"]) > LENGTH_NAME:
1002 info["prefix"], info["name"] = self._posix_split_name(info["name"])
1003
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001004 return self._create_header(info, USTAR_FORMAT, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001005
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001006 def create_gnu_header(self, info, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001007 """Return the object as a GNU header block sequence.
1008 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001009 info["magic"] = GNU_MAGIC
1010
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001011 buf = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001012 if len(info["linkname"]) > LENGTH_LINK:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001013 buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001014
1015 if len(info["name"]) > LENGTH_NAME:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001016 buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001017
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001018 return buf + self._create_header(info, GNU_FORMAT, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001019
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001020 def create_pax_header(self, info):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001021 """Return the object as a ustar header block. If it cannot be
1022 represented this way, prepend a pax extended header sequence
1023 with supplement information.
1024 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001025 info["magic"] = POSIX_MAGIC
1026 pax_headers = self.pax_headers.copy()
1027
1028 # Test string fields for values that exceed the field length or cannot
1029 # be represented in ASCII encoding.
1030 for name, hname, length in (
1031 ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK),
1032 ("uname", "uname", 32), ("gname", "gname", 32)):
1033
Guido van Rossume7ba4952007-06-06 23:52:48 +00001034 if hname in pax_headers:
1035 # The pax header has priority.
1036 continue
1037
Guido van Rossumd8faa362007-04-27 19:54:29 +00001038 # Try to encode the string as ASCII.
1039 try:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001040 info[name].encode("ascii", "strict")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001041 except UnicodeEncodeError:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001042 pax_headers[hname] = info[name]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001043 continue
1044
Guido van Rossume7ba4952007-06-06 23:52:48 +00001045 if len(info[name]) > length:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001046 pax_headers[hname] = info[name]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001047
1048 # Test number fields for values that exceed the field limit or values
1049 # that like to be stored as float.
1050 for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)):
Guido van Rossume7ba4952007-06-06 23:52:48 +00001051 if name in pax_headers:
1052 # The pax header has priority. Avoid overflow.
1053 info[name] = 0
1054 continue
1055
Guido van Rossumd8faa362007-04-27 19:54:29 +00001056 val = info[name]
1057 if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float):
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001058 pax_headers[name] = str(val)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001059 info[name] = 0
1060
Guido van Rossume7ba4952007-06-06 23:52:48 +00001061 # Create a pax extended header if necessary.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001062 if pax_headers:
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001063 buf = self._create_pax_generic_header(pax_headers, XHDTYPE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001064 else:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001065 buf = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001066
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001067 return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001068
1069 @classmethod
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001070 def create_pax_global_header(cls, pax_headers):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001071 """Return the object as a pax global header block sequence.
1072 """
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001073 return cls._create_pax_generic_header(pax_headers, XGLTYPE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001074
1075 def _posix_split_name(self, name):
1076 """Split a name longer than 100 chars into a prefix
1077 and a name part.
1078 """
1079 prefix = name[:LENGTH_PREFIX + 1]
1080 while prefix and prefix[-1] != "/":
1081 prefix = prefix[:-1]
1082
1083 name = name[len(prefix):]
1084 prefix = prefix[:-1]
1085
1086 if not prefix or len(name) > LENGTH_NAME:
1087 raise ValueError("name is too long")
1088 return prefix, name
1089
1090 @staticmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001091 def _create_header(info, format, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001092 """Return a header block. info is a dictionary with file
1093 information, format must be one of the *_FORMAT constants.
1094 """
1095 parts = [
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001096 stn(info.get("name", ""), 100, encoding, errors),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001097 itn(info.get("mode", 0) & 0o7777, 8, format),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001098 itn(info.get("uid", 0), 8, format),
1099 itn(info.get("gid", 0), 8, format),
1100 itn(info.get("size", 0), 12, format),
1101 itn(info.get("mtime", 0), 12, format),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001102 b" ", # checksum field
Guido van Rossumd8faa362007-04-27 19:54:29 +00001103 info.get("type", REGTYPE),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001104 stn(info.get("linkname", ""), 100, encoding, errors),
1105 info.get("magic", POSIX_MAGIC),
1106 stn(info.get("uname", "root"), 32, encoding, errors),
1107 stn(info.get("gname", "root"), 32, encoding, errors),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001108 itn(info.get("devmajor", 0), 8, format),
1109 itn(info.get("devminor", 0), 8, format),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001110 stn(info.get("prefix", ""), 155, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001111 ]
1112
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001113 buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001114 chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
Lars Gustäbela280ca752007-08-28 07:34:33 +00001115 buf = buf[:-364] + bytes("%06o\0" % chksum, "ascii") + buf[-357:]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001116 return buf
1117
1118 @staticmethod
1119 def _create_payload(payload):
1120 """Return the string payload filled with zero bytes
1121 up to the next 512 byte border.
1122 """
1123 blocks, remainder = divmod(len(payload), BLOCKSIZE)
1124 if remainder > 0:
1125 payload += (BLOCKSIZE - remainder) * NUL
1126 return payload
1127
1128 @classmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001129 def _create_gnu_long_header(cls, name, type, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001130 """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence
1131 for name.
1132 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001133 name = name.encode(encoding, errors) + NUL
Guido van Rossumd8faa362007-04-27 19:54:29 +00001134
1135 info = {}
1136 info["name"] = "././@LongLink"
1137 info["type"] = type
1138 info["size"] = len(name)
1139 info["magic"] = GNU_MAGIC
1140
1141 # create extended header + name blocks.
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001142 return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \
Guido van Rossumd8faa362007-04-27 19:54:29 +00001143 cls._create_payload(name)
1144
1145 @classmethod
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001146 def _create_pax_generic_header(cls, pax_headers, type):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001147 """Return a POSIX.1-2001 extended or global header sequence
1148 that contains a list of keyword, value pairs. The values
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001149 must be strings.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001150 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001151 records = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001152 for keyword, value in pax_headers.items():
1153 keyword = keyword.encode("utf8")
1154 value = value.encode("utf8")
1155 l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n'
1156 n = p = 0
1157 while True:
1158 n = l + len(str(p))
1159 if n == p:
1160 break
1161 p = n
Lars Gustäbela280ca752007-08-28 07:34:33 +00001162 records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n"
Guido van Rossumd8faa362007-04-27 19:54:29 +00001163
1164 # We use a hardcoded "././@PaxHeader" name like star does
1165 # instead of the one that POSIX recommends.
1166 info = {}
1167 info["name"] = "././@PaxHeader"
1168 info["type"] = type
1169 info["size"] = len(records)
1170 info["magic"] = POSIX_MAGIC
1171
1172 # Create pax header + record blocks.
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001173 return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \
Guido van Rossumd8faa362007-04-27 19:54:29 +00001174 cls._create_payload(records)
1175
Guido van Rossum75b64e62005-01-16 00:16:11 +00001176 @classmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001177 def frombuf(cls, buf, encoding, errors):
1178 """Construct a TarInfo object from a 512 byte bytes object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001179 """
Thomas Wouters477c8d52006-05-27 19:21:47 +00001180 if len(buf) != BLOCKSIZE:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001181 raise HeaderError("truncated header")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001182 if buf.count(NUL) == BLOCKSIZE:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001183 raise HeaderError("empty header")
1184
1185 chksum = nti(buf[148:156])
1186 if chksum not in calc_chksums(buf):
1187 raise HeaderError("bad checksum")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001188
Guido van Rossumd8faa362007-04-27 19:54:29 +00001189 obj = cls()
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001190 obj.name = nts(buf[0:100], encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001191 obj.mode = nti(buf[100:108])
1192 obj.uid = nti(buf[108:116])
1193 obj.gid = nti(buf[116:124])
1194 obj.size = nti(buf[124:136])
1195 obj.mtime = nti(buf[136:148])
1196 obj.chksum = chksum
1197 obj.type = buf[156:157]
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001198 obj.linkname = nts(buf[157:257], encoding, errors)
1199 obj.uname = nts(buf[265:297], encoding, errors)
1200 obj.gname = nts(buf[297:329], encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001201 obj.devmajor = nti(buf[329:337])
1202 obj.devminor = nti(buf[337:345])
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001203 prefix = nts(buf[345:500], encoding, errors)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001204
Guido van Rossumd8faa362007-04-27 19:54:29 +00001205 # Old V7 tar format represents a directory as a regular
1206 # file with a trailing slash.
1207 if obj.type == AREGTYPE and obj.name.endswith("/"):
1208 obj.type = DIRTYPE
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001209
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001210 # The old GNU sparse format occupies some of the unused
1211 # space in the buffer for up to 4 sparse structures.
1212 # Save the them for later processing in _proc_sparse().
1213 if obj.type == GNUTYPE_SPARSE:
1214 pos = 386
1215 structs = []
1216 for i in range(4):
1217 try:
1218 offset = nti(buf[pos:pos + 12])
1219 numbytes = nti(buf[pos + 12:pos + 24])
1220 except ValueError:
1221 break
1222 structs.append((offset, numbytes))
1223 pos += 24
1224 isextended = bool(buf[482])
1225 origsize = nti(buf[483:495])
1226 obj._sparse_structs = (structs, isextended, origsize)
1227
Guido van Rossumd8faa362007-04-27 19:54:29 +00001228 # Remove redundant slashes from directories.
1229 if obj.isdir():
1230 obj.name = obj.name.rstrip("/")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001231
Guido van Rossumd8faa362007-04-27 19:54:29 +00001232 # Reconstruct a ustar longname.
1233 if prefix and obj.type not in GNU_TYPES:
1234 obj.name = prefix + "/" + obj.name
1235 return obj
1236
1237 @classmethod
1238 def fromtarfile(cls, tarfile):
1239 """Return the next TarInfo object from TarFile object
1240 tarfile.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001241 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001242 buf = tarfile.fileobj.read(BLOCKSIZE)
1243 if not buf:
1244 return
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001245 obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001246 obj.offset = tarfile.fileobj.tell() - BLOCKSIZE
1247 return obj._proc_member(tarfile)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001248
Guido van Rossumd8faa362007-04-27 19:54:29 +00001249 #--------------------------------------------------------------------------
1250 # The following are methods that are called depending on the type of a
1251 # member. The entry point is _proc_member() which can be overridden in a
1252 # subclass to add custom _proc_*() methods. A _proc_*() method MUST
1253 # implement the following
1254 # operations:
1255 # 1. Set self.offset_data to the position where the data blocks begin,
1256 # if there is data that follows.
1257 # 2. Set tarfile.offset to the position where the next member's header will
1258 # begin.
1259 # 3. Return self or another valid TarInfo object.
1260 def _proc_member(self, tarfile):
1261 """Choose the right processing method depending on
1262 the type and call it.
Thomas Wouters89f507f2006-12-13 04:49:30 +00001263 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001264 if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
1265 return self._proc_gnulong(tarfile)
1266 elif self.type == GNUTYPE_SPARSE:
1267 return self._proc_sparse(tarfile)
1268 elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE):
1269 return self._proc_pax(tarfile)
1270 else:
1271 return self._proc_builtin(tarfile)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001272
Guido van Rossumd8faa362007-04-27 19:54:29 +00001273 def _proc_builtin(self, tarfile):
1274 """Process a builtin type or an unknown type which
1275 will be treated as a regular file.
1276 """
1277 self.offset_data = tarfile.fileobj.tell()
1278 offset = self.offset_data
1279 if self.isreg() or self.type not in SUPPORTED_TYPES:
1280 # Skip the following data blocks.
1281 offset += self._block(self.size)
1282 tarfile.offset = offset
Thomas Wouters89f507f2006-12-13 04:49:30 +00001283
Guido van Rossume7ba4952007-06-06 23:52:48 +00001284 # Patch the TarInfo object with saved global
Guido van Rossumd8faa362007-04-27 19:54:29 +00001285 # header information.
Guido van Rossume7ba4952007-06-06 23:52:48 +00001286 self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001287
1288 return self
1289
1290 def _proc_gnulong(self, tarfile):
1291 """Process the blocks that hold a GNU longname
1292 or longlink member.
1293 """
1294 buf = tarfile.fileobj.read(self._block(self.size))
1295
1296 # Fetch the next header and process it.
Guido van Rossume7ba4952007-06-06 23:52:48 +00001297 next = self.fromtarfile(tarfile)
1298 if next is None:
1299 raise HeaderError("missing subsequent header")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001300
1301 # Patch the TarInfo object from the next header with
1302 # the longname information.
1303 next.offset = self.offset
1304 if self.type == GNUTYPE_LONGNAME:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001305 next.name = nts(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001306 elif self.type == GNUTYPE_LONGLINK:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001307 next.linkname = nts(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001308
1309 return next
1310
1311 def _proc_sparse(self, tarfile):
1312 """Process a GNU sparse header plus extra headers.
1313 """
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001314 # We already collected some sparse structures in frombuf().
1315 structs, isextended, origsize = self._sparse_structs
1316 del self._sparse_structs
Guido van Rossumd8faa362007-04-27 19:54:29 +00001317
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001318 # Collect sparse structures from extended header blocks.
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001319 while isextended:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001320 buf = tarfile.fileobj.read(BLOCKSIZE)
1321 pos = 0
Guido van Rossum805365e2007-05-07 22:24:25 +00001322 for i in range(21):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001323 try:
1324 offset = nti(buf[pos:pos + 12])
1325 numbytes = nti(buf[pos + 12:pos + 24])
1326 except ValueError:
1327 break
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001328 structs.append((offset, numbytes))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001329 pos += 24
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001330 isextended = bool(buf[504])
Guido van Rossumd8faa362007-04-27 19:54:29 +00001331
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001332 # Transform the sparse structures to something we can use
1333 # in ExFileObject.
1334 self.sparse = _ringbuffer()
1335 lastpos = 0
1336 realpos = 0
1337 for offset, numbytes in structs:
1338 if offset > lastpos:
1339 self.sparse.append(_hole(lastpos, offset - lastpos))
1340 self.sparse.append(_data(offset, numbytes, realpos))
1341 realpos += numbytes
1342 lastpos = offset + numbytes
Guido van Rossumd8faa362007-04-27 19:54:29 +00001343 if lastpos < origsize:
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001344 self.sparse.append(_hole(lastpos, origsize - lastpos))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001345
1346 self.offset_data = tarfile.fileobj.tell()
1347 tarfile.offset = self.offset_data + self._block(self.size)
1348 self.size = origsize
1349
1350 return self
1351
1352 def _proc_pax(self, tarfile):
1353 """Process an extended or global header as described in
1354 POSIX.1-2001.
1355 """
1356 # Read the header information.
1357 buf = tarfile.fileobj.read(self._block(self.size))
1358
1359 # A pax header stores supplemental information for either
1360 # the following file (extended) or all following files
1361 # (global).
1362 if self.type == XGLTYPE:
1363 pax_headers = tarfile.pax_headers
1364 else:
1365 pax_headers = tarfile.pax_headers.copy()
1366
Guido van Rossumd8faa362007-04-27 19:54:29 +00001367 # Parse pax header information. A record looks like that:
1368 # "%d %s=%s\n" % (length, keyword, value). length is the size
1369 # of the complete record including the length field itself and
Guido van Rossume7ba4952007-06-06 23:52:48 +00001370 # the newline. keyword and value are both UTF-8 encoded strings.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001371 regex = re.compile(r"(\d+) ([^=]+)=", re.U)
1372 pos = 0
1373 while True:
1374 match = regex.match(buf, pos)
1375 if not match:
1376 break
1377
1378 length, keyword = match.groups()
1379 length = int(length)
1380 value = buf[match.end(2) + 1:match.start(1) + length - 1]
1381
1382 keyword = keyword.decode("utf8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001383 value = value.decode("utf8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001384
1385 pax_headers[keyword] = value
1386 pos += length
1387
Guido van Rossume7ba4952007-06-06 23:52:48 +00001388 # Fetch the next header.
1389 next = self.fromtarfile(tarfile)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001390
Guido van Rossume7ba4952007-06-06 23:52:48 +00001391 if self.type in (XHDTYPE, SOLARIS_XHDTYPE):
1392 if next is None:
1393 raise HeaderError("missing subsequent header")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001394
Guido van Rossume7ba4952007-06-06 23:52:48 +00001395 # Patch the TarInfo object with the extended header info.
1396 next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors)
1397 next.offset = self.offset
1398
1399 if "size" in pax_headers:
1400 # If the extended header replaces the size field,
1401 # we need to recalculate the offset where the next
1402 # header starts.
1403 offset = next.offset_data
1404 if next.isreg() or next.type not in SUPPORTED_TYPES:
1405 offset += next._block(next.size)
1406 tarfile.offset = offset
1407
1408 return next
1409
1410 def _apply_pax_info(self, pax_headers, encoding, errors):
1411 """Replace fields with supplemental information from a previous
1412 pax extended or global header.
1413 """
1414 for keyword, value in pax_headers.items():
1415 if keyword not in PAX_FIELDS:
1416 continue
1417
1418 if keyword == "path":
1419 value = value.rstrip("/")
1420
1421 if keyword in PAX_NUMBER_FIELDS:
1422 try:
1423 value = PAX_NUMBER_FIELDS[keyword](value)
1424 except ValueError:
1425 value = 0
Guido van Rossume7ba4952007-06-06 23:52:48 +00001426
1427 setattr(self, keyword, value)
1428
1429 self.pax_headers = pax_headers.copy()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001430
1431 def _block(self, count):
1432 """Round up a byte count by BLOCKSIZE and return it,
1433 e.g. _block(834) => 1024.
1434 """
1435 blocks, remainder = divmod(count, BLOCKSIZE)
1436 if remainder:
1437 blocks += 1
1438 return blocks * BLOCKSIZE
Thomas Wouters89f507f2006-12-13 04:49:30 +00001439
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001440 def isreg(self):
1441 return self.type in REGULAR_TYPES
1442 def isfile(self):
1443 return self.isreg()
1444 def isdir(self):
1445 return self.type == DIRTYPE
1446 def issym(self):
1447 return self.type == SYMTYPE
1448 def islnk(self):
1449 return self.type == LNKTYPE
1450 def ischr(self):
1451 return self.type == CHRTYPE
1452 def isblk(self):
1453 return self.type == BLKTYPE
1454 def isfifo(self):
1455 return self.type == FIFOTYPE
1456 def issparse(self):
1457 return self.type == GNUTYPE_SPARSE
1458 def isdev(self):
1459 return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
1460# class TarInfo
1461
1462class TarFile(object):
1463 """The TarFile Class provides an interface to tar archives.
1464 """
1465
1466 debug = 0 # May be set from 0 (no msgs) to 3 (all msgs)
1467
1468 dereference = False # If true, add content of linked file to the
1469 # tar file, else the link.
1470
1471 ignore_zeros = False # If true, skips empty or invalid blocks and
1472 # continues processing.
1473
1474 errorlevel = 0 # If 0, fatal errors only appear in debug
1475 # messages (if debug >= 0). If > 0, errors
1476 # are passed to the caller as exceptions.
1477
Guido van Rossumd8faa362007-04-27 19:54:29 +00001478 format = DEFAULT_FORMAT # The format to use when creating an archive.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001479
Guido van Rossume7ba4952007-06-06 23:52:48 +00001480 encoding = ENCODING # Encoding for 8-bit character strings.
1481
1482 errors = None # Error handler for unicode conversion.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001483
Guido van Rossumd8faa362007-04-27 19:54:29 +00001484 tarinfo = TarInfo # The default TarInfo class to use.
1485
1486 fileobject = ExFileObject # The default ExFileObject class to use.
1487
1488 def __init__(self, name=None, mode="r", fileobj=None, format=None,
1489 tarinfo=None, dereference=None, ignore_zeros=None, encoding=None,
Guido van Rossume7ba4952007-06-06 23:52:48 +00001490 errors=None, pax_headers=None, debug=None, errorlevel=None):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001491 """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
1492 read from an existing archive, 'a' to append data to an existing
1493 file or 'w' to create a new file overwriting an existing one. `mode'
1494 defaults to 'r'.
1495 If `fileobj' is given, it is used for reading or writing data. If it
1496 can be determined, `mode' is overridden by `fileobj's mode.
1497 `fileobj' is not closed, when TarFile is closed.
1498 """
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001499 if len(mode) > 1 or mode not in "raw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001500 raise ValueError("mode must be 'r', 'a' or 'w'")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001501 self.mode = mode
1502 self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001503
1504 if not fileobj:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001505 if self.mode == "a" and not os.path.exists(name):
Thomas Wouterscf297e42007-02-23 15:07:44 +00001506 # Create nonexistent files in append mode.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001507 self.mode = "w"
1508 self._mode = "wb"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001509 fileobj = bltn_open(name, self._mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001510 self._extfileobj = False
1511 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001512 if name is None and hasattr(fileobj, "name"):
1513 name = fileobj.name
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001514 if hasattr(fileobj, "mode"):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001515 self._mode = fileobj.mode
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001516 self._extfileobj = True
Thomas Woutersed03b412007-08-28 21:37:11 +00001517 self.name = os.path.abspath(name) if name else None
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001518 self.fileobj = fileobj
1519
Guido van Rossumd8faa362007-04-27 19:54:29 +00001520 # Init attributes.
1521 if format is not None:
1522 self.format = format
1523 if tarinfo is not None:
1524 self.tarinfo = tarinfo
1525 if dereference is not None:
1526 self.dereference = dereference
1527 if ignore_zeros is not None:
1528 self.ignore_zeros = ignore_zeros
1529 if encoding is not None:
1530 self.encoding = encoding
Guido van Rossume7ba4952007-06-06 23:52:48 +00001531
1532 if errors is not None:
1533 self.errors = errors
1534 elif mode == "r":
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001535 self.errors = "replace"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001536 else:
1537 self.errors = "strict"
1538
1539 if pax_headers is not None and self.format == PAX_FORMAT:
1540 self.pax_headers = pax_headers
1541 else:
1542 self.pax_headers = {}
1543
Guido van Rossumd8faa362007-04-27 19:54:29 +00001544 if debug is not None:
1545 self.debug = debug
1546 if errorlevel is not None:
1547 self.errorlevel = errorlevel
1548
1549 # Init datastructures.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001550 self.closed = False
1551 self.members = [] # list of members as TarInfo objects
1552 self._loaded = False # flag if all members have been read
Christian Heimesd8654cf2007-12-02 15:22:16 +00001553 self.offset = self.fileobj.tell()
1554 # current position in the archive file
Thomas Wouters477c8d52006-05-27 19:21:47 +00001555 self.inodes = {} # dictionary caching the inodes of
1556 # archive members already added
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001557
Guido van Rossumd8faa362007-04-27 19:54:29 +00001558 if self.mode == "r":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001559 self.firstmember = None
1560 self.firstmember = self.next()
1561
Guido van Rossumd8faa362007-04-27 19:54:29 +00001562 if self.mode == "a":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001563 # Move to the end of the archive,
1564 # before the first empty block.
1565 self.firstmember = None
1566 while True:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001567 if self.next() is None:
Thomas Wouterscf297e42007-02-23 15:07:44 +00001568 if self.offset > 0:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001569 self.fileobj.seek(self.fileobj.tell() - BLOCKSIZE)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001570 break
1571
Guido van Rossumd8faa362007-04-27 19:54:29 +00001572 if self.mode in "aw":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001573 self._loaded = True
1574
Guido van Rossume7ba4952007-06-06 23:52:48 +00001575 if self.pax_headers:
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001576 buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy())
Guido van Rossumd8faa362007-04-27 19:54:29 +00001577 self.fileobj.write(buf)
1578 self.offset += len(buf)
1579
1580 def _getposix(self):
1581 return self.format == USTAR_FORMAT
1582 def _setposix(self, value):
1583 import warnings
1584 warnings.warn("use the format attribute instead", DeprecationWarning)
1585 if value:
1586 self.format = USTAR_FORMAT
1587 else:
1588 self.format = GNU_FORMAT
1589 posix = property(_getposix, _setposix)
1590
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001591 #--------------------------------------------------------------------------
1592 # Below are the classmethods which act as alternate constructors to the
1593 # TarFile class. The open() method is the only one that is needed for
1594 # public use; it is the "super"-constructor and is able to select an
1595 # adequate "sub"-constructor for a particular compression using the mapping
1596 # from OPEN_METH.
1597 #
1598 # This concept allows one to subclass TarFile without losing the comfort of
1599 # the super-constructor. A sub-constructor is registered and made available
1600 # by adding it to the mapping in OPEN_METH.
1601
Guido van Rossum75b64e62005-01-16 00:16:11 +00001602 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001603 def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001604 """Open a tar archive for reading, writing or appending. Return
1605 an appropriate TarFile class.
1606
1607 mode:
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001608 'r' or 'r:*' open for reading with transparent compression
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001609 'r:' open for reading exclusively uncompressed
1610 'r:gz' open for reading with gzip compression
1611 'r:bz2' open for reading with bzip2 compression
Thomas Wouterscf297e42007-02-23 15:07:44 +00001612 'a' or 'a:' open for appending, creating the file if necessary
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001613 'w' or 'w:' open for writing without compression
1614 'w:gz' open for writing with gzip compression
1615 'w:bz2' open for writing with bzip2 compression
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001616
1617 'r|*' open a stream of tar blocks with transparent compression
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001618 'r|' open an uncompressed stream of tar blocks for reading
1619 'r|gz' open a gzip compressed stream of tar blocks
1620 'r|bz2' open a bzip2 compressed stream of tar blocks
1621 'w|' open an uncompressed stream for writing
1622 'w|gz' open a gzip compressed stream for writing
1623 'w|bz2' open a bzip2 compressed stream for writing
1624 """
1625
1626 if not name and not fileobj:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001627 raise ValueError("nothing to open")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001628
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001629 if mode in ("r", "r:*"):
1630 # Find out which *open() is appropriate for opening the file.
1631 for comptype in cls.OPEN_METH:
1632 func = getattr(cls, cls.OPEN_METH[comptype])
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001633 if fileobj is not None:
1634 saved_pos = fileobj.tell()
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001635 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001636 return func(name, "r", fileobj, **kwargs)
1637 except (ReadError, CompressionError) as e:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001638 if fileobj is not None:
1639 fileobj.seek(saved_pos)
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001640 continue
Thomas Wouters477c8d52006-05-27 19:21:47 +00001641 raise ReadError("file could not be opened successfully")
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001642
1643 elif ":" in mode:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001644 filemode, comptype = mode.split(":", 1)
1645 filemode = filemode or "r"
1646 comptype = comptype or "tar"
1647
1648 # Select the *open() function according to
1649 # given compression.
1650 if comptype in cls.OPEN_METH:
1651 func = getattr(cls, cls.OPEN_METH[comptype])
1652 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001653 raise CompressionError("unknown compression type %r" % comptype)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001654 return func(name, filemode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001655
1656 elif "|" in mode:
1657 filemode, comptype = mode.split("|", 1)
1658 filemode = filemode or "r"
1659 comptype = comptype or "tar"
1660
1661 if filemode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001662 raise ValueError("mode must be 'r' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001663
1664 t = cls(name, filemode,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001665 _Stream(name, filemode, comptype, fileobj, bufsize),
1666 **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001667 t._extfileobj = False
1668 return t
1669
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001670 elif mode in "aw":
Guido van Rossumd8faa362007-04-27 19:54:29 +00001671 return cls.taropen(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001672
Thomas Wouters477c8d52006-05-27 19:21:47 +00001673 raise ValueError("undiscernible mode")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001674
Guido van Rossum75b64e62005-01-16 00:16:11 +00001675 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001676 def taropen(cls, name, mode="r", fileobj=None, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001677 """Open uncompressed tar archive name for reading or writing.
1678 """
1679 if len(mode) > 1 or mode not in "raw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001680 raise ValueError("mode must be 'r', 'a' or 'w'")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001681 return cls(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001682
Guido van Rossum75b64e62005-01-16 00:16:11 +00001683 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001684 def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001685 """Open gzip compressed tar archive name for reading or writing.
1686 Appending is not allowed.
1687 """
1688 if len(mode) > 1 or mode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001689 raise ValueError("mode must be 'r' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001690
1691 try:
1692 import gzip
Neal Norwitz4ec68242003-04-11 03:05:56 +00001693 gzip.GzipFile
1694 except (ImportError, AttributeError):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001695 raise CompressionError("gzip module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001696
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001697 if fileobj is None:
Guido van Rossume7ba4952007-06-06 23:52:48 +00001698 fileobj = bltn_open(name, mode + "b")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001699
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001700 try:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001701 t = cls.taropen(name, mode,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001702 gzip.GzipFile(name, mode, compresslevel, fileobj),
1703 **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001704 except IOError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001705 raise ReadError("not a gzip file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001706 t._extfileobj = False
1707 return t
1708
Guido van Rossum75b64e62005-01-16 00:16:11 +00001709 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001710 def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001711 """Open bzip2 compressed tar archive name for reading or writing.
1712 Appending is not allowed.
1713 """
1714 if len(mode) > 1 or mode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001715 raise ValueError("mode must be 'r' or 'w'.")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001716
1717 try:
1718 import bz2
1719 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001720 raise CompressionError("bz2 module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001721
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001722 if fileobj is not None:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001723 fileobj = _BZ2Proxy(fileobj, mode)
1724 else:
1725 fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001726
1727 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001728 t = cls.taropen(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001729 except IOError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001730 raise ReadError("not a bzip2 file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001731 t._extfileobj = False
1732 return t
1733
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001734 # All *open() methods are registered here.
1735 OPEN_METH = {
1736 "tar": "taropen", # uncompressed tar
1737 "gz": "gzopen", # gzip compressed tar
1738 "bz2": "bz2open" # bzip2 compressed tar
1739 }
1740
1741 #--------------------------------------------------------------------------
1742 # The public methods which TarFile provides:
1743
1744 def close(self):
1745 """Close the TarFile. In write-mode, two finishing zero blocks are
1746 appended to the archive.
1747 """
1748 if self.closed:
1749 return
1750
Guido van Rossumd8faa362007-04-27 19:54:29 +00001751 if self.mode in "aw":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001752 self.fileobj.write(NUL * (BLOCKSIZE * 2))
1753 self.offset += (BLOCKSIZE * 2)
1754 # fill up the end with zero-blocks
1755 # (like option -b20 for tar does)
1756 blocks, remainder = divmod(self.offset, RECORDSIZE)
1757 if remainder > 0:
1758 self.fileobj.write(NUL * (RECORDSIZE - remainder))
1759
1760 if not self._extfileobj:
1761 self.fileobj.close()
1762 self.closed = True
1763
1764 def getmember(self, name):
1765 """Return a TarInfo object for member `name'. If `name' can not be
1766 found in the archive, KeyError is raised. If a member occurs more
1767 than once in the archive, its last occurence is assumed to be the
1768 most up-to-date version.
1769 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001770 tarinfo = self._getmember(name)
1771 if tarinfo is None:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001772 raise KeyError("filename %r not found" % name)
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001773 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001774
1775 def getmembers(self):
1776 """Return the members of the archive as a list of TarInfo objects. The
1777 list has the same order as the members in the archive.
1778 """
1779 self._check()
1780 if not self._loaded: # if we want to obtain a list of
1781 self._load() # all members, we first have to
1782 # scan the whole archive.
1783 return self.members
1784
1785 def getnames(self):
1786 """Return the members of the archive as a list of their names. It has
1787 the same order as the list returned by getmembers().
1788 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001789 return [tarinfo.name for tarinfo in self.getmembers()]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001790
1791 def gettarinfo(self, name=None, arcname=None, fileobj=None):
1792 """Create a TarInfo object for either the file `name' or the file
1793 object `fileobj' (using os.fstat on its file descriptor). You can
1794 modify some of the TarInfo's attributes before you add it using
1795 addfile(). If given, `arcname' specifies an alternative name for the
1796 file in the archive.
1797 """
1798 self._check("aw")
1799
1800 # When fileobj is given, replace name by
1801 # fileobj's real name.
1802 if fileobj is not None:
1803 name = fileobj.name
1804
1805 # Building the name of the member in the archive.
1806 # Backward slashes are converted to forward slashes,
1807 # Absolute paths are turned to relative paths.
1808 if arcname is None:
1809 arcname = name
1810 arcname = normpath(arcname)
1811 drv, arcname = os.path.splitdrive(arcname)
1812 while arcname[0:1] == "/":
1813 arcname = arcname[1:]
1814
1815 # Now, fill the TarInfo object with
1816 # information specific for the file.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001817 tarinfo = self.tarinfo()
1818 tarinfo.tarfile = self
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001819
1820 # Use os.stat or os.lstat, depending on platform
1821 # and if symlinks shall be resolved.
1822 if fileobj is None:
1823 if hasattr(os, "lstat") and not self.dereference:
1824 statres = os.lstat(name)
1825 else:
1826 statres = os.stat(name)
1827 else:
1828 statres = os.fstat(fileobj.fileno())
1829 linkname = ""
1830
1831 stmd = statres.st_mode
1832 if stat.S_ISREG(stmd):
1833 inode = (statres.st_ino, statres.st_dev)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001834 if not self.dereference and statres.st_nlink > 1 and \
1835 inode in self.inodes and arcname != self.inodes[inode]:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001836 # Is it a hardlink to an already
1837 # archived file?
1838 type = LNKTYPE
1839 linkname = self.inodes[inode]
1840 else:
1841 # The inode is added only if its valid.
1842 # For win32 it is always 0.
1843 type = REGTYPE
1844 if inode[0]:
1845 self.inodes[inode] = arcname
1846 elif stat.S_ISDIR(stmd):
1847 type = DIRTYPE
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001848 elif stat.S_ISFIFO(stmd):
1849 type = FIFOTYPE
1850 elif stat.S_ISLNK(stmd):
1851 type = SYMTYPE
1852 linkname = os.readlink(name)
1853 elif stat.S_ISCHR(stmd):
1854 type = CHRTYPE
1855 elif stat.S_ISBLK(stmd):
1856 type = BLKTYPE
1857 else:
1858 return None
1859
1860 # Fill the TarInfo object with all
1861 # information we can get.
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001862 tarinfo.name = arcname
1863 tarinfo.mode = stmd
1864 tarinfo.uid = statres.st_uid
1865 tarinfo.gid = statres.st_gid
1866 if stat.S_ISREG(stmd):
Martin v. Löwis61d77e02004-08-20 06:35:46 +00001867 tarinfo.size = statres.st_size
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001868 else:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001869 tarinfo.size = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001870 tarinfo.mtime = statres.st_mtime
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001871 tarinfo.type = type
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001872 tarinfo.linkname = linkname
1873 if pwd:
1874 try:
1875 tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
1876 except KeyError:
1877 pass
1878 if grp:
1879 try:
1880 tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
1881 except KeyError:
1882 pass
1883
1884 if type in (CHRTYPE, BLKTYPE):
1885 if hasattr(os, "major") and hasattr(os, "minor"):
1886 tarinfo.devmajor = os.major(statres.st_rdev)
1887 tarinfo.devminor = os.minor(statres.st_rdev)
1888 return tarinfo
1889
1890 def list(self, verbose=True):
1891 """Print a table of contents to sys.stdout. If `verbose' is False, only
1892 the names of the members are printed. If it is True, an `ls -l'-like
1893 output is produced.
1894 """
1895 self._check()
1896
1897 for tarinfo in self:
1898 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001899 print(filemode(tarinfo.mode), end=' ')
1900 print("%s/%s" % (tarinfo.uname or tarinfo.uid,
1901 tarinfo.gname or tarinfo.gid), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001902 if tarinfo.ischr() or tarinfo.isblk():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001903 print("%10s" % ("%d,%d" \
1904 % (tarinfo.devmajor, tarinfo.devminor)), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001905 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001906 print("%10d" % tarinfo.size, end=' ')
1907 print("%d-%02d-%02d %02d:%02d:%02d" \
1908 % time.localtime(tarinfo.mtime)[:6], end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001909
Guido van Rossumd8faa362007-04-27 19:54:29 +00001910 print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001911
1912 if verbose:
1913 if tarinfo.issym():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001914 print("->", tarinfo.linkname, end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001915 if tarinfo.islnk():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001916 print("link to", tarinfo.linkname, end=' ')
1917 print()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001918
Guido van Rossum486364b2007-06-30 05:01:58 +00001919 def add(self, name, arcname=None, recursive=True, exclude=None):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001920 """Add the file `name' to the archive. `name' may be any type of file
1921 (directory, fifo, symbolic link, etc.). If given, `arcname'
1922 specifies an alternative name for the file in the archive.
1923 Directories are added recursively by default. This can be avoided by
Guido van Rossum486364b2007-06-30 05:01:58 +00001924 setting `recursive' to False. `exclude' is a function that should
1925 return True for each filename to be excluded.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001926 """
1927 self._check("aw")
1928
1929 if arcname is None:
1930 arcname = name
1931
Guido van Rossum486364b2007-06-30 05:01:58 +00001932 # Exclude pathnames.
1933 if exclude is not None and exclude(name):
1934 self._dbg(2, "tarfile: Excluded %r" % name)
1935 return
1936
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001937 # Skip if somebody tries to archive the archive...
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001938 if self.name is not None and os.path.abspath(name) == self.name:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001939 self._dbg(2, "tarfile: Skipped %r" % name)
1940 return
1941
1942 # Special case: The user wants to add the current
1943 # working directory.
1944 if name == ".":
1945 if recursive:
1946 if arcname == ".":
1947 arcname = ""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001948 for f in os.listdir(name):
Guido van Rossum486364b2007-06-30 05:01:58 +00001949 self.add(f, os.path.join(arcname, f), recursive, exclude)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001950 return
1951
1952 self._dbg(1, name)
1953
1954 # Create a TarInfo object from the file.
1955 tarinfo = self.gettarinfo(name, arcname)
1956
1957 if tarinfo is None:
1958 self._dbg(1, "tarfile: Unsupported type %r" % name)
1959 return
1960
1961 # Append the tar header and data to the archive.
1962 if tarinfo.isreg():
Guido van Rossume7ba4952007-06-06 23:52:48 +00001963 f = bltn_open(name, "rb")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001964 self.addfile(tarinfo, f)
1965 f.close()
1966
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001967 elif tarinfo.isdir():
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001968 self.addfile(tarinfo)
1969 if recursive:
1970 for f in os.listdir(name):
Guido van Rossum486364b2007-06-30 05:01:58 +00001971 self.add(os.path.join(name, f), os.path.join(arcname, f), recursive, exclude)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001972
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001973 else:
1974 self.addfile(tarinfo)
1975
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001976 def addfile(self, tarinfo, fileobj=None):
1977 """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
1978 given, tarinfo.size bytes are read from it and added to the archive.
1979 You can create TarInfo objects using gettarinfo().
1980 On Windows platforms, `fileobj' should always be opened with mode
1981 'rb' to avoid irritation about the file size.
1982 """
1983 self._check("aw")
1984
Thomas Wouters89f507f2006-12-13 04:49:30 +00001985 tarinfo = copy.copy(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001986
Guido van Rossume7ba4952007-06-06 23:52:48 +00001987 buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001988 self.fileobj.write(buf)
1989 self.offset += len(buf)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001990
1991 # If there's data to follow, append it.
1992 if fileobj is not None:
1993 copyfileobj(fileobj, self.fileobj, tarinfo.size)
1994 blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
1995 if remainder > 0:
1996 self.fileobj.write(NUL * (BLOCKSIZE - remainder))
1997 blocks += 1
1998 self.offset += blocks * BLOCKSIZE
1999
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002000 self.members.append(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002001
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002002 def extractall(self, path=".", members=None):
2003 """Extract all members from the archive to the current working
2004 directory and set owner, modification time and permissions on
2005 directories afterwards. `path' specifies a different directory
2006 to extract to. `members' is optional and must be a subset of the
2007 list returned by getmembers().
2008 """
2009 directories = []
2010
2011 if members is None:
2012 members = self
2013
2014 for tarinfo in members:
2015 if tarinfo.isdir():
Christian Heimes2202f872008-02-06 14:31:34 +00002016 # Extract directories with a safe mode.
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002017 directories.append(tarinfo)
Christian Heimes2202f872008-02-06 14:31:34 +00002018 tarinfo = copy.copy(tarinfo)
2019 tarinfo.mode = 0o700
2020 self.extract(tarinfo, path)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002021
2022 # Reverse sort directories.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +00002023 directories.sort(key=lambda a: a.name)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002024 directories.reverse()
2025
2026 # Set correct owner, mtime and filemode on directories.
2027 for tarinfo in directories:
Christian Heimesfaf2f632008-01-06 16:59:19 +00002028 dirpath = os.path.join(path, tarinfo.name)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002029 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +00002030 self.chown(tarinfo, dirpath)
2031 self.utime(tarinfo, dirpath)
2032 self.chmod(tarinfo, dirpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002033 except ExtractError as e:
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002034 if self.errorlevel > 1:
2035 raise
2036 else:
2037 self._dbg(1, "tarfile: %s" % e)
2038
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002039 def extract(self, member, path=""):
2040 """Extract a member from the archive to the current working directory,
2041 using its full name. Its file information is extracted as accurately
2042 as possible. `member' may be a filename or a TarInfo object. You can
2043 specify a different directory using `path'.
2044 """
2045 self._check("r")
2046
Guido van Rossum3172c5d2007-10-16 18:12:55 +00002047 if isinstance(member, str):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002048 tarinfo = self.getmember(member)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002049 else:
2050 tarinfo = member
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002051
Neal Norwitza4f651a2004-07-20 22:07:44 +00002052 # Prepare the link target for makelink().
2053 if tarinfo.islnk():
2054 tarinfo._link_target = os.path.join(path, tarinfo.linkname)
2055
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002056 try:
2057 self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
Guido van Rossumb940e112007-01-10 16:19:56 +00002058 except EnvironmentError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002059 if self.errorlevel > 0:
2060 raise
2061 else:
2062 if e.filename is None:
2063 self._dbg(1, "tarfile: %s" % e.strerror)
2064 else:
2065 self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
Guido van Rossumb940e112007-01-10 16:19:56 +00002066 except ExtractError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002067 if self.errorlevel > 1:
2068 raise
2069 else:
2070 self._dbg(1, "tarfile: %s" % e)
2071
2072 def extractfile(self, member):
2073 """Extract a member from the archive as a file object. `member' may be
2074 a filename or a TarInfo object. If `member' is a regular file, a
2075 file-like object is returned. If `member' is a link, a file-like
2076 object is constructed from the link's target. If `member' is none of
2077 the above, None is returned.
2078 The file-like object is read-only and provides the following
2079 methods: read(), readline(), readlines(), seek() and tell()
2080 """
2081 self._check("r")
2082
Guido van Rossum3172c5d2007-10-16 18:12:55 +00002083 if isinstance(member, str):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002084 tarinfo = self.getmember(member)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002085 else:
2086 tarinfo = member
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002087
2088 if tarinfo.isreg():
2089 return self.fileobject(self, tarinfo)
2090
2091 elif tarinfo.type not in SUPPORTED_TYPES:
2092 # If a member's type is unknown, it is treated as a
2093 # regular file.
2094 return self.fileobject(self, tarinfo)
2095
2096 elif tarinfo.islnk() or tarinfo.issym():
2097 if isinstance(self.fileobj, _Stream):
2098 # A small but ugly workaround for the case that someone tries
2099 # to extract a (sym)link as a file-object from a non-seekable
2100 # stream of tar blocks.
Thomas Wouters477c8d52006-05-27 19:21:47 +00002101 raise StreamError("cannot extract (sym)link as file object")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002102 else:
Georg Brandl7eb4b7d2005-07-22 21:49:32 +00002103 # A (sym)link's file object is its target's file object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002104 return self.extractfile(self._getmember(tarinfo.linkname,
2105 tarinfo))
2106 else:
2107 # If there's no data associated with the member (directory, chrdev,
2108 # blkdev, etc.), return None instead of a file object.
2109 return None
2110
2111 def _extract_member(self, tarinfo, targetpath):
2112 """Extract the TarInfo object tarinfo to a physical
2113 file called targetpath.
2114 """
2115 # Fetch the TarInfo object for the given name
2116 # and build the destination pathname, replacing
2117 # forward slashes to platform specific separators.
2118 if targetpath[-1:] == "/":
2119 targetpath = targetpath[:-1]
2120 targetpath = os.path.normpath(targetpath)
2121
2122 # Create all upper directories.
2123 upperdirs = os.path.dirname(targetpath)
2124 if upperdirs and not os.path.exists(upperdirs):
Christian Heimes2202f872008-02-06 14:31:34 +00002125 # Create directories that are not part of the archive with
2126 # default permissions.
Thomas Woutersb2137042007-02-01 18:02:27 +00002127 os.makedirs(upperdirs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002128
2129 if tarinfo.islnk() or tarinfo.issym():
2130 self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
2131 else:
2132 self._dbg(1, tarinfo.name)
2133
2134 if tarinfo.isreg():
2135 self.makefile(tarinfo, targetpath)
2136 elif tarinfo.isdir():
2137 self.makedir(tarinfo, targetpath)
2138 elif tarinfo.isfifo():
2139 self.makefifo(tarinfo, targetpath)
2140 elif tarinfo.ischr() or tarinfo.isblk():
2141 self.makedev(tarinfo, targetpath)
2142 elif tarinfo.islnk() or tarinfo.issym():
2143 self.makelink(tarinfo, targetpath)
2144 elif tarinfo.type not in SUPPORTED_TYPES:
2145 self.makeunknown(tarinfo, targetpath)
2146 else:
2147 self.makefile(tarinfo, targetpath)
2148
2149 self.chown(tarinfo, targetpath)
2150 if not tarinfo.issym():
2151 self.chmod(tarinfo, targetpath)
2152 self.utime(tarinfo, targetpath)
2153
2154 #--------------------------------------------------------------------------
2155 # Below are the different file methods. They are called via
2156 # _extract_member() when extract() is called. They can be replaced in a
2157 # subclass to implement other functionality.
2158
2159 def makedir(self, tarinfo, targetpath):
2160 """Make a directory called targetpath.
2161 """
2162 try:
Christian Heimes2202f872008-02-06 14:31:34 +00002163 # Use a safe mode for the directory, the real mode is set
2164 # later in _extract_member().
2165 os.mkdir(targetpath, 0o700)
Guido van Rossumb940e112007-01-10 16:19:56 +00002166 except EnvironmentError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002167 if e.errno != errno.EEXIST:
2168 raise
2169
2170 def makefile(self, tarinfo, targetpath):
2171 """Make a file called targetpath.
2172 """
2173 source = self.extractfile(tarinfo)
Guido van Rossume7ba4952007-06-06 23:52:48 +00002174 target = bltn_open(targetpath, "wb")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002175 copyfileobj(source, target)
2176 source.close()
2177 target.close()
2178
2179 def makeunknown(self, tarinfo, targetpath):
2180 """Make a file from a TarInfo object with an unknown type
2181 at targetpath.
2182 """
2183 self.makefile(tarinfo, targetpath)
2184 self._dbg(1, "tarfile: Unknown file type %r, " \
2185 "extracted as regular file." % tarinfo.type)
2186
2187 def makefifo(self, tarinfo, targetpath):
2188 """Make a fifo called targetpath.
2189 """
2190 if hasattr(os, "mkfifo"):
2191 os.mkfifo(targetpath)
2192 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002193 raise ExtractError("fifo not supported by system")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002194
2195 def makedev(self, tarinfo, targetpath):
2196 """Make a character or block device called targetpath.
2197 """
2198 if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
Thomas Wouters477c8d52006-05-27 19:21:47 +00002199 raise ExtractError("special devices not supported by system")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002200
2201 mode = tarinfo.mode
2202 if tarinfo.isblk():
2203 mode |= stat.S_IFBLK
2204 else:
2205 mode |= stat.S_IFCHR
2206
2207 os.mknod(targetpath, mode,
2208 os.makedev(tarinfo.devmajor, tarinfo.devminor))
2209
2210 def makelink(self, tarinfo, targetpath):
2211 """Make a (symbolic) link called targetpath. If it cannot be created
2212 (platform limitation), we try to make a copy of the referenced file
2213 instead of a link.
2214 """
2215 linkpath = tarinfo.linkname
2216 try:
2217 if tarinfo.issym():
2218 os.symlink(linkpath, targetpath)
2219 else:
Neal Norwitza4f651a2004-07-20 22:07:44 +00002220 # See extract().
2221 os.link(tarinfo._link_target, targetpath)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002222 except AttributeError:
2223 if tarinfo.issym():
2224 linkpath = os.path.join(os.path.dirname(tarinfo.name),
2225 linkpath)
2226 linkpath = normpath(linkpath)
2227
2228 try:
2229 self._extract_member(self.getmember(linkpath), targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002230 except (EnvironmentError, KeyError) as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002231 linkpath = os.path.normpath(linkpath)
2232 try:
2233 shutil.copy2(linkpath, targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002234 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002235 raise IOError("link could not be created")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002236
2237 def chown(self, tarinfo, targetpath):
2238 """Set owner of targetpath according to tarinfo.
2239 """
2240 if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
2241 # We have to be root to do so.
2242 try:
2243 g = grp.getgrnam(tarinfo.gname)[2]
2244 except KeyError:
2245 try:
2246 g = grp.getgrgid(tarinfo.gid)[2]
2247 except KeyError:
2248 g = os.getgid()
2249 try:
2250 u = pwd.getpwnam(tarinfo.uname)[2]
2251 except KeyError:
2252 try:
2253 u = pwd.getpwuid(tarinfo.uid)[2]
2254 except KeyError:
2255 u = os.getuid()
2256 try:
2257 if tarinfo.issym() and hasattr(os, "lchown"):
2258 os.lchown(targetpath, u, g)
2259 else:
Andrew MacIntyre7970d202003-02-19 12:51:34 +00002260 if sys.platform != "os2emx":
2261 os.chown(targetpath, u, g)
Guido van Rossumb940e112007-01-10 16:19:56 +00002262 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002263 raise ExtractError("could not change owner")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002264
2265 def chmod(self, tarinfo, targetpath):
2266 """Set file permissions of targetpath according to tarinfo.
2267 """
Jack Jansen834eff62003-03-07 12:47:06 +00002268 if hasattr(os, 'chmod'):
2269 try:
2270 os.chmod(targetpath, tarinfo.mode)
Guido van Rossumb940e112007-01-10 16:19:56 +00002271 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002272 raise ExtractError("could not change mode")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002273
2274 def utime(self, tarinfo, targetpath):
2275 """Set modification time of targetpath according to tarinfo.
2276 """
Jack Jansen834eff62003-03-07 12:47:06 +00002277 if not hasattr(os, 'utime'):
Tim Petersf9347782003-03-07 15:36:41 +00002278 return
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002279 if sys.platform == "win32" and tarinfo.isdir():
2280 # According to msdn.microsoft.com, it is an error (EACCES)
2281 # to use utime() on directories.
2282 return
2283 try:
2284 os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
Guido van Rossumb940e112007-01-10 16:19:56 +00002285 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002286 raise ExtractError("could not change modification time")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002287
2288 #--------------------------------------------------------------------------
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002289 def next(self):
2290 """Return the next member of the archive as a TarInfo object, when
2291 TarFile is opened for reading. Return None if there is no more
2292 available.
2293 """
2294 self._check("ra")
2295 if self.firstmember is not None:
2296 m = self.firstmember
2297 self.firstmember = None
2298 return m
2299
2300 # Read the next block.
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002301 self.fileobj.seek(self.offset)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002302 while True:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002303 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002304 tarinfo = self.tarinfo.fromtarfile(self)
2305 if tarinfo is None:
2306 return
2307 self.members.append(tarinfo)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002308
Guido van Rossumb940e112007-01-10 16:19:56 +00002309 except HeaderError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002310 if self.ignore_zeros:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00002311 self._dbg(2, "0x%X: %s" % (self.offset, e))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002312 self.offset += BLOCKSIZE
2313 continue
2314 else:
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002315 if self.offset == 0:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00002316 raise ReadError(str(e))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002317 return None
2318 break
2319
Thomas Wouters477c8d52006-05-27 19:21:47 +00002320 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002321
2322 #--------------------------------------------------------------------------
2323 # Little helper methods:
2324
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002325 def _getmember(self, name, tarinfo=None):
2326 """Find an archive member by name from bottom to top.
2327 If tarinfo is given, it is used as the starting point.
2328 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002329 # Ensure that all members have been loaded.
2330 members = self.getmembers()
2331
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002332 if tarinfo is None:
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002333 end = len(members)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002334 else:
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002335 end = members.index(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002336
Guido van Rossum805365e2007-05-07 22:24:25 +00002337 for i in range(end - 1, -1, -1):
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002338 if name == members[i].name:
2339 return members[i]
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002340
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002341 def _load(self):
2342 """Read through the entire archive file and look for readable
2343 members.
2344 """
2345 while True:
2346 tarinfo = self.next()
2347 if tarinfo is None:
2348 break
2349 self._loaded = True
2350
2351 def _check(self, mode=None):
2352 """Check if TarFile is still open, and if the operation's mode
2353 corresponds to TarFile's mode.
2354 """
2355 if self.closed:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002356 raise IOError("%s is closed" % self.__class__.__name__)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002357 if mode is not None and self.mode not in mode:
2358 raise IOError("bad operation for mode %r" % self.mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002359
2360 def __iter__(self):
2361 """Provide an iterator object.
2362 """
2363 if self._loaded:
2364 return iter(self.members)
2365 else:
2366 return TarIter(self)
2367
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002368 def _dbg(self, level, msg):
2369 """Write debugging output to sys.stderr.
2370 """
2371 if level <= self.debug:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002372 print(msg, file=sys.stderr)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002373# class TarFile
2374
2375class TarIter:
2376 """Iterator Class.
2377
2378 for tarinfo in TarFile(...):
2379 suite...
2380 """
2381
2382 def __init__(self, tarfile):
2383 """Construct a TarIter object.
2384 """
2385 self.tarfile = tarfile
Martin v. Löwis637431b2005-03-03 23:12:42 +00002386 self.index = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002387 def __iter__(self):
2388 """Return iterator object.
2389 """
2390 return self
Georg Brandla18af4e2007-04-21 15:47:16 +00002391 def __next__(self):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002392 """Return the next item using TarFile's next() method.
2393 When all members have been read, set TarFile as _loaded.
2394 """
Martin v. Löwis637431b2005-03-03 23:12:42 +00002395 # Fix for SF #1100429: Under rare circumstances it can
2396 # happen that getmembers() is called during iteration,
2397 # which will cause TarIter to stop prematurely.
2398 if not self.tarfile._loaded:
2399 tarinfo = self.tarfile.next()
2400 if not tarinfo:
2401 self.tarfile._loaded = True
2402 raise StopIteration
2403 else:
2404 try:
2405 tarinfo = self.tarfile.members[self.index]
2406 except IndexError:
2407 raise StopIteration
2408 self.index += 1
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002409 return tarinfo
2410
2411# Helper classes for sparse file support
2412class _section:
2413 """Base class for _data and _hole.
2414 """
2415 def __init__(self, offset, size):
2416 self.offset = offset
2417 self.size = size
2418 def __contains__(self, offset):
2419 return self.offset <= offset < self.offset + self.size
2420
2421class _data(_section):
2422 """Represent a data section in a sparse file.
2423 """
2424 def __init__(self, offset, size, realpos):
2425 _section.__init__(self, offset, size)
2426 self.realpos = realpos
2427
2428class _hole(_section):
2429 """Represent a hole section in a sparse file.
2430 """
2431 pass
2432
2433class _ringbuffer(list):
2434 """Ringbuffer class which increases performance
2435 over a regular list.
2436 """
2437 def __init__(self):
2438 self.idx = 0
2439 def find(self, offset):
2440 idx = self.idx
2441 while True:
2442 item = self[idx]
2443 if offset in item:
2444 break
2445 idx += 1
2446 if idx == len(self):
2447 idx = 0
2448 if idx == self.idx:
2449 # End of File
2450 return None
2451 self.idx = idx
2452 return item
2453
2454#---------------------------------------------
2455# zipfile compatible TarFile class
2456#---------------------------------------------
2457TAR_PLAIN = 0 # zipfile.ZIP_STORED
2458TAR_GZIPPED = 8 # zipfile.ZIP_DEFLATED
2459class TarFileCompat:
2460 """TarFile class compatible with standard module zipfile's
2461 ZipFile class.
2462 """
2463 def __init__(self, file, mode="r", compression=TAR_PLAIN):
2464 if compression == TAR_PLAIN:
2465 self.tarfile = TarFile.taropen(file, mode)
2466 elif compression == TAR_GZIPPED:
2467 self.tarfile = TarFile.gzopen(file, mode)
2468 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002469 raise ValueError("unknown compression constant")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002470 if mode[0:1] == "r":
2471 members = self.tarfile.getmembers()
Raymond Hettingera1d09e22005-09-11 16:34:05 +00002472 for m in members:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002473 m.filename = m.name
2474 m.file_size = m.size
2475 m.date_time = time.gmtime(m.mtime)[:6]
2476 def namelist(self):
2477 return map(lambda m: m.name, self.infolist())
2478 def infolist(self):
2479 return filter(lambda m: m.type in REGULAR_TYPES,
2480 self.tarfile.getmembers())
2481 def printdir(self):
2482 self.tarfile.list()
2483 def testzip(self):
2484 return
2485 def getinfo(self, name):
2486 return self.tarfile.getmember(name)
2487 def read(self, name):
2488 return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
2489 def write(self, filename, arcname=None, compress_type=None):
2490 self.tarfile.add(filename, arcname)
2491 def writestr(self, zinfo, bytes):
Guido van Rossum68937b42007-05-18 00:51:22 +00002492 from io import StringIO
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002493 import calendar
2494 zinfo.name = zinfo.filename
2495 zinfo.size = zinfo.file_size
2496 zinfo.mtime = calendar.timegm(zinfo.date_time)
Raymond Hettingera6172712004-12-31 19:15:26 +00002497 self.tarfile.addfile(zinfo, StringIO(bytes))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002498 def close(self):
2499 self.tarfile.close()
2500#class TarFileCompat
2501
2502#--------------------
2503# exported functions
2504#--------------------
2505def is_tarfile(name):
2506 """Return True if name points to a tar archive that we
2507 are able to handle, else return False.
2508 """
2509 try:
2510 t = open(name)
2511 t.close()
2512 return True
2513 except TarError:
2514 return False
2515
Guido van Rossume7ba4952007-06-06 23:52:48 +00002516bltn_open = open
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002517open = TarFile.open