FDS/OS 1.0
This commit is contained in:
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build an independent, read-only recovery filesystem from its own rootfs."""
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
import tempfile
|
||||
import uuid
|
||||
|
||||
project = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(project / 'tools'))
|
||||
from image_formats import digest, NAMESPACE
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--rootfs', type=Path, default=project / 'out/rootfs-recovery.tar')
|
||||
parser.add_argument('--output-directory', type=Path)
|
||||
args = parser.parse_args()
|
||||
rootfs = args.rootfs.resolve(strict=True)
|
||||
with tarfile.open(rootfs) as archive:
|
||||
profile = archive.extractfile('usr/share/fds/image-profile').read(64).decode().strip()
|
||||
try:
|
||||
root = archive.getmember('.')
|
||||
except KeyError:
|
||||
parser.error('rootfs omits root directory metadata; rebuild the rootfs')
|
||||
if not root.isdir() or (root.uid, root.gid, root.mode) != (0, 0, 0o755):
|
||||
parser.error('rootfs must explicitly record / as root:root mode 0755; rebuild the rootfs')
|
||||
if profile != 'recovery':
|
||||
parser.error('input must be a separately built recovery rootfs')
|
||||
work = args.output_directory or Path(tempfile.mkdtemp(prefix='recovery-build.', dir=project / 'out'))
|
||||
if not work.is_dir() or any(work.iterdir()):
|
||||
parser.error('output directory must exist and be empty')
|
||||
epoch = int(subprocess.check_output(['git', '-C', str(project / 'vendor/void-packages'), 'show', '-s', '--format=%ct', 'HEAD']))
|
||||
identity = uuid.uuid5(NAMESPACE, 'recovery:' + digest(rootfs))
|
||||
runner = str(project / 'tools/in-image-tools')
|
||||
image = work / 'recovery.erofs'
|
||||
subprocess.run([runner, 'mkfs.erofs', '-T', str(epoch), '-U', str(identity), '-b4096',
|
||||
'-L', 'FDS_RECOVERY', '--tar=f', str(image), str(rootfs)], check=True)
|
||||
subprocess.run([runner, 'fsck.erofs', '--extract', str(image)], check=True)
|
||||
(work / 'manifest.json').write_text(json.dumps({
|
||||
'format': 1, 'profile': profile, 'rootfs_sha256': digest(rootfs),
|
||||
'image_sha256': digest(image), 'bytes': image.stat().st_size,
|
||||
'partition_name': 'FDS_RECOVERY', 'filesystem': 'erofs',
|
||||
}, indent=2) + '\n')
|
||||
if args.output_directory is None:
|
||||
target = project / 'out/fds-recovery.img.next'
|
||||
target.symlink_to(work.name + '/recovery.erofs')
|
||||
target.replace(project / 'out/fds-recovery.img')
|
||||
print(f'PASS: independent recovery EROFS (partition payload): {work}')
|
||||
Reference in New Issue
Block a user