blob: beb413572467eaf3ef0ffc8a2daa54a7a2f3d0ed [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
Lars Gustäbelf7317f92010-04-29 15:42:25 +0000352 self.fd = os.open(name, mode, 0o666)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000353
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
Antoine Pitrouc8428d32009-12-14 18:23:30 +0000403 self.crc = zlib.crc32(b"")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000404 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:
Lars Gustäbel42e00912009-03-22 20:34:29 +0000642 raw = self.fileobj.read(self.blocksize)
643 if not raw:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000644 break
Lars Gustäbel42e00912009-03-22 20:34:29 +0000645 data = self.bz2obj.decompress(raw)
646 self.buf += data
Thomas Wouters477c8d52006-05-27 19:21:47 +0000647 x += len(data)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000648
649 buf = self.buf[:size]
650 self.buf = self.buf[size:]
651 self.pos += len(buf)
652 return buf
653
654 def seek(self, pos):
655 if pos < self.pos:
656 self.init()
657 self.read(pos - self.pos)
658
659 def tell(self):
660 return self.pos
661
662 def write(self, data):
663 self.pos += len(data)
664 raw = self.bz2obj.compress(data)
665 self.fileobj.write(raw)
666
667 def close(self):
668 if self.mode == "w":
669 raw = self.bz2obj.flush()
670 self.fileobj.write(raw)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000671# class _BZ2Proxy
672
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000673#------------------------
674# Extraction file object
675#------------------------
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000676class _FileInFile(object):
677 """A thin wrapper around an existing file object that
678 provides a part of its data as an individual file
679 object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000680 """
681
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000682 def __init__(self, fileobj, offset, size, sparse=None):
683 self.fileobj = fileobj
684 self.offset = offset
685 self.size = size
686 self.sparse = sparse
687 self.position = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000688
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000689 def seekable(self):
690 if not hasattr(self.fileobj, "seekable"):
691 # XXX gzip.GzipFile and bz2.BZ2File
692 return True
693 return self.fileobj.seekable()
694
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000695 def tell(self):
696 """Return the current file position.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000697 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000698 return self.position
699
700 def seek(self, position):
701 """Seek to a position in the file.
702 """
703 self.position = position
704
705 def read(self, size=None):
706 """Read data from the file.
707 """
708 if size is None:
709 size = self.size - self.position
710 else:
711 size = min(size, self.size - self.position)
712
713 if self.sparse is None:
714 return self.readnormal(size)
715 else:
716 return self.readsparse(size)
717
718 def readnormal(self, size):
719 """Read operation for regular files.
720 """
721 self.fileobj.seek(self.offset + self.position)
722 self.position += size
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000723 return self.fileobj.read(size)
724
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000725 def readsparse(self, size):
726 """Read operation for sparse files.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000727 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000728 data = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000729 while size > 0:
730 buf = self.readsparsesection(size)
731 if not buf:
732 break
733 size -= len(buf)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000734 data += buf
735 return data
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000736
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000737 def readsparsesection(self, size):
738 """Read a single section of a sparse file.
739 """
740 section = self.sparse.find(self.position)
741
742 if section is None:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000743 return b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000744
745 size = min(size, section.offset + section.size - self.position)
746
747 if isinstance(section, _data):
748 realpos = section.realpos + self.position - section.offset
749 self.fileobj.seek(self.offset + realpos)
750 self.position += size
751 return self.fileobj.read(size)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000752 else:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000753 self.position += size
754 return NUL * size
755#class _FileInFile
756
757
758class ExFileObject(object):
759 """File-like object for reading an archive member.
760 Is returned by TarFile.extractfile().
761 """
762 blocksize = 1024
763
764 def __init__(self, tarfile, tarinfo):
765 self.fileobj = _FileInFile(tarfile.fileobj,
766 tarinfo.offset_data,
767 tarinfo.size,
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +0000768 tarinfo.sparse)
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000769 self.name = tarinfo.name
770 self.mode = "r"
771 self.closed = False
772 self.size = tarinfo.size
773
774 self.position = 0
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000775 self.buffer = b""
776
777 def readable(self):
778 return True
779
780 def writable(self):
781 return False
782
783 def seekable(self):
784 return self.fileobj.seekable()
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000785
786 def read(self, size=None):
787 """Read at most size bytes from the file. If size is not
788 present or None, read all data until EOF is reached.
789 """
790 if self.closed:
791 raise ValueError("I/O operation on closed file")
792
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000793 buf = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000794 if self.buffer:
795 if size is None:
796 buf = self.buffer
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000797 self.buffer = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000798 else:
799 buf = self.buffer[:size]
800 self.buffer = self.buffer[size:]
801
802 if size is None:
803 buf += self.fileobj.read()
804 else:
805 buf += self.fileobj.read(size - len(buf))
806
807 self.position += len(buf)
808 return buf
809
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000810 # XXX TextIOWrapper uses the read1() method.
811 read1 = read
812
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000813 def readline(self, size=-1):
814 """Read one entire line from the file. If size is present
815 and non-negative, return a string with at most that
816 size, which may be an incomplete line.
817 """
818 if self.closed:
819 raise ValueError("I/O operation on closed file")
820
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000821 pos = self.buffer.find(b"\n") + 1
822 if pos == 0:
823 # no newline found.
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000824 while True:
825 buf = self.fileobj.read(self.blocksize)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000826 self.buffer += buf
827 if not buf or b"\n" in buf:
828 pos = self.buffer.find(b"\n") + 1
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000829 if pos == 0:
830 # no newline found.
831 pos = len(self.buffer)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000832 break
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000833
834 if size != -1:
835 pos = min(size, pos)
836
837 buf = self.buffer[:pos]
838 self.buffer = self.buffer[pos:]
839 self.position += len(buf)
840 return buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000841
842 def readlines(self):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000843 """Return a list with all remaining lines.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000844 """
845 result = []
846 while True:
847 line = self.readline()
848 if not line: break
849 result.append(line)
850 return result
851
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000852 def tell(self):
853 """Return the current file position.
854 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000855 if self.closed:
856 raise ValueError("I/O operation on closed file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000857
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000858 return self.position
859
860 def seek(self, pos, whence=os.SEEK_SET):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000861 """Seek to a position in the file.
862 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000863 if self.closed:
864 raise ValueError("I/O operation on closed file")
865
866 if whence == os.SEEK_SET:
867 self.position = min(max(pos, 0), self.size)
868 elif whence == os.SEEK_CUR:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000869 if pos < 0:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000870 self.position = max(self.position + pos, 0)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000871 else:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000872 self.position = min(self.position + pos, self.size)
873 elif whence == os.SEEK_END:
874 self.position = max(min(self.size + pos, self.size), 0)
875 else:
876 raise ValueError("Invalid argument")
877
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000878 self.buffer = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000879 self.fileobj.seek(self.position)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000880
881 def close(self):
882 """Close the file object.
883 """
884 self.closed = True
Martin v. Löwisdf241532005-03-03 08:17:42 +0000885
886 def __iter__(self):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000887 """Get an iterator over the file's lines.
Martin v. Löwisdf241532005-03-03 08:17:42 +0000888 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000889 while True:
890 line = self.readline()
891 if not line:
892 break
893 yield line
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000894#class ExFileObject
895
896#------------------
897# Exported Classes
898#------------------
899class TarInfo(object):
900 """Informational class which holds the details about an
901 archive member given by a tar header block.
902 TarInfo objects are returned by TarFile.getmember(),
903 TarFile.getmembers() and TarFile.gettarinfo() and are
904 usually created internally.
905 """
906
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +0000907 __slots__ = ("name", "mode", "uid", "gid", "size", "mtime",
908 "chksum", "type", "linkname", "uname", "gname",
909 "devmajor", "devminor",
910 "offset", "offset_data", "pax_headers", "sparse",
911 "tarfile", "_sparse_structs", "_link_target")
912
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000913 def __init__(self, name=""):
914 """Construct a TarInfo object. name is the optional name
915 of the member.
916 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000917 self.name = name # member name
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000918 self.mode = 0o644 # file permissions
Thomas Wouters477c8d52006-05-27 19:21:47 +0000919 self.uid = 0 # user id
920 self.gid = 0 # group id
921 self.size = 0 # file size
922 self.mtime = 0 # modification time
923 self.chksum = 0 # header checksum
924 self.type = REGTYPE # member type
925 self.linkname = "" # link name
Lars Gustäbel2fdbfc52010-10-04 15:31:05 +0000926 self.uname = "" # user name
927 self.gname = "" # group name
Thomas Wouters477c8d52006-05-27 19:21:47 +0000928 self.devmajor = 0 # device major number
929 self.devminor = 0 # device minor number
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000930
Thomas Wouters477c8d52006-05-27 19:21:47 +0000931 self.offset = 0 # the tar header starts here
932 self.offset_data = 0 # the file's data starts here
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000933
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +0000934 self.sparse = None # sparse member information
Guido van Rossumd8faa362007-04-27 19:54:29 +0000935 self.pax_headers = {} # pax header information
936
937 # In pax headers the "name" and "linkname" field are called
938 # "path" and "linkpath".
939 def _getpath(self):
940 return self.name
941 def _setpath(self, name):
942 self.name = name
943 path = property(_getpath, _setpath)
944
945 def _getlinkpath(self):
946 return self.linkname
947 def _setlinkpath(self, linkname):
948 self.linkname = linkname
949 linkpath = property(_getlinkpath, _setlinkpath)
950
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000951 def __repr__(self):
952 return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self))
953
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000954 def get_info(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000955 """Return the TarInfo's attributes as a dictionary.
956 """
957 info = {
958 "name": normpath(self.name),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000959 "mode": self.mode & 0o7777,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000960 "uid": self.uid,
961 "gid": self.gid,
962 "size": self.size,
963 "mtime": self.mtime,
964 "chksum": self.chksum,
965 "type": self.type,
966 "linkname": normpath(self.linkname) if self.linkname else "",
967 "uname": self.uname,
968 "gname": self.gname,
969 "devmajor": self.devmajor,
970 "devminor": self.devminor
971 }
972
973 if info["type"] == DIRTYPE and not info["name"].endswith("/"):
974 info["name"] += "/"
975
976 return info
977
Guido van Rossume7ba4952007-06-06 23:52:48 +0000978 def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="strict"):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000979 """Return a tar header as a string of 512 byte blocks.
980 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000981 info = self.get_info()
Guido van Rossume7ba4952007-06-06 23:52:48 +0000982
Guido van Rossumd8faa362007-04-27 19:54:29 +0000983 if format == USTAR_FORMAT:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000984 return self.create_ustar_header(info, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000985 elif format == GNU_FORMAT:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000986 return self.create_gnu_header(info, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000987 elif format == PAX_FORMAT:
Lars Gustäbel3741eff2007-08-21 12:17:05 +0000988 return self.create_pax_header(info)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000989 else:
990 raise ValueError("invalid format")
991
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000992 def create_ustar_header(self, info, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000993 """Return the object as a ustar header block.
994 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000995 info["magic"] = POSIX_MAGIC
996
997 if len(info["linkname"]) > LENGTH_LINK:
998 raise ValueError("linkname is too long")
999
1000 if len(info["name"]) > LENGTH_NAME:
1001 info["prefix"], info["name"] = self._posix_split_name(info["name"])
1002
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001003 return self._create_header(info, USTAR_FORMAT, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001004
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001005 def create_gnu_header(self, info, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001006 """Return the object as a GNU header block sequence.
1007 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001008 info["magic"] = GNU_MAGIC
1009
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001010 buf = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001011 if len(info["linkname"]) > LENGTH_LINK:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001012 buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001013
1014 if len(info["name"]) > LENGTH_NAME:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001015 buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001016
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001017 return buf + self._create_header(info, GNU_FORMAT, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001018
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001019 def create_pax_header(self, info):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001020 """Return the object as a ustar header block. If it cannot be
1021 represented this way, prepend a pax extended header sequence
1022 with supplement information.
1023 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001024 info["magic"] = POSIX_MAGIC
1025 pax_headers = self.pax_headers.copy()
1026
1027 # Test string fields for values that exceed the field length or cannot
1028 # be represented in ASCII encoding.
1029 for name, hname, length in (
1030 ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK),
1031 ("uname", "uname", 32), ("gname", "gname", 32)):
1032
Guido van Rossume7ba4952007-06-06 23:52:48 +00001033 if hname in pax_headers:
1034 # The pax header has priority.
1035 continue
1036
Guido van Rossumd8faa362007-04-27 19:54:29 +00001037 # Try to encode the string as ASCII.
1038 try:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001039 info[name].encode("ascii", "strict")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001040 except UnicodeEncodeError:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001041 pax_headers[hname] = info[name]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001042 continue
1043
Guido van Rossume7ba4952007-06-06 23:52:48 +00001044 if len(info[name]) > length:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001045 pax_headers[hname] = info[name]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001046
1047 # Test number fields for values that exceed the field limit or values
1048 # that like to be stored as float.
1049 for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)):
Guido van Rossume7ba4952007-06-06 23:52:48 +00001050 if name in pax_headers:
1051 # The pax header has priority. Avoid overflow.
1052 info[name] = 0
1053 continue
1054
Guido van Rossumd8faa362007-04-27 19:54:29 +00001055 val = info[name]
1056 if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float):
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001057 pax_headers[name] = str(val)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001058 info[name] = 0
1059
Guido van Rossume7ba4952007-06-06 23:52:48 +00001060 # Create a pax extended header if necessary.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001061 if pax_headers:
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001062 buf = self._create_pax_generic_header(pax_headers, XHDTYPE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001063 else:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001064 buf = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001065
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001066 return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001067
1068 @classmethod
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001069 def create_pax_global_header(cls, pax_headers):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001070 """Return the object as a pax global header block sequence.
1071 """
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001072 return cls._create_pax_generic_header(pax_headers, XGLTYPE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001073
1074 def _posix_split_name(self, name):
1075 """Split a name longer than 100 chars into a prefix
1076 and a name part.
1077 """
1078 prefix = name[:LENGTH_PREFIX + 1]
1079 while prefix and prefix[-1] != "/":
1080 prefix = prefix[:-1]
1081
1082 name = name[len(prefix):]
1083 prefix = prefix[:-1]
1084
1085 if not prefix or len(name) > LENGTH_NAME:
1086 raise ValueError("name is too long")
1087 return prefix, name
1088
1089 @staticmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001090 def _create_header(info, format, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001091 """Return a header block. info is a dictionary with file
1092 information, format must be one of the *_FORMAT constants.
1093 """
1094 parts = [
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001095 stn(info.get("name", ""), 100, encoding, errors),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001096 itn(info.get("mode", 0) & 0o7777, 8, format),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001097 itn(info.get("uid", 0), 8, format),
1098 itn(info.get("gid", 0), 8, format),
1099 itn(info.get("size", 0), 12, format),
1100 itn(info.get("mtime", 0), 12, format),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001101 b" ", # checksum field
Guido van Rossumd8faa362007-04-27 19:54:29 +00001102 info.get("type", REGTYPE),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001103 stn(info.get("linkname", ""), 100, encoding, errors),
1104 info.get("magic", POSIX_MAGIC),
Lars Gustäbel2fdbfc52010-10-04 15:31:05 +00001105 stn(info.get("uname", ""), 32, encoding, errors),
1106 stn(info.get("gname", ""), 32, encoding, errors),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001107 itn(info.get("devmajor", 0), 8, format),
1108 itn(info.get("devminor", 0), 8, format),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001109 stn(info.get("prefix", ""), 155, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001110 ]
1111
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001112 buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001113 chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
Lars Gustäbela280ca752007-08-28 07:34:33 +00001114 buf = buf[:-364] + bytes("%06o\0" % chksum, "ascii") + buf[-357:]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001115 return buf
1116
1117 @staticmethod
1118 def _create_payload(payload):
1119 """Return the string payload filled with zero bytes
1120 up to the next 512 byte border.
1121 """
1122 blocks, remainder = divmod(len(payload), BLOCKSIZE)
1123 if remainder > 0:
1124 payload += (BLOCKSIZE - remainder) * NUL
1125 return payload
1126
1127 @classmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001128 def _create_gnu_long_header(cls, name, type, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001129 """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence
1130 for name.
1131 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001132 name = name.encode(encoding, errors) + NUL
Guido van Rossumd8faa362007-04-27 19:54:29 +00001133
1134 info = {}
1135 info["name"] = "././@LongLink"
1136 info["type"] = type
1137 info["size"] = len(name)
1138 info["magic"] = GNU_MAGIC
1139
1140 # create extended header + name blocks.
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001141 return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \
Guido van Rossumd8faa362007-04-27 19:54:29 +00001142 cls._create_payload(name)
1143
1144 @classmethod
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001145 def _create_pax_generic_header(cls, pax_headers, type):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001146 """Return a POSIX.1-2001 extended or global header sequence
1147 that contains a list of keyword, value pairs. The values
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001148 must be strings.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001149 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001150 records = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001151 for keyword, value in pax_headers.items():
1152 keyword = keyword.encode("utf8")
1153 value = value.encode("utf8")
1154 l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n'
1155 n = p = 0
1156 while True:
1157 n = l + len(str(p))
1158 if n == p:
1159 break
1160 p = n
Lars Gustäbela280ca752007-08-28 07:34:33 +00001161 records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n"
Guido van Rossumd8faa362007-04-27 19:54:29 +00001162
1163 # We use a hardcoded "././@PaxHeader" name like star does
1164 # instead of the one that POSIX recommends.
1165 info = {}
1166 info["name"] = "././@PaxHeader"
1167 info["type"] = type
1168 info["size"] = len(records)
1169 info["magic"] = POSIX_MAGIC
1170
1171 # Create pax header + record blocks.
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001172 return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \
Guido van Rossumd8faa362007-04-27 19:54:29 +00001173 cls._create_payload(records)
1174
Guido van Rossum75b64e62005-01-16 00:16:11 +00001175 @classmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001176 def frombuf(cls, buf, encoding, errors):
1177 """Construct a TarInfo object from a 512 byte bytes object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001178 """
Thomas Wouters477c8d52006-05-27 19:21:47 +00001179 if len(buf) != BLOCKSIZE:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001180 raise HeaderError("truncated header")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001181 if buf.count(NUL) == BLOCKSIZE:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001182 raise HeaderError("empty header")
1183
1184 chksum = nti(buf[148:156])
1185 if chksum not in calc_chksums(buf):
1186 raise HeaderError("bad checksum")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001187
Guido van Rossumd8faa362007-04-27 19:54:29 +00001188 obj = cls()
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001189 obj.name = nts(buf[0:100], encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001190 obj.mode = nti(buf[100:108])
1191 obj.uid = nti(buf[108:116])
1192 obj.gid = nti(buf[116:124])
1193 obj.size = nti(buf[124:136])
1194 obj.mtime = nti(buf[136:148])
1195 obj.chksum = chksum
1196 obj.type = buf[156:157]
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001197 obj.linkname = nts(buf[157:257], encoding, errors)
1198 obj.uname = nts(buf[265:297], encoding, errors)
1199 obj.gname = nts(buf[297:329], encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001200 obj.devmajor = nti(buf[329:337])
1201 obj.devminor = nti(buf[337:345])
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001202 prefix = nts(buf[345:500], encoding, errors)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001203
Guido van Rossumd8faa362007-04-27 19:54:29 +00001204 # Old V7 tar format represents a directory as a regular
1205 # file with a trailing slash.
1206 if obj.type == AREGTYPE and obj.name.endswith("/"):
1207 obj.type = DIRTYPE
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001208
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001209 # The old GNU sparse format occupies some of the unused
1210 # space in the buffer for up to 4 sparse structures.
1211 # Save the them for later processing in _proc_sparse().
1212 if obj.type == GNUTYPE_SPARSE:
1213 pos = 386
1214 structs = []
1215 for i in range(4):
1216 try:
1217 offset = nti(buf[pos:pos + 12])
1218 numbytes = nti(buf[pos + 12:pos + 24])
1219 except ValueError:
1220 break
1221 structs.append((offset, numbytes))
1222 pos += 24
1223 isextended = bool(buf[482])
1224 origsize = nti(buf[483:495])
1225 obj._sparse_structs = (structs, isextended, origsize)
1226
Guido van Rossumd8faa362007-04-27 19:54:29 +00001227 # Remove redundant slashes from directories.
1228 if obj.isdir():
1229 obj.name = obj.name.rstrip("/")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001230
Guido van Rossumd8faa362007-04-27 19:54:29 +00001231 # Reconstruct a ustar longname.
1232 if prefix and obj.type not in GNU_TYPES:
1233 obj.name = prefix + "/" + obj.name
1234 return obj
1235
1236 @classmethod
1237 def fromtarfile(cls, tarfile):
1238 """Return the next TarInfo object from TarFile object
1239 tarfile.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001240 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001241 buf = tarfile.fileobj.read(BLOCKSIZE)
1242 if not buf:
1243 return
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001244 obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001245 obj.offset = tarfile.fileobj.tell() - BLOCKSIZE
1246 return obj._proc_member(tarfile)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001247
Guido van Rossumd8faa362007-04-27 19:54:29 +00001248 #--------------------------------------------------------------------------
1249 # The following are methods that are called depending on the type of a
1250 # member. The entry point is _proc_member() which can be overridden in a
1251 # subclass to add custom _proc_*() methods. A _proc_*() method MUST
1252 # implement the following
1253 # operations:
1254 # 1. Set self.offset_data to the position where the data blocks begin,
1255 # if there is data that follows.
1256 # 2. Set tarfile.offset to the position where the next member's header will
1257 # begin.
1258 # 3. Return self or another valid TarInfo object.
1259 def _proc_member(self, tarfile):
1260 """Choose the right processing method depending on
1261 the type and call it.
Thomas Wouters89f507f2006-12-13 04:49:30 +00001262 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001263 if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
1264 return self._proc_gnulong(tarfile)
1265 elif self.type == GNUTYPE_SPARSE:
1266 return self._proc_sparse(tarfile)
1267 elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE):
1268 return self._proc_pax(tarfile)
1269 else:
1270 return self._proc_builtin(tarfile)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001271
Guido van Rossumd8faa362007-04-27 19:54:29 +00001272 def _proc_builtin(self, tarfile):
1273 """Process a builtin type or an unknown type which
1274 will be treated as a regular file.
1275 """
1276 self.offset_data = tarfile.fileobj.tell()
1277 offset = self.offset_data
1278 if self.isreg() or self.type not in SUPPORTED_TYPES:
1279 # Skip the following data blocks.
1280 offset += self._block(self.size)
1281 tarfile.offset = offset
Thomas Wouters89f507f2006-12-13 04:49:30 +00001282
Guido van Rossume7ba4952007-06-06 23:52:48 +00001283 # Patch the TarInfo object with saved global
Guido van Rossumd8faa362007-04-27 19:54:29 +00001284 # header information.
Guido van Rossume7ba4952007-06-06 23:52:48 +00001285 self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001286
1287 return self
1288
1289 def _proc_gnulong(self, tarfile):
1290 """Process the blocks that hold a GNU longname
1291 or longlink member.
1292 """
1293 buf = tarfile.fileobj.read(self._block(self.size))
1294
1295 # Fetch the next header and process it.
Guido van Rossume7ba4952007-06-06 23:52:48 +00001296 next = self.fromtarfile(tarfile)
1297 if next is None:
1298 raise HeaderError("missing subsequent header")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001299
1300 # Patch the TarInfo object from the next header with
1301 # the longname information.
1302 next.offset = self.offset
1303 if self.type == GNUTYPE_LONGNAME:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001304 next.name = nts(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001305 elif self.type == GNUTYPE_LONGLINK:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001306 next.linkname = nts(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001307
1308 return next
1309
1310 def _proc_sparse(self, tarfile):
1311 """Process a GNU sparse header plus extra headers.
1312 """
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001313 # We already collected some sparse structures in frombuf().
1314 structs, isextended, origsize = self._sparse_structs
1315 del self._sparse_structs
Guido van Rossumd8faa362007-04-27 19:54:29 +00001316
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001317 # Collect sparse structures from extended header blocks.
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001318 while isextended:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001319 buf = tarfile.fileobj.read(BLOCKSIZE)
1320 pos = 0
Guido van Rossum805365e2007-05-07 22:24:25 +00001321 for i in range(21):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001322 try:
1323 offset = nti(buf[pos:pos + 12])
1324 numbytes = nti(buf[pos + 12:pos + 24])
1325 except ValueError:
1326 break
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001327 structs.append((offset, numbytes))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001328 pos += 24
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001329 isextended = bool(buf[504])
Guido van Rossumd8faa362007-04-27 19:54:29 +00001330
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001331 # Transform the sparse structures to something we can use
1332 # in ExFileObject.
1333 self.sparse = _ringbuffer()
1334 lastpos = 0
1335 realpos = 0
1336 for offset, numbytes in structs:
1337 if offset > lastpos:
1338 self.sparse.append(_hole(lastpos, offset - lastpos))
1339 self.sparse.append(_data(offset, numbytes, realpos))
1340 realpos += numbytes
1341 lastpos = offset + numbytes
Guido van Rossumd8faa362007-04-27 19:54:29 +00001342 if lastpos < origsize:
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001343 self.sparse.append(_hole(lastpos, origsize - lastpos))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001344
1345 self.offset_data = tarfile.fileobj.tell()
1346 tarfile.offset = self.offset_data + self._block(self.size)
1347 self.size = origsize
1348
1349 return self
1350
1351 def _proc_pax(self, tarfile):
1352 """Process an extended or global header as described in
1353 POSIX.1-2001.
1354 """
1355 # Read the header information.
1356 buf = tarfile.fileobj.read(self._block(self.size))
1357
1358 # A pax header stores supplemental information for either
1359 # the following file (extended) or all following files
1360 # (global).
1361 if self.type == XGLTYPE:
1362 pax_headers = tarfile.pax_headers
1363 else:
1364 pax_headers = tarfile.pax_headers.copy()
1365
Guido van Rossumd8faa362007-04-27 19:54:29 +00001366 # Parse pax header information. A record looks like that:
1367 # "%d %s=%s\n" % (length, keyword, value). length is the size
1368 # of the complete record including the length field itself and
Guido van Rossume7ba4952007-06-06 23:52:48 +00001369 # the newline. keyword and value are both UTF-8 encoded strings.
Antoine Pitroufd036452008-08-19 17:56:33 +00001370 regex = re.compile(br"(\d+) ([^=]+)=")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001371 pos = 0
1372 while True:
1373 match = regex.match(buf, pos)
1374 if not match:
1375 break
1376
1377 length, keyword = match.groups()
1378 length = int(length)
1379 value = buf[match.end(2) + 1:match.start(1) + length - 1]
1380
1381 keyword = keyword.decode("utf8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001382 value = value.decode("utf8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001383
1384 pax_headers[keyword] = value
1385 pos += length
1386
Guido van Rossume7ba4952007-06-06 23:52:48 +00001387 # Fetch the next header.
1388 next = self.fromtarfile(tarfile)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001389
Guido van Rossume7ba4952007-06-06 23:52:48 +00001390 if self.type in (XHDTYPE, SOLARIS_XHDTYPE):
1391 if next is None:
1392 raise HeaderError("missing subsequent header")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001393
Guido van Rossume7ba4952007-06-06 23:52:48 +00001394 # Patch the TarInfo object with the extended header info.
1395 next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors)
1396 next.offset = self.offset
1397
1398 if "size" in pax_headers:
1399 # If the extended header replaces the size field,
1400 # we need to recalculate the offset where the next
1401 # header starts.
1402 offset = next.offset_data
1403 if next.isreg() or next.type not in SUPPORTED_TYPES:
1404 offset += next._block(next.size)
1405 tarfile.offset = offset
1406
1407 return next
1408
1409 def _apply_pax_info(self, pax_headers, encoding, errors):
1410 """Replace fields with supplemental information from a previous
1411 pax extended or global header.
1412 """
1413 for keyword, value in pax_headers.items():
1414 if keyword not in PAX_FIELDS:
1415 continue
1416
1417 if keyword == "path":
1418 value = value.rstrip("/")
1419
1420 if keyword in PAX_NUMBER_FIELDS:
1421 try:
1422 value = PAX_NUMBER_FIELDS[keyword](value)
1423 except ValueError:
1424 value = 0
Guido van Rossume7ba4952007-06-06 23:52:48 +00001425
1426 setattr(self, keyword, value)
1427
1428 self.pax_headers = pax_headers.copy()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001429
1430 def _block(self, count):
1431 """Round up a byte count by BLOCKSIZE and return it,
1432 e.g. _block(834) => 1024.
1433 """
1434 blocks, remainder = divmod(count, BLOCKSIZE)
1435 if remainder:
1436 blocks += 1
1437 return blocks * BLOCKSIZE
Thomas Wouters89f507f2006-12-13 04:49:30 +00001438
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001439 def isreg(self):
1440 return self.type in REGULAR_TYPES
1441 def isfile(self):
1442 return self.isreg()
1443 def isdir(self):
1444 return self.type == DIRTYPE
1445 def issym(self):
1446 return self.type == SYMTYPE
1447 def islnk(self):
1448 return self.type == LNKTYPE
1449 def ischr(self):
1450 return self.type == CHRTYPE
1451 def isblk(self):
1452 return self.type == BLKTYPE
1453 def isfifo(self):
1454 return self.type == FIFOTYPE
1455 def issparse(self):
1456 return self.type == GNUTYPE_SPARSE
1457 def isdev(self):
1458 return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
1459# class TarInfo
1460
1461class TarFile(object):
1462 """The TarFile Class provides an interface to tar archives.
1463 """
1464
1465 debug = 0 # May be set from 0 (no msgs) to 3 (all msgs)
1466
1467 dereference = False # If true, add content of linked file to the
1468 # tar file, else the link.
1469
1470 ignore_zeros = False # If true, skips empty or invalid blocks and
1471 # continues processing.
1472
1473 errorlevel = 0 # If 0, fatal errors only appear in debug
1474 # messages (if debug >= 0). If > 0, errors
1475 # are passed to the caller as exceptions.
1476
Guido van Rossumd8faa362007-04-27 19:54:29 +00001477 format = DEFAULT_FORMAT # The format to use when creating an archive.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001478
Guido van Rossume7ba4952007-06-06 23:52:48 +00001479 encoding = ENCODING # Encoding for 8-bit character strings.
1480
1481 errors = None # Error handler for unicode conversion.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001482
Guido van Rossumd8faa362007-04-27 19:54:29 +00001483 tarinfo = TarInfo # The default TarInfo class to use.
1484
1485 fileobject = ExFileObject # The default ExFileObject class to use.
1486
1487 def __init__(self, name=None, mode="r", fileobj=None, format=None,
1488 tarinfo=None, dereference=None, ignore_zeros=None, encoding=None,
Guido van Rossume7ba4952007-06-06 23:52:48 +00001489 errors=None, pax_headers=None, debug=None, errorlevel=None):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001490 """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
1491 read from an existing archive, 'a' to append data to an existing
1492 file or 'w' to create a new file overwriting an existing one. `mode'
1493 defaults to 'r'.
1494 If `fileobj' is given, it is used for reading or writing data. If it
1495 can be determined, `mode' is overridden by `fileobj's mode.
1496 `fileobj' is not closed, when TarFile is closed.
1497 """
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001498 if len(mode) > 1 or mode not in "raw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001499 raise ValueError("mode must be 'r', 'a' or 'w'")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001500 self.mode = mode
1501 self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001502
1503 if not fileobj:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001504 if self.mode == "a" and not os.path.exists(name):
Thomas Wouterscf297e42007-02-23 15:07:44 +00001505 # Create nonexistent files in append mode.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001506 self.mode = "w"
1507 self._mode = "wb"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001508 fileobj = bltn_open(name, self._mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001509 self._extfileobj = False
1510 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001511 if name is None and hasattr(fileobj, "name"):
1512 name = fileobj.name
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001513 if hasattr(fileobj, "mode"):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001514 self._mode = fileobj.mode
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001515 self._extfileobj = True
Thomas Woutersed03b412007-08-28 21:37:11 +00001516 self.name = os.path.abspath(name) if name else None
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001517 self.fileobj = fileobj
1518
Guido van Rossumd8faa362007-04-27 19:54:29 +00001519 # Init attributes.
1520 if format is not None:
1521 self.format = format
1522 if tarinfo is not None:
1523 self.tarinfo = tarinfo
1524 if dereference is not None:
1525 self.dereference = dereference
1526 if ignore_zeros is not None:
1527 self.ignore_zeros = ignore_zeros
1528 if encoding is not None:
1529 self.encoding = encoding
Guido van Rossume7ba4952007-06-06 23:52:48 +00001530
1531 if errors is not None:
1532 self.errors = errors
1533 elif mode == "r":
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001534 self.errors = "replace"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001535 else:
1536 self.errors = "strict"
1537
1538 if pax_headers is not None and self.format == PAX_FORMAT:
1539 self.pax_headers = pax_headers
1540 else:
1541 self.pax_headers = {}
1542
Guido van Rossumd8faa362007-04-27 19:54:29 +00001543 if debug is not None:
1544 self.debug = debug
1545 if errorlevel is not None:
1546 self.errorlevel = errorlevel
1547
1548 # Init datastructures.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001549 self.closed = False
1550 self.members = [] # list of members as TarInfo objects
1551 self._loaded = False # flag if all members have been read
Christian Heimesd8654cf2007-12-02 15:22:16 +00001552 self.offset = self.fileobj.tell()
1553 # current position in the archive file
Thomas Wouters477c8d52006-05-27 19:21:47 +00001554 self.inodes = {} # dictionary caching the inodes of
1555 # archive members already added
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001556
Lars Gustäbel7dfcef52009-11-18 21:11:27 +00001557 try:
1558 if self.mode == "r":
1559 self.firstmember = None
1560 self.firstmember = self.next()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001561
Lars Gustäbel7dfcef52009-11-18 21:11:27 +00001562 if self.mode == "a":
1563 # Move to the end of the archive,
1564 # before the first empty block.
1565 self.firstmember = None
1566 while True:
1567 if self.next() is None:
1568 if self.offset > 0:
1569 self.fileobj.seek(self.fileobj.tell() - BLOCKSIZE)
1570 break
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001571
Lars Gustäbel7dfcef52009-11-18 21:11:27 +00001572 if self.mode in "aw":
1573 self._loaded = True
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001574
Lars Gustäbel7dfcef52009-11-18 21:11:27 +00001575 if self.pax_headers:
1576 buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy())
1577 self.fileobj.write(buf)
1578 self.offset += len(buf)
1579 except:
1580 if not self._extfileobj:
1581 self.fileobj.close()
1582 self.closed = True
1583 raise
Guido van Rossumd8faa362007-04-27 19:54:29 +00001584
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001585 #--------------------------------------------------------------------------
1586 # Below are the classmethods which act as alternate constructors to the
1587 # TarFile class. The open() method is the only one that is needed for
1588 # public use; it is the "super"-constructor and is able to select an
1589 # adequate "sub"-constructor for a particular compression using the mapping
1590 # from OPEN_METH.
1591 #
1592 # This concept allows one to subclass TarFile without losing the comfort of
1593 # the super-constructor. A sub-constructor is registered and made available
1594 # by adding it to the mapping in OPEN_METH.
1595
Guido van Rossum75b64e62005-01-16 00:16:11 +00001596 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001597 def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001598 """Open a tar archive for reading, writing or appending. Return
1599 an appropriate TarFile class.
1600
1601 mode:
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001602 'r' or 'r:*' open for reading with transparent compression
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001603 'r:' open for reading exclusively uncompressed
1604 'r:gz' open for reading with gzip compression
1605 'r:bz2' open for reading with bzip2 compression
Thomas Wouterscf297e42007-02-23 15:07:44 +00001606 'a' or 'a:' open for appending, creating the file if necessary
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001607 'w' or 'w:' open for writing without compression
1608 'w:gz' open for writing with gzip compression
1609 'w:bz2' open for writing with bzip2 compression
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001610
1611 'r|*' open a stream of tar blocks with transparent compression
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001612 'r|' open an uncompressed stream of tar blocks for reading
1613 'r|gz' open a gzip compressed stream of tar blocks
1614 'r|bz2' open a bzip2 compressed stream of tar blocks
1615 'w|' open an uncompressed stream for writing
1616 'w|gz' open a gzip compressed stream for writing
1617 'w|bz2' open a bzip2 compressed stream for writing
1618 """
1619
1620 if not name and not fileobj:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001621 raise ValueError("nothing to open")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001622
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001623 if mode in ("r", "r:*"):
1624 # Find out which *open() is appropriate for opening the file.
1625 for comptype in cls.OPEN_METH:
1626 func = getattr(cls, cls.OPEN_METH[comptype])
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001627 if fileobj is not None:
1628 saved_pos = fileobj.tell()
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001629 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001630 return func(name, "r", fileobj, **kwargs)
1631 except (ReadError, CompressionError) as e:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001632 if fileobj is not None:
1633 fileobj.seek(saved_pos)
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001634 continue
Thomas Wouters477c8d52006-05-27 19:21:47 +00001635 raise ReadError("file could not be opened successfully")
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001636
1637 elif ":" in mode:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001638 filemode, comptype = mode.split(":", 1)
1639 filemode = filemode or "r"
1640 comptype = comptype or "tar"
1641
1642 # Select the *open() function according to
1643 # given compression.
1644 if comptype in cls.OPEN_METH:
1645 func = getattr(cls, cls.OPEN_METH[comptype])
1646 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001647 raise CompressionError("unknown compression type %r" % comptype)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001648 return func(name, filemode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001649
1650 elif "|" in mode:
1651 filemode, comptype = mode.split("|", 1)
1652 filemode = filemode or "r"
1653 comptype = comptype or "tar"
1654
1655 if filemode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001656 raise ValueError("mode must be 'r' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001657
1658 t = cls(name, filemode,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001659 _Stream(name, filemode, comptype, fileobj, bufsize),
1660 **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001661 t._extfileobj = False
1662 return t
1663
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001664 elif mode in "aw":
Guido van Rossumd8faa362007-04-27 19:54:29 +00001665 return cls.taropen(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001666
Thomas Wouters477c8d52006-05-27 19:21:47 +00001667 raise ValueError("undiscernible mode")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001668
Guido van Rossum75b64e62005-01-16 00:16:11 +00001669 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001670 def taropen(cls, name, mode="r", fileobj=None, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001671 """Open uncompressed tar archive name for reading or writing.
1672 """
1673 if len(mode) > 1 or mode not in "raw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001674 raise ValueError("mode must be 'r', 'a' or 'w'")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001675 return cls(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001676
Guido van Rossum75b64e62005-01-16 00:16:11 +00001677 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001678 def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001679 """Open gzip compressed tar archive name for reading or writing.
1680 Appending is not allowed.
1681 """
1682 if len(mode) > 1 or mode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001683 raise ValueError("mode must be 'r' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001684
1685 try:
1686 import gzip
Neal Norwitz4ec68242003-04-11 03:05:56 +00001687 gzip.GzipFile
1688 except (ImportError, AttributeError):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001689 raise CompressionError("gzip module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001690
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001691 if fileobj is None:
Guido van Rossume7ba4952007-06-06 23:52:48 +00001692 fileobj = bltn_open(name, mode + "b")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001693
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001694 try:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001695 t = cls.taropen(name, mode,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001696 gzip.GzipFile(name, mode, compresslevel, fileobj),
1697 **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001698 except IOError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001699 raise ReadError("not a gzip file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001700 t._extfileobj = False
1701 return t
1702
Guido van Rossum75b64e62005-01-16 00:16:11 +00001703 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001704 def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001705 """Open bzip2 compressed tar archive name for reading or writing.
1706 Appending is not allowed.
1707 """
1708 if len(mode) > 1 or mode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001709 raise ValueError("mode must be 'r' or 'w'.")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001710
1711 try:
1712 import bz2
1713 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001714 raise CompressionError("bz2 module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001715
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001716 if fileobj is not None:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001717 fileobj = _BZ2Proxy(fileobj, mode)
1718 else:
1719 fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001720
1721 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001722 t = cls.taropen(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001723 except IOError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001724 raise ReadError("not a bzip2 file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001725 t._extfileobj = False
1726 return t
1727
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001728 # All *open() methods are registered here.
1729 OPEN_METH = {
1730 "tar": "taropen", # uncompressed tar
1731 "gz": "gzopen", # gzip compressed tar
1732 "bz2": "bz2open" # bzip2 compressed tar
1733 }
1734
1735 #--------------------------------------------------------------------------
1736 # The public methods which TarFile provides:
1737
1738 def close(self):
1739 """Close the TarFile. In write-mode, two finishing zero blocks are
1740 appended to the archive.
1741 """
1742 if self.closed:
1743 return
1744
Guido van Rossumd8faa362007-04-27 19:54:29 +00001745 if self.mode in "aw":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001746 self.fileobj.write(NUL * (BLOCKSIZE * 2))
1747 self.offset += (BLOCKSIZE * 2)
1748 # fill up the end with zero-blocks
1749 # (like option -b20 for tar does)
1750 blocks, remainder = divmod(self.offset, RECORDSIZE)
1751 if remainder > 0:
1752 self.fileobj.write(NUL * (RECORDSIZE - remainder))
1753
1754 if not self._extfileobj:
1755 self.fileobj.close()
1756 self.closed = True
1757
1758 def getmember(self, name):
1759 """Return a TarInfo object for member `name'. If `name' can not be
1760 found in the archive, KeyError is raised. If a member occurs more
Mark Dickinson934896d2009-02-21 20:59:32 +00001761 than once in the archive, its last occurrence is assumed to be the
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001762 most up-to-date version.
1763 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001764 tarinfo = self._getmember(name)
1765 if tarinfo is None:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001766 raise KeyError("filename %r not found" % name)
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001767 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001768
1769 def getmembers(self):
1770 """Return the members of the archive as a list of TarInfo objects. The
1771 list has the same order as the members in the archive.
1772 """
1773 self._check()
1774 if not self._loaded: # if we want to obtain a list of
1775 self._load() # all members, we first have to
1776 # scan the whole archive.
1777 return self.members
1778
1779 def getnames(self):
1780 """Return the members of the archive as a list of their names. It has
1781 the same order as the list returned by getmembers().
1782 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001783 return [tarinfo.name for tarinfo in self.getmembers()]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001784
1785 def gettarinfo(self, name=None, arcname=None, fileobj=None):
1786 """Create a TarInfo object for either the file `name' or the file
1787 object `fileobj' (using os.fstat on its file descriptor). You can
1788 modify some of the TarInfo's attributes before you add it using
1789 addfile(). If given, `arcname' specifies an alternative name for the
1790 file in the archive.
1791 """
1792 self._check("aw")
1793
1794 # When fileobj is given, replace name by
1795 # fileobj's real name.
1796 if fileobj is not None:
1797 name = fileobj.name
1798
1799 # Building the name of the member in the archive.
1800 # Backward slashes are converted to forward slashes,
1801 # Absolute paths are turned to relative paths.
1802 if arcname is None:
1803 arcname = name
1804 arcname = normpath(arcname)
1805 drv, arcname = os.path.splitdrive(arcname)
1806 while arcname[0:1] == "/":
1807 arcname = arcname[1:]
1808
1809 # Now, fill the TarInfo object with
1810 # information specific for the file.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001811 tarinfo = self.tarinfo()
1812 tarinfo.tarfile = self
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001813
1814 # Use os.stat or os.lstat, depending on platform
1815 # and if symlinks shall be resolved.
1816 if fileobj is None:
1817 if hasattr(os, "lstat") and not self.dereference:
1818 statres = os.lstat(name)
1819 else:
1820 statres = os.stat(name)
1821 else:
1822 statres = os.fstat(fileobj.fileno())
1823 linkname = ""
1824
1825 stmd = statres.st_mode
1826 if stat.S_ISREG(stmd):
1827 inode = (statres.st_ino, statres.st_dev)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001828 if not self.dereference and statres.st_nlink > 1 and \
1829 inode in self.inodes and arcname != self.inodes[inode]:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001830 # Is it a hardlink to an already
1831 # archived file?
1832 type = LNKTYPE
1833 linkname = self.inodes[inode]
1834 else:
1835 # The inode is added only if its valid.
1836 # For win32 it is always 0.
1837 type = REGTYPE
1838 if inode[0]:
1839 self.inodes[inode] = arcname
1840 elif stat.S_ISDIR(stmd):
1841 type = DIRTYPE
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001842 elif stat.S_ISFIFO(stmd):
1843 type = FIFOTYPE
1844 elif stat.S_ISLNK(stmd):
1845 type = SYMTYPE
1846 linkname = os.readlink(name)
1847 elif stat.S_ISCHR(stmd):
1848 type = CHRTYPE
1849 elif stat.S_ISBLK(stmd):
1850 type = BLKTYPE
1851 else:
1852 return None
1853
1854 # Fill the TarInfo object with all
1855 # information we can get.
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001856 tarinfo.name = arcname
1857 tarinfo.mode = stmd
1858 tarinfo.uid = statres.st_uid
1859 tarinfo.gid = statres.st_gid
Lars Gustäbel547f8082010-06-03 10:15:18 +00001860 if type == REGTYPE:
Martin v. Löwis61d77e02004-08-20 06:35:46 +00001861 tarinfo.size = statres.st_size
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001862 else:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001863 tarinfo.size = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001864 tarinfo.mtime = statres.st_mtime
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001865 tarinfo.type = type
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001866 tarinfo.linkname = linkname
1867 if pwd:
1868 try:
1869 tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
1870 except KeyError:
1871 pass
1872 if grp:
1873 try:
1874 tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
1875 except KeyError:
1876 pass
1877
1878 if type in (CHRTYPE, BLKTYPE):
1879 if hasattr(os, "major") and hasattr(os, "minor"):
1880 tarinfo.devmajor = os.major(statres.st_rdev)
1881 tarinfo.devminor = os.minor(statres.st_rdev)
1882 return tarinfo
1883
1884 def list(self, verbose=True):
1885 """Print a table of contents to sys.stdout. If `verbose' is False, only
1886 the names of the members are printed. If it is True, an `ls -l'-like
1887 output is produced.
1888 """
1889 self._check()
1890
1891 for tarinfo in self:
1892 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001893 print(filemode(tarinfo.mode), end=' ')
1894 print("%s/%s" % (tarinfo.uname or tarinfo.uid,
1895 tarinfo.gname or tarinfo.gid), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001896 if tarinfo.ischr() or tarinfo.isblk():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001897 print("%10s" % ("%d,%d" \
1898 % (tarinfo.devmajor, tarinfo.devminor)), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001899 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001900 print("%10d" % tarinfo.size, end=' ')
1901 print("%d-%02d-%02d %02d:%02d:%02d" \
1902 % time.localtime(tarinfo.mtime)[:6], end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001903
Guido van Rossumd8faa362007-04-27 19:54:29 +00001904 print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001905
1906 if verbose:
1907 if tarinfo.issym():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001908 print("->", tarinfo.linkname, end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001909 if tarinfo.islnk():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001910 print("link to", tarinfo.linkname, end=' ')
1911 print()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001912
Guido van Rossum486364b2007-06-30 05:01:58 +00001913 def add(self, name, arcname=None, recursive=True, exclude=None):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001914 """Add the file `name' to the archive. `name' may be any type of file
1915 (directory, fifo, symbolic link, etc.). If given, `arcname'
1916 specifies an alternative name for the file in the archive.
1917 Directories are added recursively by default. This can be avoided by
Guido van Rossum486364b2007-06-30 05:01:58 +00001918 setting `recursive' to False. `exclude' is a function that should
1919 return True for each filename to be excluded.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001920 """
1921 self._check("aw")
1922
1923 if arcname is None:
1924 arcname = name
1925
Guido van Rossum486364b2007-06-30 05:01:58 +00001926 # Exclude pathnames.
1927 if exclude is not None and exclude(name):
1928 self._dbg(2, "tarfile: Excluded %r" % name)
1929 return
1930
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001931 # Skip if somebody tries to archive the archive...
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001932 if self.name is not None and os.path.abspath(name) == self.name:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001933 self._dbg(2, "tarfile: Skipped %r" % name)
1934 return
1935
1936 # Special case: The user wants to add the current
1937 # working directory.
1938 if name == ".":
1939 if recursive:
1940 if arcname == ".":
1941 arcname = ""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001942 for f in os.listdir(name):
Guido van Rossum486364b2007-06-30 05:01:58 +00001943 self.add(f, os.path.join(arcname, f), recursive, exclude)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001944 return
1945
1946 self._dbg(1, name)
1947
1948 # Create a TarInfo object from the file.
1949 tarinfo = self.gettarinfo(name, arcname)
1950
1951 if tarinfo is None:
1952 self._dbg(1, "tarfile: Unsupported type %r" % name)
1953 return
1954
1955 # Append the tar header and data to the archive.
1956 if tarinfo.isreg():
Guido van Rossume7ba4952007-06-06 23:52:48 +00001957 f = bltn_open(name, "rb")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001958 self.addfile(tarinfo, f)
1959 f.close()
1960
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001961 elif tarinfo.isdir():
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001962 self.addfile(tarinfo)
1963 if recursive:
1964 for f in os.listdir(name):
Guido van Rossum486364b2007-06-30 05:01:58 +00001965 self.add(os.path.join(name, f), os.path.join(arcname, f), recursive, exclude)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001966
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001967 else:
1968 self.addfile(tarinfo)
1969
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001970 def addfile(self, tarinfo, fileobj=None):
1971 """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
1972 given, tarinfo.size bytes are read from it and added to the archive.
1973 You can create TarInfo objects using gettarinfo().
1974 On Windows platforms, `fileobj' should always be opened with mode
1975 'rb' to avoid irritation about the file size.
1976 """
1977 self._check("aw")
1978
Thomas Wouters89f507f2006-12-13 04:49:30 +00001979 tarinfo = copy.copy(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001980
Guido van Rossume7ba4952007-06-06 23:52:48 +00001981 buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001982 self.fileobj.write(buf)
1983 self.offset += len(buf)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001984
1985 # If there's data to follow, append it.
1986 if fileobj is not None:
1987 copyfileobj(fileobj, self.fileobj, tarinfo.size)
1988 blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
1989 if remainder > 0:
1990 self.fileobj.write(NUL * (BLOCKSIZE - remainder))
1991 blocks += 1
1992 self.offset += blocks * BLOCKSIZE
1993
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001994 self.members.append(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001995
Martin v. Löwis00a73e72005-03-04 19:40:34 +00001996 def extractall(self, path=".", members=None):
1997 """Extract all members from the archive to the current working
1998 directory and set owner, modification time and permissions on
1999 directories afterwards. `path' specifies a different directory
2000 to extract to. `members' is optional and must be a subset of the
2001 list returned by getmembers().
2002 """
2003 directories = []
2004
2005 if members is None:
2006 members = self
2007
2008 for tarinfo in members:
2009 if tarinfo.isdir():
Christian Heimes2202f872008-02-06 14:31:34 +00002010 # Extract directories with a safe mode.
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002011 directories.append(tarinfo)
Christian Heimes2202f872008-02-06 14:31:34 +00002012 tarinfo = copy.copy(tarinfo)
2013 tarinfo.mode = 0o700
2014 self.extract(tarinfo, path)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002015
2016 # Reverse sort directories.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +00002017 directories.sort(key=lambda a: a.name)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002018 directories.reverse()
2019
2020 # Set correct owner, mtime and filemode on directories.
2021 for tarinfo in directories:
Christian Heimesfaf2f632008-01-06 16:59:19 +00002022 dirpath = os.path.join(path, tarinfo.name)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002023 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +00002024 self.chown(tarinfo, dirpath)
2025 self.utime(tarinfo, dirpath)
2026 self.chmod(tarinfo, dirpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002027 except ExtractError as e:
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002028 if self.errorlevel > 1:
2029 raise
2030 else:
2031 self._dbg(1, "tarfile: %s" % e)
2032
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002033 def extract(self, member, path=""):
2034 """Extract a member from the archive to the current working directory,
2035 using its full name. Its file information is extracted as accurately
2036 as possible. `member' may be a filename or a TarInfo object. You can
2037 specify a different directory using `path'.
2038 """
2039 self._check("r")
2040
Guido van Rossum3172c5d2007-10-16 18:12:55 +00002041 if isinstance(member, str):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002042 tarinfo = self.getmember(member)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002043 else:
2044 tarinfo = member
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002045
Neal Norwitza4f651a2004-07-20 22:07:44 +00002046 # Prepare the link target for makelink().
2047 if tarinfo.islnk():
2048 tarinfo._link_target = os.path.join(path, tarinfo.linkname)
2049
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002050 try:
2051 self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
Guido van Rossumb940e112007-01-10 16:19:56 +00002052 except EnvironmentError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002053 if self.errorlevel > 0:
2054 raise
2055 else:
2056 if e.filename is None:
2057 self._dbg(1, "tarfile: %s" % e.strerror)
2058 else:
2059 self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
Guido van Rossumb940e112007-01-10 16:19:56 +00002060 except ExtractError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002061 if self.errorlevel > 1:
2062 raise
2063 else:
2064 self._dbg(1, "tarfile: %s" % e)
2065
2066 def extractfile(self, member):
2067 """Extract a member from the archive as a file object. `member' may be
2068 a filename or a TarInfo object. If `member' is a regular file, a
2069 file-like object is returned. If `member' is a link, a file-like
2070 object is constructed from the link's target. If `member' is none of
2071 the above, None is returned.
2072 The file-like object is read-only and provides the following
2073 methods: read(), readline(), readlines(), seek() and tell()
2074 """
2075 self._check("r")
2076
Guido van Rossum3172c5d2007-10-16 18:12:55 +00002077 if isinstance(member, str):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002078 tarinfo = self.getmember(member)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002079 else:
2080 tarinfo = member
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002081
2082 if tarinfo.isreg():
2083 return self.fileobject(self, tarinfo)
2084
2085 elif tarinfo.type not in SUPPORTED_TYPES:
2086 # If a member's type is unknown, it is treated as a
2087 # regular file.
2088 return self.fileobject(self, tarinfo)
2089
2090 elif tarinfo.islnk() or tarinfo.issym():
2091 if isinstance(self.fileobj, _Stream):
2092 # A small but ugly workaround for the case that someone tries
2093 # to extract a (sym)link as a file-object from a non-seekable
2094 # stream of tar blocks.
Thomas Wouters477c8d52006-05-27 19:21:47 +00002095 raise StreamError("cannot extract (sym)link as file object")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002096 else:
Georg Brandl7eb4b7d2005-07-22 21:49:32 +00002097 # A (sym)link's file object is its target's file object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002098 return self.extractfile(self._getmember(tarinfo.linkname,
2099 tarinfo))
2100 else:
2101 # If there's no data associated with the member (directory, chrdev,
2102 # blkdev, etc.), return None instead of a file object.
2103 return None
2104
2105 def _extract_member(self, tarinfo, targetpath):
2106 """Extract the TarInfo object tarinfo to a physical
2107 file called targetpath.
2108 """
2109 # Fetch the TarInfo object for the given name
2110 # and build the destination pathname, replacing
2111 # forward slashes to platform specific separators.
2112 if targetpath[-1:] == "/":
2113 targetpath = targetpath[:-1]
2114 targetpath = os.path.normpath(targetpath)
2115
2116 # Create all upper directories.
2117 upperdirs = os.path.dirname(targetpath)
2118 if upperdirs and not os.path.exists(upperdirs):
Christian Heimes2202f872008-02-06 14:31:34 +00002119 # Create directories that are not part of the archive with
2120 # default permissions.
Thomas Woutersb2137042007-02-01 18:02:27 +00002121 os.makedirs(upperdirs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002122
2123 if tarinfo.islnk() or tarinfo.issym():
2124 self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
2125 else:
2126 self._dbg(1, tarinfo.name)
2127
2128 if tarinfo.isreg():
2129 self.makefile(tarinfo, targetpath)
2130 elif tarinfo.isdir():
2131 self.makedir(tarinfo, targetpath)
2132 elif tarinfo.isfifo():
2133 self.makefifo(tarinfo, targetpath)
2134 elif tarinfo.ischr() or tarinfo.isblk():
2135 self.makedev(tarinfo, targetpath)
2136 elif tarinfo.islnk() or tarinfo.issym():
2137 self.makelink(tarinfo, targetpath)
2138 elif tarinfo.type not in SUPPORTED_TYPES:
2139 self.makeunknown(tarinfo, targetpath)
2140 else:
2141 self.makefile(tarinfo, targetpath)
2142
2143 self.chown(tarinfo, targetpath)
2144 if not tarinfo.issym():
2145 self.chmod(tarinfo, targetpath)
2146 self.utime(tarinfo, targetpath)
2147
2148 #--------------------------------------------------------------------------
2149 # Below are the different file methods. They are called via
2150 # _extract_member() when extract() is called. They can be replaced in a
2151 # subclass to implement other functionality.
2152
2153 def makedir(self, tarinfo, targetpath):
2154 """Make a directory called targetpath.
2155 """
2156 try:
Christian Heimes2202f872008-02-06 14:31:34 +00002157 # Use a safe mode for the directory, the real mode is set
2158 # later in _extract_member().
2159 os.mkdir(targetpath, 0o700)
Guido van Rossumb940e112007-01-10 16:19:56 +00002160 except EnvironmentError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002161 if e.errno != errno.EEXIST:
2162 raise
2163
2164 def makefile(self, tarinfo, targetpath):
2165 """Make a file called targetpath.
2166 """
2167 source = self.extractfile(tarinfo)
Guido van Rossume7ba4952007-06-06 23:52:48 +00002168 target = bltn_open(targetpath, "wb")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002169 copyfileobj(source, target)
2170 source.close()
2171 target.close()
2172
2173 def makeunknown(self, tarinfo, targetpath):
2174 """Make a file from a TarInfo object with an unknown type
2175 at targetpath.
2176 """
2177 self.makefile(tarinfo, targetpath)
2178 self._dbg(1, "tarfile: Unknown file type %r, " \
2179 "extracted as regular file." % tarinfo.type)
2180
2181 def makefifo(self, tarinfo, targetpath):
2182 """Make a fifo called targetpath.
2183 """
2184 if hasattr(os, "mkfifo"):
2185 os.mkfifo(targetpath)
2186 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002187 raise ExtractError("fifo not supported by system")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002188
2189 def makedev(self, tarinfo, targetpath):
2190 """Make a character or block device called targetpath.
2191 """
2192 if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
Thomas Wouters477c8d52006-05-27 19:21:47 +00002193 raise ExtractError("special devices not supported by system")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002194
2195 mode = tarinfo.mode
2196 if tarinfo.isblk():
2197 mode |= stat.S_IFBLK
2198 else:
2199 mode |= stat.S_IFCHR
2200
2201 os.mknod(targetpath, mode,
2202 os.makedev(tarinfo.devmajor, tarinfo.devminor))
2203
2204 def makelink(self, tarinfo, targetpath):
2205 """Make a (symbolic) link called targetpath. If it cannot be created
2206 (platform limitation), we try to make a copy of the referenced file
2207 instead of a link.
2208 """
2209 linkpath = tarinfo.linkname
2210 try:
2211 if tarinfo.issym():
2212 os.symlink(linkpath, targetpath)
2213 else:
Neal Norwitza4f651a2004-07-20 22:07:44 +00002214 # See extract().
2215 os.link(tarinfo._link_target, targetpath)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002216 except AttributeError:
2217 if tarinfo.issym():
2218 linkpath = os.path.join(os.path.dirname(tarinfo.name),
2219 linkpath)
2220 linkpath = normpath(linkpath)
2221
2222 try:
2223 self._extract_member(self.getmember(linkpath), targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002224 except (EnvironmentError, KeyError) as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002225 linkpath = os.path.normpath(linkpath)
2226 try:
2227 shutil.copy2(linkpath, targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002228 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002229 raise IOError("link could not be created")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002230
2231 def chown(self, tarinfo, targetpath):
2232 """Set owner of targetpath according to tarinfo.
2233 """
2234 if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
2235 # We have to be root to do so.
2236 try:
2237 g = grp.getgrnam(tarinfo.gname)[2]
2238 except KeyError:
2239 try:
2240 g = grp.getgrgid(tarinfo.gid)[2]
2241 except KeyError:
2242 g = os.getgid()
2243 try:
2244 u = pwd.getpwnam(tarinfo.uname)[2]
2245 except KeyError:
2246 try:
2247 u = pwd.getpwuid(tarinfo.uid)[2]
2248 except KeyError:
2249 u = os.getuid()
2250 try:
2251 if tarinfo.issym() and hasattr(os, "lchown"):
2252 os.lchown(targetpath, u, g)
2253 else:
Andrew MacIntyre7970d202003-02-19 12:51:34 +00002254 if sys.platform != "os2emx":
2255 os.chown(targetpath, u, g)
Guido van Rossumb940e112007-01-10 16:19:56 +00002256 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002257 raise ExtractError("could not change owner")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002258
2259 def chmod(self, tarinfo, targetpath):
2260 """Set file permissions of targetpath according to tarinfo.
2261 """
Jack Jansen834eff62003-03-07 12:47:06 +00002262 if hasattr(os, 'chmod'):
2263 try:
2264 os.chmod(targetpath, tarinfo.mode)
Guido van Rossumb940e112007-01-10 16:19:56 +00002265 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002266 raise ExtractError("could not change mode")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002267
2268 def utime(self, tarinfo, targetpath):
2269 """Set modification time of targetpath according to tarinfo.
2270 """
Jack Jansen834eff62003-03-07 12:47:06 +00002271 if not hasattr(os, 'utime'):
Tim Petersf9347782003-03-07 15:36:41 +00002272 return
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002273 try:
2274 os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
Guido van Rossumb940e112007-01-10 16:19:56 +00002275 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002276 raise ExtractError("could not change modification time")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002277
2278 #--------------------------------------------------------------------------
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002279 def next(self):
2280 """Return the next member of the archive as a TarInfo object, when
2281 TarFile is opened for reading. Return None if there is no more
2282 available.
2283 """
2284 self._check("ra")
2285 if self.firstmember is not None:
2286 m = self.firstmember
2287 self.firstmember = None
2288 return m
2289
2290 # Read the next block.
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002291 self.fileobj.seek(self.offset)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002292 while True:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002293 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002294 tarinfo = self.tarinfo.fromtarfile(self)
2295 if tarinfo is None:
2296 return
2297 self.members.append(tarinfo)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002298
Guido van Rossumb940e112007-01-10 16:19:56 +00002299 except HeaderError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002300 if self.ignore_zeros:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00002301 self._dbg(2, "0x%X: %s" % (self.offset, e))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002302 self.offset += BLOCKSIZE
2303 continue
2304 else:
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002305 if self.offset == 0:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00002306 raise ReadError(str(e))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002307 return None
2308 break
2309
Thomas Wouters477c8d52006-05-27 19:21:47 +00002310 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002311
2312 #--------------------------------------------------------------------------
2313 # Little helper methods:
2314
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002315 def _getmember(self, name, tarinfo=None):
2316 """Find an archive member by name from bottom to top.
2317 If tarinfo is given, it is used as the starting point.
2318 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002319 # Ensure that all members have been loaded.
2320 members = self.getmembers()
2321
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002322 if tarinfo is None:
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002323 end = len(members)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002324 else:
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002325 end = members.index(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002326
Guido van Rossum805365e2007-05-07 22:24:25 +00002327 for i in range(end - 1, -1, -1):
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002328 if name == members[i].name:
2329 return members[i]
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002330
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002331 def _load(self):
2332 """Read through the entire archive file and look for readable
2333 members.
2334 """
2335 while True:
2336 tarinfo = self.next()
2337 if tarinfo is None:
2338 break
2339 self._loaded = True
2340
2341 def _check(self, mode=None):
2342 """Check if TarFile is still open, and if the operation's mode
2343 corresponds to TarFile's mode.
2344 """
2345 if self.closed:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002346 raise IOError("%s is closed" % self.__class__.__name__)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002347 if mode is not None and self.mode not in mode:
2348 raise IOError("bad operation for mode %r" % self.mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002349
2350 def __iter__(self):
2351 """Provide an iterator object.
2352 """
2353 if self._loaded:
2354 return iter(self.members)
2355 else:
2356 return TarIter(self)
2357
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002358 def _dbg(self, level, msg):
2359 """Write debugging output to sys.stderr.
2360 """
2361 if level <= self.debug:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002362 print(msg, file=sys.stderr)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002363# class TarFile
2364
2365class TarIter:
2366 """Iterator Class.
2367
2368 for tarinfo in TarFile(...):
2369 suite...
2370 """
2371
2372 def __init__(self, tarfile):
2373 """Construct a TarIter object.
2374 """
2375 self.tarfile = tarfile
Martin v. Löwis637431b2005-03-03 23:12:42 +00002376 self.index = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002377 def __iter__(self):
2378 """Return iterator object.
2379 """
2380 return self
Georg Brandla18af4e2007-04-21 15:47:16 +00002381 def __next__(self):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002382 """Return the next item using TarFile's next() method.
2383 When all members have been read, set TarFile as _loaded.
2384 """
Martin v. Löwis637431b2005-03-03 23:12:42 +00002385 # Fix for SF #1100429: Under rare circumstances it can
2386 # happen that getmembers() is called during iteration,
2387 # which will cause TarIter to stop prematurely.
2388 if not self.tarfile._loaded:
2389 tarinfo = self.tarfile.next()
2390 if not tarinfo:
2391 self.tarfile._loaded = True
2392 raise StopIteration
2393 else:
2394 try:
2395 tarinfo = self.tarfile.members[self.index]
2396 except IndexError:
2397 raise StopIteration
2398 self.index += 1
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002399 return tarinfo
2400
2401# Helper classes for sparse file support
2402class _section:
2403 """Base class for _data and _hole.
2404 """
2405 def __init__(self, offset, size):
2406 self.offset = offset
2407 self.size = size
2408 def __contains__(self, offset):
2409 return self.offset <= offset < self.offset + self.size
2410
2411class _data(_section):
2412 """Represent a data section in a sparse file.
2413 """
2414 def __init__(self, offset, size, realpos):
2415 _section.__init__(self, offset, size)
2416 self.realpos = realpos
2417
2418class _hole(_section):
2419 """Represent a hole section in a sparse file.
2420 """
2421 pass
2422
2423class _ringbuffer(list):
2424 """Ringbuffer class which increases performance
2425 over a regular list.
2426 """
2427 def __init__(self):
2428 self.idx = 0
2429 def find(self, offset):
2430 idx = self.idx
2431 while True:
2432 item = self[idx]
2433 if offset in item:
2434 break
2435 idx += 1
2436 if idx == len(self):
2437 idx = 0
2438 if idx == self.idx:
2439 # End of File
2440 return None
2441 self.idx = idx
2442 return item
2443
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002444#--------------------
2445# exported functions
2446#--------------------
2447def is_tarfile(name):
2448 """Return True if name points to a tar archive that we
2449 are able to handle, else return False.
2450 """
2451 try:
2452 t = open(name)
2453 t.close()
2454 return True
2455 except TarError:
2456 return False
2457
Guido van Rossume7ba4952007-06-06 23:52:48 +00002458bltn_open = open
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002459open = TarFile.open