📄 fatfs_supp.c
字号:
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 + -