📄 mfs_filesys.c
字号:
if (new_dir_block != first_dir_block) mfs_file_system[first_dir_block].u.dir_data.num_entries += 1; mfs_file_system[new_dir_block].u.dir_data.dir_ent[new_dir_index].index = new_entry_index; set_filename(mfs_file_system[new_dir_block].u.dir_data.dir_ent[new_dir_index].name, get_basename(filename)); mfs_file_system[new_dir_block].u.dir_data.dir_ent[new_dir_index].deleted = 'n'; return new_entry_index; }}/** * move a list of blocks starting and start_index and chained * through next_block pointers and ending at end_index * to the free list * the blocks are all already marked as MFS_BLOCK_TYPE_EMPTY * the prev_block of start_index is 0, and the next_block of end_index = 0 */static int move_to_free_list(int start_index, int end_index) { if (mfs_free_block_list != 0) { /* free list exists and is non empty */ /* prepend this list to the existing free list */ mfs_file_system[mfs_free_block_list].prev_block = end_index; mfs_file_system[end_index].next_block = mfs_free_block_list; } else { /* free list is empty - no need to prepend */ } mfs_free_block_list = start_index; return 1; /* always succeeds */}/** * mark all the data blocks associated with a file as free and add them * to the free list * return 1 for success and 0 for failure * delete dir blocks only if the directory is empty */static int delete_data_in_file(int file_index) { int next_block; int current_block; if (mfs_file_system[file_index].block_type == MFS_BLOCK_TYPE_FILE) { /* OK to delete */ } else if (mfs_file_system[file_index].block_type == MFS_BLOCK_TYPE_DIR) { /* first verify whether dir is actually empty */ if (mfs_file_system[file_index].u.dir_data.num_entries - mfs_file_system[file_index].u.dir_data.num_deleted != 2) { /* dir is not empty so cannot delete */ return 0; } } else { /* don't know what this is; cannot delete */ return 0; } /* at this point we know that it is OK to delete */ current_block = file_index; while((next_block = mfs_file_system[current_block].next_block) != 0) { mfs_file_system[current_block].block_type = MFS_BLOCK_TYPE_EMPTY; current_block = next_block; } mfs_file_system[current_block].block_type = MFS_BLOCK_TYPE_EMPTY; move_to_free_list(file_index, current_block); return 1;}/** * delete the data blocks corresponding to the file and then delete the * file entry from its directory * return 1 on success, 0 on failure * delete will not work on a directory unless the directory is empty */int mfs_delete_file (char *filename) { int dir_block; int dir_index; int entry_index; int new_block; int first_dir_block; if (!get_dir_ent(filename, &dir_block, &dir_index)) { /* file does not exist */ return 0 ; /* cannot delete file if it does not exist */ } entry_index = mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].index; if (delete_data_in_file(entry_index)) { /* now delete the file entry from the directory */ mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].deleted = 'y'; mfs_file_system[dir_block].u.dir_data.num_deleted += 1; first_dir_block = get_first_dir_block(dir_block); if (dir_block != first_dir_block) mfs_file_system[first_dir_block].u.dir_data.num_deleted += 1; } return 1;}/** * create a new empty directory inside the current directory * return index of new directory in file system if success, 0 if failure */int mfs_create_dir(char *newdir) { return create_file(newdir, MFS_BLOCK_TYPE_DIR);}/** * delete the directory named newdir if it exists, and is empty * return 1 on success, 0 on failure * cannot delete . or .. */int mfs_delete_dir (char *newdir) { if (!strcmp(newdir,"..") || !strcmp(newdir,".")) return 0; return mfs_delete_file(newdir);}/** * rename from_file to to_file * works for dirs as well as files * cannot rename to something that already exists * return 1 on success, 0 on failure */int mfs_rename_file(char *from_file, char *to_file) { int from_dir_block; int to_dir_block; int from_dir_index; int to_dir_index; if (get_dir_ent(from_file, &from_dir_block, &from_dir_index) && !get_dir_ent(to_file, &to_dir_block, &to_dir_index)) { set_filename(mfs_file_system[from_dir_block].u.dir_data.dir_ent[from_dir_index].name, get_basename(to_file)); return 1; } return 0;}/** * return 0 if filename is not a file in the current directory * return 1 if filename is a file in the current directory * return 2 if filename is a directory in the current directory */int mfs_exists_file(char *filename) { int dir_block; int dir_index; int file_block; if (get_dir_ent(filename, &dir_block, &dir_index)) { file_block = mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].index; if (mfs_file_system[file_block].block_type == MFS_BLOCK_TYPE_DIR) return 2; else if (mfs_file_system[file_block].block_type == MFS_BLOCK_TYPE_FILE) return 1; else return 0; } return 0;}/** * return the name of the current directory * in dirname = pre_allocated buffer of at least 16 chars * return 1 if success, 0 if failure */int mfs_get_current_dir_name(char *dirname){ int dir_block; int dir_index; int file_block; file_block = mfs_current_dir; if (file_block == 0) { strcpy(dirname, "/"); return 1; } if(!get_dir_ent_by_index(file_block, &dir_block, &dir_index)) { return 0; /* cannot find current dir in its parent */ } strcpy(dirname, mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].name); return 1;}/** * get the number of used blocks and the number of free blocks in the file system through pointers * the return value is 1 (for success) and 0 for failure to obtain the numbers */int mfs_get_usage(int *num_blocks_used, int *num_blocks_free) { int i; *num_blocks_used = 0; *num_blocks_free = 0; for ( i = 0; i < MFS_MAX_FILE_BLOCKS; i++) { if (mfs_file_system[i].block_type == MFS_BLOCK_TYPE_EMPTY) *num_blocks_free += 1; else *num_blocks_used += 1; } return 1;}/** * returns the index of the first free entry in the mfs_open_files array * if there is no free entry, returns -1 */static int get_first_free_ftab_index() { int i; for (i=0; i < MFS_MAX_OPEN_FILES; i++) { if (mfs_open_files[i].mode == MFS_MODE_FREE) return i; } return -1;}/** * mode can be MFS_MODE_READ/MFS_MODE_WRITE/MFS_MODE_CREATE * this function should be used for FILEs and not DIRs * no error checking (is this FILE and not DIR?) is done for MFS_MODE_READ * MFS_MODE_CREATE automatically creates a FILE and not a DIR * MFS_MODE_WRITE fails if the specified file is a DIR * return index of file in array mfs_open_files or -1 */int mfs_file_open(const char *filename, int mode) { int dir_block; int dir_index; int current_index; if (mfs_num_open_files >= MFS_MAX_OPEN_FILES) {/* cannot open any more files */ return -1; } if (mode == MFS_MODE_READ || mode == MFS_MODE_WRITE) { /* look for existing file */ if (get_dir_ent(filename, &dir_block, &dir_index)) { /* found it */ if (mode == MFS_MODE_WRITE && mfs_file_system[mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].index].block_type != MFS_BLOCK_TYPE_FILE) { /* cannot open anything other than FILE for write */ return -1; } mfs_num_open_files++; current_index = get_first_free_ftab_index(); mfs_open_files[current_index].first_block = mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].index; mfs_open_files[current_index].current_block = mfs_open_files[current_index].first_block; mfs_open_files[current_index].mode = mode; mfs_open_files[current_index].offset = 0; return current_index; } else { //file/dir not found, open it in create mode if (mode == MFS_MODE_WRITE) mode = MFS_MODE_CREATE; } } if (mode == MFS_MODE_CREATE) { /* create a new file */ dir_block = create_file(filename, MFS_BLOCK_TYPE_FILE); if (dir_block == 0) { /* failed to create the file */ return -1; } mfs_num_open_files++; current_index = get_first_free_ftab_index(); mfs_open_files[current_index].first_block = dir_block; mfs_open_files[current_index].current_block = dir_block; mfs_open_files[current_index].mode = MFS_MODE_WRITE; mfs_open_files[current_index].offset = 0; return current_index; } return -1;}/** * fd should be a valid index in mfs_open_files array * Works only if fd points to a file and not a dir * buf should be a pointer to a pre-allocated buffer of size buflen or more * buflen chars are read and placed in buf * if fewer than buflen chars are available then only that many chars are read * return num bytes read or 0 for error=no bytes read*/int mfs_file_read(int fd, char *buf, int buflen) { int num_read = 0; char *from_ptr = &(mfs_file_system[mfs_open_files[fd].current_block].u.block_data[mfs_open_files[fd].offset]); int num_left ; num_left = mfs_file_system[mfs_open_files[fd].current_block].block_size ; if (num_left > MFS_BLOCK_DATA_SIZE) num_left = MFS_BLOCK_DATA_SIZE; num_left -= mfs_open_files[fd].offset ; while (buflen > 0) { if (num_left == 0) { /* see if there is a next_block */ int next_block = mfs_file_system[mfs_open_files[fd].current_block].next_block; if (next_block == 0) { /* nothing more to read */ break; } if (mfs_file_system[next_block].block_size == 0) { /* nothing more to read */ break; } from_ptr = &(mfs_file_system[next_block].u.block_data[0]); num_left = mfs_file_system[next_block].block_size; mfs_open_files[fd].current_block = next_block; mfs_open_files[fd].offset = 0; } *buf = *from_ptr; *buf++; *from_ptr++; mfs_open_files[fd].offset += 1; num_read++; num_left--; buflen--; } return num_read;}/** * fd should be a valid index in mfs_open_files array * buf should be a pointer to a pre-allocated buffer of size buflen or more * buflen chars are read from buf and written to 1 or more blocks of the file * return 1 for success or 0 for error=unable to write to file*/ int mfs_file_write (int fd, const char *buf, int buflen) { char *to_ptr = &(mfs_file_system[mfs_open_files[fd].current_block].u.block_data[mfs_open_files[fd].offset]); int num_left = MFS_BLOCK_DATA_SIZE - mfs_open_files[fd].offset; while (buflen > 0) { *to_ptr = *buf; *buf++; *to_ptr++; mfs_open_files[fd].offset += 1; num_left--; mfs_file_system[mfs_open_files[fd].current_block].block_size +=1; if (mfs_open_files[fd].current_block != mfs_open_files[fd].first_block) mfs_file_system[mfs_open_files[fd].first_block].block_size += 1; buflen--; if (num_left == 0 && buflen > 0) { /* create next_block */ int new_block; /* create a new file block linked from this one */ if (get_next_free_block(&new_block)) { /* found a free block */ mfs_file_system[new_block].prev_block = mfs_open_files[fd].current_block; mfs_file_system[new_block].next_block = 0; mfs_file_system[new_block].block_type = MFS_BLOCK_TYPE_FILE; mfs_file_system[new_block].block_size = 0; mfs_file_system[mfs_open_files[fd].current_block].next_block = new_block; mfs_open_files[fd].current_block = new_block; mfs_open_files[fd].offset = 0; } else { /* no space for new block - return failure */ return 0; } to_ptr = &(mfs_file_system[new_block].u.block_data[0]); num_left = MFS_BLOCK_DATA_SIZE; } } return 1;}/** * recover the file table entry in mfs_open_files corresponding to the fd * if the fd is not valid, return 0 * fd is not valid if the index in mfs_open_files is out of range, or * if the corresponding entry is not an open file * return 1 on success */int mfs_file_close(int fd) { if (fd <0 || fd >= MFS_MAX_OPEN_FILES) return 0; if (mfs_open_files[fd].mode != MFS_MODE_FREE) { mfs_open_files[fd].mode = MFS_MODE_FREE; mfs_num_open_files--; return 1; } return 0;}/** * seek to a given offset within the file * if MFS_SEEK_END is specified, the offset can be either 0 or negative * otherwise offset should be positive or 0 * return 0 on failure, 1 on success * it is an error to seek before beginning of file or after the end of file */long mfs_file_lseek(int fd, long offset, int whence) { if (fd <0 || fd >= MFS_MAX_OPEN_FILES || mfs_open_files[fd].mode == MFS_MODE_FREE) return 0; if (whence == MFS_SEEK_SET || whence == MFS_SEEK_CUR) { if (whence == MFS_SEEK_CUR) offset += mfs_open_files[fd].offset; else mfs_open_files[fd].current_block = mfs_open_files[fd].first_block; if (offset > mfs_file_system[mfs_open_files[fd].first_block].block_size) { /* attempting to seek beyond end of file */ return 0; } } else { /* whence == MFS_SEEK_END */ if (offset > 0) { /* cannot seek beyond end of file */ return 0; } else { offset += mfs_file_system[mfs_open_files[fd].first_block].block_size; mfs_open_files[fd].current_block = mfs_open_files[fd].first_block; } } /* at this point offset is a positive value, guaranteed to be within the file * mfs_open_files[fd].current_block is set to first_block for MFS_SEEK_SET and MFS_SEEK_END * and is assumed to be set correctly for MFS_SEEK_CUR */ while(offset > MFS_BLOCK_DATA_SIZE) { mfs_open_files[fd].current_block = mfs_file_system[mfs_open_files[fd].current_block].next_block; offset -= MFS_BLOCK_DATA_SIZE; } mfs_open_files[fd].offset = offset; return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -