📄 romfs.c
字号:
return ENOERR;}//==========================================================================// Directory operations// -------------------------------------------------------------------------// find_direntry()// Find a directory entry for the name and return a pointer to the first// entry fragment.static romfs_dirent *find_direntry( romfs_disk *disk, romfs_node *dir, const char *name, int namelen ){ off_t pos = 0; int err; // Loop over all the entries until a match is found or we run out // of data. while( pos < dir->size ) { romfs_dirent *d; cyg_uint8 *buf; size_t size; err = findbuffer_node( disk, dir, pos, &buf, &size ); if( err != ENOERR || size == 0) return NULL; d = (romfs_dirent *)buf; // Is this the directory entry we're looking for? if ( match( d->name, name, namelen ) ) return d; // Otherwise move on to next entry in chain pos = d->next; } return NULL;}//==========================================================================// Directory search// -------------------------------------------------------------------------// init_dirsearch()// Initialize a dirsearch object to start a searchstatic void init_dirsearch( romfs_dirsearch *ds, romfs_disk *disk, romfs_node *dir, const char *name){ ds->disk = disk; ds->dir = dir; ds->path = name; ds->node = dir; ds->name = name; ds->namelen = 0; ds->last = false;}// -------------------------------------------------------------------------// find_entry()// Search a single directory for the next name in a path and update the// dirsearch object appropriately.static int find_entry( romfs_dirsearch *ds ){ romfs_node *dir = ds->dir; const char *name = ds->path; const char *n = name; int namelen = 0; romfs_dirent *d; // check that we really have a directory if( !S_ISDIR(dir->mode) ) return ENOTDIR; // Isolate the next element of the path name. while( *n != '\0' && *n != '/' ) n++, namelen++; // Check if this is the last path element. while( *n == '/') n++; if( *n == '\0' ) ds->last = true; // update name in dirsearch object ds->name = name; ds->namelen = namelen; // Here we have the name and its length set up. // Search the directory for a matching entry d = find_direntry( ds->disk, dir, name, namelen ); if( d == NULL ) return ENOENT; // pass back the node we have found ds->node = &ds->disk->node[d->node]; return ENOERR;}// -------------------------------------------------------------------------// romfs_find()// Main interface to directory search code. This is used in all file// level operations to locate the object named by the pathname.static int romfs_find( romfs_dirsearch *d ){ int err; // Short circuit empty paths if( *(d->path) == '\0' ) return ENOERR; // iterate down directory tree until we find the object // we want. for(;;) { err = find_entry( d ); if( err != ENOERR ) return err; if( d->last ) return ENOERR; // Update dirsearch object to search next directory. d->dir = d->node; d->path += d->namelen; while( *(d->path) == '/' ) d->path++; // skip dirname separators }}//==========================================================================// Pathconf support// This function provides support for pathconf() and fpathconf().static int romfs_pathconf( romfs_node *node, struct cyg_pathconf_info *info ){ int err = ENOERR; switch( info->name ) { case _PC_LINK_MAX: info->value = LINK_MAX; break; case _PC_MAX_CANON: info->value = -1; // not supported err = EINVAL; break; case _PC_MAX_INPUT: info->value = -1; // not supported err = EINVAL; break; case _PC_NAME_MAX: info->value = NAME_MAX; break; case _PC_PATH_MAX: info->value = PATH_MAX; break; case _PC_PIPE_BUF: info->value = -1; // not supported err = EINVAL; break; case _PC_ASYNC_IO: info->value = -1; // not supported err = EINVAL; break; case _PC_CHOWN_RESTRICTED: info->value = -1; // not supported err = EINVAL; break; case _PC_NO_TRUNC: info->value = 0; break; case _PC_PRIO_IO: info->value = 0; break; case _PC_SYNC_IO: info->value = 0; break; case _PC_VDISABLE: info->value = -1; // not supported err = EINVAL; break; default: err = EINVAL; break; } return err;}//==========================================================================// Filesystem operations// -------------------------------------------------------------------------// romfs_mount()// Process a mount request. This mainly finds root for the// filesystem.static int romfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte ){ romfs_disk *disk=NULL; if ( !mte->data ) { // If the image address was not in the MTE data word, if ( mte->devname && mte->devname[0] ) { // And there's something in the 'hardware device' field, // then read the address from there. sscanf( mte->devname, "%p", (char**)&disk ); } } else { disk = (romfs_disk *)mte->data; } if ( !disk ) { // If still no address, try the FSTAB entry data word disk = (romfs_disk *)fste->data; } if ( !disk ) { // If still no address, give up... return ENOENT; } // Check the ROMFS magic number to ensure that there's really an fs. if ( disk->magic == ROMFS_CIGAM ) { // The disk image has the wrong byte sex!!! return EIO; } else if ( disk->magic != ROMFS_MAGIC || disk->nodecount == 0 ) { // No image found return ENOENT; } mte->root = (cyg_dir)&disk->node[0]; mte->data = (CYG_ADDRWORD)disk; return ENOERR;}// -------------------------------------------------------------------------// romfs_umount()// Unmount the filesystem. This will currently always succeed.static int romfs_umount ( cyg_mtab_entry *mte ){ // Clear root pointer mte->root = CYG_DIR_NULL; // That's all folks. return ENOERR;}// -------------------------------------------------------------------------// romfs_open()// Open a file for readingstatic int romfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int mode, cyg_file *file ){ romfs_dirsearch ds; romfs_node *node = NULL; int err; init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name ); err = romfs_find( &ds ); if( err == ENOENT ) { return ENOENT; } else if( err == ENOERR ) { // The node exists. If the O_CREAT and O_EXCL bits are set, we // must fail the open. if( (mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) err = EEXIST; else node = ds.node; } if( err == ENOERR && (mode & O_TRUNC ) ) { // If the O_TRUNC bit is set we must fail the open err = EPERM; } if( err != ENOERR ) return err; // Check that we actually have a file here if( S_ISDIR(node->mode) ) return EISDIR; // Initialize the file object file->f_flag |= mode & CYG_FILE_MODE_MASK; file->f_type = CYG_FILE_TYPE_FILE; file->f_ops = &romfs_fileops; file->f_offset = 0; file->f_data = (CYG_ADDRWORD)node; file->f_xops = 0; return ENOERR;}// -------------------------------------------------------------------------// romfs_opendir()// Open a directory for reading.static int romfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_file *file ){ romfs_dirsearch ds; int err; init_dirsearch( &ds, (romfs_disk *)mte->data, (romfs_node *)dir, name ); err = romfs_find( &ds ); if( err != ENOERR ) return err; // check it is really a directory. if( !S_ISDIR(ds.node->mode) ) return ENOTDIR; // Initialize the file object, setting the f_ops field to a // special set of file ops. file->f_type = CYG_FILE_TYPE_FILE; file->f_ops = &romfs_dirops; file->f_offset = 0; file->f_data = (CYG_ADDRWORD)ds.node; file->f_xops = 0; return ENOERR;}// -------------------------------------------------------------------------// romfs_chdir()// Change directory support.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -