blob: c744951d7065adb7d160a5b12c27498f7ba2b566 [file] [log] [blame]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001#!/usr/bin/env python
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002#-------------------------------------------------------------------
3# tarfile.py
4#-------------------------------------------------------------------
Christian Heimes9c1257e2007-11-04 11:37:22 +00005# Copyright (C) 2002 Lars Gustaebel <lars@gustaebel.de>
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00006# All rights reserved.
7#
8# Permission is hereby granted, free of charge, to any person
9# obtaining a copy of this software and associated documentation
10# files (the "Software"), to deal in the Software without
11# restriction, including without limitation the rights to use,
12# copy, modify, merge, publish, distribute, sublicense, and/or sell
13# copies of the Software, and to permit persons to whom the
14# Software is furnished to do so, subject to the following
15# conditions:
16#
17# The above copyright notice and this permission notice shall be
18# included in all copies or substantial portions of the Software.
19#
20# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27# OTHER DEALINGS IN THE SOFTWARE.
28#
29"""Read from and write to tar format archives.
30"""
31
32__version__ = "$Revision$"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000033
Guido van Rossumd8faa362007-04-27 19:54:29 +000034version = "0.9.0"
Guido van Rossum98297ee2007-11-06 21:34:58 +000035__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000036__date__ = "$Date$"
37__cvsid__ = "$Id$"
Guido van Rossum98297ee2007-11-06 21:34:58 +000038__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend."
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000039
40#---------
41# Imports
42#---------
43import sys
44import os
45import shutil
46import stat
47import errno
48import time
49import struct
Thomas Wouters89f507f2006-12-13 04:49:30 +000050import copy
Guido van Rossumd8faa362007-04-27 19:54:29 +000051import re
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000052
Jack Jansencfc49022003-03-07 13:37:32 +000053if sys.platform == 'mac':
54 # This module needs work for MacOS9, especially in the area of pathname
55 # handling. In many places it is assumed a simple substitution of / by the
56 # local os.path.sep is good enough to convert pathnames, but this does not
57 # work with the mac rooted:path:name versus :nonrooted:path:name syntax
Collin Winterce36ad82007-08-30 01:19:48 +000058 raise ImportError("tarfile does not work for platform==mac")
Jack Jansencfc49022003-03-07 13:37:32 +000059
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000060try:
61 import grp, pwd
62except ImportError:
63 grp = pwd = None
64
65# from tarfile import *
66__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"]
67
Georg Brandl1a3284e2007-12-02 09:40:06 +000068from builtins import open as _open # Since 'open' is TarFile.open
Guido van Rossum8f78fe92006-08-24 04:03:53 +000069
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000070#---------------------------------------------------------
71# tar constants
72#---------------------------------------------------------
Lars Gustäbelb506dc32007-08-07 18:36:16 +000073NUL = b"\0" # the null character
Guido van Rossumd8faa362007-04-27 19:54:29 +000074BLOCKSIZE = 512 # length of processing blocks
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000075RECORDSIZE = BLOCKSIZE * 20 # length of records
Lars Gustäbelb506dc32007-08-07 18:36:16 +000076GNU_MAGIC = b"ustar \0" # magic gnu tar string
77POSIX_MAGIC = b"ustar\x0000" # magic posix tar string
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000078
Guido van Rossumd8faa362007-04-27 19:54:29 +000079LENGTH_NAME = 100 # maximum length of a filename
80LENGTH_LINK = 100 # maximum length of a linkname
81LENGTH_PREFIX = 155 # maximum length of the prefix field
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000082
Lars Gustäbelb506dc32007-08-07 18:36:16 +000083REGTYPE = b"0" # regular file
84AREGTYPE = b"\0" # regular file
85LNKTYPE = b"1" # link (inside tarfile)
86SYMTYPE = b"2" # symbolic link
87CHRTYPE = b"3" # character special device
88BLKTYPE = b"4" # block special device
89DIRTYPE = b"5" # directory
90FIFOTYPE = b"6" # fifo special device
91CONTTYPE = b"7" # contiguous file
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000092
Lars Gustäbelb506dc32007-08-07 18:36:16 +000093GNUTYPE_LONGNAME = b"L" # GNU tar longname
94GNUTYPE_LONGLINK = b"K" # GNU tar longlink
95GNUTYPE_SPARSE = b"S" # GNU tar sparse file
Guido van Rossumd8faa362007-04-27 19:54:29 +000096
Lars Gustäbelb506dc32007-08-07 18:36:16 +000097XHDTYPE = b"x" # POSIX.1-2001 extended header
98XGLTYPE = b"g" # POSIX.1-2001 global header
99SOLARIS_XHDTYPE = b"X" # Solaris extended header
Guido van Rossumd8faa362007-04-27 19:54:29 +0000100
101USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format
102GNU_FORMAT = 1 # GNU tar format
103PAX_FORMAT = 2 # POSIX.1-2001 (pax) format
104DEFAULT_FORMAT = GNU_FORMAT
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000105
106#---------------------------------------------------------
107# tarfile constants
108#---------------------------------------------------------
Guido van Rossumd8faa362007-04-27 19:54:29 +0000109# File types that tarfile supports:
110SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE,
111 SYMTYPE, DIRTYPE, FIFOTYPE,
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000112 CONTTYPE, CHRTYPE, BLKTYPE,
113 GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
114 GNUTYPE_SPARSE)
115
Guido van Rossumd8faa362007-04-27 19:54:29 +0000116# File types that will be treated as a regular file.
117REGULAR_TYPES = (REGTYPE, AREGTYPE,
118 CONTTYPE, GNUTYPE_SPARSE)
119
120# File types that are part of the GNU tar format.
121GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
122 GNUTYPE_SPARSE)
123
124# Fields from a pax header that override a TarInfo attribute.
125PAX_FIELDS = ("path", "linkpath", "size", "mtime",
126 "uid", "gid", "uname", "gname")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000127
Guido van Rossume7ba4952007-06-06 23:52:48 +0000128# Fields in a pax header that are numbers, all other fields
129# are treated as strings.
130PAX_NUMBER_FIELDS = {
131 "atime": float,
132 "ctime": float,
133 "mtime": float,
134 "uid": int,
135 "gid": int,
136 "size": int
137}
138
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000139#---------------------------------------------------------
140# Bits used in the mode field, values in octal.
141#---------------------------------------------------------
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000142S_IFLNK = 0o120000 # symbolic link
143S_IFREG = 0o100000 # regular file
144S_IFBLK = 0o060000 # block device
145S_IFDIR = 0o040000 # directory
146S_IFCHR = 0o020000 # character device
147S_IFIFO = 0o010000 # fifo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000148
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000149TSUID = 0o4000 # set UID on execution
150TSGID = 0o2000 # set GID on execution
151TSVTX = 0o1000 # reserved
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000152
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000153TUREAD = 0o400 # read by owner
154TUWRITE = 0o200 # write by owner
155TUEXEC = 0o100 # execute/search by owner
156TGREAD = 0o040 # read by group
157TGWRITE = 0o020 # write by group
158TGEXEC = 0o010 # execute/search by group
159TOREAD = 0o004 # read by other
160TOWRITE = 0o002 # write by other
161TOEXEC = 0o001 # execute/search by other
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000162
163#---------------------------------------------------------
Guido van Rossumd8faa362007-04-27 19:54:29 +0000164# initialization
165#---------------------------------------------------------
166ENCODING = sys.getfilesystemencoding()
167if ENCODING is None:
Lars Gustäbel3741eff2007-08-21 12:17:05 +0000168 ENCODING = "ascii"
Guido van Rossumd8faa362007-04-27 19:54:29 +0000169
170#---------------------------------------------------------
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000171# Some useful functions
172#---------------------------------------------------------
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000173
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000174def stn(s, length, encoding, errors):
175 """Convert a string to a null-terminated bytes object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000176 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000177 s = s.encode(encoding, errors)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000178 return s[:length] + (length - len(s)) * NUL
Thomas Wouters477c8d52006-05-27 19:21:47 +0000179
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000180def nts(s, encoding, errors):
181 """Convert a null-terminated bytes object to a string.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000182 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000183 p = s.find(b"\0")
184 if p != -1:
185 s = s[:p]
186 return s.decode(encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000187
Thomas Wouters477c8d52006-05-27 19:21:47 +0000188def nti(s):
189 """Convert a number field to a python number.
190 """
191 # There are two possible encodings for a number field, see
192 # itn() below.
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000193 if s[0] != chr(0o200):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000194 try:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000195 n = int(nts(s, "ascii", "strict") or "0", 8)
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000196 except ValueError:
197 raise HeaderError("invalid header")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000198 else:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000199 n = 0
Guido van Rossum805365e2007-05-07 22:24:25 +0000200 for i in range(len(s) - 1):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000201 n <<= 8
202 n += ord(s[i + 1])
203 return n
204
Guido van Rossumd8faa362007-04-27 19:54:29 +0000205def itn(n, digits=8, format=DEFAULT_FORMAT):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000206 """Convert a python number to a number field.
207 """
208 # POSIX 1003.1-1988 requires numbers to be encoded as a string of
209 # octal digits followed by a null-byte, this allows values up to
210 # (8**(digits-1))-1. GNU tar allows storing numbers greater than
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000211 # that if necessary. A leading 0o200 byte indicates this particular
Thomas Wouters477c8d52006-05-27 19:21:47 +0000212 # encoding, the following digits-1 bytes are a big-endian
213 # representation. This allows values up to (256**(digits-1))-1.
214 if 0 <= n < 8 ** (digits - 1):
Lars Gustäbela280ca752007-08-28 07:34:33 +0000215 s = bytes("%0*o" % (digits - 1, n), "ascii") + NUL
Thomas Wouters477c8d52006-05-27 19:21:47 +0000216 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000217 if format != GNU_FORMAT or n >= 256 ** (digits - 1):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000218 raise ValueError("overflow in number field")
219
220 if n < 0:
221 # XXX We mimic GNU tar's behaviour with negative numbers,
222 # this could raise OverflowError.
223 n = struct.unpack("L", struct.pack("l", n))[0]
224
Guido van Rossum254348e2007-11-21 19:29:53 +0000225 s = bytearray()
Guido van Rossum805365e2007-05-07 22:24:25 +0000226 for i in range(digits - 1):
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000227 s.insert(0, n & 0o377)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000228 n >>= 8
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000229 s.insert(0, 0o200)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000230 return s
231
232def calc_chksums(buf):
233 """Calculate the checksum for a member's header by summing up all
234 characters except for the chksum field which is treated as if
235 it was filled with spaces. According to the GNU tar sources,
236 some tars (Sun and NeXT) calculate chksum with signed char,
237 which will be different if there are chars in the buffer with
238 the high bit set. So we calculate two checksums, unsigned and
239 signed.
240 """
241 unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512]))
242 signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512]))
243 return unsigned_chksum, signed_chksum
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000244
245def copyfileobj(src, dst, length=None):
246 """Copy length bytes from fileobj src to fileobj dst.
247 If length is None, copy the entire content.
248 """
249 if length == 0:
250 return
251 if length is None:
252 shutil.copyfileobj(src, dst)
253 return
254
255 BUFSIZE = 16 * 1024
256 blocks, remainder = divmod(length, BUFSIZE)
Guido van Rossum805365e2007-05-07 22:24:25 +0000257 for b in range(blocks):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000258 buf = src.read(BUFSIZE)
259 if len(buf) < BUFSIZE:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000260 raise IOError("end of file reached")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000261 dst.write(buf)
262
263 if remainder != 0:
264 buf = src.read(remainder)
265 if len(buf) < remainder:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000266 raise IOError("end of file reached")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000267 dst.write(buf)
268 return
269
270filemode_table = (
Andrew M. Kuchling8bc462f2004-10-20 11:48:42 +0000271 ((S_IFLNK, "l"),
272 (S_IFREG, "-"),
273 (S_IFBLK, "b"),
274 (S_IFDIR, "d"),
275 (S_IFCHR, "c"),
276 (S_IFIFO, "p")),
277
278 ((TUREAD, "r"),),
279 ((TUWRITE, "w"),),
280 ((TUEXEC|TSUID, "s"),
281 (TSUID, "S"),
282 (TUEXEC, "x")),
283
284 ((TGREAD, "r"),),
285 ((TGWRITE, "w"),),
286 ((TGEXEC|TSGID, "s"),
287 (TSGID, "S"),
288 (TGEXEC, "x")),
289
290 ((TOREAD, "r"),),
291 ((TOWRITE, "w"),),
292 ((TOEXEC|TSVTX, "t"),
293 (TSVTX, "T"),
294 (TOEXEC, "x"))
295)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000296
297def filemode(mode):
298 """Convert a file's mode to a string of the form
299 -rwxrwxrwx.
300 Used by TarFile.list()
301 """
Andrew M. Kuchling8bc462f2004-10-20 11:48:42 +0000302 perm = []
303 for table in filemode_table:
304 for bit, char in table:
305 if mode & bit == bit:
306 perm.append(char)
307 break
308 else:
309 perm.append("-")
310 return "".join(perm)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000311
312if os.sep != "/":
313 normpath = lambda path: os.path.normpath(path).replace(os.sep, "/")
314else:
315 normpath = os.path.normpath
316
317class TarError(Exception):
318 """Base exception."""
319 pass
320class ExtractError(TarError):
321 """General exception for extract errors."""
322 pass
323class ReadError(TarError):
324 """Exception for unreadble tar archives."""
325 pass
326class CompressionError(TarError):
327 """Exception for unavailable compression methods."""
328 pass
329class StreamError(TarError):
330 """Exception for unsupported operations on stream-like TarFiles."""
331 pass
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000332class HeaderError(TarError):
333 """Exception for invalid headers."""
334 pass
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000335
336#---------------------------
337# internal stream interface
338#---------------------------
339class _LowLevelFile:
340 """Low-level file object. Supports reading and writing.
341 It is used instead of a regular file object for streaming
342 access.
343 """
344
345 def __init__(self, name, mode):
346 mode = {
347 "r": os.O_RDONLY,
348 "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
349 }[mode]
350 if hasattr(os, "O_BINARY"):
351 mode |= os.O_BINARY
352 self.fd = os.open(name, mode)
353
354 def close(self):
355 os.close(self.fd)
356
357 def read(self, size):
358 return os.read(self.fd, size)
359
360 def write(self, s):
361 os.write(self.fd, s)
362
363class _Stream:
364 """Class that serves as an adapter between TarFile and
365 a stream-like object. The stream-like object only
366 needs to have a read() or write() method and is accessed
367 blockwise. Use of gzip or bzip2 compression is possible.
368 A stream-like object could be for example: sys.stdin,
369 sys.stdout, a socket, a tape device etc.
370
371 _Stream is intended to be used only internally.
372 """
373
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000374 def __init__(self, name, mode, comptype, fileobj, bufsize):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000375 """Construct a _Stream object.
376 """
377 self._extfileobj = True
378 if fileobj is None:
379 fileobj = _LowLevelFile(name, mode)
380 self._extfileobj = False
381
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000382 if comptype == '*':
383 # Enable transparent compression detection for the
384 # stream interface
385 fileobj = _StreamProxy(fileobj)
386 comptype = fileobj.getcomptype()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000387
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000388 self.name = name or ""
389 self.mode = mode
390 self.comptype = comptype
391 self.fileobj = fileobj
392 self.bufsize = bufsize
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000393 self.buf = b""
Guido van Rossume2a383d2007-01-15 16:59:06 +0000394 self.pos = 0
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000395 self.closed = False
396
397 if comptype == "gz":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000398 try:
399 import zlib
400 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000401 raise CompressionError("zlib module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000402 self.zlib = zlib
403 self.crc = zlib.crc32("")
404 if mode == "r":
405 self._init_read_gz()
406 else:
407 self._init_write_gz()
408
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000409 if comptype == "bz2":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000410 try:
411 import bz2
412 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000413 raise CompressionError("bz2 module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000414 if mode == "r":
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000415 self.dbuf = b""
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000416 self.cmp = bz2.BZ2Decompressor()
417 else:
418 self.cmp = bz2.BZ2Compressor()
419
420 def __del__(self):
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000421 if hasattr(self, "closed") and not self.closed:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000422 self.close()
423
424 def _init_write_gz(self):
425 """Initialize for writing with gzip compression.
426 """
427 self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED,
428 -self.zlib.MAX_WBITS,
429 self.zlib.DEF_MEM_LEVEL,
430 0)
Guido van Rossume2a383d2007-01-15 16:59:06 +0000431 timestamp = struct.pack("<L", int(time.time()))
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000432 self.__write(b"\037\213\010\010" + timestamp + b"\002\377")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000433 if self.name.endswith(".gz"):
434 self.name = self.name[:-3]
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000435 # RFC1952 says we must use ISO-8859-1 for the FNAME field.
436 self.__write(self.name.encode("iso-8859-1", "replace") + NUL)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000437
438 def write(self, s):
439 """Write string s to the stream.
440 """
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000441 if self.comptype == "gz":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000442 self.crc = self.zlib.crc32(s, self.crc)
443 self.pos += len(s)
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000444 if self.comptype != "tar":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000445 s = self.cmp.compress(s)
446 self.__write(s)
447
448 def __write(self, s):
449 """Write string s to the stream if a whole new block
450 is ready to be written.
451 """
452 self.buf += s
453 while len(self.buf) > self.bufsize:
454 self.fileobj.write(self.buf[:self.bufsize])
455 self.buf = self.buf[self.bufsize:]
456
457 def close(self):
458 """Close the _Stream object. No operation should be
459 done on it afterwards.
460 """
461 if self.closed:
462 return
463
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000464 if self.mode == "w" and self.comptype != "tar":
Martin v. Löwisc234a522004-08-22 21:28:33 +0000465 self.buf += self.cmp.flush()
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000466
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000467 if self.mode == "w" and self.buf:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000468 self.fileobj.write(self.buf)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000469 self.buf = b""
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000470 if self.comptype == "gz":
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000471 # The native zlib crc is an unsigned 32-bit integer, but
472 # the Python wrapper implicitly casts that to a signed C
473 # long. So, on a 32-bit box self.crc may "look negative",
474 # while the same crc on a 64-bit box may "look positive".
475 # To avoid irksome warnings from the `struct` module, force
476 # it to look positive on all boxes.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000477 self.fileobj.write(struct.pack("<L", self.crc & 0xffffffff))
478 self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFF))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000479
480 if not self._extfileobj:
481 self.fileobj.close()
482
483 self.closed = True
484
485 def _init_read_gz(self):
486 """Initialize for reading a gzip compressed fileobj.
487 """
488 self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000489 self.dbuf = b""
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000490
491 # taken from gzip.GzipFile with some alterations
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000492 if self.__read(2) != b"\037\213":
Thomas Wouters477c8d52006-05-27 19:21:47 +0000493 raise ReadError("not a gzip file")
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000494 if self.__read(1) != b"\010":
Thomas Wouters477c8d52006-05-27 19:21:47 +0000495 raise CompressionError("unsupported compression method")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000496
497 flag = ord(self.__read(1))
498 self.__read(6)
499
500 if flag & 4:
501 xlen = ord(self.__read(1)) + 256 * ord(self.__read(1))
502 self.read(xlen)
503 if flag & 8:
504 while True:
505 s = self.__read(1)
506 if not s or s == NUL:
507 break
508 if flag & 16:
509 while True:
510 s = self.__read(1)
511 if not s or s == NUL:
512 break
513 if flag & 2:
514 self.__read(2)
515
516 def tell(self):
517 """Return the stream's file pointer position.
518 """
519 return self.pos
520
521 def seek(self, pos=0):
522 """Set the stream's file pointer to pos. Negative seeking
523 is forbidden.
524 """
525 if pos - self.pos >= 0:
526 blocks, remainder = divmod(pos - self.pos, self.bufsize)
Guido van Rossum805365e2007-05-07 22:24:25 +0000527 for i in range(blocks):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000528 self.read(self.bufsize)
529 self.read(remainder)
530 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000531 raise StreamError("seeking backwards is not allowed")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000532 return self.pos
533
534 def read(self, size=None):
535 """Return the next size number of bytes from the stream.
536 If size is not defined, return all bytes of the stream
537 up to EOF.
538 """
539 if size is None:
540 t = []
541 while True:
542 buf = self._read(self.bufsize)
543 if not buf:
544 break
545 t.append(buf)
546 buf = "".join(t)
547 else:
548 buf = self._read(size)
549 self.pos += len(buf)
550 return buf
551
552 def _read(self, size):
553 """Return size bytes from the stream.
554 """
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000555 if self.comptype == "tar":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000556 return self.__read(size)
557
558 c = len(self.dbuf)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000559 while c < size:
560 buf = self.__read(self.bufsize)
561 if not buf:
562 break
Guido van Rossumd8faa362007-04-27 19:54:29 +0000563 try:
564 buf = self.cmp.decompress(buf)
565 except IOError:
566 raise ReadError("invalid compressed data")
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000567 self.dbuf += buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000568 c += len(buf)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000569 buf = self.dbuf[:size]
570 self.dbuf = self.dbuf[size:]
571 return buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000572
573 def __read(self, size):
574 """Return size bytes from stream. If internal buffer is empty,
575 read another block from the stream.
576 """
577 c = len(self.buf)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000578 while c < size:
579 buf = self.fileobj.read(self.bufsize)
580 if not buf:
581 break
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000582 self.buf += buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000583 c += len(buf)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000584 buf = self.buf[:size]
585 self.buf = self.buf[size:]
586 return buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000587# class _Stream
588
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000589class _StreamProxy(object):
590 """Small proxy class that enables transparent compression
591 detection for the Stream interface (mode 'r|*').
592 """
593
594 def __init__(self, fileobj):
595 self.fileobj = fileobj
596 self.buf = self.fileobj.read(BLOCKSIZE)
597
598 def read(self, size):
599 self.read = self.fileobj.read
600 return self.buf
601
602 def getcomptype(self):
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000603 if self.buf.startswith(b"\037\213\010"):
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000604 return "gz"
Lars Gustäbela280ca752007-08-28 07:34:33 +0000605 if self.buf.startswith(b"BZh91"):
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000606 return "bz2"
607 return "tar"
608
609 def close(self):
610 self.fileobj.close()
611# class StreamProxy
612
Thomas Wouters477c8d52006-05-27 19:21:47 +0000613class _BZ2Proxy(object):
614 """Small proxy class that enables external file object
615 support for "r:bz2" and "w:bz2" modes. This is actually
616 a workaround for a limitation in bz2 module's BZ2File
617 class which (unlike gzip.GzipFile) has no support for
618 a file object argument.
619 """
620
621 blocksize = 16 * 1024
622
623 def __init__(self, fileobj, mode):
624 self.fileobj = fileobj
625 self.mode = mode
Guido van Rossumd8faa362007-04-27 19:54:29 +0000626 self.name = getattr(self.fileobj, "name", None)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000627 self.init()
628
629 def init(self):
630 import bz2
631 self.pos = 0
632 if self.mode == "r":
633 self.bz2obj = bz2.BZ2Decompressor()
634 self.fileobj.seek(0)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000635 self.buf = b""
Thomas Wouters477c8d52006-05-27 19:21:47 +0000636 else:
637 self.bz2obj = bz2.BZ2Compressor()
638
639 def read(self, size):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000640 x = len(self.buf)
641 while x < size:
642 try:
643 raw = self.fileobj.read(self.blocksize)
644 data = self.bz2obj.decompress(raw)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000645 self.buf += data
Thomas Wouters477c8d52006-05-27 19:21:47 +0000646 except EOFError:
647 break
648 x += len(data)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000649
650 buf = self.buf[:size]
651 self.buf = self.buf[size:]
652 self.pos += len(buf)
653 return buf
654
655 def seek(self, pos):
656 if pos < self.pos:
657 self.init()
658 self.read(pos - self.pos)
659
660 def tell(self):
661 return self.pos
662
663 def write(self, data):
664 self.pos += len(data)
665 raw = self.bz2obj.compress(data)
666 self.fileobj.write(raw)
667
668 def close(self):
669 if self.mode == "w":
670 raw = self.bz2obj.flush()
671 self.fileobj.write(raw)
672 self.fileobj.close()
673# class _BZ2Proxy
674
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000675#------------------------
676# Extraction file object
677#------------------------
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000678class _FileInFile(object):
679 """A thin wrapper around an existing file object that
680 provides a part of its data as an individual file
681 object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000682 """
683
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000684 def __init__(self, fileobj, offset, size, sparse=None):
685 self.fileobj = fileobj
686 self.offset = offset
687 self.size = size
688 self.sparse = sparse
689 self.position = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000690
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000691 def seekable(self):
692 if not hasattr(self.fileobj, "seekable"):
693 # XXX gzip.GzipFile and bz2.BZ2File
694 return True
695 return self.fileobj.seekable()
696
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000697 def tell(self):
698 """Return the current file position.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000699 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000700 return self.position
701
702 def seek(self, position):
703 """Seek to a position in the file.
704 """
705 self.position = position
706
707 def read(self, size=None):
708 """Read data from the file.
709 """
710 if size is None:
711 size = self.size - self.position
712 else:
713 size = min(size, self.size - self.position)
714
715 if self.sparse is None:
716 return self.readnormal(size)
717 else:
718 return self.readsparse(size)
719
720 def readnormal(self, size):
721 """Read operation for regular files.
722 """
723 self.fileobj.seek(self.offset + self.position)
724 self.position += size
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000725 return self.fileobj.read(size)
726
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000727 def readsparse(self, size):
728 """Read operation for sparse files.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000729 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000730 data = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000731 while size > 0:
732 buf = self.readsparsesection(size)
733 if not buf:
734 break
735 size -= len(buf)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000736 data += buf
737 return data
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000738
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000739 def readsparsesection(self, size):
740 """Read a single section of a sparse file.
741 """
742 section = self.sparse.find(self.position)
743
744 if section is None:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000745 return b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000746
747 size = min(size, section.offset + section.size - self.position)
748
749 if isinstance(section, _data):
750 realpos = section.realpos + self.position - section.offset
751 self.fileobj.seek(self.offset + realpos)
752 self.position += size
753 return self.fileobj.read(size)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000754 else:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000755 self.position += size
756 return NUL * size
757#class _FileInFile
758
759
760class ExFileObject(object):
761 """File-like object for reading an archive member.
762 Is returned by TarFile.extractfile().
763 """
764 blocksize = 1024
765
766 def __init__(self, tarfile, tarinfo):
767 self.fileobj = _FileInFile(tarfile.fileobj,
768 tarinfo.offset_data,
769 tarinfo.size,
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +0000770 tarinfo.sparse)
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000771 self.name = tarinfo.name
772 self.mode = "r"
773 self.closed = False
774 self.size = tarinfo.size
775
776 self.position = 0
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000777 self.buffer = b""
778
779 def readable(self):
780 return True
781
782 def writable(self):
783 return False
784
785 def seekable(self):
786 return self.fileobj.seekable()
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000787
788 def read(self, size=None):
789 """Read at most size bytes from the file. If size is not
790 present or None, read all data until EOF is reached.
791 """
792 if self.closed:
793 raise ValueError("I/O operation on closed file")
794
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000795 buf = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000796 if self.buffer:
797 if size is None:
798 buf = self.buffer
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000799 self.buffer = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000800 else:
801 buf = self.buffer[:size]
802 self.buffer = self.buffer[size:]
803
804 if size is None:
805 buf += self.fileobj.read()
806 else:
807 buf += self.fileobj.read(size - len(buf))
808
809 self.position += len(buf)
810 return buf
811
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000812 # XXX TextIOWrapper uses the read1() method.
813 read1 = read
814
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000815 def readline(self, size=-1):
816 """Read one entire line from the file. If size is present
817 and non-negative, return a string with at most that
818 size, which may be an incomplete line.
819 """
820 if self.closed:
821 raise ValueError("I/O operation on closed file")
822
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000823 pos = self.buffer.find(b"\n") + 1
824 if pos == 0:
825 # no newline found.
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000826 while True:
827 buf = self.fileobj.read(self.blocksize)
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000828 self.buffer += buf
829 if not buf or b"\n" in buf:
830 pos = self.buffer.find(b"\n") + 1
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000831 if pos == 0:
832 # no newline found.
833 pos = len(self.buffer)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000834 break
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000835
836 if size != -1:
837 pos = min(size, pos)
838
839 buf = self.buffer[:pos]
840 self.buffer = self.buffer[pos:]
841 self.position += len(buf)
842 return buf
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000843
844 def readlines(self):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000845 """Return a list with all remaining lines.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000846 """
847 result = []
848 while True:
849 line = self.readline()
850 if not line: break
851 result.append(line)
852 return result
853
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000854 def tell(self):
855 """Return the current file position.
856 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000857 if self.closed:
858 raise ValueError("I/O operation on closed file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000859
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000860 return self.position
861
862 def seek(self, pos, whence=os.SEEK_SET):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000863 """Seek to a position in the file.
864 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000865 if self.closed:
866 raise ValueError("I/O operation on closed file")
867
868 if whence == os.SEEK_SET:
869 self.position = min(max(pos, 0), self.size)
870 elif whence == os.SEEK_CUR:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000871 if pos < 0:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000872 self.position = max(self.position + pos, 0)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000873 else:
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000874 self.position = min(self.position + pos, self.size)
875 elif whence == os.SEEK_END:
876 self.position = max(min(self.size + pos, self.size), 0)
877 else:
878 raise ValueError("Invalid argument")
879
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000880 self.buffer = b""
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000881 self.fileobj.seek(self.position)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000882
883 def close(self):
884 """Close the file object.
885 """
886 self.closed = True
Martin v. Löwisdf241532005-03-03 08:17:42 +0000887
888 def __iter__(self):
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000889 """Get an iterator over the file's lines.
Martin v. Löwisdf241532005-03-03 08:17:42 +0000890 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000891 while True:
892 line = self.readline()
893 if not line:
894 break
895 yield line
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000896#class ExFileObject
897
898#------------------
899# Exported Classes
900#------------------
901class TarInfo(object):
902 """Informational class which holds the details about an
903 archive member given by a tar header block.
904 TarInfo objects are returned by TarFile.getmember(),
905 TarFile.getmembers() and TarFile.gettarinfo() and are
906 usually created internally.
907 """
908
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +0000909 __slots__ = ("name", "mode", "uid", "gid", "size", "mtime",
910 "chksum", "type", "linkname", "uname", "gname",
911 "devmajor", "devminor",
912 "offset", "offset_data", "pax_headers", "sparse",
913 "tarfile", "_sparse_structs", "_link_target")
914
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000915 def __init__(self, name=""):
916 """Construct a TarInfo object. name is the optional name
917 of the member.
918 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000919 self.name = name # member name
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000920 self.mode = 0o644 # file permissions
Thomas Wouters477c8d52006-05-27 19:21:47 +0000921 self.uid = 0 # user id
922 self.gid = 0 # group id
923 self.size = 0 # file size
924 self.mtime = 0 # modification time
925 self.chksum = 0 # header checksum
926 self.type = REGTYPE # member type
927 self.linkname = "" # link name
Guido van Rossumd8faa362007-04-27 19:54:29 +0000928 self.uname = "root" # user name
929 self.gname = "root" # group name
Thomas Wouters477c8d52006-05-27 19:21:47 +0000930 self.devmajor = 0 # device major number
931 self.devminor = 0 # device minor number
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000932
Thomas Wouters477c8d52006-05-27 19:21:47 +0000933 self.offset = 0 # the tar header starts here
934 self.offset_data = 0 # the file's data starts here
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000935
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +0000936 self.sparse = None # sparse member information
Guido van Rossumd8faa362007-04-27 19:54:29 +0000937 self.pax_headers = {} # pax header information
938
939 # In pax headers the "name" and "linkname" field are called
940 # "path" and "linkpath".
941 def _getpath(self):
942 return self.name
943 def _setpath(self, name):
944 self.name = name
945 path = property(_getpath, _setpath)
946
947 def _getlinkpath(self):
948 return self.linkname
949 def _setlinkpath(self, linkname):
950 self.linkname = linkname
951 linkpath = property(_getlinkpath, _setlinkpath)
952
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000953 def __repr__(self):
954 return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self))
955
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000956 def get_info(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000957 """Return the TarInfo's attributes as a dictionary.
958 """
959 info = {
960 "name": normpath(self.name),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000961 "mode": self.mode & 0o7777,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000962 "uid": self.uid,
963 "gid": self.gid,
964 "size": self.size,
965 "mtime": self.mtime,
966 "chksum": self.chksum,
967 "type": self.type,
968 "linkname": normpath(self.linkname) if self.linkname else "",
969 "uname": self.uname,
970 "gname": self.gname,
971 "devmajor": self.devmajor,
972 "devminor": self.devminor
973 }
974
975 if info["type"] == DIRTYPE and not info["name"].endswith("/"):
976 info["name"] += "/"
977
978 return info
979
Guido van Rossume7ba4952007-06-06 23:52:48 +0000980 def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="strict"):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000981 """Return a tar header as a string of 512 byte blocks.
982 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000983 info = self.get_info()
Guido van Rossume7ba4952007-06-06 23:52:48 +0000984
Guido van Rossumd8faa362007-04-27 19:54:29 +0000985 if format == USTAR_FORMAT:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000986 return self.create_ustar_header(info, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000987 elif format == GNU_FORMAT:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000988 return self.create_gnu_header(info, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000989 elif format == PAX_FORMAT:
Lars Gustäbel3741eff2007-08-21 12:17:05 +0000990 return self.create_pax_header(info)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000991 else:
992 raise ValueError("invalid format")
993
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000994 def create_ustar_header(self, info, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000995 """Return the object as a ustar header block.
996 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000997 info["magic"] = POSIX_MAGIC
998
999 if len(info["linkname"]) > LENGTH_LINK:
1000 raise ValueError("linkname is too long")
1001
1002 if len(info["name"]) > LENGTH_NAME:
1003 info["prefix"], info["name"] = self._posix_split_name(info["name"])
1004
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001005 return self._create_header(info, USTAR_FORMAT, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001006
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001007 def create_gnu_header(self, info, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001008 """Return the object as a GNU header block sequence.
1009 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001010 info["magic"] = GNU_MAGIC
1011
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001012 buf = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001013 if len(info["linkname"]) > LENGTH_LINK:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001014 buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001015
1016 if len(info["name"]) > LENGTH_NAME:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001017 buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001018
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001019 return buf + self._create_header(info, GNU_FORMAT, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001020
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001021 def create_pax_header(self, info):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001022 """Return the object as a ustar header block. If it cannot be
1023 represented this way, prepend a pax extended header sequence
1024 with supplement information.
1025 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001026 info["magic"] = POSIX_MAGIC
1027 pax_headers = self.pax_headers.copy()
1028
1029 # Test string fields for values that exceed the field length or cannot
1030 # be represented in ASCII encoding.
1031 for name, hname, length in (
1032 ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK),
1033 ("uname", "uname", 32), ("gname", "gname", 32)):
1034
Guido van Rossume7ba4952007-06-06 23:52:48 +00001035 if hname in pax_headers:
1036 # The pax header has priority.
1037 continue
1038
Guido van Rossumd8faa362007-04-27 19:54:29 +00001039 # Try to encode the string as ASCII.
1040 try:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001041 info[name].encode("ascii", "strict")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001042 except UnicodeEncodeError:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001043 pax_headers[hname] = info[name]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001044 continue
1045
Guido van Rossume7ba4952007-06-06 23:52:48 +00001046 if len(info[name]) > length:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001047 pax_headers[hname] = info[name]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001048
1049 # Test number fields for values that exceed the field limit or values
1050 # that like to be stored as float.
1051 for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)):
Guido van Rossume7ba4952007-06-06 23:52:48 +00001052 if name in pax_headers:
1053 # The pax header has priority. Avoid overflow.
1054 info[name] = 0
1055 continue
1056
Guido van Rossumd8faa362007-04-27 19:54:29 +00001057 val = info[name]
1058 if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float):
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001059 pax_headers[name] = str(val)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001060 info[name] = 0
1061
Guido van Rossume7ba4952007-06-06 23:52:48 +00001062 # Create a pax extended header if necessary.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001063 if pax_headers:
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001064 buf = self._create_pax_generic_header(pax_headers, XHDTYPE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001065 else:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001066 buf = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001067
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001068 return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001069
1070 @classmethod
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001071 def create_pax_global_header(cls, pax_headers):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001072 """Return the object as a pax global header block sequence.
1073 """
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001074 return cls._create_pax_generic_header(pax_headers, XGLTYPE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001075
1076 def _posix_split_name(self, name):
1077 """Split a name longer than 100 chars into a prefix
1078 and a name part.
1079 """
1080 prefix = name[:LENGTH_PREFIX + 1]
1081 while prefix and prefix[-1] != "/":
1082 prefix = prefix[:-1]
1083
1084 name = name[len(prefix):]
1085 prefix = prefix[:-1]
1086
1087 if not prefix or len(name) > LENGTH_NAME:
1088 raise ValueError("name is too long")
1089 return prefix, name
1090
1091 @staticmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001092 def _create_header(info, format, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001093 """Return a header block. info is a dictionary with file
1094 information, format must be one of the *_FORMAT constants.
1095 """
1096 parts = [
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001097 stn(info.get("name", ""), 100, encoding, errors),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001098 itn(info.get("mode", 0) & 0o7777, 8, format),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001099 itn(info.get("uid", 0), 8, format),
1100 itn(info.get("gid", 0), 8, format),
1101 itn(info.get("size", 0), 12, format),
1102 itn(info.get("mtime", 0), 12, format),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001103 b" ", # checksum field
Guido van Rossumd8faa362007-04-27 19:54:29 +00001104 info.get("type", REGTYPE),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001105 stn(info.get("linkname", ""), 100, encoding, errors),
1106 info.get("magic", POSIX_MAGIC),
1107 stn(info.get("uname", "root"), 32, encoding, errors),
1108 stn(info.get("gname", "root"), 32, encoding, errors),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001109 itn(info.get("devmajor", 0), 8, format),
1110 itn(info.get("devminor", 0), 8, format),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001111 stn(info.get("prefix", ""), 155, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001112 ]
1113
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001114 buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001115 chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
Lars Gustäbela280ca752007-08-28 07:34:33 +00001116 buf = buf[:-364] + bytes("%06o\0" % chksum, "ascii") + buf[-357:]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001117 return buf
1118
1119 @staticmethod
1120 def _create_payload(payload):
1121 """Return the string payload filled with zero bytes
1122 up to the next 512 byte border.
1123 """
1124 blocks, remainder = divmod(len(payload), BLOCKSIZE)
1125 if remainder > 0:
1126 payload += (BLOCKSIZE - remainder) * NUL
1127 return payload
1128
1129 @classmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001130 def _create_gnu_long_header(cls, name, type, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001131 """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence
1132 for name.
1133 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001134 name = name.encode(encoding, errors) + NUL
Guido van Rossumd8faa362007-04-27 19:54:29 +00001135
1136 info = {}
1137 info["name"] = "././@LongLink"
1138 info["type"] = type
1139 info["size"] = len(name)
1140 info["magic"] = GNU_MAGIC
1141
1142 # create extended header + name blocks.
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001143 return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \
Guido van Rossumd8faa362007-04-27 19:54:29 +00001144 cls._create_payload(name)
1145
1146 @classmethod
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001147 def _create_pax_generic_header(cls, pax_headers, type):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001148 """Return a POSIX.1-2001 extended or global header sequence
1149 that contains a list of keyword, value pairs. The values
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001150 must be strings.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001151 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001152 records = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001153 for keyword, value in pax_headers.items():
1154 keyword = keyword.encode("utf8")
1155 value = value.encode("utf8")
1156 l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n'
1157 n = p = 0
1158 while True:
1159 n = l + len(str(p))
1160 if n == p:
1161 break
1162 p = n
Lars Gustäbela280ca752007-08-28 07:34:33 +00001163 records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n"
Guido van Rossumd8faa362007-04-27 19:54:29 +00001164
1165 # We use a hardcoded "././@PaxHeader" name like star does
1166 # instead of the one that POSIX recommends.
1167 info = {}
1168 info["name"] = "././@PaxHeader"
1169 info["type"] = type
1170 info["size"] = len(records)
1171 info["magic"] = POSIX_MAGIC
1172
1173 # Create pax header + record blocks.
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001174 return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \
Guido van Rossumd8faa362007-04-27 19:54:29 +00001175 cls._create_payload(records)
1176
Guido van Rossum75b64e62005-01-16 00:16:11 +00001177 @classmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001178 def frombuf(cls, buf, encoding, errors):
1179 """Construct a TarInfo object from a 512 byte bytes object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001180 """
Thomas Wouters477c8d52006-05-27 19:21:47 +00001181 if len(buf) != BLOCKSIZE:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001182 raise HeaderError("truncated header")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001183 if buf.count(NUL) == BLOCKSIZE:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001184 raise HeaderError("empty header")
1185
1186 chksum = nti(buf[148:156])
1187 if chksum not in calc_chksums(buf):
1188 raise HeaderError("bad checksum")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001189
Guido van Rossumd8faa362007-04-27 19:54:29 +00001190 obj = cls()
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001191 obj.name = nts(buf[0:100], encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001192 obj.mode = nti(buf[100:108])
1193 obj.uid = nti(buf[108:116])
1194 obj.gid = nti(buf[116:124])
1195 obj.size = nti(buf[124:136])
1196 obj.mtime = nti(buf[136:148])
1197 obj.chksum = chksum
1198 obj.type = buf[156:157]
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001199 obj.linkname = nts(buf[157:257], encoding, errors)
1200 obj.uname = nts(buf[265:297], encoding, errors)
1201 obj.gname = nts(buf[297:329], encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001202 obj.devmajor = nti(buf[329:337])
1203 obj.devminor = nti(buf[337:345])
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001204 prefix = nts(buf[345:500], encoding, errors)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001205
Guido van Rossumd8faa362007-04-27 19:54:29 +00001206 # Old V7 tar format represents a directory as a regular
1207 # file with a trailing slash.
1208 if obj.type == AREGTYPE and obj.name.endswith("/"):
1209 obj.type = DIRTYPE
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001210
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001211 # The old GNU sparse format occupies some of the unused
1212 # space in the buffer for up to 4 sparse structures.
1213 # Save the them for later processing in _proc_sparse().
1214 if obj.type == GNUTYPE_SPARSE:
1215 pos = 386
1216 structs = []
1217 for i in range(4):
1218 try:
1219 offset = nti(buf[pos:pos + 12])
1220 numbytes = nti(buf[pos + 12:pos + 24])
1221 except ValueError:
1222 break
1223 structs.append((offset, numbytes))
1224 pos += 24
1225 isextended = bool(buf[482])
1226 origsize = nti(buf[483:495])
1227 obj._sparse_structs = (structs, isextended, origsize)
1228
Guido van Rossumd8faa362007-04-27 19:54:29 +00001229 # Remove redundant slashes from directories.
1230 if obj.isdir():
1231 obj.name = obj.name.rstrip("/")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001232
Guido van Rossumd8faa362007-04-27 19:54:29 +00001233 # Reconstruct a ustar longname.
1234 if prefix and obj.type not in GNU_TYPES:
1235 obj.name = prefix + "/" + obj.name
1236 return obj
1237
1238 @classmethod
1239 def fromtarfile(cls, tarfile):
1240 """Return the next TarInfo object from TarFile object
1241 tarfile.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001242 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001243 buf = tarfile.fileobj.read(BLOCKSIZE)
1244 if not buf:
1245 return
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001246 obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001247 obj.offset = tarfile.fileobj.tell() - BLOCKSIZE
1248 return obj._proc_member(tarfile)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001249
Guido van Rossumd8faa362007-04-27 19:54:29 +00001250 #--------------------------------------------------------------------------
1251 # The following are methods that are called depending on the type of a
1252 # member. The entry point is _proc_member() which can be overridden in a
1253 # subclass to add custom _proc_*() methods. A _proc_*() method MUST
1254 # implement the following
1255 # operations:
1256 # 1. Set self.offset_data to the position where the data blocks begin,
1257 # if there is data that follows.
1258 # 2. Set tarfile.offset to the position where the next member's header will
1259 # begin.
1260 # 3. Return self or another valid TarInfo object.
1261 def _proc_member(self, tarfile):
1262 """Choose the right processing method depending on
1263 the type and call it.
Thomas Wouters89f507f2006-12-13 04:49:30 +00001264 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001265 if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
1266 return self._proc_gnulong(tarfile)
1267 elif self.type == GNUTYPE_SPARSE:
1268 return self._proc_sparse(tarfile)
1269 elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE):
1270 return self._proc_pax(tarfile)
1271 else:
1272 return self._proc_builtin(tarfile)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001273
Guido van Rossumd8faa362007-04-27 19:54:29 +00001274 def _proc_builtin(self, tarfile):
1275 """Process a builtin type or an unknown type which
1276 will be treated as a regular file.
1277 """
1278 self.offset_data = tarfile.fileobj.tell()
1279 offset = self.offset_data
1280 if self.isreg() or self.type not in SUPPORTED_TYPES:
1281 # Skip the following data blocks.
1282 offset += self._block(self.size)
1283 tarfile.offset = offset
Thomas Wouters89f507f2006-12-13 04:49:30 +00001284
Guido van Rossume7ba4952007-06-06 23:52:48 +00001285 # Patch the TarInfo object with saved global
Guido van Rossumd8faa362007-04-27 19:54:29 +00001286 # header information.
Guido van Rossume7ba4952007-06-06 23:52:48 +00001287 self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001288
1289 return self
1290
1291 def _proc_gnulong(self, tarfile):
1292 """Process the blocks that hold a GNU longname
1293 or longlink member.
1294 """
1295 buf = tarfile.fileobj.read(self._block(self.size))
1296
1297 # Fetch the next header and process it.
Guido van Rossume7ba4952007-06-06 23:52:48 +00001298 next = self.fromtarfile(tarfile)
1299 if next is None:
1300 raise HeaderError("missing subsequent header")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001301
1302 # Patch the TarInfo object from the next header with
1303 # the longname information.
1304 next.offset = self.offset
1305 if self.type == GNUTYPE_LONGNAME:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001306 next.name = nts(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001307 elif self.type == GNUTYPE_LONGLINK:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001308 next.linkname = nts(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001309
1310 return next
1311
1312 def _proc_sparse(self, tarfile):
1313 """Process a GNU sparse header plus extra headers.
1314 """
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001315 # We already collected some sparse structures in frombuf().
1316 structs, isextended, origsize = self._sparse_structs
1317 del self._sparse_structs
Guido van Rossumd8faa362007-04-27 19:54:29 +00001318
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001319 # Collect sparse structures from extended header blocks.
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001320 while isextended:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001321 buf = tarfile.fileobj.read(BLOCKSIZE)
1322 pos = 0
Guido van Rossum805365e2007-05-07 22:24:25 +00001323 for i in range(21):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001324 try:
1325 offset = nti(buf[pos:pos + 12])
1326 numbytes = nti(buf[pos + 12:pos + 24])
1327 except ValueError:
1328 break
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001329 structs.append((offset, numbytes))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001330 pos += 24
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001331 isextended = bool(buf[504])
Guido van Rossumd8faa362007-04-27 19:54:29 +00001332
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001333 # Transform the sparse structures to something we can use
1334 # in ExFileObject.
1335 self.sparse = _ringbuffer()
1336 lastpos = 0
1337 realpos = 0
1338 for offset, numbytes in structs:
1339 if offset > lastpos:
1340 self.sparse.append(_hole(lastpos, offset - lastpos))
1341 self.sparse.append(_data(offset, numbytes, realpos))
1342 realpos += numbytes
1343 lastpos = offset + numbytes
Guido van Rossumd8faa362007-04-27 19:54:29 +00001344 if lastpos < origsize:
Lars Gustäbelc2ea8c62008-04-14 10:05:48 +00001345 self.sparse.append(_hole(lastpos, origsize - lastpos))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001346
1347 self.offset_data = tarfile.fileobj.tell()
1348 tarfile.offset = self.offset_data + self._block(self.size)
1349 self.size = origsize
1350
1351 return self
1352
1353 def _proc_pax(self, tarfile):
1354 """Process an extended or global header as described in
1355 POSIX.1-2001.
1356 """
1357 # Read the header information.
1358 buf = tarfile.fileobj.read(self._block(self.size))
1359
1360 # A pax header stores supplemental information for either
1361 # the following file (extended) or all following files
1362 # (global).
1363 if self.type == XGLTYPE:
1364 pax_headers = tarfile.pax_headers
1365 else:
1366 pax_headers = tarfile.pax_headers.copy()
1367
Guido van Rossumd8faa362007-04-27 19:54:29 +00001368 # Parse pax header information. A record looks like that:
1369 # "%d %s=%s\n" % (length, keyword, value). length is the size
1370 # of the complete record including the length field itself and
Guido van Rossume7ba4952007-06-06 23:52:48 +00001371 # the newline. keyword and value are both UTF-8 encoded strings.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001372 regex = re.compile(r"(\d+) ([^=]+)=", re.U)
1373 pos = 0
1374 while True:
1375 match = regex.match(buf, pos)
1376 if not match:
1377 break
1378
1379 length, keyword = match.groups()
1380 length = int(length)
1381 value = buf[match.end(2) + 1:match.start(1) + length - 1]
1382
1383 keyword = keyword.decode("utf8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001384 value = value.decode("utf8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001385
1386 pax_headers[keyword] = value
1387 pos += length
1388
Guido van Rossume7ba4952007-06-06 23:52:48 +00001389 # Fetch the next header.
1390 next = self.fromtarfile(tarfile)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001391
Guido van Rossume7ba4952007-06-06 23:52:48 +00001392 if self.type in (XHDTYPE, SOLARIS_XHDTYPE):
1393 if next is None:
1394 raise HeaderError("missing subsequent header")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001395
Guido van Rossume7ba4952007-06-06 23:52:48 +00001396 # Patch the TarInfo object with the extended header info.
1397 next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors)
1398 next.offset = self.offset
1399
1400 if "size" in pax_headers:
1401 # If the extended header replaces the size field,
1402 # we need to recalculate the offset where the next
1403 # header starts.
1404 offset = next.offset_data
1405 if next.isreg() or next.type not in SUPPORTED_TYPES:
1406 offset += next._block(next.size)
1407 tarfile.offset = offset
1408
1409 return next
1410
1411 def _apply_pax_info(self, pax_headers, encoding, errors):
1412 """Replace fields with supplemental information from a previous
1413 pax extended or global header.
1414 """
1415 for keyword, value in pax_headers.items():
1416 if keyword not in PAX_FIELDS:
1417 continue
1418
1419 if keyword == "path":
1420 value = value.rstrip("/")
1421
1422 if keyword in PAX_NUMBER_FIELDS:
1423 try:
1424 value = PAX_NUMBER_FIELDS[keyword](value)
1425 except ValueError:
1426 value = 0
Guido van Rossume7ba4952007-06-06 23:52:48 +00001427
1428 setattr(self, keyword, value)
1429
1430 self.pax_headers = pax_headers.copy()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001431
1432 def _block(self, count):
1433 """Round up a byte count by BLOCKSIZE and return it,
1434 e.g. _block(834) => 1024.
1435 """
1436 blocks, remainder = divmod(count, BLOCKSIZE)
1437 if remainder:
1438 blocks += 1
1439 return blocks * BLOCKSIZE
Thomas Wouters89f507f2006-12-13 04:49:30 +00001440
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001441 def isreg(self):
1442 return self.type in REGULAR_TYPES
1443 def isfile(self):
1444 return self.isreg()
1445 def isdir(self):
1446 return self.type == DIRTYPE
1447 def issym(self):
1448 return self.type == SYMTYPE
1449 def islnk(self):
1450 return self.type == LNKTYPE
1451 def ischr(self):
1452 return self.type == CHRTYPE
1453 def isblk(self):
1454 return self.type == BLKTYPE
1455 def isfifo(self):
1456 return self.type == FIFOTYPE
1457 def issparse(self):
1458 return self.type == GNUTYPE_SPARSE
1459 def isdev(self):
1460 return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
1461# class TarInfo
1462
1463class TarFile(object):
1464 """The TarFile Class provides an interface to tar archives.
1465 """
1466
1467 debug = 0 # May be set from 0 (no msgs) to 3 (all msgs)
1468
1469 dereference = False # If true, add content of linked file to the
1470 # tar file, else the link.
1471
1472 ignore_zeros = False # If true, skips empty or invalid blocks and
1473 # continues processing.
1474
1475 errorlevel = 0 # If 0, fatal errors only appear in debug
1476 # messages (if debug >= 0). If > 0, errors
1477 # are passed to the caller as exceptions.
1478
Guido van Rossumd8faa362007-04-27 19:54:29 +00001479 format = DEFAULT_FORMAT # The format to use when creating an archive.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001480
Guido van Rossume7ba4952007-06-06 23:52:48 +00001481 encoding = ENCODING # Encoding for 8-bit character strings.
1482
1483 errors = None # Error handler for unicode conversion.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001484
Guido van Rossumd8faa362007-04-27 19:54:29 +00001485 tarinfo = TarInfo # The default TarInfo class to use.
1486
1487 fileobject = ExFileObject # The default ExFileObject class to use.
1488
1489 def __init__(self, name=None, mode="r", fileobj=None, format=None,
1490 tarinfo=None, dereference=None, ignore_zeros=None, encoding=None,
Guido van Rossume7ba4952007-06-06 23:52:48 +00001491 errors=None, pax_headers=None, debug=None, errorlevel=None):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001492 """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
1493 read from an existing archive, 'a' to append data to an existing
1494 file or 'w' to create a new file overwriting an existing one. `mode'
1495 defaults to 'r'.
1496 If `fileobj' is given, it is used for reading or writing data. If it
1497 can be determined, `mode' is overridden by `fileobj's mode.
1498 `fileobj' is not closed, when TarFile is closed.
1499 """
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001500 if len(mode) > 1 or mode not in "raw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001501 raise ValueError("mode must be 'r', 'a' or 'w'")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001502 self.mode = mode
1503 self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001504
1505 if not fileobj:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001506 if self.mode == "a" and not os.path.exists(name):
Thomas Wouterscf297e42007-02-23 15:07:44 +00001507 # Create nonexistent files in append mode.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001508 self.mode = "w"
1509 self._mode = "wb"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001510 fileobj = bltn_open(name, self._mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001511 self._extfileobj = False
1512 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001513 if name is None and hasattr(fileobj, "name"):
1514 name = fileobj.name
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001515 if hasattr(fileobj, "mode"):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001516 self._mode = fileobj.mode
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001517 self._extfileobj = True
Thomas Woutersed03b412007-08-28 21:37:11 +00001518 self.name = os.path.abspath(name) if name else None
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001519 self.fileobj = fileobj
1520
Guido van Rossumd8faa362007-04-27 19:54:29 +00001521 # Init attributes.
1522 if format is not None:
1523 self.format = format
1524 if tarinfo is not None:
1525 self.tarinfo = tarinfo
1526 if dereference is not None:
1527 self.dereference = dereference
1528 if ignore_zeros is not None:
1529 self.ignore_zeros = ignore_zeros
1530 if encoding is not None:
1531 self.encoding = encoding
Guido van Rossume7ba4952007-06-06 23:52:48 +00001532
1533 if errors is not None:
1534 self.errors = errors
1535 elif mode == "r":
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001536 self.errors = "replace"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001537 else:
1538 self.errors = "strict"
1539
1540 if pax_headers is not None and self.format == PAX_FORMAT:
1541 self.pax_headers = pax_headers
1542 else:
1543 self.pax_headers = {}
1544
Guido van Rossumd8faa362007-04-27 19:54:29 +00001545 if debug is not None:
1546 self.debug = debug
1547 if errorlevel is not None:
1548 self.errorlevel = errorlevel
1549
1550 # Init datastructures.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001551 self.closed = False
1552 self.members = [] # list of members as TarInfo objects
1553 self._loaded = False # flag if all members have been read
Christian Heimesd8654cf2007-12-02 15:22:16 +00001554 self.offset = self.fileobj.tell()
1555 # current position in the archive file
Thomas Wouters477c8d52006-05-27 19:21:47 +00001556 self.inodes = {} # dictionary caching the inodes of
1557 # archive members already added
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001558
Guido van Rossumd8faa362007-04-27 19:54:29 +00001559 if self.mode == "r":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001560 self.firstmember = None
1561 self.firstmember = self.next()
1562
Guido van Rossumd8faa362007-04-27 19:54:29 +00001563 if self.mode == "a":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001564 # Move to the end of the archive,
1565 # before the first empty block.
1566 self.firstmember = None
1567 while True:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001568 if self.next() is None:
Thomas Wouterscf297e42007-02-23 15:07:44 +00001569 if self.offset > 0:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001570 self.fileobj.seek(self.fileobj.tell() - BLOCKSIZE)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001571 break
1572
Guido van Rossumd8faa362007-04-27 19:54:29 +00001573 if self.mode in "aw":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001574 self._loaded = True
1575
Guido van Rossume7ba4952007-06-06 23:52:48 +00001576 if self.pax_headers:
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001577 buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy())
Guido van Rossumd8faa362007-04-27 19:54:29 +00001578 self.fileobj.write(buf)
1579 self.offset += len(buf)
1580
1581 def _getposix(self):
1582 return self.format == USTAR_FORMAT
1583 def _setposix(self, value):
1584 import warnings
1585 warnings.warn("use the format attribute instead", DeprecationWarning)
1586 if value:
1587 self.format = USTAR_FORMAT
1588 else:
1589 self.format = GNU_FORMAT
1590 posix = property(_getposix, _setposix)
1591
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001592 #--------------------------------------------------------------------------
1593 # Below are the classmethods which act as alternate constructors to the
1594 # TarFile class. The open() method is the only one that is needed for
1595 # public use; it is the "super"-constructor and is able to select an
1596 # adequate "sub"-constructor for a particular compression using the mapping
1597 # from OPEN_METH.
1598 #
1599 # This concept allows one to subclass TarFile without losing the comfort of
1600 # the super-constructor. A sub-constructor is registered and made available
1601 # by adding it to the mapping in OPEN_METH.
1602
Guido van Rossum75b64e62005-01-16 00:16:11 +00001603 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001604 def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001605 """Open a tar archive for reading, writing or appending. Return
1606 an appropriate TarFile class.
1607
1608 mode:
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001609 'r' or 'r:*' open for reading with transparent compression
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001610 'r:' open for reading exclusively uncompressed
1611 'r:gz' open for reading with gzip compression
1612 'r:bz2' open for reading with bzip2 compression
Thomas Wouterscf297e42007-02-23 15:07:44 +00001613 'a' or 'a:' open for appending, creating the file if necessary
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001614 'w' or 'w:' open for writing without compression
1615 'w:gz' open for writing with gzip compression
1616 'w:bz2' open for writing with bzip2 compression
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001617
1618 'r|*' open a stream of tar blocks with transparent compression
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001619 'r|' open an uncompressed stream of tar blocks for reading
1620 'r|gz' open a gzip compressed stream of tar blocks
1621 'r|bz2' open a bzip2 compressed stream of tar blocks
1622 'w|' open an uncompressed stream for writing
1623 'w|gz' open a gzip compressed stream for writing
1624 'w|bz2' open a bzip2 compressed stream for writing
1625 """
1626
1627 if not name and not fileobj:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001628 raise ValueError("nothing to open")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001629
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001630 if mode in ("r", "r:*"):
1631 # Find out which *open() is appropriate for opening the file.
1632 for comptype in cls.OPEN_METH:
1633 func = getattr(cls, cls.OPEN_METH[comptype])
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001634 if fileobj is not None:
1635 saved_pos = fileobj.tell()
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001636 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001637 return func(name, "r", fileobj, **kwargs)
1638 except (ReadError, CompressionError) as e:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001639 if fileobj is not None:
1640 fileobj.seek(saved_pos)
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001641 continue
Thomas Wouters477c8d52006-05-27 19:21:47 +00001642 raise ReadError("file could not be opened successfully")
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001643
1644 elif ":" in mode:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001645 filemode, comptype = mode.split(":", 1)
1646 filemode = filemode or "r"
1647 comptype = comptype or "tar"
1648
1649 # Select the *open() function according to
1650 # given compression.
1651 if comptype in cls.OPEN_METH:
1652 func = getattr(cls, cls.OPEN_METH[comptype])
1653 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001654 raise CompressionError("unknown compression type %r" % comptype)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001655 return func(name, filemode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001656
1657 elif "|" in mode:
1658 filemode, comptype = mode.split("|", 1)
1659 filemode = filemode or "r"
1660 comptype = comptype or "tar"
1661
1662 if filemode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001663 raise ValueError("mode must be 'r' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001664
1665 t = cls(name, filemode,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001666 _Stream(name, filemode, comptype, fileobj, bufsize),
1667 **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001668 t._extfileobj = False
1669 return t
1670
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001671 elif mode in "aw":
Guido van Rossumd8faa362007-04-27 19:54:29 +00001672 return cls.taropen(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001673
Thomas Wouters477c8d52006-05-27 19:21:47 +00001674 raise ValueError("undiscernible mode")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001675
Guido van Rossum75b64e62005-01-16 00:16:11 +00001676 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001677 def taropen(cls, name, mode="r", fileobj=None, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001678 """Open uncompressed tar archive name for reading or writing.
1679 """
1680 if len(mode) > 1 or mode not in "raw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001681 raise ValueError("mode must be 'r', 'a' or 'w'")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001682 return cls(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001683
Guido van Rossum75b64e62005-01-16 00:16:11 +00001684 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001685 def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001686 """Open gzip compressed tar archive name for reading or writing.
1687 Appending is not allowed.
1688 """
1689 if len(mode) > 1 or mode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001690 raise ValueError("mode must be 'r' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001691
1692 try:
1693 import gzip
Neal Norwitz4ec68242003-04-11 03:05:56 +00001694 gzip.GzipFile
1695 except (ImportError, AttributeError):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001696 raise CompressionError("gzip module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001697
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001698 if fileobj is None:
Guido van Rossume7ba4952007-06-06 23:52:48 +00001699 fileobj = bltn_open(name, mode + "b")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001700
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001701 try:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001702 t = cls.taropen(name, mode,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001703 gzip.GzipFile(name, mode, compresslevel, fileobj),
1704 **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001705 except IOError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001706 raise ReadError("not a gzip file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001707 t._extfileobj = False
1708 return t
1709
Guido van Rossum75b64e62005-01-16 00:16:11 +00001710 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001711 def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001712 """Open bzip2 compressed tar archive name for reading or writing.
1713 Appending is not allowed.
1714 """
1715 if len(mode) > 1 or mode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001716 raise ValueError("mode must be 'r' or 'w'.")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001717
1718 try:
1719 import bz2
1720 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001721 raise CompressionError("bz2 module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001722
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001723 if fileobj is not None:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001724 fileobj = _BZ2Proxy(fileobj, mode)
1725 else:
1726 fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001727
1728 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001729 t = cls.taropen(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001730 except IOError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001731 raise ReadError("not a bzip2 file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001732 t._extfileobj = False
1733 return t
1734
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001735 # All *open() methods are registered here.
1736 OPEN_METH = {
1737 "tar": "taropen", # uncompressed tar
1738 "gz": "gzopen", # gzip compressed tar
1739 "bz2": "bz2open" # bzip2 compressed tar
1740 }
1741
1742 #--------------------------------------------------------------------------
1743 # The public methods which TarFile provides:
1744
1745 def close(self):
1746 """Close the TarFile. In write-mode, two finishing zero blocks are
1747 appended to the archive.
1748 """
1749 if self.closed:
1750 return
1751
Guido van Rossumd8faa362007-04-27 19:54:29 +00001752 if self.mode in "aw":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001753 self.fileobj.write(NUL * (BLOCKSIZE * 2))
1754 self.offset += (BLOCKSIZE * 2)
1755 # fill up the end with zero-blocks
1756 # (like option -b20 for tar does)
1757 blocks, remainder = divmod(self.offset, RECORDSIZE)
1758 if remainder > 0:
1759 self.fileobj.write(NUL * (RECORDSIZE - remainder))
1760
1761 if not self._extfileobj:
1762 self.fileobj.close()
1763 self.closed = True
1764
1765 def getmember(self, name):
1766 """Return a TarInfo object for member `name'. If `name' can not be
1767 found in the archive, KeyError is raised. If a member occurs more
1768 than once in the archive, its last occurence is assumed to be the
1769 most up-to-date version.
1770 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001771 tarinfo = self._getmember(name)
1772 if tarinfo is None:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001773 raise KeyError("filename %r not found" % name)
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001774 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001775
1776 def getmembers(self):
1777 """Return the members of the archive as a list of TarInfo objects. The
1778 list has the same order as the members in the archive.
1779 """
1780 self._check()
1781 if not self._loaded: # if we want to obtain a list of
1782 self._load() # all members, we first have to
1783 # scan the whole archive.
1784 return self.members
1785
1786 def getnames(self):
1787 """Return the members of the archive as a list of their names. It has
1788 the same order as the list returned by getmembers().
1789 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001790 return [tarinfo.name for tarinfo in self.getmembers()]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001791
1792 def gettarinfo(self, name=None, arcname=None, fileobj=None):
1793 """Create a TarInfo object for either the file `name' or the file
1794 object `fileobj' (using os.fstat on its file descriptor). You can
1795 modify some of the TarInfo's attributes before you add it using
1796 addfile(). If given, `arcname' specifies an alternative name for the
1797 file in the archive.
1798 """
1799 self._check("aw")
1800
1801 # When fileobj is given, replace name by
1802 # fileobj's real name.
1803 if fileobj is not None:
1804 name = fileobj.name
1805
1806 # Building the name of the member in the archive.
1807 # Backward slashes are converted to forward slashes,
1808 # Absolute paths are turned to relative paths.
1809 if arcname is None:
1810 arcname = name
1811 arcname = normpath(arcname)
1812 drv, arcname = os.path.splitdrive(arcname)
1813 while arcname[0:1] == "/":
1814 arcname = arcname[1:]
1815
1816 # Now, fill the TarInfo object with
1817 # information specific for the file.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001818 tarinfo = self.tarinfo()
1819 tarinfo.tarfile = self
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001820
1821 # Use os.stat or os.lstat, depending on platform
1822 # and if symlinks shall be resolved.
1823 if fileobj is None:
1824 if hasattr(os, "lstat") and not self.dereference:
1825 statres = os.lstat(name)
1826 else:
1827 statres = os.stat(name)
1828 else:
1829 statres = os.fstat(fileobj.fileno())
1830 linkname = ""
1831
1832 stmd = statres.st_mode
1833 if stat.S_ISREG(stmd):
1834 inode = (statres.st_ino, statres.st_dev)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001835 if not self.dereference and statres.st_nlink > 1 and \
1836 inode in self.inodes and arcname != self.inodes[inode]:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001837 # Is it a hardlink to an already
1838 # archived file?
1839 type = LNKTYPE
1840 linkname = self.inodes[inode]
1841 else:
1842 # The inode is added only if its valid.
1843 # For win32 it is always 0.
1844 type = REGTYPE
1845 if inode[0]:
1846 self.inodes[inode] = arcname
1847 elif stat.S_ISDIR(stmd):
1848 type = DIRTYPE
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001849 elif stat.S_ISFIFO(stmd):
1850 type = FIFOTYPE
1851 elif stat.S_ISLNK(stmd):
1852 type = SYMTYPE
1853 linkname = os.readlink(name)
1854 elif stat.S_ISCHR(stmd):
1855 type = CHRTYPE
1856 elif stat.S_ISBLK(stmd):
1857 type = BLKTYPE
1858 else:
1859 return None
1860
1861 # Fill the TarInfo object with all
1862 # information we can get.
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001863 tarinfo.name = arcname
1864 tarinfo.mode = stmd
1865 tarinfo.uid = statres.st_uid
1866 tarinfo.gid = statres.st_gid
1867 if stat.S_ISREG(stmd):
Martin v. Löwis61d77e02004-08-20 06:35:46 +00001868 tarinfo.size = statres.st_size
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001869 else:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001870 tarinfo.size = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001871 tarinfo.mtime = statres.st_mtime
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001872 tarinfo.type = type
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001873 tarinfo.linkname = linkname
1874 if pwd:
1875 try:
1876 tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
1877 except KeyError:
1878 pass
1879 if grp:
1880 try:
1881 tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
1882 except KeyError:
1883 pass
1884
1885 if type in (CHRTYPE, BLKTYPE):
1886 if hasattr(os, "major") and hasattr(os, "minor"):
1887 tarinfo.devmajor = os.major(statres.st_rdev)
1888 tarinfo.devminor = os.minor(statres.st_rdev)
1889 return tarinfo
1890
1891 def list(self, verbose=True):
1892 """Print a table of contents to sys.stdout. If `verbose' is False, only
1893 the names of the members are printed. If it is True, an `ls -l'-like
1894 output is produced.
1895 """
1896 self._check()
1897
1898 for tarinfo in self:
1899 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001900 print(filemode(tarinfo.mode), end=' ')
1901 print("%s/%s" % (tarinfo.uname or tarinfo.uid,
1902 tarinfo.gname or tarinfo.gid), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001903 if tarinfo.ischr() or tarinfo.isblk():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001904 print("%10s" % ("%d,%d" \
1905 % (tarinfo.devmajor, tarinfo.devminor)), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001906 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001907 print("%10d" % tarinfo.size, end=' ')
1908 print("%d-%02d-%02d %02d:%02d:%02d" \
1909 % time.localtime(tarinfo.mtime)[:6], end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001910
Guido van Rossumd8faa362007-04-27 19:54:29 +00001911 print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001912
1913 if verbose:
1914 if tarinfo.issym():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001915 print("->", tarinfo.linkname, end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001916 if tarinfo.islnk():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001917 print("link to", tarinfo.linkname, end=' ')
1918 print()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001919
Guido van Rossum486364b2007-06-30 05:01:58 +00001920 def add(self, name, arcname=None, recursive=True, exclude=None):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001921 """Add the file `name' to the archive. `name' may be any type of file
1922 (directory, fifo, symbolic link, etc.). If given, `arcname'
1923 specifies an alternative name for the file in the archive.
1924 Directories are added recursively by default. This can be avoided by
Guido van Rossum486364b2007-06-30 05:01:58 +00001925 setting `recursive' to False. `exclude' is a function that should
1926 return True for each filename to be excluded.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001927 """
1928 self._check("aw")
1929
1930 if arcname is None:
1931 arcname = name
1932
Guido van Rossum486364b2007-06-30 05:01:58 +00001933 # Exclude pathnames.
1934 if exclude is not None and exclude(name):
1935 self._dbg(2, "tarfile: Excluded %r" % name)
1936 return
1937
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001938 # Skip if somebody tries to archive the archive...
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001939 if self.name is not None and os.path.abspath(name) == self.name:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001940 self._dbg(2, "tarfile: Skipped %r" % name)
1941 return
1942
1943 # Special case: The user wants to add the current
1944 # working directory.
1945 if name == ".":
1946 if recursive:
1947 if arcname == ".":
1948 arcname = ""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001949 for f in os.listdir(name):
Guido van Rossum486364b2007-06-30 05:01:58 +00001950 self.add(f, os.path.join(arcname, f), recursive, exclude)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001951 return
1952
1953 self._dbg(1, name)
1954
1955 # Create a TarInfo object from the file.
1956 tarinfo = self.gettarinfo(name, arcname)
1957
1958 if tarinfo is None:
1959 self._dbg(1, "tarfile: Unsupported type %r" % name)
1960 return
1961
1962 # Append the tar header and data to the archive.
1963 if tarinfo.isreg():
Guido van Rossume7ba4952007-06-06 23:52:48 +00001964 f = bltn_open(name, "rb")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001965 self.addfile(tarinfo, f)
1966 f.close()
1967
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001968 elif tarinfo.isdir():
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001969 self.addfile(tarinfo)
1970 if recursive:
1971 for f in os.listdir(name):
Guido van Rossum486364b2007-06-30 05:01:58 +00001972 self.add(os.path.join(name, f), os.path.join(arcname, f), recursive, exclude)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001973
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001974 else:
1975 self.addfile(tarinfo)
1976
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001977 def addfile(self, tarinfo, fileobj=None):
1978 """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
1979 given, tarinfo.size bytes are read from it and added to the archive.
1980 You can create TarInfo objects using gettarinfo().
1981 On Windows platforms, `fileobj' should always be opened with mode
1982 'rb' to avoid irritation about the file size.
1983 """
1984 self._check("aw")
1985
Thomas Wouters89f507f2006-12-13 04:49:30 +00001986 tarinfo = copy.copy(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001987
Guido van Rossume7ba4952007-06-06 23:52:48 +00001988 buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001989 self.fileobj.write(buf)
1990 self.offset += len(buf)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001991
1992 # If there's data to follow, append it.
1993 if fileobj is not None:
1994 copyfileobj(fileobj, self.fileobj, tarinfo.size)
1995 blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
1996 if remainder > 0:
1997 self.fileobj.write(NUL * (BLOCKSIZE - remainder))
1998 blocks += 1
1999 self.offset += blocks * BLOCKSIZE
2000
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002001 self.members.append(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002002
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002003 def extractall(self, path=".", members=None):
2004 """Extract all members from the archive to the current working
2005 directory and set owner, modification time and permissions on
2006 directories afterwards. `path' specifies a different directory
2007 to extract to. `members' is optional and must be a subset of the
2008 list returned by getmembers().
2009 """
2010 directories = []
2011
2012 if members is None:
2013 members = self
2014
2015 for tarinfo in members:
2016 if tarinfo.isdir():
Christian Heimes2202f872008-02-06 14:31:34 +00002017 # Extract directories with a safe mode.
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002018 directories.append(tarinfo)
Christian Heimes2202f872008-02-06 14:31:34 +00002019 tarinfo = copy.copy(tarinfo)
2020 tarinfo.mode = 0o700
2021 self.extract(tarinfo, path)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002022
2023 # Reverse sort directories.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +00002024 directories.sort(key=lambda a: a.name)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002025 directories.reverse()
2026
2027 # Set correct owner, mtime and filemode on directories.
2028 for tarinfo in directories:
Christian Heimesfaf2f632008-01-06 16:59:19 +00002029 dirpath = os.path.join(path, tarinfo.name)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002030 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +00002031 self.chown(tarinfo, dirpath)
2032 self.utime(tarinfo, dirpath)
2033 self.chmod(tarinfo, dirpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002034 except ExtractError as e:
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002035 if self.errorlevel > 1:
2036 raise
2037 else:
2038 self._dbg(1, "tarfile: %s" % e)
2039
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002040 def extract(self, member, path=""):
2041 """Extract a member from the archive to the current working directory,
2042 using its full name. Its file information is extracted as accurately
2043 as possible. `member' may be a filename or a TarInfo object. You can
2044 specify a different directory using `path'.
2045 """
2046 self._check("r")
2047
Guido van Rossum3172c5d2007-10-16 18:12:55 +00002048 if isinstance(member, str):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002049 tarinfo = self.getmember(member)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002050 else:
2051 tarinfo = member
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002052
Neal Norwitza4f651a2004-07-20 22:07:44 +00002053 # Prepare the link target for makelink().
2054 if tarinfo.islnk():
2055 tarinfo._link_target = os.path.join(path, tarinfo.linkname)
2056
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002057 try:
2058 self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
Guido van Rossumb940e112007-01-10 16:19:56 +00002059 except EnvironmentError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002060 if self.errorlevel > 0:
2061 raise
2062 else:
2063 if e.filename is None:
2064 self._dbg(1, "tarfile: %s" % e.strerror)
2065 else:
2066 self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
Guido van Rossumb940e112007-01-10 16:19:56 +00002067 except ExtractError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002068 if self.errorlevel > 1:
2069 raise
2070 else:
2071 self._dbg(1, "tarfile: %s" % e)
2072
2073 def extractfile(self, member):
2074 """Extract a member from the archive as a file object. `member' may be
2075 a filename or a TarInfo object. If `member' is a regular file, a
2076 file-like object is returned. If `member' is a link, a file-like
2077 object is constructed from the link's target. If `member' is none of
2078 the above, None is returned.
2079 The file-like object is read-only and provides the following
2080 methods: read(), readline(), readlines(), seek() and tell()
2081 """
2082 self._check("r")
2083
Guido van Rossum3172c5d2007-10-16 18:12:55 +00002084 if isinstance(member, str):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002085 tarinfo = self.getmember(member)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002086 else:
2087 tarinfo = member
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002088
2089 if tarinfo.isreg():
2090 return self.fileobject(self, tarinfo)
2091
2092 elif tarinfo.type not in SUPPORTED_TYPES:
2093 # If a member's type is unknown, it is treated as a
2094 # regular file.
2095 return self.fileobject(self, tarinfo)
2096
2097 elif tarinfo.islnk() or tarinfo.issym():
2098 if isinstance(self.fileobj, _Stream):
2099 # A small but ugly workaround for the case that someone tries
2100 # to extract a (sym)link as a file-object from a non-seekable
2101 # stream of tar blocks.
Thomas Wouters477c8d52006-05-27 19:21:47 +00002102 raise StreamError("cannot extract (sym)link as file object")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002103 else:
Georg Brandl7eb4b7d2005-07-22 21:49:32 +00002104 # A (sym)link's file object is its target's file object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002105 return self.extractfile(self._getmember(tarinfo.linkname,
2106 tarinfo))
2107 else:
2108 # If there's no data associated with the member (directory, chrdev,
2109 # blkdev, etc.), return None instead of a file object.
2110 return None
2111
2112 def _extract_member(self, tarinfo, targetpath):
2113 """Extract the TarInfo object tarinfo to a physical
2114 file called targetpath.
2115 """
2116 # Fetch the TarInfo object for the given name
2117 # and build the destination pathname, replacing
2118 # forward slashes to platform specific separators.
2119 if targetpath[-1:] == "/":
2120 targetpath = targetpath[:-1]
2121 targetpath = os.path.normpath(targetpath)
2122
2123 # Create all upper directories.
2124 upperdirs = os.path.dirname(targetpath)
2125 if upperdirs and not os.path.exists(upperdirs):
Christian Heimes2202f872008-02-06 14:31:34 +00002126 # Create directories that are not part of the archive with
2127 # default permissions.
Thomas Woutersb2137042007-02-01 18:02:27 +00002128 os.makedirs(upperdirs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002129
2130 if tarinfo.islnk() or tarinfo.issym():
2131 self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
2132 else:
2133 self._dbg(1, tarinfo.name)
2134
2135 if tarinfo.isreg():
2136 self.makefile(tarinfo, targetpath)
2137 elif tarinfo.isdir():
2138 self.makedir(tarinfo, targetpath)
2139 elif tarinfo.isfifo():
2140 self.makefifo(tarinfo, targetpath)
2141 elif tarinfo.ischr() or tarinfo.isblk():
2142 self.makedev(tarinfo, targetpath)
2143 elif tarinfo.islnk() or tarinfo.issym():
2144 self.makelink(tarinfo, targetpath)
2145 elif tarinfo.type not in SUPPORTED_TYPES:
2146 self.makeunknown(tarinfo, targetpath)
2147 else:
2148 self.makefile(tarinfo, targetpath)
2149
2150 self.chown(tarinfo, targetpath)
2151 if not tarinfo.issym():
2152 self.chmod(tarinfo, targetpath)
2153 self.utime(tarinfo, targetpath)
2154
2155 #--------------------------------------------------------------------------
2156 # Below are the different file methods. They are called via
2157 # _extract_member() when extract() is called. They can be replaced in a
2158 # subclass to implement other functionality.
2159
2160 def makedir(self, tarinfo, targetpath):
2161 """Make a directory called targetpath.
2162 """
2163 try:
Christian Heimes2202f872008-02-06 14:31:34 +00002164 # Use a safe mode for the directory, the real mode is set
2165 # later in _extract_member().
2166 os.mkdir(targetpath, 0o700)
Guido van Rossumb940e112007-01-10 16:19:56 +00002167 except EnvironmentError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002168 if e.errno != errno.EEXIST:
2169 raise
2170
2171 def makefile(self, tarinfo, targetpath):
2172 """Make a file called targetpath.
2173 """
2174 source = self.extractfile(tarinfo)
Guido van Rossume7ba4952007-06-06 23:52:48 +00002175 target = bltn_open(targetpath, "wb")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002176 copyfileobj(source, target)
2177 source.close()
2178 target.close()
2179
2180 def makeunknown(self, tarinfo, targetpath):
2181 """Make a file from a TarInfo object with an unknown type
2182 at targetpath.
2183 """
2184 self.makefile(tarinfo, targetpath)
2185 self._dbg(1, "tarfile: Unknown file type %r, " \
2186 "extracted as regular file." % tarinfo.type)
2187
2188 def makefifo(self, tarinfo, targetpath):
2189 """Make a fifo called targetpath.
2190 """
2191 if hasattr(os, "mkfifo"):
2192 os.mkfifo(targetpath)
2193 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002194 raise ExtractError("fifo not supported by system")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002195
2196 def makedev(self, tarinfo, targetpath):
2197 """Make a character or block device called targetpath.
2198 """
2199 if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
Thomas Wouters477c8d52006-05-27 19:21:47 +00002200 raise ExtractError("special devices not supported by system")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002201
2202 mode = tarinfo.mode
2203 if tarinfo.isblk():
2204 mode |= stat.S_IFBLK
2205 else:
2206 mode |= stat.S_IFCHR
2207
2208 os.mknod(targetpath, mode,
2209 os.makedev(tarinfo.devmajor, tarinfo.devminor))
2210
2211 def makelink(self, tarinfo, targetpath):
2212 """Make a (symbolic) link called targetpath. If it cannot be created
2213 (platform limitation), we try to make a copy of the referenced file
2214 instead of a link.
2215 """
2216 linkpath = tarinfo.linkname
2217 try:
2218 if tarinfo.issym():
2219 os.symlink(linkpath, targetpath)
2220 else:
Neal Norwitza4f651a2004-07-20 22:07:44 +00002221 # See extract().
2222 os.link(tarinfo._link_target, targetpath)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002223 except AttributeError:
2224 if tarinfo.issym():
2225 linkpath = os.path.join(os.path.dirname(tarinfo.name),
2226 linkpath)
2227 linkpath = normpath(linkpath)
2228
2229 try:
2230 self._extract_member(self.getmember(linkpath), targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002231 except (EnvironmentError, KeyError) as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002232 linkpath = os.path.normpath(linkpath)
2233 try:
2234 shutil.copy2(linkpath, targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002235 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002236 raise IOError("link could not be created")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002237
2238 def chown(self, tarinfo, targetpath):
2239 """Set owner of targetpath according to tarinfo.
2240 """
2241 if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
2242 # We have to be root to do so.
2243 try:
2244 g = grp.getgrnam(tarinfo.gname)[2]
2245 except KeyError:
2246 try:
2247 g = grp.getgrgid(tarinfo.gid)[2]
2248 except KeyError:
2249 g = os.getgid()
2250 try:
2251 u = pwd.getpwnam(tarinfo.uname)[2]
2252 except KeyError:
2253 try:
2254 u = pwd.getpwuid(tarinfo.uid)[2]
2255 except KeyError:
2256 u = os.getuid()
2257 try:
2258 if tarinfo.issym() and hasattr(os, "lchown"):
2259 os.lchown(targetpath, u, g)
2260 else:
Andrew MacIntyre7970d202003-02-19 12:51:34 +00002261 if sys.platform != "os2emx":
2262 os.chown(targetpath, u, g)
Guido van Rossumb940e112007-01-10 16:19:56 +00002263 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002264 raise ExtractError("could not change owner")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002265
2266 def chmod(self, tarinfo, targetpath):
2267 """Set file permissions of targetpath according to tarinfo.
2268 """
Jack Jansen834eff62003-03-07 12:47:06 +00002269 if hasattr(os, 'chmod'):
2270 try:
2271 os.chmod(targetpath, tarinfo.mode)
Guido van Rossumb940e112007-01-10 16:19:56 +00002272 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002273 raise ExtractError("could not change mode")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002274
2275 def utime(self, tarinfo, targetpath):
2276 """Set modification time of targetpath according to tarinfo.
2277 """
Jack Jansen834eff62003-03-07 12:47:06 +00002278 if not hasattr(os, 'utime'):
Tim Petersf9347782003-03-07 15:36:41 +00002279 return
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002280 if sys.platform == "win32" and tarinfo.isdir():
2281 # According to msdn.microsoft.com, it is an error (EACCES)
2282 # to use utime() on directories.
2283 return
2284 try:
2285 os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
Guido van Rossumb940e112007-01-10 16:19:56 +00002286 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002287 raise ExtractError("could not change modification time")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002288
2289 #--------------------------------------------------------------------------
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002290 def next(self):
2291 """Return the next member of the archive as a TarInfo object, when
2292 TarFile is opened for reading. Return None if there is no more
2293 available.
2294 """
2295 self._check("ra")
2296 if self.firstmember is not None:
2297 m = self.firstmember
2298 self.firstmember = None
2299 return m
2300
2301 # Read the next block.
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002302 self.fileobj.seek(self.offset)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002303 while True:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002304 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002305 tarinfo = self.tarinfo.fromtarfile(self)
2306 if tarinfo is None:
2307 return
2308 self.members.append(tarinfo)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002309
Guido van Rossumb940e112007-01-10 16:19:56 +00002310 except HeaderError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002311 if self.ignore_zeros:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00002312 self._dbg(2, "0x%X: %s" % (self.offset, e))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002313 self.offset += BLOCKSIZE
2314 continue
2315 else:
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002316 if self.offset == 0:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00002317 raise ReadError(str(e))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002318 return None
2319 break
2320
Thomas Wouters477c8d52006-05-27 19:21:47 +00002321 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002322
2323 #--------------------------------------------------------------------------
2324 # Little helper methods:
2325
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002326 def _getmember(self, name, tarinfo=None):
2327 """Find an archive member by name from bottom to top.
2328 If tarinfo is given, it is used as the starting point.
2329 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002330 # Ensure that all members have been loaded.
2331 members = self.getmembers()
2332
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002333 if tarinfo is None:
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002334 end = len(members)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002335 else:
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002336 end = members.index(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002337
Guido van Rossum805365e2007-05-07 22:24:25 +00002338 for i in range(end - 1, -1, -1):
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002339 if name == members[i].name:
2340 return members[i]
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002341
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002342 def _load(self):
2343 """Read through the entire archive file and look for readable
2344 members.
2345 """
2346 while True:
2347 tarinfo = self.next()
2348 if tarinfo is None:
2349 break
2350 self._loaded = True
2351
2352 def _check(self, mode=None):
2353 """Check if TarFile is still open, and if the operation's mode
2354 corresponds to TarFile's mode.
2355 """
2356 if self.closed:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002357 raise IOError("%s is closed" % self.__class__.__name__)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002358 if mode is not None and self.mode not in mode:
2359 raise IOError("bad operation for mode %r" % self.mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002360
2361 def __iter__(self):
2362 """Provide an iterator object.
2363 """
2364 if self._loaded:
2365 return iter(self.members)
2366 else:
2367 return TarIter(self)
2368
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002369 def _dbg(self, level, msg):
2370 """Write debugging output to sys.stderr.
2371 """
2372 if level <= self.debug:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002373 print(msg, file=sys.stderr)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002374# class TarFile
2375
2376class TarIter:
2377 """Iterator Class.
2378
2379 for tarinfo in TarFile(...):
2380 suite...
2381 """
2382
2383 def __init__(self, tarfile):
2384 """Construct a TarIter object.
2385 """
2386 self.tarfile = tarfile
Martin v. Löwis637431b2005-03-03 23:12:42 +00002387 self.index = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002388 def __iter__(self):
2389 """Return iterator object.
2390 """
2391 return self
Georg Brandla18af4e2007-04-21 15:47:16 +00002392 def __next__(self):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002393 """Return the next item using TarFile's next() method.
2394 When all members have been read, set TarFile as _loaded.
2395 """
Martin v. Löwis637431b2005-03-03 23:12:42 +00002396 # Fix for SF #1100429: Under rare circumstances it can
2397 # happen that getmembers() is called during iteration,
2398 # which will cause TarIter to stop prematurely.
2399 if not self.tarfile._loaded:
2400 tarinfo = self.tarfile.next()
2401 if not tarinfo:
2402 self.tarfile._loaded = True
2403 raise StopIteration
2404 else:
2405 try:
2406 tarinfo = self.tarfile.members[self.index]
2407 except IndexError:
2408 raise StopIteration
2409 self.index += 1
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002410 return tarinfo
2411
2412# Helper classes for sparse file support
2413class _section:
2414 """Base class for _data and _hole.
2415 """
2416 def __init__(self, offset, size):
2417 self.offset = offset
2418 self.size = size
2419 def __contains__(self, offset):
2420 return self.offset <= offset < self.offset + self.size
2421
2422class _data(_section):
2423 """Represent a data section in a sparse file.
2424 """
2425 def __init__(self, offset, size, realpos):
2426 _section.__init__(self, offset, size)
2427 self.realpos = realpos
2428
2429class _hole(_section):
2430 """Represent a hole section in a sparse file.
2431 """
2432 pass
2433
2434class _ringbuffer(list):
2435 """Ringbuffer class which increases performance
2436 over a regular list.
2437 """
2438 def __init__(self):
2439 self.idx = 0
2440 def find(self, offset):
2441 idx = self.idx
2442 while True:
2443 item = self[idx]
2444 if offset in item:
2445 break
2446 idx += 1
2447 if idx == len(self):
2448 idx = 0
2449 if idx == self.idx:
2450 # End of File
2451 return None
2452 self.idx = idx
2453 return item
2454
2455#---------------------------------------------
2456# zipfile compatible TarFile class
2457#---------------------------------------------
2458TAR_PLAIN = 0 # zipfile.ZIP_STORED
2459TAR_GZIPPED = 8 # zipfile.ZIP_DEFLATED
2460class TarFileCompat:
2461 """TarFile class compatible with standard module zipfile's
2462 ZipFile class.
2463 """
2464 def __init__(self, file, mode="r", compression=TAR_PLAIN):
2465 if compression == TAR_PLAIN:
2466 self.tarfile = TarFile.taropen(file, mode)
2467 elif compression == TAR_GZIPPED:
2468 self.tarfile = TarFile.gzopen(file, mode)
2469 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002470 raise ValueError("unknown compression constant")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002471 if mode[0:1] == "r":
2472 members = self.tarfile.getmembers()
Raymond Hettingera1d09e22005-09-11 16:34:05 +00002473 for m in members:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002474 m.filename = m.name
2475 m.file_size = m.size
2476 m.date_time = time.gmtime(m.mtime)[:6]
2477 def namelist(self):
2478 return map(lambda m: m.name, self.infolist())
2479 def infolist(self):
2480 return filter(lambda m: m.type in REGULAR_TYPES,
2481 self.tarfile.getmembers())
2482 def printdir(self):
2483 self.tarfile.list()
2484 def testzip(self):
2485 return
2486 def getinfo(self, name):
2487 return self.tarfile.getmember(name)
2488 def read(self, name):
2489 return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
2490 def write(self, filename, arcname=None, compress_type=None):
2491 self.tarfile.add(filename, arcname)
2492 def writestr(self, zinfo, bytes):
Guido van Rossum68937b42007-05-18 00:51:22 +00002493 from io import StringIO
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002494 import calendar
2495 zinfo.name = zinfo.filename
2496 zinfo.size = zinfo.file_size
2497 zinfo.mtime = calendar.timegm(zinfo.date_time)
Raymond Hettingera6172712004-12-31 19:15:26 +00002498 self.tarfile.addfile(zinfo, StringIO(bytes))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002499 def close(self):
2500 self.tarfile.close()
2501#class TarFileCompat
2502
2503#--------------------
2504# exported functions
2505#--------------------
2506def is_tarfile(name):
2507 """Return True if name points to a tar archive that we
2508 are able to handle, else return False.
2509 """
2510 try:
2511 t = open(name)
2512 t.close()
2513 return True
2514 except TarError:
2515 return False
2516
Guido van Rossume7ba4952007-06-06 23:52:48 +00002517bltn_open = open
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002518open = TarFile.open