⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ramfs.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                            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 + -