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

📄 namei.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
字号:
/* *  linux/fs/isofs/namei.c * *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem. * *  (C) 1991  Linus Torvalds - minix filesystem */#include <linux/sched.h>#include <linux/iso_fs.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/stat.h>#include <linux/fcntl.h>#include <asm/segment.h>#include <linux/malloc.h>#include <linux/errno.h>/* * ok, we cannot use strncmp, as the name is not in our data space. * Thus we'll have to use isofs_match. No big problem. Match also makes * some sanity tests. * * NOTE! unlike strncmp, isofs_match returns 1 for success, 0 for failure. */static int isofs_match(int len,const char * name, const char * compare, int dlen){	if (!compare)		return 0;	/* check special "." and ".." files */	if (dlen == 1) {		/* "." */		if (compare[0] == 0) {			if (!len)				return 1;			compare = ".";		} else if (compare[0] == 1) {			compare = "..";			dlen = 2;		}	}#if 0	if (len <= 2) printk("Match: %d %d %s %d %d \n",len,dlen,compare,de->name[0], dlen);#endif		if (dlen != len)		return 0;	return !memcmp(name, compare, len);}/* *	isofs_find_entry() * * finds an entry in the specified directory with the wanted name. It * returns the cache buffer in which the entry was found, and the entry * itself (as an inode number). It does NOT read the inode of the * entry - you'll have to do that yourself if you want to. */static struct buffer_head *isofs_find_entry(struct inode * dir, const char * name, int namelen,		 unsigned long * ino, unsigned long * ino_back){	unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);	unsigned char bufbits = ISOFS_BUFFER_BITS(dir);	unsigned int block, i, f_pos, offset, inode_number;	struct buffer_head * bh;	void * cpnt = NULL;	unsigned int old_offset;	unsigned int backlink;	int dlen, match;	char * dpnt;	unsigned char *page = NULL;	struct iso_directory_record * de;	char c;	*ino = 0;	if (!dir) return NULL;		if (!(block = dir->u.isofs_i.i_first_extent)) return NULL;  	f_pos = 0;	offset = f_pos & (bufsize - 1);	block = isofs_bmap(dir,f_pos >> bufbits);	if (!block || !(bh = bread(dir->i_dev,block,bufsize))) return NULL;  	while (f_pos < dir->i_size) {		de = (struct iso_directory_record *) (bh->b_data + offset);		backlink = dir->i_ino;		inode_number = (block << bufbits) + (offset & (bufsize - 1));		/* If byte is zero, this is the end of file, or time to move to		   the next sector. Usually 2048 byte boundaries. */				if (*((unsigned char *) de) == 0) {			brelse(bh);			offset = 0;			f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1))				 + ISOFS_BLOCK_SIZE);			block = isofs_bmap(dir,f_pos>>bufbits);			if (!block || !(bh = bread(dir->i_dev,block,bufsize)))				return NULL;			continue; /* Will kick out if past end of directory */		}		old_offset = offset;		offset += *((unsigned char *) de);		f_pos += *((unsigned char *) de);		/* Handle case where the directory entry spans two blocks.		   Usually 1024 byte boundaries */		if (offset >= bufsize) {		        unsigned int frag1;			frag1 = bufsize - old_offset;			cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);			if (!cpnt) return NULL;			memcpy(cpnt, bh->b_data + old_offset, frag1);			de = (struct iso_directory_record *) cpnt;			brelse(bh);			offset = f_pos & (bufsize - 1);			block = isofs_bmap(dir,f_pos>>bufbits);			if (!block || !(bh = bread(dir->i_dev,block,bufsize))) {			        kfree(cpnt);				return NULL;			};			memcpy((char *)cpnt+frag1, bh->b_data, offset);		}		dlen = de->name_len[0];		dpnt = de->name;		/* Handle the '.' case */				if (*dpnt==0 && dlen==1) {			inode_number = dir->i_ino;			backlink = 0;		}				/* Handle the '..' case */		else if (*dpnt==1 && dlen==1) {#if 0			printk("Doing .. (%d %d)",			       dir->i_sb->s_firstdatazone,			       dir->i_ino);#endif			if((dir->i_sb->u.isofs_sb.s_firstdatazone) != dir->i_ino) 				inode_number = dir->u.isofs_i.i_backlink;			else				inode_number = dir->i_ino;			backlink = 0;		} else {			if (dir->i_sb->u.isofs_sb.s_rock ||			    dir->i_sb->u.isofs_sb.s_joliet_level) {				page = (unsigned char *)					__get_free_page(GFP_KERNEL);				if (!page) return NULL;			}			if (dir->i_sb->u.isofs_sb.s_rock &&			    ((i = get_rock_ridge_filename(de, page, dir)))){				if (i == -1)					goto out;/* Relocated deep directory */				dlen = i;				dpnt = page;			} else if (dir->i_sb->u.isofs_sb.s_joliet_level) {				dlen = get_joliet_filename(de, dir, page);				dpnt = page;			} else if (dir->i_sb->u.isofs_sb.s_mapping == 'n') {				for (i = 0; i < dlen; i++) {					c = dpnt[i];					/* lower case */					if (c >= 'A' && c <= 'Z') c |= 0x20;					if (c == ';' && i == dlen-2 && dpnt[i+1] == '1') {						dlen -= 2;						break;					}					if (c == ';') c = '.';					dpnt[i] = c;				}				/* This allows us to match with and without				 * a trailing period. */				if(dpnt[dlen-1] == '.' && namelen == dlen-1)					dlen--;			}		}		/*		 * Skip hidden or associated files unless unhide is set 		 */		match = 0;		if(   !(de->flags[-dir->i_sb->u.isofs_sb.s_high_sierra] & 5)		   || dir->i_sb->u.isofs_sb.s_unhide == 'y' )		{			match = isofs_match(namelen,name,dpnt,dlen);		}		if (cpnt)		{			kfree(cpnt);			cpnt = NULL;		}		if (page) free_page((unsigned long) page);		if (match) {			if(inode_number == -1) {				/* Should only happen for the '..' entry */				inode_number = 					isofs_lookup_grandparent(dir,					   find_rock_ridge_relocation(de,dir));				if(inode_number == -1){					/* Should never happen */					printk("Backlink not properly set %x %lx.\n",					       isonum_733(de->extent),					       dir->i_ino);					goto out;				}			}			*ino = inode_number;			*ino_back = backlink;			return bh;		}	} out:	if (cpnt)		kfree(cpnt);	brelse(bh);	return NULL;}int isofs_lookup(struct inode * dir,const char * name, int len,	struct inode ** result){	unsigned long ino, ino_back;	struct buffer_head * bh;#ifdef DEBUG	printk("lookup: %x %d\n",dir->i_ino, len);#endif	*result = NULL;	if (!dir)		return -ENOENT;	if (!S_ISDIR(dir->i_mode)) {		iput(dir);		return -ENOENT;	}	ino = 0;	if (dcache_lookup(dir, name, len, &ino)) ino_back = dir->i_ino;	if (!ino) {		char *lcname;		/* First try the original name. If that doesn't work and the fs		 * was mounted with check=relaxed, convert the name to lower		 * case and try again.		 */		if (!(bh = isofs_find_entry(dir,name,len, &ino, &ino_back))		    && dir->i_sb->u.isofs_sb.s_name_check == 'r'		    && (lcname = kmalloc(len, GFP_KERNEL)) != NULL) {			int i;			char c;			for (i=0; i<len; i++) {				c = name[i];				if (c >= 'A' && c <= 'Z') c |= 0x20;				lcname[i] = c;			}			bh = isofs_find_entry(dir,lcname,len, &ino, &ino_back);			kfree(lcname);		}		if (!bh) {			iput(dir);	  		return -ENOENT;		}		if (ino_back == dir->i_ino) {			dcache_add(dir, name, len, ino);		}		brelse(bh);	}	if (!(*result = iget(dir->i_sb,ino))) {		iput(dir);		return -EACCES;	}	/* We need this backlink for the ".." entry unless the name that we	   are looking up traversed a mount point (in which case the inode	   may not even be on an iso9660 filesystem, and writing to	   u.isofs_i would only cause memory corruption).	*/		if (ino_back && !(*result)->i_pipe && (*result)->i_sb == dir->i_sb) {		(*result)->u.isofs_i.i_backlink = ino_back; 	}		iput(dir);	return 0;}

⌨️ 快捷键说明

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