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

📄 fat_nls.c

📁 嵌入式FAT文件系统
💻 C
字号:
#include <cyg/infra/cyg_type.h>   #include <cyg/infra/cyg_trac.h>        // tracing macros#include <cyg/infra/cyg_ass.h>         // assertion macros#include <errno.h>#include <string.h>#include "nls.h"#include "stdlib.h"#define _U	0x01	/* upper */#define _L	0x02	/* lower */#define _D	0x04	/* digit */#define _C	0x08	/* cntrl */#define _P	0x10	/* punct */#define _S	0x20	/* white space (space/lf/tab) */#define _X	0x40	/* hex digit */#define _SP	0x80	/* hard space (0x20) */static unsigned char _ctype[] = {_C,_C,_C,_C,_C,_C,_C,_C,			/* 0-7 */_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,		/* 8-15 */_C,_C,_C,_C,_C,_C,_C,_C,			/* 16-23 */_C,_C,_C,_C,_C,_C,_C,_C,			/* 24-31 */_S|_SP,_P,_P,_P,_P,_P,_P,_P,			/* 32-39 */_P,_P,_P,_P,_P,_P,_P,_P,			/* 40-47 */_D,_D,_D,_D,_D,_D,_D,_D,			/* 48-55 */_D,_D,_P,_P,_P,_P,_P,_P,			/* 56-63 */_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,	/* 64-71 */_U,_U,_U,_U,_U,_U,_U,_U,			/* 72-79 */_U,_U,_U,_U,_U,_U,_U,_U,			/* 80-87 */_U,_U,_U,_P,_P,_P,_P,_P,			/* 88-95 */_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,	/* 96-103 */_L,_L,_L,_L,_L,_L,_L,_L,			/* 104-111 */_L,_L,_L,_L,_L,_L,_L,_L,			/* 112-119 */_L,_L,_L,_P,_P,_P,_P,_C,			/* 120-127 */0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 128-143 */0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 144-159 */_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */#define __ismask(x) (_ctype[(int)(unsigned char)(x)])#define isalnum(c)	((__ismask(c)&(_U|_L|_D)) != 0)#define isalpha(c)	((__ismask(c)&(_U|_L)) != 0)#define iscntrl(c)	((__ismask(c)&(_C)) != 0)#define isdigit(c)	((__ismask(c)&(_D)) != 0)#define isgraph(c)	((__ismask(c)&(_P|_U|_L|_D)) != 0)#define islower(c)	((__ismask(c)&(_L)) != 0)#define isprint(c)	((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)#define ispunct(c)	((__ismask(c)&(_P)) != 0)#define isspace(c)	((__ismask(c)&(_S)) != 0)#define isupper(c)	((__ismask(c)&(_U)) != 0)#define isxdigit(c)	((__ismask(c)&(_D|_X)) != 0)#define isascii(c) (((unsigned char)(c))<=0x7f)#define toascii(c) (((unsigned char)(c))&0x7f)static cyg_uint16 fat_bad_char(cyg_uint16 w){	return (w < 0x0020)	    || (w == '*') || (w == '?') || (w == '<') || (w == '>')	    || (w == '|') || (w == '"') || (w == ':') || (w == '/')	    || (w == '\\');	}static  cyg_uint16 fat_replace_char( cyg_uint16 w){	return (w == '[') || (w == ']') || (w == ';') || (w == ',')	    || (w == '+') || (w == '=');}static  cyg_uint16 fat_skip_char( cyg_uint16 w){	return (w == '.') || (w == ' ');}static inline int fat_is_used_badchars(const cyg_uint16 *s, int len){	int i;	for (i = 0; i < len; i++)		if (fat_bad_char(s[i]))			return -EINVAL;	return 0;}static int fat_valid_longname(const cyg_uint8 *name, cyg_uint32 len){	if (name[len - 1] == ' ')		return -EINVAL;	if (len >= 256)		return -ENAMETOOLONG;	return 0;}struct shortname_info {	unsigned char lower:1,		      upper:1,		      valid:1;};#define INIT_SHORTNAME_INFO(x)	do {		\	(x)->lower = 1;				\	(x)->upper = 1;				\	(x)->valid = 1;				\} while (0)static cyg_uint32 to_shortname_char(struct nls_table *nls,				    cyg_uint8 *buf, cyg_uint32 buf_size,				    cyg_uint16 *src, struct shortname_info *info){	int len;	if (fat_skip_char(*src)) {		info->valid = 0;		return 0;	}	if (fat_replace_char(*src)) {		info->valid = 0;		buf[0] = '_';		return 1;	}	len = nls->uni2char(*src, buf, buf_size);	if (len <= 0) {		info->valid = 0;		buf[0] = '_';		len = 1;	} else if (len == 1) {		unsigned char prev = buf[0];		if (buf[0] >= 0x7F) {			info->lower = 0;			info->upper = 0;		}		buf[0] = nls_toupper(nls, buf[0]);		if (isalpha(buf[0])) {			if (buf[0] == prev)				info->lower = 0;			else				info->upper = 0;		}	} else {		info->lower = 0;		info->upper = 0;	}	return len;}int create_shortname(void *dir,                         fatfs_disk_t *disk,                        struct nls_table *nls,			const char *name,int len,			cyg_uint8 *name_res){	cyg_uint16 *ip, *ext_start, *end, *name_start;	cyg_uint8 base[9], ext[4], buf[8], *p;	cyg_uint8 charbuf[NLS_MAX_CHARSET_SIZE];	cyg_uint16 uname[256]={0};	int ret,ulen=0;	int chl, chi;	cyg_uint32 jiffies;	int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen;	int is_shortname;	fatfs_dirsearch_t ds;	struct shortname_info base_info, ext_info;	jiffies=rand();	is_shortname = 1;	INIT_SHORTNAME_INFO(&base_info);	INIT_SHORTNAME_INFO(&ext_info);        for(i=0;i<len;)        {	        ret=fatfs_utf8_table->char2uni(name+i, len, uname[ulen]);		if(ret<0)  return ret;		if(ulen>=256) return -1;		i+=ret;		ulen++;	}	/* Now, we need to create a shortname from the long name */	ext_start = end = &uname[ulen];	while (--ext_start >= uname) {		if (*ext_start == 0x002E) {	/* is `.' */			if (ext_start == end - 1) {				sz = ulen;				ext_start = NULL;			}			break;		}	}		if (ext_start == uname - 1) {		sz = ulen;		ext_start = NULL;	} else if (ext_start) {		/*		 * Names which start with a dot could be just		 * an extension eg. "...test".  In this case Win95		 * uses the extension as the name and sets no extension.		 */		name_start = &uname[0];		while (name_start < ext_start) {			if (!fat_skip_char(*name_start))				break;			name_start++;		}		if (name_start != ext_start) {			sz = ext_start - uname;			ext_start++;		} else {			sz = ulen;			ext_start = NULL;		}	}	numtail_baselen = 6;	numtail2_baselen = 2;	for (baselen = i = 0, p = base, ip = uname; i < sz; i++, ip++) {		chl = to_shortname_char(nls, charbuf, sizeof(charbuf),					ip, &base_info);		if (chl == 0)			continue;		if (baselen < 2 && (baselen + chl) > 2)			numtail2_baselen = baselen;		if (baselen < 6 && (baselen + chl) > 6)			numtail_baselen = baselen;		for (chi = 0; chi < chl; chi++) {			*p++ = charbuf[chi];			baselen++;			if (baselen >= 8)				break;		}		if (baselen >= 8) {			if ((chi < chl - 1) || (ip + 1) - uname < sz)				is_shortname = 0;			break;		}	}	if (baselen == 0) {		return -EINVAL;	}	extlen = 0;	if (ext_start) {		for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {			chl = to_shortname_char(nls, charbuf, sizeof(charbuf),						ip, &ext_info);			if (chl == 0)				continue;			if ((extlen + chl) > 3) {				is_shortname = 0;				break;			}			for (chi = 0; chi < chl; chi++) {				*p++ = charbuf[chi];				extlen++;			}			if (extlen >= 3) {				if (ip + 1 != end)					is_shortname = 0;				break;			}		}	}	ext[extlen] = '\0';	base[baselen] = '\0';	/* Yes, it can happen. ".\xe5" would do it. */	if (base[0] == 0xe5)		base[0] = 0x05;	/* OK, at this point we know that base is not longer than 8 symbols,	 * ext is not longer than 3, base is nonempty, both don't contain	 * any bad symbols (lowercase transformed to uppercase).	 */	memset(name_res, ' ', 11);	memcpy(name_res, base, baselen);	memcpy(name_res + 8, ext, extlen);	if (is_shortname && base_info.valid && ext_info.valid) {		init_dirsearch(&ds,disk,(fatfs_node_t*)dir,name_res);		if (fatfs_find(&ds)!=)			return EEXIST;	}	/*	 * Try to find a unique extension.  This used to	 * iterate through all possibilities sequentially,	 * but that gave extremely bad performance.  Windows	 * only tries a few cases before using random	 * values for part of the base.	 */	if (baselen > 6) {		baselen = numtail_baselen;		name_res[7] = ' ';	}	name_res[baselen] = '~';	for (i = 1; i < 10; i++) {		name_res[baselen + 1] = i + '0';		init_dirsearch(&ds,disk,(fatfs_node_t*)dir,name_res);		if (fatfs_find(&ds)!=ENOERR)			return EEXIST;	}	i = jiffies & 0xffff;	sz = (jiffies >> 16) & 0x7;	if (baselen > 2) {		baselen = numtail2_baselen;		name_res[7] = ' ';	}	name_res[baselen + 4] = '~';	name_res[baselen + 5] = '1' + sz;	while (1) {		sprintf(buf, "%04X", i);		memcpy(&name_res[baselen], buf, 4);		init_dirsearch(&ds,disk,(fatfs_node_t*)dir,name_res);		if (fatfs_find(&ds)!=ENOERR)			return EEXIST;		i -= 11;	}	return 0;}/* Translate a string, including coded sequences into Unicode */intxlate_to_uni(const unsigned char *name, int len, unsigned char *outname,	     int *longlen, int *outlen){	const unsigned char *ip;	unsigned char nc;	unsigned char *op;	unsigned int ec;	int i, k, fill;	int charlen;		int name_len = strlen(name);		*outlen = utf8_mbstowcs((wchar_t *)outname, name, PAGE_SIZE);		/*		 * We stripped '.'s before and set len appropriately,		 * but utf8_mbstowcs doesn't care about len		 */		*outlen -= (name_len - len);		op = &outname[*outlen * sizeof(wchar_t)];			if (*outlen > 260)		return -ENAMETOOLONG;	*longlen = *outlen;	if (*outlen % 13) {		*op++ = 0;		*op++ = 0;		*outlen += 1;		if (*outlen % 13) {			fill = 13 - (*outlen % 13);			for (i = 0; i < fill; i++) {				*op++ = 0xff;				*op++ = 0xff;			}			*outlen += fill;		}	}	return 0;}

⌨️ 快捷键说明

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