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

📄 ramfs.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
    // 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,
                            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);
		if ( pos < dir->size )
		  continue;
		// End if directory, didn't find it.
		return NULL;
            }

            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 ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -