📄 ramfs.c
字号:
off_t pos, cyg_uint8 **buffer, size_t *size, cyg_bool alloc){#if CYGNUM_RAMFS_BLOCKS_DIRECT > 0 if( pos < RAMFS_DIRECT_MAX ) return findbuffer_direct( pos, node->direct, CYGNUM_RAMFS_BLOCKS_DIRECT, buffer, size, alloc);#endif #if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0 if( pos < RAMFS_INDIRECT1_MAX ) return findbuffer_indirect1( pos - RAMFS_DIRECT_MAX, node->indirect1, CYGNUM_RAMFS_BLOCKS_INDIRECT1, buffer, size, alloc);#endif #if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0 if( pos < RAMFS_INDIRECT2_MAX ) return findbuffer_indirect2( pos - RAMFS_INDIRECT1_MAX, node->indirect2, CYGNUM_RAMFS_BLOCKS_INDIRECT2, buffer, size, alloc);#endif return ENOSPC;}// -------------------------------------------------------------------------// freeblock_list()// Free a list of data blocks.static void freeblock_list( ramfs_block *blocks[],int nblocks ){ int i; for( i = 0; i < nblocks ; i++ ) { if( blocks[i] != NULL ) { block_free( blocks[i] ); blocks[i] = NULL; } }}// -------------------------------------------------------------------------// freebuffer_node()// Free all the data blocks in the node and clear the pointers.static int freebuffer_node( ramfs_node *node ){#if CYGNUM_RAMFS_BLOCKS_DIRECT > 0 freeblock_list( node->direct, CYGNUM_RAMFS_BLOCKS_DIRECT );#endif#if CYGNUM_RAMFS_BLOCKS_INDIRECT1 > 0 { int i; for( i = 0; i < CYGNUM_RAMFS_BLOCKS_INDIRECT1 ; i++ ) { if( node->indirect1[i] != NULL ) { freeblock_list( (ramfs_block **)node->indirect1[i], RAMFS_INDIRECT_PER_BLOCK ); block_free( (ramfs_block *)node->indirect1[i] ); node->indirect1[i] = NULL; } } }#endif #if CYGNUM_RAMFS_BLOCKS_INDIRECT2 > 0 { int i; for( i = 0; i < CYGNUM_RAMFS_BLOCKS_INDIRECT2 ; i++ ) { if( node->indirect2[i] != NULL ) { ramfs_block ***b = node->indirect2[i]; int j; for( j = 0; j < RAMFS_INDIRECT_PER_BLOCK ; j++ ) { if( b[j] != NULL ) { freeblock_list( (ramfs_block **)b[j], RAMFS_INDIRECT_PER_BLOCK ); block_free( (ramfs_block *)b[j] ); b[j] = NULL; } } block_free( (ramfs_block *)node->indirect2[i] ); node->indirect2[i] = NULL; } } }#endif return ENOERR;}//==========================================================================#endif//==========================================================================// Node allocation// -------------------------------------------------------------------------// alloc_node()// Allocate a node and initialize it.// For the _SIMPLE allocation option, we just malloc it. For the// _BLOCKS option we allocate a block and use that. In theory we could// pack several nodes into a single block, but we don't at present due// to sheer lazyness.static ramfs_node *alloc_node( mode_t mode ){#ifdef CYGPKG_FS_RAM_SIMPLE ramfs_node *node = malloc( sizeof( ramfs_node ) ); if( node == NULL ) return NULL; #else ramfs_block *b = block_alloc(); ramfs_node *node; if( b == NULL ) return NULL; node = (ramfs_node *)b; #endif memset( node, 0, sizeof(ramfs_node) ); node->mode = mode; node->refcnt = 0; node->nlink = 0; node->size = 0; node->atime = node->mtime = node->ctime = cyg_timestamp();#ifdef CYGPKG_FS_RAM_SIMPLE node->datasize = 0; node->data = NULL;#else // The node is already all zero #endif return node;}// -------------------------------------------------------------------------// free_node()// Release a node either back to the free pool or back into the block// pool.static void free_node( ramfs_node *node ){#ifdef CYGPKG_FS_RAM_SIMPLE free( node );#else block_free( (ramfs_block *)node );#endif }//==========================================================================// Ref count and nlink management// -------------------------------------------------------------------------// dec_refcnt()// Decrment the reference count on a node. If this makes the ref count// zero, and the number of links is either zero for a file or one for// a node, then this node is detached from the directory tree and can// be freed.static int dec_refcnt( ramfs_node *node ){ int err = ENOERR; node->refcnt--; if( node->refcnt == 0 && ((S_ISREG(node->mode) && node->nlink == 0 ) || (S_ISDIR(node->mode) && node->nlink == 1) ) ) { // This node it now totally detached from the directory tree, // so delete it. if( S_ISDIR(node->mode) ) { del_direntry( node, ".", 1 ); del_direntry( node, "..", 2 ); } err = freebuffer_node( node ); if( err == ENOERR ) free_node( node ); } return err;}// -------------------------------------------------------------------------// dec_nlink()// Decrement a node's link count. Since this has to do all the same// work as dec_refcnt() we implement this using that function by// essentially transferring the count to refcnt and then decrement// that.static int dec_nlink( ramfs_node *node ){ node->refcnt++; node->nlink--; return dec_refcnt( node );}//==========================================================================// Directory operations// -------------------------------------------------------------------------// add_direntry()// Add an entry to a directory. This is added as a chain of entry// fragments until the name is exhausted.static int add_direntry( ramfs_node *dir, // dir to add to const char *name, // name to add int namelen, // length of name ramfs_node *node // node to reference ){ off_t pos = 0; ramfs_dirent *d = NULL, *dp = NULL; cyg_bool isfirst = true; // Loop inserting fragments of the name into the directory until we // have found a home for them all. while( namelen > 0 ) { int fraglen = namelen; if( fraglen > sizeof(d->name) ) fraglen = sizeof(d->name); // Find a free fragment for(;;) { cyg_uint8 *buf; size_t size; int err = findbuffer_node( dir, pos, &buf, &size, true ); if( err != ENOERR ) return err; d = (ramfs_dirent *)buf; if( size < sizeof(ramfs_dirent) || d->inuse ) { pos += sizeof(ramfs_dirent); continue; } break; } // d now points to a free dirent structure d->node = node; d->inuse = 1; d->first = isfirst; d->namelen = namelen; d->fraglen = fraglen; if( dp ) dp->next = pos; memcpy( d->name, name, fraglen ); name += fraglen; namelen -= fraglen; pos += sizeof(ramfs_dirent); dp = d; isfirst = false; } d->last = 1; // Mark last fragment // Update directory times dir->mtime = dir->ctime = cyg_timestamp(); // Extend dir size if necessary if( pos > dir->size ) dir->size = pos; // Count the new link node->nlink++; return ENOERR;}// -------------------------------------------------------------------------// find_direntry()// Find a directory entry for the name and return a pointer to the first// entry fragment.static ramfs_dirent *find_direntry( ramfs_node *dir, const char *name, int namelen ){ ramfs_dirent *first = NULL; 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 ) { const char *frag = name; ramfs_dirent *d; cyg_uint8 *buf; size_t size; // look for a first name fragment for(;;) { err = findbuffer_node( dir, pos, &buf, &size, false ); if( err != ENOERR || size == 0) return NULL; d = (ramfs_dirent *)buf; if( size < sizeof(ramfs_dirent) || !d->inuse || !d->first ) { pos += sizeof(ramfs_dirent); continue; } break; } // Here we have got a first fragment of a name, check it // against the name we are looking for. First check that they // are the same length. if( d->namelen == namelen ) { // We have a potential candidate here... first = d; // Save it for later // Now check that all the name fragments match for(;;) { int fraglen = namelen-(frag-name); if( fraglen > d->fraglen ) fraglen = d->fraglen; // compare strings, if different, look for another if( memcmp( frag, d->name, fraglen ) != 0 ) break; frag += fraglen; // If we are at the last fragment, then the whole name string // has matched and we have a successful search. if( d->last ) return first; // Otherwise move on to next entry in chain err = findbuffer_node( dir, d->next, &buf, &size, false ); if( err != ENOERR ) return NULL; d = (ramfs_dirent *)buf; } } pos += sizeof(ramfs_dirent); } return NULL;}// -------------------------------------------------------------------------// del_direntry()// Delete a named directory entry. Find it and then follow the chain// deleting the fragments as we go.static int del_direntry( ramfs_node *dir, const char *name, int namelen ){ ramfs_dirent *d = find_direntry( dir, name, namelen ); if( d == NULL ) return ENOENT; for(;;) { int err; cyg_uint8 *buf; size_t size; d->inuse = 0; if( d->last ) break; err = findbuffer_node( dir, d->next, &buf, &size, false ); if( err != ENOERR ) return ENOENT; d = (ramfs_dirent *)buf; } dec_nlink( d->node ); return ENOERR;}//==========================================================================// Directory search
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -