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

📄 namei.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (chl < 0)			return -EINVAL;		for (chi = 0; chi < chl; chi++) {			c = vfat_getupper(nls, charbuf[chi]);			if (!c) return -EINVAL;			if (charbuf[chi] != vfat_tolower(nls, c)) return -EINVAL;			if (strchr(replace_chars,c)) return -EINVAL;			if (c < ' '|| c==':') return -EINVAL;			if (c == '.') goto dot;			space = c == ' ';		}	}dot:;	if (space) return -EINVAL;	if (len && c != '.') {		len--;		if (vfat_uni2upper_short(nls, *walk++, charbuf, NLS_MAX_CHARSET_SIZE) == 1) {			if (charbuf[0] != '.') return -EINVAL;		} else			return -EINVAL;		c = '.';	}	if (c == '.') {		if (len >= 4) return -EINVAL;		while (len > 0) {			len--;			chl = nls->uni2char(*walk++, charbuf, NLS_MAX_CHARSET_SIZE);			if (chl < 0)				return -EINVAL;			for (chi = 0; chi < chl; chi++) {				c = vfat_getupper(nls, charbuf[chi]);				if (!c) return -EINVAL;				if (charbuf[chi] != vfat_tolower(nls, c)) return -EINVAL;				if (strchr(replace_chars,c))					return -EINVAL;				if (c < ' ' || c == '.'|| c==':')					return -EINVAL;				space = c == ' ';			}		}		if (space) return -EINVAL;	}	return 0;}static int vfat_find_form(struct inode *dir,char *name){	struct msdos_dir_entry *de;	struct buffer_head *bh = NULL;	int ino,res;	res=fat_scan(dir,name,&bh,&de,&ino);	fat_brelse(dir->i_sb, bh);	if (res<0)		return -ENOENT;	return 0;}static int vfat_format_name(struct nls_table *nls, wchar_t *name,				int len, char *res){	char *walk;	unsigned char charbuf[NLS_MAX_CHARSET_SIZE];	int chi, chl;	int space;	if (vfat_uni2upper_short(nls, *name, charbuf, NLS_MAX_CHARSET_SIZE) == 0)		return -EINVAL;	if (IS_FREE(charbuf))		return -EINVAL;	space = 1; /* disallow names starting with a dot */	for (walk = res; len--; ) {		chl = vfat_uni2upper_short(nls, *name++, charbuf, NLS_MAX_CHARSET_SIZE);		if (chl == 0)			return -EINVAL;		for (chi = 0; chi < chl; chi++){			if (charbuf[chi] == '.') goto dot;			if (!charbuf[chi]) return -EINVAL;			if (walk-res == 8) return -EINVAL;			if (strchr(replace_chars,charbuf[chi])) return -EINVAL;			if (charbuf[chi] < ' '|| charbuf[chi]==':') return -EINVAL;			space = charbuf[chi] == ' ';			*walk = charbuf[chi];			walk++;		}	}dot:;	if (space) return -EINVAL;	if (len >= 0) {		while (walk-res < 8) *walk++ = ' ';		while (len > 0 && walk-res < MSDOS_NAME) {			chl = vfat_uni2upper_short(nls, *name++, charbuf, NLS_MAX_CHARSET_SIZE);			if (len < chl)				chl = len;			len -= chl;			for (chi = 0; chi < chl; chi++){				if (!charbuf[chi]) return -EINVAL;				if (strchr(replace_chars,charbuf[chi]))					return -EINVAL;				if (charbuf[chi] < ' ' || charbuf[chi] == '.'|| charbuf[chi]==':')					return -EINVAL;				space = charbuf[chi] == ' ';				*walk++ = charbuf[chi];			}		}		if (space) return -EINVAL;		if (len) return -EINVAL;	}	while (walk-res < MSDOS_NAME) *walk++ = ' ';	return 0;}static char skip_chars[] = ".:\"?<>| ";/* Given a valid longname, create a unique shortname.  Make sure the * shortname does not exist */static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,					wchar_t *name, int len,					char *name_res){	wchar_t *ip, *op, *ext_start, *end, *name_start;	wchar_t msdos_name[13];	char base[9], ext[4], buf[8], *p;	unsigned char charbuf[NLS_MAX_CHARSET_SIZE];	int chl, chi;	int sz, extlen, baselen, i;	PRINTK2(("Entering vfat_create_shortname\n"));	chl = 0;	sz = 0;			/* Make compiler happy */	if (len <= 12) {		/* Do a case insensitive search if the name would be a valid		 * shortname if is were all capitalized.  However, do not		 * allow spaces in short names because Win95 scandisk does		 * not like that */		for (i = 0, op = &msdos_name[0], ip = name; ; i++, ip++, op++) {			if (i == len) {				if (vfat_format_name(nls, &msdos_name[0], len,							name_res) < 0)					break;				PRINTK3(("vfat_create_shortname 1\n"));				if (vfat_find_form(dir, name_res) < 0)					return 0;				return -EEXIST;			}			chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);			for (chi = 0; chi < chl; chi++){				if (charbuf[chi] == ' ')					break;			}			if (chi < chl)				break;			*op = *ip;		}	}	PRINTK3(("vfat_create_shortname 3\n"));	/* Now, we need to create a shortname from the long name */	ext_start = end = &name[len];	while (--ext_start >= name) {		chl = vfat_uni2upper_short(nls, *ext_start, charbuf, NLS_MAX_CHARSET_SIZE);		for (chi = 0; chi < chl; chi++) {			if (charbuf[chi] == '.') {				if (ext_start == end - 1) {					sz = len;					ext_start = NULL;				}				goto stop0;			}		}	}stop0:;		if (ext_start == name - 1) {		sz = len;		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 = &name[0];		while (name_start < ext_start)		{			chl = vfat_uni2upper_short(nls, *name_start, charbuf, NLS_MAX_CHARSET_SIZE);			if (chl == 0)				break;			for (chi = 0; chi < chl; chi++)				if (!strchr(skip_chars, charbuf[chi])) {					goto stop1;				}			name_start++;		}stop1:;				if (name_start != ext_start) {			sz = ext_start - name;			ext_start++;		} else {			sz = len;			ext_start=NULL;		}	}	for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++, ip++)	{		chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);		if (chl == 0){			*p++ = '_';			baselen++;			continue;		}		for (chi = 0; chi < chl; chi++){			if (!strchr(skip_chars, charbuf[chi])){				if (strchr(replace_chars, charbuf[chi]))					*p = '_';				else					*p = charbuf[chi];				p++; baselen++;			}		}	}	if (baselen == 0) {		return -EINVAL;	}	extlen = 0;	if (ext_start) {		for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {			chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);			if (chl == 0) {				*p++ = '_';				extlen++;				continue;			}			for (chi = 0; chi < chl; chi++) {				if (!strchr(skip_chars, charbuf[chi])) {					if (strchr(replace_chars, charbuf[chi]))						*p = '_';					else						*p = charbuf[chi];					p++; extlen++;				}			}		}	}	ext[extlen] = '\0';	base[baselen] = '\0';	/* Yes, it can happen. ".\xe5" would do it. */	if (IS_FREE(base))		base[0]='_';	/* 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);	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 = 6;	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 = 2;	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 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;	const char *ip;	char *uniname, msdos_name[MSDOS_NAME];	int res, utf8, slot, ulen, unilen, i;	loff_t offset;	de = (struct msdos_dir_entry *) ds;	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;	if (vfat_valid_shortname(nls_disk, uname, ulen) >= 0) {		res = vfat_format_name(nls_disk, uname, ulen, de->name);		if (!res)			goto out_free;	}	res = vfat_create_shortname(dir, nls_disk, uname, ulen, msdos_name);	if (res)		goto out_free;	*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;

⌨️ 快捷键说明

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