📄 fs_fat.c
字号:
/* Write also cached Data and FAT table. */
write_cache (0);
cache_fat (0);
return (__TRUE);
}
/*--------------------------- fat_set_fpos ----------------------------------*/
BOOL fat_set_fpos (IOB *fcb, U32 pos) {
/* Set File Position pointer. */
U32 i;
if (pos > fcb->fsize) {
pos = fcb->fsize;
}
fcb->_currDatSect = (pos / 512) % mmc.SecPerClus;
fcb->_currDatClus = fcb->_firstClus;
for (i = pos / mmc.ClusSize; i; i--) {
/* Scan the cluster chain. */
set_next_clus (&fcb->_currDatClus);
}
fcb->fpos = pos;
return (__TRUE);
}
/*--------------------------- fat_rename ------------------------------------*/
BOOL fat_rename (const char *old, const char *new, IOB *fcb) {
/* Rename a file or directory to new name. */
U8 type;
if (mmc.FatType == FS_RAW) {
/* RAW File System or FAT not initialized. */
return (__FALSE);
}
/* Remove starting '\' if it exists. */
if (*old == '\\') old++;
/* Remove starting '\' if it exists. */
if (*new == '\\') new++;
/* Exit function if "old" on "new" is not given. */
if (*old == 0 || *new == 0) {
return(__FALSE);
}
/* Search for directory. */
fcb->_firstClus = 0;
if (fat_find_dir (old, fcb, 0) == __FALSE) {
/* Directory does not exist. */
return (__FALSE);
}
type = ENT_DIR;
if (name_buf[0]) {
if (check_name (new, fcb, ENT_FILE) == __TRUE) {
/* New file already exist. */
return (__FALSE);
}
type = ENT_FILE;
/* Search for file if file name exists. */
if (find_name (name_buf, fcb, ENT_FILE) == __FALSE) {
/* File does not exist. */
return (__FALSE);
}
}
else {
if (check_name (new, fcb, ENT_DIR) == __TRUE) {
/* New directory already exist. */
return (__FALSE);
}
}
if (rename_entries (new, fcb, type) == __FALSE) {
/* If rename was unsuccessfully. */
return (__FALSE);
}
/* File or directory renamed. */
return (__TRUE);
}
/*--------------------------- write_label -----------------------------------*/
static BOOL write_label (const char *label) {
/* Write a drive label to Root Directory. */
FILEREC *frec;
U32 i;
U8 ch;
read_sector (mmc.BootRecSec + mmc.RootDirAddr);
frec = (FILEREC *)&ca.buf[0];
memset (frec, 0, 32);
for (i = 0; i < 11; i++) {
ch = val_char_lab (label[i]);
if (ch == 0) break;
frec->FileName[i] = ch;
}
for ( ; i < 11; i++) {
frec->FileName[i] = ' ';
}
frec->Attr = ATTR_VOLUME_ID;
set_u16 ((U8 *)&frec->WriteDate, get_date ());
set_u16 ((U8 *)&frec->WriteTime, get_time ());
write_sector (mmc.BootRecSec + mmc.RootDirAddr);
return (__TRUE);
}
/*--------------------------- set_next_clus ---------------------------------*/
static BOOL set_next_clus (U32 *ptr_clus) {
/* Read next Cluster address from FAT table. */
U32 sect,ofs,next;
U32 clus = *ptr_clus;
/* Read a part of FAT table to buffer. */
sect = get_fat_sect (clus);
cache_fat (sect);
next = 0;
switch (mmc.FatType) {
case FS_FAT12:
ofs = ((clus * 3) / 2) & 0x1FF;
if (ofs < 511) {
next = get_u16 (&fat.buf[ofs]);
}
else {
/* This cluster spans on two sectors in the FAT. */
next = fat.buf[511];
cache_fat (sect+1);
next |= fat.buf[0] << 8;
}
if (clus & 0x001) {
next >>= 4;
}
else {
next &= 0xFFF;
}
break;
case FS_FAT16:
ofs = (clus & 0xFF) << 1;
next = *(U16 *)&fat.buf[ofs];
break;
case FS_FAT32:
ofs = (clus & 0x7F) << 2;
next = *(U32 *)&fat.buf[ofs];
break;
default:
return (__FALSE);
}
*ptr_clus = next;
return (__TRUE);
}
/*--------------------------- get_free_clus ---------------------------------*/
static BOOL get_free_clus (U32 *ptr_clus) {
/* Scan FAT Table and find first free cluster. */
U32 sect,ofs,next;
U32 clus = *ptr_clus;
for (clus = top_clus; clus < (mmc.DataClusCnt + 2); clus++) {
/* Read a part of FAT table to buffer. */
sect = get_fat_sect (clus);
cache_fat (sect);
switch (mmc.FatType) {
case FS_FAT12:
ofs = ((clus * 3) / 2) & 0x1FF;
if (ofs < 511) {
next = get_u16 (&fat.buf[ofs]);
}
else {
/* This cluster spans on two sectors in the FAT. */
next = fat.buf[511];
cache_fat (sect+1);
next |= fat.buf[0] << 8;
}
if (clus & 0x001) {
next >>= 4;
}
else {
next &= 0xFFF;
}
break;
case FS_FAT16:
ofs = (clus & 0xFF) << 1;
next = get_u16 (&fat.buf[ofs]);
break;
case FS_FAT32:
ofs = (clus & 0x7F) << 2;
next = get_u32 (&fat.buf[ofs]);
break;
default:
return (__FALSE);
}
if (next == 0) {
if (clus_in_use (clus) == __FALSE) {
*ptr_clus = clus;
top_clus = clus + 1;
return (__TRUE);
}
}
}
/* Disk Full, no free clusters found. */
top_clus = clus;
return (__FALSE);
}
/*--------------------------- clus_in_use -----------------------------------*/
static BOOL clus_in_use (U32 clus) {
/* Check if cluster in use by another file. */
IOB *fcb;
U32 i,nfile = _NFILE;
for (i = 0, fcb = &_iob[0]; i < nfile; fcb++, i++) {
if (!(fcb->flags & _IOWRT)) {
/* File not opened for writing. */
continue;
}
if (fcb->_currDatClus == clus) {
/* This cluster used by another file. */
return (__TRUE);
}
}
return (__FALSE);
}
/*--------------------------- clear_clus ------------------------------------*/
static BOOL clear_clus (U32 clus) {
/* Clear current cluster. */
U32 i;
U32 sect = clus_to_sect(clus);
/* Use cache for faster write. */
memset(ca.buf, 0, 512);
for (i = 0; i < mmc.SecPerClus; i++) {
write_cache(sect + i);
}
/* Flush the cache buffer when done. */
write_cache (0);
return (__TRUE);
}
/*--------------------------- write_fat_link --------------------------------*/
static BOOL write_fat_link (U32 clus, U32 next_clus) {
/* Write FAT table, update link cluster at cluster address. */
U32 sect,ofs,temp;
sect = get_fat_sect (clus);
cache_fat (sect);
switch (mmc.FatType) {
case FS_FAT12:
next_clus &= 0x0FFF;
ofs = ((clus * 3) / 2) & 0x1FF;
if (ofs < 511) {
temp = get_u16 (&fat.buf[ofs]);
if (clus & 0x001) {
temp = (temp & 0x000F) | (next_clus << 4);
}
else {
temp = (temp & 0xF000) | next_clus;
}
set_u16 (&fat.buf[ofs], temp);
}
else {
/* This cluster spans on two sectors in the FAT. */
if (clus & 0x001) {
fat.buf[511] = (fat.buf[511] & 0x0F) | (next_clus << 4);
}
else {
fat.buf[511] = (U8)next_clus;
}
fat.dirty = __TRUE;
cache_fat (++sect);
if (clus & 0x001) {
fat.buf[0] = next_clus >> 4;
}
else {
fat.buf[0] = (fat.buf[0] & 0xF0) | (next_clus >> 8);
}
}
break;
case FS_FAT16:
ofs = (clus & 0xFF) << 1;
set_u16 (&fat.buf[ofs], next_clus);
break;
case FS_FAT32:
ofs = (clus & 0x7F) << 2;
set_u32 (&fat.buf[ofs], next_clus);
break;
default:
return (__FALSE);
}
if (free_clus) free_clus--;
fat.dirty = __TRUE;
return (__TRUE);
}
/*--------------------------- unlink_clus_chain -----------------------------*/
static BOOL unlink_clus_chain (U32 clus) {
/* Remove a cluster chain starting with 'clus'. Reset the values to 0.*/
U32 sect,ofs,next,temp;
if (clus < 2) {
/* An empty file, do nothing here. */
return (__TRUE);
}
while (clus < (mmc.DataClusCnt + 2)) {
/* Reset top used cluster index. */
if (clus < top_clus) {
top_clus = clus;
}
sect = get_fat_sect (clus);
cache_fat (sect);
switch (mmc.FatType) {
case FS_FAT12:
ofs = ((clus * 3) / 2) & 0x1FF;
if (ofs < 511) {
next = get_u16 (&fat.buf[ofs]);
if (clus & 0x001) {
temp = next & 0x000F;
next >>= 4;
}
else {
temp = next & 0xF000;
next &= 0xFFF;
}
set_u16 (&fat.buf[ofs], temp);
}
else {
/* This cluster spans on two sectors in the FAT. */
next = fat.buf[511];
if (clus & 0x001) {
fat.buf[511] &= 0x0F;
}
else {
fat.buf[511] = 0;
}
fat.dirty = __TRUE;
cache_fat (++sect);
next |= fat.buf[0] << 8;
if (clus & 0x001) {
fat.buf[0] = 0;
next >>= 4;
}
else {
fat.buf[0] &= 0xF0;
next &= 0xFFF;
}
}
goto chk_eoc;
case FS_FAT16:
ofs = (clus & 0xFF) << 1;
next = get_u16 (&fat.buf[ofs]);
*(U16 *)&fat.buf[ofs] = 0;
goto chk_eoc;
case FS_FAT32:
ofs = (clus & 0x7F) << 2;
next = get_u32 (&fat.buf[ofs]);
*(U32 *)&fat.buf[ofs] = 0;
chk_eoc: fat.dirty = __TRUE;
if (is_EOC (next) == __TRUE) {
cache_fat (0);
return (__TRUE);
}
break;
default:
return (__FALSE);
}
clus = next;
free_clus++;
}
cache_fat (0);
/* Failed, something wrong with FAT table. */
return (__FALSE);
}
/*--------------------------- alloc_new_clus --------------------------------*/
static BOOL alloc_new_clus (U32 *ptr_clus, U8 wr_fat_link) {
/* Allocate a new cluster. */
U32 clus = *ptr_clus;
if (get_free_clus (ptr_clus) == __FALSE) {
/* Failed to allocate a free cluster. */
return (__FALSE);
}
write_fat_link (*ptr_clus, get_EOC());
if (wr_fat_link) {
/* Update also a FAT cluster chain. */
write_fat_link (clus, *ptr_clus);
}
cache_fat (0);
/* New cluster allocated successfully. */
return (__TRUE);
}
/*--------------------------- count_free_clus -------------------------------*/
static U32 count_free_clus (void) {
/* Scan FAT table and Count number of free clusters. */
U32 clus,sect,ofs,next,nfree;
nfree = 0;
if (mmc.FatType == FS_FAT12) {
for (clus = 2; clus < (mmc.DataClusCnt + 2); clus++) {
/* Read a part of FAT table to buffer. */
sect = get_fat_sect (clus);
cache_fat (sect);
ofs = ((clus * 3) / 2) & 0x1FF;
if (ofs < 511) {
next = get_u16 (&fat.buf[ofs]);
}
else {
/* This cluster spans on two sectors in the FAT. */
next = fat.buf[511];
cache_fat (sect+1);
next |= fat.buf[0] << 8;
}
if (clus & 0x001) {
next >>= 4;
}
else {
next &= 0xFFF;
}
if (next == 0) {
nfree++;
}
}
return (nfree);
}
if (mmc.FatType == FS_FAT16) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -