📄 fat_nls.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 + -