📄 testfs.c
字号:
nd->refcnt++; // Pass it out *dir_out = (cyg_dir)nd; } 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. testfs_node *nd = (testfs_node *)dir; // Just decrement reference count. nd->refcnt--; } return ENOERR;}// -------------------------------------------------------------------------static int testfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *path, struct stat *buf){ 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; *buf = nd->status; return err;}// -------------------------------------------------------------------------static int testfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *path, int key, void *buf, int len ){ return ENOSYS;}// -------------------------------------------------------------------------static int testfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *path, int key, void *buf, int len ){ return ENOSYS;}//==========================================================================// File operations// -------------------------------------------------------------------------static int testfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio){ testfs_node *nd = (testfs_node *)fp->f_data; int i; off_t pos = fp->f_offset; 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; while( len > 0 && pos < nd->status.st_size ) { testfs_block *b = nd->u.file.data[pos/TESTFS_BLOCKSIZE]; off_t l = len; off_t bpos = pos%TESTFS_BLOCKSIZE; // If there is no block in that pos, we have reached // the end of the file. if( b == NULL ) return ENOERR; // adjust size to this block if( l > (b->size-bpos) ) l = (b->size-bpos); // copy data out memcpy( buf, &b->data[bpos], l ); uio->uio_resid -= l; len -= l; buf += l; pos += l; // keep offset up to date incase of errors fp->f_offset = pos; } } return ENOERR;}// -------------------------------------------------------------------------static int testfs_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio){ testfs_node *nd = (testfs_node *)fp->f_data; int i; off_t pos = fp->f_offset; // Check we are not at end of allowed max file size if( pos >= TESTFS_FILESIZE_MAX ) return EFBIG; // Check that pos is within current file size, or at the very end. if( pos < 0 || pos > nd->status.st_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; while( len > 0 ) { testfs_block *b = nd->u.file.data[pos/TESTFS_BLOCKSIZE]; off_t l = len; off_t bpos = pos%TESTFS_BLOCKSIZE; // If there is no block in that pos, allocate one // and initialize it if( b == NULL ) { b = free_block; if( b == NULL ) return ENOSPC; free_block = b->u.next; nd->u.file.data[pos/TESTFS_BLOCKSIZE] = b; b->u.file = nd; b->pos = pos; b->size = 0; } // adjust size to this block if( l > (TESTFS_BLOCKSIZE-bpos) ) l = (TESTFS_BLOCKSIZE-bpos); // copy data in memcpy( &b->data[bpos], buf, l ); // adjust buffer info if( b->size < bpos+l ) b->size = bpos+l; uio->uio_resid -= l; len -= l; buf += l; pos += l; // keep node size and file offset up to date //in case of an error. if( pos > nd->status.st_size ) nd->status.st_size = pos; fp->f_offset = pos; if( pos >= TESTFS_FILESIZE_MAX ) return EFBIG; } } return ENOERR;}// -------------------------------------------------------------------------static int testfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *apos, int whence ){ testfs_node *nd = (testfs_node *)fp->f_data; off_t pos = *apos; switch( whence ) { case SEEK_SET: // we are already where we want to be. break; case SEEK_CUR: pos += fp->f_offset; break; case SEEK_END: pos += nd->status.st_size; break; default: return EINVAL; } // Check that pos is within current file size, or at the very end. if( pos < 0 || pos > nd->status.st_size ) return EINVAL; // All OK, set fp offset. *apos = fp->f_offset = pos; return ENOERR;}// -------------------------------------------------------------------------static int testfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, CYG_ADDRWORD data){ return ENOSYS;}// -------------------------------------------------------------------------static int testfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode ){ // Nothing to do return ENOERR;}// -------------------------------------------------------------------------static int testfs_fo_close (struct CYG_FILE_TAG *fp){ testfs_node *nd = (testfs_node *)fp->f_data; nd->refcnt--; // remove open count fp->f_data = 0; // clear data pointer return ENOERR;}// -------------------------------------------------------------------------static int testfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf ){ testfs_node *nd = (testfs_node *)fp->f_data; *buf = nd->status; return ENOERR;}// -------------------------------------------------------------------------static int testfs_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ){ return ENOERR;}// -------------------------------------------------------------------------static int testfs_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ){ return ENOERR;}//==========================================================================// Directory operationsstatic int testfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio){ testfs_node *nd = (testfs_node *)fp->f_data; off_t pos = fp->f_offset; cyg_iovec *iov = &uio->uio_iov[0]; char *buf = (char *)iov->iov_base; off_t len = iov->iov_len; // End of directory if( pos >= TESTFS_FILEBLOCKS ) return ENOERR; if( len < sizeof(struct dirent) ) return EINVAL; for( ; pos < TESTFS_FILEBLOCKS; pos++ ) if( nd->u.dir.nodes[pos] != NULL ) { struct dirent *ent = (struct dirent *)buf; strcpy( ent->d_name, nd->u.dir.nodes[pos]->name ); uio->uio_resid -= sizeof(struct dirent); break; } fp->f_offset = pos+1; return ENOERR;}// -------------------------------------------------------------------------static int testfs_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence ){ if( whence != SEEK_SET || *pos != 0) return EINVAL; *pos = fp->f_offset = 0; return ENOERR;}//==========================================================================// Filesystem dump// Dumps out the node and block arrays in a readable format, and does// a little consistency checking as it goes.void testfs_dump(void){ int errors = 0; int i; char *indent = "\n |"; diag_printf("Nodes:\n"); for( i = 0; i < TESTFS_NFILE; i++ ) { testfs_node *nd = &node[i]; diag_printf("%3d : ",i); if( nd->refcnt < 0 ) diag_printf("<free>"); else if( !S_ISDIR(nd->status.st_mode) ) { // Regular file int j; diag_printf("f %8s %4d |",nd->name,nd->status.st_size); for( j = 0; j < TESTFS_FILEBLOCKS; j++ ) { testfs_block *b = nd->u.file.data[j]; if( b != NULL ) { if( j > 0 && (j%4) == 0 ) diag_printf(indent); diag_printf(" %3d[%3d,%3d]",b-block,b->pos,b->size); if( b->u.file != nd ) { errors++; diag_printf("!"); } } } } else { // Directory int j; int rc = 1; diag_printf("d %8s |",nd->name); for( j = 0; j < TESTFS_FILEBLOCKS; j++ ) { testfs_node *n = nd->u.dir.nodes[j]; if( n != NULL ) { if( j > 0 && (j%4) == 0 ) diag_printf(indent); diag_printf(" %3d[%7s]",n-node,n->name); rc++; } } if( nd->refcnt != rc ) { diag_printf("%s refcount is %d should be %d",indent,nd->refcnt,rc); if( nd->refcnt == rc+1 ) diag_printf(" (but may be current dir)"); } } diag_printf("\n"); } diag_printf("Blocks:\n"); for( i = 0; i < TESTFS_NBLOCK; i++ ) { testfs_block *b = &block[i]; diag_printf("%3d :",i); if( b->pos == -1 ) diag_printf(" <free>"); else { int j; testfs_node *nd = b->u.file; diag_printf(" %3d %3d %d[%7s]",b->pos,b->size,nd-node,nd->name); for( j = 0; j < TESTFS_FILEBLOCKS; j++ ) { if( nd->u.file.data[j] == b ) break; } if( j == TESTFS_FILEBLOCKS ) { errors++; diag_printf(" block not in file!"); } } diag_printf("\n"); } if( errors != 0 ) diag_printf("%d errors detected\n",errors);}// -------------------------------------------------------------------------// EOF testfs.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -