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

📄 namei.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 3 页
字号:
 * 2) File name is 8.3 format, but it contain the uppercase and * lowercase char, muliti bytes char, etc. In this case numtail is not * added, but Longfilename is stored. *  * 3) When the one except for the above, or the following special * character are contained: *        .   [ ] ; , + = * numtail is added, and Longfilename must be stored in disk . */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 inline unsigned charshortname_info_to_lcase(struct shortname_info *base,			struct shortname_info *ext){	unsigned char lcase = 0;	if (base->valid && ext->valid) {		if (!base->upper && base->lower && (ext->lower || ext->upper))			lcase |= CASE_LOWER_BASE;		if (!ext->upper && ext->lower && (base->lower || base->upper))			lcase |= CASE_LOWER_EXT;	}	return lcase;}static inline int to_shortname_char(struct nls_table *nls,				    char *buf, int buf_size, wchar_t *src,				    struct shortname_info *info){	int len;	if (IS_SKIPCHAR(*src)) {		info->valid = 0;		return 0;	}	if (IS_REPLACECHAR(*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] = vfat_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;}/* * Given a valid longname, create a unique shortname.  Make sure the * shortname does not exist * Returns negative number on error, 0 for a normal * return, and 1 for valid shortname */static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,				 wchar_t *uname, int ulen,				 char *name_res, unsigned char *lcase){	wchar_t *ip, *ext_start, *end, *name_start;	unsigned char base[9], ext[4], buf[8], *p;	unsigned char charbuf[NLS_MAX_CHARSET_SIZE];	int chl, chi;	int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen;	int is_shortname;	struct shortname_info base_info, ext_info;	unsigned short opt_shortname = MSDOS_SB(dir->i_sb)->options.shortname;	is_shortname = 1;	INIT_SHORTNAME_INFO(&base_info);	INIT_SHORTNAME_INFO(&ext_info);	/* 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 (!IS_SKIPCHAR(*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] == DELETED_FLAG)		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, ' ', MSDOS_NAME);	memcpy(name_res, base, baselen);	memcpy(name_res + 8, ext, extlen);	*lcase = 0;	if (is_shortname && base_info.valid && ext_info.valid) {		if (vfat_find_form(dir, name_res) == 0)			return -EEXIST;		if (opt_shortname & VFAT_SFN_CREATE_WIN95) {			return (base_info.upper && ext_info.upper);		} else if (opt_shortname & VFAT_SFN_CREATE_WINNT) {			if ((base_info.upper || base_info.lower)			    && (ext_info.upper || ext_info.lower)) {				*lcase = shortname_info_to_lcase(&base_info,								 &ext_info);				return 1;			}			return 0;		} else {			BUG();		}	}		if (MSDOS_SB(dir->i_sb)->options.numtail == 0)		if (vfat_find_form(dir, name_res) < 0)			return 0;	/*	 * 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';		if (vfat_find_form(dir, name_res) < 0)			return 0;	}	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);		if (vfat_find_form(dir, name_res) < 0)			break;		i -= 11;	}	return 0;}/* Translate a string, including coded sequences into Unicode */static intxlate_to_uni(const char *name, int len, char *outname, int *longlen, int *outlen,	     int escape, int utf8, struct nls_table *nls){	const unsigned char *ip;	unsigned char nc;	char *op;	unsigned int ec;	int i, k, fill;	int charlen;	if (utf8) {		*outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);		if (name[len-1] == '.')			*outlen-=2;		op = &outname[*outlen * sizeof(__u16)];	} else {		if (name[len-1] == '.') 			len--;		if (nls) {			for (i = 0, ip = name, op = outname, *outlen = 0;			     i < len && *outlen <= 260; *outlen += 1)			{				if (escape && (*ip == ':')) {					if (i > len - 5)						return -EINVAL;					ec = 0;					for (k = 1; k < 5; k++) {						nc = ip[k];						ec <<= 4;						if (nc >= '0' && nc <= '9') {							ec |= nc - '0';							continue;						}						if (nc >= 'a' && nc <= 'f') {							ec |= nc - ('a' - 10);							continue;						}						if (nc >= 'A' && nc <= 'F') {							ec |= nc - ('A' - 10);							continue;						}						return -EINVAL;					}					*op++ = ec & 0xFF;					*op++ = ec >> 8;					ip += 5;					i += 5;				} else {					if ((charlen = nls->char2uni(ip, len-i, (wchar_t *)op)) < 0)						return -EINVAL;					ip += charlen;					i += charlen;					op += 2;				}			}		} else {			for (i = 0, ip = name, op = outname, *outlen = 0;			     i < len && *outlen <= 260; i++, *outlen += 1)			{				*op++ = *ip++;				*op++ = 0;			}		}	}	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;}static intvfat_fill_slots(struct inode *dir, struct msdos_dir_slot *ds, const char *name,		int len, int *slots, int is_dir, int uni_xlate){	struct nls_table *nls_io, *nls_disk;	wchar_t *uname;	struct msdos_dir_slot *ps;	struct msdos_dir_entry *de;	unsigned long page;	unsigned char cksum, lcase;	char *uniname, msdos_name[MSDOS_NAME];	int res, utf8, slot, ulen, unilen, i;	loff_t offset;	*slots = 0;	utf8 = MSDOS_SB(dir->i_sb)->options.utf8;	nls_io = MSDOS_SB(dir->i_sb)->nls_io;	nls_disk = MSDOS_SB(dir->i_sb)->nls_disk;	if (name[len-1] == '.')		len--;	if(!(page = __get_free_page(GFP_KERNEL)))		return -ENOMEM;	uniname = (char *) page;	res = xlate_to_uni(name, len, uniname, &ulen, &unilen, uni_xlate,			   utf8, nls_io);	if (res < 0)		goto out_free;	uname = (wchar_t *) page;	res = vfat_is_used_badchars(uname, ulen);	if (res < 0)		goto out_free;	res = vfat_create_shortname(dir, nls_disk, uname, ulen,				    msdos_name, &lcase);	if (res < 0)		goto out_free;	else if (res == 1) {		de = (struct msdos_dir_entry *)ds;		res = 0;		goto shortname;	}	/* build the entry of long file name */	*slots = unilen / 13;	for (cksum = i = 0; i < 11; i++) {		cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];	}	PRINTK3(("vfat_fill_slots 3: slots=%d\n",*slots));	for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {		ps->id = slot;		ps->attr = ATTR_EXT;		ps->reserved = 0;		ps->alias_checksum = cksum;		ps->start = 0;		offset = (slot - 1) * 13;		fatwchar_to16(ps->name0_4, uname + offset, 5);		fatwchar_to16(ps->name5_10, uname + offset + 5, 6);		fatwchar_to16(ps->name11_12, uname + offset + 11, 2);	}	ds[0].id |= 0x40;	de = (struct msdos_dir_entry *) ps;shortname:	PRINTK3(("vfat_fill_slots 9\n"));	/* build the entry of 8.3 alias name */	(*slots)++;	strncpy(de->name, msdos_name, MSDOS_NAME);	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;	de->lcase = lcase;	de->adate = de->cdate = de->date = 0;	de->ctime_ms = de->ctime = de->time = 0;	de->start = 0;	de->starthi = 0;

⌨️ 快捷键说明

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