[Bug #1633678] Improve pattern used for mbox 'From' lines; add a simple test
[pytest.git] / Lib / tarfile.py
blob4c7dadbc6ad744e17d21360a7a8cbe318ced343a
1 #!/usr/bin/env python
2 # -*- coding: iso-8859-1 -*-
3 #-------------------------------------------------------------------
4 # tarfile.py
5 #-------------------------------------------------------------------
6 # Copyright (C) 2002 Lars Gustäbel <lars@gustaebel.de>
7 # All rights reserved.
9 # Permission is hereby granted, free of charge, to any person
10 # obtaining a copy of this software and associated documentation
11 # files (the "Software"), to deal in the Software without
12 # restriction, including without limitation the rights to use,
13 # copy, modify, merge, publish, distribute, sublicense, and/or sell
14 # copies of the Software, and to permit persons to whom the
15 # Software is furnished to do so, subject to the following
16 # conditions:
18 # The above copyright notice and this permission notice shall be
19 # included in all copies or substantial portions of the Software.
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 # OTHER DEALINGS IN THE SOFTWARE.
30 """Read from and write to tar format archives.
31 """
33 __version__ = "$Revision$"
34 # $Source$
36 version = "0.8.0"
37 __author__ = "Lars Gustäbel (lars@gustaebel.de)"
38 __date__ = "$Date$"
39 __cvsid__ = "$Id$"
40 __credits__ = "Gustavo Niemeyer, Niels Gustäbel, Richard Townsend."
42 #---------
43 # Imports
44 #---------
45 import sys
46 import os
47 import shutil
48 import stat
49 import errno
50 import time
51 import struct
52 import copy
54 if sys.platform == 'mac':
55 # This module needs work for MacOS9, especially in the area of pathname
56 # handling. In many places it is assumed a simple substitution of / by the
57 # local os.path.sep is good enough to convert pathnames, but this does not
58 # work with the mac rooted:path:name versus :nonrooted:path:name syntax
59 raise ImportError, "tarfile does not work for platform==mac"
61 try:
62 import grp, pwd
63 except ImportError:
64 grp = pwd = None
66 # from tarfile import *
67 __all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"]
69 #---------------------------------------------------------
70 # tar constants
71 #---------------------------------------------------------
72 NUL = "\0" # the null character
73 BLOCKSIZE = 512 # length of processing blocks
74 RECORDSIZE = BLOCKSIZE * 20 # length of records
75 MAGIC = "ustar" # magic tar string
76 VERSION = "00" # version number
78 LENGTH_NAME = 100 # maximum length of a filename
79 LENGTH_LINK = 100 # maximum length of a linkname
80 LENGTH_PREFIX = 155 # maximum length of the prefix field
81 MAXSIZE_MEMBER = 077777777777L # maximum size of a file (11 octal digits)
83 REGTYPE = "0" # regular file
84 AREGTYPE = "\0" # regular file
85 LNKTYPE = "1" # link (inside tarfile)
86 SYMTYPE = "2" # symbolic link
87 CHRTYPE = "3" # character special device
88 BLKTYPE = "4" # block special device
89 DIRTYPE = "5" # directory
90 FIFOTYPE = "6" # fifo special device
91 CONTTYPE = "7" # contiguous file
93 GNUTYPE_LONGNAME = "L" # GNU tar extension for longnames
94 GNUTYPE_LONGLINK = "K" # GNU tar extension for longlink
95 GNUTYPE_SPARSE = "S" # GNU tar extension for sparse file
97 #---------------------------------------------------------
98 # tarfile constants
99 #---------------------------------------------------------
100 SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, # file types that tarfile
101 SYMTYPE, DIRTYPE, FIFOTYPE, # can cope with.
102 CONTTYPE, CHRTYPE, BLKTYPE,
103 GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
104 GNUTYPE_SPARSE)
106 REGULAR_TYPES = (REGTYPE, AREGTYPE, # file types that somehow
107 CONTTYPE, GNUTYPE_SPARSE) # represent regular files
109 #---------------------------------------------------------
110 # Bits used in the mode field, values in octal.
111 #---------------------------------------------------------
112 S_IFLNK = 0120000 # symbolic link
113 S_IFREG = 0100000 # regular file
114 S_IFBLK = 0060000 # block device
115 S_IFDIR = 0040000 # directory
116 S_IFCHR = 0020000 # character device
117 S_IFIFO = 0010000 # fifo
119 TSUID = 04000 # set UID on execution
120 TSGID = 02000 # set GID on execution
121 TSVTX = 01000 # reserved
123 TUREAD = 0400 # read by owner
124 TUWRITE = 0200 # write by owner
125 TUEXEC = 0100 # execute/search by owner
126 TGREAD = 0040 # read by group
127 TGWRITE = 0020 # write by group
128 TGEXEC = 0010 # execute/search by group
129 TOREAD = 0004 # read by other
130 TOWRITE = 0002 # write by other
131 TOEXEC = 0001 # execute/search by other
133 #---------------------------------------------------------
134 # Some useful functions
135 #---------------------------------------------------------
137 def stn(s, length):
138 """Convert a python string to a null-terminated string buffer.
140 return s[:length] + (length - len(s)) * NUL
142 def nti(s):
143 """Convert a number field to a python number.
145 # There are two possible encodings for a number field, see
146 # itn() below.
147 if s[0] != chr(0200):
148 n = int(s.rstrip(NUL + " ") or "0", 8)
149 else:
150 n = 0L
151 for i in xrange(len(s) - 1):
152 n <<= 8
153 n += ord(s[i + 1])
154 return n
156 def itn(n, digits=8, posix=False):
157 """Convert a python number to a number field.
159 # POSIX 1003.1-1988 requires numbers to be encoded as a string of
160 # octal digits followed by a null-byte, this allows values up to
161 # (8**(digits-1))-1. GNU tar allows storing numbers greater than
162 # that if necessary. A leading 0200 byte indicates this particular
163 # encoding, the following digits-1 bytes are a big-endian
164 # representation. This allows values up to (256**(digits-1))-1.
165 if 0 <= n < 8 ** (digits - 1):
166 s = "%0*o" % (digits - 1, n) + NUL
167 else:
168 if posix:
169 raise ValueError("overflow in number field")
171 if n < 0:
172 # XXX We mimic GNU tar's behaviour with negative numbers,
173 # this could raise OverflowError.
174 n = struct.unpack("L", struct.pack("l", n))[0]
176 s = ""
177 for i in xrange(digits - 1):
178 s = chr(n & 0377) + s
179 n >>= 8
180 s = chr(0200) + s
181 return s
183 def calc_chksums(buf):
184 """Calculate the checksum for a member's header by summing up all
185 characters except for the chksum field which is treated as if
186 it was filled with spaces. According to the GNU tar sources,
187 some tars (Sun and NeXT) calculate chksum with signed char,
188 which will be different if there are chars in the buffer with
189 the high bit set. So we calculate two checksums, unsigned and
190 signed.
192 unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512]))
193 signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512]))
194 return unsigned_chksum, signed_chksum
196 def copyfileobj(src, dst, length=None):
197 """Copy length bytes from fileobj src to fileobj dst.
198 If length is None, copy the entire content.
200 if length == 0:
201 return
202 if length is None:
203 shutil.copyfileobj(src, dst)
204 return
206 BUFSIZE = 16 * 1024
207 blocks, remainder = divmod(length, BUFSIZE)
208 for b in xrange(blocks):
209 buf = src.read(BUFSIZE)
210 if len(buf) < BUFSIZE:
211 raise IOError("end of file reached")
212 dst.write(buf)
214 if remainder != 0:
215 buf = src.read(remainder)
216 if len(buf) < remainder:
217 raise IOError("end of file reached")
218 dst.write(buf)
219 return
221 filemode_table = (
222 ((S_IFLNK, "l"),
223 (S_IFREG, "-"),
224 (S_IFBLK, "b"),
225 (S_IFDIR, "d"),
226 (S_IFCHR, "c"),
227 (S_IFIFO, "p")),
229 ((TUREAD, "r"),),
230 ((TUWRITE, "w"),),
231 ((TUEXEC|TSUID, "s"),
232 (TSUID, "S"),
233 (TUEXEC, "x")),
235 ((TGREAD, "r"),),
236 ((TGWRITE, "w"),),
237 ((TGEXEC|TSGID, "s"),
238 (TSGID, "S"),
239 (TGEXEC, "x")),
241 ((TOREAD, "r"),),
242 ((TOWRITE, "w"),),
243 ((TOEXEC|TSVTX, "t"),
244 (TSVTX, "T"),
245 (TOEXEC, "x"))
248 def filemode(mode):
249 """Convert a file's mode to a string of the form
250 -rwxrwxrwx.
251 Used by TarFile.list()
253 perm = []
254 for table in filemode_table:
255 for bit, char in table:
256 if mode & bit == bit:
257 perm.append(char)
258 break
259 else:
260 perm.append("-")
261 return "".join(perm)
263 if os.sep != "/":
264 normpath = lambda path: os.path.normpath(path).replace(os.sep, "/")
265 else:
266 normpath = os.path.normpath
268 class TarError(Exception):
269 """Base exception."""
270 pass
271 class ExtractError(TarError):
272 """General exception for extract errors."""
273 pass
274 class ReadError(TarError):
275 """Exception for unreadble tar archives."""
276 pass
277 class CompressionError(TarError):
278 """Exception for unavailable compression methods."""
279 pass
280 class StreamError(TarError):
281 """Exception for unsupported operations on stream-like TarFiles."""
282 pass
284 #---------------------------
285 # internal stream interface
286 #---------------------------
287 class _LowLevelFile:
288 """Low-level file object. Supports reading and writing.
289 It is used instead of a regular file object for streaming
290 access.
293 def __init__(self, name, mode):
294 mode = {
295 "r": os.O_RDONLY,
296 "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
297 }[mode]
298 if hasattr(os, "O_BINARY"):
299 mode |= os.O_BINARY
300 self.fd = os.open(name, mode)
302 def close(self):
303 os.close(self.fd)
305 def read(self, size):
306 return os.read(self.fd, size)
308 def write(self, s):
309 os.write(self.fd, s)
311 class _Stream:
312 """Class that serves as an adapter between TarFile and
313 a stream-like object. The stream-like object only
314 needs to have a read() or write() method and is accessed
315 blockwise. Use of gzip or bzip2 compression is possible.
316 A stream-like object could be for example: sys.stdin,
317 sys.stdout, a socket, a tape device etc.
319 _Stream is intended to be used only internally.
322 def __init__(self, name, mode, comptype, fileobj, bufsize):
323 """Construct a _Stream object.
325 self._extfileobj = True
326 if fileobj is None:
327 fileobj = _LowLevelFile(name, mode)
328 self._extfileobj = False
330 if comptype == '*':
331 # Enable transparent compression detection for the
332 # stream interface
333 fileobj = _StreamProxy(fileobj)
334 comptype = fileobj.getcomptype()
336 self.name = name or ""
337 self.mode = mode
338 self.comptype = comptype
339 self.fileobj = fileobj
340 self.bufsize = bufsize
341 self.buf = ""
342 self.pos = 0L
343 self.closed = False
345 if comptype == "gz":
346 try:
347 import zlib
348 except ImportError:
349 raise CompressionError("zlib module is not available")
350 self.zlib = zlib
351 self.crc = zlib.crc32("")
352 if mode == "r":
353 self._init_read_gz()
354 else:
355 self._init_write_gz()
357 if comptype == "bz2":
358 try:
359 import bz2
360 except ImportError:
361 raise CompressionError("bz2 module is not available")
362 if mode == "r":
363 self.dbuf = ""
364 self.cmp = bz2.BZ2Decompressor()
365 else:
366 self.cmp = bz2.BZ2Compressor()
368 def __del__(self):
369 if hasattr(self, "closed") and not self.closed:
370 self.close()
372 def _init_write_gz(self):
373 """Initialize for writing with gzip compression.
375 self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED,
376 -self.zlib.MAX_WBITS,
377 self.zlib.DEF_MEM_LEVEL,
379 timestamp = struct.pack("<L", long(time.time()))
380 self.__write("\037\213\010\010%s\002\377" % timestamp)
381 if self.name.endswith(".gz"):
382 self.name = self.name[:-3]
383 self.__write(self.name + NUL)
385 def write(self, s):
386 """Write string s to the stream.
388 if self.comptype == "gz":
389 self.crc = self.zlib.crc32(s, self.crc)
390 self.pos += len(s)
391 if self.comptype != "tar":
392 s = self.cmp.compress(s)
393 self.__write(s)
395 def __write(self, s):
396 """Write string s to the stream if a whole new block
397 is ready to be written.
399 self.buf += s
400 while len(self.buf) > self.bufsize:
401 self.fileobj.write(self.buf[:self.bufsize])
402 self.buf = self.buf[self.bufsize:]
404 def close(self):
405 """Close the _Stream object. No operation should be
406 done on it afterwards.
408 if self.closed:
409 return
411 if self.mode == "w" and self.comptype != "tar":
412 self.buf += self.cmp.flush()
414 if self.mode == "w" and self.buf:
415 self.fileobj.write(self.buf)
416 self.buf = ""
417 if self.comptype == "gz":
418 # The native zlib crc is an unsigned 32-bit integer, but
419 # the Python wrapper implicitly casts that to a signed C
420 # long. So, on a 32-bit box self.crc may "look negative",
421 # while the same crc on a 64-bit box may "look positive".
422 # To avoid irksome warnings from the `struct` module, force
423 # it to look positive on all boxes.
424 self.fileobj.write(struct.pack("<L", self.crc & 0xffffffffL))
425 self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFFL))
427 if not self._extfileobj:
428 self.fileobj.close()
430 self.closed = True
432 def _init_read_gz(self):
433 """Initialize for reading a gzip compressed fileobj.
435 self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS)
436 self.dbuf = ""
438 # taken from gzip.GzipFile with some alterations
439 if self.__read(2) != "\037\213":
440 raise ReadError("not a gzip file")
441 if self.__read(1) != "\010":
442 raise CompressionError("unsupported compression method")
444 flag = ord(self.__read(1))
445 self.__read(6)
447 if flag & 4:
448 xlen = ord(self.__read(1)) + 256 * ord(self.__read(1))
449 self.read(xlen)
450 if flag & 8:
451 while True:
452 s = self.__read(1)
453 if not s or s == NUL:
454 break
455 if flag & 16:
456 while True:
457 s = self.__read(1)
458 if not s or s == NUL:
459 break
460 if flag & 2:
461 self.__read(2)
463 def tell(self):
464 """Return the stream's file pointer position.
466 return self.pos
468 def seek(self, pos=0):
469 """Set the stream's file pointer to pos. Negative seeking
470 is forbidden.
472 if pos - self.pos >= 0:
473 blocks, remainder = divmod(pos - self.pos, self.bufsize)
474 for i in xrange(blocks):
475 self.read(self.bufsize)
476 self.read(remainder)
477 else:
478 raise StreamError("seeking backwards is not allowed")
479 return self.pos
481 def read(self, size=None):
482 """Return the next size number of bytes from the stream.
483 If size is not defined, return all bytes of the stream
484 up to EOF.
486 if size is None:
487 t = []
488 while True:
489 buf = self._read(self.bufsize)
490 if not buf:
491 break
492 t.append(buf)
493 buf = "".join(t)
494 else:
495 buf = self._read(size)
496 self.pos += len(buf)
497 return buf
499 def _read(self, size):
500 """Return size bytes from the stream.
502 if self.comptype == "tar":
503 return self.__read(size)
505 c = len(self.dbuf)
506 t = [self.dbuf]
507 while c < size:
508 buf = self.__read(self.bufsize)
509 if not buf:
510 break
511 buf = self.cmp.decompress(buf)
512 t.append(buf)
513 c += len(buf)
514 t = "".join(t)
515 self.dbuf = t[size:]
516 return t[:size]
518 def __read(self, size):
519 """Return size bytes from stream. If internal buffer is empty,
520 read another block from the stream.
522 c = len(self.buf)
523 t = [self.buf]
524 while c < size:
525 buf = self.fileobj.read(self.bufsize)
526 if not buf:
527 break
528 t.append(buf)
529 c += len(buf)
530 t = "".join(t)
531 self.buf = t[size:]
532 return t[:size]
533 # class _Stream
535 class _StreamProxy(object):
536 """Small proxy class that enables transparent compression
537 detection for the Stream interface (mode 'r|*').
540 def __init__(self, fileobj):
541 self.fileobj = fileobj
542 self.buf = self.fileobj.read(BLOCKSIZE)
544 def read(self, size):
545 self.read = self.fileobj.read
546 return self.buf
548 def getcomptype(self):
549 if self.buf.startswith("\037\213\010"):
550 return "gz"
551 if self.buf.startswith("BZh91"):
552 return "bz2"
553 return "tar"
555 def close(self):
556 self.fileobj.close()
557 # class StreamProxy
559 class _BZ2Proxy(object):
560 """Small proxy class that enables external file object
561 support for "r:bz2" and "w:bz2" modes. This is actually
562 a workaround for a limitation in bz2 module's BZ2File
563 class which (unlike gzip.GzipFile) has no support for
564 a file object argument.
567 blocksize = 16 * 1024
569 def __init__(self, fileobj, mode):
570 self.fileobj = fileobj
571 self.mode = mode
572 self.init()
574 def init(self):
575 import bz2
576 self.pos = 0
577 if self.mode == "r":
578 self.bz2obj = bz2.BZ2Decompressor()
579 self.fileobj.seek(0)
580 self.buf = ""
581 else:
582 self.bz2obj = bz2.BZ2Compressor()
584 def read(self, size):
585 b = [self.buf]
586 x = len(self.buf)
587 while x < size:
588 try:
589 raw = self.fileobj.read(self.blocksize)
590 data = self.bz2obj.decompress(raw)
591 b.append(data)
592 except EOFError:
593 break
594 x += len(data)
595 self.buf = "".join(b)
597 buf = self.buf[:size]
598 self.buf = self.buf[size:]
599 self.pos += len(buf)
600 return buf
602 def seek(self, pos):
603 if pos < self.pos:
604 self.init()
605 self.read(pos - self.pos)
607 def tell(self):
608 return self.pos
610 def write(self, data):
611 self.pos += len(data)
612 raw = self.bz2obj.compress(data)
613 self.fileobj.write(raw)
615 def close(self):
616 if self.mode == "w":
617 raw = self.bz2obj.flush()
618 self.fileobj.write(raw)
619 self.fileobj.close()
620 # class _BZ2Proxy
622 #------------------------
623 # Extraction file object
624 #------------------------
625 class _FileInFile(object):
626 """A thin wrapper around an existing file object that
627 provides a part of its data as an individual file
628 object.
631 def __init__(self, fileobj, offset, size, sparse=None):
632 self.fileobj = fileobj
633 self.offset = offset
634 self.size = size
635 self.sparse = sparse
636 self.position = 0
638 def tell(self):
639 """Return the current file position.
641 return self.position
643 def seek(self, position):
644 """Seek to a position in the file.
646 self.position = position
648 def read(self, size=None):
649 """Read data from the file.
651 if size is None:
652 size = self.size - self.position
653 else:
654 size = min(size, self.size - self.position)
656 if self.sparse is None:
657 return self.readnormal(size)
658 else:
659 return self.readsparse(size)
661 def readnormal(self, size):
662 """Read operation for regular files.
664 self.fileobj.seek(self.offset + self.position)
665 self.position += size
666 return self.fileobj.read(size)
668 def readsparse(self, size):
669 """Read operation for sparse files.
671 data = []
672 while size > 0:
673 buf = self.readsparsesection(size)
674 if not buf:
675 break
676 size -= len(buf)
677 data.append(buf)
678 return "".join(data)
680 def readsparsesection(self, size):
681 """Read a single section of a sparse file.
683 section = self.sparse.find(self.position)
685 if section is None:
686 return ""
688 size = min(size, section.offset + section.size - self.position)
690 if isinstance(section, _data):
691 realpos = section.realpos + self.position - section.offset
692 self.fileobj.seek(self.offset + realpos)
693 self.position += size
694 return self.fileobj.read(size)
695 else:
696 self.position += size
697 return NUL * size
698 #class _FileInFile
701 class ExFileObject(object):
702 """File-like object for reading an archive member.
703 Is returned by TarFile.extractfile().
705 blocksize = 1024
707 def __init__(self, tarfile, tarinfo):
708 self.fileobj = _FileInFile(tarfile.fileobj,
709 tarinfo.offset_data,
710 tarinfo.size,
711 getattr(tarinfo, "sparse", None))
712 self.name = tarinfo.name
713 self.mode = "r"
714 self.closed = False
715 self.size = tarinfo.size
717 self.position = 0
718 self.buffer = ""
720 def read(self, size=None):
721 """Read at most size bytes from the file. If size is not
722 present or None, read all data until EOF is reached.
724 if self.closed:
725 raise ValueError("I/O operation on closed file")
727 buf = ""
728 if self.buffer:
729 if size is None:
730 buf = self.buffer
731 self.buffer = ""
732 else:
733 buf = self.buffer[:size]
734 self.buffer = self.buffer[size:]
736 if size is None:
737 buf += self.fileobj.read()
738 else:
739 buf += self.fileobj.read(size - len(buf))
741 self.position += len(buf)
742 return buf
744 def readline(self, size=-1):
745 """Read one entire line from the file. If size is present
746 and non-negative, return a string with at most that
747 size, which may be an incomplete line.
749 if self.closed:
750 raise ValueError("I/O operation on closed file")
752 if "\n" in self.buffer:
753 pos = self.buffer.find("\n") + 1
754 else:
755 buffers = [self.buffer]
756 while True:
757 buf = self.fileobj.read(self.blocksize)
758 buffers.append(buf)
759 if not buf or "\n" in buf:
760 self.buffer = "".join(buffers)
761 pos = self.buffer.find("\n") + 1
762 if pos == 0:
763 # no newline found.
764 pos = len(self.buffer)
765 break
767 if size != -1:
768 pos = min(size, pos)
770 buf = self.buffer[:pos]
771 self.buffer = self.buffer[pos:]
772 self.position += len(buf)
773 return buf
775 def readlines(self):
776 """Return a list with all remaining lines.
778 result = []
779 while True:
780 line = self.readline()
781 if not line: break
782 result.append(line)
783 return result
785 def tell(self):
786 """Return the current file position.
788 if self.closed:
789 raise ValueError("I/O operation on closed file")
791 return self.position
793 def seek(self, pos, whence=os.SEEK_SET):
794 """Seek to a position in the file.
796 if self.closed:
797 raise ValueError("I/O operation on closed file")
799 if whence == os.SEEK_SET:
800 self.position = min(max(pos, 0), self.size)
801 elif whence == os.SEEK_CUR:
802 if pos < 0:
803 self.position = max(self.position + pos, 0)
804 else:
805 self.position = min(self.position + pos, self.size)
806 elif whence == os.SEEK_END:
807 self.position = max(min(self.size + pos, self.size), 0)
808 else:
809 raise ValueError("Invalid argument")
811 self.buffer = ""
812 self.fileobj.seek(self.position)
814 def close(self):
815 """Close the file object.
817 self.closed = True
819 def __iter__(self):
820 """Get an iterator over the file's lines.
822 while True:
823 line = self.readline()
824 if not line:
825 break
826 yield line
827 #class ExFileObject
829 #------------------
830 # Exported Classes
831 #------------------
832 class TarInfo(object):
833 """Informational class which holds the details about an
834 archive member given by a tar header block.
835 TarInfo objects are returned by TarFile.getmember(),
836 TarFile.getmembers() and TarFile.gettarinfo() and are
837 usually created internally.
840 def __init__(self, name=""):
841 """Construct a TarInfo object. name is the optional name
842 of the member.
844 self.name = name # member name (dirnames must end with '/')
845 self.mode = 0666 # file permissions
846 self.uid = 0 # user id
847 self.gid = 0 # group id
848 self.size = 0 # file size
849 self.mtime = 0 # modification time
850 self.chksum = 0 # header checksum
851 self.type = REGTYPE # member type
852 self.linkname = "" # link name
853 self.uname = "user" # user name
854 self.gname = "group" # group name
855 self.devmajor = 0 # device major number
856 self.devminor = 0 # device minor number
858 self.offset = 0 # the tar header starts here
859 self.offset_data = 0 # the file's data starts here
861 def __repr__(self):
862 return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self))
864 @classmethod
865 def frombuf(cls, buf):
866 """Construct a TarInfo object from a 512 byte string buffer.
868 if len(buf) != BLOCKSIZE:
869 raise ValueError("truncated header")
870 if buf.count(NUL) == BLOCKSIZE:
871 raise ValueError("empty header")
873 tarinfo = cls()
874 tarinfo.buf = buf
875 tarinfo.name = buf[0:100].rstrip(NUL)
876 tarinfo.mode = nti(buf[100:108])
877 tarinfo.uid = nti(buf[108:116])
878 tarinfo.gid = nti(buf[116:124])
879 tarinfo.size = nti(buf[124:136])
880 tarinfo.mtime = nti(buf[136:148])
881 tarinfo.chksum = nti(buf[148:156])
882 tarinfo.type = buf[156:157]
883 tarinfo.linkname = buf[157:257].rstrip(NUL)
884 tarinfo.uname = buf[265:297].rstrip(NUL)
885 tarinfo.gname = buf[297:329].rstrip(NUL)
886 tarinfo.devmajor = nti(buf[329:337])
887 tarinfo.devminor = nti(buf[337:345])
888 prefix = buf[345:500].rstrip(NUL)
890 if prefix and not tarinfo.issparse():
891 tarinfo.name = prefix + "/" + tarinfo.name
893 if tarinfo.chksum not in calc_chksums(buf):
894 raise ValueError("invalid header")
895 return tarinfo
897 def tobuf(self, posix=False):
898 """Return a tar header as a string of 512 byte blocks.
900 buf = ""
901 type = self.type
902 prefix = ""
904 if self.name.endswith("/"):
905 type = DIRTYPE
907 if type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
908 # Prevent "././@LongLink" from being normalized.
909 name = self.name
910 else:
911 name = normpath(self.name)
913 if type == DIRTYPE:
914 # directories should end with '/'
915 name += "/"
917 linkname = self.linkname
918 if linkname:
919 # if linkname is empty we end up with a '.'
920 linkname = normpath(linkname)
922 if posix:
923 if self.size > MAXSIZE_MEMBER:
924 raise ValueError("file is too large (>= 8 GB)")
926 if len(self.linkname) > LENGTH_LINK:
927 raise ValueError("linkname is too long (>%d)" % (LENGTH_LINK))
929 if len(name) > LENGTH_NAME:
930 prefix = name[:LENGTH_PREFIX + 1]
931 while prefix and prefix[-1] != "/":
932 prefix = prefix[:-1]
934 name = name[len(prefix):]
935 prefix = prefix[:-1]
937 if not prefix or len(name) > LENGTH_NAME:
938 raise ValueError("name is too long")
940 else:
941 if len(self.linkname) > LENGTH_LINK:
942 buf += self._create_gnulong(self.linkname, GNUTYPE_LONGLINK)
944 if len(name) > LENGTH_NAME:
945 buf += self._create_gnulong(name, GNUTYPE_LONGNAME)
947 parts = [
948 stn(name, 100),
949 itn(self.mode & 07777, 8, posix),
950 itn(self.uid, 8, posix),
951 itn(self.gid, 8, posix),
952 itn(self.size, 12, posix),
953 itn(self.mtime, 12, posix),
954 " ", # checksum field
955 type,
956 stn(self.linkname, 100),
957 stn(MAGIC, 6),
958 stn(VERSION, 2),
959 stn(self.uname, 32),
960 stn(self.gname, 32),
961 itn(self.devmajor, 8, posix),
962 itn(self.devminor, 8, posix),
963 stn(prefix, 155)
966 buf += struct.pack("%ds" % BLOCKSIZE, "".join(parts))
967 chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
968 buf = buf[:-364] + "%06o\0" % chksum + buf[-357:]
969 self.buf = buf
970 return buf
972 def _create_gnulong(self, name, type):
973 """Create a GNU longname/longlink header from name.
974 It consists of an extended tar header, with the length
975 of the longname as size, followed by data blocks,
976 which contain the longname as a null terminated string.
978 name += NUL
980 tarinfo = self.__class__()
981 tarinfo.name = "././@LongLink"
982 tarinfo.type = type
983 tarinfo.mode = 0
984 tarinfo.size = len(name)
986 # create extended header
987 buf = tarinfo.tobuf()
988 # create name blocks
989 buf += name
990 blocks, remainder = divmod(len(name), BLOCKSIZE)
991 if remainder > 0:
992 buf += (BLOCKSIZE - remainder) * NUL
993 return buf
995 def isreg(self):
996 return self.type in REGULAR_TYPES
997 def isfile(self):
998 return self.isreg()
999 def isdir(self):
1000 return self.type == DIRTYPE
1001 def issym(self):
1002 return self.type == SYMTYPE
1003 def islnk(self):
1004 return self.type == LNKTYPE
1005 def ischr(self):
1006 return self.type == CHRTYPE
1007 def isblk(self):
1008 return self.type == BLKTYPE
1009 def isfifo(self):
1010 return self.type == FIFOTYPE
1011 def issparse(self):
1012 return self.type == GNUTYPE_SPARSE
1013 def isdev(self):
1014 return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
1015 # class TarInfo
1017 class TarFile(object):
1018 """The TarFile Class provides an interface to tar archives.
1021 debug = 0 # May be set from 0 (no msgs) to 3 (all msgs)
1023 dereference = False # If true, add content of linked file to the
1024 # tar file, else the link.
1026 ignore_zeros = False # If true, skips empty or invalid blocks and
1027 # continues processing.
1029 errorlevel = 0 # If 0, fatal errors only appear in debug
1030 # messages (if debug >= 0). If > 0, errors
1031 # are passed to the caller as exceptions.
1033 posix = False # If True, generates POSIX.1-1990-compliant
1034 # archives (no GNU extensions!)
1036 fileobject = ExFileObject
1038 def __init__(self, name=None, mode="r", fileobj=None):
1039 """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
1040 read from an existing archive, 'a' to append data to an existing
1041 file or 'w' to create a new file overwriting an existing one. `mode'
1042 defaults to 'r'.
1043 If `fileobj' is given, it is used for reading or writing data. If it
1044 can be determined, `mode' is overridden by `fileobj's mode.
1045 `fileobj' is not closed, when TarFile is closed.
1047 self.name = os.path.abspath(name)
1049 if len(mode) > 1 or mode not in "raw":
1050 raise ValueError("mode must be 'r', 'a' or 'w'")
1051 self._mode = mode
1052 self.mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]
1054 if not fileobj:
1055 fileobj = file(self.name, self.mode)
1056 self._extfileobj = False
1057 else:
1058 if self.name is None and hasattr(fileobj, "name"):
1059 self.name = os.path.abspath(fileobj.name)
1060 if hasattr(fileobj, "mode"):
1061 self.mode = fileobj.mode
1062 self._extfileobj = True
1063 self.fileobj = fileobj
1065 # Init datastructures
1066 self.closed = False
1067 self.members = [] # list of members as TarInfo objects
1068 self._loaded = False # flag if all members have been read
1069 self.offset = 0L # current position in the archive file
1070 self.inodes = {} # dictionary caching the inodes of
1071 # archive members already added
1073 if self._mode == "r":
1074 self.firstmember = None
1075 self.firstmember = self.next()
1077 if self._mode == "a":
1078 # Move to the end of the archive,
1079 # before the first empty block.
1080 self.firstmember = None
1081 while True:
1082 try:
1083 tarinfo = self.next()
1084 except ReadError:
1085 self.fileobj.seek(0)
1086 break
1087 if tarinfo is None:
1088 self.fileobj.seek(- BLOCKSIZE, 1)
1089 break
1091 if self._mode in "aw":
1092 self._loaded = True
1094 #--------------------------------------------------------------------------
1095 # Below are the classmethods which act as alternate constructors to the
1096 # TarFile class. The open() method is the only one that is needed for
1097 # public use; it is the "super"-constructor and is able to select an
1098 # adequate "sub"-constructor for a particular compression using the mapping
1099 # from OPEN_METH.
1101 # This concept allows one to subclass TarFile without losing the comfort of
1102 # the super-constructor. A sub-constructor is registered and made available
1103 # by adding it to the mapping in OPEN_METH.
1105 @classmethod
1106 def open(cls, name=None, mode="r", fileobj=None, bufsize=20*512):
1107 """Open a tar archive for reading, writing or appending. Return
1108 an appropriate TarFile class.
1110 mode:
1111 'r' or 'r:*' open for reading with transparent compression
1112 'r:' open for reading exclusively uncompressed
1113 'r:gz' open for reading with gzip compression
1114 'r:bz2' open for reading with bzip2 compression
1115 'a' or 'a:' open for appending
1116 'w' or 'w:' open for writing without compression
1117 'w:gz' open for writing with gzip compression
1118 'w:bz2' open for writing with bzip2 compression
1120 'r|*' open a stream of tar blocks with transparent compression
1121 'r|' open an uncompressed stream of tar blocks for reading
1122 'r|gz' open a gzip compressed stream of tar blocks
1123 'r|bz2' open a bzip2 compressed stream of tar blocks
1124 'w|' open an uncompressed stream for writing
1125 'w|gz' open a gzip compressed stream for writing
1126 'w|bz2' open a bzip2 compressed stream for writing
1129 if not name and not fileobj:
1130 raise ValueError("nothing to open")
1132 if mode in ("r", "r:*"):
1133 # Find out which *open() is appropriate for opening the file.
1134 for comptype in cls.OPEN_METH:
1135 func = getattr(cls, cls.OPEN_METH[comptype])
1136 if fileobj is not None:
1137 saved_pos = fileobj.tell()
1138 try:
1139 return func(name, "r", fileobj)
1140 except (ReadError, CompressionError):
1141 if fileobj is not None:
1142 fileobj.seek(saved_pos)
1143 continue
1144 raise ReadError("file could not be opened successfully")
1146 elif ":" in mode:
1147 filemode, comptype = mode.split(":", 1)
1148 filemode = filemode or "r"
1149 comptype = comptype or "tar"
1151 # Select the *open() function according to
1152 # given compression.
1153 if comptype in cls.OPEN_METH:
1154 func = getattr(cls, cls.OPEN_METH[comptype])
1155 else:
1156 raise CompressionError("unknown compression type %r" % comptype)
1157 return func(name, filemode, fileobj)
1159 elif "|" in mode:
1160 filemode, comptype = mode.split("|", 1)
1161 filemode = filemode or "r"
1162 comptype = comptype or "tar"
1164 if filemode not in "rw":
1165 raise ValueError("mode must be 'r' or 'w'")
1167 t = cls(name, filemode,
1168 _Stream(name, filemode, comptype, fileobj, bufsize))
1169 t._extfileobj = False
1170 return t
1172 elif mode in "aw":
1173 return cls.taropen(name, mode, fileobj)
1175 raise ValueError("undiscernible mode")
1177 @classmethod
1178 def taropen(cls, name, mode="r", fileobj=None):
1179 """Open uncompressed tar archive name for reading or writing.
1181 if len(mode) > 1 or mode not in "raw":
1182 raise ValueError("mode must be 'r', 'a' or 'w'")
1183 return cls(name, mode, fileobj)
1185 @classmethod
1186 def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9):
1187 """Open gzip compressed tar archive name for reading or writing.
1188 Appending is not allowed.
1190 if len(mode) > 1 or mode not in "rw":
1191 raise ValueError("mode must be 'r' or 'w'")
1193 try:
1194 import gzip
1195 gzip.GzipFile
1196 except (ImportError, AttributeError):
1197 raise CompressionError("gzip module is not available")
1199 if fileobj is None:
1200 fileobj = file(name, mode + "b")
1202 try:
1203 t = cls.taropen(name, mode,
1204 gzip.GzipFile(name, mode, compresslevel, fileobj))
1205 except IOError:
1206 raise ReadError("not a gzip file")
1207 t._extfileobj = False
1208 return t
1210 @classmethod
1211 def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9):
1212 """Open bzip2 compressed tar archive name for reading or writing.
1213 Appending is not allowed.
1215 if len(mode) > 1 or mode not in "rw":
1216 raise ValueError("mode must be 'r' or 'w'.")
1218 try:
1219 import bz2
1220 except ImportError:
1221 raise CompressionError("bz2 module is not available")
1223 if fileobj is not None:
1224 fileobj = _BZ2Proxy(fileobj, mode)
1225 else:
1226 fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel)
1228 try:
1229 t = cls.taropen(name, mode, fileobj)
1230 except IOError:
1231 raise ReadError("not a bzip2 file")
1232 t._extfileobj = False
1233 return t
1235 # All *open() methods are registered here.
1236 OPEN_METH = {
1237 "tar": "taropen", # uncompressed tar
1238 "gz": "gzopen", # gzip compressed tar
1239 "bz2": "bz2open" # bzip2 compressed tar
1242 #--------------------------------------------------------------------------
1243 # The public methods which TarFile provides:
1245 def close(self):
1246 """Close the TarFile. In write-mode, two finishing zero blocks are
1247 appended to the archive.
1249 if self.closed:
1250 return
1252 if self._mode in "aw":
1253 self.fileobj.write(NUL * (BLOCKSIZE * 2))
1254 self.offset += (BLOCKSIZE * 2)
1255 # fill up the end with zero-blocks
1256 # (like option -b20 for tar does)
1257 blocks, remainder = divmod(self.offset, RECORDSIZE)
1258 if remainder > 0:
1259 self.fileobj.write(NUL * (RECORDSIZE - remainder))
1261 if not self._extfileobj:
1262 self.fileobj.close()
1263 self.closed = True
1265 def getmember(self, name):
1266 """Return a TarInfo object for member `name'. If `name' can not be
1267 found in the archive, KeyError is raised. If a member occurs more
1268 than once in the archive, its last occurence is assumed to be the
1269 most up-to-date version.
1271 tarinfo = self._getmember(name)
1272 if tarinfo is None:
1273 raise KeyError("filename %r not found" % name)
1274 return tarinfo
1276 def getmembers(self):
1277 """Return the members of the archive as a list of TarInfo objects. The
1278 list has the same order as the members in the archive.
1280 self._check()
1281 if not self._loaded: # if we want to obtain a list of
1282 self._load() # all members, we first have to
1283 # scan the whole archive.
1284 return self.members
1286 def getnames(self):
1287 """Return the members of the archive as a list of their names. It has
1288 the same order as the list returned by getmembers().
1290 return [tarinfo.name for tarinfo in self.getmembers()]
1292 def gettarinfo(self, name=None, arcname=None, fileobj=None):
1293 """Create a TarInfo object for either the file `name' or the file
1294 object `fileobj' (using os.fstat on its file descriptor). You can
1295 modify some of the TarInfo's attributes before you add it using
1296 addfile(). If given, `arcname' specifies an alternative name for the
1297 file in the archive.
1299 self._check("aw")
1301 # When fileobj is given, replace name by
1302 # fileobj's real name.
1303 if fileobj is not None:
1304 name = fileobj.name
1306 # Building the name of the member in the archive.
1307 # Backward slashes are converted to forward slashes,
1308 # Absolute paths are turned to relative paths.
1309 if arcname is None:
1310 arcname = name
1311 arcname = normpath(arcname)
1312 drv, arcname = os.path.splitdrive(arcname)
1313 while arcname[0:1] == "/":
1314 arcname = arcname[1:]
1316 # Now, fill the TarInfo object with
1317 # information specific for the file.
1318 tarinfo = TarInfo()
1320 # Use os.stat or os.lstat, depending on platform
1321 # and if symlinks shall be resolved.
1322 if fileobj is None:
1323 if hasattr(os, "lstat") and not self.dereference:
1324 statres = os.lstat(name)
1325 else:
1326 statres = os.stat(name)
1327 else:
1328 statres = os.fstat(fileobj.fileno())
1329 linkname = ""
1331 stmd = statres.st_mode
1332 if stat.S_ISREG(stmd):
1333 inode = (statres.st_ino, statres.st_dev)
1334 if not self.dereference and \
1335 statres.st_nlink > 1 and inode in self.inodes:
1336 # Is it a hardlink to an already
1337 # archived file?
1338 type = LNKTYPE
1339 linkname = self.inodes[inode]
1340 else:
1341 # The inode is added only if its valid.
1342 # For win32 it is always 0.
1343 type = REGTYPE
1344 if inode[0]:
1345 self.inodes[inode] = arcname
1346 elif stat.S_ISDIR(stmd):
1347 type = DIRTYPE
1348 if arcname[-1:] != "/":
1349 arcname += "/"
1350 elif stat.S_ISFIFO(stmd):
1351 type = FIFOTYPE
1352 elif stat.S_ISLNK(stmd):
1353 type = SYMTYPE
1354 linkname = os.readlink(name)
1355 elif stat.S_ISCHR(stmd):
1356 type = CHRTYPE
1357 elif stat.S_ISBLK(stmd):
1358 type = BLKTYPE
1359 else:
1360 return None
1362 # Fill the TarInfo object with all
1363 # information we can get.
1364 tarinfo.name = arcname
1365 tarinfo.mode = stmd
1366 tarinfo.uid = statres.st_uid
1367 tarinfo.gid = statres.st_gid
1368 if stat.S_ISREG(stmd):
1369 tarinfo.size = statres.st_size
1370 else:
1371 tarinfo.size = 0L
1372 tarinfo.mtime = statres.st_mtime
1373 tarinfo.type = type
1374 tarinfo.linkname = linkname
1375 if pwd:
1376 try:
1377 tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
1378 except KeyError:
1379 pass
1380 if grp:
1381 try:
1382 tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
1383 except KeyError:
1384 pass
1386 if type in (CHRTYPE, BLKTYPE):
1387 if hasattr(os, "major") and hasattr(os, "minor"):
1388 tarinfo.devmajor = os.major(statres.st_rdev)
1389 tarinfo.devminor = os.minor(statres.st_rdev)
1390 return tarinfo
1392 def list(self, verbose=True):
1393 """Print a table of contents to sys.stdout. If `verbose' is False, only
1394 the names of the members are printed. If it is True, an `ls -l'-like
1395 output is produced.
1397 self._check()
1399 for tarinfo in self:
1400 if verbose:
1401 print filemode(tarinfo.mode),
1402 print "%s/%s" % (tarinfo.uname or tarinfo.uid,
1403 tarinfo.gname or tarinfo.gid),
1404 if tarinfo.ischr() or tarinfo.isblk():
1405 print "%10s" % ("%d,%d" \
1406 % (tarinfo.devmajor, tarinfo.devminor)),
1407 else:
1408 print "%10d" % tarinfo.size,
1409 print "%d-%02d-%02d %02d:%02d:%02d" \
1410 % time.localtime(tarinfo.mtime)[:6],
1412 print tarinfo.name,
1414 if verbose:
1415 if tarinfo.issym():
1416 print "->", tarinfo.linkname,
1417 if tarinfo.islnk():
1418 print "link to", tarinfo.linkname,
1419 print
1421 def add(self, name, arcname=None, recursive=True):
1422 """Add the file `name' to the archive. `name' may be any type of file
1423 (directory, fifo, symbolic link, etc.). If given, `arcname'
1424 specifies an alternative name for the file in the archive.
1425 Directories are added recursively by default. This can be avoided by
1426 setting `recursive' to False.
1428 self._check("aw")
1430 if arcname is None:
1431 arcname = name
1433 # Skip if somebody tries to archive the archive...
1434 if self.name is not None and os.path.abspath(name) == self.name:
1435 self._dbg(2, "tarfile: Skipped %r" % name)
1436 return
1438 # Special case: The user wants to add the current
1439 # working directory.
1440 if name == ".":
1441 if recursive:
1442 if arcname == ".":
1443 arcname = ""
1444 for f in os.listdir("."):
1445 self.add(f, os.path.join(arcname, f))
1446 return
1448 self._dbg(1, name)
1450 # Create a TarInfo object from the file.
1451 tarinfo = self.gettarinfo(name, arcname)
1453 if tarinfo is None:
1454 self._dbg(1, "tarfile: Unsupported type %r" % name)
1455 return
1457 # Append the tar header and data to the archive.
1458 if tarinfo.isreg():
1459 f = file(name, "rb")
1460 self.addfile(tarinfo, f)
1461 f.close()
1463 elif tarinfo.isdir():
1464 self.addfile(tarinfo)
1465 if recursive:
1466 for f in os.listdir(name):
1467 self.add(os.path.join(name, f), os.path.join(arcname, f))
1469 else:
1470 self.addfile(tarinfo)
1472 def addfile(self, tarinfo, fileobj=None):
1473 """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
1474 given, tarinfo.size bytes are read from it and added to the archive.
1475 You can create TarInfo objects using gettarinfo().
1476 On Windows platforms, `fileobj' should always be opened with mode
1477 'rb' to avoid irritation about the file size.
1479 self._check("aw")
1481 tarinfo = copy.copy(tarinfo)
1483 buf = tarinfo.tobuf(self.posix)
1484 self.fileobj.write(buf)
1485 self.offset += len(buf)
1487 # If there's data to follow, append it.
1488 if fileobj is not None:
1489 copyfileobj(fileobj, self.fileobj, tarinfo.size)
1490 blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
1491 if remainder > 0:
1492 self.fileobj.write(NUL * (BLOCKSIZE - remainder))
1493 blocks += 1
1494 self.offset += blocks * BLOCKSIZE
1496 self.members.append(tarinfo)
1498 def extractall(self, path=".", members=None):
1499 """Extract all members from the archive to the current working
1500 directory and set owner, modification time and permissions on
1501 directories afterwards. `path' specifies a different directory
1502 to extract to. `members' is optional and must be a subset of the
1503 list returned by getmembers().
1505 directories = []
1507 if members is None:
1508 members = self
1510 for tarinfo in members:
1511 if tarinfo.isdir():
1512 # Extract directory with a safe mode, so that
1513 # all files below can be extracted as well.
1514 try:
1515 os.makedirs(os.path.join(path, tarinfo.name), 0777)
1516 except EnvironmentError:
1517 pass
1518 directories.append(tarinfo)
1519 else:
1520 self.extract(tarinfo, path)
1522 # Reverse sort directories.
1523 directories.sort(lambda a, b: cmp(a.name, b.name))
1524 directories.reverse()
1526 # Set correct owner, mtime and filemode on directories.
1527 for tarinfo in directories:
1528 path = os.path.join(path, tarinfo.name)
1529 try:
1530 self.chown(tarinfo, path)
1531 self.utime(tarinfo, path)
1532 self.chmod(tarinfo, path)
1533 except ExtractError, e:
1534 if self.errorlevel > 1:
1535 raise
1536 else:
1537 self._dbg(1, "tarfile: %s" % e)
1539 def extract(self, member, path=""):
1540 """Extract a member from the archive to the current working directory,
1541 using its full name. Its file information is extracted as accurately
1542 as possible. `member' may be a filename or a TarInfo object. You can
1543 specify a different directory using `path'.
1545 self._check("r")
1547 if isinstance(member, TarInfo):
1548 tarinfo = member
1549 else:
1550 tarinfo = self.getmember(member)
1552 # Prepare the link target for makelink().
1553 if tarinfo.islnk():
1554 tarinfo._link_target = os.path.join(path, tarinfo.linkname)
1556 try:
1557 self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
1558 except EnvironmentError, e:
1559 if self.errorlevel > 0:
1560 raise
1561 else:
1562 if e.filename is None:
1563 self._dbg(1, "tarfile: %s" % e.strerror)
1564 else:
1565 self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
1566 except ExtractError, e:
1567 if self.errorlevel > 1:
1568 raise
1569 else:
1570 self._dbg(1, "tarfile: %s" % e)
1572 def extractfile(self, member):
1573 """Extract a member from the archive as a file object. `member' may be
1574 a filename or a TarInfo object. If `member' is a regular file, a
1575 file-like object is returned. If `member' is a link, a file-like
1576 object is constructed from the link's target. If `member' is none of
1577 the above, None is returned.
1578 The file-like object is read-only and provides the following
1579 methods: read(), readline(), readlines(), seek() and tell()
1581 self._check("r")
1583 if isinstance(member, TarInfo):
1584 tarinfo = member
1585 else:
1586 tarinfo = self.getmember(member)
1588 if tarinfo.isreg():
1589 return self.fileobject(self, tarinfo)
1591 elif tarinfo.type not in SUPPORTED_TYPES:
1592 # If a member's type is unknown, it is treated as a
1593 # regular file.
1594 return self.fileobject(self, tarinfo)
1596 elif tarinfo.islnk() or tarinfo.issym():
1597 if isinstance(self.fileobj, _Stream):
1598 # A small but ugly workaround for the case that someone tries
1599 # to extract a (sym)link as a file-object from a non-seekable
1600 # stream of tar blocks.
1601 raise StreamError("cannot extract (sym)link as file object")
1602 else:
1603 # A (sym)link's file object is its target's file object.
1604 return self.extractfile(self._getmember(tarinfo.linkname,
1605 tarinfo))
1606 else:
1607 # If there's no data associated with the member (directory, chrdev,
1608 # blkdev, etc.), return None instead of a file object.
1609 return None
1611 def _extract_member(self, tarinfo, targetpath):
1612 """Extract the TarInfo object tarinfo to a physical
1613 file called targetpath.
1615 # Fetch the TarInfo object for the given name
1616 # and build the destination pathname, replacing
1617 # forward slashes to platform specific separators.
1618 if targetpath[-1:] == "/":
1619 targetpath = targetpath[:-1]
1620 targetpath = os.path.normpath(targetpath)
1622 # Create all upper directories.
1623 upperdirs = os.path.dirname(targetpath)
1624 if upperdirs and not os.path.exists(upperdirs):
1625 ti = TarInfo()
1626 ti.name = upperdirs
1627 ti.type = DIRTYPE
1628 ti.mode = 0777
1629 ti.mtime = tarinfo.mtime
1630 ti.uid = tarinfo.uid
1631 ti.gid = tarinfo.gid
1632 ti.uname = tarinfo.uname
1633 ti.gname = tarinfo.gname
1634 try:
1635 self._extract_member(ti, ti.name)
1636 except:
1637 pass
1639 if tarinfo.islnk() or tarinfo.issym():
1640 self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
1641 else:
1642 self._dbg(1, tarinfo.name)
1644 if tarinfo.isreg():
1645 self.makefile(tarinfo, targetpath)
1646 elif tarinfo.isdir():
1647 self.makedir(tarinfo, targetpath)
1648 elif tarinfo.isfifo():
1649 self.makefifo(tarinfo, targetpath)
1650 elif tarinfo.ischr() or tarinfo.isblk():
1651 self.makedev(tarinfo, targetpath)
1652 elif tarinfo.islnk() or tarinfo.issym():
1653 self.makelink(tarinfo, targetpath)
1654 elif tarinfo.type not in SUPPORTED_TYPES:
1655 self.makeunknown(tarinfo, targetpath)
1656 else:
1657 self.makefile(tarinfo, targetpath)
1659 self.chown(tarinfo, targetpath)
1660 if not tarinfo.issym():
1661 self.chmod(tarinfo, targetpath)
1662 self.utime(tarinfo, targetpath)
1664 #--------------------------------------------------------------------------
1665 # Below are the different file methods. They are called via
1666 # _extract_member() when extract() is called. They can be replaced in a
1667 # subclass to implement other functionality.
1669 def makedir(self, tarinfo, targetpath):
1670 """Make a directory called targetpath.
1672 try:
1673 os.mkdir(targetpath)
1674 except EnvironmentError, e:
1675 if e.errno != errno.EEXIST:
1676 raise
1678 def makefile(self, tarinfo, targetpath):
1679 """Make a file called targetpath.
1681 source = self.extractfile(tarinfo)
1682 target = file(targetpath, "wb")
1683 copyfileobj(source, target)
1684 source.close()
1685 target.close()
1687 def makeunknown(self, tarinfo, targetpath):
1688 """Make a file from a TarInfo object with an unknown type
1689 at targetpath.
1691 self.makefile(tarinfo, targetpath)
1692 self._dbg(1, "tarfile: Unknown file type %r, " \
1693 "extracted as regular file." % tarinfo.type)
1695 def makefifo(self, tarinfo, targetpath):
1696 """Make a fifo called targetpath.
1698 if hasattr(os, "mkfifo"):
1699 os.mkfifo(targetpath)
1700 else:
1701 raise ExtractError("fifo not supported by system")
1703 def makedev(self, tarinfo, targetpath):
1704 """Make a character or block device called targetpath.
1706 if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
1707 raise ExtractError("special devices not supported by system")
1709 mode = tarinfo.mode
1710 if tarinfo.isblk():
1711 mode |= stat.S_IFBLK
1712 else:
1713 mode |= stat.S_IFCHR
1715 os.mknod(targetpath, mode,
1716 os.makedev(tarinfo.devmajor, tarinfo.devminor))
1718 def makelink(self, tarinfo, targetpath):
1719 """Make a (symbolic) link called targetpath. If it cannot be created
1720 (platform limitation), we try to make a copy of the referenced file
1721 instead of a link.
1723 linkpath = tarinfo.linkname
1724 try:
1725 if tarinfo.issym():
1726 os.symlink(linkpath, targetpath)
1727 else:
1728 # See extract().
1729 os.link(tarinfo._link_target, targetpath)
1730 except AttributeError:
1731 if tarinfo.issym():
1732 linkpath = os.path.join(os.path.dirname(tarinfo.name),
1733 linkpath)
1734 linkpath = normpath(linkpath)
1736 try:
1737 self._extract_member(self.getmember(linkpath), targetpath)
1738 except (EnvironmentError, KeyError), e:
1739 linkpath = os.path.normpath(linkpath)
1740 try:
1741 shutil.copy2(linkpath, targetpath)
1742 except EnvironmentError, e:
1743 raise IOError("link could not be created")
1745 def chown(self, tarinfo, targetpath):
1746 """Set owner of targetpath according to tarinfo.
1748 if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
1749 # We have to be root to do so.
1750 try:
1751 g = grp.getgrnam(tarinfo.gname)[2]
1752 except KeyError:
1753 try:
1754 g = grp.getgrgid(tarinfo.gid)[2]
1755 except KeyError:
1756 g = os.getgid()
1757 try:
1758 u = pwd.getpwnam(tarinfo.uname)[2]
1759 except KeyError:
1760 try:
1761 u = pwd.getpwuid(tarinfo.uid)[2]
1762 except KeyError:
1763 u = os.getuid()
1764 try:
1765 if tarinfo.issym() and hasattr(os, "lchown"):
1766 os.lchown(targetpath, u, g)
1767 else:
1768 if sys.platform != "os2emx":
1769 os.chown(targetpath, u, g)
1770 except EnvironmentError, e:
1771 raise ExtractError("could not change owner")
1773 def chmod(self, tarinfo, targetpath):
1774 """Set file permissions of targetpath according to tarinfo.
1776 if hasattr(os, 'chmod'):
1777 try:
1778 os.chmod(targetpath, tarinfo.mode)
1779 except EnvironmentError, e:
1780 raise ExtractError("could not change mode")
1782 def utime(self, tarinfo, targetpath):
1783 """Set modification time of targetpath according to tarinfo.
1785 if not hasattr(os, 'utime'):
1786 return
1787 if sys.platform == "win32" and tarinfo.isdir():
1788 # According to msdn.microsoft.com, it is an error (EACCES)
1789 # to use utime() on directories.
1790 return
1791 try:
1792 os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
1793 except EnvironmentError, e:
1794 raise ExtractError("could not change modification time")
1796 #--------------------------------------------------------------------------
1797 def next(self):
1798 """Return the next member of the archive as a TarInfo object, when
1799 TarFile is opened for reading. Return None if there is no more
1800 available.
1802 self._check("ra")
1803 if self.firstmember is not None:
1804 m = self.firstmember
1805 self.firstmember = None
1806 return m
1808 # Read the next block.
1809 self.fileobj.seek(self.offset)
1810 while True:
1811 buf = self.fileobj.read(BLOCKSIZE)
1812 if not buf:
1813 return None
1815 try:
1816 tarinfo = TarInfo.frombuf(buf)
1818 # Set the TarInfo object's offset to the current position of the
1819 # TarFile and set self.offset to the position where the data blocks
1820 # should begin.
1821 tarinfo.offset = self.offset
1822 self.offset += BLOCKSIZE
1824 tarinfo = self.proc_member(tarinfo)
1826 except ValueError, e:
1827 if self.ignore_zeros:
1828 self._dbg(2, "0x%X: empty or invalid block: %s" %
1829 (self.offset, e))
1830 self.offset += BLOCKSIZE
1831 continue
1832 else:
1833 if self.offset == 0:
1834 raise ReadError("empty, unreadable or compressed "
1835 "file: %s" % e)
1836 return None
1837 break
1839 # Some old tar programs represent a directory as a regular
1840 # file with a trailing slash.
1841 if tarinfo.isreg() and tarinfo.name.endswith("/"):
1842 tarinfo.type = DIRTYPE
1844 # Directory names should have a '/' at the end.
1845 if tarinfo.isdir():
1846 tarinfo.name += "/"
1848 self.members.append(tarinfo)
1849 return tarinfo
1851 #--------------------------------------------------------------------------
1852 # The following are methods that are called depending on the type of a
1853 # member. The entry point is proc_member() which is called with a TarInfo
1854 # object created from the header block from the current offset. The
1855 # proc_member() method can be overridden in a subclass to add custom
1856 # proc_*() methods. A proc_*() method MUST implement the following
1857 # operations:
1858 # 1. Set tarinfo.offset_data to the position where the data blocks begin,
1859 # if there is data that follows.
1860 # 2. Set self.offset to the position where the next member's header will
1861 # begin.
1862 # 3. Return tarinfo or another valid TarInfo object.
1863 def proc_member(self, tarinfo):
1864 """Choose the right processing method for tarinfo depending
1865 on its type and call it.
1867 if tarinfo.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
1868 return self.proc_gnulong(tarinfo)
1869 elif tarinfo.type == GNUTYPE_SPARSE:
1870 return self.proc_sparse(tarinfo)
1871 else:
1872 return self.proc_builtin(tarinfo)
1874 def proc_builtin(self, tarinfo):
1875 """Process a builtin type member or an unknown member
1876 which will be treated as a regular file.
1878 tarinfo.offset_data = self.offset
1879 if tarinfo.isreg() or tarinfo.type not in SUPPORTED_TYPES:
1880 # Skip the following data blocks.
1881 self.offset += self._block(tarinfo.size)
1882 return tarinfo
1884 def proc_gnulong(self, tarinfo):
1885 """Process the blocks that hold a GNU longname
1886 or longlink member.
1888 buf = ""
1889 count = tarinfo.size
1890 while count > 0:
1891 block = self.fileobj.read(BLOCKSIZE)
1892 buf += block
1893 self.offset += BLOCKSIZE
1894 count -= BLOCKSIZE
1896 # Fetch the next header and process it.
1897 b = self.fileobj.read(BLOCKSIZE)
1898 t = TarInfo.frombuf(b)
1899 t.offset = self.offset
1900 self.offset += BLOCKSIZE
1901 next = self.proc_member(t)
1903 # Patch the TarInfo object from the next header with
1904 # the longname information.
1905 next.offset = tarinfo.offset
1906 if tarinfo.type == GNUTYPE_LONGNAME:
1907 next.name = buf.rstrip(NUL)
1908 elif tarinfo.type == GNUTYPE_LONGLINK:
1909 next.linkname = buf.rstrip(NUL)
1911 return next
1913 def proc_sparse(self, tarinfo):
1914 """Process a GNU sparse header plus extra headers.
1916 buf = tarinfo.buf
1917 sp = _ringbuffer()
1918 pos = 386
1919 lastpos = 0L
1920 realpos = 0L
1921 # There are 4 possible sparse structs in the
1922 # first header.
1923 for i in xrange(4):
1924 try:
1925 offset = nti(buf[pos:pos + 12])
1926 numbytes = nti(buf[pos + 12:pos + 24])
1927 except ValueError:
1928 break
1929 if offset > lastpos:
1930 sp.append(_hole(lastpos, offset - lastpos))
1931 sp.append(_data(offset, numbytes, realpos))
1932 realpos += numbytes
1933 lastpos = offset + numbytes
1934 pos += 24
1936 isextended = ord(buf[482])
1937 origsize = nti(buf[483:495])
1939 # If the isextended flag is given,
1940 # there are extra headers to process.
1941 while isextended == 1:
1942 buf = self.fileobj.read(BLOCKSIZE)
1943 self.offset += BLOCKSIZE
1944 pos = 0
1945 for i in xrange(21):
1946 try:
1947 offset = nti(buf[pos:pos + 12])
1948 numbytes = nti(buf[pos + 12:pos + 24])
1949 except ValueError:
1950 break
1951 if offset > lastpos:
1952 sp.append(_hole(lastpos, offset - lastpos))
1953 sp.append(_data(offset, numbytes, realpos))
1954 realpos += numbytes
1955 lastpos = offset + numbytes
1956 pos += 24
1957 isextended = ord(buf[504])
1959 if lastpos < origsize:
1960 sp.append(_hole(lastpos, origsize - lastpos))
1962 tarinfo.sparse = sp
1964 tarinfo.offset_data = self.offset
1965 self.offset += self._block(tarinfo.size)
1966 tarinfo.size = origsize
1968 return tarinfo
1970 #--------------------------------------------------------------------------
1971 # Little helper methods:
1973 def _block(self, count):
1974 """Round up a byte count by BLOCKSIZE and return it,
1975 e.g. _block(834) => 1024.
1977 blocks, remainder = divmod(count, BLOCKSIZE)
1978 if remainder:
1979 blocks += 1
1980 return blocks * BLOCKSIZE
1982 def _getmember(self, name, tarinfo=None):
1983 """Find an archive member by name from bottom to top.
1984 If tarinfo is given, it is used as the starting point.
1986 # Ensure that all members have been loaded.
1987 members = self.getmembers()
1989 if tarinfo is None:
1990 end = len(members)
1991 else:
1992 end = members.index(tarinfo)
1994 for i in xrange(end - 1, -1, -1):
1995 if name == members[i].name:
1996 return members[i]
1998 def _load(self):
1999 """Read through the entire archive file and look for readable
2000 members.
2002 while True:
2003 tarinfo = self.next()
2004 if tarinfo is None:
2005 break
2006 self._loaded = True
2008 def _check(self, mode=None):
2009 """Check if TarFile is still open, and if the operation's mode
2010 corresponds to TarFile's mode.
2012 if self.closed:
2013 raise IOError("%s is closed" % self.__class__.__name__)
2014 if mode is not None and self._mode not in mode:
2015 raise IOError("bad operation for mode %r" % self._mode)
2017 def __iter__(self):
2018 """Provide an iterator object.
2020 if self._loaded:
2021 return iter(self.members)
2022 else:
2023 return TarIter(self)
2025 def _dbg(self, level, msg):
2026 """Write debugging output to sys.stderr.
2028 if level <= self.debug:
2029 print >> sys.stderr, msg
2030 # class TarFile
2032 class TarIter:
2033 """Iterator Class.
2035 for tarinfo in TarFile(...):
2036 suite...
2039 def __init__(self, tarfile):
2040 """Construct a TarIter object.
2042 self.tarfile = tarfile
2043 self.index = 0
2044 def __iter__(self):
2045 """Return iterator object.
2047 return self
2048 def next(self):
2049 """Return the next item using TarFile's next() method.
2050 When all members have been read, set TarFile as _loaded.
2052 # Fix for SF #1100429: Under rare circumstances it can
2053 # happen that getmembers() is called during iteration,
2054 # which will cause TarIter to stop prematurely.
2055 if not self.tarfile._loaded:
2056 tarinfo = self.tarfile.next()
2057 if not tarinfo:
2058 self.tarfile._loaded = True
2059 raise StopIteration
2060 else:
2061 try:
2062 tarinfo = self.tarfile.members[self.index]
2063 except IndexError:
2064 raise StopIteration
2065 self.index += 1
2066 return tarinfo
2068 # Helper classes for sparse file support
2069 class _section:
2070 """Base class for _data and _hole.
2072 def __init__(self, offset, size):
2073 self.offset = offset
2074 self.size = size
2075 def __contains__(self, offset):
2076 return self.offset <= offset < self.offset + self.size
2078 class _data(_section):
2079 """Represent a data section in a sparse file.
2081 def __init__(self, offset, size, realpos):
2082 _section.__init__(self, offset, size)
2083 self.realpos = realpos
2085 class _hole(_section):
2086 """Represent a hole section in a sparse file.
2088 pass
2090 class _ringbuffer(list):
2091 """Ringbuffer class which increases performance
2092 over a regular list.
2094 def __init__(self):
2095 self.idx = 0
2096 def find(self, offset):
2097 idx = self.idx
2098 while True:
2099 item = self[idx]
2100 if offset in item:
2101 break
2102 idx += 1
2103 if idx == len(self):
2104 idx = 0
2105 if idx == self.idx:
2106 # End of File
2107 return None
2108 self.idx = idx
2109 return item
2111 #---------------------------------------------
2112 # zipfile compatible TarFile class
2113 #---------------------------------------------
2114 TAR_PLAIN = 0 # zipfile.ZIP_STORED
2115 TAR_GZIPPED = 8 # zipfile.ZIP_DEFLATED
2116 class TarFileCompat:
2117 """TarFile class compatible with standard module zipfile's
2118 ZipFile class.
2120 def __init__(self, file, mode="r", compression=TAR_PLAIN):
2121 if compression == TAR_PLAIN:
2122 self.tarfile = TarFile.taropen(file, mode)
2123 elif compression == TAR_GZIPPED:
2124 self.tarfile = TarFile.gzopen(file, mode)
2125 else:
2126 raise ValueError("unknown compression constant")
2127 if mode[0:1] == "r":
2128 members = self.tarfile.getmembers()
2129 for m in members:
2130 m.filename = m.name
2131 m.file_size = m.size
2132 m.date_time = time.gmtime(m.mtime)[:6]
2133 def namelist(self):
2134 return map(lambda m: m.name, self.infolist())
2135 def infolist(self):
2136 return filter(lambda m: m.type in REGULAR_TYPES,
2137 self.tarfile.getmembers())
2138 def printdir(self):
2139 self.tarfile.list()
2140 def testzip(self):
2141 return
2142 def getinfo(self, name):
2143 return self.tarfile.getmember(name)
2144 def read(self, name):
2145 return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
2146 def write(self, filename, arcname=None, compress_type=None):
2147 self.tarfile.add(filename, arcname)
2148 def writestr(self, zinfo, bytes):
2149 try:
2150 from cStringIO import StringIO
2151 except ImportError:
2152 from StringIO import StringIO
2153 import calendar
2154 zinfo.name = zinfo.filename
2155 zinfo.size = zinfo.file_size
2156 zinfo.mtime = calendar.timegm(zinfo.date_time)
2157 self.tarfile.addfile(zinfo, StringIO(bytes))
2158 def close(self):
2159 self.tarfile.close()
2160 #class TarFileCompat
2162 #--------------------
2163 # exported functions
2164 #--------------------
2165 def is_tarfile(name):
2166 """Return True if name points to a tar archive that we
2167 are able to handle, else return False.
2169 try:
2170 t = open(name)
2171 t.close()
2172 return True
2173 except TarError:
2174 return False
2176 open = TarFile.open