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

📄 ramfs.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
		  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

// -------------------------------------------------------------------------
// init_dirsearch()
// Initialize a dirsearch object to start a search

static void init_dirsearch( ramfs_dirsearch *ds,
                            ramfs_node *dir,
                            const char *name)
{
    ds->dir      = dir;
    ds->path     = name;
    ds->node     = dir;
    ds->name     = name;
    ds->namelen  = 0;
    ds->last     = false;    
}

// -------------------------------------------------------------------------
// find_entry()
// Search a single directory for the next name in a path and update the
// dirsearch object appropriately.

static int find_entry( ramfs_dirsearch *ds )
{
    ramfs_node *dir = ds->dir;
    const char *name = ds->path;
    const char *n = name;
    char namelen = 0;
    ramfs_dirent *d;
    
    // check that we really have a directory
    if( !S_ISDIR(dir->mode) )
        return ENOTDIR;

    // Isolate the next element of the path name. 
    while( *n != '\0' && *n != '/' )
        n++, namelen++;

    // Check if this is the last path element.
    while( *n == '/') n++;
    if( *n == '\0' ) 
        ds->last = true;

    // update name in dirsearch object
    ds->name = name;
    ds->namelen = namelen;
    
    // Here we have the name and its length set up.
    // Search the directory for a matching entry

    d = find_direntry( dir, name, namelen );

    if( d == NULL )
        return ENOENT;

    // pass back the node we have found
    ds->node = d->node;

    return ENOERR;

}

// -------------------------------------------------------------------------
// ramfs_find()
// Main interface to directory search code. This is used in all file
// level operations to locate the object named by the pathname.

static int ramfs_find( ramfs_dirsearch *d )
{
    int err;

    // Short circuit empty paths
    if( *(d->path) == '\0' )
        return ENOERR;

    // iterate down directory tree until we find the object
    // we want.
    for(;;)
    {
        err = find_entry( d );

        if( err != ENOERR )
            return err;

        if( d->last )
            return ENOERR;

        // Update dirsearch object to search next directory.
        d->dir = d->node;
        d->path += d->namelen;
        while( *(d->path) == '/' ) d->path++; // skip dirname separators
    }
}

//==========================================================================
// Pathconf support
// This function provides support for pathconf() and fpathconf().

static int ramfs_pathconf( ramfs_node *node, struct cyg_pathconf_info *info )
{
    int err = ENOERR;
    
    switch( info->name )
    {
    case _PC_LINK_MAX:
        info->value = LINK_MAX;
        break;
        
    case _PC_MAX_CANON:
        info->value = -1;       // not supported
        err = EINVAL;
        break;
        
    case _PC_MAX_INPUT:
        info->value = -1;       // not supported
        err = EINVAL;        
        break;
        
    case _PC_NAME_MAX:
        info->value = NAME_MAX;
        break;
        
    case _PC_PATH_MAX:
        info->value = PATH_MAX;
        break;        

    case _PC_PIPE_BUF:
        info->value = -1;       // not supported
        err = EINVAL;        
        break;        

        
    case _PC_ASYNC_IO:
        info->value = -1;       // not supported
        err = EINVAL;        
        break;
        
    case _PC_CHOWN_RESTRICTED:
        info->value = -1;       // not supported
        err = EINVAL;
        break;
        
    case _PC_NO_TRUNC:
        info->value = 0;
        break;
        
    case _PC_PRIO_IO:
        info->value = 0;
        break;
        
    case _PC_SYNC_IO:
        info->value = 0;
        break;
        
    case _PC_VDISABLE:
        info->value = -1;       // not supported
        err = EINVAL;        
        break;
        
    default:
        err = EINVAL;
        break;
    }

    return err;
}

//==========================================================================
// Filesystem operations

// -------------------------------------------------------------------------
// ramfs_mount()
// Process a mount request. This mainly creates a root for the
// filesystem.

