Skip to content

Commit b62a14e

Browse files
committed
Fix lint to check /etc/tmpfiles.d
The bootc container lint command now reads tmpfiles.d configuration files from both /usr/lib/tmpfiles.d and /etc/tmpfiles.d, with /etc entries taking precedence (matching systemd's behavior). Fixes #1732 Signed-off-by: gursewak1997 <[email protected]>
1 parent 051a881 commit b62a14e

File tree

1 file changed

+35
-5
lines changed

1 file changed

+35
-5
lines changed

crates/tmpfiles/src/lib.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustix::path::Arg;
2020
use thiserror::Error;
2121

2222
const TMPFILESD: &str = "usr/lib/tmpfiles.d";
23+
const ETC_TMPFILESD: &str = "etc/tmpfiles.d";
2324
/// The path to the file we use for generation
2425
const BOOTC_GENERATED_PREFIX: &str = "bootc-autogenerated-var";
2526

@@ -452,14 +453,16 @@ pub fn find_missing_tmpfiles_current_root() -> Result<TmpfilesResult> {
452453
})
453454
}
454455

455-
/// Read all tmpfiles.d entries in the target directory, and return a mapping
456-
/// from (file path) => (single tmpfiles.d entry line)
457-
fn read_tmpfiles(rootfs: &Dir) -> Result<(BTreeMap<PathBuf, String>, BootcTmpfilesGeneration)> {
458-
let Some(tmpfiles_dir) = rootfs.open_dir_optional(TMPFILESD)? else {
456+
/// Read all tmpfiles.d entries from a single directory
457+
fn read_tmpfiles_from_dir(
458+
rootfs: &Dir,
459+
dir_path: &str,
460+
generation: &mut BootcTmpfilesGeneration,
461+
) -> Result<BTreeMap<PathBuf, String>> {
462+
let Some(tmpfiles_dir) = rootfs.open_dir_optional(dir_path)? else {
459463
return Ok(Default::default());
460464
};
461465
let mut result = BTreeMap::new();
462-
let mut generation = BootcTmpfilesGeneration::default();
463466
for entry in tmpfiles_dir.entries()? {
464467
let entry = entry?;
465468
let name = entry.file_name();
@@ -486,6 +489,25 @@ fn read_tmpfiles(rootfs: &Dir) -> Result<(BTreeMap<PathBuf, String>, BootcTmpfil
486489
result.insert(path.to_owned(), line);
487490
}
488491
}
492+
Ok(result)
493+
}
494+
495+
/// Read all tmpfiles.d entries in the target directory, and return a mapping
496+
/// from (file path) => (single tmpfiles.d entry line)
497+
///
498+
/// This function reads from both `/usr/lib/tmpfiles.d` and `/etc/tmpfiles.d`,
499+
/// with `/etc` entries taking precedence (matching systemd's behavior).
500+
fn read_tmpfiles(rootfs: &Dir) -> Result<(BTreeMap<PathBuf, String>, BootcTmpfilesGeneration)> {
501+
let mut generation = BootcTmpfilesGeneration::default();
502+
503+
// Read from /usr/lib/tmpfiles.d first (system/package-provided)
504+
let mut result = read_tmpfiles_from_dir(rootfs, TMPFILESD, &mut generation)?;
505+
506+
// Read from /etc/tmpfiles.d and merge (user-provided, takes precedence)
507+
let etc_result = read_tmpfiles_from_dir(rootfs, ETC_TMPFILESD, &mut generation)?;
508+
// /etc entries override /usr/lib entries for the same path
509+
result.extend(etc_result);
510+
489511
Ok((result, generation))
490512
}
491513

@@ -569,10 +591,18 @@ mod tests {
569591
"#},
570592
)?;
571593

594+
// Also test /etc/tmpfiles.d (user-provided configs)
595+
rootfs.create_dir_all(ETC_TMPFILESD)?;
596+
rootfs.write(
597+
Path::new(ETC_TMPFILESD).join("user.conf"),
598+
"d /var/lib/user 0755 root root - -\n",
599+
)?;
600+
572601
// Add test content.
573602
rootfs.ensure_dir_with("var/lib/systemd", &db)?;
574603
rootfs.ensure_dir_with("var/lib/private", &db)?;
575604
rootfs.ensure_dir_with("var/lib/nfs", &db)?;
605+
rootfs.ensure_dir_with("var/lib/user", &db)?;
576606
let global_rwx = Permissions::from_mode(0o777);
577607
rootfs.ensure_dir_with("var/lib/test/nested", &db).unwrap();
578608
rootfs.set_permissions("var/lib/test", global_rwx.clone())?;

0 commit comments

Comments
 (0)