Prepare clean Sargo images and validated storage inventories

Keep internal documents out of system images while retaining license notices and package versions. Generate boot mappings from a bounded storage inventory, and allow long SSH diagnostics. Hardware boot qualification remains pending.
This commit is contained in:
OverSu 2026-10-01 12:25:53 +02:00
commit 9b606ed5f3
7 changed files with 193 additions and 4 deletions

View file

@ -0,0 +1,37 @@
# SPDX-License-Identifier: MPL-2.0
from pathlib import Path
import sys
import unittest
sys.path.insert(0, str(Path(__file__).resolve().parents[1]/'tools'))
from storage_layout import mount_table
class StorageLayoutTests(unittest.TestCase):
def layout(self):
return dict(schema=2, device='/dev/mmcblk0p72', partitionLabel='userdata',
filesystem='ext4', backingDevice='259:40', size=53648801280,
table='0 104448000 linear 259:40 329728', firstMiBSha256='a'*64)
def test_supported_inventory_uses_partition_path(self):
self.assertEqual(mount_table(self.layout()),
'0 104448000 linear /dev/mmcblk0p72 329728')
def test_different_inventory_offset_is_not_replaced_with_developer_offset(self):
layout=self.layout(); layout['table']='0 104000000 linear 259:40 8192'
self.assertEqual(mount_table(layout), '0 104000000 linear /dev/mmcblk0p72 8192')
def test_rejects_overflow_other_partition_and_multiple_extents(self):
for patch in ({'table':'0 104448000 linear 259:40 999999999'},
{'device':'/dev/mmcblk0p1'}, {'filesystem':'crypto_LUKS'},
{'backingDevice':'259:41'},
{'table':'0 104448000 linear 259:40 329728\n1 2 linear 259:40 3'},
{'firstMiBSha256':'not-a-hash'}):
with self.subTest(patch=patch), self.assertRaises(ValueError):
mount_table(self.layout() | patch)
def test_legacy_inventory_remains_supported_but_not_generalized(self):
layout=self.layout();layout.pop('schema')
self.assertIn('329728',mount_table(layout))
layout['table']='0 104000000 linear 259:40 8192'
with self.assertRaises(ValueError):mount_table(layout)

View file

@ -1,6 +1,7 @@
# SPDX-License-Identifier: MPL-2.0
"""Exercise ownership/format safeguards without writing to a real device."""
import importlib.util
import json
import os
from pathlib import Path
import tempfile
@ -14,6 +15,32 @@ spec.loader.exec_module(image)
class SystemImageTests(unittest.TestCase):
def test_distribution_omits_working_documents_but_keeps_component_licenses(self):
with tempfile.TemporaryDirectory() as temporary:
root=Path(temporary); product=root/'product'; reference=root/'reference'
(product/'component').mkdir(parents=True);reference.mkdir()
(product/'README.md').write_text('Internal working document')
(product/'component/LICENSE.md').write_text('Original upstream notice')
(reference/'manifest.json').write_text(json.dumps({'packages':{
'example':{'binary:Package':'example','Version':'1',
'source:Package':'example','source:Version':'1',
'localPath':'private/path'}}}))
image.prepare_distribution_metadata(product,reference)
self.assertFalse((product/'README.md').exists())
self.assertEqual((product/'component/LICENSE').read_text(),'Original upstream notice')
inventory=json.loads((product/'runtime-packages.json').read_text())
self.assertEqual(inventory['packages'][0]['binary:Package'],'example')
self.assertNotIn('localPath',inventory['packages'][0])
self.assertTrue((product/'NOTICE').is_file())
def test_conflicting_project_license_is_not_overwritten(self):
with tempfile.TemporaryDirectory() as temporary:
product=Path(temporary)
(product/'LICENSE').write_text('Keep this upstream notice')
with self.assertRaisesRegex(ValueError,'existing notice'):
image.prepare_distribution_metadata(product,Path('/unused'))
self.assertEqual((product/'LICENSE').read_text(),'Keep this upstream notice')
def test_pack_refuses_real_ownership_changes_outside_fakeroot(self):
with patch.dict(os.environ, {}, clear=True), patch.object(image.os, 'lchown') as chown:
with self.assertRaisesRegex(RuntimeError, 'fakeroot'):