Skip to content

Instantly share code, notes, and snippets.

@danielrichman
Created September 30, 2018 14:49
Show Gist options
  • Save danielrichman/79c92b956c72e241f65ac1f1a8d550c7 to your computer and use it in GitHub Desktop.
Save danielrichman/79c92b956c72e241f65ac1f1a8d550c7 to your computer and use it in GitHub Desktop.
import time
import shlex
class CPIOWriter:
# https://www.kernel.org/doc/Documentation/early-userspace/buffer-format.txt
HEADER_FORMAT = "070701{ino:08X}{mode:08X}{uid:08X}{gid:08X}{nlink:08X}{mtime:08X}" \
"{filesize:08X}{maj:08X}{min:08X}{rmaj:08X}{rmin:08X}{namesize:08X}{chksum:08X}"
OTHER_HEADER_ARGS = \
{ "mode": 0o100000 + 0o644 # regular file + perms, see stat(2)
, "uid": 0
, "gid": 0
, "nlink": 1
, "mtime": int(time.time())
, "maj": 0
, "min": 0
, "rmaj": 0
, "rmin": 0
, "chksum": 0 # magic ends '1' so no chksum required
}
def __init__(self, file):
self.file = file
self.bytes_written = 0
self.inode_count = 0
def _write(self, string):
self.file.write(string)
self.bytes_written += len(string)
def _align(self):
n = self.bytes_written % 4
if n == 0:
return
else:
self._write("\0" * (4 - n))
def append_file(self, filename, contents):
self.inode_count += 1
self._write(
self.HEADER_FORMAT.format(
ino=self.inode_count
, filesize=len(contents)
, namesize=len(filename) + 1
, **self.OTHER_HEADER_ARGS
)
)
self._write(filename + "\0")
self._align()
self._write(contents)
self._align()
def append_bash_vars_file(self, filename, dictionary):
contents = "".join("{}={}\n".format(k, shlex.quote(v)) for k, v in dictionary.items())
self.append_file(filename=filename, contents=contents)
def append_trailer(self):
self.append_file(filename="TRAILER!!!", contents="")
if __name__ == "__main__":
import sys
w = CPIOWriter(sys.stdout)
w.append_bash_vars_file("preseed-settings", {"a": "test", "b": "test two", "c": "moo'"})
w.append_trailer()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment