aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/tarfile.py
diff options
context:
space:
mode:
authorJoshua Root <jmr@macports.org>2022-02-10 04:06:19 +1100
committerGitHub <noreply@github.com>2022-02-09 18:06:19 +0100
commitbf2d44ffb06e8f49aacc6b1c140a6717df5cf897 (patch)
tree3a800a1bc6bf17b549cb2d0e43ff0046835a0baa /Lib/tarfile.py
parentc0a5ebeb1239020f2ecc199053bb1a70d78841a1 (diff)
downloadcpython-bf2d44ffb06e8f49aacc6b1c140a6717df5cf897.tar.gz
cpython-bf2d44ffb06e8f49aacc6b1c140a6717df5cf897.zip
bpo-45863: tarfile: don't zero out header fields unnecessarily (GH-29693)
Numeric fields of type float, notably mtime, can't be represented exactly in the ustar header, so the pax header is used. But it is helpful to set them to the nearest int (i.e. second rather than nanosecond precision mtimes) in the ustar header as well, for the benefit of unarchivers that don't understand the pax header. Add test for tarfile.TarInfo.create_pax_header to confirm correct behaviour.
Diffstat (limited to 'Lib/tarfile.py')
-rwxr-xr-xLib/tarfile.py21
1 files changed, 15 insertions, 6 deletions
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index e7951001587..8d43d0da7b9 100755
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -888,15 +888,24 @@ class TarInfo(object):
# Test number fields for values that exceed the field limit or values
# that like to be stored as float.
for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)):
- if name in pax_headers:
- # The pax header has priority. Avoid overflow.
- info[name] = 0
- continue
+ needs_pax = False
val = info[name]
- if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float):
- pax_headers[name] = str(val)
+ val_is_float = isinstance(val, float)
+ val_int = round(val) if val_is_float else val
+ if not 0 <= val_int < 8 ** (digits - 1):
+ # Avoid overflow.
info[name] = 0
+ needs_pax = True
+ elif val_is_float:
+ # Put rounded value in ustar header, and full
+ # precision value in pax header.
+ info[name] = val_int
+ needs_pax = True
+
+ # The existing pax header has priority.
+ if needs_pax and name not in pax_headers:
+ pax_headers[name] = str(val)
# Create a pax extended header if necessary.
if pax_headers: