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

📄 ramfs.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:

typedef cyg_uint8 ramfs_block[CYGNUM_RAMFS_BLOCK_SIZE];

#endif

//==========================================================================
// File and directory node
// This data structure represents a file or directory.

struct ramfs_node
{
    mode_t              mode;           // node type
    cyg_ucount32        refcnt;         // open file/current dir references
    nlink_t             nlink;          // number of links to this node
    size_t              size;           // size of file in bytes
    time_t              atime;          // last access time
    time_t              mtime;          // last modified time
    time_t              ctime;          // last changed status time

#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 defs

static 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 here

static 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 blocks
static 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_ARRAY

static 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 + node->datasize, 0, 
                     pos + CYGNUM_RAMFS_REALLOC_INCREMENT - node->datasize );
        
        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 = CYGNUM_RAMFS_BLOCK_SIZE - bpos;
    
    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 there
        // is no block and size indicates where the block would end if
        // it existed.
        if( alloc )
        {
            b = block_alloc();
            if( b == NULL )
                return ENOSPC;
            blocks[bi] = b;
        }
        else return ENOERR;
    }

    *buffer = &((*b)[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 > 0

static 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 > 0

static 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;

⌨️ 快捷键说明

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