feat(ext4): mkdir and nested directory support

This commit is contained in:
2026-10-18 23:16:35 +02:00
parent 2ede01bdd2
commit bc4659eabd
3 changed files with 117 additions and 1 deletions

View File

@@ -179,6 +179,25 @@ pub fn remove_entry<B: BlockDevice>(
None
}
pub fn init_dir_block(buf: &mut [u8], self_inode: u32, parent_inode: u32, block_size: usize) {
for b in buf.iter_mut() { *b = 0; }
let mut pos = 0;
// "." entry
write_u32(buf, pos, self_inode);
write_u16(buf, pos + 4, 12);
buf[pos + 6] = 1;
buf[pos + 7] = 2;
buf[pos + 8] = b'.';
pos += 12;
// ".." entry
write_u32(buf, pos, parent_inode);
write_u16(buf, pos + 4, (block_size - 12) as u16);
buf[pos + 6] = 2;
buf[pos + 7] = 2;
buf[pos + 8] = b'.';
buf[pos + 9] = b'.';
}
pub fn list_entries<B: BlockDevice>(
device: &mut B,
sb: &Superblock,

View File

@@ -586,5 +586,60 @@ impl<B: BlockDevice> FileSystem for Ext4<B> {
self.open_files[handle.raw() as usize].as_ref().map(|f| f.size)
}
fn mkdir(&mut self, _path: &[u8]) -> bool { false }
fn mkdir(&mut self, path: &[u8]) -> bool {
let (parent_inode_num, dirname) = match self.resolve_parent(path) {
Some(v) => v,
None => return false,
};
let parent_inode = match self.read_inode(parent_inode_num) {
Some(i) => i,
None => return false,
};
if !parent_inode.is_dir() { return false; }
if dir::find_entry(&mut self.device, &self.sb, self.gdt_block, &parent_inode, dirname).is_some() {
return false;
}
let new_inode_num = match self.alloc_inode() {
Some(n) => n,
None => return false,
};
let new_block = match self.alloc_block() {
Some(b) => b,
None => { self.free_inode(new_inode_num); return false; }
};
let mut new_inode = Self::init_empty_inode(0x4000 | 0o755);
new_inode.links_count = 2;
new_inode.size = self.sb.block_size as u64;
new_inode.blocks_count = (self.sb.block_size / 512) as u32;
if !Self::append_extent(&mut new_inode.block_data, 0, new_block as u64, 1) {
self.free_block(new_block);
self.free_inode(new_inode_num);
return false;
}
self.write_inode(new_inode_num, &new_inode);
let mut dir_block = [0u8; 4096];
dir::init_dir_block(&mut dir_block, new_inode_num, parent_inode_num, self.sb.block_size);
io::write_block(&mut self.device, new_block as u64, self.sb.sectors_per_block(), &dir_block);
let parent_inode = match self.read_inode(parent_inode_num) {
Some(i) => i,
None => return false,
};
if !dir::add_entry(&mut self.device, &self.sb, self.gdt_block, &parent_inode, dirname, new_inode_num, 2) {
self.free_block(new_block);
self.free_inode(new_inode_num);
return false;
}
if let Some(mut pi) = self.read_inode(parent_inode_num) {
pi.links_count += 1;
self.write_inode(parent_inode_num, &pi);
}
true
}
}