📄 mfs_filesys.c
字号:
//////////////////////////////////////////////////////////////////////////////////// Copyright (c) 2002 Xilinx, Inc. All rights reserved.//// Xilinx, Inc.// // File : mfs_filesys.c// Date : 2002, March 20.// Company: Xilinx// Group : Emerging Software Technologies//// Description : //// $Header: /devl/xcs/repo/env/Jobs/MDT/sw/os/xilmfs/src/mfs_filesys.c,v 1.1 2002/04/08 20:40:54 sid Exp $//////////////////////////////////////////////////////////////////////////////////#include <string.h>#include "xilmfs.h"struct mfs_file_block mfs_file_system[MFS_MAX_FILE_BLOCKS];int mfs_free_block_list;struct mfs_open_file_struct mfs_open_files[MFS_MAX_OPEN_FILES];int mfs_num_open_files; /* the number of mfs_open_files */int mfs_current_dir;/** * initialize the file system; * this function must be called before any file system operations */void mfs_init_fs() { int i; /* set the zeroth block to be a dir_block with itself as its parent */ /* initialize the free block list */ mfs_file_system[0].block_type = MFS_BLOCK_TYPE_DIR; mfs_file_system[0].index = 0; mfs_file_system[0].next_block = 0; mfs_file_system[0].prev_block = 0; mfs_file_system[0].u.dir_data.num_entries = 2; /* .. and . */ mfs_file_system[0].u.dir_data.num_deleted = 0; strcpy(mfs_file_system[0].u.dir_data.dir_ent[0].name, ".."); mfs_file_system[0].u.dir_data.dir_ent[0].deleted = 'n'; mfs_file_system[0].u.dir_data.dir_ent[0].index = 0; /* .. = index of this block */ strcpy(mfs_file_system[0].u.dir_data.dir_ent[1].name, "."); mfs_file_system[0].u.dir_data.dir_ent[1].deleted = 'n'; mfs_file_system[0].u.dir_data.dir_ent[1].index = 0; /* . = index of this block */ for (i = 1; i < MFS_MAX_FILE_BLOCKS; i++) { mfs_file_system[i].block_type = MFS_BLOCK_TYPE_EMPTY; mfs_file_system[i].next_block = i+1; mfs_file_system[i].index = i; mfs_file_system[i].prev_block = i-1; } mfs_file_system[MFS_MAX_FILE_BLOCKS-1].next_block = 0; /* the last block points to 0 */ /* initialize free block list to the first free index = 1 */ mfs_free_block_list = 1; /* initialize current dir to the top level */ mfs_current_dir = 0; /* initialize mfs_open_files */ for (i = 0; i < MFS_MAX_OPEN_FILES; i++) mfs_open_files[i].mode = MFS_MODE_FREE; mfs_num_open_files = 0;}/** * return 0 for failure and 1 for success * on success: * return dir_block = index of dir block (may not always be mfs_current_dir) * return dir_index = index within dir_block or undefined on failure * on failure: * return dir_block = index of dir block that has the first "free entry" or * index of last searched block which should have no free entries or * -1 to indicate error * return dir_index = index within dir_block of first free entry or * MFS_MAX_LOCAL_ENT if last searched block has no free entry or * -1 to indicate error */static int get_dir_ent_base(const char *filename, int *dir_block, int *dir_index) { /* *dir_index = 0; *dir_block = valid dir corresponding to filename prefixes processed so far, on entry to this proc */ int numentriesleft = mfs_file_system[*dir_block].u.dir_data.num_entries; char tmpfilename[MFS_MAX_FILENAME_LENGTH]; int index = 0; while(*filename != '/' && *filename != '\0') { tmpfilename[index] = *filename; filename++; index++; } tmpfilename[index] = '\0'; while (numentriesleft > 0) { if (*dir_index == MFS_MAX_LOCAL_ENT) { /* move to the next dir block */ *dir_index = 0; *dir_block = mfs_file_system[*dir_block].next_block; } if (mfs_file_system[*dir_block].u.dir_data.dir_ent[*dir_index].deleted != 'y' && !strcmp(mfs_file_system[*dir_block].u.dir_data.dir_ent[*dir_index].name, tmpfilename)) { /* found the entry */ /* *dir_index = index; */ /* *dir_block = dir; */ if (*filename == '\0'|| (*filename == '/' && *(filename+1)== '\0')) /* this is the base file name, ignore final '/' if present */ return 1; else { /* tmpname is the current prefix, filename is the rest of the path */ *dir_block = mfs_file_system[*dir_block].u.dir_data.dir_ent[*dir_index].index; *dir_index = 0; filename++; return(get_dir_ent_base(filename, dir_block, dir_index)); } } *dir_index += 1; numentriesleft--; } if (*filename == '\0' || (*filename == '/' && *(filename+1)=='\0')) { /* could not find the base name but path prefix is correct */ return 0; } else { /* path prefix is wrong */ *dir_block = -1; *dir_index = -1; return 0; }}/** * filename is an arbitrarily long '/' separated path name * each component of the path name is never longer than MFS_MAX_FILENAME_LENGTH * if the first character is '/', search starting at the root directory * else search starting at the current directory * return 0 for failure and 1 for success * on success: * return dir_block = index of dir block (may not always be mfs_current_dir) * return dir_index = index within dir_block or undefined on failure * on failure: * return dir_block = index of dir block that has the first "free entry" or * index of last searched block which should have no free entries or * -1 to indicate error * return dir_index = index within dir_block of first free entry or * MFS_MAX_LOCAL_ENT if last searched block has no free entry or * -1 to indicate error */static int get_dir_ent(const char *filename, int *dir_block, int *dir_index) { if (filename != NULL && *filename != '\0') { if (*filename == '/') { filename++; *dir_block = 0; } else { *dir_block = mfs_current_dir; } *dir_index = 0; if (*filename == '\0') /* done - looking for the root directory */ return 1; else return(get_dir_ent_base(filename, dir_block, dir_index)); } /* error condition */ *dir_block = -1; *dir_index = -1; return 0;}/** * return 0 for failure and 1 for success * on success: * return dir_block = index of dir block (may not always be mfs_current_dir) * return dir_index = index within dir_block or undefined on failure * on failure: * return dir_block = index of dir block that has the first "free entry" or * index of last searched block which should have no free entries * return dir_index = index within dir_block of first free entry or MFS_MAX_LOCAL_ENT if last searched block has no free entry*/// static int get_dir_ent_by_index(int file_index, int *dir_block, int *dir_index) {// int numentriesleft = mfs_file_system[mfs_current_dir].u.dir_data.num_entries;// *dir_index = 0;// *dir_block = mfs_current_dir;// while (numentriesleft > 0) {// if (*dir_index == MFS_MAX_LOCAL_ENT) { /* move to the next dir block */// *dir_index = 0;// *dir_block = mfs_file_system[*dir_block].next_block;// }// if (mfs_file_system[*dir_block].u.dir_data.dir_ent[*dir_index].deleted != 'y' &&// mfs_file_system[*dir_block].u.dir_data.dir_ent[*dir_index].index == file_index) { /* found the entry */// /* *dir_index = index; */// /* *dir_block = dir; */// return 1;// }// *dir_index += 1;// numentriesleft--;// }// return 0;// }static int get_dir_ent_by_index(int file_index, int *dir_block, int *dir_index) { int numentriesleft; *dir_block = mfs_file_system[file_index].u.dir_data.dir_ent[0].index; numentriesleft = mfs_file_system[*dir_block].u.dir_data.num_entries; *dir_index = 0; while (numentriesleft > 0) { if (*dir_index == MFS_MAX_LOCAL_ENT) { /* move to the next dir block */ *dir_index = 0; *dir_block = mfs_file_system[*dir_block].next_block; } if (mfs_file_system[*dir_block].u.dir_data.dir_ent[*dir_index].deleted != 'y' && mfs_file_system[*dir_block].u.dir_data.dir_ent[*dir_index].index == file_index) { /* found the entry */ /* *dir_index = index; */ /* *dir_block = dir; */ return 1; } *dir_index += 1; numentriesleft--; } return 0;}/** * modify mfs_current_dir to index of newdir if it exists * mfs_current_dir is not modified otherwise * return 1 for success and 0 for failure */int mfs_change_dir(const char *newdir) { /* search current dir for newdir and change current dir if found */ /* return 1 for success, 0 for failure */ int new_dir_block; int new_dir_index; if (get_dir_ent(newdir, &new_dir_block, &new_dir_index)) { mfs_current_dir = mfs_file_system[new_dir_block].u.dir_data.dir_ent[new_dir_index].index; return 1; } return 0;}/** * allocate a new block from the free list * new_entry_index is modified to point to the newly allocated block * return 1 on success, 0 on failure */static int get_next_free_block(int *new_entry_index) { if (mfs_free_block_list != 0) { *new_entry_index = mfs_free_block_list; /* update free_list */ mfs_free_block_list = mfs_file_system[*new_entry_index].next_block; if (mfs_free_block_list != 0) { mfs_file_system[mfs_free_block_list].prev_block = 0; } else { /* free list is empty so do not update prev pointer of first element */ } /* remove block from free list */ mfs_file_system[*new_entry_index].prev_block = 0; mfs_file_system[*new_entry_index].next_block = 0; return 1; } return 0; /* failed to get free block */}/** * create a new directory block, and initialize it with info about . and .. * if this dir wants to know its name, it needs to ask its parent */static int create_new_file(int file_type, int *new_entry_index, int parent_dir_block) { if (get_next_free_block(new_entry_index)) { if (file_type == MFS_BLOCK_TYPE_DIR) { /* fill in the new dir block with .. and . */ mfs_file_system[*new_entry_index].block_type = MFS_BLOCK_TYPE_DIR; mfs_file_system[*new_entry_index].u.dir_data.num_entries = 2; mfs_file_system[*new_entry_index].u.dir_data.num_deleted = 0; mfs_file_system[*new_entry_index].u.dir_data.dir_ent[0].index = parent_dir_block; /* parent dir of this new dir */ strcpy(mfs_file_system[*new_entry_index].u.dir_data.dir_ent[0].name, ".."); mfs_file_system[*new_entry_index].u.dir_data.dir_ent[0].deleted = 'n'; mfs_file_system[*new_entry_index].u.dir_data.dir_ent[1].index = *new_entry_index; strcpy(mfs_file_system[*new_entry_index].u.dir_data.dir_ent[1].name, "."); mfs_file_system[*new_entry_index].u.dir_data.dir_ent[1].deleted = 'n'; return 1; } else if (file_type == MFS_BLOCK_TYPE_FILE) { mfs_file_system[*new_entry_index].block_type = MFS_BLOCK_TYPE_FILE; mfs_file_system[*new_entry_index].block_size = 0; /* empty file */ return 1; } else { /* unknown file_type - error */ return 0; } } return 0;}/** * return a pointer to the first char that follows the last '/' in filename * unless the last char in filename is a '/', in which case return a pointer * to the first char that follows the previous '/' * if there is no '/' in filename, return filename itself */static char *get_basename(const char *filename) { char *base_filename = (char*)filename; while(*filename != '\0') { if (*filename == '/') { filename++; if (*filename != '\0') base_filename = (char*)filename; /* the first char after / */ } else filename++; } return base_filename;}/** * special strcpy for filename that omits the final '/' in the stored file name * return 2 if final '/' is seen * return 1 otherwise */static int set_filename(char *to_name, char *from_name) { while (*from_name != '\0') { if (*from_name == '/') { *to_name = '\0'; return 2; } *to_name = *from_name; to_name++; from_name++; } *to_name = '\0'; return 1;}/** * return the first directory block corresponding to this directory block * the first directory block contains info about the number of files in the dir */static int get_first_dir_block(int dir_block) { while(mfs_file_system[dir_block].prev_block != 0) { dir_block = mfs_file_system[dir_block].prev_block; } return dir_block;}/** * Create a new file or dir named filename * If a dir or file of the same name exists, return 0 * If there is no space on the file system to create file, return 0 * else create the new file or dir, add entry in current dir table * and return index of first block of file or dir */static int create_file(const char *filename, int file_type) { int new_dir_block; int new_dir_index; int new_entry_index; int new_block; int first_dir_block; if (get_dir_ent(filename, &new_dir_block, &new_dir_index)) { /* file already exists */ return 0 ; /* cannot create file if it already exists */ } else if (new_dir_block == -1 || new_dir_index == -1) { /* file does not exist but path prefix does not exist either */ return 0; /* cannot create file because its parent dir does not exist */ } else { /* create the file */ /* first check if the current dir block is full and allocate a new dir block if needed */ if (new_dir_index == MFS_MAX_LOCAL_ENT) { /* create a new dir block linked from this one */ if (get_next_free_block(&new_block)) { /* found a free block */ mfs_file_system[new_block].prev_block = new_dir_block; mfs_file_system[new_block].next_block = 0; mfs_file_system[new_block].block_type = MFS_BLOCK_TYPE_DIR; mfs_file_system[new_block].u.dir_data.num_entries = 0; mfs_file_system[new_block].u.dir_data.num_deleted = 0; mfs_file_system[new_dir_block].next_block = new_block; new_dir_block = new_block; new_dir_index = 0; } else { /* no space for new block - return failure */ return 0; } } /* at this point new_dir_index and new_dir_block both point to the first free entry */ first_dir_block = get_first_dir_block(new_dir_block); if (!create_new_file(file_type, &new_entry_index, first_dir_block)) { /* cannot create new file */ return 0; /* failure */ }; /* update number of entries in current block */ mfs_file_system[new_dir_block].u.dir_data.num_entries += 1; /* update number of entries in directory if it is different than current block */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -