Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d96d101

Browse files
committed
SF #918101, allow files >= 8 GB using GNU extension
1 parent a4f651a commit d96d101

2 files changed

Lines changed: 38 additions & 11 deletions

File tree

Doc/lib/libtarfile.tex

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,12 @@ \subsection{TarFile Objects \label{tarfile-objects}}
256256
\begin{memberdesc}{posix}
257257
If true, create a \POSIX{} 1003.1-1990 compliant archive. GNU
258258
extensions are not used, because they are not part of the \POSIX{}
259-
standard. This limits the length of filenames to at most 256 and
260-
link names to 100 characters. A \exception{ValueError} is raised
261-
if a pathname exceeds this limit. If false, create a GNU tar
262-
compatible archive. It will not be \POSIX{} compliant, but can
263-
store pathnames of unlimited length.
259+
standard. This limits the length of filenames to at most 256,
260+
link names to 100 characters and the maximum file size to 8
261+
gigabytes. A \exception{ValueError} is raised if a file exceeds
262+
this limit. If false, create a GNU tar compatible archive. It
263+
will not be \POSIX{} compliant, but can store files without any
264+
of the above restrictions.
264265
\end{memberdesc}
265266

266267
\begin{memberdesc}{dereference}

Lib/tarfile.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -655,11 +655,21 @@ def frombuf(cls, buf):
655655
"""Construct a TarInfo object from a 512 byte string buffer.
656656
"""
657657
tarinfo = cls()
658-
tarinfo.name = nts(buf[0:100])
658+
tarinfo.name = nts(buf[0:100])
659659
tarinfo.mode = int(buf[100:108], 8)
660660
tarinfo.uid = int(buf[108:116],8)
661661
tarinfo.gid = int(buf[116:124],8)
662-
tarinfo.size = long(buf[124:136], 8)
662+
663+
# There are two possible codings for the size field we
664+
# have to discriminate, see comment in tobuf() below.
665+
if buf[124] != chr(0200):
666+
tarinfo.size = long(buf[124:136], 8)
667+
else:
668+
tarinfo.size = 0L
669+
for i in range(11):
670+
tarinfo.size <<= 8
671+
tarinfo.size += ord(buf[125 + i])
672+
663673
tarinfo.mtime = long(buf[136:148], 8)
664674
tarinfo.chksum = int(buf[148:156], 8)
665675
tarinfo.type = buf[156:157]
@@ -689,16 +699,28 @@ def frombuf(cls, buf):
689699
def tobuf(self):
690700
"""Return a tar header block as a 512 byte string.
691701
"""
692-
name = self.name
702+
# Prefer the size to be encoded as 11 octal ascii digits
703+
# which is the most portable. If the size exceeds this
704+
# limit (>= 8 GB), encode it as an 88-bit value which is
705+
# a GNU tar feature.
706+
if self.size <= MAXSIZE_MEMBER:
707+
size = "%011o" % self.size
708+
else:
709+
s = self.size
710+
size = ""
711+
for i in range(11):
712+
size = chr(s & 0377) + size
713+
s >>= 8
714+
size = chr(0200) + size
693715

694716
# The following code was contributed by Detlef Lannert.
695717
parts = []
696718
for value, fieldsize in (
697-
(name, 100),
719+
(self.name, 100),
698720
("%07o" % (self.mode & 07777), 8),
699721
("%07o" % self.uid, 8),
700722
("%07o" % self.gid, 8),
701-
("%011o" % self.size, 12),
723+
(size, 12),
702724
("%011o" % self.mtime, 12),
703725
(" ", 8),
704726
(self.type, 1),
@@ -1236,7 +1258,11 @@ def addfile(self, tarinfo, fileobj=None):
12361258
tarinfo.linkname = normpath(tarinfo.linkname)
12371259

12381260
if tarinfo.size > MAXSIZE_MEMBER:
1239-
raise ValueError, "file is too large (>8GB)"
1261+
if self.posix:
1262+
raise ValueError, "file is too large (>= 8 GB)"
1263+
else:
1264+
self._dbg(2, "tarfile: Created GNU tar largefile header")
1265+
12401266

12411267
if len(tarinfo.linkname) > LENGTH_LINK:
12421268
if self.posix:

0 commit comments

Comments
 (0)