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

📄 testfs.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    if( !testfs_initialized )
    {
        int i;

        for( i = 0; i < TESTFS_NFILE; i++ )
        {
            node[i].next = free_node;
            node[i].refcnt = -1;
            free_node = &node[i];
        }

        for( i = 0; i < TESTFS_NBLOCK; i++ )
        {
            block[i].u.next = free_block;
            block[i].pos = -1;
            free_block = &block[i];
        }

        testfs_initialized = true;
    }

    // Allocate a node to be the root of this filesystem and
    // initialize it.

    root = free_node;
    
    if( root == NULL ) return ENOSPC;

    free_node = root->next;

    root->next                  = root;  // form circular list
    root->parent                = root;  // I'm my own parent!
    root->refcnt                = 1;     // don't want to ever lose root
    strcpy( root->name, "root");
    root->status.st_mode        = __stat_mode_DIR;
    root->status.st_ino         = root-&node[0];
    root->status.st_dev         = 0;
    root->status.st_nlink       = 1;
    root->status.st_uid         = 0;
    root->status.st_gid         = 0;
    root->status.st_size        = 0;
    root->status.st_atime       = testfs_time();
    root->status.st_mtime       = testfs_time();
    root->status.st_ctime       = testfs_time();

    for( i = 0; i < TESTFS_FILEBLOCKS; i++ )
        root->u.dir.nodes[i]    = NULL;
    
    mte->root = (cyg_dir)root;
    
    return 0;
}

// -------------------------------------------------------------------------

static int testfs_umount    ( cyg_mtab_entry *mte )
{
    testfs_node *root = (testfs_node *)mte->root;

    // Non-empty filesystem, do not unmount
    if( root->refcnt != 1 )
        return EBUSY;

    // Otherwise just return it to the free pool
    root->next = free_node;
    root->refcnt = -1;
    free_node = root;

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

static int testfs_open     ( cyg_mtab_entry *mte, cyg_dir dir, const char *path,
                          int mode,  cyg_file *file )
{
    testfs_node *nd, *parent;
    int err;
    char name[TESTFS_NAMESIZE];
    cyg_bool lastp;
    
    err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp );

    if( lastp && err == ENOENT && (mode & O_CREAT) )
    {
        int i;
        // No node there, if the O_CREAT bit is set then we must
        // create a new one. The parent and name results will have been filled
        // in, so we know where to put it.

        // first check that there is space for it
        for( i = 0; i < TESTFS_FILEBLOCKS; i++ )
            if( parent->u.dir.nodes[i] == NULL )
                break;

        if( i == TESTFS_FILEBLOCKS ) return ENOSPC;
        
        // Allocate a new node
        nd = free_node;
        if( nd == NULL ) return ENOSPC;
        free_node = nd->next;

        // Add to directory list
        parent->u.dir.nodes[i] = nd;

        parent->refcnt++;
        
        // Fill in details
        nd->parent              = parent;
        nd->refcnt              = 1;    // 1 for directory reference
        strcpy( nd->name, name);
        nd->status.st_mode      = __stat_mode_REG;
        nd->status.st_ino       = nd-&node[0];
        nd->status.st_dev       = 0;
        nd->status.st_nlink     = 1;
        nd->status.st_uid       = 0;
        nd->status.st_gid       = 0;
        nd->status.st_size      = 0;
        nd->status.st_atime     = testfs_time();
        nd->status.st_mtime     = testfs_time();
        nd->status.st_ctime     = testfs_time();

        for( i = 0; i < TESTFS_FILEBLOCKS; i++ )
            nd->u.file.data[i]  = NULL;

        err = ENOERR;
    }

    if( err == ENOERR && (mode & O_TRUNC ) )
    {
        // Clean out any blocks in the file...

        int i;
        
        for( i = 0; i < TESTFS_FILEBLOCKS; i++ )
        {
            testfs_block *b = nd->u.file.data[i];
            if( b != NULL )
            {
                b->u.next = free_block;
                b->pos = -1;
                free_block = b;
                nd->u.file.data[i] = NULL;
            }
        }

        nd->status.st_size = 0;
    }
    
    if( err != ENOERR ) return err;

    if( S_ISDIR(nd->status.st_mode) ) return EISDIR;

    nd->refcnt++;       // Count successful open as a ref
    
    // Initialize the file object
    
    file->f_flag        |= mode & CYG_FILE_MODE_MASK;
    file->f_type        = CYG_FILE_TYPE_FILE;
    file->f_ops         = &testfs_fileops;
    file->f_offset      = 0;
    file->f_data        = (CYG_ADDRWORD)nd;
    file->f_xops        = 0;
    
    return ENOERR;
}

// -------------------------------------------------------------------------

static int testfs_unlink   ( cyg_mtab_entry *mte, cyg_dir dir, const char *path )
{
    testfs_node *nd, *parent;
    int err;
    char name[TESTFS_NAMESIZE];
    cyg_bool lastp;
   
    err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp );

    if( err != ENOERR ) return err;

    // Cannot unlink directories, use rmdir() instead
    if( S_ISDIR(nd->status.st_mode) )
        return EPERM;

    err = testfs_delnode( nd );
    
    return err;
}

// -------------------------------------------------------------------------

static int testfs_mkdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *path )
{
    
    testfs_node *nd, *parent;
    int err;
    char name[TESTFS_NAMESIZE];
    cyg_bool lastp;
    
    err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp );

    if( lastp && err == ENOENT )
    {
        int i;
        // No node there, create a new one. The parent and name
        // results will have been filled in, so we know where to put
        // it.

        // first check that there is space for it
        for( i = 0; i < TESTFS_FILEBLOCKS; i++ )
            if( parent->u.dir.nodes[i] == NULL )
                break;

        if( i == TESTFS_FILEBLOCKS ) return ENOSPC;
        
        // Allocate a new node
        nd = free_node;
        if( nd == NULL ) return ENOSPC;
        free_node = nd->next;

        // Add to directory list
        parent->u.dir.nodes[i] = nd;

        parent->refcnt++;
 
        // Fill in details
        nd->parent              = parent;
        nd->refcnt              = 1;    // 1 for directory reference
        strcpy( nd->name, name);
        nd->status.st_mode      = __stat_mode_DIR;
        nd->status.st_ino       = nd-&node[0];
        nd->status.st_dev       = 0;
        nd->status.st_nlink     = 1;
        nd->status.st_uid       = 0;
        nd->status.st_gid       = 0;
        nd->status.st_size      = 0;
        nd->status.st_atime     = testfs_time();
        nd->status.st_mtime     = testfs_time();
        nd->status.st_ctime     = testfs_time();

        for( i = 0; i < TESTFS_FILEBLOCKS; i++ )
            nd->u.dir.nodes[i]  = NULL;
        
        err = ENOERR;
    }

    return err;
}

// -------------------------------------------------------------------------

static int testfs_rmdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *path )
{
    testfs_node *nd, *parent;
    int err;
    char name[TESTFS_NAMESIZE];
    cyg_bool lastp;
   
    err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp );

    if( err != ENOERR ) return err;

    // Check that it is a directory
    if( !S_ISDIR(nd->status.st_mode) )
        return EPERM;

    err = testfs_delnode( nd );

    return err;
}

// -------------------------------------------------------------------------

static int testfs_rename   ( cyg_mtab_entry *mte, cyg_dir dir1, const char *path1,
                          cyg_dir dir2, const char *path2 )
{
    testfs_node *nd1, *parent1;
    testfs_node *nd2, *parent2;
    int err;
    char name1[TESTFS_NAMESIZE];
    char name2[TESTFS_NAMESIZE];
    cyg_bool lastp;
    int i,j;
    
    err = testfs_find( (testfs_node *)dir1, path1, &nd1, &parent1, name1, &lastp );

    if( err != ENOERR ) return err;

    err = testfs_find( (testfs_node *)dir2, path2, &nd2, &parent2, name2, &lastp );

    // Allow through renames to non-existent objects.
    if( lastp && err == ENOENT )
        err = ENOERR;
    
    if( err != ENOERR ) return err;

    // Null rename, just return
    if( nd1 == nd2 )
        return ENOERR;
    

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

        if( !S_ISDIR(nd1->status.st_mode) && S_ISDIR(nd2->status.st_mode) )
            return EISDIR;

        if( S_ISDIR(nd1->status.st_mode) && !S_ISDIR(nd2->status.st_mode) )
            return ENOTDIR;

        // Now delete the destination node.
        err = testfs_delnode( nd2 );
        if( err != ENOERR ) return err;
    }

    // Now we know that there is no clashing node at the destination.
    // Move the node over and change its name.

    // first check that there is space for it
    for( i = 0; i < TESTFS_FILEBLOCKS; i++ )
        if( parent2->u.dir.nodes[i] == NULL )
            break;

    if( i == TESTFS_FILEBLOCKS ) return ENOSPC;

    // Now remove node from old parent.
    for( j = 0; j < TESTFS_FILEBLOCKS; j++ )
        if( parent1->u.dir.nodes[j] == nd1 )
        {
            parent1->u.dir.nodes[j] = NULL;
            break;
        }

    parent1->refcnt--;

    // Add to directory list
    parent2->u.dir.nodes[i] = nd1;
    parent2->refcnt++;
    nd1->parent = parent2;
    
    // And give it a new name.
    strcpy( nd1->name, name2 );
    
    return err;
}

// -------------------------------------------------------------------------

static int testfs_link   ( cyg_mtab_entry *mte, cyg_dir dir1, const char *path1,
                          cyg_dir dir2, const char *path2, int type )
{
    // The data structures of this file system do not support the
    // creation of links.
    
    return ENOSYS;
}

// -------------------------------------------------------------------------

static int testfs_opendir  ( cyg_mtab_entry *mte, cyg_dir dir, const char *path,
                          cyg_file *file )
{
    testfs_node *nd, *parent;
    int err;
    char name[TESTFS_NAMESIZE];
    cyg_bool lastp;
    
    err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp );

    if( err != ENOERR ) return err;

    if( !S_ISDIR(nd->status.st_mode) )
        return ENOTDIR;

    nd->refcnt++;       // Count successful open as a ref
    
    // Initialize the file object
    
    file->f_type        = CYG_FILE_TYPE_FILE;
    file->f_ops         = &testfs_dirops;
    file->f_offset      = 0;
    file->f_data        = (CYG_ADDRWORD)nd;
    file->f_xops        = 0;
    
    return ENOERR;
}

// -------------------------------------------------------------------------

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

        testfs_node *nd, *parent;
        int err;
        char name[TESTFS_NAMESIZE];
        cyg_bool lastp;
    
        err = testfs_find( (testfs_node *)dir, path, &nd, &parent, name, &lastp );

        if( err != ENOERR ) return err;

        if( !S_ISDIR(nd->status.st_mode) )
            return ENOTDIR;
        
        // Increment ref count to keep this directory in existent
        // while it is the current cdir.

⌨️ 快捷键说明

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