/* * Remove/delete an existing file * * This function returns zero on success. */ int sfs_remove(int fd) { blkid frame_bid, next_frame_bid; sfs_dirblock_t dir; sfs_inode_frame_t frame; int i, j; char *tmp; /* TODO: update dir */ sfs_read_block((char*)&dir, fdtable[fd].dir_bid); for (i = 0; i < SFS_DB_NINODES; i++) { if (dir.inodes[i] == fdtable[fd].inode_bid) { dir.inodes[i] = 0; } } // Write dir block to update inode values sfs_write_block((char*)&dir, fdtable[fd].dir_bid); /* TODO: free inode and all its frames */ frame_bid = fdtable[fd].inode.first_frame; while (frame_bid != 0) { sfs_read_block((char*)&frame, frame_bid); // Free all the content blocks for each frame for (j = 0; j < SFS_FRAME_COUNT; j++) { tmp = (char*)malloc(BLOCK_SIZE); memset(tmp, 0, BLOCK_SIZE); sfs_write_block(tmp, frame.content[j]); sfs_free_block(frame.content[j]); free(tmp); } next_frame_bid = frame.next; memset(&frame, 0, BLOCK_SIZE); sfs_write_block((char*)&frame, frame_bid); sfs_free_block(frame_bid); frame_bid = next_frame_bid; } // Free the inode memset((char*)&fdtable[fd].inode, 0, BLOCK_SIZE); sfs_write_block((char*)&fdtable[fd].inode, fdtable[fd].inode_bid); sfs_free_block(fdtable[fd].inode_bid); /* TODO: close the file */ sfs_close(fd); return 0; }
/* * 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; }
W sfs_i_truncate (struct inode *ip, W newsize) { int nblock, blockno, inblock, offset, dinblock; int i; W errno; W fd; struct fs *fsp; struct sfs_inode *sfs_ip; fd = ip->i_device; fsp = ip->i_fs; sfs_ip = &(ip->i_private.sfs_inode); nblock = ROUNDUP (newsize, fsp->fs_blksize)/fsp->fs_blksize; if (nblock < ip->i_size_blk) { /* 余分なブロックを開放 */ blockno = nblock; if (blockno < SFS_DIRECT_BLOCK_ENTRY) { /* 直接ブロックの範囲内 */ for(i = blockno; i < SFS_DIRECT_BLOCK_ENTRY; ++i) { if (sfs_ip->sfs_i_direct[i] > 0) sfs_free_block(fd, fsp, sfs_ip->sfs_i_direct[i]); sfs_ip->sfs_i_direct[i] = 0; } sfs_free_indirect(fd, fsp, sfs_ip, 0, 0); sfs_free_all_dindirect(fd, fsp, sfs_ip, 0); } else if (blockno < (SFS_DIRECT_BLOCK_ENTRY + (SFS_INDIRECT_BLOCK_ENTRY * SFS_INDIRECT_BLOCK))) { /* 一重間接ブロックの範囲内 */ inblock = (blockno - SFS_DIRECT_BLOCK_ENTRY); offset = inblock % SFS_INDIRECT_BLOCK; inblock = inblock / SFS_INDIRECT_BLOCK; sfs_free_indirect(fd, fsp, sfs_ip, offset, inblock); sfs_free_all_dindirect(fd, fsp, sfs_ip, 0); } else if (blockno < (SFS_DIRECT_BLOCK_ENTRY + (SFS_INDIRECT_BLOCK_ENTRY * SFS_INDIRECT_BLOCK) + (SFS_DINDIRECT_BLOCK_ENTRY * SFS_INDIRECT_BLOCK * SFS_INDIRECT_BLOCK))) { /* 二重間接ブロックの範囲内 */ blockno = blockno - (SFS_DIRECT_BLOCK_ENTRY + SFS_INDIRECT_BLOCK_ENTRY * SFS_INDIRECT_BLOCK); inblock = blockno / (SFS_DINDIRECT_BLOCK_ENTRY * SFS_INDIRECT_BLOCK); dinblock = (blockno % (SFS_DINDIRECT_BLOCK_ENTRY * SFS_INDIRECT_BLOCK)) / SFS_INDIRECT_BLOCK; offset = blockno % SFS_INDIRECT_BLOCK; sfs_free_dindirect(fd, fsp, sfs_ip, offset, dinblock, inblock); sfs_free_all_dindirect(fd, fsp, sfs_ip, inblock+1); } } ip->i_size = newsize; ip->i_size_blk = nblock; ip->i_dirty = 1; /* これは deallocate の中で処理するのが普通 */ errno = sfs_i_sync(ip); if (errno) { return(errno); } /* ここで fs を sync する必要があるか? */ errno = sfs_syncfs(fsp); if (errno) { return(errno); } return (EP_OK); }
/* * Remove/delete an existing file * This function returns zero on success. */ int sfs_remove(int fd_num) { blkid frame_bid; sfs_dirblock_t dir; char block_ptr[BLOCK_SIZE]; int i; fd_struct_t fd = fdtable[fd_num]; //Set the index of the inode to zero blkid dir_bid = fd.dir_bid; blkid inode_bid = fd.inode_bid; //Remove the inode from the directory sfs_read_block(block_ptr, dir_bid); dir = *(sfs_dirblock_t*)block_ptr; //Find the index at which the inode is stored int count = 0; while(count < SFS_DB_NINODES){ if(dir.inodes[count] == inode_bid){ dir.inodes[count] = 0; break; } count++; } dir.inodes[inode_bid] = 0; sfs_write_block(&dir, dir_bid); /* TODO: free inode and all its frames */ sfs_inode_t inode; sfs_read_block(block_ptr, inode_bid); inode = *(sfs_inode_t*)block_ptr; char frame_ptr[BLOCK_SIZE]; sfs_inode_frame_t frame; blkid next_frame = inode.first_frame; //Iterate through each of the nonzero content blocks //sfs_free_block() on all of them while(next_frame != 0){ sfs_read_block(frame_ptr, next_frame); frame = *(sfs_inode_frame_t*)frame_ptr; //Check each of the entries of the frame and free nonzero blocks int i; for(i = 0; i < SFS_FRAME_COUNT; i++){ blkid content_blk = frame.content[i]; if(content_blk != 0){ sfs_free_block(content_blk); } } sfs_free_block(next_frame); next_frame = frame.next; } /* TODO: close the file */ sfs_free_block(inode_bid); //Reset the file description to default fd.valid = 0; memset(&fd.inode, 0, sizeof(sfs_inode_t)); fd.dir_bid = 0; fd.inode_bid = 0; return 0; }
/* * 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; }