📄 testfs.c
字号:
//==========================================================================//// testfs.c//// Test file system////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): nickg// Contributors: nickg// Date: 2000-05-25// Purpose: Test file system// Description: This is a very simple implementation of a RAM file system.// This implementation is not "industrial strength" or suitable// for production use, it is too wasteful of both memory and time.// Its primary purpose is to support testing of the fileio// infrastructure and API. It can, however, serve as a model// and source of code fragments for the implementation// of further filesystems.// ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/hal.h>#include <pkgconf/kernel.h>#include <pkgconf/io_fileio.h>#include <cyg/kernel/ktypes.h> // base kernel types#include <cyg/infra/cyg_trac.h> // tracing macros#include <cyg/infra/cyg_ass.h> // assertion macros#include <unistd.h>#include <fcntl.h>#include <sys/stat.h>#include <errno.h>#include <dirent.h>#include <cyg/fileio/fileio.h>#include <cyg/kernel/kapi.h>#include <cyg/infra/diag.h>//==========================================================================// Configuration parameters#define TESTFS_NFILE 10 // Max number of files/directories#define TESTFS_NBLOCK 20 // Number of data blocks available#define TESTFS_BLOCKSIZE 128 // Bytes stored per block#define TESTFS_FILEBLOCKS 8 // Max blocks per file#define TESTFS_NAMESIZE 32 // Length of file names in bytes// Maximum file size is blocksize*blocks#define TESTFS_FILESIZE_MAX (TESTFS_BLOCKSIZE*TESTFS_FILEBLOCKS)//==========================================================================// Data structuresstruct testfs_node;typedef struct testfs_node testfs_node;struct testfs_block;typedef struct testfs_block testfs_block;struct testfs_node{ testfs_node *next; // next node in list testfs_node *parent; // Back pointer to parent int refcnt; // reference count char name[TESTFS_NAMESIZE]; // file name struct stat status; // status data union { struct { testfs_block *data[TESTFS_FILEBLOCKS]; // array of blocks } file; struct { testfs_node *nodes[TESTFS_FILEBLOCKS]; // array of nodes } dir; } u;};struct testfs_block{ union { testfs_block *next; // next block in free list testfs_node *file; // back pointer to file } u; off_t pos; // position in file of first byte size_t size; // number of bytes in buffer char data[TESTFS_BLOCKSIZE]; // the data};//==========================================================================// Local data// Array of nodesstatic testfs_node node[TESTFS_NFILE];// node free list.static testfs_node *free_node = NULL;// Array of data blocksstatic testfs_block block[TESTFS_NBLOCK];// block free list.static testfs_block *free_block = NULL;// Init flagcyg_bool testfs_initialized = false;//==========================================================================// Forward definitions// Filesystem operationsstatic int testfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte );static int testfs_umount ( cyg_mtab_entry *mte );static int testfs_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int mode, cyg_file *fte );static int testfs_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );static int testfs_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );static int testfs_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );static int testfs_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2 );static int testfs_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2, int type );static int testfs_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_file *fte );static int testfs_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_dir *dir_out );static int testfs_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, struct stat *buf);static int testfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len );static int testfs_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len );// File operationsstatic int testfs_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static int testfs_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static int testfs_fo_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );static int testfs_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, CYG_ADDRWORD data);//static int testfs_fo_select (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info);static int testfs_fo_fsync (struct CYG_FILE_TAG *fp, int mode ); static int testfs_fo_close (struct CYG_FILE_TAG *fp);static int testfs_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf );static int testfs_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );static int testfs_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );// Directory operationsstatic int testfs_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static int testfs_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );//==========================================================================// Filesystem table entriesFSTAB_ENTRY( testfs_fste, "testfs", 0, CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM, testfs_mount, testfs_umount, testfs_open, testfs_unlink, testfs_mkdir, testfs_rmdir, testfs_rename, testfs_link, testfs_opendir, testfs_chdir, testfs_stat, testfs_getinfo, testfs_setinfo);MTAB_ENTRY( testfs_mte1, "/", "testfs", "", 0);#if 0MTAB_ENTRY( testfs_mte2, "/ram", "testfs", "", 0);#endifstatic cyg_fileops testfs_fileops ={ testfs_fo_read, testfs_fo_write, testfs_fo_lseek, testfs_fo_ioctl, cyg_fileio_seltrue, testfs_fo_fsync, testfs_fo_close, testfs_fo_fstat, testfs_fo_getinfo, testfs_fo_setinfo};static cyg_fileops testfs_dirops ={ testfs_fo_dirread, (cyg_fileop_write *)cyg_fileio_enosys, testfs_fo_dirlseek, (cyg_fileop_ioctl *)cyg_fileio_enosys, cyg_fileio_seltrue, (cyg_fileop_fsync *)cyg_fileio_enosys, testfs_fo_close, (cyg_fileop_fstat *)cyg_fileio_enosys, (cyg_fileop_getinfo *)cyg_fileio_enosys, (cyg_fileop_setinfo *)cyg_fileio_enosys};//==========================================================================// Support routines// -------------------------------------------------------------------------// Local strcmp() and strcpy()static int strcmp( const char *s1, const char *s2 ){ while( *s1 == *s2 && *s1 != '\0' && *s2 != '\0' ) s1++, s2++; return (*s2)-(*s1);}static char *strcpy( char *s1, const char *s2 ){ char *s = s1; while( (*s1++ = *s2++) != 0); return s;}// -------------------------------------------------------------------------// Follow a path through the directory structurestatic int testfs_find( testfs_node *dir, // dir to start search in const char *path, // path to follow testfs_node **found, // return node found testfs_node **parent, // return last dir searched char *name, // name fragment buffer cyg_bool *lastp) // last name in path ?{ testfs_node *nd = dir; *lastp = false; *found = NULL; while( *path != '\0' ) { const char *p = path; char *n = name; testfs_node *nd1; int i; // check nd is a directory if( !S_ISDIR(nd->status.st_mode) ) return ENOTDIR; // Isolate the next element of the path name. while( *p != '\0' && *p != '/' && (n-&name[0]) < TESTFS_NAMESIZE) *n++ = *p++; if( (n-&name[0]) >= TESTFS_NAMESIZE ) return ENAMETOOLONG; // Step path on past the separator // If this is the last name element in the path, // set *lastp to indicate this. if( *(path=p) == '/' ) path++; else *lastp = true; // teminate name *n = '\0'; // name now contains the next path element, search the node // in nd for it. *parent = nd; nd1 = NULL; for( i = 0; i < TESTFS_FILEBLOCKS; i++ ) { testfs_node *n = nd->u.dir.nodes[i]; if( n == NULL ) continue; if( strcmp( name, n->name ) == 0 ) { nd1 = n; break; } } if( nd1 == NULL ) return ENOENT; nd = nd1; } // Return what we have found *found = nd; return ENOERR;}// -------------------------------------------------------------------------// Get current time since epochstatic time_t testfs_time(void){ // FIXME: !!!!Temporary!!!! return cyg_current_time();}// -------------------------------------------------------------------------static int testfs_delnode( testfs_node *nd ){ testfs_node *parent; int i; // Non-unitary ref count means this node is either open // or is a dir with entries in it. if( nd->refcnt > 1 ) return EBUSY; // Remove from parent's node list. parent = nd->parent; for( i = 0; i < TESTFS_FILEBLOCKS; i++ ) if( parent->u.dir.nodes[i] == nd ) { parent->u.dir.nodes[i] = NULL; break; } parent->refcnt--; if( S_ISREG(nd->status.st_mode) ) { // for a file, return blocks to free list 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; } } } // and finally return nd to free node list nd->next = free_node; nd->refcnt = -1; free_node = nd; return ENOERR;}//==========================================================================// Filesystem operations// -------------------------------------------------------------------------static int testfs_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte ){ testfs_node *root; int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -