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

📄 namei.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 4 页
字号:
		}		/*		 * See if the low-level filesystem might want		 * to use its own hash..		 */		if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {			err = nd->dentry->d_op->d_hash(nd->dentry, &this);			if (err < 0)				break;		}		/* This does the actual lookups.. */		dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);		if (!dentry) {			dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);			err = PTR_ERR(dentry);			if (IS_ERR(dentry))				break;		}		/* Check mountpoints.. */		while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))			;		err = -ENOENT;		inode = dentry->d_inode;		if (!inode)			goto out_dput;		err = -ENOTDIR; 		if (!inode->i_op)			goto out_dput;		if (inode->i_op->follow_link) {			err = do_follow_link(dentry, nd);			dput(dentry);			if (err)				goto return_err;			err = -ENOENT;			inode = nd->dentry->d_inode;			if (!inode)				break;			err = -ENOTDIR; 			if (!inode->i_op)				break;		} else {			dput(nd->dentry);			nd->dentry = dentry;		}		err = -ENOTDIR; 		if (!inode->i_op->lookup)			break;		continue;		/* here ends the main loop */last_with_slashes:		lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;last_component:		if (lookup_flags & LOOKUP_PARENT)			goto lookup_parent;		if (this.name[0] == '.') switch (this.len) {			default:				break;			case 2:					if (this.name[1] != '.')					break;				follow_dotdot(nd);				inode = nd->dentry->d_inode;				/* fallthrough */			case 1:				goto return_base;		}		if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {			err = nd->dentry->d_op->d_hash(nd->dentry, &this);			if (err < 0)				break;		}		dentry = cached_lookup(nd->dentry, &this, 0);		if (!dentry) {			dentry = real_lookup(nd->dentry, &this, 0);			err = PTR_ERR(dentry);			if (IS_ERR(dentry))				break;		}		while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))			;		inode = dentry->d_inode;		if ((lookup_flags & LOOKUP_FOLLOW)		    && inode && inode->i_op && inode->i_op->follow_link) {			err = do_follow_link(dentry, nd);			dput(dentry);			if (err)				goto return_err;			inode = nd->dentry->d_inode;		} else {			dput(nd->dentry);			nd->dentry = dentry;		}		err = -ENOENT;		if (!inode)			goto no_inode;		if (lookup_flags & LOOKUP_DIRECTORY) {			err = -ENOTDIR; 			if (!inode->i_op || !inode->i_op->lookup)				break;		}		goto return_base;no_inode:		err = -ENOENT;		if (lookup_flags & (LOOKUP_POSITIVE|LOOKUP_DIRECTORY))			break;		goto return_base;lookup_parent:		nd->last = this;		nd->last_type = LAST_NORM;		if (this.name[0] != '.')			goto return_base;		if (this.len == 1)			nd->last_type = LAST_DOT;		else if (this.len == 2 && this.name[1] == '.')			nd->last_type = LAST_DOTDOT;return_base:		return 0;out_dput:		dput(dentry);		break;	}	path_release(nd);return_err:	return err;}int path_walk(const char * name, struct nameidata *nd){	current->total_link_count = 0;	return link_path_walk(name, nd);}/* SMP-safe *//* returns 1 if everything is done */static int __emul_lookup_dentry(const char *name, struct nameidata *nd){	if (path_walk(name, nd))		return 0;		/* something went wrong... */	if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) {		struct nameidata nd_root;		/*		 * NAME was not found in alternate root or it's a directory.  Try to find		 * it in the normal root:		 */		nd_root.last_type = LAST_ROOT;		nd_root.flags = nd->flags;		read_lock(&current->fs->lock);		nd_root.mnt = mntget(current->fs->rootmnt);		nd_root.dentry = dget(current->fs->root);		read_unlock(&current->fs->lock);		if (path_walk(name, &nd_root))			return 1;		if (nd_root.dentry->d_inode) {			path_release(nd);			nd->dentry = nd_root.dentry;			nd->mnt = nd_root.mnt;			nd->last = nd_root.last;			return 1;		}		path_release(&nd_root);	}	return 1;}void set_fs_altroot(void){	char *emul = __emul_prefix();	struct nameidata nd;	struct vfsmount *mnt = NULL, *oldmnt;	struct dentry *dentry = NULL, *olddentry;	if (emul) {		read_lock(&current->fs->lock);		nd.mnt = mntget(current->fs->rootmnt);		nd.dentry = dget(current->fs->root);		read_unlock(&current->fs->lock);		nd.flags = LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_POSITIVE;		if (path_walk(emul,&nd) == 0) {			mnt = nd.mnt;			dentry = nd.dentry;		}	}	write_lock(&current->fs->lock);	oldmnt = current->fs->altrootmnt;	olddentry = current->fs->altroot;	current->fs->altrootmnt = mnt;	current->fs->altroot = dentry;	write_unlock(&current->fs->lock);	if (olddentry) {		dput(olddentry);		mntput(oldmnt);	}}/* SMP-safe */static inline intwalk_init_root(const char *name, struct nameidata *nd){	read_lock(&current->fs->lock);	if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {		nd->mnt = mntget(current->fs->altrootmnt);		nd->dentry = dget(current->fs->altroot);		read_unlock(&current->fs->lock);		if (__emul_lookup_dentry(name,nd))			return 0;		read_lock(&current->fs->lock);	}	nd->mnt = mntget(current->fs->rootmnt);	nd->dentry = dget(current->fs->root);	read_unlock(&current->fs->lock);	return 1;}/* SMP-safe */int path_init(const char *name, unsigned int flags, struct nameidata *nd){	nd->last_type = LAST_ROOT; /* if there are only slashes... */	nd->flags = flags;	if (*name=='/')		return walk_init_root(name,nd);	read_lock(&current->fs->lock);	nd->mnt = mntget(current->fs->pwdmnt);	nd->dentry = dget(current->fs->pwd);	read_unlock(&current->fs->lock);	return 1;}/* * Restricted form of lookup. Doesn't follow links, single-component only, * needs parent already locked. Doesn't follow mounts. * SMP-safe. */struct dentry * lookup_hash(struct qstr *name, struct dentry * base){	struct dentry * dentry;	struct inode *inode;	int err;	inode = base->d_inode;	err = permission(inode, MAY_EXEC);	dentry = ERR_PTR(err);	if (err)		goto out;	/*	 * See if the low-level filesystem might want	 * to use its own hash..	 */	if (base->d_op && base->d_op->d_hash) {		err = base->d_op->d_hash(base, name);		dentry = ERR_PTR(err);		if (err < 0)			goto out;	}	dentry = cached_lookup(base, name, 0);	if (!dentry) {		struct dentry *new = d_alloc(base, name);		dentry = ERR_PTR(-ENOMEM);		if (!new)			goto out;		lock_kernel();		dentry = inode->i_op->lookup(inode, new);		unlock_kernel();		if (!dentry)			dentry = new;		else			dput(new);	}out:	return dentry;}/* SMP-safe */struct dentry * lookup_one_len(const char * name, struct dentry * base, int len){	unsigned long hash;	struct qstr this;	unsigned int c;	this.name = name;	this.len = len;	if (!len)		goto access;	hash = init_name_hash();	while (len--) {		c = *(const unsigned char *)name++;		if (c == '/' || c == '\0')			goto access;		hash = partial_name_hash(c, hash);	}	this.hash = end_name_hash(hash);	return lookup_hash(&this, base);access:	return ERR_PTR(-EACCES);}/* *	namei() * * is used by most simple commands to get the inode of a specified name. * Open, link etc use their own routines, but this is enough for things * like 'chmod' etc. * * namei exists in two versions: namei/lnamei. The only difference is * that namei follows links, while lnamei does not. * SMP-safe */int __user_walk(const char *name, unsigned flags, struct nameidata *nd){	char *tmp;	int err;	tmp = getname(name);	err = PTR_ERR(tmp);	if (!IS_ERR(tmp)) {		err = 0;		if (path_init(tmp, flags, nd))			err = path_walk(tmp, nd);		putname(tmp);	}	return err;}/* * It's inline, so penalty for filesystems that don't use sticky bit is * minimal. */static inline int check_sticky(struct inode *dir, struct inode *inode){	if (!(dir->i_mode & S_ISVTX))		return 0;	if (inode->i_uid == current->fsuid)		return 0;	if (dir->i_uid == current->fsuid)		return 0;	return !capable(CAP_FOWNER);}/* *	Check whether we can remove a link victim from directory dir, check *  whether the type of victim is right. *  1. We can't do it if dir is read-only (done in permission()) *  2. We should have write and exec permissions on dir *  3. We can't remove anything from append-only dir *  4. We can't do anything with immutable dir (done in permission()) *  5. If the sticky bit on dir is set we should either *	a. be owner of dir, or *	b. be owner of victim, or *	c. have CAP_FOWNER capability *  6. If the victim is append-only or immutable we can't do antyhing with *     links pointing to it. *  7. If we were asked to remove a directory and victim isn't one - ENOTDIR. *  8. If we were asked to remove a non-directory and victim isn't one - EISDIR. *  9. We can't remove a root or mountpoint. */static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir){	int error;	if (!victim->d_inode || victim->d_parent->d_inode != dir)		return -ENOENT;	error = permission(dir,MAY_WRITE | MAY_EXEC);	if (error)		return error;	if (IS_APPEND(dir))		return -EPERM;	if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||	    IS_IMMUTABLE(victim->d_inode))		return -EPERM;	if (isdir) {		if (!S_ISDIR(victim->d_inode->i_mode))			return -ENOTDIR;		if (IS_ROOT(victim))			return -EBUSY;	} else if (S_ISDIR(victim->d_inode->i_mode))		return -EISDIR;	return 0;}/*	Check whether we can create an object with dentry child in directory *  dir. *  1. We can't do it if child already exists (open has special treatment for *     this case, but since we are inlined it's OK) *  2. We can't do it if dir is read-only (done in permission()) *  3. We should have write and exec permissions on dir *  4. We can't do it if dir is immutable (done in permission()) */static inline int may_create(struct inode *dir, struct dentry *child) {	if (child->d_inode)		return -EEXIST;	if (IS_DEADDIR(dir))		return -ENOENT;	return permission(dir,MAY_WRITE | MAY_EXEC);}/*  * Special case: O_CREAT|O_EXCL implies O_NOFOLLOW for security * reasons. * * O_DIRECTORY translates into forcing a directory lookup. */static inline int lookup_flags(unsigned int f){	unsigned long retval = LOOKUP_FOLLOW;	if (f & O_NOFOLLOW)		retval &= ~LOOKUP_FOLLOW;		if ((f & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))		retval &= ~LOOKUP_FOLLOW;		if (f & O_DIRECTORY)		retval |= LOOKUP_DIRECTORY;	return retval;}int vfs_create(struct inode *dir, struct dentry *dentry, int mode){	int error;	mode &= S_IALLUGO;	mode |= S_IFREG;	down(&dir->i_zombie);	error = may_create(dir, dentry);	if (error)		goto exit_lock;	error = -EACCES;	/* shouldn't it be ENOSYS? */	if (!dir->i_op || !dir->i_op->create)		goto exit_lock;	DQUOT_INIT(dir);	lock_kernel();	error = dir->i_op->create(dir, dentry, mode);	unlock_kernel();exit_lock:	up(&dir->i_zombie);	if (!error)		inode_dir_notify(dir, DN_CREATE);	return error;}/* *	open_namei() * * namei for open - this is in fact almost the whole open-routine. * * Note that the low bits of "flag" aren't the same as in the open * system call - they are 00 - no permissions needed *			  01 - read permission needed *			  10 - write permission needed *			  11 - read/write permissions needed * which is a lot more logical, and also allows the "no perm" needed * for symlinks (where the permissions are checked later). * SMP-safe */int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd){	int acc_mode, error = 0;	struct inode *inode;	struct dentry *dentry;	struct dentry *dir;	int count = 0;	acc_mode = ACC_MODE(flag);	/*	 * The simplest case - just a plain lookup.	 */	if (!(flag & O_CREAT)) {		if (path_init(pathname, lookup_flags(flag), nd))			error = path_walk(pathname, nd);		if (error)			return error;		dentry = nd->dentry;		goto ok;	}	/*	 * Create - we need to know the parent.	 */	if (path_init(pathname, LOOKUP_PARENT, nd))		error = path_walk(pathname, nd);	if (error)		return error;	/*	 * We have the parent and last component. First of all, check	 * that we are not asked to creat(2) an obvious directory - that	 * will not do.	 */	error = -EISDIR;	if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len])		goto exit;	dir = nd->dentry;	down(&dir->d_inode->i_sem);	dentry = lookup_hash(&nd->last, nd->dentry);do_last:	error = PTR_ERR(dentry);	if (IS_ERR(dentry)) {

⌨️ 快捷键说明

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