Skip to content

Commit 9f1871c

Browse files
ext2: mkdir
Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
1 parent 67c8a38 commit 9f1871c

File tree

2 files changed

+90
-70
lines changed

2 files changed

+90
-70
lines changed

src/aero_kernel/src/fs/ext2/disk.rs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1+
use crate::fs::inode;
12
use crate::utils::CeilDiv;
23

3-
use super::FileType;
4-
54
#[derive(Debug, Copy, Clone)]
65
#[repr(C, packed)]
76
pub struct SuperBlock {
@@ -129,21 +128,45 @@ impl DirEntry {
129128
name_bytes.copy_from_slice(name.as_bytes());
130129
}
131130

132-
pub fn avaliable_size(&self) -> usize {
133-
if self.inode == 0 {
134-
self.entry_size as usize
135-
} else {
136-
0
137-
}
138-
}
139-
140131
pub fn as_bytes(&self) -> &[u8] {
141132
unsafe {
142133
core::slice::from_raw_parts(self as *const Self as *const u8, self.entry_size as usize)
143134
}
144135
}
145136
}
146137

138+
#[repr(u8)]
139+
#[derive(PartialEq)]
140+
pub enum FileType {
141+
Unknown = 0,
142+
Fifo = 1,
143+
CharDev = 2,
144+
Directory = 4,
145+
BlockDev = 6,
146+
File = 8,
147+
Symlink = 10,
148+
Socket = 12,
149+
}
150+
151+
impl FileType {
152+
pub fn bits(&self) -> u16 {
153+
let val = *self as u8;
154+
(val as u16) << 12
155+
}
156+
}
157+
158+
impl From<FileType> for inode::FileType {
159+
fn from(ty: FileType) -> Self {
160+
match ty {
161+
FileType::Symlink => Self::Symlink,
162+
FileType::Directory => Self::Directory,
163+
FileType::BlockDev | FileType::CharDev => Self::Device,
164+
165+
_ => Self::File,
166+
}
167+
}
168+
}
169+
147170
#[repr(C)]
148171
#[derive(Debug, Default, Copy, Clone)]
149172
pub struct INode {
@@ -168,6 +191,12 @@ pub struct INode {
168191
}
169192

170193
impl INode {
194+
pub fn set_file_type(&mut self, file_type: FileType) {
195+
// The last 4 bits are used to store the filetype.
196+
let mask = 0b0000_1111_1111_1111u16;
197+
self.type_and_perm = file_type.bits() | (self.type_and_perm & mask);
198+
}
199+
171200
pub fn file_type(&self) -> FileType {
172201
let ty = self.type_and_perm >> 12;
173202

src/aero_kernel/src/fs/ext2/mod.rs

Lines changed: 51 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use spin::RwLock;
3030

3131
use crate::fs::block::BlockDeviceInterface;
3232
use crate::fs::cache::CachedINode;
33-
use crate::fs::ext2::disk::SuperBlock;
33+
use crate::fs::ext2::disk::{FileType, SuperBlock};
3434
use crate::mem::paging::{FrameAllocator, PhysFrame, FRAME_ALLOCATOR};
3535

3636
use self::group_desc::GroupDescriptors;
@@ -43,30 +43,6 @@ use super::{cache, FileSystemError};
4343
use super::inode::{DirEntry, INodeInterface, Metadata};
4444
use super::FileSystem;
4545

46-
#[derive(PartialEq)]
47-
pub enum FileType {
48-
Fifo,
49-
CharDev,
50-
Directory,
51-
BlockDev,
52-
File,
53-
Symlink,
54-
Socket,
55-
Unknown,
56-
}
57-
58-
impl From<FileType> for super::inode::FileType {
59-
fn from(ty: FileType) -> Self {
60-
match ty {
61-
FileType::Symlink => Self::Symlink,
62-
FileType::Directory => Self::Directory,
63-
FileType::BlockDev | FileType::CharDev => Self::Device,
64-
65-
_ => Self::File,
66-
}
67-
}
68-
}
69-
7046
pub struct INode {
7147
id: usize,
7248
fs: Weak<Ext2>,
@@ -218,6 +194,51 @@ impl INode {
218194
todo!("triply indirect block")
219195
}
220196

197+
pub fn make_inode(&self, name: &str, typ: FileType) -> super::Result<INodeCacheItem> {
198+
if !self.metadata()?.is_directory() {
199+
return Err(FileSystemError::NotSupported);
200+
}
201+
202+
if DirEntryIter::new(self.sref())
203+
.find(|(e, _)| e == name)
204+
.is_some()
205+
{
206+
return Err(FileSystemError::EntryExists);
207+
}
208+
209+
assert!(self.inode.read().hl_count != 0, "ext2: dangling inode");
210+
211+
let fs = self.fs.upgrade().expect("ext2: filesystem was dropped");
212+
213+
let inode = fs.bgdt.alloc_inode().expect("ext2: out of inodes");
214+
let ext2_inode = inode.downcast_arc::<INode>().expect("ext2: invalid inode");
215+
216+
{
217+
let mut inode = ext2_inode.inode.write();
218+
inode.set_file_type(typ);
219+
inode.hl_count += 1;
220+
}
221+
222+
// TODO: scan for unused directory entries and check if this can be
223+
// inserted into the existing block.
224+
let block = self.append_block().unwrap();
225+
let block_size = fs.superblock.block_size();
226+
227+
let mut entry = Box::<disk::DirEntry>::new_uninit();
228+
fs.block.read(block * block_size, entry.as_bytes_mut());
229+
230+
// SAFETY: We have initialized the entry above.
231+
let mut entry = unsafe { entry.assume_init() };
232+
233+
entry.entry_size = block_size as _;
234+
entry.inode = ext2_inode.id as _;
235+
entry.file_type = 2;
236+
entry.set_name(name);
237+
238+
fs.block.write(block * block_size, entry.as_bytes());
239+
Ok(inode)
240+
}
241+
221242
pub fn make_dir_entry(
222243
&self,
223244
parent: DirCacheItem,
@@ -314,44 +335,14 @@ impl INodeInterface for INode {
314335
}
315336

316337
fn touch(&self, parent: DirCacheItem, name: &str) -> super::Result<DirCacheItem> {
317-
let fs = self.fs.upgrade().expect("ext2: filesystem was dropped");
318-
let inode = fs.bgdt.alloc_inode().ok_or(FileSystemError::EntryExists)?;
319-
320-
let ext2_inode = inode.downcast_arc::<INode>().expect("ext2: invalid inode");
321-
322-
log::debug!(
323-
"ext2: allocated inode alloced_id={} this_id={}",
324-
ext2_inode.id,
325-
self.id
326-
);
327-
328-
let dirent_size = name.len() + core::mem::size_of::<disk::DirEntry>();
329-
330-
if let Some((_name, _entry)) =
331-
DirEntryIter::new(self.sref()).find(|(_, e)| e.avaliable_size() >= dirent_size)
332-
{
333-
todo!()
334-
} else {
335-
let block = self.append_block().unwrap();
336-
let block_size = fs.superblock.block_size();
337-
338-
let mut entry = Box::<disk::DirEntry>::new_uninit();
339-
fs.block.read(block * block_size, entry.as_bytes_mut());
340-
341-
// SAFETY: We have initialized the entry above.
342-
let mut entry = unsafe { entry.assume_init() };
343-
344-
entry.entry_size = block_size as _;
345-
entry.inode = ext2_inode.id as _;
346-
entry.file_type = 2;
347-
entry.set_name(name);
348-
349-
fs.block.write(block * block_size, entry.as_bytes());
350-
}
351-
338+
let inode = self.make_inode(name, FileType::File)?;
352339
Ok(DirEntry::new(parent, inode, name.to_string()))
353340
}
354341

342+
fn mkdir(&self, name: &str) -> super::Result<INodeCacheItem> {
343+
self.make_inode(name, FileType::Directory)
344+
}
345+
355346
fn resolve_link(&self) -> super::Result<String> {
356347
if !self.metadata()?.is_symlink() {
357348
return Err(FileSystemError::NotSupported);

0 commit comments

Comments
 (0)