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

📄 fatfs.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    err = fatfs_get_disk_info(disk);
    if (err != ENOERR)
    {
        fatfs_tcache_delete(disk);
        cyg_blib_delete(&disk->blib);
        free(disk->bcache_mem);
        free(disk);
        return err;
    }
   
#if TFS    
    print_disk_info(disk);
#endif

    CYG_TRACE0(TFS, "Initializing node cache");

    fatfs_node_cache_init(disk);
    
    CYG_TRACE0(TFS, "Initializing root node");
    
    fatfs_get_root_node(disk, &root_data);
    disk->root = fatfs_node_alloc(disk, &root_data);
    fatfs_node_ref(disk, disk->root);
    
    mte->root = (cyg_dir)disk->root;
    mte->data = (CYG_ADDRWORD)disk;

    CYG_TRACE0(TFS, "Disk mounted");

    return ENOERR;
}

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

static int
fatfs_umount(cyg_mtab_entry *mte)
{
    fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
    fatfs_node_t *root = (fatfs_node_t *)mte->root;

    CYG_TRACE3(TFS, "Umount mte=%p %d live nodes %d dead nodes", 
                    mte, fatfs_get_live_node_count(disk), 
                    fatfs_get_dead_node_count(disk));

    if (root->refcnt > 1)
        return EBUSY;
    
    if (fatfs_get_live_node_count(disk) != 1)
        return EBUSY;

    fatfs_node_unref(disk, root);
    fatfs_node_cache_flush(disk);
    fatfs_tcache_delete(disk);
    // FIXME: cache delete can fail if cache can't be synced
    cyg_blib_delete(&disk->blib); 
    free(disk->bcache_mem);
    free(disk);
    
    mte->root = CYG_DIR_NULL;
    mte->data = (CYG_ADDRWORD)NULL;
    
    CYG_TRACE0(TFS, "Disk umounted");
    
    return ENOERR;
}

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

static int 
fatfs_open(cyg_mtab_entry *mte,
           cyg_dir         dir, 
           const char     *name,
           int             mode,  
           cyg_file       *file)
{
    fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
    fatfs_node_t *node = NULL;
    fatfs_dirsearch_t ds;
    int err;

    CYG_TRACE5(TFS, "Open mte=%p dir=%p name='%s' mode=%d file=%p", 
                    mte, dir, name, mode, file);

    init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);

    err = fatfs_find(&ds);

    if (err == ENOENT)
    {
        if (ds.last && (mode & O_CREAT))
        {
            fatfs_node_t node_data;
            
            // 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.

            CYG_TRACE1(TFS, "Creating new file '%s'", name); 

            err = fatfs_create_file(disk, ds.dir, ds.name, 
                                    ds.namelen, &node_data);
            if (err != ENOERR)
                return err;

            node = fatfs_node_alloc(disk, &node_data);
            if (NULL == node)
                return ENOMEM;
           
            // Update directory times
            ds.dir->atime =
            ds.dir->mtime = cyg_timestamp();
            
            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.
        CYG_TRACE0(TFS, "Truncating file"); 
        fatfs_trunc_file(disk, node);
    }

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

    // Make a reference to this file node     
    fatfs_node_ref(disk, node);

    // Initialize the file object

    file->f_flag   |= mode & CYG_FILE_MODE_MASK;
    file->f_type    = CYG_FILE_TYPE_FILE;
    file->f_ops     = &fatfs_fileops;
    file->f_offset  = (mode & O_APPEND) ? node->size : 0;
    file->f_data    = (CYG_ADDRWORD)node;
    file->f_xops    = 0;

    return ENOERR;
}

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

static int 
fatfs_unlink(cyg_mtab_entry *mte, 
             cyg_dir         dir, 
             const char     *name)
{
    fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
    fatfs_dirsearch_t ds;
    int err;

    CYG_TRACE3(TFS, "Unlink mte=%p dir=%p name='%s'", mte, dir, name);

    init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);

    err = fatfs_find(&ds);

    if (err != ENOERR)
        return err;
  
    if (ds.node->refcnt > 0)
        return EBUSY;
    
    // Delete node
    err = fatfs_delete_file(disk, ds.node);
    if (err == ENOERR)
        fatfs_node_free(disk, ds.node);
    
    return err;
}

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

static int
fatfs_mkdir(cyg_mtab_entry *mte, cyg_dir dir, const char *name)
{
    fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
    fatfs_dirsearch_t ds;
    int err;
    
    CYG_TRACE3(TFS, "Mkdir mte=%p dir=%p name='%s'", mte, dir, name);

    init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);

    err = fatfs_find(&ds);

    if (err == ENOENT)
    {
        if (ds.last)
        {
            fatfs_node_t node_data;
            
            // The entry does not exist, and it is the last element in
            // the pathname, so we can create it here.

            err = fatfs_create_dir(disk, ds.dir, ds.name, 
                                   ds.namelen, &node_data);
            if (err != ENOERR)
                return err;
            
            fatfs_node_alloc(disk, &node_data);

            return ENOERR;
        }
    } 
    else if (err == ENOERR)
    {
        return EEXIST;
    }
    
    return err;
}

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

