📄 ramfs.c
字号:
#ifdef CYGPKG_FS_RAM_SIMPLE // The data storage in this case consists of a single // malloced memory block, together with its size. size_t datasize; // size of data block cyg_uint8 *data; // malloced data buffer#else // The data storage in this case consists of arrays of pointers // to data blocks. #if CYGNUM_RAMFS_BLOCKS_DIRECT > 0 // Directly accessible blocks from the inode. ramfs_block *direct[CYGNUM_RAMFS_BLOCKS_DIRECT];#endif#if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0 // Single level indirection ramfs_block **indirect1[CYGNUM_RAMFS_BLOCKS_INDIRECT1];#endif#if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0 // Two level indirection ramfs_block ***indirect2[CYGNUM_RAMFS_BLOCKS_INDIRECT2];#endif#endif };//==========================================================================// Directory entry.// Fixed sized entry containing a fragment of the name of a file/directory.struct ramfs_dirent{ ramfs_node *node; // pointer to node unsigned int inuse:1, // entry in use? first:1, // first directory entry fragment? last:1, // last directory entry fragment? namelen:8, // bytes in whole name fraglen:8; // bytes in name fragment off_t next; // offset of next dirent // Name fragment, fills rest of entry. char name[CYGNUM_RAMFS_DIRENT_SIZE- sizeof(ramfs_node *)- sizeof( cyg_uint32)- sizeof(off_t)];};//==========================================================================// Directory search data// Parameters for a directory search. The fields of this structure are// updated as we follow a pathname through the directory tree.struct ramfs_dirsearch{ ramfs_node *dir; // directory to search const char *path; // path to follow ramfs_node *node; // Node found const char *name; // last name fragment used int namelen; // name fragment length cyg_bool last; // last name in path?};typedef struct ramfs_dirsearch ramfs_dirsearch;//==========================================================================// Forward defsstatic int del_direntry( ramfs_node *dir, const char *name, int namelen );//==========================================================================// Block array// This is used for block allocation when malloc is not being used.#ifdef CYGPKG_FS_RAM_BLOCKS_ARRAY# ifdef CYGPKG_FS_RAM_BLOCKS_ARRAY_EXTERN// Array is defined externally with a user-supplied name__externC ramfs_block CYGPKG_FS_RAM_BLOCKS_ARRAY_NAME[CYGNUM_FS_RAM_BLOCKS_ARRAY_SIZE];// Translate into a usable common name#define ramfs_block_array CYGPKG_FS_RAM_BLOCKS_ARRAY_NAME# else// Array is defined herestatic ramfs_block cyg_ramfs_block_array[CYGNUM_FS_RAM_BLOCKS_ARRAY_SIZE];#define ramfs_block_array cyg_ramfs_block_array# endif// Pointer to list of free blocksstatic ramfs_block *block_free_list = NULL;#endif//==========================================================================// Block allocation#ifndef CYGPKG_FS_RAM_SIMPLE// -------------------------------------------------------------------------// block_init()// Initialize the block allocator by chaining them all together on// block_free_list.#ifdef CYGPKG_FS_RAM_BLOCKS_ARRAYstatic void block_init(void){ static cyg_bool initialized = false; int i; if( !initialized ) { for( i = 0; i < CYGNUM_FS_RAM_BLOCKS_ARRAY_SIZE; i++ ) { ramfs_block *b = &ramfs_block_array[i]; *(ramfs_block **)b = block_free_list; block_free_list = b; } initialized = true; }}#endif// -------------------------------------------------------------------------// block_alloc()// Allocate a block for data storage.// If we have a block array, just pick the first off the free list.// If we are mallocing, call malloc() to get it.static ramfs_block *block_alloc(void){ ramfs_block *b;#ifdef CYGPKG_FS_RAM_BLOCKS_ARRAY block_init(); // Check blocks are initialized // pick first block off free list. b = block_free_list; // and advance list if( b != NULL ) block_free_list = *(ramfs_block **)b;#else b = malloc(CYGNUM_RAMFS_BLOCK_SIZE);#endif // Clear the block to zero if it was allocated if( b != NULL ) memset( b, 0, CYGNUM_RAMFS_BLOCK_SIZE ); return b;}// -------------------------------------------------------------------------// block_free()// Free a block. Depending on the configuration send it back to the// heap or put it back on free list.static void block_free( ramfs_block *b ){#ifdef CYGPKG_FS_RAM_BLOCKS_ARRAY // Put the block back on the free list *(ramfs_block **)b = block_free_list; block_free_list = b; #else // Call free() to return it to the memory pool free( b );#endif}#endif//==========================================================================// Node buffer management// There are two versions of this, one for the _SIMPLE variant and one for// the _BLOCKS variant. In both cases the interface to this code is via the// findbuffer_node() and freebuffer_node() functions.#ifdef CYGPKG_FS_RAM_SIMPLE//==========================================================================// SIMPLE buffer management.// Each node has a data buffer pointer and a size. This buffer is// realloc()ed as needed.// -------------------------------------------------------------------------// findbuffer_node()// return a pointer to the data at the indicated file position, extending// the buffer if required.static int findbuffer_node( ramfs_node *node, // node pointer off_t pos, // data position to get cyg_uint8 **buffer, // returned buffer pointer size_t *size, // returned buffer size cyg_bool alloc) // extend allocation?{ if( alloc && (pos == node->datasize || node->datasize == 0) ) { // If we are allowed to alloc new data, and we are at the end of the // current data allocation, or there is no data present, allocate or // extend the data buffer. cyg_uint8 *newdata; if( node->data == NULL ) newdata = malloc( CYGNUM_RAMFS_REALLOC_INCREMENT ); else newdata = realloc( node->data, pos+CYGNUM_RAMFS_REALLOC_INCREMENT ); if( newdata == NULL ) return ENOSPC; else memset( newdata+pos, 0, CYGNUM_RAMFS_REALLOC_INCREMENT ); node->data = newdata; node->datasize = pos+CYGNUM_RAMFS_REALLOC_INCREMENT; } else if( pos > node->datasize ) { // Indicate end of data. *size = 0; return ENOERR; } *buffer = node->data+pos; *size = node->datasize-pos; return ENOERR;}// -------------------------------------------------------------------------// freebuffer_node()// Empty out the data storage from the node.static int freebuffer_node( ramfs_node *node ){ if( node->data != NULL ) { free( node->data ); } node->data = NULL; node->datasize = 0; return ENOERR;}//==========================================================================#else//==========================================================================// _BLOCKS storage management.// Data storage in the node is by means of a set of arrays of pointers to// blocks. The first array points directly to the data blocks. Subsequent// arrays point to single and double indirect blocks respectively. // -------------------------------------------------------------------------// findbuffer_direct()// Indexes into an array of block pointers and extracts a pointer to the// data at offset _pos_, allocating new blocks if required.static int findbuffer_direct( off_t pos, ramfs_block **blocks, int nblocks, cyg_uint8 **buffer, size_t *size, cyg_bool alloc){ int bi = pos / CYGNUM_RAMFS_BLOCK_SIZE; int bpos = pos % CYGNUM_RAMFS_BLOCK_SIZE; ramfs_block *b; *buffer = NULL; *size = 0; if( bi >= nblocks ) return ENOERR; b = blocks[bi]; if( b == NULL ) { // There is no block there. If _alloc_ is true we can fill the // slot in with a new block. If it is false, we indicate end of // data with a zero size result. if( alloc ) { b = block_alloc(); if( b == NULL ) return ENOSPC; blocks[bi] = b; } else return ENOERR; } *buffer = &((*b)[bpos]); *size = CYGNUM_RAMFS_BLOCK_SIZE - bpos; return ENOERR;}// -------------------------------------------------------------------------// findbuffer_indirect1()// Indexes into an array of pointers to blocks containing pointers to// blocks and extracts a pointer to the data at offset _pos_,// allocating new blocks if required.#if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0static int findbuffer_indirect1( off_t pos, ramfs_block ***blocks, int nblocks, cyg_uint8 **buffer, size_t *size, cyg_bool alloc){ int bi = pos / RAMFS_INDIRECT1_BLOCK_EXTENT; int bpos = pos % RAMFS_INDIRECT1_BLOCK_EXTENT; int err; cyg_uint8 *b; size_t sz; // Use findbuffer_direct() to index and allocate // the first level indirect block. err = findbuffer_direct( bi*CYGNUM_RAMFS_BLOCK_SIZE, (ramfs_block **)blocks, nblocks, &b, &sz, alloc); if( err != ENOERR ) return err; if( sz == 0 ) { *size = 0; return ENOERR; } // Use findbuffer_direct() on the first level indirect // block to allocate and return the data pointer. return findbuffer_direct( bpos, blocks[bi], RAMFS_INDIRECT_PER_BLOCK, buffer, size, alloc);}#endif// -------------------------------------------------------------------------// findbuffer_indirect1()// Indexes into an array of pointers to blocks containing pointers to// blocks containing pointers to blocks (!) and extracts a pointer to// the data at offset _pos_, allocating new blocks if required.#if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0static int findbuffer_indirect2( off_t pos, ramfs_block ****blocks, int nblocks, cyg_uint8 **buffer, size_t *size, cyg_bool alloc){ int bi = pos / RAMFS_INDIRECT2_BLOCK_EXTENT; int bpos = pos % RAMFS_INDIRECT2_BLOCK_EXTENT; int err; cyg_uint8 *b; size_t sz; // Use findbuffer_direct() to index and allocate // the first level indirect block. err = findbuffer_direct( bi*CYGNUM_RAMFS_BLOCK_SIZE, (ramfs_block **)blocks, nblocks, &b, &sz, alloc); if( err != ENOERR ) return err; if( sz == 0 ) { *size = 0; return ENOERR; } // Use findbuffer_indirect1() on the first level indirect block to // index and allocate the next level indirect block and the data // block. return findbuffer_indirect1( bpos, blocks[bi], RAMFS_INDIRECT_PER_BLOCK, buffer, size, alloc);}#endif// -------------------------------------------------------------------------// findbuffer_node()// Depending on the offset and configuration, call the appropriate// function to get the buffer pointer.static int findbuffer_node( ramfs_node *node,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -