📄 fatfs_supp.c
字号:
}
// -------------------------------------------------------------------------
// free_cluster_chain()
// Marks all clusters FREE from given cluster to the last cluster in chain.
static int
free_cluster_chain(fatfs_disk_t *disk, cyg_uint32 start_cluster)
{
cyg_uint32 c, next_c, tentry;
bool last;
int err;
CYG_TRACE1(TCL, "start cluster=%d", start_cluster);
c = next_c = start_cluster;
last = false;
while (!last)
{
err = read_tentry(disk, c, &tentry);
if (err != ENOERR)
return err;
switch (get_tentry_type(disk, tentry))
{
case TENTRY_LAST:
// Last cluster in chain
last = true;
break;
case TENTRY_REGULAR:
// Get next cluster in chain
next_c = get_tentry_next_cluster(disk, tentry);
break;
default:
CYG_TRACE2(TCL, "!!! inconsistant FAT tentry=%x c=%d",
tentry, c);
return EIO;
}
// Set the current tentry to FREE
set_tentry_type(disk, &tentry, TENTRY_FREE);
err = write_tentry(disk, c, &tentry);
if (err != ENOERR)
return err;
// Next cluster in chain
c = next_c;
}
CYG_TRACE1(TCL, "last cluster=%d", c);
return ENOERR;
}
//==========================================================================
// FAT dir entry functions
// -------------------------------------------------------------------------
// print_raw_dentry()
// Prints FAT directory entry.
#if TDE
static void
print_raw_dentry(fat_raw_dir_entry_t* dentry)
{
if (DENTRY_IS_DELETED(dentry))
diag_printf("FAT: FDE name: '?%.7s'\n", &dentry->name[1]);
else
diag_printf("FAT: FDE name: '%.8s'\n", dentry->name);
diag_printf("FAT: FDE ext: '%.3s'\n", dentry->ext);
diag_printf("FAT: FDE attr: %c%c%c%c%c%c\n",
(DENTRY_IS_RDONLY(dentry) ? 'R' : '-'),
(DENTRY_IS_HIDDEN(dentry) ? 'H' : '-'),
(DENTRY_IS_SYSTEM(dentry) ? 'S' : '-'),
(DENTRY_IS_VOLUME(dentry) ? 'V' : '-'),
(DENTRY_IS_DIR(dentry) ? 'D' : '-'),
(DENTRY_IS_ARCHIVE(dentry) ? 'A' : '-'));
diag_printf("FAT: FDE crt time: %u\n", dentry->crt_time);
diag_printf("FAT: FDE crt date: %u\n", dentry->crt_date);
diag_printf("FAT: FDE acc date: %u\n", dentry->acc_date);
diag_printf("FAT: FDE wrt time: %u\n", dentry->wrt_time);
diag_printf("FAT: FDE wrt date: %u\n", dentry->wrt_date);
diag_printf("FAT: FDE cluster: %u\n", (dentry->cluster_HI << 16) | dentry->cluster);
diag_printf("FAT: FDE size: %u\n", dentry->size);
}
#endif // TDE
// -------------------------------------------------------------------------
// read_raw_dentry()
// Reads dir entry from disk.
static int
read_raw_dentry(fatfs_disk_t *disk,
fatfs_data_pos_t *pos,
fat_raw_short_dir_entry_t *dentry)
{
cyg_uint8 data[DENTRY_SIZE];
cyg_uint32 len;
int err;
CYG_TRACE3(TDE, "cluster=%d snum=%d pos=%d",
pos->cluster, pos->cluster_snum, pos->cluster_pos);
len = DENTRY_SIZE;
// Check if we are reading the FAT12/16 root directory
if (0 == pos->cluster)
err = disk_read(disk, (void*)data, &len,
disk->fat_root_dir_pos + pos->cluster_pos);
else
err = disk_cluster_read(disk, (void*)data, &len,
pos->cluster, pos->cluster_pos);
if (err != ENOERR)
return err;
GET_BYTES(data, dentry->name, 8, 0x00);
GET_BYTES(data, dentry->ext, 3, 0x08);
GET_BYTE(data, dentry->attr, 0x0B);
GET_BYTE(data, dentry->nt_reserved, 0x0C);
GET_BYTE(data, dentry->crt_sec_100, 0x0D);
GET_WORD(data, dentry->crt_time, 0x0E);
GET_WORD(data, dentry->crt_date, 0x10);
GET_WORD(data, dentry->acc_date, 0x12);
GET_WORD(data, dentry->cluster_HI, 0x14);
GET_WORD(data, dentry->wrt_time, 0x16);
GET_WORD(data, dentry->wrt_date, 0x18);
GET_WORD(data, dentry->cluster, 0x1A);
GET_DWORD(data, dentry->size, 0x1C);
// Zero terminate strings
dentry->name[8] = '\0';
dentry->ext[3] = '\0';
#if TDE
print_raw_dentry(dentry);
#endif
return ENOERR;
}
// -------------------------------------------------------------------------
// write_raw_dentry()
// Writes raw dir entry to disk.
static int
write_raw_dentry(fatfs_disk_t *disk,
fatfs_data_pos_t *pos,
fat_raw_short_dir_entry_t *dentry)
{
cyg_uint8 data[DENTRY_SIZE];
cyg_uint32 len;
int err;
CYG_TRACE3(TDE, "cluster=%d snum=%d pos=%d",
pos->cluster, pos->cluster_snum, pos->cluster_pos);
SET_BYTES(data, dentry->name, 8, 0x00);
SET_BYTES(data, dentry->ext, 3, 0x08);
SET_BYTE(data, dentry->attr, 0x0B);
SET_BYTE(data, dentry->nt_reserved, 0x0C);
SET_BYTE(data, dentry->crt_sec_100, 0x0D);
SET_WORD(data, dentry->crt_time, 0x0E);
SET_WORD(data, dentry->crt_date, 0x10);
SET_WORD(data, dentry->acc_date, 0x12);
SET_WORD(data, dentry->cluster_HI, 0x14);
SET_WORD(data, dentry->wrt_time, 0x16);
SET_WORD(data, dentry->wrt_date, 0x18);
SET_WORD(data, dentry->cluster, 0x1A);
SET_DWORD(data, dentry->size, 0x1C);
len = DENTRY_SIZE;
// Check if we are writting to the FAT12/16 root directory
if (0 == pos->cluster)
err = disk_write(disk, (void*)data, &len,
disk->fat_root_dir_pos + pos->cluster_pos);
else
err = disk_cluster_write(disk, (void*)data, &len,
pos->cluster, pos->cluster_pos);
if (err != ENOERR)
return err;
#if TDE
print_raw_dentry(dentry);
#endif
return ENOERR;
}
static int
write_raw_dentry_long_name(fatfs_disk_t *disk,
fatfs_data_pos_t *pos,
fat_raw_long_dir_entry_t *ldentry)
{
cyg_uint8 data[DENTRY_SIZE];
cyg_uint32 len;
int err;
CYG_TRACE3(TDE, "cluster=%d snum=%d pos=%d",
pos->cluster, pos->cluster_snum, pos->cluster_pos);
SET_BYTE(data, ldentry->LDIR_Ord,0x00);
SET_BYTES(data, ldentry->LDIR_Name1, 10, 0x01);
SET_BYTE(data, ldentry->attr, 11);
SET_BYTE(data, ldentry->LDIR_Type, 12);
SET_BYTE(data, ldentry->LDIR_Chksum, 13);
SET_BYTES(data, ldentry->LDIR_Name2,12,14);
SET_WORD(data, ldentry->LDIR_FstClusLO, 26);
SET_BYTES(data, ldentry->LDIR_Name3,4,28);
len = DENTRY_SIZE;
// Check if we are writting to the FAT12/16 root directory
if (0 == pos->cluster)
err = disk_write(disk, (void*)data, &len,
disk->fat_root_dir_pos + pos->cluster_pos);
else
err = disk_cluster_write(disk, (void*)data, &len,
pos->cluster, pos->cluster_pos);
if (err != ENOERR)
return err;
#if TDE
print_raw_dentry(ldentry);
#endif
return ENOERR;
}
// -------------------------------------------------------------------------
// raw_dentry_set_deleted()
// Sets the dentry filename first char to 0xE5 (ie deleted).
static __inline__ void
raw_dentry_set_deleted(fatfs_disk_t *disk, fat_raw_short_dir_entry_t *dentry)
{
dentry->name[0] = 0xE5;
}
// -------------------------------------------------------------------------
// get_raw_dentry_filename()
// Gets the filename from given dir entry.
static void
get_raw_dentry_filename(fat_raw_short_dir_entry_t *dentry, char *name)
{
int i = 0;
char *cptr = dentry->name;
char *cname = name;
while (*cptr != ' ' && i < 8)
{
*cname++ = *cptr++; i++;
}
cptr = dentry->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'",
dentry->name, dentry->ext, name);
}
// -------------------------------------------------------------------------
// set_raw_dentry_filename()
// Sets the filename of given dir entry.
static void
set_raw_dentry_filename(fat_raw_short_dir_entry_t *dentry,
const char *name,
int namelen)
{
int i, nidx;
const char *cname;
char *cptr;
// Special case check
if ('.' == name[0])
{
if ('\0' == name[1])
{
strcpy(dentry->name, ". ");
strcpy(dentry->ext, " ");
return;
}
else if ('.' == name[1] && '\0' == name[2])
{
strcpy(dentry->name, ".. ");
strcpy(dentry->ext, " ");
return;
}
}
if (0 == namelen)
namelen = 9999;
nidx = 0;
cname = name;
cptr = dentry->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 = dentry->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, dentry->name, dentry->ext);
}
// -------------------------------------------------------------------------
// read_next_raw_dentry()
// Gets next dir entry searching from given position to the end.
// If EEOF is returned there are no more entries in given dir.
static int
read_next_raw_dentry(fatfs_disk_t *disk,
fatfs_data_pos_t *pos,
fat_raw_short_dir_entry_t *dentry,int flow)
{
int err = ENOERR;
// If we are reading the root dir on FAT32 we have
// to correct the position to the root dir cluster
if (FATFS_FAT32 == disk->fat_type && 0 == pos->cluster)
pos->cluster = disk->fat_root_dir_cluster;
while (true)
{
// FAT12/16 root dir check
if (0 == pos->cluster)
{
if (pos->cluster_pos >= disk->fat_root_dir_size)
err = EEOF;
}
else
{
// Change cluster if needed
if (pos->cluster_pos >= disk->cluster_size)
err = get_next_cluster(disk, pos, CO_NONE);
}
if (err != ENOERR)
break;
err = read_raw_dentry(disk, pos, 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, "end of dir");
err = EEOF;
break;
}
else if (!DENTRY_IS_DELETED(dentry))
{
// Dir entry found
CYG_TRACE3(TDE, "found new dentry at cluster=%d snum=%d pos=%d",
pos->cluster, pos->cluster_snum, pos->cluster_pos);
break;
}
if(flow!=0)
{
return EEOF;
}
pos->cluster_pos += DENTRY_SIZE;
}
// 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_raw_dentry()
// Gets free dir entry slot searching from given position extending the
// directory if needed. If an deleated entry is found it is reused.
static int
get_free_raw_dentry(fatfs_disk_t *disk,
fatfs_data_pos_t *pos,int len)
{
fat_raw_short_dir_entry_t raw_dentry;
fatfs_data_pos_t cpos,cpos1;
int err = ENOERR;
int namelen=len;
cpos = *pos;
// If we are reading the root dir on FAT32 we have
// to correct the position to the root dir cluster
if (FATFS_FAT32 == disk->fat_type && 0 == cpos.cluster)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -