#!/usr/bin/env python3 """Minimal ar archive packer/extractor for .deb files on a-Shell. Usage: ardeb pack [file ...] ardeb extract """ import os import sys def pack(out_path, files): with open(out_path, "wb") as out: out.write(b"!\n") for path in files: data = open(path, "rb").read() name = os.path.basename(path) if len(name) > 15: raise SystemExit("ardeb: member name too long: " + name) header = ( name.ljust(16) + "0".ljust(12) + "0".ljust(6) + "0".ljust(6) + "100644".ljust(8) + str(len(data)).ljust(10) + "`\n" ).encode("ascii") out.write(header) out.write(data) if len(data) & 1: out.write(b"\n") def extract(archive, dest): data = open(archive, "rb").read() if not data.startswith(b"!\n"): raise SystemExit("ardeb: not an ar archive") os.makedirs(dest, exist_ok=True) pos = 8 while pos + 60 <= len(data): header = data[pos:pos + 60] pos += 60 name = header[:16].decode("ascii", "ignore").strip().rstrip("/") if not name: continue try: size = int(header[48:58].decode("ascii", "ignore").strip() or "0") except ValueError: size = 0 body = data[pos:pos + size] pos += size + (size & 1) if name in (".", ".."): continue open(os.path.join(dest, name), "wb").write(body) def main(): if len(sys.argv) < 4: raise SystemExit(__doc__) if sys.argv[1] == "pack": pack(sys.argv[2], sys.argv[3:]) elif sys.argv[1] == "extract": extract(sys.argv[2], sys.argv[3]) else: raise SystemExit(__doc__) if __name__ == "__main__": main()