/* * Remove an existing empty directory and return 0 on success. * If the dir does not exist or still contains files, return -1. */ int sfs_rmdir(char *dirname) { sfs_dirblock_t currentDir, prevDir, nextDir; blkid bid, prevBlkid, nextBlkid; /* TODO: check if the dir exists */ bid = sfs_find_dir(dirname); if (bid != 0) { // Directory exists sfs_read_block((char*)¤tDir, bid); /* TODO: check if no files */ int i; for (i = 0; i < SFS_DB_NINODES; i++) { if (currentDir.inodes[i] != 0) { // directory is not empty printf("ERROR: inodes not empty = %d\n", currentDir.inodes[i]); return -1; } } /* TODO: go thru the linked list to delete the dir*/ // Need to change the next_dir pointer of the previous dir and dir to be deleted nextBlkid = sb.first_dir; if (nextBlkid == bid) { // Deleting the root directory sb.first_dir = 0; sfs_read_block((char*)¤tDir, nextBlkid); currentDir.next_dir = 0; memset(currentDir.dir_name, 0, sizeof(currentDir.dir_name)); return 0; } else { while (nextBlkid != bid) { prevBlkid = nextBlkid; sfs_read_block((char*)&prevDir, nextBlkid); nextBlkid = prevDir.next_dir; } nextBlkid = currentDir.next_dir; } // Remove the directory: update the linked list next_dir variable prevDir.next_dir = nextBlkid; currentDir.next_dir = 0; // Remove the dir_name of the dir to be deleted memset(currentDir.dir_name, 0, sizeof(currentDir.dir_name)); // Flush the removed directory and prevDir sfs_write_block((char*)¤tDir, bid); sfs_write_block((char*)&prevDir, prevBlkid); // Update the freemap so that deleted dir is empty sfs_free_block(bid); return 0; } return -1; }
/* * Create a new directory and return 0 on success. * If the dir already exists, return -1. */ int sfs_mkdir(char *dirname) { /* TODO: test if the dir exists */ /* TODO: insert a new dir to the linked list */ blkid nextBlkid; sfs_dirblock_t dir, new_dir; // Try finding the directory if it exists blkid bid = sfs_find_dir(dirname); if (bid == 0) { // Directory does not exists, create a new one bid = sfs_alloc_block(); // Add the new directory to the directory linked list nextBlkid = sb.first_dir; if (nextBlkid == 0) { sb.first_dir = bid; sfs_write_block((char*)&sb, 0); } else { sfs_read_block((char*)&dir, nextBlkid); while (dir.next_dir != 0) { nextBlkid = dir.next_dir; sfs_read_block((char*)&dir, nextBlkid); } dir.next_dir = bid; sfs_write_block((char*)&dir, nextBlkid); } // Create new directory with next_dir=0 and dir_name new_dir.next_dir = 0; memset(new_dir.dir_name, 0, sizeof(new_dir.dir_name)); // Empty dir_name memset(new_dir.inodes, 0, sizeof(new_dir.inodes)); // Empty inodes strcpy(new_dir.dir_name, dirname); // Copy new dir_name sfs_write_block((char*)&new_dir, bid); return 0; } // Directory already exists return -1; }
/* * Open a file. If it does not exist, create a new one. * Allocate a file desriptor for the opened file and return the fd. */ int sfs_open(char *dirname, char *name) { blkid dir_bid = 0, inode_bid = 0; char inode_ptr[BLOCK_SIZE]; sfs_inode_t inode; sfs_dirblock_t dir; fd_struct_t *fd_ptr; fd_struct_t fd; //Finds a free file descriptor number int fd_num = 0; while(fd_num < SFS_MAX_OPENED_FILES){ fd = fdtable[fd_num]; if(fd.valid == 0){ fd.valid = 1; fd.cur = 0; break; } else if(fd_num == SFS_MAX_OPENED_FILES - 1){ printf("The maximum number of files are already in use\n"); return -1; } else{ fd_num++; } } //Find the directory in which the specified file is contained dir_bid = sfs_find_dir(dirname); sfs_read_block(&dir, dir_bid); fd.dir_bid = dir_bid; //Iterate through all the indices of the inodes to find the file int count = 0; int fd_set = 0; int free_inode = -1; char *file_name; while(count < SFS_DB_NINODES){ inode_bid = dir.inodes[count]; if(inode_bid == 0){ if(free_inode == -1){ free_inode = count; } count++; continue; } //Read the inode at the specified index sfs_read_block(inode_ptr, inode_bid); inode = *(sfs_inode_t*)inode_ptr; file_name = inode.file_name; if(strcmp(file_name, name) == 0){ fd.inode = inode; fd.inode_bid = inode_bid; fd_set = 1; break; } count++; } //Create a new file if(fd_set == 0){ //Allocate a block for the inode blkid new_inode_bid = sfs_alloc_block(); //Put the inode bid into the directory inode array dir.inodes[free_inode] = new_inode_bid; sfs_write_block(&dir, dir_bid); strcpy(inode.file_name, name); //Allocate a block for the first frame blkid new_frame_bid = sfs_alloc_block(); inode.first_frame = new_frame_bid; inode.size = 0; //Place the inode in the file descriptor array fd.inode = inode; fd.inode_bid = new_inode_bid; sfs_write_block(&inode, new_inode_bid); sfs_read_block(&inode, new_inode_bid); //Allocate a block for the first content block of the frame char tmp[BLOCK_SIZE]; sfs_read_block(tmp, new_frame_bid); sfs_inode_frame_t new_frame = *(sfs_inode_frame_t*)tmp; blkid new_content_bid = sfs_alloc_block(); new_frame.content[0] = new_content_bid; sfs_write_block(&new_frame, new_frame_bid); } //Set the file descriptor in the file descriptor table fdtable[fd_num] = fd; return fd_num; }
/* * Remove an existing empty directory and return 0 on success. * If the dir does not exist or still contains files, return -1. */ int sfs_rmdir(char *dirname) { /* TODO: check if the dir exists */ blkid dir_bid = sfs_find_dir(dirname); if(dir_bid == 0){ printf("ERROR sfs_rmdir: Specified directory does not exist\n"); return -1; } if(sb.first_dir == 0 || dir_bid == 0){ //The directory does not exist return -1; } else{ //Unset the corresponding bit in the freemap sfs_free_block(dir_bid); } //Find the directories that come before and after the //directory we want to delete blkid next_dir = sb.first_dir; //First block blkid current_dir; //Current block is sb blkid previous_dir = 0; //No previous blocks char block_ptr[BLOCK_SIZE]; sfs_dirblock_t dir; if(next_dir == dir_bid){ sfs_read_block(block_ptr, next_dir); dir = *(sfs_dirblock_t*)block_ptr; blkid block_to_copy = dir.next_dir; sfs_read_block(&sb, 0); sb.first_dir = block_to_copy; sfs_write_block(&sb, 0); } //General case while(next_dir != dir_bid){ previous_dir = current_dir; current_dir = next_dir; sfs_read_block(block_ptr, next_dir); dir = *(sfs_dirblock_t*)block_ptr; next_dir = dir.next_dir; //The next block is what we want to remove if(next_dir == dir_bid){ //Set the next dir of the current block to the next+1 block sfs_read_block(block_ptr, next_dir); dir = *(sfs_dirblock_t*)block_ptr; blkid block_to_copy = dir.next_dir; sfs_read_block(block_ptr, current_dir); dir = *(sfs_dirblock_t*)block_ptr; dir.next_dir = block_to_copy; sfs_write_block(&dir, current_dir); } } return 0; }
/* * Create a new directory and return 0 on success. * If the dir already exists, return -1. */ int sfs_mkdir(char *dirname) { //Check if the directory has a valid name if(sizeof(dirname) > 120){ printf("Dir name exceeds max allowed characters.\n"); return -1; } //Test if the dir exists if(sfs_find_dir(dirname) != 0){ return -1; } else{ //Initialize variables blkid next_dir_id; char block_ptr[BLOCK_SIZE]; sfs_dirblock_t dir; //Allocate space for a new block blkid new_bid = sfs_alloc_block(); //Set the next_dir in the last directory block next_dir_id = sb.first_dir; sfs_read_block(block_ptr, next_dir_id); dir = *(sfs_dirblock_t*)block_ptr; if(next_dir_id == 0){ sb.first_dir = new_bid; sfs_write_block(&sb, 0); } else{ while(next_dir_id != 0){ sfs_read_block(block_ptr, next_dir_id); dir = *(sfs_dirblock_t*)block_ptr; //Next dir is zero, set it to the next available block if(dir.next_dir == 0){ blkid modified_dir_id = next_dir_id; sfs_read_block(block_ptr, modified_dir_id); dir = *(sfs_dirblock_t*)block_ptr; dir.next_dir = new_bid; //A value was changed, so this must be flushed to disk sfs_write_block(&dir, modified_dir_id); next_dir_id = 0; } else{ next_dir_id = dir.next_dir; } } } //Create a temporary directory and initialize its members //Set the next dir, name, and set all its inodes to zero sfs_dirblock_t temp_dir; temp_dir.next_dir = 0; strcpy(temp_dir.dir_name, dirname); memset(&temp_dir.inodes[0], 0, SFS_DB_NINODES * sizeof(blkid)); //Write the temporary block into the disk sfs_write_block(&temp_dir, new_bid); } return 0; }
/* * Open a file. If it does not exist, create a new one. * Allocate a file desriptor for the opened file and return the fd. */ int sfs_open(char *dirname, char *name) { blkid dir_bid = 0, inode_bid = 0; sfs_inode_t *inode, new_inode; sfs_dirblock_t dir; int fd; int i; /* TODO: find a free fd number */ for (i = 0; i < SFS_MAX_OPENED_FILES; i++) { if (fdtable[i].valid == 0) { // Found a free fd fd = i; break; } } /* TODO: find the dir first */ dir_bid = sfs_find_dir(dirname); if (dir_bid == 0) { printf("ERROR: the directory does not exists\n"); return -1; } sfs_read_block((char*)&dir, dir_bid); /* TODO: traverse the inodes to see if the file exists. If it exists, load its inode. Otherwise, create a new file. */ for (i = 0; i < SFS_DB_NINODES; i++) { if (dir.inodes[i] != 0) { sfs_read_block((char*)&new_inode, dir.inodes[i]); if (strcmp(new_inode.file_name, name) == 0) { inode_bid = dir.inodes[i]; break; } } } if (inode_bid == 0) { // Allocate a block to store new inode inode_bid = sfs_alloc_block(); // Find empty space in dir.inodes[] and set inode_bid for (i=0; i<SFS_DB_NINODES; i++) { if (dir.inodes[i] == 0) { dir.inodes[i] = inode_bid; break; } } // Did not find the inode, create a new one new_inode.first_frame = 0; new_inode.size = 0; memset(new_inode.file_name, 0, sizeof(new_inode.file_name)); strcpy(new_inode.file_name, name); sfs_write_block((char*)&new_inode, inode_bid); sfs_write_block((char*)&dir, dir_bid); } /* TODO: create a new file */ fdtable[fd].dir_bid = dir_bid; fdtable[fd].inode_bid = inode_bid; fdtable[fd].inode = new_inode; fdtable[fd].cur = 0; fdtable[fd].valid = 1; return fd; }