@@ -6,13 +6,15 @@ use std::ffi::{CString, OsStr, OsString};
66use  std:: io:: Seek ; 
77use  std:: os:: unix:: process:: CommandExt ; 
88use  std:: process:: Command ; 
9+ use  std:: sync:: Arc ; 
910
1011use  anyhow:: { ensure,  Context ,  Result } ; 
11- use  camino:: Utf8PathBuf ; 
12+ use  camino:: { Utf8Path ,   Utf8PathBuf } ; 
1213use  cap_std_ext:: cap_std; 
1314use  cap_std_ext:: cap_std:: fs:: Dir ; 
1415use  clap:: Parser ; 
1516use  clap:: ValueEnum ; 
17+ use  composefs_boot:: BootOps  as  _; 
1618use  etc_merge:: { compute_diff,  print_diff} ; 
1719use  fn_error_context:: context; 
1820use  indoc:: indoc; 
@@ -23,11 +25,13 @@ use ostree_ext::composefs::fsverity::FsVerityHashValue;
2325use  ostree_ext:: composefs:: splitstream:: SplitStreamWriter ; 
2426use  ostree_ext:: container as  ostree_container; 
2527use  ostree_ext:: container_utils:: ostree_booted; 
28+ use  ostree_ext:: containers_image_proxy:: ImageProxyConfig ; 
2629use  ostree_ext:: keyfileext:: KeyFileExt ; 
2730use  ostree_ext:: ostree; 
2831use  ostree_ext:: sysroot:: SysrootLock ; 
2932use  schemars:: schema_for; 
3033use  serde:: { Deserialize ,  Serialize } ; 
34+ use  tempfile:: tempdir_in; 
3135
3236#[ cfg( feature = "composefs-backend" ) ]  
3337use  crate :: bootc_composefs:: { 
@@ -40,9 +44,11 @@ use crate::bootc_composefs::{
4044} ; 
4145use  crate :: deploy:: RequiredHostSpec ; 
4246use  crate :: lints; 
47+ use  crate :: podstorage:: set_additional_image_store; 
4348use  crate :: progress_jsonl:: { ProgressWriter ,  RawProgressFd } ; 
4449use  crate :: spec:: Host ; 
4550use  crate :: spec:: ImageReference ; 
51+ use  crate :: store:: ComposefsRepository ; 
4652use  crate :: utils:: sigpolicy_from_opt; 
4753
4854/// Shared progress options 
@@ -315,6 +321,12 @@ pub(crate) enum ContainerOpts {
315321         #[ clap( long) ]  
316322        no_truncate :  bool , 
317323    } , 
324+     /// Output the bootable composefs digest. 
325+      #[ clap( hide = true ) ]  
326+     ComputeComposefsDigest  { 
327+         /// Identifier for image; if not provided, the running image will be used. 
328+          image :  Option < String > , 
329+     } , 
318330} 
319331
320332/// Subcommands which operate on images. 
@@ -1335,6 +1347,55 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
13351347                ) ?; 
13361348                Ok ( ( ) ) 
13371349            } 
1350+             ContainerOpts :: ComputeComposefsDigest  {  image }  => { 
1351+                 // Allocate a tempdir 
1352+                 let  td = tempdir_in ( "/var/tmp" ) ?; 
1353+                 let  td = td. path ( ) ; 
1354+                 let  td = & Dir :: open_ambient_dir ( td,  cap_std:: ambient_authority ( ) ) ?; 
1355+ 
1356+                 td. create_dir ( "repo" ) ?; 
1357+                 let  repo = td. open_dir ( "repo" ) ?; 
1358+                 let  mut  repo =
1359+                     ComposefsRepository :: open_path ( & repo,  "." ) . context ( "Init cfs repo" ) ?; 
1360+                 // We don't need to hard require verity on the *host* system, we're just computing a checksum here 
1361+                 repo. set_insecure ( true ) ; 
1362+                 let  repo = & Arc :: new ( repo) ; 
1363+ 
1364+                 let  mut  proxycfg = ImageProxyConfig :: default ( ) ; 
1365+ 
1366+                 let  image = if  let  Some ( image)  = image { 
1367+                     image
1368+                 }  else  { 
1369+                     let  host_container_store = Utf8Path :: new ( "/run/host-container-storage" ) ; 
1370+                     // If no image is provided, assume that we're running in a container in privileged mode 
1371+                     // with access to the container storage. 
1372+                     let  container_info = crate :: containerenv:: get_container_execution_info ( & root) ?; 
1373+                     let  iid = container_info. imageid ; 
1374+                     tracing:: debug!( "Computing digest of {iid}" ) ; 
1375+ 
1376+                     if  !host_container_store. try_exists ( ) ? { 
1377+                         anyhow:: bail!( "Must be readonly mount of host container store: {host_container_store}" ) ; 
1378+                     } 
1379+                     // And ensure we're finding the image in the host storage 
1380+                     let  mut  cmd = Command :: new ( "skopeo" ) ; 
1381+                     set_additional_image_store ( & mut  cmd,  "/run/host-container-storage" ) ; 
1382+                     proxycfg. skopeo_cmd  = Some ( cmd) ; 
1383+                     iid
1384+                 } ; 
1385+ 
1386+                 let  imgref = format ! ( "containers-storage:{image}" ) ; 
1387+                 let  ( imgid,  verity)  = composefs_oci:: pull ( repo,  & imgref,  None ,  Some ( proxycfg) ) 
1388+                     . await 
1389+                     . context ( "Pulling image" ) ?; 
1390+                 let  imgid = hex:: encode ( imgid) ; 
1391+                 let  mut  fs = composefs_oci:: image:: create_filesystem ( repo,  & imgid,  Some ( & verity) ) 
1392+                     . context ( "Populating fs" ) ?; 
1393+                 fs. transform_for_boot ( & repo) . context ( "Preparing for boot" ) ?; 
1394+                 let  id = fs. compute_image_id ( ) ; 
1395+                 println ! ( "{}" ,  id. to_hex( ) ) ; 
1396+ 
1397+                 Ok ( ( ) ) 
1398+             } 
13381399        } , 
13391400        Opt :: Image ( opts)  => match  opts { 
13401401            ImageOpts :: List  { 
0 commit comments