diff --git a/ext2/src/fs.rs b/ext2/src/fs.rs index 2900cba4c8..c8b33222b3 100644 --- a/ext2/src/fs.rs +++ b/ext2/src/fs.rs @@ -716,6 +716,20 @@ impl<'a> Ext2<'a> { /// Walks through `src_dir` and copies directories and files to the new file system. fn copy_dirtree>(&mut self, arena: &'a Arena<'a>, src_dir: P) -> Result<()> { + // Update the root directory's metadata with the metadata of `src_dir`. + let root_inode_num = InodeNum::new(2).expect("2 is a valid inode number"); + let group_id = self.group_num_for_inode(root_inode_num); + let gm = &mut self.group_metadata[group_id]; + let inode: &mut &mut Inode = gm + .inode_table + .get_mut(&root_inode_num) + .expect("root dir is not stored"); + let metadata = src_dir + .as_ref() + .metadata() + .with_context(|| format!("failed to get metadata of {:?}", src_dir.as_ref()))?; + inode.update_metadata(&metadata); + self.copy_dirtree_rec(arena, InodeNum(2), src_dir) } diff --git a/ext2/src/inode.rs b/ext2/src/inode.rs index 48234d16bd..29dda22d68 100644 --- a/ext2/src/inode.rs +++ b/ext2/src/inode.rs @@ -173,13 +173,13 @@ impl InodeBlock { #[derive(Default, Debug, Copy, Clone, FromZeroes, FromBytes, AsBytes)] pub(crate) struct Inode { mode: u16, - _uid: u16, + uid: u16, pub size: u32, atime: u32, ctime: u32, mtime: u32, _dtime: u32, - _gid: u16, + gid: u16, pub links_count: u16, pub blocks: InodeBlocksCount, _flags: u32, @@ -192,8 +192,8 @@ pub(crate) struct Inode { _fragment_num: u8, _fragment_size: u8, _reserved1: u16, - _uid_high: u16, - _gid_high: u16, + uid_high: u16, + gid_high: u16, _reserved2: u32, } @@ -278,10 +278,10 @@ impl Inode { atime: now, ctime: now, mtime: now, - _uid: uid_low, - _gid: gid_low, - _uid_high: uid_high, - _gid_high: gid_high, + uid: uid_low, + gid: gid_low, + uid_high, + gid_high, ..Default::default() }; Ok(inode) @@ -319,8 +319,8 @@ impl Inode { *inode = Inode { mode, - _uid: uid_low, - _gid: gid_low, + uid: uid_low, + gid: gid_low, size, atime, ctime, @@ -328,16 +328,29 @@ impl Inode { links_count, blocks, block, - - _uid_high: uid_high, - _gid_high: gid_high, - + uid_high, + gid_high, ..Default::default() }; Ok(inode) } + pub fn update_metadata(&mut self, m: &std::fs::Metadata) { + self.mode = m.mode() as u16; + + let uid: u32 = m.uid(); + self.uid_high = (uid >> 16) as u16; + self.uid = uid as u16; + let gid = m.gid(); + self.gid_high = (gid >> 16) as u16; + self.gid = gid as u16; + + self.atime = m.atime() as u32; + self.ctime = m.ctime() as u32; + self.mtime = m.mtime() as u32; + } + pub fn typ(&self) -> Option { InodeType::n((self.mode >> 12) as u8) } diff --git a/ext2/tests/tests.rs b/ext2/tests/tests.rs index 1e77c699dd..2b55fe3366 100644 --- a/ext2/tests/tests.rs +++ b/ext2/tests/tests.rs @@ -236,6 +236,8 @@ fn test_simple_dir() { ); assert_eq_dirs(&td, &dir, &disk); + + td.close().unwrap(); // make sure that tempdir is properly deleted. } #[test]