@@ -38,12 +38,20 @@ use chrono::prelude::*;
3838use clap:: ValueEnum ;
3939use fn_error_context:: context;
4040use 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+ } ;
4147use ostree_ext:: oci_spec;
4248use ostree_ext:: ostree;
4349use ostree_ext:: ostree_prepareroot:: { ComposefsState , Tristate } ;
4450use ostree_ext:: prelude:: Cast ;
4551use 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+ } ;
4755#[ cfg( feature = "install-to-disk" ) ]
4856use rustix:: fs:: FileTypeExt ;
4957use rustix:: fs:: MetadataExt as _;
@@ -366,6 +374,7 @@ pub(crate) struct SourceInfo {
366374}
367375
368376// Shared read-only global state
377+ #[ derive( Debug ) ]
369378pub ( crate ) struct State {
370379 pub ( crate ) source : SourceInfo ,
371380 /// Force SELinux off in target system
@@ -1428,10 +1437,32 @@ impl BoundImages {
14281437 }
14291438}
14301439
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+
14311461async fn install_to_filesystem_impl (
14321462 state : & State ,
14331463 rootfs : & mut RootSetup ,
14341464 cleanup : Cleanup ,
1465+ composefs : bool ,
14351466) -> Result < ( ) > {
14361467 if matches ! ( state. selinux_state, SELinuxFinalState :: ForceTargetDisabled ) {
14371468 rootfs. kargs . push ( "selinux=0" . to_string ( ) ) ;
@@ -1460,34 +1491,45 @@ async fn install_to_filesystem_impl(
14601491
14611492 let bound_images = BoundImages :: from_state ( state) . await ?;
14621493
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 ?;
14641497
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 ?;
14781519
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+ }
14841525
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+ } ;
14881529
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+ }
14911533
14921534 // Finalize mounted filesystems
14931535 if !rootfs. skip_finalize {
@@ -1550,7 +1592,7 @@ pub(crate) async fn install_to_disk(mut opts: InstallToDiskOpts) -> Result<()> {
15501592 ( rootfs, loopback_dev)
15511593 } ;
15521594
1553- install_to_filesystem_impl ( & state, & mut rootfs, Cleanup :: Skip ) . await ?;
1595+ install_to_filesystem_impl ( & state, & mut rootfs, Cleanup :: Skip , opts . composefs ) . await ?;
15541596
15551597 // Drop all data about the root except the bits we need to ensure any file descriptors etc. are closed.
15561598 let ( root_path, luksdev) = rootfs. into_storage ( ) ;
@@ -1936,7 +1978,7 @@ pub(crate) async fn install_to_filesystem(
19361978 skip_finalize,
19371979 } ;
19381980
1939- install_to_filesystem_impl ( & state, & mut rootfs, cleanup) . await ?;
1981+ install_to_filesystem_impl ( & state, & mut rootfs, cleanup, false ) . await ?;
19401982
19411983 // Drop all data about the root except the path to ensure any file descriptors etc. are closed.
19421984 drop ( rootfs) ;
0 commit comments