// Delete directory (if it is empty) int removeDirHelper(int fd, char *dname, int parINodeNo){ int i; struct INode parent_in; // Tokenize the name and find its parent directory readINode(fd, parINodeNo, &parent_in); // Find dname in parent directory and read its inode struct DirEntry d; int linkNo = fileExists(fd, dname, parent_in, &d); int inodeNo = d.d_entry.d_inode; if( linkNo==-1 ){ printf("Directory does not exist!\n"); return -1; } if( inodeNo == s.sb_rootdir ){ printf("Cannot delete root directory!\n"); return -1; } struct INode in; readINode(fd, inodeNo, &in); // On each of the link in its inode call recursive delete after taking permission if( in.i_nlinks==0 ){ printf("Not a valid directory!\n"); return -1; } if( in.i_nlinks>2 ){ printf("Directory not empty! Do you want to proceed[y]? "); char c; scanf("%c",&c); if( c!='y' || c!='Y' ){ return -1; } struct DirEntry temp; struct INode tempINode; for(i=1; i<in.i_nlinks; i++){ readDirEntry(fd, i, &temp); if( strcmp(temp.d_entry.d_name, "..")==0 ) continue; readINode(fd, temp.d_entry.d_inode, &tempINode); if( tempINode.i_nlinks==0 ) freeINode(fd, temp.d_entry.d_inode); else{ removeDirHelper(fd, temp.d_entry.d_name, inodeNo); } } } freeINode(fd, inodeNo); freeDirEntry(fd, &parent_in, linkNo); printf("Directory successfully deleted!\n"); }
void testINodes(UINT nDBlks, UINT nINodes) { printf("\n==== inode test ====\n"); //test makefs printf("\n---- makefs ----\n"); FileSystem fs; UINT succ = makefs(nDBlks, nINodes, &fs); if(succ == 0) { printf("makefs succeeded with filesystem size: %d\n", fs.nBytes); } printf("\nSuperblock:\n"); printSuperBlock(&fs.superblock); printf("\nINodes:\n"); printINodes(&fs); printf("\nData blocks:\n"); printDBlks(&fs); printf("\nFree inode cache:\n"); printFreeINodeCache(&fs.superblock); printf("\nFree dblk cache:\n"); printFreeDBlkCache(&fs.superblock); assert(fs.diskINodeBlkOffset == 1); assert(fs.diskDBlkOffset == 1 + nINodes / INODES_PER_BLK); //test allocINode until no free inodes are left printf("\n---- allocINode ----\n"); for(int i = 0; i < nINodes; i++) { INode testINode; UINT id = allocINode(&fs, &testINode); printf("allocINode call %d returned ID %d\n", i, id); printINode(&testINode); } assert(fs.superblock.nFreeINodes == 0); //allocINode should fail gracefully when no free inodes are left INode testINode; UINT id = allocINode(&fs, &testINode); printf("Invalid allocINode call returned ID %d\n", id); assert(id == -1); printf("\nSuperblock:\n"); printSuperBlock(&fs.superblock); printf("\nINodes:\n"); printINodes(&fs); printf("\nFree inode cache:\n"); printFreeINodeCache(&fs.superblock); //test random freeINode printf("\n---- random freeINode ----\n"); int shuffled[nINodes]; for(int i = 0; i < nINodes; i++) { shuffled[i] = i; } shuffle(shuffled, nINodes); for(int i = 0; i < nINodes; i++) { printf("Freeing inode id: %d\n", shuffled[i]); succ = freeINode(&fs, shuffled[i]); assert(succ == 0); } printf("%d, %d\n", fs.superblock.nFreeINodes, nINodes); assert(fs.superblock.nFreeINodes == nINodes); printf("\nSuperblock:\n"); printSuperBlock(&fs.superblock); printf("\nINodes:\n"); printINodes(&fs); printf("\nFree inode cache:\n"); printFreeINodeCache(&fs.superblock); //test allocINode until no free inodes are left printf("\n---- allocINode ----\n"); for(int i = 0; i < nINodes; i++) { INode testINode; UINT id = allocINode(&fs, &testINode); printf("allocINode call %d returned ID %d\n", i, id); } assert(fs.superblock.nFreeINodes == 0); //test ordered freeINode printf("\n---- ordered freeINode ----\n"); for(int i = 0; i < nINodes; i++) { printf("Freeing inode id: %d\n", i); succ = freeINode(&fs, i); assert(succ == 0); } assert(fs.superblock.nFreeINodes == nINodes); printf("\nSuperblock:\n"); printSuperBlock(&fs.superblock); printf("\nINodes:\n"); printINodes(&fs); printf("\nFree inode cache:\n"); printFreeINodeCache(&fs.superblock); //temporary variables for read/write test if(nINodes < NUM_TEST_INODES) { printf("\nError: must have at least %d inodes to do read/write test!\n", NUM_TEST_INODES); exit(1); } INode inodes[NUM_TEST_INODES]; UINT inodeIds[NUM_TEST_INODES]; for(int i = 0; i < NUM_TEST_INODES; i++) { inodeIds[i] = -1; } //test allocINode printf("\n---- allocINode (2) ----\n"); for(int i = 0; i < NUM_TEST_INODES; i++) { inodeIds[i] = allocINode(&fs, &inodes[i]); printf("allocINode call %d returned ID %d\n", i, inodeIds[i]); printINode(&inodes[i]); //ensure allocated IDs are valid and unique assert(inodeIds[i] >= 0 && inodeIds[i] < nINodes); for(UINT j = 0; j < i; j++) { assert(inodeIds[i] != inodeIds[j]); } } //test group writeINode printf("\n---- writeINode ----\n"); for(int i = 0; i < NUM_TEST_INODES; i++) { //inodes[i]._in_owner = TEST_OWNER; strcpy(inodes[i]._in_owner, TEST_OWNER); inodes[i]._in_permissions = TEST_PERMISSIONS; inodes[i]._in_modtime = TEST_MODTIME; inodes[i]._in_accesstime = TEST_ACCESSTIME; inodes[i]._in_filesize = TEST_FILESIZE; printf("Writing test data to inode id: %d\n", inodeIds[i]); succ = writeINode(&fs, inodeIds[i], &inodes[i]); assert(succ == 0); } printINodes(&fs); //test group readINode printf("\n---- readINode ----\n"); for(int i = 0; i < NUM_TEST_INODES; i++) { INode testINode; printf("Reading test data from inode id: %d\n", inodeIds[i]); succ = readINode(&fs, inodeIds[i], &testINode); printINode(&testINode); assert(succ == 0); //assert(testINode._in_owner = TEST_OWNER); assert(!strcmp(testINode._in_owner, TEST_OWNER)); assert(testINode._in_permissions = TEST_PERMISSIONS); assert(testINode._in_modtime = TEST_MODTIME); assert(testINode._in_accesstime = TEST_ACCESSTIME); assert(testINode._in_filesize = TEST_FILESIZE); } //test modifying read/writeINode printf("\n---- modify read/writeINode ----\n"); printINodes(&fs); for(int i = NUM_TEST_INODES - 1; i >= 0; i--) { succ = readINode(&fs, inodeIds[i], &inodes[i]); assert(succ == 0); printf("Modifying inode id: %d\n", inodeIds[i]); //inodes[i]._in_owner = "WILL"; strcpy(inodes[i]._in_owner, "WILL"); inodes[i]._in_permissions = TEST_PERMISSIONS - 1; inodes[i]._in_modtime = TEST_MODTIME - 1; inodes[i]._in_accesstime = TEST_ACCESSTIME - 1; inodes[i]._in_filesize = TEST_FILESIZE - 1; succ = writeINode(&fs, inodeIds[i], &inodes[i]); assert(succ == 0); INode testINode2; succ = readINode(&fs, inodeIds[i], &testINode2); printINode(&testINode2); assert(succ == 0); //assert(testINode2._in_owner = inodes[i]._in_owner); assert(!strcmp(testINode2._in_owner, inodes[i]._in_owner)); assert(testINode2._in_permissions = inodes[i]._in_permissions); assert(testINode2._in_modtime = inodes[i]._in_modtime); assert(testINode2._in_accesstime = inodes[i]._in_accesstime); assert(testINode2._in_filesize = inodes[i]._in_filesize); } printf("\n---- closefs ----\n"); succ = closefs(&fs); assert(succ == 0); printf("\n==== inode test complete ====\n"); }