static int 
fatfs_rmdir(cyg_mtab_entry *mte, cyg_dir dir, const char *name)
{
    fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
    fatfs_dirsearch_t ds;
    int err;

    CYG_TRACE3(TFS, "Rmdir mte=%p dir=%p name='%s'", mte, dir, name);

    init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);

    err = fatfs_find(&ds);

    if (err != ENOERR)
        return err;
  
    // Check that this is actually a directory.
    if (!S_ISDIR(ds.node->mode))
        return EPERM;
 
    if (ds.node->refcnt > 0)
        return EBUSY;
    
    err = fatfs_delete_file(disk, ds.node);
    if (err == ENOERR)
        fatfs_node_free(disk, ds.node);
    
    return err;
}

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

static int 
fatfs_rename(cyg_mtab_entry *mte, 
             cyg_dir         dir1, 
             const char     *name1,
             cyg_dir         dir2, 
             const char     *name2)
{
    fatfs_disk_t *disk  = (fatfs_disk_t *)mte->data;
    fatfs_dirsearch_t ds1, ds2;
    int err;
 
    CYG_TRACE5(TFS, "Rename mte=%p dir1=%p name1='%s' dir2=%p name2='%s'", 
                    mte, dir1, name1, dir2, name2);

    init_dirsearch(&ds1, disk, (fatfs_node_t *)dir1, name1);

    err = fatfs_find(&ds1);
    if (err != ENOERR)
        return err;

    // Protect the found nodes from being reused by the
    // following search
    fatfs_node_ref(disk, ds1.dir);
    fatfs_node_ref(disk, ds1.node);
    
    init_dirsearch(&ds2, disk, (fatfs_node_t *)dir2, name2);
   
    err = fatfs_find(&ds2);

    if (err == ENOERR && ds2.last)
    {
        err = EEXIST;  
        goto out;  
    }
    
    if (err == ENOENT && !ds2.last)
        goto out;
    
    if (ds1.node == ds2.node)
    {
        err = ENOERR;
        goto out;
    }
    
    err = fatfs_rename_file(disk, ds1.dir, ds1.node, ds2.dir, 
                            ds2.name, ds2.namelen);  
    fatfs_node_rehash(disk, ds1.node);

out:
    fatfs_node_unref(disk, ds1.dir);
    fatfs_node_unref(disk, ds1.node);
   
    if (err == ENOERR)
    {
        ds1.dir->atime =
        ds1.dir->mtime = 
        ds2.dir->atime = 
        ds2.dir->mtime = cyg_timestamp();    
    } 
    return err;
}

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

static int 
fatfs_link(cyg_mtab_entry *mte, 
           cyg_dir         dir1, 
           const char     *name1,
           cyg_dir         dir2, 
           const char     *name2, 
           int             type)
{
    CYG_TRACE6(TFS, "Link mte=%p dir1=%p name1='%s' dir2=%p name2='%s' type=%d",
                    mte, dir1, name1, dir2, name2, type);

    // Linking not supported
    return EINVAL;
}

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

static int
fatfs_opendir(cyg_mtab_entry *mte,
              cyg_dir         dir,
              const char     *name,
              cyg_file       *file)
{
    fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
    fatfs_dirsearch_t ds;
    int err;

    CYG_TRACE4(TFS, "Opendir mte=%p dir=%p name='%s' file=%p", 
                    mte, dir, name, file);

    init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);

    err = fatfs_find(&ds);

    if (err != ENOERR)
        return err;

    // Check it is really a directory.
    if (!S_ISDIR(ds.node->mode)) 
        return ENOTDIR;
  
    // Make a reference to this dir node
    fatfs_node_ref(disk, ds.node);
    
    // Initialize the file object
    file->f_type        = CYG_FILE_TYPE_FILE;
    file->f_ops         = &fatfs_dirops;
    file->f_data        = (CYG_ADDRWORD)ds.node;
    file->f_xops        = 0;
    file->f_offset      = 0;

    return ENOERR;
}

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

static int
fatfs_chdir(cyg_mtab_entry *mte,
            cyg_dir         dir,
            const char     *name,
            cyg_dir        *dir_out)
{
    fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;

    CYG_TRACE4(TFS, "Chdir mte=%p dir=%p dir_out=%p name=%d", 
                    mte, dir, dir_out, name);

    if (dir_out != NULL)
    {
        // This is a request to get a new directory pointer in
        // *dir_out.
        
        fatfs_dirsearch_t ds;
        int err;

        init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);

        err = fatfs_find(&ds);

        if (err != ENOERR)
            return err;

⌨️ 快捷键说明

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