blob: b789ccad8e4393d847164d1524f6629fc9a06df3 [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,
770 getattr(tarinfo, "sparse", None))
771 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
909 def __init__(self, name=""):
910 """Construct a TarInfo object. name is the optional name
911 of the member.
912 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000913 self.name = name # member name
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000914 self.mode = 0o644 # file permissions
Thomas Wouters477c8d52006-05-27 19:21:47 +0000915 self.uid = 0 # user id
916 self.gid = 0 # group id
917 self.size = 0 # file size
918 self.mtime = 0 # modification time
919 self.chksum = 0 # header checksum
920 self.type = REGTYPE # member type
921 self.linkname = "" # link name
Guido van Rossumd8faa362007-04-27 19:54:29 +0000922 self.uname = "root" # user name
923 self.gname = "root" # group name
Thomas Wouters477c8d52006-05-27 19:21:47 +0000924 self.devmajor = 0 # device major number
925 self.devminor = 0 # device minor number
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000926
Thomas Wouters477c8d52006-05-27 19:21:47 +0000927 self.offset = 0 # the tar header starts here
928 self.offset_data = 0 # the file's data starts here
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000929
Guido van Rossumd8faa362007-04-27 19:54:29 +0000930 self.pax_headers = {} # pax header information
931
932 # In pax headers the "name" and "linkname" field are called
933 # "path" and "linkpath".
934 def _getpath(self):
935 return self.name
936 def _setpath(self, name):
937 self.name = name
938 path = property(_getpath, _setpath)
939
940 def _getlinkpath(self):
941 return self.linkname
942 def _setlinkpath(self, linkname):
943 self.linkname = linkname
944 linkpath = property(_getlinkpath, _setlinkpath)
945
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000946 def __repr__(self):
947 return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self))
948
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000949 def get_info(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000950 """Return the TarInfo's attributes as a dictionary.
951 """
952 info = {
953 "name": normpath(self.name),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000954 "mode": self.mode & 0o7777,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000955 "uid": self.uid,
956 "gid": self.gid,
957 "size": self.size,
958 "mtime": self.mtime,
959 "chksum": self.chksum,
960 "type": self.type,
961 "linkname": normpath(self.linkname) if self.linkname else "",
962 "uname": self.uname,
963 "gname": self.gname,
964 "devmajor": self.devmajor,
965 "devminor": self.devminor
966 }
967
968 if info["type"] == DIRTYPE and not info["name"].endswith("/"):
969 info["name"] += "/"
970
971 return info
972
Guido van Rossume7ba4952007-06-06 23:52:48 +0000973 def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="strict"):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000974 """Return a tar header as a string of 512 byte blocks.
975 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000976 info = self.get_info()
Guido van Rossume7ba4952007-06-06 23:52:48 +0000977
Guido van Rossumd8faa362007-04-27 19:54:29 +0000978 if format == USTAR_FORMAT:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000979 return self.create_ustar_header(info, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000980 elif format == GNU_FORMAT:
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000981 return self.create_gnu_header(info, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000982 elif format == PAX_FORMAT:
Lars Gustäbel3741eff2007-08-21 12:17:05 +0000983 return self.create_pax_header(info)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000984 else:
985 raise ValueError("invalid format")
986
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000987 def create_ustar_header(self, info, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000988 """Return the object as a ustar header block.
989 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000990 info["magic"] = POSIX_MAGIC
991
992 if len(info["linkname"]) > LENGTH_LINK:
993 raise ValueError("linkname is too long")
994
995 if len(info["name"]) > LENGTH_NAME:
996 info["prefix"], info["name"] = self._posix_split_name(info["name"])
997
Lars Gustäbelb506dc32007-08-07 18:36:16 +0000998 return self._create_header(info, USTAR_FORMAT, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000999
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001000 def create_gnu_header(self, info, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001001 """Return the object as a GNU header block sequence.
1002 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001003 info["magic"] = GNU_MAGIC
1004
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001005 buf = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001006 if len(info["linkname"]) > LENGTH_LINK:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001007 buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001008
1009 if len(info["name"]) > LENGTH_NAME:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001010 buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001011
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001012 return buf + self._create_header(info, GNU_FORMAT, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001013
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001014 def create_pax_header(self, info):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001015 """Return the object as a ustar header block. If it cannot be
1016 represented this way, prepend a pax extended header sequence
1017 with supplement information.
1018 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001019 info["magic"] = POSIX_MAGIC
1020 pax_headers = self.pax_headers.copy()
1021
1022 # Test string fields for values that exceed the field length or cannot
1023 # be represented in ASCII encoding.
1024 for name, hname, length in (
1025 ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK),
1026 ("uname", "uname", 32), ("gname", "gname", 32)):
1027
Guido van Rossume7ba4952007-06-06 23:52:48 +00001028 if hname in pax_headers:
1029 # The pax header has priority.
1030 continue
1031
Guido van Rossumd8faa362007-04-27 19:54:29 +00001032 # Try to encode the string as ASCII.
1033 try:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001034 info[name].encode("ascii", "strict")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001035 except UnicodeEncodeError:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001036 pax_headers[hname] = info[name]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001037 continue
1038
Guido van Rossume7ba4952007-06-06 23:52:48 +00001039 if len(info[name]) > length:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001040 pax_headers[hname] = info[name]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001041
1042 # Test number fields for values that exceed the field limit or values
1043 # that like to be stored as float.
1044 for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)):
Guido van Rossume7ba4952007-06-06 23:52:48 +00001045 if name in pax_headers:
1046 # The pax header has priority. Avoid overflow.
1047 info[name] = 0
1048 continue
1049
Guido van Rossumd8faa362007-04-27 19:54:29 +00001050 val = info[name]
1051 if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float):
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001052 pax_headers[name] = str(val)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001053 info[name] = 0
1054
Guido van Rossume7ba4952007-06-06 23:52:48 +00001055 # Create a pax extended header if necessary.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001056 if pax_headers:
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001057 buf = self._create_pax_generic_header(pax_headers, XHDTYPE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001058 else:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001059 buf = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001060
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001061 return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001062
1063 @classmethod
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001064 def create_pax_global_header(cls, pax_headers):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001065 """Return the object as a pax global header block sequence.
1066 """
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001067 return cls._create_pax_generic_header(pax_headers, XGLTYPE)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001068
1069 def _posix_split_name(self, name):
1070 """Split a name longer than 100 chars into a prefix
1071 and a name part.
1072 """
1073 prefix = name[:LENGTH_PREFIX + 1]
1074 while prefix and prefix[-1] != "/":
1075 prefix = prefix[:-1]
1076
1077 name = name[len(prefix):]
1078 prefix = prefix[:-1]
1079
1080 if not prefix or len(name) > LENGTH_NAME:
1081 raise ValueError("name is too long")
1082 return prefix, name
1083
1084 @staticmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001085 def _create_header(info, format, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001086 """Return a header block. info is a dictionary with file
1087 information, format must be one of the *_FORMAT constants.
1088 """
1089 parts = [
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001090 stn(info.get("name", ""), 100, encoding, errors),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001091 itn(info.get("mode", 0) & 0o7777, 8, format),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001092 itn(info.get("uid", 0), 8, format),
1093 itn(info.get("gid", 0), 8, format),
1094 itn(info.get("size", 0), 12, format),
1095 itn(info.get("mtime", 0), 12, format),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001096 b" ", # checksum field
Guido van Rossumd8faa362007-04-27 19:54:29 +00001097 info.get("type", REGTYPE),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001098 stn(info.get("linkname", ""), 100, encoding, errors),
1099 info.get("magic", POSIX_MAGIC),
1100 stn(info.get("uname", "root"), 32, encoding, errors),
1101 stn(info.get("gname", "root"), 32, encoding, errors),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001102 itn(info.get("devmajor", 0), 8, format),
1103 itn(info.get("devminor", 0), 8, format),
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001104 stn(info.get("prefix", ""), 155, encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001105 ]
1106
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001107 buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts))
Guido van Rossumd8faa362007-04-27 19:54:29 +00001108 chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
Lars Gustäbela280ca752007-08-28 07:34:33 +00001109 buf = buf[:-364] + bytes("%06o\0" % chksum, "ascii") + buf[-357:]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001110 return buf
1111
1112 @staticmethod
1113 def _create_payload(payload):
1114 """Return the string payload filled with zero bytes
1115 up to the next 512 byte border.
1116 """
1117 blocks, remainder = divmod(len(payload), BLOCKSIZE)
1118 if remainder > 0:
1119 payload += (BLOCKSIZE - remainder) * NUL
1120 return payload
1121
1122 @classmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001123 def _create_gnu_long_header(cls, name, type, encoding, errors):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001124 """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence
1125 for name.
1126 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001127 name = name.encode(encoding, errors) + NUL
Guido van Rossumd8faa362007-04-27 19:54:29 +00001128
1129 info = {}
1130 info["name"] = "././@LongLink"
1131 info["type"] = type
1132 info["size"] = len(name)
1133 info["magic"] = GNU_MAGIC
1134
1135 # create extended header + name blocks.
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001136 return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \
Guido van Rossumd8faa362007-04-27 19:54:29 +00001137 cls._create_payload(name)
1138
1139 @classmethod
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001140 def _create_pax_generic_header(cls, pax_headers, type):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001141 """Return a POSIX.1-2001 extended or global header sequence
1142 that contains a list of keyword, value pairs. The values
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001143 must be strings.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001144 """
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001145 records = b""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001146 for keyword, value in pax_headers.items():
1147 keyword = keyword.encode("utf8")
1148 value = value.encode("utf8")
1149 l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n'
1150 n = p = 0
1151 while True:
1152 n = l + len(str(p))
1153 if n == p:
1154 break
1155 p = n
Lars Gustäbela280ca752007-08-28 07:34:33 +00001156 records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n"
Guido van Rossumd8faa362007-04-27 19:54:29 +00001157
1158 # We use a hardcoded "././@PaxHeader" name like star does
1159 # instead of the one that POSIX recommends.
1160 info = {}
1161 info["name"] = "././@PaxHeader"
1162 info["type"] = type
1163 info["size"] = len(records)
1164 info["magic"] = POSIX_MAGIC
1165
1166 # Create pax header + record blocks.
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001167 return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \
Guido van Rossumd8faa362007-04-27 19:54:29 +00001168 cls._create_payload(records)
1169
Guido van Rossum75b64e62005-01-16 00:16:11 +00001170 @classmethod
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001171 def frombuf(cls, buf, encoding, errors):
1172 """Construct a TarInfo object from a 512 byte bytes object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001173 """
Thomas Wouters477c8d52006-05-27 19:21:47 +00001174 if len(buf) != BLOCKSIZE:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001175 raise HeaderError("truncated header")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001176 if buf.count(NUL) == BLOCKSIZE:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001177 raise HeaderError("empty header")
1178
1179 chksum = nti(buf[148:156])
1180 if chksum not in calc_chksums(buf):
1181 raise HeaderError("bad checksum")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001182
Guido van Rossumd8faa362007-04-27 19:54:29 +00001183 obj = cls()
1184 obj.buf = buf
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001185 obj.name = nts(buf[0:100], encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001186 obj.mode = nti(buf[100:108])
1187 obj.uid = nti(buf[108:116])
1188 obj.gid = nti(buf[116:124])
1189 obj.size = nti(buf[124:136])
1190 obj.mtime = nti(buf[136:148])
1191 obj.chksum = chksum
1192 obj.type = buf[156:157]
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001193 obj.linkname = nts(buf[157:257], encoding, errors)
1194 obj.uname = nts(buf[265:297], encoding, errors)
1195 obj.gname = nts(buf[297:329], encoding, errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001196 obj.devmajor = nti(buf[329:337])
1197 obj.devminor = nti(buf[337:345])
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001198 prefix = nts(buf[345:500], encoding, errors)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001199
Guido van Rossumd8faa362007-04-27 19:54:29 +00001200 # Old V7 tar format represents a directory as a regular
1201 # file with a trailing slash.
1202 if obj.type == AREGTYPE and obj.name.endswith("/"):
1203 obj.type = DIRTYPE
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001204
Guido van Rossumd8faa362007-04-27 19:54:29 +00001205 # Remove redundant slashes from directories.
1206 if obj.isdir():
1207 obj.name = obj.name.rstrip("/")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001208
Guido van Rossumd8faa362007-04-27 19:54:29 +00001209 # Reconstruct a ustar longname.
1210 if prefix and obj.type not in GNU_TYPES:
1211 obj.name = prefix + "/" + obj.name
1212 return obj
1213
1214 @classmethod
1215 def fromtarfile(cls, tarfile):
1216 """Return the next TarInfo object from TarFile object
1217 tarfile.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001218 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001219 buf = tarfile.fileobj.read(BLOCKSIZE)
1220 if not buf:
1221 return
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001222 obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001223 obj.offset = tarfile.fileobj.tell() - BLOCKSIZE
1224 return obj._proc_member(tarfile)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001225
Guido van Rossumd8faa362007-04-27 19:54:29 +00001226 #--------------------------------------------------------------------------
1227 # The following are methods that are called depending on the type of a
1228 # member. The entry point is _proc_member() which can be overridden in a
1229 # subclass to add custom _proc_*() methods. A _proc_*() method MUST
1230 # implement the following
1231 # operations:
1232 # 1. Set self.offset_data to the position where the data blocks begin,
1233 # if there is data that follows.
1234 # 2. Set tarfile.offset to the position where the next member's header will
1235 # begin.
1236 # 3. Return self or another valid TarInfo object.
1237 def _proc_member(self, tarfile):
1238 """Choose the right processing method depending on
1239 the type and call it.
Thomas Wouters89f507f2006-12-13 04:49:30 +00001240 """
Guido van Rossumd8faa362007-04-27 19:54:29 +00001241 if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
1242 return self._proc_gnulong(tarfile)
1243 elif self.type == GNUTYPE_SPARSE:
1244 return self._proc_sparse(tarfile)
1245 elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE):
1246 return self._proc_pax(tarfile)
1247 else:
1248 return self._proc_builtin(tarfile)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001249
Guido van Rossumd8faa362007-04-27 19:54:29 +00001250 def _proc_builtin(self, tarfile):
1251 """Process a builtin type or an unknown type which
1252 will be treated as a regular file.
1253 """
1254 self.offset_data = tarfile.fileobj.tell()
1255 offset = self.offset_data
1256 if self.isreg() or self.type not in SUPPORTED_TYPES:
1257 # Skip the following data blocks.
1258 offset += self._block(self.size)
1259 tarfile.offset = offset
Thomas Wouters89f507f2006-12-13 04:49:30 +00001260
Guido van Rossume7ba4952007-06-06 23:52:48 +00001261 # Patch the TarInfo object with saved global
Guido van Rossumd8faa362007-04-27 19:54:29 +00001262 # header information.
Guido van Rossume7ba4952007-06-06 23:52:48 +00001263 self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001264
1265 return self
1266
1267 def _proc_gnulong(self, tarfile):
1268 """Process the blocks that hold a GNU longname
1269 or longlink member.
1270 """
1271 buf = tarfile.fileobj.read(self._block(self.size))
1272
1273 # Fetch the next header and process it.
Guido van Rossume7ba4952007-06-06 23:52:48 +00001274 next = self.fromtarfile(tarfile)
1275 if next is None:
1276 raise HeaderError("missing subsequent header")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001277
1278 # Patch the TarInfo object from the next header with
1279 # the longname information.
1280 next.offset = self.offset
1281 if self.type == GNUTYPE_LONGNAME:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001282 next.name = nts(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001283 elif self.type == GNUTYPE_LONGLINK:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001284 next.linkname = nts(buf, tarfile.encoding, tarfile.errors)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001285
1286 return next
1287
1288 def _proc_sparse(self, tarfile):
1289 """Process a GNU sparse header plus extra headers.
1290 """
1291 buf = self.buf
1292 sp = _ringbuffer()
1293 pos = 386
1294 lastpos = 0
1295 realpos = 0
1296 # There are 4 possible sparse structs in the
1297 # first header.
Guido van Rossum805365e2007-05-07 22:24:25 +00001298 for i in range(4):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001299 try:
1300 offset = nti(buf[pos:pos + 12])
1301 numbytes = nti(buf[pos + 12:pos + 24])
1302 except ValueError:
1303 break
1304 if offset > lastpos:
1305 sp.append(_hole(lastpos, offset - lastpos))
1306 sp.append(_data(offset, numbytes, realpos))
1307 realpos += numbytes
1308 lastpos = offset + numbytes
1309 pos += 24
1310
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001311 isextended = bool(buf[482])
Guido van Rossumd8faa362007-04-27 19:54:29 +00001312 origsize = nti(buf[483:495])
1313
1314 # If the isextended flag is given,
1315 # there are extra headers to process.
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001316 while isextended:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001317 buf = tarfile.fileobj.read(BLOCKSIZE)
1318 pos = 0
Guido van Rossum805365e2007-05-07 22:24:25 +00001319 for i in range(21):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001320 try:
1321 offset = nti(buf[pos:pos + 12])
1322 numbytes = nti(buf[pos + 12:pos + 24])
1323 except ValueError:
1324 break
1325 if offset > lastpos:
1326 sp.append(_hole(lastpos, offset - lastpos))
1327 sp.append(_data(offset, numbytes, realpos))
1328 realpos += numbytes
1329 lastpos = offset + numbytes
1330 pos += 24
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001331 isextended = bool(buf[504])
Guido van Rossumd8faa362007-04-27 19:54:29 +00001332
1333 if lastpos < origsize:
1334 sp.append(_hole(lastpos, origsize - lastpos))
1335
1336 self.sparse = sp
1337
1338 self.offset_data = tarfile.fileobj.tell()
1339 tarfile.offset = self.offset_data + self._block(self.size)
1340 self.size = origsize
1341
1342 return self
1343
1344 def _proc_pax(self, tarfile):
1345 """Process an extended or global header as described in
1346 POSIX.1-2001.
1347 """
1348 # Read the header information.
1349 buf = tarfile.fileobj.read(self._block(self.size))
1350
1351 # A pax header stores supplemental information for either
1352 # the following file (extended) or all following files
1353 # (global).
1354 if self.type == XGLTYPE:
1355 pax_headers = tarfile.pax_headers
1356 else:
1357 pax_headers = tarfile.pax_headers.copy()
1358
Guido van Rossumd8faa362007-04-27 19:54:29 +00001359 # Parse pax header information. A record looks like that:
1360 # "%d %s=%s\n" % (length, keyword, value). length is the size
1361 # of the complete record including the length field itself and
Guido van Rossume7ba4952007-06-06 23:52:48 +00001362 # the newline. keyword and value are both UTF-8 encoded strings.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001363 regex = re.compile(r"(\d+) ([^=]+)=", re.U)
1364 pos = 0
1365 while True:
1366 match = regex.match(buf, pos)
1367 if not match:
1368 break
1369
1370 length, keyword = match.groups()
1371 length = int(length)
1372 value = buf[match.end(2) + 1:match.start(1) + length - 1]
1373
1374 keyword = keyword.decode("utf8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001375 value = value.decode("utf8")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001376
1377 pax_headers[keyword] = value
1378 pos += length
1379
Guido van Rossume7ba4952007-06-06 23:52:48 +00001380 # Fetch the next header.
1381 next = self.fromtarfile(tarfile)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001382
Guido van Rossume7ba4952007-06-06 23:52:48 +00001383 if self.type in (XHDTYPE, SOLARIS_XHDTYPE):
1384 if next is None:
1385 raise HeaderError("missing subsequent header")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001386
Guido van Rossume7ba4952007-06-06 23:52:48 +00001387 # Patch the TarInfo object with the extended header info.
1388 next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors)
1389 next.offset = self.offset
1390
1391 if "size" in pax_headers:
1392 # If the extended header replaces the size field,
1393 # we need to recalculate the offset where the next
1394 # header starts.
1395 offset = next.offset_data
1396 if next.isreg() or next.type not in SUPPORTED_TYPES:
1397 offset += next._block(next.size)
1398 tarfile.offset = offset
1399
1400 return next
1401
1402 def _apply_pax_info(self, pax_headers, encoding, errors):
1403 """Replace fields with supplemental information from a previous
1404 pax extended or global header.
1405 """
1406 for keyword, value in pax_headers.items():
1407 if keyword not in PAX_FIELDS:
1408 continue
1409
1410 if keyword == "path":
1411 value = value.rstrip("/")
1412
1413 if keyword in PAX_NUMBER_FIELDS:
1414 try:
1415 value = PAX_NUMBER_FIELDS[keyword](value)
1416 except ValueError:
1417 value = 0
Guido van Rossume7ba4952007-06-06 23:52:48 +00001418
1419 setattr(self, keyword, value)
1420
1421 self.pax_headers = pax_headers.copy()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001422
1423 def _block(self, count):
1424 """Round up a byte count by BLOCKSIZE and return it,
1425 e.g. _block(834) => 1024.
1426 """
1427 blocks, remainder = divmod(count, BLOCKSIZE)
1428 if remainder:
1429 blocks += 1
1430 return blocks * BLOCKSIZE
Thomas Wouters89f507f2006-12-13 04:49:30 +00001431
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001432 def isreg(self):
1433 return self.type in REGULAR_TYPES
1434 def isfile(self):
1435 return self.isreg()
1436 def isdir(self):
1437 return self.type == DIRTYPE
1438 def issym(self):
1439 return self.type == SYMTYPE
1440 def islnk(self):
1441 return self.type == LNKTYPE
1442 def ischr(self):
1443 return self.type == CHRTYPE
1444 def isblk(self):
1445 return self.type == BLKTYPE
1446 def isfifo(self):
1447 return self.type == FIFOTYPE
1448 def issparse(self):
1449 return self.type == GNUTYPE_SPARSE
1450 def isdev(self):
1451 return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
1452# class TarInfo
1453
1454class TarFile(object):
1455 """The TarFile Class provides an interface to tar archives.
1456 """
1457
1458 debug = 0 # May be set from 0 (no msgs) to 3 (all msgs)
1459
1460 dereference = False # If true, add content of linked file to the
1461 # tar file, else the link.
1462
1463 ignore_zeros = False # If true, skips empty or invalid blocks and
1464 # continues processing.
1465
1466 errorlevel = 0 # If 0, fatal errors only appear in debug
1467 # messages (if debug >= 0). If > 0, errors
1468 # are passed to the caller as exceptions.
1469
Guido van Rossumd8faa362007-04-27 19:54:29 +00001470 format = DEFAULT_FORMAT # The format to use when creating an archive.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001471
Guido van Rossume7ba4952007-06-06 23:52:48 +00001472 encoding = ENCODING # Encoding for 8-bit character strings.
1473
1474 errors = None # Error handler for unicode conversion.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001475
Guido van Rossumd8faa362007-04-27 19:54:29 +00001476 tarinfo = TarInfo # The default TarInfo class to use.
1477
1478 fileobject = ExFileObject # The default ExFileObject class to use.
1479
1480 def __init__(self, name=None, mode="r", fileobj=None, format=None,
1481 tarinfo=None, dereference=None, ignore_zeros=None, encoding=None,
Guido van Rossume7ba4952007-06-06 23:52:48 +00001482 errors=None, pax_headers=None, debug=None, errorlevel=None):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001483 """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
1484 read from an existing archive, 'a' to append data to an existing
1485 file or 'w' to create a new file overwriting an existing one. `mode'
1486 defaults to 'r'.
1487 If `fileobj' is given, it is used for reading or writing data. If it
1488 can be determined, `mode' is overridden by `fileobj's mode.
1489 `fileobj' is not closed, when TarFile is closed.
1490 """
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001491 if len(mode) > 1 or mode not in "raw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001492 raise ValueError("mode must be 'r', 'a' or 'w'")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001493 self.mode = mode
1494 self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001495
1496 if not fileobj:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001497 if self.mode == "a" and not os.path.exists(name):
Thomas Wouterscf297e42007-02-23 15:07:44 +00001498 # Create nonexistent files in append mode.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001499 self.mode = "w"
1500 self._mode = "wb"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001501 fileobj = bltn_open(name, self._mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001502 self._extfileobj = False
1503 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001504 if name is None and hasattr(fileobj, "name"):
1505 name = fileobj.name
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001506 if hasattr(fileobj, "mode"):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001507 self._mode = fileobj.mode
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001508 self._extfileobj = True
Thomas Woutersed03b412007-08-28 21:37:11 +00001509 self.name = os.path.abspath(name) if name else None
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001510 self.fileobj = fileobj
1511
Guido van Rossumd8faa362007-04-27 19:54:29 +00001512 # Init attributes.
1513 if format is not None:
1514 self.format = format
1515 if tarinfo is not None:
1516 self.tarinfo = tarinfo
1517 if dereference is not None:
1518 self.dereference = dereference
1519 if ignore_zeros is not None:
1520 self.ignore_zeros = ignore_zeros
1521 if encoding is not None:
1522 self.encoding = encoding
Guido van Rossume7ba4952007-06-06 23:52:48 +00001523
1524 if errors is not None:
1525 self.errors = errors
1526 elif mode == "r":
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001527 self.errors = "replace"
Guido van Rossume7ba4952007-06-06 23:52:48 +00001528 else:
1529 self.errors = "strict"
1530
1531 if pax_headers is not None and self.format == PAX_FORMAT:
1532 self.pax_headers = pax_headers
1533 else:
1534 self.pax_headers = {}
1535
Guido van Rossumd8faa362007-04-27 19:54:29 +00001536 if debug is not None:
1537 self.debug = debug
1538 if errorlevel is not None:
1539 self.errorlevel = errorlevel
1540
1541 # Init datastructures.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001542 self.closed = False
1543 self.members = [] # list of members as TarInfo objects
1544 self._loaded = False # flag if all members have been read
Christian Heimesd8654cf2007-12-02 15:22:16 +00001545 self.offset = self.fileobj.tell()
1546 # current position in the archive file
Thomas Wouters477c8d52006-05-27 19:21:47 +00001547 self.inodes = {} # dictionary caching the inodes of
1548 # archive members already added
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001549
Guido van Rossumd8faa362007-04-27 19:54:29 +00001550 if self.mode == "r":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001551 self.firstmember = None
1552 self.firstmember = self.next()
1553
Guido van Rossumd8faa362007-04-27 19:54:29 +00001554 if self.mode == "a":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001555 # Move to the end of the archive,
1556 # before the first empty block.
1557 self.firstmember = None
1558 while True:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001559 if self.next() is None:
Thomas Wouterscf297e42007-02-23 15:07:44 +00001560 if self.offset > 0:
Lars Gustäbelb506dc32007-08-07 18:36:16 +00001561 self.fileobj.seek(self.fileobj.tell() - BLOCKSIZE)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001562 break
1563
Guido van Rossumd8faa362007-04-27 19:54:29 +00001564 if self.mode in "aw":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001565 self._loaded = True
1566
Guido van Rossume7ba4952007-06-06 23:52:48 +00001567 if self.pax_headers:
Lars Gustäbel3741eff2007-08-21 12:17:05 +00001568 buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy())
Guido van Rossumd8faa362007-04-27 19:54:29 +00001569 self.fileobj.write(buf)
1570 self.offset += len(buf)
1571
1572 def _getposix(self):
1573 return self.format == USTAR_FORMAT
1574 def _setposix(self, value):
1575 import warnings
1576 warnings.warn("use the format attribute instead", DeprecationWarning)
1577 if value:
1578 self.format = USTAR_FORMAT
1579 else:
1580 self.format = GNU_FORMAT
1581 posix = property(_getposix, _setposix)
1582
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001583 #--------------------------------------------------------------------------
1584 # Below are the classmethods which act as alternate constructors to the
1585 # TarFile class. The open() method is the only one that is needed for
1586 # public use; it is the "super"-constructor and is able to select an
1587 # adequate "sub"-constructor for a particular compression using the mapping
1588 # from OPEN_METH.
1589 #
1590 # This concept allows one to subclass TarFile without losing the comfort of
1591 # the super-constructor. A sub-constructor is registered and made available
1592 # by adding it to the mapping in OPEN_METH.
1593
Guido van Rossum75b64e62005-01-16 00:16:11 +00001594 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001595 def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001596 """Open a tar archive for reading, writing or appending. Return
1597 an appropriate TarFile class.
1598
1599 mode:
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001600 'r' or 'r:*' open for reading with transparent compression
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001601 'r:' open for reading exclusively uncompressed
1602 'r:gz' open for reading with gzip compression
1603 'r:bz2' open for reading with bzip2 compression
Thomas Wouterscf297e42007-02-23 15:07:44 +00001604 'a' or 'a:' open for appending, creating the file if necessary
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001605 'w' or 'w:' open for writing without compression
1606 'w:gz' open for writing with gzip compression
1607 'w:bz2' open for writing with bzip2 compression
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001608
1609 'r|*' open a stream of tar blocks with transparent compression
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001610 'r|' open an uncompressed stream of tar blocks for reading
1611 'r|gz' open a gzip compressed stream of tar blocks
1612 'r|bz2' open a bzip2 compressed stream of tar blocks
1613 'w|' open an uncompressed stream for writing
1614 'w|gz' open a gzip compressed stream for writing
1615 'w|bz2' open a bzip2 compressed stream for writing
1616 """
1617
1618 if not name and not fileobj:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001619 raise ValueError("nothing to open")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001620
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001621 if mode in ("r", "r:*"):
1622 # Find out which *open() is appropriate for opening the file.
1623 for comptype in cls.OPEN_METH:
1624 func = getattr(cls, cls.OPEN_METH[comptype])
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001625 if fileobj is not None:
1626 saved_pos = fileobj.tell()
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001627 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001628 return func(name, "r", fileobj, **kwargs)
1629 except (ReadError, CompressionError) as e:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001630 if fileobj is not None:
1631 fileobj.seek(saved_pos)
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001632 continue
Thomas Wouters477c8d52006-05-27 19:21:47 +00001633 raise ReadError("file could not be opened successfully")
Martin v. Löwis78be7df2005-03-05 12:47:42 +00001634
1635 elif ":" in mode:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001636 filemode, comptype = mode.split(":", 1)
1637 filemode = filemode or "r"
1638 comptype = comptype or "tar"
1639
1640 # Select the *open() function according to
1641 # given compression.
1642 if comptype in cls.OPEN_METH:
1643 func = getattr(cls, cls.OPEN_METH[comptype])
1644 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001645 raise CompressionError("unknown compression type %r" % comptype)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001646 return func(name, filemode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001647
1648 elif "|" in mode:
1649 filemode, comptype = mode.split("|", 1)
1650 filemode = filemode or "r"
1651 comptype = comptype or "tar"
1652
1653 if filemode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001654 raise ValueError("mode must be 'r' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001655
1656 t = cls(name, filemode,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001657 _Stream(name, filemode, comptype, fileobj, bufsize),
1658 **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001659 t._extfileobj = False
1660 return t
1661
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001662 elif mode in "aw":
Guido van Rossumd8faa362007-04-27 19:54:29 +00001663 return cls.taropen(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001664
Thomas Wouters477c8d52006-05-27 19:21:47 +00001665 raise ValueError("undiscernible mode")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001666
Guido van Rossum75b64e62005-01-16 00:16:11 +00001667 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001668 def taropen(cls, name, mode="r", fileobj=None, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001669 """Open uncompressed tar archive name for reading or writing.
1670 """
1671 if len(mode) > 1 or mode not in "raw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001672 raise ValueError("mode must be 'r', 'a' or 'w'")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001673 return cls(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001674
Guido van Rossum75b64e62005-01-16 00:16:11 +00001675 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001676 def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001677 """Open gzip compressed tar archive name for reading or writing.
1678 Appending is not allowed.
1679 """
1680 if len(mode) > 1 or mode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001681 raise ValueError("mode must be 'r' or 'w'")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001682
1683 try:
1684 import gzip
Neal Norwitz4ec68242003-04-11 03:05:56 +00001685 gzip.GzipFile
1686 except (ImportError, AttributeError):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001687 raise CompressionError("gzip module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001688
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001689 if fileobj is None:
Guido van Rossume7ba4952007-06-06 23:52:48 +00001690 fileobj = bltn_open(name, mode + "b")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001691
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001692 try:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001693 t = cls.taropen(name, mode,
Guido van Rossumd8faa362007-04-27 19:54:29 +00001694 gzip.GzipFile(name, mode, compresslevel, fileobj),
1695 **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001696 except IOError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001697 raise ReadError("not a gzip file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001698 t._extfileobj = False
1699 return t
1700
Guido van Rossum75b64e62005-01-16 00:16:11 +00001701 @classmethod
Guido van Rossumd8faa362007-04-27 19:54:29 +00001702 def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001703 """Open bzip2 compressed tar archive name for reading or writing.
1704 Appending is not allowed.
1705 """
1706 if len(mode) > 1 or mode not in "rw":
Thomas Wouters477c8d52006-05-27 19:21:47 +00001707 raise ValueError("mode must be 'r' or 'w'.")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001708
1709 try:
1710 import bz2
1711 except ImportError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001712 raise CompressionError("bz2 module is not available")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001713
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001714 if fileobj is not None:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001715 fileobj = _BZ2Proxy(fileobj, mode)
1716 else:
1717 fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001718
1719 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001720 t = cls.taropen(name, mode, fileobj, **kwargs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001721 except IOError:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001722 raise ReadError("not a bzip2 file")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001723 t._extfileobj = False
1724 return t
1725
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001726 # All *open() methods are registered here.
1727 OPEN_METH = {
1728 "tar": "taropen", # uncompressed tar
1729 "gz": "gzopen", # gzip compressed tar
1730 "bz2": "bz2open" # bzip2 compressed tar
1731 }
1732
1733 #--------------------------------------------------------------------------
1734 # The public methods which TarFile provides:
1735
1736 def close(self):
1737 """Close the TarFile. In write-mode, two finishing zero blocks are
1738 appended to the archive.
1739 """
1740 if self.closed:
1741 return
1742
Guido van Rossumd8faa362007-04-27 19:54:29 +00001743 if self.mode in "aw":
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001744 self.fileobj.write(NUL * (BLOCKSIZE * 2))
1745 self.offset += (BLOCKSIZE * 2)
1746 # fill up the end with zero-blocks
1747 # (like option -b20 for tar does)
1748 blocks, remainder = divmod(self.offset, RECORDSIZE)
1749 if remainder > 0:
1750 self.fileobj.write(NUL * (RECORDSIZE - remainder))
1751
1752 if not self._extfileobj:
1753 self.fileobj.close()
1754 self.closed = True
1755
1756 def getmember(self, name):
1757 """Return a TarInfo object for member `name'. If `name' can not be
1758 found in the archive, KeyError is raised. If a member occurs more
1759 than once in the archive, its last occurence is assumed to be the
1760 most up-to-date version.
1761 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001762 tarinfo = self._getmember(name)
1763 if tarinfo is None:
Thomas Wouters477c8d52006-05-27 19:21:47 +00001764 raise KeyError("filename %r not found" % name)
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001765 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001766
1767 def getmembers(self):
1768 """Return the members of the archive as a list of TarInfo objects. The
1769 list has the same order as the members in the archive.
1770 """
1771 self._check()
1772 if not self._loaded: # if we want to obtain a list of
1773 self._load() # all members, we first have to
1774 # scan the whole archive.
1775 return self.members
1776
1777 def getnames(self):
1778 """Return the members of the archive as a list of their names. It has
1779 the same order as the list returned by getmembers().
1780 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001781 return [tarinfo.name for tarinfo in self.getmembers()]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001782
1783 def gettarinfo(self, name=None, arcname=None, fileobj=None):
1784 """Create a TarInfo object for either the file `name' or the file
1785 object `fileobj' (using os.fstat on its file descriptor). You can
1786 modify some of the TarInfo's attributes before you add it using
1787 addfile(). If given, `arcname' specifies an alternative name for the
1788 file in the archive.
1789 """
1790 self._check("aw")
1791
1792 # When fileobj is given, replace name by
1793 # fileobj's real name.
1794 if fileobj is not None:
1795 name = fileobj.name
1796
1797 # Building the name of the member in the archive.
1798 # Backward slashes are converted to forward slashes,
1799 # Absolute paths are turned to relative paths.
1800 if arcname is None:
1801 arcname = name
1802 arcname = normpath(arcname)
1803 drv, arcname = os.path.splitdrive(arcname)
1804 while arcname[0:1] == "/":
1805 arcname = arcname[1:]
1806
1807 # Now, fill the TarInfo object with
1808 # information specific for the file.
Guido van Rossumd8faa362007-04-27 19:54:29 +00001809 tarinfo = self.tarinfo()
1810 tarinfo.tarfile = self
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001811
1812 # Use os.stat or os.lstat, depending on platform
1813 # and if symlinks shall be resolved.
1814 if fileobj is None:
1815 if hasattr(os, "lstat") and not self.dereference:
1816 statres = os.lstat(name)
1817 else:
1818 statres = os.stat(name)
1819 else:
1820 statres = os.fstat(fileobj.fileno())
1821 linkname = ""
1822
1823 stmd = statres.st_mode
1824 if stat.S_ISREG(stmd):
1825 inode = (statres.st_ino, statres.st_dev)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001826 if not self.dereference and statres.st_nlink > 1 and \
1827 inode in self.inodes and arcname != self.inodes[inode]:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001828 # Is it a hardlink to an already
1829 # archived file?
1830 type = LNKTYPE
1831 linkname = self.inodes[inode]
1832 else:
1833 # The inode is added only if its valid.
1834 # For win32 it is always 0.
1835 type = REGTYPE
1836 if inode[0]:
1837 self.inodes[inode] = arcname
1838 elif stat.S_ISDIR(stmd):
1839 type = DIRTYPE
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001840 elif stat.S_ISFIFO(stmd):
1841 type = FIFOTYPE
1842 elif stat.S_ISLNK(stmd):
1843 type = SYMTYPE
1844 linkname = os.readlink(name)
1845 elif stat.S_ISCHR(stmd):
1846 type = CHRTYPE
1847 elif stat.S_ISBLK(stmd):
1848 type = BLKTYPE
1849 else:
1850 return None
1851
1852 # Fill the TarInfo object with all
1853 # information we can get.
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001854 tarinfo.name = arcname
1855 tarinfo.mode = stmd
1856 tarinfo.uid = statres.st_uid
1857 tarinfo.gid = statres.st_gid
1858 if stat.S_ISREG(stmd):
Martin v. Löwis61d77e02004-08-20 06:35:46 +00001859 tarinfo.size = statres.st_size
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001860 else:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001861 tarinfo.size = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001862 tarinfo.mtime = statres.st_mtime
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001863 tarinfo.type = type
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001864 tarinfo.linkname = linkname
1865 if pwd:
1866 try:
1867 tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
1868 except KeyError:
1869 pass
1870 if grp:
1871 try:
1872 tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
1873 except KeyError:
1874 pass
1875
1876 if type in (CHRTYPE, BLKTYPE):
1877 if hasattr(os, "major") and hasattr(os, "minor"):
1878 tarinfo.devmajor = os.major(statres.st_rdev)
1879 tarinfo.devminor = os.minor(statres.st_rdev)
1880 return tarinfo
1881
1882 def list(self, verbose=True):
1883 """Print a table of contents to sys.stdout. If `verbose' is False, only
1884 the names of the members are printed. If it is True, an `ls -l'-like
1885 output is produced.
1886 """
1887 self._check()
1888
1889 for tarinfo in self:
1890 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001891 print(filemode(tarinfo.mode), end=' ')
1892 print("%s/%s" % (tarinfo.uname or tarinfo.uid,
1893 tarinfo.gname or tarinfo.gid), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001894 if tarinfo.ischr() or tarinfo.isblk():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001895 print("%10s" % ("%d,%d" \
1896 % (tarinfo.devmajor, tarinfo.devminor)), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001897 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001898 print("%10d" % tarinfo.size, end=' ')
1899 print("%d-%02d-%02d %02d:%02d:%02d" \
1900 % time.localtime(tarinfo.mtime)[:6], end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001901
Guido van Rossumd8faa362007-04-27 19:54:29 +00001902 print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001903
1904 if verbose:
1905 if tarinfo.issym():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001906 print("->", tarinfo.linkname, end=' ')
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001907 if tarinfo.islnk():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001908 print("link to", tarinfo.linkname, end=' ')
1909 print()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001910
Guido van Rossum486364b2007-06-30 05:01:58 +00001911 def add(self, name, arcname=None, recursive=True, exclude=None):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001912 """Add the file `name' to the archive. `name' may be any type of file
1913 (directory, fifo, symbolic link, etc.). If given, `arcname'
1914 specifies an alternative name for the file in the archive.
1915 Directories are added recursively by default. This can be avoided by
Guido van Rossum486364b2007-06-30 05:01:58 +00001916 setting `recursive' to False. `exclude' is a function that should
1917 return True for each filename to be excluded.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001918 """
1919 self._check("aw")
1920
1921 if arcname is None:
1922 arcname = name
1923
Guido van Rossum486364b2007-06-30 05:01:58 +00001924 # Exclude pathnames.
1925 if exclude is not None and exclude(name):
1926 self._dbg(2, "tarfile: Excluded %r" % name)
1927 return
1928
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001929 # Skip if somebody tries to archive the archive...
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001930 if self.name is not None and os.path.abspath(name) == self.name:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001931 self._dbg(2, "tarfile: Skipped %r" % name)
1932 return
1933
1934 # Special case: The user wants to add the current
1935 # working directory.
1936 if name == ".":
1937 if recursive:
1938 if arcname == ".":
1939 arcname = ""
Guido van Rossumd8faa362007-04-27 19:54:29 +00001940 for f in os.listdir(name):
Guido van Rossum486364b2007-06-30 05:01:58 +00001941 self.add(f, os.path.join(arcname, f), recursive, exclude)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001942 return
1943
1944 self._dbg(1, name)
1945
1946 # Create a TarInfo object from the file.
1947 tarinfo = self.gettarinfo(name, arcname)
1948
1949 if tarinfo is None:
1950 self._dbg(1, "tarfile: Unsupported type %r" % name)
1951 return
1952
1953 # Append the tar header and data to the archive.
1954 if tarinfo.isreg():
Guido van Rossume7ba4952007-06-06 23:52:48 +00001955 f = bltn_open(name, "rb")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001956 self.addfile(tarinfo, f)
1957 f.close()
1958
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001959 elif tarinfo.isdir():
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001960 self.addfile(tarinfo)
1961 if recursive:
1962 for f in os.listdir(name):
Guido van Rossum486364b2007-06-30 05:01:58 +00001963 self.add(os.path.join(name, f), os.path.join(arcname, f), recursive, exclude)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001964
Martin v. Löwis5dbdc592005-08-27 10:07:56 +00001965 else:
1966 self.addfile(tarinfo)
1967
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001968 def addfile(self, tarinfo, fileobj=None):
1969 """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
1970 given, tarinfo.size bytes are read from it and added to the archive.
1971 You can create TarInfo objects using gettarinfo().
1972 On Windows platforms, `fileobj' should always be opened with mode
1973 'rb' to avoid irritation about the file size.
1974 """
1975 self._check("aw")
1976
Thomas Wouters89f507f2006-12-13 04:49:30 +00001977 tarinfo = copy.copy(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001978
Guido van Rossume7ba4952007-06-06 23:52:48 +00001979 buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
Thomas Wouters89f507f2006-12-13 04:49:30 +00001980 self.fileobj.write(buf)
1981 self.offset += len(buf)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001982
1983 # If there's data to follow, append it.
1984 if fileobj is not None:
1985 copyfileobj(fileobj, self.fileobj, tarinfo.size)
1986 blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
1987 if remainder > 0:
1988 self.fileobj.write(NUL * (BLOCKSIZE - remainder))
1989 blocks += 1
1990 self.offset += blocks * BLOCKSIZE
1991
Martin v. Löwisf3c56112004-09-18 09:08:52 +00001992 self.members.append(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001993
Martin v. Löwis00a73e72005-03-04 19:40:34 +00001994 def extractall(self, path=".", members=None):
1995 """Extract all members from the archive to the current working
1996 directory and set owner, modification time and permissions on
1997 directories afterwards. `path' specifies a different directory
1998 to extract to. `members' is optional and must be a subset of the
1999 list returned by getmembers().
2000 """
2001 directories = []
2002
2003 if members is None:
2004 members = self
2005
2006 for tarinfo in members:
2007 if tarinfo.isdir():
Christian Heimes2202f872008-02-06 14:31:34 +00002008 # Extract directories with a safe mode.
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002009 directories.append(tarinfo)
Christian Heimes2202f872008-02-06 14:31:34 +00002010 tarinfo = copy.copy(tarinfo)
2011 tarinfo.mode = 0o700
2012 self.extract(tarinfo, path)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002013
2014 # Reverse sort directories.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +00002015 directories.sort(key=lambda a: a.name)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002016 directories.reverse()
2017
2018 # Set correct owner, mtime and filemode on directories.
2019 for tarinfo in directories:
Christian Heimesfaf2f632008-01-06 16:59:19 +00002020 dirpath = os.path.join(path, tarinfo.name)
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002021 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +00002022 self.chown(tarinfo, dirpath)
2023 self.utime(tarinfo, dirpath)
2024 self.chmod(tarinfo, dirpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002025 except ExtractError as e:
Martin v. Löwis00a73e72005-03-04 19:40:34 +00002026 if self.errorlevel > 1:
2027 raise
2028 else:
2029 self._dbg(1, "tarfile: %s" % e)
2030
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002031 def extract(self, member, path=""):
2032 """Extract a member from the archive to the current working directory,
2033 using its full name. Its file information is extracted as accurately
2034 as possible. `member' may be a filename or a TarInfo object. You can
2035 specify a different directory using `path'.
2036 """
2037 self._check("r")
2038
Guido van Rossum3172c5d2007-10-16 18:12:55 +00002039 if isinstance(member, str):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002040 tarinfo = self.getmember(member)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002041 else:
2042 tarinfo = member
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002043
Neal Norwitza4f651a2004-07-20 22:07:44 +00002044 # Prepare the link target for makelink().
2045 if tarinfo.islnk():
2046 tarinfo._link_target = os.path.join(path, tarinfo.linkname)
2047
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002048 try:
2049 self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
Guido van Rossumb940e112007-01-10 16:19:56 +00002050 except EnvironmentError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002051 if self.errorlevel > 0:
2052 raise
2053 else:
2054 if e.filename is None:
2055 self._dbg(1, "tarfile: %s" % e.strerror)
2056 else:
2057 self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
Guido van Rossumb940e112007-01-10 16:19:56 +00002058 except ExtractError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002059 if self.errorlevel > 1:
2060 raise
2061 else:
2062 self._dbg(1, "tarfile: %s" % e)
2063
2064 def extractfile(self, member):
2065 """Extract a member from the archive as a file object. `member' may be
2066 a filename or a TarInfo object. If `member' is a regular file, a
2067 file-like object is returned. If `member' is a link, a file-like
2068 object is constructed from the link's target. If `member' is none of
2069 the above, None is returned.
2070 The file-like object is read-only and provides the following
2071 methods: read(), readline(), readlines(), seek() and tell()
2072 """
2073 self._check("r")
2074
Guido van Rossum3172c5d2007-10-16 18:12:55 +00002075 if isinstance(member, str):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002076 tarinfo = self.getmember(member)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002077 else:
2078 tarinfo = member
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002079
2080 if tarinfo.isreg():
2081 return self.fileobject(self, tarinfo)
2082
2083 elif tarinfo.type not in SUPPORTED_TYPES:
2084 # If a member's type is unknown, it is treated as a
2085 # regular file.
2086 return self.fileobject(self, tarinfo)
2087
2088 elif tarinfo.islnk() or tarinfo.issym():
2089 if isinstance(self.fileobj, _Stream):
2090 # A small but ugly workaround for the case that someone tries
2091 # to extract a (sym)link as a file-object from a non-seekable
2092 # stream of tar blocks.
Thomas Wouters477c8d52006-05-27 19:21:47 +00002093 raise StreamError("cannot extract (sym)link as file object")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002094 else:
Georg Brandl7eb4b7d2005-07-22 21:49:32 +00002095 # A (sym)link's file object is its target's file object.
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002096 return self.extractfile(self._getmember(tarinfo.linkname,
2097 tarinfo))
2098 else:
2099 # If there's no data associated with the member (directory, chrdev,
2100 # blkdev, etc.), return None instead of a file object.
2101 return None
2102
2103 def _extract_member(self, tarinfo, targetpath):
2104 """Extract the TarInfo object tarinfo to a physical
2105 file called targetpath.
2106 """
2107 # Fetch the TarInfo object for the given name
2108 # and build the destination pathname, replacing
2109 # forward slashes to platform specific separators.
2110 if targetpath[-1:] == "/":
2111 targetpath = targetpath[:-1]
2112 targetpath = os.path.normpath(targetpath)
2113
2114 # Create all upper directories.
2115 upperdirs = os.path.dirname(targetpath)
2116 if upperdirs and not os.path.exists(upperdirs):
Christian Heimes2202f872008-02-06 14:31:34 +00002117 # Create directories that are not part of the archive with
2118 # default permissions.
Thomas Woutersb2137042007-02-01 18:02:27 +00002119 os.makedirs(upperdirs)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002120
2121 if tarinfo.islnk() or tarinfo.issym():
2122 self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
2123 else:
2124 self._dbg(1, tarinfo.name)
2125
2126 if tarinfo.isreg():
2127 self.makefile(tarinfo, targetpath)
2128 elif tarinfo.isdir():
2129 self.makedir(tarinfo, targetpath)
2130 elif tarinfo.isfifo():
2131 self.makefifo(tarinfo, targetpath)
2132 elif tarinfo.ischr() or tarinfo.isblk():
2133 self.makedev(tarinfo, targetpath)
2134 elif tarinfo.islnk() or tarinfo.issym():
2135 self.makelink(tarinfo, targetpath)
2136 elif tarinfo.type not in SUPPORTED_TYPES:
2137 self.makeunknown(tarinfo, targetpath)
2138 else:
2139 self.makefile(tarinfo, targetpath)
2140
2141 self.chown(tarinfo, targetpath)
2142 if not tarinfo.issym():
2143 self.chmod(tarinfo, targetpath)
2144 self.utime(tarinfo, targetpath)
2145
2146 #--------------------------------------------------------------------------
2147 # Below are the different file methods. They are called via
2148 # _extract_member() when extract() is called. They can be replaced in a
2149 # subclass to implement other functionality.
2150
2151 def makedir(self, tarinfo, targetpath):
2152 """Make a directory called targetpath.
2153 """
2154 try:
Christian Heimes2202f872008-02-06 14:31:34 +00002155 # Use a safe mode for the directory, the real mode is set
2156 # later in _extract_member().
2157 os.mkdir(targetpath, 0o700)
Guido van Rossumb940e112007-01-10 16:19:56 +00002158 except EnvironmentError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002159 if e.errno != errno.EEXIST:
2160 raise
2161
2162 def makefile(self, tarinfo, targetpath):
2163 """Make a file called targetpath.
2164 """
2165 source = self.extractfile(tarinfo)
Guido van Rossume7ba4952007-06-06 23:52:48 +00002166 target = bltn_open(targetpath, "wb")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002167 copyfileobj(source, target)
2168 source.close()
2169 target.close()
2170
2171 def makeunknown(self, tarinfo, targetpath):
2172 """Make a file from a TarInfo object with an unknown type
2173 at targetpath.
2174 """
2175 self.makefile(tarinfo, targetpath)
2176 self._dbg(1, "tarfile: Unknown file type %r, " \
2177 "extracted as regular file." % tarinfo.type)
2178
2179 def makefifo(self, tarinfo, targetpath):
2180 """Make a fifo called targetpath.
2181 """
2182 if hasattr(os, "mkfifo"):
2183 os.mkfifo(targetpath)
2184 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002185 raise ExtractError("fifo not supported by system")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002186
2187 def makedev(self, tarinfo, targetpath):
2188 """Make a character or block device called targetpath.
2189 """
2190 if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
Thomas Wouters477c8d52006-05-27 19:21:47 +00002191 raise ExtractError("special devices not supported by system")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002192
2193 mode = tarinfo.mode
2194 if tarinfo.isblk():
2195 mode |= stat.S_IFBLK
2196 else:
2197 mode |= stat.S_IFCHR
2198
2199 os.mknod(targetpath, mode,
2200 os.makedev(tarinfo.devmajor, tarinfo.devminor))
2201
2202 def makelink(self, tarinfo, targetpath):
2203 """Make a (symbolic) link called targetpath. If it cannot be created
2204 (platform limitation), we try to make a copy of the referenced file
2205 instead of a link.
2206 """
2207 linkpath = tarinfo.linkname
2208 try:
2209 if tarinfo.issym():
2210 os.symlink(linkpath, targetpath)
2211 else:
Neal Norwitza4f651a2004-07-20 22:07:44 +00002212 # See extract().
2213 os.link(tarinfo._link_target, targetpath)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002214 except AttributeError:
2215 if tarinfo.issym():
2216 linkpath = os.path.join(os.path.dirname(tarinfo.name),
2217 linkpath)
2218 linkpath = normpath(linkpath)
2219
2220 try:
2221 self._extract_member(self.getmember(linkpath), targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002222 except (EnvironmentError, KeyError) as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002223 linkpath = os.path.normpath(linkpath)
2224 try:
2225 shutil.copy2(linkpath, targetpath)
Guido van Rossumb940e112007-01-10 16:19:56 +00002226 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002227 raise IOError("link could not be created")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002228
2229 def chown(self, tarinfo, targetpath):
2230 """Set owner of targetpath according to tarinfo.
2231 """
2232 if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
2233 # We have to be root to do so.
2234 try:
2235 g = grp.getgrnam(tarinfo.gname)[2]
2236 except KeyError:
2237 try:
2238 g = grp.getgrgid(tarinfo.gid)[2]
2239 except KeyError:
2240 g = os.getgid()
2241 try:
2242 u = pwd.getpwnam(tarinfo.uname)[2]
2243 except KeyError:
2244 try:
2245 u = pwd.getpwuid(tarinfo.uid)[2]
2246 except KeyError:
2247 u = os.getuid()
2248 try:
2249 if tarinfo.issym() and hasattr(os, "lchown"):
2250 os.lchown(targetpath, u, g)
2251 else:
Andrew MacIntyre7970d202003-02-19 12:51:34 +00002252 if sys.platform != "os2emx":
2253 os.chown(targetpath, u, g)
Guido van Rossumb940e112007-01-10 16:19:56 +00002254 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002255 raise ExtractError("could not change owner")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002256
2257 def chmod(self, tarinfo, targetpath):
2258 """Set file permissions of targetpath according to tarinfo.
2259 """
Jack Jansen834eff62003-03-07 12:47:06 +00002260 if hasattr(os, 'chmod'):
2261 try:
2262 os.chmod(targetpath, tarinfo.mode)
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 mode")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002265
2266 def utime(self, tarinfo, targetpath):
2267 """Set modification time of targetpath according to tarinfo.
2268 """
Jack Jansen834eff62003-03-07 12:47:06 +00002269 if not hasattr(os, 'utime'):
Tim Petersf9347782003-03-07 15:36:41 +00002270 return
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002271 if sys.platform == "win32" and tarinfo.isdir():
2272 # According to msdn.microsoft.com, it is an error (EACCES)
2273 # to use utime() on directories.
2274 return
2275 try:
2276 os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
Guido van Rossumb940e112007-01-10 16:19:56 +00002277 except EnvironmentError as e:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002278 raise ExtractError("could not change modification time")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002279
2280 #--------------------------------------------------------------------------
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002281 def next(self):
2282 """Return the next member of the archive as a TarInfo object, when
2283 TarFile is opened for reading. Return None if there is no more
2284 available.
2285 """
2286 self._check("ra")
2287 if self.firstmember is not None:
2288 m = self.firstmember
2289 self.firstmember = None
2290 return m
2291
2292 # Read the next block.
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002293 self.fileobj.seek(self.offset)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002294 while True:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002295 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00002296 tarinfo = self.tarinfo.fromtarfile(self)
2297 if tarinfo is None:
2298 return
2299 self.members.append(tarinfo)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002300
Guido van Rossumb940e112007-01-10 16:19:56 +00002301 except HeaderError as e:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002302 if self.ignore_zeros:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00002303 self._dbg(2, "0x%X: %s" % (self.offset, e))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002304 self.offset += BLOCKSIZE
2305 continue
2306 else:
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002307 if self.offset == 0:
Thomas Wouters902d6eb2007-01-09 23:18:33 +00002308 raise ReadError(str(e))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002309 return None
2310 break
2311
Thomas Wouters477c8d52006-05-27 19:21:47 +00002312 return tarinfo
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002313
2314 #--------------------------------------------------------------------------
2315 # Little helper methods:
2316
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002317 def _getmember(self, name, tarinfo=None):
2318 """Find an archive member by name from bottom to top.
2319 If tarinfo is given, it is used as the starting point.
2320 """
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002321 # Ensure that all members have been loaded.
2322 members = self.getmembers()
2323
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002324 if tarinfo is None:
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002325 end = len(members)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002326 else:
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002327 end = members.index(tarinfo)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002328
Guido van Rossum805365e2007-05-07 22:24:25 +00002329 for i in range(end - 1, -1, -1):
Martin v. Löwisf3c56112004-09-18 09:08:52 +00002330 if name == members[i].name:
2331 return members[i]
Andrew M. Kuchling864bba12004-07-10 22:02:11 +00002332
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002333 def _load(self):
2334 """Read through the entire archive file and look for readable
2335 members.
2336 """
2337 while True:
2338 tarinfo = self.next()
2339 if tarinfo is None:
2340 break
2341 self._loaded = True
2342
2343 def _check(self, mode=None):
2344 """Check if TarFile is still open, and if the operation's mode
2345 corresponds to TarFile's mode.
2346 """
2347 if self.closed:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002348 raise IOError("%s is closed" % self.__class__.__name__)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002349 if mode is not None and self.mode not in mode:
2350 raise IOError("bad operation for mode %r" % self.mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002351
2352 def __iter__(self):
2353 """Provide an iterator object.
2354 """
2355 if self._loaded:
2356 return iter(self.members)
2357 else:
2358 return TarIter(self)
2359
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002360 def _dbg(self, level, msg):
2361 """Write debugging output to sys.stderr.
2362 """
2363 if level <= self.debug:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002364 print(msg, file=sys.stderr)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002365# class TarFile
2366
2367class TarIter:
2368 """Iterator Class.
2369
2370 for tarinfo in TarFile(...):
2371 suite...
2372 """
2373
2374 def __init__(self, tarfile):
2375 """Construct a TarIter object.
2376 """
2377 self.tarfile = tarfile
Martin v. Löwis637431b2005-03-03 23:12:42 +00002378 self.index = 0
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002379 def __iter__(self):
2380 """Return iterator object.
2381 """
2382 return self
Georg Brandla18af4e2007-04-21 15:47:16 +00002383 def __next__(self):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002384 """Return the next item using TarFile's next() method.
2385 When all members have been read, set TarFile as _loaded.
2386 """
Martin v. Löwis637431b2005-03-03 23:12:42 +00002387 # Fix for SF #1100429: Under rare circumstances it can
2388 # happen that getmembers() is called during iteration,
2389 # which will cause TarIter to stop prematurely.
2390 if not self.tarfile._loaded:
2391 tarinfo = self.tarfile.next()
2392 if not tarinfo:
2393 self.tarfile._loaded = True
2394 raise StopIteration
2395 else:
2396 try:
2397 tarinfo = self.tarfile.members[self.index]
2398 except IndexError:
2399 raise StopIteration
2400 self.index += 1
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002401 return tarinfo
2402
2403# Helper classes for sparse file support
2404class _section:
2405 """Base class for _data and _hole.
2406 """
2407 def __init__(self, offset, size):
2408 self.offset = offset
2409 self.size = size
2410 def __contains__(self, offset):
2411 return self.offset <= offset < self.offset + self.size
2412
2413class _data(_section):
2414 """Represent a data section in a sparse file.
2415 """
2416 def __init__(self, offset, size, realpos):
2417 _section.__init__(self, offset, size)
2418 self.realpos = realpos
2419
2420class _hole(_section):
2421 """Represent a hole section in a sparse file.
2422 """
2423 pass
2424
2425class _ringbuffer(list):
2426 """Ringbuffer class which increases performance
2427 over a regular list.
2428 """
2429 def __init__(self):
2430 self.idx = 0
2431 def find(self, offset):
2432 idx = self.idx
2433 while True:
2434 item = self[idx]
2435 if offset in item:
2436 break
2437 idx += 1
2438 if idx == len(self):
2439 idx = 0
2440 if idx == self.idx:
2441 # End of File
2442 return None
2443 self.idx = idx
2444 return item
2445
2446#---------------------------------------------
2447# zipfile compatible TarFile class
2448#---------------------------------------------
2449TAR_PLAIN = 0 # zipfile.ZIP_STORED
2450TAR_GZIPPED = 8 # zipfile.ZIP_DEFLATED
2451class TarFileCompat:
2452 """TarFile class compatible with standard module zipfile's
2453 ZipFile class.
2454 """
2455 def __init__(self, file, mode="r", compression=TAR_PLAIN):
2456 if compression == TAR_PLAIN:
2457 self.tarfile = TarFile.taropen(file, mode)
2458 elif compression == TAR_GZIPPED:
2459 self.tarfile = TarFile.gzopen(file, mode)
2460 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +00002461 raise ValueError("unknown compression constant")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002462 if mode[0:1] == "r":
2463 members = self.tarfile.getmembers()
Raymond Hettingera1d09e22005-09-11 16:34:05 +00002464 for m in members:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002465 m.filename = m.name
2466 m.file_size = m.size
2467 m.date_time = time.gmtime(m.mtime)[:6]
2468 def namelist(self):
2469 return map(lambda m: m.name, self.infolist())
2470 def infolist(self):
2471 return filter(lambda m: m.type in REGULAR_TYPES,
2472 self.tarfile.getmembers())
2473 def printdir(self):
2474 self.tarfile.list()
2475 def testzip(self):
2476 return
2477 def getinfo(self, name):
2478 return self.tarfile.getmember(name)
2479 def read(self, name):
2480 return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
2481 def write(self, filename, arcname=None, compress_type=None):
2482 self.tarfile.add(filename, arcname)
2483 def writestr(self, zinfo, bytes):
Guido van Rossum68937b42007-05-18 00:51:22 +00002484 from io import StringIO
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002485 import calendar
2486 zinfo.name = zinfo.filename
2487 zinfo.size = zinfo.file_size
2488 zinfo.mtime = calendar.timegm(zinfo.date_time)
Raymond Hettingera6172712004-12-31 19:15:26 +00002489 self.tarfile.addfile(zinfo, StringIO(bytes))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002490 def close(self):
2491 self.tarfile.close()
2492#class TarFileCompat
2493
2494#--------------------
2495# exported functions
2496#--------------------
2497def is_tarfile(name):
2498 """Return True if name points to a tar archive that we
2499 are able to handle, else return False.
2500 """
2501 try:
2502 t = open(name)
2503 t.close()
2504 return True
2505 except TarError:
2506 return False
2507
Guido van Rossume7ba4952007-06-06 23:52:48 +00002508bltn_open = open
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00002509open = TarFile.open