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

📄 fatfs_supp.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
            apos = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos);
        }
        
        // Adjust the data chunk size to be read to the cluster boundary
        if (size > (disk->cluster_size - dpos->cluster_pos))
            csize = disk->cluster_size - dpos->cluster_pos;
        else
            csize = size;

        CYG_TRACE5(TDO, "-- len=%d cluster=%d cluster_pos=%d "
                        "cluster_snum=%d apos=%d", csize, dpos->cluster,
                        dpos->cluster_pos, dpos->cluster_snum, apos);

        // Read data chunk 
        err = cyg_blib_read(&disk->blib, (void*)buf, &csize, 0, apos);

        if (err != ENOERR)
            goto out;

        // Adjust running variables
        buf               += csize;
        dpos->cluster_pos += csize;
        apos              += csize;
        size              -= csize;    
    }
    
out:
    *len -= size;

    CYG_TRACE1(TDO, "total len=%d", *len);

    return err;
}

// -------------------------------------------------------------------------
// write_data()
// Writes data to given position. 
 
static int
write_data(fatfs_disk_t     *disk,
           void             *data,
           cyg_uint32       *len,
           fatfs_data_pos_t *dpos,
           fatfs_tcache_t   *tcache)
{
    unsigned char *buf;
    cyg_uint32 apos;
    cyg_uint32 size;
    int err;

    // Initialize variables and get the absolute starting pos on disk
    buf   = (unsigned char *)data;
    size  = *len;
    apos  = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos);
    err   = ENOERR;
  
    CYG_TRACE5(TDO, "len=%d cluster=%d cluster_pos=%d "
                    "cluster_snum=%d apos=%d", *len, dpos->cluster, 
                    dpos->cluster_pos, dpos->cluster_snum, apos);

    while (size > 0)
    {
        cyg_uint32 csize;

        // Check if we are still inside current cluster
        if (!is_pos_inside_cluster(disk, dpos->cluster_pos))
        {
            // Get next cluster of file and adjust absolute disk position,
            // if at the last cluster try to extend the cluster chain 
            err = get_next_cluster(disk, dpos, tcache, CO_EXTEND);
            if (err != ENOERR)
                goto out;
            apos = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos);
        }
        
        // Adjust the data chunk size to be read to the cluster boundary
        if (size > (disk->cluster_size - dpos->cluster_pos))
            csize = disk->cluster_size - dpos->cluster_pos;
        else
            csize = size;
 
        CYG_TRACE5(TDO, "-- len=%d cluster=%d cluster_pos=%d "
                        "cluster_snum=%d apos=%d", csize, dpos->cluster,
                        dpos->cluster_pos, dpos->cluster_snum, apos);

        // Write data chunk 
        err = cyg_blib_write(&disk->blib, (void*)buf, &csize, 0, apos);

        if (err != ENOERR)
            goto out;

        // Adjust running variables
        buf               += csize;
        dpos->cluster_pos += csize;
        apos              += csize;
        size              -= csize;    
    }
    
out:
    *len -= size;

    CYG_TRACE1(TDO, "total len=%d", *len);

    return err;
}

//==========================================================================
// Misc functions 

// -------------------------------------------------------------------------
// init_node()
// Initializes file attributes of a new node. 
 
static void
init_node_fattr(fatfs_node_t     *node, 
                const char       *name, 
                int               namelen,
                mode_t            mode,
                cyg_uint32        parent_cluster, 
                fatfs_data_pos_t *dentry_pos)
{
    if (namelen == 0)
        namelen = 12;
    
    strncpy(node->filename, name, namelen);
    node->filename[namelen] = '\0';
    
    node->mode  = mode;
    node->ctime = 
    node->atime =
    node->mtime = cyg_timestamp();

    node->priv_data      = 0;
    node->size           = 0;
    node->cluster        = 0;
    node->parent_cluster = parent_cluster;
    node->dentry_pos     = *dentry_pos;
}

// -------------------------------------------------------------------------
// is_node_root_node()
// Check if the given node is the root dir node 
 
static __inline__ bool
is_node_root_node(fatfs_node_t *node)
{
    return (node->filename[0] == '\0' && node->cluster == 0);
}

//==========================================================================
//==========================================================================
// Exported functions 

// -------------------------------------------------------------------------
// fatfs_get_disk_info()
// Gets disk info. 
 
int
fatfs_get_disk_info(fatfs_disk_t *disk)
{
    int err;
    cyg_uint32 sec_num, root_dir_sec_num;
    cyg_uint32 data_sec_num, data_clu_num;
    fat_boot_record_t boot_rec;

    CYG_CHECK_DATA_PTRC(disk);
 
    err = read_boot_record(disk, &boot_rec);
    if (err != ENOERR)    
        return err;

    // Check some known boot record values
    if (0x29 != boot_rec.ext_sig       ||
        0x55 != boot_rec.exe_marker[0] ||
        0xAA != boot_rec.exe_marker[1])
        return EINVAL;

    // Determine number of sectors
    if (boot_rec.sec_num_32 != 0)
        sec_num = boot_rec.sec_num_32;
    else
        sec_num = boot_rec.sec_num;
    
    // Number of sectors used by root directory 
    root_dir_sec_num = ((boot_rec.max_root_dents * DENTRY_SIZE) +
                        (boot_rec.bytes_per_sec - 1)) / boot_rec.bytes_per_sec;
        
    // Number of data sectors
    data_sec_num = sec_num - (boot_rec.res_sec_num + 
        (boot_rec.fat_tbls_num * boot_rec.sec_per_fat) + root_dir_sec_num);
    
    // Number of data clusters
    data_clu_num = data_sec_num / boot_rec.sec_per_clust;

    // Determine the type of FAT based on number of data clusters
    if (data_clu_num < 4085) 
        disk->fat_type = FATFS_FAT12;
    else if (data_clu_num < 65525) 
        disk->fat_type = FATFS_FAT16;
    else // FAT32
        return EINVAL;
    
    // Sector and cluster sizes 
    disk->sector_size       = boot_rec.bytes_per_sec;
    disk->sector_size_log2  = get_val_log2(disk->sector_size);
    disk->cluster_size      = boot_rec.bytes_per_sec * boot_rec.sec_per_clust;
    disk->cluster_size_log2 = get_val_log2(disk->cluster_size);

    // Sector and cluster size should always be a power of 2
    if (0 == disk->sector_size_log2 || 0 == disk->cluster_size_log2)
        return EINVAL;

    // FAT table and root dir sizes and position
    disk->fat_tbl_pos        = boot_rec.bytes_per_sec * boot_rec.res_sec_num;
    disk->fat_tbl_size       = boot_rec.bytes_per_sec * boot_rec.sec_per_fat;   
    disk->fat_tbl_nents      = data_clu_num + 2;
    disk->fat_tbls_num       = boot_rec.fat_tbls_num;
    disk->fat_root_dir_pos   = disk->fat_tbl_pos + 
                               disk->fat_tbls_num * disk->fat_tbl_size;
    disk->fat_root_dir_size  = boot_rec.max_root_dents * DENTRY_SIZE;
    disk->fat_root_dir_nents = boot_rec.max_root_dents;
    disk->fat_data_pos       = disk->fat_root_dir_pos + disk->fat_root_dir_size;

    return ENOERR;
}

// -------------------------------------------------------------------------
// fatfs_get_root_node()
// Gets root dir node. 

void
fatfs_get_root_node(fatfs_disk_t *disk, fatfs_node_t *node)
{
    CYG_CHECK_DATA_PTRC(disk);
    CYG_CHECK_DATA_PTRC(node);
    
    node->mode           = __stat_mode_DIR;
    node->size           = disk->fat_root_dir_size;
    node->ctime          = 0;
    node->atime          = 0;
    node->mtime          = 0;
    node->filename[0]    = '\0';
    node->cluster        = 0;
    node->parent_cluster = 0;

    node->dentry_pos.cluster      = 0;
    node->dentry_pos.cluster_snum = 0;
    node->dentry_pos.cluster_pos  = 0;
}

// -------------------------------------------------------------------------
// fatfs_is_node_root_node()
// Check if the given node is root dir node. 

bool
fatfs_is_node_root_node(fatfs_node_t *node)
{
    return(is_node_root_node(node));
}

// -------------------------------------------------------------------------
// fatfs_get_dir_entry_node()
// Gets dir entry node at given position.
// If there is no dir entry at given position the next closest
// dir entry and its position are returned. 
// If EEOF error is returned, then there are no more dir
// entries in given dir. 

int
fatfs_get_dir_entry_node(fatfs_disk_t *disk,
                         fatfs_node_t *dir,
                         cyg_uint32   *pos,
                         fatfs_node_t *node)
{
    fat_dir_entry_t dentry;
    int err;

    CYG_CHECK_DATA_PTRC(disk);
    CYG_CHECK_DATA_PTRC(dir);
    CYG_CHECK_DATA_PTRC(pos);
    CYG_CHECK_DATA_PTRC(node);
 
    err = get_next_dentry(disk, dir, pos, &dentry);
  
    if (err != ENOERR)
       return err;

    dentry_to_node(&dentry, node);
    node->parent_cluster = dir->cluster;

    return ENOERR;
}

// -------------------------------------------------------------------------
// fatfs_write_node()
// Writes node attributes to its dir entry (to disk).
 
int
fatfs_write_file_attr(fatfs_disk_t *disk, fatfs_node_t *node)
{
    fat_dir_entry_t dentry;
    int err;

    CYG_CHECK_DATA_PTRC(disk);
    CYG_CHECK_DATA_PTRC(node);
 
    node_to_dentry(node, &dentry);
    err = write_dentry(disk, &dentry.pos, &dentry);
    return err;
}

// -------------------------------------------------------------------------
// fatfs_delete_file()
// Marks file dir entry as deleted.
 
int
fatfs_delete_file(fatfs_disk_t *disk, fatfs_node_t *node)
{
    fat_dir_entry_t dentry;
    int err;

    CYG_CHECK_DATA_PTRC(disk);
    CYG_CHECK_DATA_PTRC(node);

    // Can't delete root
    if (is_node_root_node(node))
        return EINVAL;
    
    CYG_TRACE1(TDE, "filename='%s'", node->filename);

    node_to_dentry(node, &dentry);

    // Check if we are about to delete a directory
    if (DENTRY_IS_DIR(&dentry))
    {
        fat_dir_entry_t cdentry;
        cyg_uint32 pos = 0;
        int i = 0;
        
        CYG_TRACE0(TDE, "got directory");
        // Count number of entries in this dir    
        while (true)
        {
            err = get_next_dentry(disk, node, &pos, &cdentry);

            if (EEOF == err)
                break;
            else if (err != ENOERR)
                return err;
            i++; pos++;
        }
        CYG_TRACE1(TDE, "child count=%d", i);
        
        // Check if the dir is empty (except '.' and '..')
        if (i > 2)
            return EPERM; 
    }    
    
    // Free file clusters
    free_cluster_chain(disk, dentry.cluster);
    dentry_set_deleted(disk, &dentry);
    err = write_dentry(disk, &dentry.pos, &dentry);
    return err;
} 

// -------------------------------------------------------------------------
// fatfs_create_file()
// Creates a new file.
 
int
fatfs_create_file(fatfs_disk_t *disk, 
                  fatfs_node_t *dir, 
                  const char   *name,
                  int           namelen,
                  fatfs_node_t *node)
{
    fat_dir_entry_t dentry;
    int err;

    CYG_CHECK_DATA_PTRC(disk);
    CYG_CHECK_DATA_PTRC(dir);
    CYG_CHECK_DATA_PTRC(name);
    CYG_CHECK_DATA_PTRC(node);
 
    CYG_TRACE2(TDE, "filename='%s' parent='%s'", name, dir->filename);

    dentry.pos.cluster      = dir->cluster;
    dentry.pos.cluster_snum = 0;
    dentry.pos.cluster_pos  = 0;

    // Get free dir entry in parent dir
    err = get_free_dentry(disk, &dentry.pos, &dir->tcache);
    if (err != ENOERR)
        return err;

    // Set new file attributes
    init_node_fattr(node, name, namelen, __stat_mode_REG, 
                    dir->cluster, &dentry.pos); 

    // Write new dir dentry  
    node_to_dentry(node, &dentry);
    err = write_dentry(disk, &dentry.pos, &dentry);
    if (err != ENOERR)
       return err;
 
    return ENOERR;     
}

// -------------------------------------------------------------------------
// fatfs_create_dir()
// Creates a new directory.
 
int
fatfs_create_dir(fatfs_disk_t *disk, 
                 fatfs_node_t *dir, 
                 const char   *name,
                 int           namelen,
                 fatfs_node_t *node)
{
    fat_dir_entry_t dentry;
    fatfs_no

⌨️ 快捷键说明

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