@@ -30,7 +30,7 @@ use spin::RwLock;
30
30
31
31
use crate :: fs:: block:: BlockDeviceInterface ;
32
32
use crate :: fs:: cache:: CachedINode ;
33
- use crate :: fs:: ext2:: disk:: SuperBlock ;
33
+ use crate :: fs:: ext2:: disk:: { FileType , SuperBlock } ;
34
34
use crate :: mem:: paging:: { FrameAllocator , PhysFrame , FRAME_ALLOCATOR } ;
35
35
36
36
use self :: group_desc:: GroupDescriptors ;
@@ -43,30 +43,6 @@ use super::{cache, FileSystemError};
43
43
use super :: inode:: { DirEntry , INodeInterface , Metadata } ;
44
44
use super :: FileSystem ;
45
45
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
-
70
46
pub struct INode {
71
47
id : usize ,
72
48
fs : Weak < Ext2 > ,
@@ -218,6 +194,51 @@ impl INode {
218
194
todo ! ( "triply indirect block" )
219
195
}
220
196
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
+
221
242
pub fn make_dir_entry (
222
243
& self ,
223
244
parent : DirCacheItem ,
@@ -314,44 +335,14 @@ impl INodeInterface for INode {
314
335
}
315
336
316
337
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 ) ?;
352
339
Ok ( DirEntry :: new ( parent, inode, name. to_string ( ) ) )
353
340
}
354
341
342
+ fn mkdir ( & self , name : & str ) -> super :: Result < INodeCacheItem > {
343
+ self . make_inode ( name, FileType :: Directory )
344
+ }
345
+
355
346
fn resolve_link ( & self ) -> super :: Result < String > {
356
347
if !self . metadata ( ) ?. is_symlink ( ) {
357
348
return Err ( FileSystemError :: NotSupported ) ;
0 commit comments