提交 eb9b7c3f 编写于 作者: F Far

fix: statfs can't get f_bfree and f_bavail of a FAT12/FAT16 partition

FAT12/FAT16 partition has no FSINFO sector storing the free cluster number,
so scanning the FAT is necessary to get the free clusters nums.

Close #I3Q0VS
上级 c9c6b40b
......@@ -4290,6 +4290,51 @@ FRESULT f_stat (
}
FRESULT fat_count_free_entries(
DWORD *nclst, /* Pointer to a variable to return number of free clusters */
FATFS *fs /* Pointer to corresponding filesystem object */
)
{
DWORD nfree, clst, stat;
QWORD sect;
UINT i;
FFOBJID obj;
FRESULT res = FR_OK;
nfree = 0;
if (fs->fs_type == FS_FAT12) { /* FAT12: Scan bit field FAT entries */
clst = 2; obj.fs = fs;
do {
stat = get_fat(&obj, clst);
if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
if (stat == 1) { res = FR_INT_ERR; break; }
if (stat == 0) nfree++;
} while (++clst < fs->n_fatent);
} else {
/* FAT16/32: Scan WORD/DWORD FAT entries */
clst = fs->n_fatent; /* Number of entries */
sect = fs->fatbase; /* Top of the FAT */
i = 0; /* Offset in the sector */
do { /* Counts numbuer of entries with zero in the FAT */
if (i == 0) {
res = move_window(fs, sect++);
if (res != FR_OK) break;
}
if (fs->fs_type == FS_FAT16) {
if (ld_word(fs->win + i) == 0) nfree++;
i += 2;
} else {
if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++;
i += 4;
}
i %= SS(fs);
} while (--clst);
}
*nclst = nfree; /* Return the free clusters */
fs->free_clst = nfree; /* Now free_clst is valid */
fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */
return res;
}
#if !FF_FS_READONLY
/*-----------------------------------------------------------------------*/
......@@ -4304,11 +4349,6 @@ FRESULT f_getfree (
{
FRESULT res;
FATFS *fs;
DWORD nfree, clst, stat;
QWORD sect;
UINT i;
FFOBJID obj;
/* Get logical drive */
res = find_volume(&path, &fs, 0);
......@@ -4319,38 +4359,7 @@ FRESULT f_getfree (
*nclst = fs->free_clst;
} else {
/* Scan FAT to obtain number of free clusters */
nfree = 0;
if (fs->fs_type == FS_FAT12) { /* FAT12: Scan bit field FAT entries */
clst = 2; obj.fs = fs;
do {
stat = get_fat(&obj, clst);
if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
if (stat == 1) { res = FR_INT_ERR; break; }
if (stat == 0) nfree++;
} while (++clst < fs->n_fatent);
} else {
/* FAT16/32: Scan WORD/DWORD FAT entries */
clst = fs->n_fatent; /* Number of entries */
sect = fs->fatbase; /* Top of the FAT */
i = 0; /* Offset in the sector */
do { /* Counts numbuer of entries with zero in the FAT */
if (i == 0) {
res = move_window(fs, sect++);
if (res != FR_OK) break;
}
if (fs->fs_type == FS_FAT16) {
if (ld_word(fs->win + i) == 0) nfree++;
i += 2;
} else {
if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++;
i += 4;
}
i %= SS(fs);
} while (--clst);
}
*nclst = nfree; /* Return the free clusters */
fs->free_clst = nfree; /* Now free_clst is valid */
fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */
res = fat_count_free_entries(nclst, fs);
}
}
......
......@@ -450,7 +450,8 @@ FRESULT f_getclustinfo (FIL* fp, DWORD* fclust, DWORD* fcount); /* get the clust
FRESULT f_checkopenlock(int index);
FRESULT sync_fs (FATFS* fs);
FRESULT sync_window(FATFS *fs);
FRESULT move_window ( FATFS* fs, QWORD sector);
FRESULT move_window (FATFS* fs, QWORD sector);
FRESULT fat_count_free_entries(DWORD *nclst, FATFS *fs);
void get_fileinfo (DIR* dp, FILINFO* fno);
DWORD get_fat (FFOBJID *obj, DWORD clst);
FRESULT put_fat(FATFS *fs, DWORD clst, DWORD val);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册