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

📄 namei.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/fs/umsdos/namei.c * *	Written 1993 by Jacques Gelinas  *	Inspired from linux/fs/msdos/... by Werner Almesberger * * Maintain and access the --linux alternate directory file. */#include <linux/errno.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/stat.h>#include <linux/string.h>#include <linux/msdos_fs.h>#include <linux/umsdos_fs.h>#include <linux/malloc.h>#define PRINTK(x)#define Printk(x)	printk x#if 1/*	Wait for creation exclusivity.	Return 0 if the dir was already available.	Return 1 if a wait was necessary.		When 1 is return, it means a wait was done. It does not		mean the directory is available.*/static int umsdos_waitcreate(struct inode *dir){	int ret = 0;	if (dir->u.umsdos_i.u.dir_info.creating		&& dir->u.umsdos_i.u.dir_info.pid != current->pid){		sleep_on(&dir->u.umsdos_i.u.dir_info.p);		ret = 1;	}	return ret;}/*	Wait for any lookup process to finish*/static void umsdos_waitlookup (struct inode *dir){	while (dir->u.umsdos_i.u.dir_info.looking){		sleep_on(&dir->u.umsdos_i.u.dir_info.p);	}}/*	Lock all other process out of this directory.*/void umsdos_lockcreate (struct inode *dir){	/* #Specification: file creation / not atomic		File creation is a two step process. First we create (allocate)		an entry in the EMD file and then (using the entry offset) we		build a unique name for MSDOS. We create this name in the msdos		space.		We have to use semaphore (sleep_on/wake_up) to prevent lookup		into a directory when we create a file or directory and to		prevent creation while a lookup is going on. Since many lookup		may happen at the same time, the semaphore is a counter.		Only one creation is allowed at the same time. This protection		may not be necessary. The problem arise mainly when a lookup		or a readdir is done while a file is partially created. The		lookup process see that as a "normal" problem and silently		erase the file from the EMD file. Normal because a file		may be erased during a MSDOS session, but not removed from		the EMD file.		The locking is done on a directory per directory basis. Each		directory inode has its wait_queue.		For some operation like hard link, things even get worse. Many		creation must occur at once (atomic). To simplify the design		a process is allowed to recursively lock the directory for		creation. The pid of the locking process is kept along with		a counter so a second level of locking is granted or not.	*/	/*		Wait for any creation process to finish except		if we (the process) own the lock	*/	while (umsdos_waitcreate(dir)!=0);	dir->u.umsdos_i.u.dir_info.creating++;	dir->u.umsdos_i.u.dir_info.pid = current->pid;	umsdos_waitlookup (dir);}/*	Lock all other process out of those two directories.*/static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2){	/*		We must check that both directory are available before		locking anyone of them. This is to avoid some deadlock.		Thanks to dglaude@is1.vub.ac.be (GLAUDE DAVID) for pointing		this to me.	*/	while (1){		if (umsdos_waitcreate(dir1)==0			&& umsdos_waitcreate(dir2)==0){			/* We own both now */			dir1->u.umsdos_i.u.dir_info.creating++;			dir1->u.umsdos_i.u.dir_info.pid = current->pid;			dir2->u.umsdos_i.u.dir_info.creating++;			dir2->u.umsdos_i.u.dir_info.pid = current->pid;			break;		}	}	umsdos_waitlookup(dir1);	umsdos_waitlookup(dir2);}/*	Wait until creation is finish in this directory.*/void umsdos_startlookup (struct inode *dir){	while (umsdos_waitcreate (dir) != 0);	dir->u.umsdos_i.u.dir_info.looking++;}/*	Unlock the directory.*/void umsdos_unlockcreate (struct inode *dir){	dir->u.umsdos_i.u.dir_info.creating--;	if (dir->u.umsdos_i.u.dir_info.creating < 0){		printk ("UMSDOS: dir->u.umsdos_i.u.dir_info.creating < 0: %d"			,dir->u.umsdos_i.u.dir_info.creating);	}	wake_up (&dir->u.umsdos_i.u.dir_info.p);}/*	Tell directory lookup is over.*/void umsdos_endlookup (struct inode *dir){	dir->u.umsdos_i.u.dir_info.looking--;	if (dir->u.umsdos_i.u.dir_info.looking < 0){		printk ("UMSDOS: dir->u.umsdos_i.u.dir_info.looking < 0: %d"			,dir->u.umsdos_i.u.dir_info.looking);	}	wake_up (&dir->u.umsdos_i.u.dir_info.p);}#elsestatic void umsdos_lockcreate (struct inode *dir){}static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2){}void umsdos_startlookup (struct inode *dir){}static void umsdos_unlockcreate (struct inode *dir){}void umsdos_endlookup (struct inode *dir){}#endifstatic int umsdos_nevercreat(	struct inode *dir,	const char *name,		/* Name of the file to add */	int len,	int errcod)				/* Length of the name */{	int ret = 0;	if (umsdos_is_pseudodos(dir,name,len)){		/* #Specification: pseudo root / any file creation /DOS			The pseudo sub-directory /DOS can't be created!			EEXIST is returned.			The pseudo sub-directory /DOS can't be removed!			EPERM is returned.		*/		ret = -EPERM;		ret = errcod;	}else if (name[0] == '.'		&& (len == 1 || (len == 2 && name[1] == '.'))){		/* #Specification: create / . and ..			If one try to creates . or .., it always fail and return			EEXIST.			If one try to delete . or .., it always fail and return			EPERM.			This should be test at the VFS layer level to avoid			duplicating this in all file systems. Any comments ?		*/		ret = errcod;	}	return ret;}	/*	Add a new file (ordinary or special) into the alternate directory.	The file is added to the real MSDOS directory. If successful, it	is then added to the EDM file.	Return the status of the operation. 0 mean success.*/static int umsdos_create_any (	struct inode *dir,	const char *name,		/* Name of the file to add */	int len,				/* Length of the name */	int mode,				/* Permission bit + file type ??? */	int rdev,				/* major, minor or 0 for ordinary file */							/* and symlinks */	char flags,	struct inode **result)	/* Will hold the inode of the newly created */							/* file */{	int ret = umsdos_nevercreat(dir,name,len,-EEXIST);	if (ret == 0){		struct umsdos_info info;		ret = umsdos_parse (name,len,&info);		*result = NULL;		if (ret == 0){			info.entry.mode = mode;			info.entry.rdev = rdev;			info.entry.flags = flags;			info.entry.uid = current->fsuid;			info.entry.gid = (dir->i_mode & S_ISGID)				? dir->i_gid : current->fsgid;			info.entry.ctime = info.entry.atime = info.entry.mtime				= CURRENT_TIME;			info.entry.nlink = 1;			umsdos_lockcreate(dir);			ret = umsdos_newentry (dir,&info);			if (ret == 0){				dir->i_count++;				ret = msdos_create (dir,info.fake.fname,info.fake.len					,S_IFREG|0777,result);				if (ret == 0){					struct inode *inode = *result;					umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);					PRINTK (("inode %p[%d] ",inode,inode->i_count));					PRINTK (("Creation OK: [%d] %s %d pos %d\n",dir->i_ino						,info.fake.fname,current->pid,info.f_pos));				}else{					/* #Specification: create / file exist in DOS						Here is a situation. Trying to create a file with						UMSDOS. The file is unknown to UMSDOS but already						exist in the DOS directory.						Here is what we are NOT doing:						We could silently assume that everything is fine						and allows the creation to succeed.						It is possible not all files in the partition						are mean to be visible from linux. By trying to create						those file in some directory, one user may get access						to those file without proper permissions. Looks like						a security hole to me. Off course sharing a file system						with DOS is some kind of security hole :-)						So ?						We return EEXIST in this case.						The same is true for directory creation.					*/					if (ret == -EEXIST){						printk ("UMSDOS: out of sync, Creation error [%ld], "							"deleting %s %d %d pos %ld\n",dir->i_ino							,info.fake.fname,-ret,current->pid,info.f_pos);					}					umsdos_delentry (dir,&info,0);				}				PRINTK (("umsdos_create %s ret = %d pos %d\n"					,info.fake.fname,ret,info.f_pos));			}			umsdos_unlockcreate(dir);		}	}	iput (dir);	return ret;}/*	Initialise the new_entry from the old for a rename operation.	(Only useful for umsdos_rename_f() below).*/static void umsdos_ren_init(	struct umsdos_info *new_info,	struct umsdos_info *old_info,	int flags)		/* 0 == copy flags from old_name */					/* != 0, this is the value of flags */{	new_info->entry.mode = old_info->entry.mode;	new_info->entry.rdev = old_info->entry.rdev;	new_info->entry.uid = old_info->entry.uid;	new_info->entry.gid = old_info->entry.gid;	new_info->entry.ctime = old_info->entry.ctime;	new_info->entry.atime = old_info->entry.atime;	new_info->entry.mtime = old_info->entry.mtime;	new_info->entry.flags = flags ? flags : old_info->entry.flags;	new_info->entry.nlink = old_info->entry.nlink;}#define chkstk() \	if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page){\		printk(KERN_ALERT "UMSDOS: %s magic %x != %lx ligne %d\n" \		, current->comm,STACK_MAGIC \		,*(unsigned long *)current->kernel_stack_page \		,__LINE__); \	}	/*	Rename a file (move) in the file system.*/static int umsdos_rename_f(	struct inode * old_dir,	const char * old_name,	int old_len,	struct inode * new_dir,	const char * new_name,	int new_len,	int flags)		/* 0 == copy flags from old_name */					/* != 0, this is the value of flags */{	int ret = -EPERM;	struct umsdos_info old_info;	int old_ret = umsdos_parse (old_name,old_len,&old_info);	struct umsdos_info new_info;	int new_ret = umsdos_parse (new_name,new_len,&new_info);chkstk();	PRINTK (("umsdos_rename %d %d ",old_ret,new_ret));	if (old_ret == 0 && new_ret == 0){		umsdos_lockcreate2(old_dir,new_dir);chkstk();		PRINTK (("old findentry "));		ret = umsdos_findentry(old_dir,&old_info,0);chkstk();		PRINTK (("ret %d ",ret));		if (ret == 0){			/* check sticky bit on old_dir */			if ( !(old_dir->i_mode & S_ISVTX) || fsuser() ||			    current->fsuid == old_info.entry.uid ||			    current->fsuid == old_dir->i_uid ) {				/* Does new_name already exist? */				PRINTK(("new findentry "));				ret = umsdos_findentry(new_dir,&new_info,0);				if (ret != 0 || /* if destination file exists, are we allowed to replace it ? */				    !(new_dir->i_mode & S_ISVTX) || fsuser() ||				    current->fsuid == new_info.entry.uid ||				    current->fsuid == new_dir->i_uid ) {					PRINTK (("new newentry "));					umsdos_ren_init(&new_info,&old_info,flags);					ret = umsdos_newentry (new_dir,&new_info);chkstk();					PRINTK (("ret %d %d ",ret,new_info.fake.len));					if (ret == 0){						PRINTK (("msdos_rename "));						old_dir->i_count++;						new_dir->i_count++;	/* Both inode are needed later */						ret = msdos_rename (old_dir								    ,old_info.fake.fname,old_info.fake.len								    ,new_dir								    ,new_info.fake.fname,new_info.fake.len								    ,0);chkstk();						PRINTK (("after m_rename ret %d ",ret));						if (ret != 0){							umsdos_delentry (new_dir,&new_info									 ,S_ISDIR(new_info.entry.mode));chkstk();						}else{							ret = umsdos_delentry (old_dir,&old_info									       ,S_ISDIR(old_info.entry.mode));

⌨️ 快捷键说明

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