📄 landzo
字号:
}
#endif
clst = nxt; /* Next cluster */
}
}
return res;
}
#endif
/*-----------------------------------------------------------------------*/
/* FAT handling - Stretch or Create a cluster chain */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
static
DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
FATFS *fs, /* File system object */
DWORD clst /* Cluster# to stretch. 0 means create a new chain. */
)
{
DWORD cs, ncl, scl;
FRESULT res;
if (clst == 0) /* Create a new chain */
{
scl = fs->last_clust; /* Get suggested start point */
if (!scl || scl >= fs->n_fatent) scl = 1;
}
else /* Stretch the current chain */
{
cs = get_fat(fs, clst); /* Check the cluster status */
if (cs < 2) return 1; /* It is an invalid cluster */
if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */
scl = clst;
}
ncl = scl; /* Start cluster */
for (;;)
{
ncl++; /* Next cluster */
if (ncl >= fs->n_fatent) /* Wrap around */
{
ncl = 2;
if (ncl > scl) return 0; /* No free cluster */
}
cs = get_fat(fs, ncl); /* Get the cluster status */
if (cs == 0) break; /* Found a free cluster */
if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */
return cs;
if (ncl == scl) return 0; /* No free cluster */
}
res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */
if (res == FR_OK && clst != 0)
{
res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */
}
if (res == FR_OK)
{
fs->last_clust = ncl; /* Update FSINFO */
if (fs->free_clust != 0xFFFFFFFF)
{
fs->free_clust--;
fs->fsi_flag = 1;
}
}
else
{
ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;
}
return ncl; /* Return new cluster number or error code */
}
#endif /* !_FS_READONLY */
/*-----------------------------------------------------------------------*/
/* FAT handling - Convert offset into cluster with link map table */
/*-----------------------------------------------------------------------*/
#if _USE_FASTSEEK
static
DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */
FIL *fp, /* Pointer to the file object */
DWORD ofs /* File offset to be converted to cluster# */
)
{
DWORD cl, ncl, *tbl;
tbl = fp->cltbl + 1; /* Top of CLMT */
cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */
for (;;)
{
ncl = *tbl++; /* Number of cluters in the fragment */
if (!ncl) return 0; /* End of table? (error) */
if (cl < ncl) break; /* In this fragment? */
cl -= ncl;
tbl++; /* Next fragment */
}
return cl + *tbl; /* Return the cluster number */
}
#endif /* _USE_FASTSEEK */
/*-----------------------------------------------------------------------*/
/* Directory handling - Set directory index */
/*-----------------------------------------------------------------------*/
static
FRESULT dir_sdi (
DIR *dj, /* Pointer to directory object */
WORD idx /* Directory index number */
)
{
DWORD clst;
WORD ic;
dj->index = idx;
clst = dj->sclust;
if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */
return FR_INT_ERR;
if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */
clst = dj->fs->dirbase;
if (clst == 0) /* Static table (root-dir in FAT12/16) */
{
dj->clust = clst;
if (idx >= dj->fs->n_rootdir) /* Index is out of range */
return FR_INT_ERR;
dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */
}
else /* Dynamic table (sub-dirs or root-dir in FAT32) */
{
ic = SS(dj->fs) / SZ_DIR * dj->fs->csize; /* Entries per cluster */
while (idx >= ic) /* Follow cluster chain */
{
clst = get_fat(dj->fs, clst); /* Get next cluster */
if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */
if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */
return FR_INT_ERR;
idx -= ic;
}
dj->clust = clst;
dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */
}
dj->dir = dj->fs->win + (idx % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; /* Ptr to the entry in the sector */
return FR_OK; /* Seek succeeded */
}
/*-----------------------------------------------------------------------*/
/* Directory handling - Move directory index next */
/*-----------------------------------------------------------------------*/
static
FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */
DIR *dj, /* Pointer to directory object */
int stretch /* 0: Do not stretch table, 1: Stretch table if needed */
)
{
DWORD clst;
WORD i;
stretch = stretch; /* To suppress warning on read-only cfg. */
i = dj->index + 1;
if (!i || !dj->sect) /* Report EOT when index has reached 65535 */
return FR_NO_FILE;
if (!(i % (SS(dj->fs) / SZ_DIR))) /* Sector changed? */
{
dj->sect++; /* Next sector */
if (dj->clust == 0) /* Static table */
{
if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */
return FR_NO_FILE;
}
else /* Dynamic table */
{
if (((i / (SS(dj->fs) / SZ_DIR)) & (dj->fs->csize - 1)) == 0) /* Cluster changed? */
{
clst = get_fat(dj->fs, dj->clust); /* Get next cluster */
if (clst <= 1) return FR_INT_ERR;
if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
if (clst >= dj->fs->n_fatent) /* When it reached end of dynamic table */
{
#if !_FS_READONLY
BYTE c;
if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */
clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */
if (clst == 0) return FR_DENIED; /* No free cluster */
if (clst == 1) return FR_INT_ERR;
if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
/* Clean-up stretched table */
if (move_window(dj->fs, 0)) return FR_DISK_ERR; /* Flush active window */
mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */
dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */
for (c = 0; c < dj->fs->csize; c++) /* Fill the new cluster with 0 */
{
dj->fs->wflag = 1;
if (move_window(dj->fs, 0)) return FR_DISK_ERR;
dj->fs->winsect++;
}
dj->fs->winsect -= c; /* Rewind window address */
#else
return FR_NO_FILE; /* Report EOT */
#endif
}
dj->clust = clst; /* Initialize data for new cluster */
dj->sect = clust2sect(dj->fs, clst);
}
}
}
dj->index = i;
dj->dir = dj->fs->win + (i % (SS(dj->fs) / SZ_DIR)) * SZ_DIR;
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */
/*-----------------------------------------------------------------------*/
#if _USE_LFN
static
const BYTE LfnOfs[] = {1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30}; /* Offset of LFN chars in the directory entry */
static
int cmp_lfn ( /* 1:Matched, 0:Not matched */
WCHAR *lfnbuf, /* Pointer to the LFN to be compared */
BYTE *dir /* Pointer to the directory entry containing a part of LFN */
)
{
UINT i, s;
WCHAR wc, uc;
i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */
s = 0;
wc = 1;
do
{
uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character from the entry */
if (wc) /* Last char has not been processed */
{
wc = ff_wtoupper(uc); /* Convert it to upper case */
if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */
return 0; /* Not matched */
}
else
{
if (uc != 0xFFFF) return 0; /* Check filler */
}
}
while (++s < 13); /* Repeat until all chars in the entry are checked */
if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i]) /* Last segment matched but different length */
return 0;
return 1; /* The part of LFN matched */
}
static
int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */
BYTE *dir /* Pointer to the directory entry */
)
{
UINT i, s;
WCHAR wc, uc;
i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
s = 0;
wc = 1;
do
{
uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character from the entry */
if (wc) /* Last char has not been processed */
{
if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
lfnbuf[i++] = wc = uc; /* Store it */
}
else
{
if (uc != 0xFFFF) return 0; /* Check filler */
}
}
while (++s < 13); /* Read all character in the entry */
if (dir[LDIR_Ord] & LLE) /* Put terminator if it is the last LFN part */
{
if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
lfnbuf[i] = 0;
}
return 1;
}
#if !_FS_READONLY
static
void fit_lfn (
const WCHAR *lfnbuf, /* Pointer to the LFN buffer */
BYTE *dir, /* Pointer to the directory entry */
BYTE ord, /* LFN order (1-20) */
BYTE sum /* SFN sum */
)
{
UINT i, s;
WCHAR wc;
dir[LDIR_Chksum] = sum; /* Set check sum */
dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */
dir[LDIR_Type] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -