1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 from urllib
.request
import urlopen
13 from mozpack
.macpkg
import Pbzx
, uncpio
, unxar
16 def unpack_sdk(url
, sha256
, extract_prefix
, out_dir
="."):
17 with tempfile
.TemporaryFile() as pkg
:
18 hash = hashlib
.sha256()
19 with
urlopen(url
) as fh
:
20 # Equivalent to shutil.copyfileobj, but computes sha256 at the same time.
22 buf
= fh
.read(1024 * 1024)
27 digest
= hash.hexdigest()
29 raise Exception(f
"(actual) {digest} != (expected) {sha256}")
31 pkg
.seek(0, os
.SEEK_SET
)
33 for name
, content
in unxar(pkg
):
35 extract_payload(content
, extract_prefix
, out_dir
)
38 def extract_payload(fileobj
, extract_prefix
, out_dir
="."):
39 for path
, mode
, content
in uncpio(Pbzx(fileobj
)):
43 if not path
.startswith(extract_prefix
):
45 path
= os
.path
.join(out_dir
, path
[len(extract_prefix
) :].lstrip("/"))
46 if stat
.S_ISDIR(mode
):
47 os
.makedirs(path
, exist_ok
=True)
49 parent
= os
.path
.dirname(path
)
51 os
.makedirs(parent
, exist_ok
=True)
53 if stat
.S_ISLNK(mode
):
54 os
.symlink(content
.read(), path
)
55 elif stat
.S_ISREG(mode
):
56 with
open(path
, "wb") as out
:
57 shutil
.copyfileobj(content
, out
)
59 raise Exception(f
"File mode {mode:o} is not supported")
62 if __name__
== "__main__":
63 unpack_sdk(*sys
.argv
[1:])