?? ff.c
字號:
if (c != 0xE5 && c != '.' && !(a & AM_VOL) && !MemCmp(dir, dj->fn, 11)) /* Is it a valid entry? */
break;
#endif
res = dir_next(dj, FALSE); /* Next entry */
} while (res == FR_OK);
return res;
}
/*-----------------------------------------------------------------------*/
/* Read an object from the directory */
/*-----------------------------------------------------------------------*/
#if _FS_MINIMIZE <= 2
static
FRESULT dir_read (
DIR *dj /* Pointer to the directory object to store read object name */
)
{
FRESULT res;
BYTE a, c, ord, sum, *dir;
ord = sum = 0xFF;
res = FR_NO_FILE;
while (dj->sect) {
res = move_window(dj->fs, dj->sect);
if (res != FR_OK) break;
dir = dj->dir; /* Ptr to the directory entry of current index */
c = dir[DIR_Name];
if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
a = dir[DIR_Attr] & AM_MASK;
#if _USE_LFN /* LFN configuration */
if (c == 0xE5 || c == '.' || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */
ord = 0xFF;
} else {
if (a == AM_LFN) { /* An LFN entry is found */
if (c & 0x40) { /* Is it start of LFN sequence? */
sum = dir[LDIR_Chksum];
c &= 0xBF; ord = c;
dj->lfn_idx = dj->index;
}
/* Check LFN validity and capture it */
ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF;
} else { /* An SFN entry is found */
if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN entry? */
dj->lfn_idx = 0xFFFF; /* No LFN. */
break;
}
}
#else /* Non LFN configuration */
if (c != 0xE5 && c != '.' && !(a & AM_VOL)) /* Is it a valid entry? */
break;
#endif
res = dir_next(dj, FALSE); /* Next entry */
if (res != FR_OK) break;
}
if (res != FR_OK) dj->sect = 0;
return res;
}
#endif
/*-----------------------------------------------------------------------*/
/* Register an object to the directory */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
static
FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */
DIR *dj /* Target directory with object name to be created */
)
{
FRESULT res;
BYTE c, *dir;
#if _USE_LFN /* LFN configuration */
WORD n, ne, is;
BYTE sn[12], *fn, sum;
WCHAR *lfn;
fn = dj->fn; lfn = dj->lfn;
MemCpy(sn, fn, 12);
if (sn[11] & 1) { /* When LFN is out of 8.3 format, generate a numbered name */
fn[11] = 0; dj->lfn = NULL; /* Find only SFN */
for (n = 1; n < 100; n++) {
gen_numname(fn, sn, lfn, n); /* Generate a numbered name */
res = dir_seek(dj, 0);
if (res != FR_OK) break;
res = dir_find(dj); /* Check if the name collides with existing SFN */
if (res != FR_OK) break;
}
if (n == 100) return FR_DENIED; /* Abort if too many collisions */
if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */
fn[11] = sn[11]; dj->lfn = lfn;
}
if (sn[11] & 2) { /* When eliminate LFN, reserve only an SFN entry. */
ne = 1;
} else { /* Otherwise reserve an SFN + LFN entries. */
for (ne = 0; lfn[ne]; ne++) ;
ne = (ne + 25) / 13;
}
/* Reserve contiguous entries */
res = dir_seek(dj, 0);
if (res != FR_OK) return res;
n = is = 0;
do {
res = move_window(dj->fs, dj->sect);
if (res != FR_OK) break;
c = *dj->dir; /* Check the entry status */
if (c == 0xE5 || c == 0) { /* Is it a blank entry? */
if (n == 0) is = dj->index; /* First index of the contigulus entry */
if (++n == ne) break; /* A contiguous entry that requiered count is found */
} else {
n = 0; /* Not a blank entry. Restart to search */
}
res = dir_next(dj, TRUE); /* Next entry with table streach */
} while (res == FR_OK);
if (res == FR_OK && ne > 1) { /* Initialize LFN entry if needed */
res = dir_seek(dj, is);
if (res == FR_OK) {
sum = sum_sfn(dj->fn); /* Sum of the SFN tied to the LFN */
ne--;
do { /* Store LFN entries in bottom first */
res = move_window(dj->fs, dj->sect);
if (res != FR_OK) break;
fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum);
dj->fs->wflag = 1;
res = dir_next(dj, FALSE); /* Next entry */
} while (res == FR_OK && --ne);
}
}
#else /* Non LFN configuration */
res = dir_seek(dj, 0);
if (res == FR_OK) {
do { /* Find a blank entry for the SFN */
res = move_window(dj->fs, dj->sect);
if (res != FR_OK) break;
c = *dj->dir;
if (c == 0xE5 || c == 0) break; /* Is it a blank entry? */
res = dir_next(dj, TRUE); /* Next entry with table streach */
} while (res == FR_OK);
}
#endif
if (res == FR_OK) { /* Initialize the SFN entry */
res = move_window(dj->fs, dj->sect);
if (res == FR_OK) {
dir = dj->dir;
MemSet(dir, 0, 32); /* Clean the entry */
MemCpy(dir, dj->fn, 11); /* Put SFN */
dir[DIR_NTres] = *(dj->fn+11) & 0x18; /* Put NT flag */
dj->fs->wflag = 1;
}
}
return res;
}
#endif /* !_FS_READONLY */
/*-----------------------------------------------------------------------*/
/* Remove an object from the directory */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY && !_FS_MINIMIZE
static
FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */
DIR *dj /* Directory object pointing the entry to be removed */
)
{
FRESULT res;
#if _USE_LFN /* LFN configuration */
WORD i;
i = dj->index; /* SFN index */
res = dir_seek(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */
if (res == FR_OK) {
do {
res = move_window(dj->fs, dj->sect);
if (res != FR_OK) break;
*dj->dir = 0xE5; /* Mark the entry "deleted" */
dj->fs->wflag = 1;
if (dj->index >= i) break; /* When SFN is deleted, all entries of the object is deleted. */
res = dir_next(dj, FALSE); /* Next entry */
} while (res == FR_OK);
if (res == FR_NO_FILE) res = FR_INT_ERR;
}
#else /* Non LFN configuration */
res = dir_seek(dj, dj->index);
if (res == FR_OK) {
res = move_window(dj->fs, dj->sect);
if (res == FR_OK) {
*dj->dir = 0xE5; /* Mark the entry "deleted" */
dj->fs->wflag = 1;
}
}
#endif
return res;
}
#endif /* !_FS_READONLY */
/*-----------------------------------------------------------------------*/
/* Pick a segment and create the object name in directory form */
/*-----------------------------------------------------------------------*/
static
FRESULT create_name (
DIR *dj, /* Pointer to the directory object */
const char **path /* Pointer to pointer to the segment in the path string */
)
{
#if _USE_LFN
BYTE c, b, cf, *sfn;
WCHAR w, *lfn;
int i, ni, si, di;
const char *p;
/* Create LFN in Unicode */
si = di = 0;
p = *path;
lfn = dj->lfn;
for (;;) {
w = (BYTE)p[si++]; /* Get a character */
if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */
if (IsDBCS1(w)) { /* If it is DBC 1st byte */
c = p[si++]; /* Get 2nd byte */
if (!IsDBCS2(c)) /* Reject invalid DBC */
return FR_INVALID_NAME;
w = (w << 8) + c;
} else {
if (StrChr("\"*:<>?|\x7F", w)) /* Reject unallowable chars for LFN */
return FR_INVALID_NAME;
}
w = ff_convert(w, 1); /* Convert OEM to Unicode, store it */
if (!w || di >= _MAX_LFN) /* Reject invalid code or too long name */
return FR_INVALID_NAME;
lfn[di++] = w;
}
*path = &p[si]; /* Rerurn pointer to the next segment */
cf = (w < ' ') ? 4 : 0; /* Set last segment flag if end of path */
while (di) { /* Strip trailing spaces and dots */
w = lfn[di - 1];
if (w != ' ' && w != '.') break;
di--;
}
if (!di) return FR_INVALID_NAME; /* Reject null string */
lfn[di] = 0; /* LFN is created */
/* Create SFN in directory form */
sfn = dj->fn;
MemSet(sfn, ' ', 11);
for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */
if (si) cf |= 1;
while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */
b = i = 0; ni = 8;
for (;;) {
w = lfn[si++]; /* Get an LFN char */
if (w == 0) break; /* Break when enf of the LFN */
if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */
cf |= 1; continue;
}
if (i >= ni || si == di) { /* Here is extension or end of SFN */
if (ni == 11) { /* Extension is longer than 3 bytes */
cf |= 1; break;
}
if (si != di) cf |= 1; /* File name is longer than 8 bytes */
if (si > di) break; /* No extension */
si = di; i = 8; ni = 11; /* Enter extension section */
b <<= 2; continue;
}
w = ff_convert(w, 0); /* Unicode -> OEM code */
if (w >= 0x80) cf |= 0x20; /* If there is any extended char, force create an LFN */
if (w >= 0x100) { /* Double byte char */
if (i >= ni - 1) {
cf |= 1; i = ni; continue;
}
sfn[i++] = (BYTE)(w >> 8);
} else { /* Single byte char */
if (StrChr("+,;[=]", w)) { /* Replace unallowable chars for SFN */
w = '_'; cf |= 1;
} else {
if (IsUpper(w)) { /* Large capital */
b |= 2;
} else {
if (IsLower(w)) { /* Small capital */
b |= 1; w -= 0x20;
}
}
}
}
sfn[i++] = (BYTE)w;
}
if (sfn[0] == 0xE5) sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */
if (ni == 8) b <<= 2;
if ((cf & 0x21) == 0) { /* When LFN is in 8.3 format without extended char, NT flags are created */
if ((b & 0x03) == 0x01) cf |= 0x10; /* NT flag (Extension has only small capital) */
if ((b & 0x0C) == 0x04) cf |= 0x08; /* NT flag (Filename has only small capital) */
if ((b & 0x0C) != 0x0C && (b & 0x03) != 0x03) cf |= 2; /* Eliminate LFN when non composite capitals */
}
sfn[11] = cf; /* SFN is created */
#else
BYTE c, d, b, *sfn;
int ni, si, i;
const char *p;
/* Create file name in directory form */
sfn = dj->fn;
MemSet(sfn, ' ', 11);
si = i = b = 0; ni = 8;
p = *path;
for (;;) {
c = p[si++];
if (c < ' ' || c == '/' || c == '\\') break; /* Break on end of segment */
if (c == '.' || i >= ni) {
if (ni != 8 || c != '.') return FR_INVALID_NAME;
i = 8; ni = 11;
b <<= 2; continue;
}
if (c >= 0x80) b |= 3; /* If there is any extended char, eliminate NT flag */
if (IsDBCS1(c)) { /* If it is DBC 1st byte */
d = p[si++]; /* Get 2nd byte */
if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */
return FR_INVALID_NAME;
sfn[i++] = c;
sfn[i++] = d;
} else {
if (StrChr(" +,;[=]\"*:<>?|\x7F", c)) /* Reject unallowable chrs for SFN */
return FR_INVALID_NAME;
if (IsUpper(c)) {
b |= 2;
} else {
if (IsLower(c)) {
b |= 1; c -= 0x20;
}
}
sfn[i++] = c;
}
}
*path = &p[si]; /* Rerurn pointer to the next segment */
c = (c < ' ') ? 4 : 0; /* Set last segment flag if end of path */
if (!i) return FR_INVALID_NAME; /* Reject null string */
if (sfn[0] == 0xE5) sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */
if (ni == 8) b <<= 2;
if ((b & 0x03) == 0x01) c |= 0x10; /* NT flag (Extension has only small capital) */
if ((b & 0x0C) == 0x04) c |= 0x08; /* NT flag (Filename has only small capital) */
sfn[11] = c; /* Store NT flag, File name is created */
#endif
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* Get file information from directory entry */
/*-----------------------------------------------------------------------*/
#if _FS_MINIMIZE <= 1
static
void get_fileinfo ( /* No return code */
DIR *dj, /* Pointer to the directory object */
FILINFO *fno /* Pointer to store the file information */
)
{
int i;
BYTE c, nt, *dir;
char *p;
p = fno->fname;
if (dj->sect) {
dir = dj->dir;
nt = dir[DIR_NTres]; /* NT flag */
for (i = 0; i < 8; i++) { /* Copy file name body */
c = dir[i];
if (c == ' ') break;
if (c == 0x05) c = 0xE5;
if ((nt & 0x08) && IsUpper(c)) c += 0x20;
*p++ = c;
}
if (dir[8] != ' ') { /* Copy file name extension */
*p++ = '.';
for (i = 8; i < 11; i++) {
c = dir[i];
if (c == ' ') break;
if ((nt & 0x10) && IsUpper(c)) c += 0x20;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -