@@ -181,72 +181,102 @@ impl Cage {
181
181
}
182
182
183
183
//------------------MKDIR SYSCALL------------------
184
-
184
+ // Description
185
+ // The mkdir_syscall() creates a new directory named by the path name pointed to by a path as the input parameter in the function.
186
+ // The mode of the new directory is initialized from the "mode" provided as the input parameter in the function.
187
+ // The newly created directory is empty with size 0 and is associated with a new inode of type "DIR".
188
+ // On successful completion, the timestamps for both the newly formed directory and its parent are updated along with their linkcounts.
189
+
190
+ // Function Arguments
191
+ // The mkdir_syscall() receives two arguments:
192
+ // 1. Path - This represents the path at which the new directory will be created.
193
+ // For example: "/parentdir/dir" represents the new directory name as "dir", which will be created at this path (/parentdir/dir).
194
+ // 2. Mode - This represents the permission of the newly created directory.
195
+ // The general mode used is "S_IRWXA": which represents the read, write, and search permissions on the new directory.
196
+
197
+ // Return Values
198
+ // Upon successful creation of the directory, 0 is returned.
199
+ // Otherwise, an error with a proper errorNumber and errorMessage is returned based on the different scenarios.
200
+ //
201
+ // Tests
202
+ // All the different scenarios for mkdir_syscall() are covered and tested in the "fs_tests.rs" file under "mkdir_syscall_tests" section.
203
+ //
185
204
pub fn mkdir_syscall ( & self , path : & str , mode : u32 ) -> i32 {
186
- //Check that path is not empty
205
+
206
+ // Check that the given input path is not empty
187
207
if path. len ( ) == 0 {
188
208
return syscall_error ( Errno :: ENOENT , "mkdir" , "given path was null" ) ;
189
209
}
190
- let truepath = normpath ( convpath ( path) , self ) ;
191
210
192
- //pass the metadata to this helper. If passed table is none, then create new instance
211
+ // Store the FileMetadata into a helper variable which is used for fetching the metadata of a given inode from the Inode Table.
193
212
let metadata = & FS_METADATA ;
194
213
214
+ // Retrieve the absolute path from the root directory. The absolute path is then used to validate directory paths
215
+ // while navigating through subdirectories and establishing new directory at the given location.
216
+ let truepath = normpath ( convpath ( path) , self ) ;
217
+
218
+ // Walk through the absolute path which returns a tuple consisting of inode number of file (if it exists), and inode number of parent (if it exists)
195
219
match metawalkandparent ( truepath. as_path ( ) ) {
196
- //If neither the file nor parent exists
220
+ // Case 1: When neither the file directory nor the parent directory exists
197
221
( None , None ) => syscall_error (
198
222
Errno :: ENOENT ,
199
223
"mkdir" ,
200
224
"a directory component in pathname does not exist or is a dangling symbolic link" ,
201
225
) ,
202
226
203
- //If the file doesn't exist but the parent does
227
+ // Case 2: When the file doesn't exist but the parent directory exists
204
228
( None , Some ( pardirinode) ) => {
205
229
let filename = truepath. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ; //for now we assume this is sane, but maybe this should be checked later
206
230
207
231
let effective_mode = S_IFDIR as u32 | mode;
208
-
209
- //assert sane mode bits
232
+ // Check for the condition if the mode bits are correct and have the required permissions to create a directory
210
233
if mode & ( S_IRWXA | S_FILETYPEFLAGS as u32 ) != mode {
211
234
return syscall_error ( Errno :: EPERM , "mkdir" , "Mode bits were not sane" ) ;
212
235
}
213
236
237
+ // Fetch the next available inode number using the FileSystem MetaData table
238
+ // Create a new inode of type "Dir" representing a directory and set the required attributes
214
239
let newinodenum = FS_METADATA
215
240
. nextinode
216
241
. fetch_add ( 1 , interface:: RustAtomicOrdering :: Relaxed ) ; //fetch_add returns the previous value, which is the inode number we want
217
242
let time = interface:: timestamp ( ) ; //We do a real timestamp now
218
-
219
243
let newinode = Inode :: Dir ( DirectoryInode {
220
- size : 0 ,
244
+ size : 0 , //initial size of a directory is 0 as it is empty
221
245
uid : DEFAULT_UID ,
222
246
gid : DEFAULT_GID ,
223
247
mode : effective_mode,
224
- linkcount : 3 ,
225
- refcount : 0 , //2 because ., and .., as well as reference in parent directory
248
+ linkcount : 3 , //because of the directory name(.), itself, and reference to the parent directory(..)
249
+ refcount : 0 , //because no file descriptors are pointing to it currently
226
250
atime : time,
227
251
ctime : time,
228
252
mtime : time,
229
- filename_to_inode_dict : init_filename_to_inode_dict ( newinodenum, pardirinode) ,
253
+ filename_to_inode_dict : init_filename_to_inode_dict ( newinodenum, pardirinode) , //Establish a mapping between the newly created inode and the parent directory inode for easy retrieval and linking
230
254
} ) ;
231
255
232
- if let Inode :: Dir ( ref mut parentdir) =
233
- * ( metadata. inodetable . get_mut ( & pardirinode) . unwrap ( ) )
256
+ // Insert a reference to the file in the parent directory and update the inode attributes
257
+ // Fetch the inode of the parent directory and only proceed when its type is directory.
258
+ if let Inode :: Dir ( ref mut parentdir) = * ( metadata. inodetable . get_mut ( & pardirinode) . unwrap ( ) )
234
259
{
235
260
parentdir
236
261
. filename_to_inode_dict
237
262
. insert ( filename, newinodenum) ;
238
- parentdir. linkcount += 1 ;
263
+ parentdir. linkcount += 1 ; // Since the parent is now associated to the new directory, its linkcount will increment by 1
264
+ parentdir. ctime = time; // Here, update the ctime and mtime for the parent directory as well
265
+ parentdir. mtime = time;
239
266
}
240
- //insert a reference to the file in the parent directory
241
267
else {
242
268
unreachable ! ( ) ;
243
269
}
270
+ // Update the inode table by inserting the newly formed inode mapped with its inode number.
244
271
metadata. inodetable . insert ( newinodenum, newinode) ;
245
272
log_metadata ( & metadata, pardirinode) ;
246
273
log_metadata ( & metadata, newinodenum) ;
247
- 0 //mkdir has succeeded
274
+
275
+ // Return 0 when mkdir has succeeded
276
+ 0
248
277
}
249
278
279
+ // Case 3: When the file directory name already exists, then return the error.
250
280
( Some ( _) , ..) => syscall_error (
251
281
Errno :: EEXIST ,
252
282
"mkdir" ,
0 commit comments