8000 utarfile: Lightweight tarfile module subset. · micropython/micropython-lib@b85a246 · GitHub
[go: up one dir, main page]

Skip to content

Commit b85a246

Browse files
author
Paul Sokolovsky
committed
utarfile: Lightweight tarfile module subset.
1 parent a03e185 commit b85a246

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

utarfile/utarfile.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import uctypes
2+
3+
# http://www.gnu.org/software/tar/manual/html_node/Standard.html
4+
TAR_HEADER = {
5+
"name": (uctypes.ARRAY | 0, uctypes.UINT8 | 100),
6+
"size": (uctypes.ARRAY | 124, uctypes.UINT8 | 12),
7+
}
8+
9+
DIRTYPE = "dir"
10+
REGTYPE = "file"
11+
12+
def roundup(val, align):
13+
return (val + align - 1) & ~(align - 1)
14+
15+
def skip(f, size):
16+
assert size % 512 == 0
17+
buf = bytearray(512)
18+
while size:
19+
size -= f.readinto(buf)
20+
21+
class FileSection:
22+
23+
def __init__(self, f, content_len, aligned_len):
24+
self.f = f
25+
self.content_len = content_len
26+
self.align = aligned_len - content_len
27+
28+
def read(self, sz=65536):
29+
if self.content_len == 0:
30+
return b""
31+
if sz > self.content_len:
32+
sz = self.content_len
33+
data = self.f.read(sz)
34+
sz = len(data)
35+
self.content_len -= sz
36+
return data
37+
38+
def skip(self):
39+
self.f.read(self.content_len + self.align)
40+
41+
class TarInfo:
42+
43+
def __str__(self):
44+
return "TarInfo(%r, %s, %d)" % (self.name, self.type, self.size)
45+
46+
class TarFile:
47+
48+
def __init__(self, name):
49+
self.f = open(name, "rb")
50+
self.subf = None
51+
52+
def next(self):
53+
if self.subf:
54+
self.subf.skip()
55+
buf = self.f.read(512)
56+
if not buf:
57+
return None
58+
59+
h = uctypes.struct(TAR_HEADER, uctypes.addressof(buf), uctypes.LITTLE_ENDIAN)
60+
61+
# Empty block means end of archive
62+
if h.name[0] == 0:
63+
return None
64+
65+
d = TarInfo()
66+
d.name = str(h.name, "utf-8").rstrip()
67+
d.size = int(bytes(h.size).rstrip(), 8)
68+
d.type = [REGTYPE, DIRTYPE][d.name[-1] == "/"]
69+
self.subf = d.subf = FileSection(self.f, d.size, roundup(d.size, 512))
70+
return d
71+
72+
def __iter__(self):
73+
return self
74+
75+
def __next__(self):
76+
v = self.next()
77+
if v is None:
78+
raise StopIteration
79+
return v
80+
81+
def extractfile(self, tarinfo):
82+
return tarinfo.subf

0 commit comments

Comments
 (0)
0