📄 fatfs_supp.c
字号:
cpos.cluster = disk->fat_root_dir_cluster;
CYG_TRACE3(TDE, "cluster=%d snum=%d pos=%d",
pos->cluster, pos->cluster_snum, pos->cluster_pos);
cpos1=cpos;
while (true)
{
// FAT12/16 root dir check
if (0 == cpos.cluster)
{
if (cpos.cluster_pos >= disk->fat_root_dir_size)
err = ENOSPC;
}
else
{
// Change cluster if needed
if (cpos.cluster_pos >= disk->cluster_size)
err = get_next_cluster(disk, &cpos, CO_EXTEND | CO_ERASE_NEW);
}
if (err != ENOERR)
return err;
err = read_raw_dentry(disk, &cpos, &raw_dentry);
if (err != ENOERR)
return err;
if (DENTRY_IS_DELETED(&raw_dentry))
{
CYG_TRACE3(TDE, "deleted dentry at cluster=%d snum=%d pos=%d",
cpos.cluster, cpos.cluster_snum, cpos.cluster_pos);
cpos.cluster_pos+=DENTRY_SIZE;
len-=13;
if(len<=0)
{
*pos=cpos1;
break;
}
continue;
}
else if (DENTRY_IS_ZERO(&raw_dentry))
{
CYG_TRACE3(TDE, "zero dentry at cluster=%d snum=%d pos=%d",
cpos.cluster, cpos.cluster_snum, cpos.cluster_pos);
cpos.cluster_pos+=DENTRY_SIZE;
len-=13;
if(len<=0)
{
*pos=cpos1;
break;
}
continue;
}
else
{
len=namelen;
cpos1.cluster_pos+=DENTRY_SIZE;
cpos=cpos1;
continue;
}
}
return ENOERR;
}
// -------------------------------------------------------------------------
// raw_to_dentry()
// Converts raw FAT dir entry to dir entry.
static void
raw_to_dentry(fat_raw_short_dir_entry_t *raw_dentry,
fatfs_data_pos_t *raw_dentry_pos,
fatfs_dir_entry_t *dentry)
{
get_raw_dentry_filename(raw_dentry, dentry->filename);
if (DENTRY_IS_DIR(raw_dentry))
dentry->mode = __stat_mode_DIR;
else
dentry->mode = __stat_mode_REG;
#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
dentry->attrib = raw_dentry->attr;
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES
date_dos2unix(raw_dentry->crt_time, raw_dentry->crt_date, &dentry->ctime);
date_dos2unix(0, raw_dentry->acc_date, &dentry->atime);
date_dos2unix(raw_dentry->wrt_time, raw_dentry->wrt_date, &dentry->mtime);
dentry->size = raw_dentry->size;
dentry->priv_data = raw_dentry->nt_reserved;
dentry->cluster = raw_dentry->cluster | (raw_dentry->cluster_HI << 16);
dentry->disk_pos = *raw_dentry_pos;
}
// -------------------------------------------------------------------------
// dentry_to_raw()
// Converts dir entry to raw FAT dir entry.
static void
dentry_to_raw(fatfs_dir_entry_t *dentry, fat_raw_short_dir_entry_t *raw_dentry)
{
set_raw_dentry_filename(raw_dentry, dentry->filename, 0);
if (__stat_mode_DIR == dentry->mode)
raw_dentry->attr = S_FATFS_DIR;
else
raw_dentry->attr = S_FATFS_ARCHIVE;
#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
raw_dentry->attr = dentry->attrib;
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES
date_unix2dos(dentry->ctime, &raw_dentry->crt_time, &raw_dentry->crt_date);
date_unix2dos(dentry->atime, NULL, &raw_dentry->acc_date);
date_unix2dos(dentry->mtime, &raw_dentry->wrt_time, &raw_dentry->wrt_date);
raw_dentry->crt_sec_100 = 0; //FIXME
raw_dentry->size = dentry->size;
raw_dentry->nt_reserved = dentry->priv_data;
raw_dentry->cluster = dentry->cluster & 0xFFFF;
raw_dentry->cluster_HI = dentry->cluster >> 16;
}
static int dentry_to_longraw(fatfs_dir_entry_t *dentry,
fat_raw_long_dir_entry_t *raw_dentry,
int namepos,cyg_uint8 ldir_ord)
{
int i;
int clen;
cyg_uint16 tmp=0;
int num_transfer=namepos;
for(i=0;i<5;i++)
{
if(namepos>=512||dentry->longfilename[namepos]==0)
{
tmp=0;
}
else
{
clen=fatfs_utf8_table->char2uni(dentry->longfilename+namepos,512,&tmp);
if(clen>0)
namepos+=clen;
else
return clen;
}
raw_dentry->LDIR_Name1[i]=tmp;
}
raw_dentry->attr=S_FATFS_LONG_NAME;
raw_dentry->LDIR_Type=0;
raw_dentry->LDIR_Chksum=fatfs_chksum(dentry->filename);
for(i=0;i<6;i++)
{
if(namepos>=512||dentry->longfilename[namepos]==0)
{
tmp=0;
}
else
{
clen=fatfs_utf8_table->char2uni(dentry->longfilename+namepos,512,&tmp);
if(clen>0)
namepos+=clen;
else
return clen;
}
raw_dentry->LDIR_Name2[i]=tmp;
}
raw_dentry->LDIR_FstClusLO=0;
for(i=0;i<2;i++)
{
if(namepos>=512||dentry->longfilename[namepos]==0)
{
tmp=0;
}
else
{
clen=fatfs_utf8_table->char2uni(dentry->longfilename+namepos,512,&tmp);
if(clen>0)
namepos+=clen;
else
return clen;
}
raw_dentry->LDIR_Name3[i]=tmp;
}
if(namepos>=512||
dentry->longfilename[namepos]==0||
dentry->longfilename[namepos+1]==0)
{
raw_dentry->LDIR_Ord=ldir_ord|0x40;
}
else
{
raw_dentry->LDIR_Ord=ldir_ord;
}
return namepos-num_transfer;
}
//==========================================================================
// 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 *pos)
{
cyg_uint8 *buf = (cyg_uint8 *) data;
cyg_uint32 size = *len;
int err = ENOERR;
CYG_TRACE4(TDO, "len=%d cluster=%d snum=%d pos=%d",
*len, pos->cluster, pos->cluster_snum,
pos->cluster_pos);
while (size > 0)
{
cyg_uint32 csize;
// Check if we are still inside current cluster
if (pos->cluster_pos >= disk->cluster_size)
{
// Get next cluster of file
err = get_next_cluster(disk, pos, CO_NONE);
if (err != ENOERR)
goto out;
}
// Adjust the data chunk size to be read to the cluster boundary
if (size > (disk->cluster_size - pos->cluster_pos))
csize = disk->cluster_size - pos->cluster_pos;
else
csize = size;
CYG_TRACE4(TDO, "-- len=%d cluster=%d snum=%d pos=%d",
csize, pos->cluster, pos->cluster_snum,
pos->cluster_pos);
err = disk_cluster_read(disk, (void*)buf, &csize,
pos->cluster, pos->cluster_pos);
if (err != ENOERR)
goto out;
// Adjust running variables
buf += csize;
pos->cluster_pos += 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 *pos)
{
cyg_uint8 *buf = (cyg_uint8 *) data;
cyg_uint32 size = *len;
int err = ENOERR;
CYG_TRACE4(TDO, "len=%d cluster=%d snum=%d pos=%d",
*len, pos->cluster, pos->cluster_snum,
pos->cluster_pos);
while (size > 0)
{
cyg_uint32 csize;
// Check if we are still inside current cluster
if (pos->cluster_pos >= disk->cluster_size)
{
// Get next cluster of file, if at the last
// cluster try to extend the cluster chain
err = get_next_cluster(disk, pos, CO_EXTEND);
if (err != ENOERR)
goto out;
}
// Adjust the data chunk size to be read to the cluster boundary
if (size > (disk->cluster_size - pos->cluster_pos))
csize = disk->cluster_size - pos->cluster_pos;
else
csize = size;
CYG_TRACE4(TDO, "-- len=%d cluster=%d snum=%d pos=%d",
csize, pos->cluster, pos->cluster_snum,
pos->cluster_pos);
err = disk_cluster_write(disk, (void*)buf, &csize,
pos->cluster, pos->cluster_pos);
if (err != ENOERR)
goto out;
// Adjust running variables
buf += csize;
pos->cluster_pos += csize;
size -= csize;
}
out:
*len -= size;
CYG_TRACE1(TDO, "total len=%d", *len);
return err;
}
//==========================================================================
// Misc functions
// -------------------------------------------------------------------------
// init_dir_entry()
// Initializes attributes of a new dir entry.
static void
init_dir_entry(fatfs_dir_entry_t *dentry,
const char *shortname,
int shortnamelen,
const char *longname,
int longnamelen,
mode_t mode,
cyg_uint32 parent_cluster,
cyg_uint32 first_cluster,
fatfs_data_pos_t *pos)
{
int i;
if (0 == shortnamelen)
shortnamelen = 12;
// if(0==longnamelen)
// longnamelen=512;
memset(dentry,0,sizeof(fatfs_dir_entry_t));
strncpy(dentry->filename, shortname, shortnamelen);
dentry->filename[shortnamelen] = '\0';
for(i=0;i<longnamelen;i++)
{
dentry->longfilename[i]=longname[i];
}
dentry->longfilename[longnamelen]=0;
dentry->mode = mode;
#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
if (S_ISDIR(dentry->mode))
dentry->attrib = S_FATFS_DIR;
else
dentry->attrib = S_FATFS_ARCHIVE;
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES
dentry->ctime =
dentry->atime =
dentry->mtime = cyg_timestamp();
dentry->priv_data = 0;
dentry->size = 0;
dentry->cluster = first_cluster;
dentry->parent_cluster = parent_cluster;
dentry->disk_pos = *pos;
}
// -------------------------------------------------------------------------
// is_root_dir_entry()
// Check if the given dir entry is the root dir entry.
static __inline__ bool
is_root_dir_entry(fatfs_dir_entry_t *dentry)
{
return ('\0' == dentry->filename[0] && 0 == dentry->cluster);
}
//==========================================================================
//==========================================================================
// Exported functions
// -------------------------------------------------------------------------
// fatfs_init()
// Gets disk info.
int
fatfs_init(fatfs_disk_t *disk)
{
cyg_uint32 sec_num, sec_per_fat, root_dir_sec_num;
cyg_uint32 data_sec_num, data_clu_num;
fat_boot_record_t boot_rec;
int err;
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;
// Sector and cluster sizes
disk->sector_size = boot_rec.bytes_per_sec;
disk->sector_si
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -