Skip to content

Commit c226cf4

Browse files
etc-merge: Handle ownership changes
Signed-off-by: Johan-Liebert1 <[email protected]>
1 parent 6bb619e commit c226cf4

File tree

1 file changed

+44
-31
lines changed

1 file changed

+44
-31
lines changed

crates/etc-merge/src/lib.rs

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use cap_std_ext::dirext::CapStdExtDirExt;
1616
use composefs::fsverity::{FsVerityHashValue, Sha256HashValue, Sha512HashValue};
1717
use composefs::generic_tree::{Directory, Inode, Leaf, LeafContent, Stat};
1818
use composefs::tree::ImageError;
19-
use rustix::fs::readlinkat;
19+
use rustix::fs::{AtFlags, Gid, Uid, readlinkat};
2020

2121
#[derive(Debug)]
2222
struct CustomMetadata {
@@ -195,7 +195,6 @@ fn get_modifications(
195195
.extend(collect_all_files(&curr_dir, current_path.clone()));
196196
}
197197

198-
// TODO: Test if a file was changed to a directory
199198
Err(e) => Err(e)?,
200199
}
201200
}
@@ -439,19 +438,14 @@ fn create_dir_with_perms(
439438
.set_permissions(&dir_name, Permissions::from_mode(stat.st_mode))
440439
.context(format!("Changing permissions for dir {dir_name:?}"))?;
441440

442-
println!(
443-
"Set permission of {dir_name:?} to {:?}",
444-
Permissions::from_mode(stat.st_mode)
445-
);
446-
447-
// TODO: Handle ownership
448-
//
449-
// rustix::fs::chown(
450-
// &modified,
451-
// Some(Uid::from_raw(current_inode.stat().st_uid)),
452-
// Some(Gid::from_raw(current_inode.stat().st_gid)),
453-
// )
454-
// .context(format!("chown {modified:?}"))?;
441+
rustix::fs::chownat(
442+
&new_etc_fd,
443+
dir_name,
444+
Some(Uid::from_raw(stat.st_uid)),
445+
Some(Gid::from_raw(stat.st_gid)),
446+
AtFlags::SYMLINK_NOFOLLOW,
447+
)
448+
.context(format!("chown {dir_name:?}"))?;
455449

456450
Ok(())
457451
}
@@ -478,6 +472,15 @@ fn handle_leaf(
478472
.copy(&file, new_etc_fd, &file)
479473
.context(format!("Copying file {file:?}"))?;
480474

475+
rustix::fs::chownat(
476+
&new_etc_fd,
477+
file,
478+
Some(Uid::from_raw(leaf.stat.st_uid)),
479+
Some(Gid::from_raw(leaf.stat.st_gid)),
480+
AtFlags::SYMLINK_NOFOLLOW,
481+
)
482+
.context(format!("chown {file:?}"))?;
483+
481484
"file"
482485
}
483486

@@ -495,6 +498,15 @@ fn handle_leaf(
495498
.symlink(PathBuf::from(os_str), &file)
496499
.context(format!("Creating symlink {file:?}"))?;
497500

501+
rustix::fs::chownat(
502+
&new_etc_fd,
503+
file,
504+
Some(Uid::from_raw(leaf.stat.st_uid)),
505+
Some(Gid::from_raw(leaf.stat.st_gid)),
506+
AtFlags::SYMLINK_NOFOLLOW,
507+
)
508+
.context(format!("chown {file:?}"))?;
509+
498510
"symlink"
499511
}
500512

@@ -528,22 +540,8 @@ fn handle_modified_files(
528540
// Directory exists in the new /etc, but was modified in some way
529541
Ok((dir, filename)) => {
530542
let new_inode = dir.lookup(filename);
531-
// println!("new_inode: {new_inode:?}");
532-
533543
let ty = match current_inode {
534544
Inode::Directory(..) => {
535-
// let remove = match new_inode {
536-
// // Dir with the same name is present in new /etc
537-
// // We delete this dir and create a new one
538-
// Some(Inode::Directory(..)) => true,
539-
540-
// // Dir doesn't exist in the new /etc, so create it
541-
// // Nothing to remove
542-
// None => false,
543-
544-
// _ => anyhow::bail!("Dir {file:?} converted to file"),
545-
// };
546-
547545
create_dir_with_perms(new_etc_fd, file, current_inode.stat(), true)?;
548546

549547
"dir"
@@ -852,13 +850,23 @@ mod tests {
852850
c.create_dir_all("dir/perms")?;
853851
c.set_permissions("dir/perms", Permissions::from_mode(0o777))?;
854852

853+
// Directory ownership
854+
p.create_dir_all("dir/owner")?;
855+
856+
c.create_dir_all("dir/owner")?;
857+
rustix::fs::chownat(
858+
&c,
859+
"dir/owner",
860+
Some(Uid::from_raw(u16::MAX as u32)),
861+
Some(Gid::from_raw(u16::MAX as u32)),
862+
AtFlags::SYMLINK_NOFOLLOW,
863+
)?;
864+
855865
let (pristine_etc_files, current_etc_files, new_etc_files) = traverse_etc(&p, &c, &n)?;
856866
let diff = compute_diff(&pristine_etc_files, &current_etc_files)?;
857867
println!("current_etc_files: {current_etc_files:#?}");
858868
merge(&c, &current_etc_files, &n, &new_etc_files, diff)?;
859869

860-
// std::thread::sleep(std::time::Duration::from_secs(4434));
861-
862870
assert!(files_eq(&c, &n, "new_file.txt")?);
863871
assert!(files_eq(&c, &n, "a/new_file.txt")?);
864872
assert!(files_eq(&c, &n, "a/b/new_file.txt")?);
@@ -892,6 +900,11 @@ mod tests {
892900
n.metadata("dir/perms")?
893901
));
894902

903+
assert!(compare_meta(
904+
c.metadata("dir/owner")?,
905+
n.metadata("dir/owner")?
906+
));
907+
895908
Ok(())
896909
}
897910
}

0 commit comments

Comments
 (0)