📄 fatfs_supp.c
字号:
GET_WORD(data, fde->crt_date, 0x10);
GET_WORD(data, fde->acc_date, 0x12);
GET_WORD(data, fde->cluster_HI, 0x14);
GET_WORD(data, fde->wrt_time, 0x16);
GET_WORD(data, fde->wrt_date, 0x18);
GET_WORD(data, fde->cluster, 0x1A);
GET_DWORD(data, fde->size, 0x1C);
// Zero terminate strings
fde->name[8] = '\0';
fde->ext[3] = '\0';
// Store position
fde->pos = *dpos;
#if TDE
print_dentry(fde);
#endif
return ENOERR;
}
// -------------------------------------------------------------------------
// write_dentry()
// Writes dir entry to disk.
// If cluster is 0 writes to root dir.
static int
write_dentry(fatfs_disk_t *disk,
fatfs_data_pos_t *dpos,
fat_dir_entry_t *fde)
{
unsigned char data[DENTRY_SIZE];
cyg_uint32 apos;
int len, err;
// Check if we are writting to the root directory
if (0 == dpos->cluster)
apos = disk->fat_root_dir_pos + dpos->cluster_pos;
else
apos = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos);
CYG_TRACE3(TDE, "cluster=%d pos=%d apos=%d",
dpos->cluster, dpos->cluster_pos, apos);
SET_BYTES(data, fde->name, 8, 0x00);
SET_BYTES(data, fde->ext, 3, 0x08);
SET_BYTE(data, fde->attr, 0x0B);
SET_BYTE(data, fde->nt_reserved, 0x0C);
SET_BYTE(data, fde->crt_sec_100, 0x0D);
SET_WORD(data, fde->crt_time, 0x0E);
SET_WORD(data, fde->crt_date, 0x10);
SET_WORD(data, fde->acc_date, 0x12);
SET_WORD(data, fde->cluster_HI, 0x14);
SET_WORD(data, fde->wrt_time, 0x16);
SET_WORD(data, fde->wrt_date, 0x18);
SET_WORD(data, fde->cluster, 0x1A);
SET_DWORD(data, fde->size, 0x1C);
len = DENTRY_SIZE;
err = cyg_blib_write(&disk->blib, (void*)data, &len, 0, apos);
if (err != ENOERR)
return err;
#if TDE
print_dentry(fde);
#endif
return ENOERR;
}
// -------------------------------------------------------------------------
// dentry_set_deleted()
// Sets the dentry filename first char to 0xE5 (ie deleted).
static __inline__ void
dentry_set_deleted(fatfs_disk_t *disk, fat_dir_entry_t *dentry)
{
dentry->name[0] = 0xE5;
}
// -------------------------------------------------------------------------
// get_dentry_filename()
// Gets the filename from given dir entry.
static void
get_dentry_filename(fat_dir_entry_t *fde, char *name)
{
int i = 0;
char *cptr = fde->name;
char *cname = name;
while (*cptr != ' ' && i < 8)
{
*cname++ = *cptr++; i++;
}
cptr = fde->ext;
if (*cptr != ' ')
{
*cname++ = '.'; i = 0;
while (*cptr != ' ' && i < 3)
{
*cname++ = *cptr++; i++;
}
}
*cname = '\0';
CYG_TRACE3(TDE, "dos_name='%s' dos_ext='%s' filename='%s'",
fde->name, fde->ext, name);
}
// -------------------------------------------------------------------------
// set_dentry_filename()
// Sets the filename to given dir entry.
static void
set_dentry_filename(fat_dir_entry_t *fde, const char *name, int namelen)
{
int i, nidx;
const char *cname;
char *cptr;
// Special case check
if (name[0] == '.')
{
if (name[1] == '\0')
{
strcpy(fde->name, ". ");
strcpy(fde->ext, " ");
return;
}
else if (name[1] == '.' && name[2] == '\0')
{
strcpy(fde->name, ".. ");
strcpy(fde->ext, " ");
return;
}
}
if (0 == namelen)
namelen = 9999;
nidx = 0;
cname = name;
cptr = fde->name;
for (i = 0; i < 8; i++)
{
if (*cname != '.' && *cname != '\0' && nidx++ < namelen)
*cptr++ = toupper(*cname++);
else
*cptr++ = ' ';
}
*cptr = '\0';
while (*cname != '.' && *cname != '\0' && nidx++ < namelen)
cname++;
if (*cname == '.' && nidx++ < namelen)
cname++;
cptr = fde->ext;
for (i = 0; i < 3; i++)
{
if (*cname != '.' && *cname != '\0' && nidx++ < namelen)
*cptr++ = toupper(*cname++);
else
*cptr++ = ' ';
}
*cptr = '\0';
CYG_TRACE4(TDE, "filename='%s' namelen=%d dos_name='%s' dos_ext='%s'",
name, namelen, fde->name, fde->ext);
}
// -------------------------------------------------------------------------
// get_next_dentry()
// Gets next dir entry searching from given position to the end.
// Position is expected in DENTRY_SIZE units.
// If EEOF is returned there are no more extries in given dir.
static int
get_next_dentry(fatfs_disk_t *disk,
fatfs_node_t *dir,
cyg_uint32 *pos,
fat_dir_entry_t *dentry)
{
fatfs_data_pos_t dpos;
cyg_uint32 off;
int err = ENOERR;
// Calculate dentry offset
off = *pos * DENTRY_SIZE;
CYG_TRACE4(TDE, "pos=%d off=%d dir=%p cluster=%d",
off, *pos, dir, dir->cluster);
// Root dir check
if (0 == dir->cluster)
{
dpos.cluster = 0;
dpos.cluster_snum = 0;
dpos.cluster_pos = off;
}
else
{
err = get_data_position_from_off(disk, dir->cluster,
off, &dpos, &dir->tcache, false);
if (err != ENOERR)
return err;
}
while (true)
{
// Root dir check
if (0 != dir->cluster)
{
// Change cluster if needed
if (!is_pos_inside_cluster(disk, dpos.cluster_pos))
err = get_next_cluster(disk, &dpos, &dir->tcache, CO_NONE);
}
else
{
if (*pos >= disk->fat_root_dir_nents)
err = EEOF;
}
if (err != ENOERR)
break;
err = read_dentry(disk, &dpos, dentry);
if (err != ENOERR)
return err;
if (DENTRY_IS_ZERO(dentry))
{
// If we get a ZERO dir entry, we assume that
// there are no more entries in current dir
CYG_TRACE0(TDE, "ZERO dentry");
err = EEOF;
break;
}
else if (!DENTRY_IS_DELETED(dentry))
{
// Dir entry found
CYG_TRACE3(TDE, "dentry_pos=%d cluster=%d pos=%d",
*pos, dpos.cluster, dpos.cluster_pos);
break;
}
// Increment offset and position
dpos.cluster_pos += DENTRY_SIZE;
(*pos)++;
}
if (EEOF == err) CYG_TRACE0(TDE, "end of dir");
// EEOF could be returned if there are no more entries in this
// dir - this should be cought by the calling function
return err;
}
// -------------------------------------------------------------------------
// get_free_dentry()
// Gets free dir entry slot searching from given position.
// If an deleated entry is found, its clusters are freed and the
// entry is reused.
// The directory is extended if needed.
static int
get_free_dentry(fatfs_disk_t *disk,
fatfs_data_pos_t *dpos,
fatfs_tcache_t *tcache)
{
fat_dir_entry_t dentry;
fatfs_data_pos_t cdpos;
int err = ENOERR;
CYG_TRACE3(TDE, "cluster=%d cluster_snum=%d cluster_pos=%d",
dpos->cluster, dpos->cluster_snum, dpos->cluster_pos);
cdpos = *dpos;
while (true)
{
// Root dir check
if (0 != cdpos.cluster)
{
// Change cluster if needed
if (!is_pos_inside_cluster(disk, cdpos.cluster_pos))
err = get_next_cluster(disk, &cdpos, tcache,
CO_EXTEND | CO_ERASE_NEW);
}
else
{
if (cdpos.cluster_pos >= disk->fat_root_dir_size)
err = ENOSPC;
}
if (err != ENOERR)
return err;
err = read_dentry(disk, &cdpos, &dentry);
if (err != ENOERR)
return err;
if (DENTRY_IS_DELETED(&dentry))
{
CYG_TRACE3(TDE, "deleted dentry at cluster=%d cluster_snum=%d "
"cluster_pos=%d", cdpos.cluster, cdpos.cluster_snum,
cdpos.cluster_pos);
// Retrun found dentry position
*dpos = cdpos;
return ENOERR;
}
else if (DENTRY_IS_ZERO(&dentry))
{
CYG_TRACE3(TDE, "zero dentry at cluster=%d cluster_snum=%d "
"cluster_pos=%d", cdpos.cluster, cdpos.cluster_snum,
cdpos.cluster_pos);
// Retrun found dentry position
*dpos = cdpos;
return ENOERR;
}
// Increment current position
cdpos.cluster_pos += DENTRY_SIZE;
}
}
// -------------------------------------------------------------------------
// dentry_to_node()
// Converts FAT dir entry to node.
static void
dentry_to_node(fat_dir_entry_t *dentry,
fatfs_node_t *node)
{
get_dentry_filename(dentry, node->filename);
if (DENTRY_IS_DIR(dentry))
node->mode = __stat_mode_DIR;
else
node->mode = __stat_mode_REG;
date_dos2unix(dentry->crt_time, dentry->crt_date, &node->ctime);
date_dos2unix(0, dentry->acc_date, &node->atime);
date_dos2unix(dentry->wrt_time, dentry->wrt_date, &node->mtime);
node->size = dentry->size;
node->priv_data = dentry->nt_reserved;
node->cluster = dentry->cluster;
node->dentry_pos = dentry->pos;
}
// -------------------------------------------------------------------------
// node_to_dentry()
// Converts node to FAT dir entry.
static void
node_to_dentry(fatfs_node_t *node, fat_dir_entry_t *dentry)
{
set_dentry_filename(dentry, node->filename, 0);
if (node->mode == __stat_mode_DIR)
dentry->attr = DENTRY_ATTR_DIR;
else
dentry->attr = DENTRY_ATTR_ARCHIVE;
date_unix2dos(node->ctime, &dentry->crt_time, &dentry->crt_date);
date_unix2dos(node->atime, NULL, &dentry->acc_date);
date_unix2dos(node->mtime, &dentry->wrt_time, &dentry->wrt_date);
dentry->crt_sec_100 = 0; //FIXME
dentry->size = node->size;
dentry->nt_reserved = node->priv_data;
dentry->cluster = node->cluster;
dentry->cluster_HI = 0;
dentry->pos = node->dentry_pos;
}
//==========================================================================
// FAT data functions
// -------------------------------------------------------------------------
// read_data()
// Reads data from given position.
static int
read_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
err = get_next_cluster(disk, dpos, tcache, CO_NONE);
if (err != ENOERR)
goto out;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -