@@ -25,6 +25,8 @@ use serde::Serialize;
2525
2626/// Reference to embedded default baseimage content that should exist.
2727const BASEIMAGE_REF : & str = "usr/share/doc/bootc/baseimage/base" ;
28+ // https://systemd.io/API_FILE_SYSTEMS/ with /var added for us
29+ const API_DIRS : & [ & str ] = & [ "dev" , "proc" , "sys" , "run" , "tmp" , "var" ] ;
2830
2931/// A lint check has failed.
3032#[ derive( thiserror:: Error , Debug ) ]
@@ -375,6 +377,31 @@ fn check_prepareroot_composefs_norecurse(dir: &Dir) -> LintResult {
375377 lint_ok ( )
376378}
377379
380+ #[ distributed_slice( LINTS ) ]
381+ static LINT_API_DIRS : Lint = Lint :: new_fatal (
382+ "api-base-directories" ,
383+ indoc ! { r#"
384+ Verify that expected base API directories exist. For more information
385+ on these, see <https://systemd.io/API_FILE_SYSTEMS/>.
386+
387+ Note that in addition, bootc requires that `/var` exist as a directory.
388+ "# } ,
389+ check_api_dirs,
390+ ) ;
391+ fn check_api_dirs ( root : & Dir ) -> LintResult {
392+ for d in API_DIRS {
393+ let Some ( meta) = root. symlink_metadata_optional ( d) ? else {
394+ return lint_err ( format ! ( "Missing API filesystem base directory: /{d}" ) ) ;
395+ } ;
396+ if !meta. is_dir ( ) {
397+ return lint_err ( format ! (
398+ "Expected directory for API filesystem base directory: /{d}"
399+ ) ) ;
400+ }
401+ }
402+ lint_ok ( )
403+ }
404+
378405#[ distributed_slice( LINTS ) ]
379406static LINT_COMPOSEFS : Lint = Lint :: new_warning (
380407 "baseimage-composefs" ,
@@ -645,6 +672,9 @@ mod tests {
645672
646673 fn passing_fixture ( ) -> Result < cap_std_ext:: cap_tempfile:: TempDir > {
647674 let root = cap_std_ext:: cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
675+ for d in API_DIRS {
676+ root. create_dir ( d) ?;
677+ }
648678 root. create_dir_all ( "usr/lib/modules/5.7.2" ) ?;
649679 root. write ( "usr/lib/modules/5.7.2/vmlinuz" , "vmlinuz" ) ?;
650680
@@ -674,6 +704,18 @@ mod tests {
674704 Ok ( ( ) )
675705 }
676706
707+ #[ test]
708+ fn test_api ( ) -> Result < ( ) > {
709+ let root = & passing_fixture ( ) ?;
710+ // This one should pass
711+ check_api_dirs ( root) . unwrap ( ) . unwrap ( ) ;
712+ root. remove_dir ( "var" ) ?;
713+ assert ! ( check_api_dirs( root) . unwrap( ) . is_err( ) ) ;
714+ root. write ( "var" , "a file for var" ) ?;
715+ assert ! ( check_api_dirs( root) . unwrap( ) . is_err( ) ) ;
716+ Ok ( ( ) )
717+ }
718+
677719 #[ test]
678720 fn test_lint_main ( ) -> Result < ( ) > {
679721 let root = & passing_fixture ( ) ?;
0 commit comments