// 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"); }
int closeDir(int dirhandle){ // Find the corresponding open file object and remove it int i; struct InCoreINode icn; struct DirEntry d; struct INode in; int inodeNo = isOpen(dirhandle, &icn); if( inodeNo==-1 ){ printf("Directory not open!\n"); return -1; } if( icn.ic_inode.i_nlinks==0 ){ // readDirEntry(icn.ic_inode, ) printf("Not a directory!%d\n", icn.ic_ino); return -1; } for(i=1; i<icn.ic_inode.i_nlinks; i++){ readDirEntry(icn.ic_dev, &icn.ic_inode, i, &d); readINode(icn.ic_dev, d.d_entry.d_inode, &in); if( in.i_nlinks==0 ) closeFile(d.d_entry.d_inode); else closeDir(d.d_entry.d_inode); } removeOpenFile(dirhandle); }
int freeINode(int fd, int inodeNo){ struct INode in; int i; readINode(fd, inodeNo, &in); for(i=0; i<13 && in.i_blocks[i]>0; i++){ freeBlock(fd, in.i_blocks[i]); } lseek(fd, INODEBLOCKSTART + inodeNo*sizeof(struct INode), SEEK_SET); write(fd, &nullINode, sizeof(struct INode)); printf("Freed inode number %d\n", inodeNo); s.sb_nfreeinodes++; }
// Create a directory int makeDir(int fd, char *dname, int uid, int gid, int attributes){ printf("Creating new directory %s\n",dname); int parINodeNo, inodeNo; struct INode parent_in; struct DirEntry d; //Tokenize the dname, check for validity and find its parent directory parINodeNo = currDirINode; readINode(fd, parINodeNo, &parent_in); // Check if the dname already exists in the INode in if( fileExists(fd, dname, parent_in, &d)!=-1 ){ printf("Directory already exists!\n\n"); return -1; } // Initialize an inode and data block for new directory struct INode in; in.i_atime = 0; bzero(in.i_blocks, 13); in.i_blocks[0] = allocBlock(fd); in.i_gen = 0; in.i_gid = gid; in.i_uid = uid; in.i_nlinks = 0; in.i_mode = attributes; bzero(d.d_entry.d_name, MAXNAMELENGTH); strcpy(d.d_entry.d_name, "."); int allocatedINode = allocINode(fd, &in); d.d_entry.d_inode = allocatedINode; d.d_offset = 0; allocDirEntry(fd, &in, &d); bzero(d.d_entry.d_name, MAXNAMELENGTH); strcpy(d.d_entry.d_name, ".."); d.d_entry.d_inode = parINodeNo; allocDirEntry(fd, &in, &d); writeInode(fd, allocatedINode, &in); // Add its DirEntry in its parent INode and rewrite Inode entry bzero(d.d_entry.d_name, MAXNAMELENGTH); strcpy(d.d_entry.d_name, dname); d.d_entry.d_inode = allocatedINode; allocDirEntry(fd, &parent_in, &d); writeInode(fd, parINodeNo, &parent_in); printf("\n"); return 0; }
int openDir(int fd, char *dname){ struct INode parent_in; struct InCoreINode* icn; struct DirEntry d; readINode(fd, currDirINode, &parent_in); // Tokenize the name and find its inode no int linkNo = fileExists(fd, dname, parent_in, &d); if( linkNo==-1 ){ printf("No such directory exists!\n"); return -1; } int dirhandle = isOpen(d.d_entry.d_inode, icn); if( dirhandle!=-1 ) return dirhandle; // Add the inode to open file object DLL and return the reference number return addOpenFile(fd, d.d_entry.d_inode); }
int addOpenFile(int fd, int inodeNo){ printf("Opening directory no %d\n", inodeNo); struct InCoreINode *icn = malloc(sizeof(struct InCoreINode)); struct INode in; readINode(fd, inodeNo, &icn->ic_inode); icn->ic_ref = 0; icn->ofo_curpos = 0; icn->ic_ino = inodeNo; icn->ic_dev = fd; icn->ic_next = NULL; icn->ic_prev = NULL; struct InCoreINode* temp = o.ofo_inode; if( o.ofo_inode==NULL ){ o.ofo_inode = icn; return inodeNo; } while( temp->ic_next!=NULL ){ temp = temp->ic_next; } temp->ic_next = icn; icn->ic_prev = temp; return inodeNo; }
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"); }