Skip to content

Commit 1b8c5f9

Browse files
ext2: directory entry iterator implementation
Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
1 parent 16f80bb commit 1b8c5f9

File tree

2 files changed

+112
-7
lines changed

2 files changed

+112
-7
lines changed

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

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use core::mem::MaybeUninit;
2121

2222
use alloc::boxed::Box;
23+
use alloc::string::ToString;
2324
use alloc::sync::{Arc, Weak};
2425

2526
use crate::fs::cache::CachedINode;
@@ -197,10 +198,12 @@ impl DiskINode {
197198

198199
const_assert_eq!(core::mem::size_of::<DiskINode>(), 128);
199200

200-
struct INode {
201+
pub struct INode {
201202
id: usize,
202203
fs: Weak<Ext2>,
203204
inode: Box<DiskINode>,
205+
206+
sref: Weak<INode>,
204207
}
205208

206209
impl INode {
@@ -238,15 +241,31 @@ impl INode {
238241
// SAFETY: We have initialized the inode above.
239242
let inode = unsafe { inode.assume_init() };
240243

241-
log::debug!("ino_table_index={ino_table_index:?} inode={inode:?}");
244+
Some(
245+
icache.make_item_cached(CachedINode::new(Arc::new_cyclic(|sref| Self {
246+
inode,
247+
id,
248+
fs: ext2,
242249

243-
Some(icache.make_item_cached(CachedINode::new(Arc::new(Self {
244-
inode,
245-
id,
246-
fs: ext2,
247-
}))))
250+
sref: sref.clone(),
251+
}))),
252+
)
248253
}
249254
}
255+
256+
pub fn sref(&self) -> Arc<INode> {
257+
self.sref.upgrade().unwrap()
258+
}
259+
260+
pub fn make_dir_entry(
261+
&self,
262+
parent: DirCacheItem,
263+
name: &str,
264+
entry: &DiskDirEntry,
265+
) -> Option<DirCacheItem> {
266+
let inode = self.fs.upgrade()?.find_inode(entry.inode as usize)?;
267+
Some(DirEntry::new(parent, inode, name.to_string()))
268+
}
250269
}
251270

252271
impl INodeInterface for INode {
@@ -262,6 +281,72 @@ impl INodeInterface for INode {
262281
children_len: 0,
263282
})
264283
}
284+
285+
fn dirent(&self, parent: DirCacheItem, index: usize) -> super::Result<Option<DirCacheItem>> {
286+
Ok(DirEntryIter::new(parent, self.sref()).nth(index))
287+
}
288+
}
289+
290+
#[derive(Debug, Copy, Clone)]
291+
#[repr(C, packed)]
292+
pub struct DiskDirEntry {
293+
inode: u32,
294+
entry_size: u16,
295+
name_size: u8,
296+
file_type: u8,
297+
}
298+
299+
pub struct DirEntryIter {
300+
parent: DirCacheItem,
301+
inode: Arc<INode>,
302+
offset: usize,
303+
}
304+
305+
impl DirEntryIter {
306+
pub fn new(parent: DirCacheItem, inode: Arc<INode>) -> Self {
307+
Self {
308+
parent,
309+
inode,
310+
311+
offset: 0,
312+
}
313+
}
314+
}
315+
316+
impl Iterator for DirEntryIter {
317+
type Item = DirCacheItem;
318+
319+
fn next(&mut self) -> Option<Self::Item> {
320+
let filesystem = self.inode.fs.upgrade()?;
321+
let file_size = self.inode.inode.size_lower as usize;
322+
323+
if self.offset + core::mem::size_of::<DiskDirEntry>() > file_size {
324+
return None;
325+
}
326+
327+
let mut entry = Box::<DiskDirEntry>::new_uninit();
328+
329+
let offset = (self.inode.inode.data_ptr[0] as usize * filesystem.superblock.block_size())
330+
+ self.offset;
331+
332+
filesystem.block.device().read(offset, entry.as_bytes_mut());
333+
334+
// SAFETY: We have initialized the entry above.
335+
let entry = unsafe { entry.assume_init() };
336+
337+
let mut name = Box::<[u8]>::new_uninit_slice(entry.name_size as usize);
338+
filesystem.block.device().read(
339+
offset + core::mem::size_of::<DiskDirEntry>(),
340+
MaybeUninit::slice_as_bytes_mut(&mut name),
341+
);
342+
343+
// SAFETY: We have initialized the name above.
344+
let name = unsafe { name.assume_init() };
345+
let name = unsafe { core::str::from_utf8_unchecked(&*name) };
346+
347+
self.offset += entry.entry_size as usize;
348+
self.inode.make_dir_entry(self.parent.clone(), name, &entry)
349+
}
265350
}
266351

267352
pub struct Ext2 {

tools/mkimage.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# XXX: fucking hell andy. you had a reminder to not commit this
2+
# file. you did. you fucking did. you're a fucking idiot. move
3+
# this shit to aero.py.
4+
5+
rm -rf disk.img
6+
7+
dd if=/dev/zero bs=1M count=0 seek=512 of=disk.img
8+
parted -s disk.img mklabel gpt
9+
parted -s disk.img mkpart primary 2048s 100%
10+
sudo losetup -Pf --show disk.img > loopback_dev
11+
sudo mkfs.ext2 `cat loopback_dev`p1
12+
rm -rf disk_image/
13+
mkdir disk_image
14+
sudo mount `cat loopback_dev`p1 disk_image
15+
sudo cp aero.py disk_image/aero.py
16+
sync
17+
sudo umount disk_image/
18+
sudo losetup -d `cat loopback_dev`
19+
sync
20+
rm -rf loopback_dev

0 commit comments

Comments
 (0)