Skip to content

Commit 0a5b635

Browse files
committed
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 7128d42). For writing, the size must always be terminated by a null. Signed-off-by: Damien George <[email protected]>
1 parent da5ddfc commit 0a5b635

File tree

4 files changed

+16
-21
lines changed

4 files changed

+16
-21
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
metadata(description="Adds write (create/append) support to utarfile.", version="0.1")
1+
metadata(description="Adds write (create/append) support to utarfile.", version="0.1.1")
22

33
require("utarfile")
44
package("utarfile")

micropython/utarfile-write/utarfile/write.py

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
# http://www.gnu.org/software/tar/manual/html_node/Standard.html
1212
_TAR_HEADER = {
1313
"name": (uctypes.ARRAY | 0, uctypes.UINT8 | 100),
14-
"mode": (uctypes.ARRAY | 100, uctypes.UINT8 | 7),
15-
"uid": (uctypes.ARRAY | 108, uctypes.UINT8 | 7),
16-
"gid": (uctypes.ARRAY | 116, uctypes.UINT8 | 7),
14+
"mode": (uctypes.ARRAY | 100, uctypes.UINT8 | 8),
15+
"uid": (uctypes.ARRAY | 108, uctypes.UINT8 | 8),
16+
"gid": (uctypes.ARRAY | 116, uctypes.UINT8 | 8),
1717
"size": (uctypes.ARRAY | 124, uctypes.UINT8 | 12),
1818
"mtime": (uctypes.ARRAY | 136, uctypes.UINT8 | 12),
1919
"chksum": (uctypes.ARRAY | 148, uctypes.UINT8 | 8),
@@ -26,12 +26,6 @@
2626
_RECORDSIZE = const(_BLOCKSIZE * 20) # length of records
2727

2828

29-
# Write a string into a bytearray by copying each byte.
30-
def _setstring(b, s, maxlen):
31-
for i, c in enumerate(s.encode("utf-8")[:maxlen]):
32-
b[i] = c
33-
34-
3529
def _open_write(self, name, mode, fileobj):
3630
if mode == "w":
3731
if not fileobj:
@@ -72,18 +66,18 @@ def addfile(self, tarinfo, fileobj=None):
7266
if not name.endswith("/"):
7367
name += "/"
7468
hdr = uctypes.struct(uctypes.addressof(buf), _TAR_HEADER, uctypes.LITTLE_ENDIAN)
75-
_setstring(hdr.name, name, 100)
76-
_setstring(hdr.mode, "%06o " % (tarinfo.mode & 0o7777), 7)
77-
_setstring(hdr.uid, "%06o " % tarinfo.uid, 7)
78-
_setstring(hdr.gid, "%06o " % tarinfo.gid, 7)
79-
_setstring(hdr.size, "%011o " % size, 12)
80-
_setstring(hdr.mtime, "%011o " % tarinfo.mtime, 12)
81-
_setstring(hdr.typeflag, "5" if tarinfo.isdir() else "0", 1)
69+
hdr.name[:] = name.encode("utf-8")[:100]
70+
hdr.mode[:] = b"%07o\0" % (tarinfo.mode & 0o7777)
71+
hdr.uid[:] = b"%07o\0" % tarinfo.uid
72+
hdr.gid[:] = b"%07o\0" % tarinfo.gid
73+
hdr.size[:] = b"%011o\0" % size
74+
hdr.mtime[:] = b"%011o\0" % tarinfo.mtime
75+
hdr.typeflag[:] = b"5" if tarinfo.isdir() else b"0"
8276
# Checksum is calculated with checksum field all blanks.
83-
_setstring(hdr.chksum, " " * 8, 8)
77+
hdr.chksum[:] = b" "
8478
# Calculate and insert the actual checksum.
8579
chksum = sum(buf)
86-
_setstring(hdr.chksum, "%06o\0" % chksum, 7)
80+
hdr.chksum[:] = b"%06o\0 " % chksum
8781
# Emit the header.
8882
self.f.write(buf)
8983
self.offset += len(buf)

micropython/utarfile/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
metadata(description="Read-only implementation of Python's tarfile.", version="0.4.0")
1+
metadata(description="Read-only implementation of Python's tarfile.", version="0.4.1")
22

33
# Originally written by Paul Sokolovsky.
44

micropython/utarfile/utarfile/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
# Minimal set of tar header fields for reading.
66
# http://www.gnu.org/software/tar/manual/html_node/Standard.html
7+
# The "size" entry is 11 (not 12) to implicitly cut off the null terminator.
78
_TAR_HEADER = {
89
"name": (uctypes.ARRAY | 0, uctypes.UINT8 | 100),
9-
"size": (uctypes.ARRAY | 124, uctypes.UINT8 | 12),
10+
"size": (uctypes.ARRAY | 124, uctypes.UINT8 | 11),
1011
}
1112

1213
DIRTYPE = const("dir")

0 commit comments

Comments
 (0)