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

📄 namei.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/msdos/namei.c * *  Written 1992,1993 by Werner Almesberger *  Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu> */#define __NO_VERSION__#include <linux/module.h>#include <linux/sched.h>#include <linux/msdos_fs.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/stat.h>#include <asm/segment.h>#include "../fat/msbuffer.h"#define PRINTK(x)/* 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 bad_if_strict[] = "+=,; ";void msdos_put_super(struct super_block *sb){	fat_put_super(sb);	MOD_DEC_USE_COUNT;}struct super_operations msdos_sops = { 	msdos_read_inode,	fat_notify_change,	fat_write_inode,	fat_put_inode,	msdos_put_super,	NULL, /* added in 0.96c */	fat_statfs,	NULL};struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent){	struct super_block *res;	MOD_INC_USE_COUNT;	MSDOS_SB(sb)->options.isvfat = 0;	sb->s_op = &msdos_sops;	res =  fat_read_super(sb, data, silent);	if (res == NULL)		MOD_DEC_USE_COUNT;	return res;}/***** Formats an MS-DOS file name. Rejects invalid names. */static int msdos_format_name(char conv,const char *name,int len,	char *res,int dot_dirs,char dotsOK)	/* conv is relaxed/normal/strict, name is proposed name,	 * len is the length of the proposed name, res is the result name,	 * dot_dirs is . and .. are OK, dotsOK is if hidden files get dots.	 */{	char *walk;	const char **reserved;	unsigned char c;	int space;	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {		if (!dot_dirs) return -EEXIST;		memset(res+1,' ',10);		while (len--) *res++ = '.';		return 0;	}	if (name[0] == '.') {  /* dotfile because . and .. already done */		if (!dotsOK) return -EINVAL;		/* Get rid of dot - test for it elsewhere */		name++; len--;	}	space = 1; /* disallow names that _really_ start with a dot */	c = 0;	for (walk = res; len && walk-res < 8; walk++) {	    	c = *name++;		len--;		if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;		if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL;  		if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;		if (c < ' ' || c == ':' || c == '\\') return -EINVAL;/*  0xE5 is legal as a first character, but we must substitute 0x05     *//*  because 0xE5 marks deleted files.  Yes, DOS really does this.       *//*  It seems that Microsoft hacked DOS to support non-US characters     *//*  after the 0xE5 character was already in use to mark deleted files.  */		if((res==walk) && (c==0xE5)) c=0x05;		if (c == '.') break;		space = (c == ' ');		*walk = (c >= 'a' && c <= 'z') ? c-32 : c;	}	if (space) return -EINVAL;	if (conv == 's' && 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 (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;			if (conv == 's' && strchr(bad_if_strict,c))				return -EINVAL;			if (c < ' ' || c == ':' || c == '\\' || c == '.')				return -EINVAL;			if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;			space = c == ' ';			*walk++ = c >= 'a' && c <= 'z' ? c-32 : c;		}		if (space) return -EINVAL;		if (conv == 's' && len) return -EINVAL;	}	while (walk-res < MSDOS_NAME) *walk++ = ' ';	for (reserved = reserved_names; *reserved; reserved++)		if (!strncmp(res,*reserved,8)) return -EINVAL;	return 0;}/***** Locates a directory entry.  Uses unformatted name. */static int msdos_find(struct inode *dir,const char *name,int len,    struct buffer_head **bh,struct msdos_dir_entry **de,int *ino){	char msdos_name[MSDOS_NAME];	int res;	char dotsOK;	char scantype;	dotsOK = MSDOS_SB(dir->i_sb)->options.dotsOK;	res = msdos_format_name(MSDOS_SB(dir->i_sb)->options.name_check,				name,len, msdos_name,1,dotsOK);	if (res < 0)		return -ENOENT;	if((name[0]=='.') && dotsOK){	    switch(len){		case  0: panic("Empty name in msdos_find!");		case  1: scantype = SCAN_ANY;				break;		case  2: scantype = ((name[1]=='.')?SCAN_ANY:SCAN_HID); break;		default: scantype = SCAN_HID;	    }	} else {	    scantype = (dotsOK ? SCAN_NOTHID : SCAN_ANY);	}	return fat_scan(dir,msdos_name,bh,de,ino,scantype);}/***** Get inode using directory and name */int msdos_lookup(struct inode *dir,const char *name,int len,    struct inode **result){	struct super_block *sb = dir->i_sb;	int ino,res;	struct msdos_dir_entry *de;	struct buffer_head *bh;	struct inode *next;		PRINTK (("msdos_lookup\n"));	*result = NULL;	if (!dir) return -ENOENT;	if (!S_ISDIR(dir->i_mode)) {		iput(dir);		return -ENOENT;	}	PRINTK (("msdos_lookup 2\n"));	if (len == 1 && name[0] == '.') {		*result = dir;		return 0;	}	if (len == 2 && name[0] == '.' && name[1] == '.') {		ino = fat_parent_ino(dir,0);		iput(dir);		if (ino < 0) return ino;		if (!(*result = iget(dir->i_sb,ino))) return -EACCES;		return 0;	}#if 0	if (dcache_lookup(dir, name, len, (unsigned long *) &ino)) {		iput(dir);		if (!(*result = iget(dir->i_sb, ino)))			return -EACCES;		return 0;	}#endif	PRINTK (("msdos_lookup 3\n"));	if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) {		iput(dir);		return res;	}	PRINTK (("msdos_lookup 4\n"));	if (bh)		fat_brelse(sb, bh);	PRINTK (("msdos_lookup 4.5\n"));	if (!(*result = iget(dir->i_sb,ino))) {		iput(dir);		return -EACCES;	}	PRINTK (("msdos_lookup 5\n"));	if (!(*result)->i_sb ||	    ((*result)->i_sb->s_magic != MSDOS_SUPER_MAGIC)) {		/* crossed a mount point into a non-msdos fs */		iput(dir);		return 0;	}	if (MSDOS_I(*result)->i_busy) { /* mkdir in progress */		iput(*result);		iput(dir);		return -ENOENT;	}	PRINTK (("msdos_lookup 6\n"));	while (MSDOS_I(*result)->i_old) {		next = MSDOS_I(*result)->i_old;		iput(*result);		if (!(*result = iget(next->i_sb,next->i_ino))) {			fat_fs_panic(dir->i_sb,"msdos_lookup: Can't happen");			iput(dir);			return -ENOENT;		}	}	PRINTK (("msdos_lookup 7\n"));	iput(dir);	PRINTK (("msdos_lookup 8\n"));	return 0;}/***** Creates a directory entry (name is already formatted). */static int msdos_create_entry(struct inode *dir, const char *name,int len,    int is_dir, int is_hid, struct inode **result){	struct super_block *sb = dir->i_sb;	struct buffer_head *bh;	struct msdos_dir_entry *de;	int res,ino;	if ((res = fat_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) {		if (res != -ENOENT) return res;		if ((dir->i_ino == MSDOS_ROOT_INO) &&		    (MSDOS_SB(sb)->fat_bits != 32))			return -ENOSPC;		if ((res = fat_add_cluster(dir)) < 0) return res;		if ((res = fat_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) return res;	}	/*	 * XXX all times should be set by caller upon successful completion.	 */	dir->i_ctime = dir->i_mtime = CURRENT_TIME;	dir->i_dirt = 1;	memcpy(de->name,name,MSDOS_NAME);	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;	de->attr = is_hid ? (de->attr|ATTR_HIDDEN) : (de->attr&~ATTR_HIDDEN);	de->start = 0;	de->starthi = 0;	fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);	de->size = 0;	fat_mark_buffer_dirty(sb, bh, 1);	if ((*result = iget(dir->i_sb,ino)) != NULL)		msdos_read_inode(*result);	fat_brelse(sb, bh);	if (!*result) return -EIO;	(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =	    CURRENT_TIME;	(*result)->i_dirt = 1;	dcache_add(dir, name, len, ino);	return 0;}/***** Create a file or directory */int msdos_create(struct inode *dir,const char *name,int len,int mode,	struct inode **result){	struct super_block *sb = dir->i_sb;	struct buffer_head *bh;	struct msdos_dir_entry *de;	char msdos_name[MSDOS_NAME];	int ino,res,is_hid;	if (!dir) return -ENOENT;	if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->options.name_check,				     name,len,msdos_name,0,				     MSDOS_SB(dir->i_sb)->options.dotsOK)) < 0) {		iput(dir);		return res;	}	is_hid = (name[0]=='.') && (msdos_name[0]!='.');	fat_lock_creation();	/* Scan for existing file twice, so that creating a file fails	 * with -EINVAL if the other (dotfile/nondotfile) exists.	 * Else SCAN_ANY would do. Maybe use EACCES, EBUSY, ENOSPC, ENFILE?	 */	if (fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_HID) >= 0) {		fat_unlock_creation();		fat_brelse(sb, bh);		iput(dir);		return is_hid ? -EEXIST : -EINVAL; 	}	if (fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_NOTHID) >= 0) {		fat_unlock_creation();		fat_brelse(sb, bh);		iput(dir);		return is_hid ? -EINVAL : -EEXIST; 	}	res = msdos_create_entry(dir,msdos_name,len,S_ISDIR(mode),is_hid,				 result);	fat_unlock_creation();	iput(dir);	return res;}#ifdef DEBUGstatic 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");}#endif/***** See if directory is empty */static int msdos_empty(struct inode *dir){	struct super_block *sb = dir->i_sb;	loff_t pos;	struct buffer_head *bh;	struct msdos_dir_entry *de;	if (dir->i_count > 1)		return -EBUSY;	if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */		pos = 0;		bh = NULL;		while (fat_get_entry(dir,&pos,&bh,&de) > -1)			/* Ignore vfat longname entries */			if (de->attr == ATTR_EXT)				continue;			if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,			    MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,			    MSDOS_NAME)) {				fat_brelse(sb, bh);				return -ENOTEMPTY;			}		if (bh)			fat_brelse(sb, bh);	}	return 0;}/***** Remove a directory */int msdos_rmdir(struct inode *dir,const char *name,int len){	struct super_block *sb = dir->i_sb;	int res,ino;	struct buffer_head *bh;	struct msdos_dir_entry *de;	struct inode *inode;	bh = NULL;	inode = NULL;	res = -EPERM;	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.')))		goto rmdir_done;	if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done;	res = -ENOENT;	if (!(inode = iget(dir->i_sb,ino))) goto rmdir_done;	res = -ENOTDIR;	if (!S_ISDIR(inode->i_mode)) goto rmdir_done;	res = -EBUSY;	if (dir->i_dev != inode->i_dev || dir == inode)	  goto rmdir_done;	res = msdos_empty(inode);	if (res)		goto rmdir_done;	inode->i_nlink = 0;	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;	dir->i_nlink--;	inode->i_dirt = dir->i_dirt = 1;

⌨️ 快捷键说明

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