@@ -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