// 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; }
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"); }
//============== UFS INTERFACE LAYER ========================== int init_FS(int fd){ // Boot block dummy block (Because no boot loader nothing...) bzero(nullbuf, BLOCKSIZE); write(fd, nullbuf, BLOCKSIZE); // Initialize variables int i; nsuperblocks = 1; ninodeblocks = 8; nbootblocks = 1; nrootdirblocks = 1; ndatablocks = TOTALBLOCKS - nsuperblocks - ninodeblocks - nbootblocks - nrootdirblocks; INODETABLESIZE = (ninodeblocks*BLOCKSIZE)/sizeof(struct INode); MAXDIRENTRIES = BLOCKSIZE/ sizeof(struct DirEntry); DATABLOCKSTART = BLOCKSIZE*(TOTALBLOCKS - ndatablocks); INODEBLOCKSTART = BLOCKSIZE*(nsuperblocks+nbootblocks); //Initialize super block strcpy(s.sb_vname, "root"); s.sb_ninodes = (ninodeblocks*BLOCKSIZE)/sizeof(struct INode); s.sb_nblocks = ndatablocks; s.sb_nfreeblocks = s.sb_nblocks; s.sb_nfreeinodes = s.sb_ninodes; s.sb_flags = 0; bzero(s.sb_freeblocks, CACHESIZE); bzero(s.sb_freeinodes, CACHESIZE); s.sb_freeblockindex = CACHESIZE; s.sb_freeinodeindex = CACHESIZE; s.sb_chktime = time(NULL); s.sb_ctime = time(NULL); write(fd, &s, sizeof(struct SuperBlock)); write(fd, nullbuf, (nsuperblocks*BLOCKSIZE) - sizeof(struct SuperBlock)); printf("Superblock initialized!\n"); // Write initialized list of inodes nullINode.i_size = 0; nullINode.i_atime = 0; nullINode.i_ctime = 0; nullINode.i_mtime = 0; bzero(nullINode.i_blocks, 13); nullINode.i_mode = 0; nullINode.i_uid = 0; nullINode.i_gid = 0; nullINode.i_gen = 0; nullINode.i_nlinks = 0; for(i=0; i<INODETABLESIZE; i++) write(fd, &nullINode, sizeof(struct INode)); write(fd, &nullbuf, BLOCKSIZE%sizeof(struct INode)); printf("Inodes initialized!\n"); // Write initialized list of directory entries // Fill the remaining empty datablocks printf("%d\n",ndatablocks+nrootdirblocks ); for(i=0; i<ndatablocks+nrootdirblocks; i++) write(fd, &nullbuf, BLOCKSIZE); printf("All data blocks initialized!\n"); // Write free block information (data structures) 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 = 1; in.i_uid = 1; in.i_nlinks = 0; in.i_mode = 0; struct DirEntry d; bzero(d.d_entry.d_name, MAXNAMELENGTH); strcpy(d.d_entry.d_name,"."); s.sb_rootdir = currDirINode = d.d_entry.d_inode = allocINode(fd, &in); d.d_offset = 0; allocDirEntry(fd, &in, &d); writeInode(fd, s.sb_rootdir, &in); updateSB(fd); printf("\n"); o.ofo_inode = NULL; o.ofo_mode = o.ofo_ref = 0; return 0; }