📄 testfs.c
字号:
if( !testfs_initialized ) { int i; for( i = 0; i < TESTFS_NFILE; i++ ) { node[i].next = free_node; node[i].refcnt = -1; free_node = &node[i]; } for( i = 0; i < TESTFS_NBLOCK; i++ ) { block[i].u.next = free_block; block[i].pos = -1; free_block = &block[i]; } testfs_initialized = true; } // Allocate a node to be the root of this filesystem and // initialize it. root = free_node; if( root == NULL ) return ENOSPC; free_node = root->next; root->next = root; // form circular list root->parent = root; // I'm my own parent! root->refcnt = 1; // don't want to ever lose root strcpy( root->name, "root"); root->status.st_mode = __stat_mode_DIR; root->status.st_ino = root-&node[0]; root->status.st_dev = 0; root->status.st_nlink = 1; root->status.st_uid = 0; root->status.st_gid = 0; root->status.st_size = 0; root->status.st_atime = testfs_time(); root->status.st_mtime = testfs_time(); root->status.st_ctime = testfs_time(); for( i = 0; i < TESTFS_FILEBLOCKS; i++ ) root->u.dir.nodes[i] = NULL; mte->root = (cyg_dir)root; return 0;}// -------------------------------------------------------------------------static int testfs_umount ( cyg_mtab_entry *mte ){ testfs_node *root = (testfs_node *)mte->root; // Non-empty filesystem, do not unmount if( root->refcnt != 1 ) return EBUSY; // Otherwise just return it to the free pool root->next = free_node; root->refcnt = -1; free_node = root; // Clear root pointer mte->root = CYG_DIR_NULL; // That's all folks. return ENOERR;}// -------------------------------------------------------------------------static int testfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *path, int mode, cyg_file *file ){ testfs_node *nd, *parent; int err; char name[TESTFS_NAMESIZE]; cyg_bool lastp; err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp ); if( lastp && err == ENOENT && (mode & O_CREAT) ) { int i; // No node there, if the O_CREAT bit is set then we must // create a new one. The parent and name results will have been filled // in, so we know where to put it. // first check that there is space for it for( i = 0; i < TESTFS_FILEBLOCKS; i++ ) if( parent->u.dir.nodes[i] == NULL ) break; if( i == TESTFS_FILEBLOCKS ) return ENOSPC; // Allocate a new node nd = free_node; if( nd == NULL ) return ENOSPC; free_node = nd->next; // Add to directory list parent->u.dir.nodes[i] = nd; parent->refcnt++; // Fill in details nd->parent = parent; nd->refcnt = 1; // 1 for directory reference strcpy( nd->name, name); nd->status.st_mode = __stat_mode_REG; nd->status.st_ino = nd-&node[0]; nd->status.st_dev = 0; nd->status.st_nlink = 1; nd->status.st_uid = 0; nd->status.st_gid = 0; nd->status.st_size = 0; nd->status.st_atime = testfs_time(); nd->status.st_mtime = testfs_time(); nd->status.st_ctime = testfs_time(); for( i = 0; i < TESTFS_FILEBLOCKS; i++ ) nd->u.file.data[i] = NULL; err = ENOERR; } if( err == ENOERR && (mode & O_TRUNC ) ) { // Clean out any blocks in the file... int i; for( i = 0; i < TESTFS_FILEBLOCKS; i++ ) { testfs_block *b = nd->u.file.data[i]; if( b != NULL ) { b->u.next = free_block; b->pos = -1; free_block = b; nd->u.file.data[i] = NULL; } } nd->status.st_size = 0; } if( err != ENOERR ) return err; if( S_ISDIR(nd->status.st_mode) ) return EISDIR; nd->refcnt++; // Count successful open as a ref // Initialize the file object file->f_flag |= mode & CYG_FILE_MODE_MASK; file->f_type = CYG_FILE_TYPE_FILE; file->f_ops = &testfs_fileops; file->f_offset = 0; file->f_data = (CYG_ADDRWORD)nd; file->f_xops = 0; return ENOERR;}// -------------------------------------------------------------------------static int testfs_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *path ){ testfs_node *nd, *parent; int err; char name[TESTFS_NAMESIZE]; cyg_bool lastp; err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp ); if( err != ENOERR ) return err; // Cannot unlink directories, use rmdir() instead if( S_ISDIR(nd->status.st_mode) ) return EPERM; err = testfs_delnode( nd ); return err;}// -------------------------------------------------------------------------static int testfs_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *path ){ testfs_node *nd, *parent; int err; char name[TESTFS_NAMESIZE]; cyg_bool lastp; err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp ); if( lastp && err == ENOENT ) { int i; // No node there, create a new one. The parent and name // results will have been filled in, so we know where to put // it. // first check that there is space for it for( i = 0; i < TESTFS_FILEBLOCKS; i++ ) if( parent->u.dir.nodes[i] == NULL ) break; if( i == TESTFS_FILEBLOCKS ) return ENOSPC; // Allocate a new node nd = free_node; if( nd == NULL ) return ENOSPC; free_node = nd->next; // Add to directory list parent->u.dir.nodes[i] = nd; parent->refcnt++; // Fill in details nd->parent = parent; nd->refcnt = 1; // 1 for directory reference strcpy( nd->name, name); nd->status.st_mode = __stat_mode_DIR; nd->status.st_ino = nd-&node[0]; nd->status.st_dev = 0; nd->status.st_nlink = 1; nd->status.st_uid = 0; nd->status.st_gid = 0; nd->status.st_size = 0; nd->status.st_atime = testfs_time(); nd->status.st_mtime = testfs_time(); nd->status.st_ctime = testfs_time(); for( i = 0; i < TESTFS_FILEBLOCKS; i++ ) nd->u.dir.nodes[i] = NULL; err = ENOERR; } return err;}// -------------------------------------------------------------------------static int testfs_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *path ){ testfs_node *nd, *parent; int err; char name[TESTFS_NAMESIZE]; cyg_bool lastp; err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp ); if( err != ENOERR ) return err; // Check that it is a directory if( !S_ISDIR(nd->status.st_mode) ) return EPERM; err = testfs_delnode( nd ); return err;}// -------------------------------------------------------------------------static int testfs_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *path1, cyg_dir dir2, const char *path2 ){ testfs_node *nd1, *parent1; testfs_node *nd2, *parent2; int err; char name1[TESTFS_NAMESIZE]; char name2[TESTFS_NAMESIZE]; cyg_bool lastp; int i,j; err = testfs_find( (testfs_node *)dir1, path1, &nd1, &parent1, name1, &lastp ); if( err != ENOERR ) return err; err = testfs_find( (testfs_node *)dir2, path2, &nd2, &parent2, name2, &lastp ); // Allow through renames to non-existent objects. if( lastp && err == ENOENT ) err = ENOERR; if( err != ENOERR ) return err; // Null rename, just return if( nd1 == nd2 ) return ENOERR; // First deal with any node that is at the destination if( nd2 ) { // Check that we are renaming like-for-like if( !S_ISDIR(nd1->status.st_mode) && S_ISDIR(nd2->status.st_mode) ) return EISDIR; if( S_ISDIR(nd1->status.st_mode) && !S_ISDIR(nd2->status.st_mode) ) return ENOTDIR; // Now delete the destination node. err = testfs_delnode( nd2 ); if( err != ENOERR ) return err; } // Now we know that there is no clashing node at the destination. // Move the node over and change its name. // first check that there is space for it for( i = 0; i < TESTFS_FILEBLOCKS; i++ ) if( parent2->u.dir.nodes[i] == NULL ) break; if( i == TESTFS_FILEBLOCKS ) return ENOSPC; // Now remove node from old parent. for( j = 0; j < TESTFS_FILEBLOCKS; j++ ) if( parent1->u.dir.nodes[j] == nd1 ) { parent1->u.dir.nodes[j] = NULL; break; } parent1->refcnt--; // Add to directory list parent2->u.dir.nodes[i] = nd1; parent2->refcnt++; nd1->parent = parent2; // And give it a new name. strcpy( nd1->name, name2 ); return err;}// -------------------------------------------------------------------------static int testfs_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *path1, cyg_dir dir2, const char *path2, int type ){ // The data structures of this file system do not support the // creation of links. return ENOSYS;}// -------------------------------------------------------------------------static int testfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *path, cyg_file *file ){ testfs_node *nd, *parent; int err; char name[TESTFS_NAMESIZE]; cyg_bool lastp; err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp ); if( err != ENOERR ) return err; if( !S_ISDIR(nd->status.st_mode) ) return ENOTDIR; nd->refcnt++; // Count successful open as a ref // Initialize the file object file->f_type = CYG_FILE_TYPE_FILE; file->f_ops = &testfs_dirops; file->f_offset = 0; file->f_data = (CYG_ADDRWORD)nd; file->f_xops = 0; return ENOERR;}// -------------------------------------------------------------------------static int testfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *path, cyg_dir *dir_out ){ if( dir_out != NULL ) { // This is a request to get a new directory pointer in // *dir_out. testfs_node *nd, *parent; int err; char name[TESTFS_NAMESIZE]; cyg_bool lastp; err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp ); if( err != ENOERR ) return err; if( !S_ISDIR(nd->status.st_mode) ) return ENOTDIR; // Increment ref count to keep this directory in existent // while it is the current cdir.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -