📄 ramfs.c
字号:
}// -------------------------------------------------------------------------// ramfs_rename()// Rename a file/dir.static int ramfs_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2 ){ ramfs_dirsearch ds1, ds2; int err; init_dirsearch( &ds1, (ramfs_node *)dir1, name1 ); err = ramfs_find( &ds1 ); if( err != ENOERR ) return err; init_dirsearch( &ds2, (ramfs_node *)dir2, name2 ); err = ramfs_find( &ds2 ); // Allow through renames to non-existent objects. if( ds2.last && err == ENOENT ) ds2.node = NULL, err = ENOERR; if( err != ENOERR ) return err; // Null rename, just return if( ds1.node == ds2.node ) return ENOERR; // First deal with any entry that is at the destination if( ds2.node ) { // Check that we are renaming like-for-like if( !S_ISDIR(ds1.node->mode) && S_ISDIR(ds2.node->mode) ) return EISDIR; if( S_ISDIR(ds1.node->mode) && !S_ISDIR(ds2.node->mode) ) return ENOTDIR; // Now delete the destination directory entry err = del_direntry( ds2.dir, ds2.name, ds2.namelen ); if( err != ENOERR ) return err; } // Now we know that there is no clashing node at the destination, // make a new direntry at the destination and delete the old entry // at the source. err = add_direntry( ds2.dir, ds2.name, ds2.namelen, ds1.node ); if( err == ENOERR ) err = del_direntry( ds1.dir, ds1.name, ds1.namelen ); // Update directory times if( err == ENOERR ) ds1.dir->ctime = ds1.dir->mtime = ds2.dir->ctime = ds2.dir->mtime = cyg_timestamp(); return err;}// -------------------------------------------------------------------------// ramfs_link()// Make a new directory entry for a file.static int ramfs_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2, int type ){ ramfs_dirsearch ds1, ds2; int err; // Only do hard links for now in this filesystem if( type != CYG_FSLINK_HARD ) return EINVAL; init_dirsearch( &ds1, (ramfs_node *)dir1, name1 ); err = ramfs_find( &ds1 ); if( err != ENOERR ) return err; init_dirsearch( &ds2, (ramfs_node *)dir2, name2 ); err = ramfs_find( &ds2 ); // Don't allow links to existing objects if( err == ENOERR ) return EEXIST; // Allow through links to non-existing terminal objects if( ds2.last && err == ENOENT ) ds2.node = NULL, err = ENOERR; if( err != ENOERR ) return err; // Now we know that there is no existing node at the destination, // make a new direntry at the destination. err = add_direntry( ds2.dir, ds2.name, ds2.namelen, ds1.node ); if( err == ENOERR ) ds1.node->ctime = ds2.dir->ctime = ds2.dir->mtime = cyg_timestamp(); return err;}// -------------------------------------------------------------------------// ramfs_opendir()// Open a directory for reading.static int ramfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_file *file ){ ramfs_dirsearch ds; int err; init_dirsearch( &ds, (ramfs_node *)dir, name ); err = ramfs_find( &ds ); if( err != ENOERR ) return err; // check it is really a directory. if( !S_ISDIR(ds.node->mode) ) return ENOTDIR; ds.node->refcnt++; // Count successful open // 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 = &ramfs_dirops; file->f_offset = 0; file->f_data = (CYG_ADDRWORD)ds.node; file->f_xops = 0; return ENOERR;}// -------------------------------------------------------------------------// ramfs_chdir()// Change directory support.static int ramfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_dir *dir_out ){ if( dir_out != NULL ) { // This is a request to get a new directory pointer in // *dir_out. ramfs_dirsearch ds; int err; init_dirsearch( &ds, (ramfs_node *)dir, name ); err = ramfs_find( &ds ); if( err != ENOERR ) return err; // check it is a directory if( !S_ISDIR(ds.node->mode) ) return ENOTDIR; // Increment ref count to keep this directory in existent // while it is the current cdir. ds.node->refcnt++; // Pass it out *dir_out = (cyg_dir)ds.node; } else { // If no output dir is required, this means that the mte and // dir arguments are the current cdir setting and we should // forget this fact. ramfs_node *node = (ramfs_node *)dir; // Just decrement directory reference count. dec_refcnt( node ); } return ENOERR;}// -------------------------------------------------------------------------// ramfs_stat()// Get struct stat info for named object.static int ramfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, struct stat *buf){ ramfs_dirsearch ds; int err; init_dirsearch( &ds, (ramfs_node *)dir, name ); err = ramfs_find( &ds ); if( err != ENOERR ) return err; // Fill in the status buf->st_mode = ds.node->mode; buf->st_ino = (ino_t)ds.node; buf->st_dev = 0; buf->st_nlink = ds.node->nlink; buf->st_uid = 0; buf->st_gid = 0; buf->st_size = ds.node->size; buf->st_atime = ds.node->atime; buf->st_mtime = ds.node->mtime; buf->st_ctime = ds.node->ctime; return err;}// -------------------------------------------------------------------------// ramfs_getinfo()// Getinfo. Currently only support pathconf().static int ramfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len ){ ramfs_dirsearch ds; int err; init_dirsearch( &ds, (ramfs_node *)dir, name ); err = ramfs_find( &ds ); if( err != ENOERR ) return err; switch( key ) { case FS_INFO_CONF: err = ramfs_pathconf( ds.node, (struct cyg_pathconf_info *)buf ); break; default: err = EINVAL; } return err;}// -------------------------------------------------------------------------// ramfs_setinfo()// Setinfo. Nothing to support here at present.static int ramfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len ){ // No setinfo keys supported at present return EINVAL;}//==========================================================================// File operations// -------------------------------------------------------------------------// ramfs_fo_read()// Read data from the file.static int ramfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio){ ramfs_node *node = (ramfs_node *)fp->f_data; int i; off_t pos = fp->f_offset; ssize_t resid = uio->uio_resid; // Loop over the io vectors until there are none left for( i = 0; i < uio->uio_iovcnt; i++ ) { cyg_iovec *iov = &uio->uio_iov[i]; char *buf = (char *)iov->iov_base; off_t len = iov->iov_len; // Loop over each vector filling it with data from the file. while( len > 0 && pos < node->size ) { cyg_uint8 *fbuf; size_t bsize; off_t l = len; int err; // Get a pointer to the data at offset _pos_. err = findbuffer_node( node, pos, &fbuf, &bsize, false ); if( err != ENOERR ) return err; // adjust size to end of file if necessary if( l > node->size-pos ) l = node->size-pos; // adjust size to the amount of contiguous data we can see // at present. if( l > bsize ) l = bsize; // copy data out memcpy( buf, fbuf, l ); // Update working vars len -= l; buf += l; pos += l; resid -= l; } } // We successfully read some data, update the node's access time // and update the file offset and transfer residue. node->atime = cyg_timestamp(); uio->uio_resid = resid; fp->f_offset = pos; return ENOERR;}// -------------------------------------------------------------------------// ramfs_fo_write()// Write data to file.static int ramfs_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio){ ramfs_node *node = (ramfs_node *)fp->f_data; off_t pos = fp->f_offset; ssize_t resid = uio->uio_resid; int err = ENOERR; int i; // If the APPEND mode bit was supplied, force all writes to // the end of the file. if( fp->f_flag & CYG_FAPPEND ) pos = fp->f_offset = node->size; // Check that pos is within current file size, or at the very end. if( pos < 0 || pos > node->size ) return EINVAL; // Now loop over the iovecs until they are all done, or // we get an error. for( i = 0; i < uio->uio_iovcnt; i++ ) { cyg_iovec *iov = &uio->uio_iov[i]; char *buf = (char *)iov->iov_base; off_t len = iov->iov_len; // loop over the vector writing it to the file until it has // all been done. while( len > 0 ) { cyg_uint8 *fbuf; size_t bsize; off_t l = len; err = findbuffer_node( node, pos, &fbuf, &bsize, true ); // Stop writing if there is no more space in the file and // indicate end of data. if( err == ENOSPC ) break; if( err != ENOERR ) return err; // adjust size to this block if( l > bsize ) l = bsize; // copy data in memcpy( fbuf, buf, l ); // Update working vars len -= l; buf += l; pos += l; resid -= l; } } // We wrote some data successfully, update the modified and access // times of the node, increase its size appropriately, and update // the file offset and transfer residue. node->mtime = node->ctime = cyg_timestamp(); if( pos > node->size ) node->size = pos; uio->uio_resid = resid; fp->f_offset = pos; return err;}// -------------------------------------------------------------------------// ramfs_fo_lseek()// Seek to a new file position.static int ramfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *apos, int whence ){ ramfs_node *node = (ramfs_node *)fp->f_data; off_t pos = *apos; switch( whence ) { case SEEK_SET: // Pos is already where we want to be. break; case SEEK_CUR: // Add pos to current offset. pos += fp->f_offset; break; case SEEK_END: // Add pos to file size. pos
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -