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

📄 ramfs.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
            // the pathname, so we can create it here.
            int doterr, dotdoterr, direrr;
        
            node = alloc_node( __stat_mode_DIR | S_IRWXU|S_IRWXG|S_IRWXO);

            if( node == NULL )
                return ENOSPC;

            // Add "." and ".." entries.
            doterr = add_direntry( node, ".", 1, node );
            dotdoterr = add_direntry( node, "..", 2, ds.dir );

            // And add to parent directory.
            direrr = add_direntry( ds.dir, ds.name, ds.namelen, node );

            // check for any errors in that...
            if( doterr+dotdoterr+direrr != ENOERR )
            {
                // For each of the add_direntry() calls that succeeded,
                // we must now undo it.
                
                if( doterr == ENOERR )
                    del_direntry( node, ".", 1 );
                else err = doterr;

                if( dotdoterr == ENOERR )
                    del_direntry( node, "..", 2 );
                else err = dotdoterr;

                if( direrr == ENOERR )
                    del_direntry( ds.dir, ds.name, ds.namelen );
                else err = direrr;

                // Free the data and the node itself.
                freebuffer_node( node );
                free_node( node );
            }
            else err = ENOERR;
        }
        // If this was not the last element, then and intermediate
        // directory does not exist.
    }
    else
    {
        // If there we no error, something already exists with that
        // name, so we cannot create another one.
        
        if( err == ENOERR )
            err = EEXIST;
    }

    return err;
}

// -------------------------------------------------------------------------
// ramfs_rmdir()
// Remove a directory.

static int ramfs_rmdir    ( 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;

    // Check that this is actually a directory.
    if( !S_ISDIR(ds.node->mode) )
        return EPERM;

    // Delete the entry. This will adjust the link values
    // accordingly and if the directory is now unreferenced,
    // will cause it to be deleted.
    
    err = del_direntry( ds.dir, ds.name, ds.namelen );
    
    return err;
}

// -------------------------------------------------------------------------
// ramfs_rename()
// Rename a file/dir.

static int ramfs_rename   ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
                             cyg_dir dir2, const char *name2 )
{
    ramfs_dirsearch ds1, ds2;
    int err;

    init_dirsearch( &ds1, (ramfs_node *)dir1, name1 );
    
    err = ramfs_find( &ds1 );

    if( err != ENOERR ) return err;

    init_dirsearch( &ds2, (ramfs_node *)dir2, name2 );
    
    err = ramfs_find( &ds2 );

    // Allow through renames to non-existent objects.
    if( ds2.last && err == ENOENT )
        ds2.node = NULL, err = ENOERR;
    
    if( err != ENOERR ) return err;

    // Null rename, just return
    if( ds1.node == ds2.node )
        return ENOERR;

    // First deal with any entry that is at the destination
    if( ds2.node )
    {
        // Check that we are renaming like-for-like

        if( !S_ISDIR(ds1.node->mode) && S_ISDIR(ds2.node->mode) )
            return EISDIR;

        if( S_ISDIR(ds1.node->mode) && !S_ISDIR(ds2.node->mode) )
            return ENOTDIR;

        // Now delete the destination directory entry
        
        err = del_direntry( ds2.dir, ds2.name, ds2.namelen );
        
        if( err != ENOERR ) return err;

    }

    // Now we know that there is no clashing node at the destination,
    // make a new direntry at the destination and delete the old entry
    // at the source.

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

    if( err == ENOERR )
        err = del_direntry( ds1.dir, ds1.name, ds1.namelen );

    // Update directory times
    if( err == ENOERR )
        ds1.dir->ctime =
        ds1.dir->mtime =
        ds2.dir->ctime =
        ds2.dir->mtime = cyg_timestamp();
            
    return err;
}

// -------------------------------------------------------------------------
// ramfs_link()
// Make a new directory entry for a file.

static int ramfs_link     ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
                             cyg_dir dir2, const char *name2, int type )
{
    ramfs_dirsearch ds1, ds2;
    int err;

    // Only do hard links for now in this filesystem
    if( type != CYG_FSLINK_HARD )
        return EINVAL;
    
    init_dirsearch( &ds1, (ramfs_node *)dir1, name1 );
    
    err = ramfs_find( &ds1 );

    if( err != ENOERR ) return err;

    init_dirsearch( &ds2, (ramfs_node *)dir2, name2 );
    
    err = ramfs_find( &ds2 );

    // Don't allow links to existing objects
    if( err == ENOERR ) return EEXIST;
    
    // Allow through links to non-existing terminal objects
    if( ds2.last && err == ENOENT )
        ds2.node = NULL, err = ENOERR;

    if( err != ENOERR ) return err;
    
    // Now we know that there is no existing node at the destination,
    // make a new direntry at the destination.

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

    if( err == ENOERR )
        ds1.node->ctime =
        ds2.dir->ctime =
        ds2.dir->mtime = cyg_timestamp();
            
    return err;
}

// -------------------------------------------------------------------------
// ramfs_opendir()
// Open a directory for reading.

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

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

    if( err != ENOERR ) return err;

    // check it is really a directory.
    if( !S_ISDIR(ds.node->mode) ) return ENOTDIR;

    ds.node->refcnt++;       // Count successful open
    
    // Initialize the file object, setting the f_ops field to a
    // special set of file ops.
    
    file->f_type        = CYG_FILE_TYPE_FILE;
    file->f_ops         = &ramfs_dirops;
    file->f_offset      = 0;
    file->f_data        = (CYG_ADDRWORD)ds.node;
    file->f_xops        = 0;
        
    return ENOERR;

}

// -------------------------------------------------------------------------
// ramfs_chdir()
// Change directory support.

static int ramfs_chdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             cyg_dir *dir_out )
{
    if( dir_out != NULL )
    {
        // This is a request to get a new directory pointer in
        // *dir_out.

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

        if( err != ENOERR ) return err;

        // check it is a directory
        if( !S_ISDIR(ds.node->mode) )
            return ENOTDIR;
        
        // Increment ref count to keep this directory in existent
        // while it is the current cdir.
        ds.node->refcnt++;

        // Pass it out
        *dir_out = (cyg_dir)ds.node;
    }
    else
    {
        // If no output dir is required, this means that the mte and
        // dir arguments are the current cdir setting and we should
        // forget this fact.

        ramfs_node *node = (ramfs_node *)dir;

        // Just decrement directory reference count.
        dec_refcnt( node );
    }
        
    return ENOERR;
}

// -------------------------------------------------------------------------
// ramfs_stat()
// Get struct stat info for named object.

static int ramfs_stat     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             struct stat *buf)
{
    ramfs_dirsearch ds;
    int err;

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

    if( err != ENOERR ) return err;

    // Fill in the status
    buf->st_mode        = ds.node->mode;
    buf->st_ino         = (ino_t)ds.node;
    buf->st_dev         = 0;
    buf->st_nlink       = ds.node->nlink;
    buf->st_uid         = 0;
    buf->st_gid         = 0;
    buf->st_size        = ds.node->size;
    buf->st_atime       = ds.node->atime;
    buf->st_mtime       = ds.node->mtime;
    buf->st_ctime       = ds.node->ctime;
    
    return err;
}

// -------------------------------------------------------------------------
// ramfs_getinfo()
// Getinfo. Currently only support pathconf() and filesystem usage.

static int ramfs_getinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             int key, void *buf, int len )
{
    ramfs_dirsearch ds;
    int err;

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

    if( err != ENOERR ) return err;

    switch( key )
    {
    case FS_INFO_CONF:
        err = ramfs_pathconf( ds.node, (struct cyg_pathconf_info *)buf );
        break;
#if defined(CYGSEM_FILEIO_BLOCK_USAGE) && defined(CYGPKG_FS_RAM_BLOCKS_ARRAY)
	// When using malloc for storage this does not make much
	// sense, so only implement this when using pre-allocated
	// blocks
    case FS_INFO_BLOCK_USAGE: {
      struct cyg_fs_block_usage *usage = (struct cyg_fs_block_usage *) buf;
      ramfs_block *b;
      
      usage->total_blocks = CYGNUM_FS_RAM_BLOCKS_ARRAY_SIZE;
      usage->free_blocks = 0;
      // Iterate over the free list to count its size
      b = block_free_list;
      while(b) {
	usage->free_blocks++;
	b=*(ramfs_block **)b;
      }
      usage->block_size = CYGNUM_RAMFS_BLOCK_SIZE;
      return ENOERR;
    }
#endif
    default:
        err = EINVAL;
    }
    return err;
}

// -------------------------------------------------------------------------
// ramfs_setinfo()
// Setinfo. Nothing to support here at present.

static int ramfs_setinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             int key, void *buf, int len )
{
    // No setinfo keys supported at present
    
    return EINVAL;
}


//==========================================================================
// File operations

// -------------------------------------------------------------------------
// ramfs_fo_read()
// Read data from the file.

static int ramfs_fo_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
    ramfs_node *node = (ramfs_node *)fp->f_data;
    int i;
    off_t pos = fp->f_offset;
    ssize_t resid = uio->uio_resid;

    // Loop over the io vectors until there are none left
    for( i = 0; i < uio->uio_iovcnt; i++ )
    {
        cyg_iovec *iov = &uio->uio_iov[i];
        char *buf = (char *)iov->iov_base;
        off_t len = iov->iov_len;

        // Loop over each vector filling it with data from the file.
        while( len > 0 && pos < node->size )
        {
            cyg_uint8 *fbuf;
            size_t bsize;
            off_t l = len;
            int err;

            // Get a pointer to the data at offset _pos_.
            err = findbuffer_node( node, pos, &fbuf, &bsize, false );

            if( err != ENOERR )
                return err;

            // adjust size to end of file if necessary
            if( l > node->size-pos )
                l = node->size-pos;
            
            // adjust size to the amount of contiguous data we can see
            // at present.
            if( l > bsize )
                l = bsize;
            
            if (fbuf) {
              // copy data out
              memcpy( buf, fbuf, l );
            } else { // hole, so return zeros here.
              memset( buf, 0, l )

⌨️ 快捷键说明

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