@@ -38,12 +38,20 @@ use chrono::prelude::*;
38
38
use clap:: ValueEnum ;
39
39
use fn_error_context:: context;
40
40
use ostree:: gio;
41
+ use ostree_ext:: composefs:: {
42
+ fsverity:: { FsVerityHashValue , Sha256HashValue } ,
43
+ oci:: pull as composefs_oci_pull,
44
+ repository:: Repository as ComposefsRepository ,
45
+ util:: Sha256Digest ,
46
+ } ;
41
47
use ostree_ext:: oci_spec;
42
48
use ostree_ext:: ostree;
43
49
use ostree_ext:: ostree_prepareroot:: { ComposefsState , Tristate } ;
44
50
use ostree_ext:: prelude:: Cast ;
45
51
use ostree_ext:: sysroot:: SysrootLock ;
46
- use ostree_ext:: { container as ostree_container, ostree_prepareroot} ;
52
+ use ostree_ext:: {
53
+ container as ostree_container, container:: ImageReference as OstreeExtImgRef , ostree_prepareroot,
54
+ } ;
47
55
#[ cfg( feature = "install-to-disk" ) ]
48
56
use rustix:: fs:: FileTypeExt ;
49
57
use rustix:: fs:: MetadataExt as _;
@@ -366,6 +374,7 @@ pub(crate) struct SourceInfo {
366
374
}
367
375
368
376
// Shared read-only global state
377
+ #[ derive( Debug ) ]
369
378
pub ( crate ) struct State {
370
379
pub ( crate ) source : SourceInfo ,
371
380
/// Force SELinux off in target system
@@ -1428,10 +1437,32 @@ impl BoundImages {
1428
1437
}
1429
1438
}
1430
1439
1440
+ async fn initialize_composefs_repository (
1441
+ state : & State ,
1442
+ root_setup : & RootSetup ,
1443
+ ) -> Result < ( Sha256Digest , impl FsVerityHashValue ) > {
1444
+ let rootfs_dir = & root_setup. physical_root ;
1445
+
1446
+ rootfs_dir
1447
+ . create_dir_all ( "composefs" )
1448
+ . context ( "Creating dir 'composefs'" ) ?;
1449
+
1450
+ tracing:: warn!( "STATE: {state:#?}" ) ;
1451
+
1452
+ let repo: ComposefsRepository < Sha256HashValue > =
1453
+ ComposefsRepository :: open_path ( rootfs_dir, "composefs" ) . expect ( "failed to open_path" ) ;
1454
+
1455
+ let OstreeExtImgRef { transport, name } = & state. target_imgref . imgref ;
1456
+
1457
+ // transport's display is already of type "<transport_type>:"
1458
+ composefs_oci_pull ( & Arc :: new ( repo) , & format ! ( "{transport}{name}" , ) , None ) . await
1459
+ }
1460
+
1431
1461
async fn install_to_filesystem_impl (
1432
1462
state : & State ,
1433
1463
rootfs : & mut RootSetup ,
1434
1464
cleanup : Cleanup ,
1465
+ composefs : bool ,
1435
1466
) -> Result < ( ) > {
1436
1467
if matches ! ( state. selinux_state, SELinuxFinalState :: ForceTargetDisabled ) {
1437
1468
rootfs. kargs . push ( "selinux=0" . to_string ( ) ) ;
@@ -1460,34 +1491,45 @@ async fn install_to_filesystem_impl(
1460
1491
1461
1492
let bound_images = BoundImages :: from_state ( state) . await ?;
1462
1493
1463
- // Initialize the ostree sysroot (repo, stateroot, etc.)
1494
+ if composefs {
1495
+ // Load a fd for the mounted target physical root
1496
+ let ( id, verity) = initialize_composefs_repository ( state, rootfs) . await ?;
1464
1497
1465
- {
1466
- let ( sysroot, has_ostree, imgstore) = initialize_ostree_root ( state, rootfs) . await ?;
1467
-
1468
- install_with_sysroot (
1469
- state,
1470
- rootfs,
1471
- & sysroot,
1472
- & boot_uuid,
1473
- bound_images,
1474
- has_ostree,
1475
- & imgstore,
1476
- )
1477
- . await ?;
1498
+ tracing:: warn!(
1499
+ "id = {id}, verity = {verity}" ,
1500
+ id = hex:: encode( id) ,
1501
+ verity = verity. to_hex( )
1502
+ ) ;
1503
+ } else {
1504
+ // Initialize the ostree sysroot (repo, stateroot, etc.)
1505
+
1506
+ {
1507
+ let ( sysroot, has_ostree, imgstore) = initialize_ostree_root ( state, rootfs) . await ?;
1508
+
1509
+ install_with_sysroot (
1510
+ state,
1511
+ rootfs,
1512
+ & sysroot,
1513
+ & boot_uuid,
1514
+ bound_images,
1515
+ has_ostree,
1516
+ & imgstore,
1517
+ )
1518
+ . await ?;
1478
1519
1479
- if matches ! ( cleanup, Cleanup :: TriggerOnNextBoot ) {
1480
- let sysroot_dir = crate :: utils:: sysroot_dir ( & sysroot) ?;
1481
- tracing:: debug!( "Writing {DESTRUCTIVE_CLEANUP}" ) ;
1482
- sysroot_dir. atomic_write ( format ! ( "etc/{}" , DESTRUCTIVE_CLEANUP ) , b"" ) ?;
1483
- }
1520
+ if matches ! ( cleanup, Cleanup :: TriggerOnNextBoot ) {
1521
+ let sysroot_dir = crate :: utils:: sysroot_dir ( & sysroot) ?;
1522
+ tracing:: debug!( "Writing {DESTRUCTIVE_CLEANUP}" ) ;
1523
+ sysroot_dir. atomic_write ( format ! ( "etc/{}" , DESTRUCTIVE_CLEANUP ) , b"" ) ?;
1524
+ }
1484
1525
1485
- // We must drop the sysroot here in order to close any open file
1486
- // descriptors.
1487
- } ;
1526
+ // We must drop the sysroot here in order to close any open file
1527
+ // descriptors.
1528
+ } ;
1488
1529
1489
- // Run this on every install as the penultimate step
1490
- install_finalize ( & rootfs. physical_root_path ) . await ?;
1530
+ // Run this on every install as the penultimate step
1531
+ install_finalize ( & rootfs. physical_root_path ) . await ?;
1532
+ }
1491
1533
1492
1534
// Finalize mounted filesystems
1493
1535
if !rootfs. skip_finalize {
@@ -1550,7 +1592,7 @@ pub(crate) async fn install_to_disk(mut opts: InstallToDiskOpts) -> Result<()> {
1550
1592
( rootfs, loopback_dev)
1551
1593
} ;
1552
1594
1553
- install_to_filesystem_impl ( & state, & mut rootfs, Cleanup :: Skip ) . await ?;
1595
+ install_to_filesystem_impl ( & state, & mut rootfs, Cleanup :: Skip , opts . composefs ) . await ?;
1554
1596
1555
1597
// Drop all data about the root except the bits we need to ensure any file descriptors etc. are closed.
1556
1598
let ( root_path, luksdev) = rootfs. into_storage ( ) ;
@@ -1936,7 +1978,7 @@ pub(crate) async fn install_to_filesystem(
1936
1978
skip_finalize,
1937
1979
} ;
1938
1980
1939
- install_to_filesystem_impl ( & state, & mut rootfs, cleanup) . await ?;
1981
+ install_to_filesystem_impl ( & state, & mut rootfs, cleanup, false ) . await ?;
1940
1982
1941
1983
// Drop all data about the root except the path to ensure any file descriptors etc. are closed.
1942
1984
drop ( rootfs) ;
0 commit comments