static int ramfs_mount    ( cyg_fstab_entry *fste, cyg_mtab_entry *mte )
{
    ramfs_node *root;
    int err;
    
    // Allocate a node to be the root of this filesystem and initialize it.

    root = alloc_node(__stat_mode_DIR|S_IRWXU|S_IRWXG|S_IRWXO);

    if( root == NULL )
        return ENOSPC;

    // Add . and .. entries back to self.
        
    err = add_direntry( root, ".", 1, root );
    if( err == ENOERR )
        err = add_direntry( root, "..", 2, root );

    if( err != ENOERR )
    {
        free_node( root );
        return err;
    }
    
    mte->root = (cyg_dir)root;
    
    return ENOERR;
}

// -------------------------------------------------------------------------
// ramfs_umount()
// Unmount the filesystem. This will currently only succeed if the
// filesystem is empty.

static int ramfs_umount   ( cyg_mtab_entry *mte )
{
    ramfs_node *root = (ramfs_node *)mte->root;

    // Check for open/inuse root
    if( root->refcnt != 0 )
        return EBUSY;

    // Check that root directory is clear of extra links.
    if( root->nlink != 2 )
        return EBUSY;

    // Just return it to free pool
    free_node( root );

    // Clear root pointer
    mte->root = CYG_DIR_NULL;
    
    // That's all folks.
        
    return ENOERR;
}

// -------------------------------------------------------------------------
// ramfs_open()
// Open a file for reading or writing.

static int ramfs_open     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             int mode,  cyg_file *file )
{

    ramfs_dirsearch ds;
    ramfs_node *node = NULL;
    int err;

    init_dirsearch( &ds, (ramfs_node *)dir, name );
    
    err = ramfs_find( &ds );

    if( err == ENOENT )
    {
        if( ds.last && (mode & O_CREAT) )
        {
            // No node there, if the O_CREAT bit is set then we must
            // create a new one. The dir and name fields of the dirsearch
            // object will have been updated so we know where to put it.

            node = alloc_node( __stat_mode_REG|S_IRWXU|S_IRWXG|S_IRWXO);

            if( node == NULL )
                return ENOSPC;

            err = add_direntry( ds.dir, ds.name, ds.namelen, node );

            if( err != ENOERR )
            {
                free_node( node );
                return err;
            }
        
            err = ENOERR;
        }
    }
    else if( err == ENOERR )
    {
        // The node exists. If the O_CREAT and O_EXCL bits are set, we
        // must fail the open.
        
        if( (mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) )
            err = EEXIST;
        else node = ds.node;
    }
    
    if( err == ENOERR && (mode & O_TRUNC ) )
    {
        // If the O_TRUNC bit is set we must clean out the file data.

        err = freebuffer_node( node );
        node->size = 0;

        // Update file times
        node->ctime =
        node->mtime = cyg_timestamp();
    }

    if( err != ENOERR ) return err;

    // Check that we actually have a file here
    if( S_ISDIR(node->mode) ) return EISDIR;

    node->refcnt++;       // Count successful open
    
    // Initialize the file object
    
    file->f_flag        |= mode & CYG_FILE_MODE_MASK;
    file->f_type        = CYG_FILE_TYPE_FILE;
    file->f_ops         = &ramfs_fileops;
    file->f_offset      = (mode&O_APPEND) ? node->size : 0;
    file->f_data        = (CYG_ADDRWORD)node;
    file->f_xops        = 0;

    return ENOERR;
}

// -------------------------------------------------------------------------
// ramfs_unlink()
// Remove a file link from its directory.

static int ramfs_unlink   ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
{
    ramfs_dirsearch ds;
    int err;

    init_dirsearch( &ds, (ramfs_node *)dir, name );
    
    err = ramfs_find( &ds );

    if( err != ENOERR ) return err;

    // Cannot unlink directories, use rmdir() instead
    if( S_ISDIR(ds.node->mode) )
        return EPERM;

    // Delete it from its directory
    err = del_direntry( ds.dir, ds.name, ds.namelen );
    
    return err;
}

// -------------------------------------------------------------------------
// ramfs_mkdir()
// Create a new directory.

static int ramfs_mkdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
{
    ramfs_dirsearch ds;
    ramfs_node *node = NULL;
    int err;

    init_dirsearch( &ds, (ramfs_node *)dir, name );
    
    err = ramfs_find( &ds );

    if( err == ENOENT )
    {
        if( ds.last )
        {
            // The entry does not exist, and it is the last element in

⌨️ 快捷键说明

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