⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ff.c

📁 STM32_电子相框.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
				}
				if (lfen) {				/* Match LFN if it is out of 8.3 format */
					if (ord == 0) break;
				} else {				/* Match SFN if LFN is in 8.3 format */
					if (!mem_cmp(dir, dj->fn, 11)) break;
				}
			}
		}
#else	/* Non LFN configuration */
		if (c != 0xE5 && c != '.' && !(a & AM_VOL) && !mem_cmp(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;
	mem_cpy(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_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;
			mem_set(dir, 0, 32);			/* Clean the entry */
			mem_cpy(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 (chk_chr("\"*:<>\?|\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;
	mem_set(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 (chk_chr("+,;[=]", 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;
	mem_set(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 (chk_chr(" +,;[=]\"*:<>\?|\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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -