@@ -30,7 +30,7 @@ use spin::RwLock;
3030
3131use crate :: fs:: block:: BlockDeviceInterface ;
3232use crate :: fs:: cache:: CachedINode ;
33- use crate :: fs:: ext2:: disk:: SuperBlock ;
33+ use crate :: fs:: ext2:: disk:: { FileType , SuperBlock } ;
3434use crate :: mem:: paging:: { FrameAllocator , PhysFrame , FRAME_ALLOCATOR } ;
3535
3636use self :: group_desc:: GroupDescriptors ;
@@ -43,30 +43,6 @@ use super::{cache, FileSystemError};
4343use super :: inode:: { DirEntry , INodeInterface , Metadata } ;
4444use 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-
7046pub 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