From 0a5b63559421a791083cdfadfdba2633f34f4d65 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 21 Jul 2023 12:57:08 +1000 Subject: [PATCH] utarfile: Fix read/write handling of nulls in tar header. For reading, the size is always terminated by a null, so just ignore it by using 11 for the uctypes entry (this fixes a regression introduced in 7128d423c2e7c0309ac17a1e6ba873b909b24fcc). For writing, the size must always be terminated by a null. Signed-off-by: Damien George --- micropython/utarfile-write/manifest.py | 2 +- micropython/utarfile-write/utarfile/write.py | 30 ++++++++------------ micropython/utarfile/manifest.py | 2 +- micropython/utarfile/utarfile/__init__.py | 3 +- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/micropython/utarfile-write/manifest.py b/micropython/utarfile-write/manifest.py index a0c95a46..bd120ef5 100644 --- a/micropython/utarfile-write/manifest.py +++ b/micropython/utarfile-write/manifest.py @@ -1,4 +1,4 @@ -metadata(description="Adds write (create/append) support to utarfile.", version="0.1") +metadata(description="Adds write (create/append) support to utarfile.", version="0.1.1") require("utarfile") package("utarfile") diff --git a/micropython/utarfile-write/utarfile/write.py b/micropython/utarfile-write/utarfile/write.py index 8999bd91..2bae38a5 100644 --- a/micropython/utarfile-write/utarfile/write.py +++ b/micropython/utarfile-write/utarfile/write.py @@ -11,9 +11,9 @@ import os # http://www.gnu.org/software/tar/manual/html_node/Standard.html _TAR_HEADER = { "name": (uctypes.ARRAY | 0, uctypes.UINT8 | 100), - "mode": (uctypes.ARRAY | 100, uctypes.UINT8 | 7), - "uid": (uctypes.ARRAY | 108, uctypes.UINT8 | 7), - "gid": (uctypes.ARRAY | 116, uctypes.UINT8 | 7), + "mode": (uctypes.ARRAY | 100, uctypes.UINT8 | 8), + "uid": (uctypes.ARRAY | 108, uctypes.UINT8 | 8), + "gid": (uctypes.ARRAY | 116, uctypes.UINT8 | 8), "size": (uctypes.ARRAY | 124, uctypes.UINT8 | 12), "mtime": (uctypes.ARRAY | 136, uctypes.UINT8 | 12), "chksum": (uctypes.ARRAY | 148, uctypes.UINT8 | 8), @@ -26,12 +26,6 @@ _BLOCKSIZE = const(512) # length of processing blocks _RECORDSIZE = const(_BLOCKSIZE * 20) # length of records -# Write a string into a bytearray by copying each byte. -def _setstring(b, s, maxlen): - for i, c in enumerate(s.encode("utf-8")[:maxlen]): - b[i] = c - - def _open_write(self, name, mode, fileobj): if mode == "w": if not fileobj: @@ -72,18 +66,18 @@ def addfile(self, tarinfo, fileobj=None): if not name.endswith("/"): name += "/" hdr = uctypes.struct(uctypes.addressof(buf), _TAR_HEADER, uctypes.LITTLE_ENDIAN) - _setstring(hdr.name, name, 100) - _setstring(hdr.mode, "%06o " % (tarinfo.mode & 0o7777), 7) - _setstring(hdr.uid, "%06o " % tarinfo.uid, 7) - _setstring(hdr.gid, "%06o " % tarinfo.gid, 7) - _setstring(hdr.size, "%011o " % size, 12) - _setstring(hdr.mtime, "%011o " % tarinfo.mtime, 12) - _setstring(hdr.typeflag, "5" if tarinfo.isdir() else "0", 1) + hdr.name[:] = name.encode("utf-8")[:100] + hdr.mode[:] = b"%07o\0" % (tarinfo.mode & 0o7777) + hdr.uid[:] = b"%07o\0" % tarinfo.uid + hdr.gid[:] = b"%07o\0" % tarinfo.gid + hdr.size[:] = b"%011o\0" % size + hdr.mtime[:] = b"%011o\0" % tarinfo.mtime + hdr.typeflag[:] = b"5" if tarinfo.isdir() else b"0" # Checksum is calculated with checksum field all blanks. - _setstring(hdr.chksum, " " * 8, 8) + hdr.chksum[:] = b" " # Calculate and insert the actual checksum. chksum = sum(buf) - _setstring(hdr.chksum, "%06o\0" % chksum, 7) + hdr.chksum[:] = b"%06o\0 " % chksum # Emit the header. self.f.write(buf) self.offset += len(buf) diff --git a/micropython/utarfile/manifest.py b/micropython/utarfile/manifest.py index 3e6ac576..68f88e33 100644 --- a/micropython/utarfile/manifest.py +++ b/micropython/utarfile/manifest.py @@ -1,4 +1,4 @@ -metadata(description="Read-only implementation of Python's tarfile.", version="0.4.0") +metadata(description="Read-only implementation of Python's tarfile.", version="0.4.1") # Originally written by Paul Sokolovsky. diff --git a/micropython/utarfile/utarfile/__init__.py b/micropython/utarfile/utarfile/__init__.py index 524207aa..c367b2b3 100644 --- a/micropython/utarfile/utarfile/__init__.py +++ b/micropython/utarfile/utarfile/__init__.py @@ -4,9 +4,10 @@ import uctypes # Minimal set of tar header fields for reading. # http://www.gnu.org/software/tar/manual/html_node/Standard.html +# The "size" entry is 11 (not 12) to implicitly cut off the null terminator. _TAR_HEADER = { "name": (uctypes.ARRAY | 0, uctypes.UINT8 | 100), - "size": (uctypes.ARRAY | 124, uctypes.UINT8 | 12), + "size": (uctypes.ARRAY | 124, uctypes.UINT8 | 11), } DIRTYPE = const("dir")