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

📄 namei.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/fs/vfat/namei.c * *  Written 1992,1993 by Werner Almesberger * *  Windows95/Windows NT compatible extended MSDOS filesystem *    by Gordon Chaffee Copyright (C) 1995.  Send bug reports for the *    VFAT filesystem to <chaffee@plateau.cs.berkeley.edu>.  Specify *    what file operation caused you trouble and if you can duplicate *    the problem, send a script that demonstrates it. */#include <linux/config.h>#define __NO_VERSION__#include <linux/module.h>#include <linux/sched.h>#include <linux/msdos_fs.h>#include <linux/nls.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/stat.h>#include <linux/mm.h>#include <linux/malloc.h>#include "../fat/msbuffer.h"#if 0# define PRINTK(x) printk x#else# define PRINTK(x)#endif#ifndef DEBUG# define CHECK_STACK#else# define CHECK_STACK check_stack(__FILE__, __LINE__)#endif/* * XXX: It would be better to use the tolower from linux/ctype.h, * but _ctype is needed and it is not exported. */#define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c)-('A'-'a') : (c))struct vfat_find_info {	const char *name;	int len;	int new_filename;	int found;	int is_long;	off_t offset;	off_t short_offset;	int long_slots;	ino_t ino;	int posix;};void vfat_read_inode(struct inode *inode);void vfat_put_super(struct super_block *sb){	fat_put_super(sb);	MOD_DEC_USE_COUNT;}static struct super_operations vfat_sops = { 	vfat_read_inode,	fat_notify_change,	fat_write_inode,	fat_put_inode,	vfat_put_super,	NULL, /* added in 0.96c */	fat_statfs,	NULL};static int parse_options(char *options,	struct fat_mount_options *opts){	char *this_char,*value,save,*savep;	int ret;	opts->unicode_xlate = opts->posixfs = 0;	opts->numtail = 1;	opts->utf8 = 0;	if (!options) return 1;	save = 0;	savep = NULL;	ret = 1;	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {		if ((value = strchr(this_char,'=')) != NULL) {			save = *value;			savep = value;			*value++ = 0;		}		if (!strcmp(this_char,"utf8")) {			if (value) {				ret = 0;			} else {				opts->utf8 = 1;			}		} else if (!strcmp(this_char,"uni_xlate")) {			if (value) {				ret = 0;			} else {				opts->unicode_xlate = 1;			}		}		else if (!strcmp(this_char,"posix")) {			if (value) {				ret = 0;			} else {				opts->posixfs = 1;			}		}		else if (!strcmp(this_char,"nonumtail")) {			if (value) {				ret = 0;			} else {				opts->numtail = 0;			}		}		if (this_char != options)			*(this_char-1) = ',';		if (value) {			*savep = save;		}		if (ret == 0) {			return 0;		}	}	if (opts->unicode_xlate) {		opts->utf8 = 0;	}	return 1;}struct super_block *vfat_read_super(struct super_block *sb,void *data,				    int silent){	struct super_block *res;  	MOD_INC_USE_COUNT;		MSDOS_SB(sb)->options.isvfat = 1;	sb->s_op = &vfat_sops;	res = fat_read_super(sb, data, silent);	if (res == NULL) {		sb->s_dev = 0;		MOD_DEC_USE_COUNT;		return NULL;	}	if (!parse_options((char *) data, &(MSDOS_SB(sb)->options))) {		MOD_DEC_USE_COUNT;	} else {		MSDOS_SB(sb)->options.dotsOK = 0;	}	return res;}#ifdef DEBUGstatic voidcheck_stack(const char *fname, int lineno){	int stack_level;	char *pg_dir;	stack_level = (long)(&pg_dir)-current->kernel_stack_page;	if (stack_level < 0)	        printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",		       fname, lineno, stack_level);	else if (stack_level < 500)	        printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",		       fname, lineno, stack_level);#if 0	else		printk("------- vfat kstack ok in %s line %d: SL=%d\n",		       fname, lineno, stack_level);#endif	if (*(unsigned long *) current->kernel_stack_page != STACK_MAGIC) {		printk("******* vfat stack corruption detected in %s at line %d\n",		       fname, lineno);	}}static int debug = 0;static void dump_fat(struct super_block *sb,int start){	printk("[");	while (start) {		printk("%d ",start);		start = fat_access(sb,start,-1);		if (!start) {			printk("ERROR");			break;		}		if (start == -1) break;	}	printk("]\n");}static void dump_de(struct msdos_dir_entry *de){	int i;	unsigned char *p = (unsigned char *) de;	printk("[");	for (i = 0; i < 32; i++, p++) {		printk("%02x ", *p);	}	printk("]\n");}#endif/* MS-DOS "device special files" */static const char *reserved_names[] = {	"CON     ","PRN     ","NUL     ","AUX     ",	"LPT1    ","LPT2    ","LPT3    ","LPT4    ",	"COM1    ","COM2    ","COM3    ","COM4    ",	NULL };/* Characters that are undesirable in an MS-DOS file name */static char bad_chars[] = "*?<>|\":/\\";static char replace_chars[] = "[];,+=";static int vfat_find(struct inode *dir,const char *name,int len,		      int find_long,int new_filename,int is_dir,		      struct slot_info *sinfo_out);/* Checks the validity of an long MS-DOS filename *//* Returns negative number on error, 0 for a normal * return, and 1 for . or .. */static int vfat_valid_longname(const char *name, int len, int dot_dirs,			       int xlate){	const char **reserved;	unsigned char c;	int i;	if (IS_FREE(name)) return -EINVAL;	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {		if (!dot_dirs) return -EEXIST;		return 1;	}	if (len && name[len-1] == ' ') return -EINVAL;	if (len >= 256) return -EINVAL;	for (i = 0; i < len; i++) {		c = name[i];		if (xlate && c == ':') continue;		if (strchr(bad_chars,c)) {			return -EINVAL;		}	} 	if (len == 3 || len == 4) {		for (reserved = reserved_names; *reserved; reserved++)			if (!strncmp(name,*reserved,8)) return -EINVAL;	}	return 0;}static int vfat_valid_shortname(const char *name,int len,				int dot_dirs, int utf8){	const char *walk, **reserved;	unsigned char c;	int space;	if (IS_FREE(name)) return -EINVAL;	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {		if (!dot_dirs) return -EEXIST;		return 1;	}	space = 1; /* disallow names starting with a dot */	c = 0;	for (walk = name; len && walk-name < 8;) {	    	c = *walk++;		len--;		if (utf8 && (c & 0x80)) return -EINVAL;		if (strchr(bad_chars,c)) return -EINVAL;		if (strchr(replace_chars,c)) return -EINVAL;  		if (c >= 'A' && c <= 'Z') return -EINVAL;		if (c < ' ' || c == ':' || c == '\\') return -EINVAL;		if ((walk == name) && (c == 0xE5)) c = 0x05;		if (c == '.') break;		space = c == ' ';	}	if (space) return -EINVAL;	if (len && c != '.') {		c = *walk++;		len--;		if (c != '.') return -EINVAL;	}	while (c != '.' && len--) c = *walk++;	if (c == '.') {		if (len >= 4) return -EINVAL;		while (len > 0 && walk-name < (MSDOS_NAME+1)) {			c = *walk++;			len--;			if (utf8 && (c & 0x80)) return -EINVAL;			if (strchr(bad_chars,c)) return -EINVAL;			if (strchr(replace_chars,c))				return -EINVAL;			if (c < ' ' || c == ':' || c == '\\' || c == '.')				return -EINVAL;			if (c >= 'A' && c <= 'Z') return -EINVAL;			space = c == ' ';		}		if (space) return -EINVAL;		if (len) return -EINVAL;	}	for (reserved = reserved_names; *reserved; reserved++)		if (!strncmp(name,*reserved,8)) return -EINVAL;	return 0;}/* Takes a short filename and converts it to a formatted MS-DOS filename. * If the short filename is not a valid MS-DOS filename, an error is  * returned.  The formatted short filename is returned in 'res'. */static int vfat_format_name(const char *name,int len,char *res,  int dot_dirs,int utf8){	char *walk;	const char **reserved;	unsigned char c;	int space;	if (IS_FREE(name)) return -EINVAL;	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {		if (!dot_dirs) return -EEXIST;		memset(res+1,' ',10);		while (len--) *res++ = '.';		return 0;	}	space = 1; /* disallow names starting with a dot */	c = 0;	for (walk = res; len && walk-res < 8; walk++) {	    	c = *name++;		len--;		if (utf8 && (c & 0x80)) return -EINVAL;		if (strchr(bad_chars,c)) return -EINVAL;		if (strchr(replace_chars,c)) return -EINVAL;		if (c >= 'A' && c <= 'Z') return -EINVAL;		if (c < ' ' || c == ':' || c == '\\') return -EINVAL;		if (c == '.') break;		space = c == ' ';		*walk = c >= 'a' && c <= 'z' ? c-32 : c;	}	if (space) return -EINVAL;	if (len && c != '.') {		c = *name++;		len--;		if (c != '.') return -EINVAL;	}	while (c != '.' && len--) c = *name++;	if (c == '.') {		while (walk-res < 8) *walk++ = ' ';		while (len > 0 && walk-res < MSDOS_NAME) {			c = *name++;			len--;			if (utf8 && (c & 0x80)) return -EINVAL;			if (strchr(bad_chars,c)) return -EINVAL;			if (strchr(replace_chars,c))				return -EINVAL;			if (c < ' ' || c == ':' || c == '\\' || c == '.')				return -EINVAL;			if (c >= 'A' && c <= 'Z') return -EINVAL;			space = c == ' ';			*walk++ = c >= 'a' && c <= 'z' ? c-32 : c;		}		if (space) return -EINVAL;		if (len) return -EINVAL;	}	while (walk-res < MSDOS_NAME) *walk++ = ' ';	for (reserved = reserved_names; *reserved; reserved++)		if (!strncmp(res,*reserved,8)) return -EINVAL;	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, const char *name,     int len, char *name_res, int utf8){	const char *ip, *ext_start, *end;	char *p;	int sz, extlen, baselen, totlen;	char msdos_name[13];	char base[9], ext[4];	int i;	int res;	int spaces;	char buf[8];	struct slot_info sinfo;	const char *name_start;	PRINTK(("Entering vfat_create_shortname: name=%s, len=%d\n", name, len));	sz = 0;			/* Make compiler happy */	if (len && name[len-1]==' ') return -EINVAL;	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 */		res = 0;		for (i = 0, p = msdos_name, ip = name; i < len; i++, p++, ip++)		{			if (*ip == ' ') {				res = -EINVAL;				break;			}			if (*ip >= 'A' && *ip <= 'Z') {				*p = *ip + 32;			} else {				*p = *ip;			}		}		if (res == 0) {			res = vfat_format_name(msdos_name, len, name_res, 1, utf8);		}		if (res > -1) {			PRINTK(("vfat_create_shortname 1\n"));			res = vfat_find(dir, msdos_name, len, 0, 0, 0, &sinfo);			PRINTK(("vfat_create_shortname 2\n"));			if (res > -1) return -EEXIST;			return 0;		}	}	PRINTK(("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) {		if (*ext_start == '.') {			if (ext_start == end - 1) {				sz = len;				ext_start = NULL;			}			break;		}	}	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)		{			if (!strchr(skip_chars,*name_start)) break;			name_start++;		}		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++)	{		if (utf8 && (*ip & 0x80)) {			*p++ = '_';			baselen++;		} else if (!strchr(skip_chars, *ip)) {			if (*ip >= 'A' && *ip <= 'Z') {				*p = *ip + 32;			} else {				*p = *ip;			}			if (strchr(replace_chars, *p)) *p='_';			p++; baselen++;		}		ip++;	}	if (baselen == 0) {		return -EINVAL;	}			spaces = 8 - baselen;	if (ext_start) {		extlen = 0;		for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {			if (utf8 && (*ip & 0x80)) {				*p++ = '_';				extlen++;			} else if (!strchr(skip_chars, *ip)) {				if (*ip >= 'A' && *ip <= 'Z') {					*p = *ip + 32;				} else {					*p = *ip;				}				if (strchr(replace_chars, *p)) *p='_';				extlen++;				p++;			}		}	} else {		extlen = 0;	}	ext[extlen] = '\0';	base[baselen] = '\0';	strcpy(msdos_name, base);	msdos_name[baselen] = '.';	strcpy(&msdos_name[baselen+1], ext);	totlen = baselen + extlen + (extlen > 0);	res = 0;	if (MSDOS_SB(dir->i_sb)->options.numtail == 0) {		res = vfat_find(dir, msdos_name, totlen, 0, 0, 0, &sinfo);	}	i = 0;	while (res > -1) {		/* Create the next shortname to try */		i++;		if (i == 10000000) return -EEXIST;		sprintf(buf, "%d", i);		sz = strlen(buf);		if (sz + 1 > spaces) {			baselen = baselen - (sz + 1 - spaces);			spaces = sz + 1;		}		strncpy(msdos_name, base, baselen);		msdos_name[baselen] = '~';		strcpy(&msdos_name[baselen+1], buf);		msdos_name[baselen+sz+1] = '.';		strcpy(&msdos_name[baselen+sz+2], ext);		totlen = baselen + sz + 1 + extlen + (extlen > 0);		res = vfat_find(dir, msdos_name, totlen, 0, 0, 0, &sinfo);	}	res = vfat_format_name(msdos_name, totlen, name_res, 1, utf8);	return res;

⌨️ 快捷键说明

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