"""
info["magic"] = POSIX_MAGIC
pax_headers = self.pax_headers.copy()
+ if self.ismultivol():
+ info['size'] = info['size'] - self.volume_offset
# Test string fields for values that exceed the field length or cannot
# be represented in ASCII encoding.
except HeaderError:
raise SubsequentHeaderError("missing or bad subsequent header")
-
if self.type in (XHDTYPE, SOLARIS_XHDTYPE):
# Patch the TarInfo object with the extended header info.
next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors)
offset += next._block(next.size)
tarfile.offset = offset
- if "GNU.volume.filename" in pax_headers and\
- pax_headers["GNU.volume.filename"] == next.name:
- if "GNU.volume.size" in pax_headers:
- next.size = int(pax_headers["GNU.volume.size"])
- if "GNU.volume.offset" in pax_headers:
- next.volume_offset = int(pax_headers["GNU.volume.offset"])
+ if next is not None:
+ if "GNU.volume.filename" in pax_headers:
+ if pax_headers["GNU.volume.filename"] == next.name:
+ if "GNU.volume.size" in pax_headers:
+ next.size = int(pax_headers["GNU.volume.size"])
+ if "GNU.volume.offset" in pax_headers:
+ next.volume_offset = int(pax_headers["GNU.volume.offset"])
+
+ for key in pax_headers.keys():
+ if key.startswith("GNU.volume"):
+ del tarfile.pax_headers[key]
return next
def isdev(self):
return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
def ismultivol(self):
- return self.type == GNUTYPE_MULTIVOL or self.volume_offset > 0
+ return self.type == GNUTYPE_MULTIVOL or self.volume_offset > 0 or\
+ "GNU.volume.offset" in self.pax_headers
# class TarInfo
class TarFile(object):
# handle multivolume support
if self.max_volume_size:
size_left = self._size_left()
+ # we only split volumes in the middle of a file, that means we have
+ # to write at least one block
+ if size_left < BLOCKSIZE:
+ size_left = BLOCKSIZE
max_size_to_write = min(size_left, tarinfo.size - tarinfo.volume_offset)
else:
size_left = max_size_to_write = tarinfo.size
if self.max_volume_size and max_size_to_write == size_left:
assert remainder == 0
+
self.offset += blocks * BLOCKSIZE
size_left -= blocks * BLOCKSIZE
tarinfo.volume_offset += blocks * BLOCKSIZE
# check if creating a new volume is needed
- if self.max_volume_size and size_left < BLOCKSIZE:
+ if tarinfo.volume_offset < tarinfo.size and\
+ self.max_volume_size and size_left < 3*BLOCKSIZE:
+
tarinfo.type = GNUTYPE_MULTIVOL
if not self.new_volume_handler or\
not callable(self.new_volume_handler):
- raise Exception("We need to create a new volume and you"
- " didn't supply a new_volume_handler")
+ raise Exception("We need to create a new volume and you "
+ "didn't supply a new_volume_handler")
# the new volume handler should do everything needed to
# start working in a new volume. usually, the handler calls
if self.mode in "aw":
self._loaded = True
- self.pax_headers["GNU.volume.filename"] = unicode(self.volume_tarinfo.name)
- self.pax_headers["GNU.volume.size"] = unicode(self.volume_tarinfo.size - self.volume_tarinfo.volume_offset)
- self.pax_headers["GNU.volume.offset"] = unicode(self.volume_tarinfo.volume_offset)
+ if self.format == PAX_FORMAT:
+ volume_info = {
+ "GNU.volume.filename": unicode(self.volume_tarinfo.name),
+ "GNU.volume.size": unicode(self.volume_tarinfo.size - self.volume_tarinfo.volume_offset),
+ "GNU.volume.offset": unicode(self.volume_tarinfo.volume_offset),
+ }
- buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy())
- self.fileobj.write(buf)
- self.offset += len(buf)
+ self.pax_headers.update(volume_info)
+
+ buf = self.tarinfo.create_pax_global_header(volume_info.copy())
+ self.fileobj.write(buf)
+ self.offset += len(buf)
except:
if not self._extfileobj:
self.fileobj.close()