Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73d049a4 authored by Al Viro's avatar Al Viro
Browse files

open-style analog of vfs_path_lookup()



new function: file_open_root(dentry, mnt, name, flags) opens the file
vfs_path_lookup would arrive to.

Note that name can be empty; in that case the usual requirement that
dentry should be a directory is lifted.

open-coded equivalents switched to it, may_open() got down exactly
one caller and became static.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 5b6ca027
Loading
Loading
Loading
Loading
+2 −19
Original line number Original line Diff line number Diff line
@@ -124,35 +124,18 @@ void mconsole_log(struct mc_request *req)
#if 0
#if 0
void mconsole_proc(struct mc_request *req)
void mconsole_proc(struct mc_request *req)
{
{
	struct nameidata nd;
	struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
	struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
	struct file *file;
	struct file *file;
	int n, err;
	int n;
	char *ptr = req->request.data, *buf;
	char *ptr = req->request.data, *buf;
	mm_segment_t old_fs = get_fs();
	mm_segment_t old_fs = get_fs();


	ptr += strlen("proc");
	ptr += strlen("proc");
	ptr = skip_spaces(ptr);
	ptr = skip_spaces(ptr);


	err = vfs_path_lookup(mnt->mnt_root, mnt, ptr, LOOKUP_FOLLOW, &nd);
	file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
	if (err) {
		mconsole_reply(req, "Failed to look up file", 1, 0);
		goto out;
	}

	err = may_open(&nd.path, MAY_READ, O_RDONLY);
	if (result) {
		mconsole_reply(req, "Failed to open file", 1, 0);
		path_put(&nd.path);
		goto out;
	}

	file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
			   current_cred());
	err = PTR_ERR(file);
	if (IS_ERR(file)) {
	if (IS_ERR(file)) {
		mconsole_reply(req, "Failed to open file", 1, 0);
		mconsole_reply(req, "Failed to open file", 1, 0);
		path_put(&nd.path);
		goto out;
		goto out;
	}
	}


+2 −0
Original line number Original line Diff line number Diff line
@@ -114,6 +114,8 @@ struct open_flags {
};
};
extern struct file *do_filp_open(int dfd, const char *pathname,
extern struct file *do_filp_open(int dfd, const char *pathname,
		const struct open_flags *op, int lookup_flags);
		const struct open_flags *op, int lookup_flags);
extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
		const char *, const struct open_flags *, int lookup_flags);


/*
/*
 * inode.c
 * inode.c
+52 −28
Original line number Original line Diff line number Diff line
@@ -1487,11 +1487,13 @@ static int path_init(int dfd, const char *name, unsigned int flags,
	nd->depth = 0;
	nd->depth = 0;
	if (flags & LOOKUP_ROOT) {
	if (flags & LOOKUP_ROOT) {
		struct inode *inode = nd->root.dentry->d_inode;
		struct inode *inode = nd->root.dentry->d_inode;
		if (*name) {
			if (!inode->i_op->lookup)
			if (!inode->i_op->lookup)
				return -ENOTDIR;
				return -ENOTDIR;
			retval = inode_permission(inode, MAY_EXEC);
			retval = inode_permission(inode, MAY_EXEC);
			if (retval)
			if (retval)
				return retval;
				return retval;
		}
		nd->path = nd->root;
		nd->path = nd->root;
		nd->inode = inode;
		nd->inode = inode;
		if (flags & LOOKUP_RCU) {
		if (flags & LOOKUP_RCU) {
@@ -1937,7 +1939,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
	return error;
	return error;
}
}


int may_open(struct path *path, int acc_mode, int flag)
static int may_open(struct path *path, int acc_mode, int flag)
{
{
	struct dentry *dentry = path->dentry;
	struct dentry *dentry = path->dentry;
	struct inode *inode = dentry->d_inode;
	struct inode *inode = dentry->d_inode;
@@ -2250,11 +2252,10 @@ exit:
}
}


static struct file *path_openat(int dfd, const char *pathname,
static struct file *path_openat(int dfd, const char *pathname,
		const struct open_flags *op, int flags)
		struct nameidata *nd, const struct open_flags *op, int flags)
{
{
	struct file *base = NULL;
	struct file *base = NULL;
	struct file *filp;
	struct file *filp;
	struct nameidata nd;
	struct path path;
	struct path path;
	int count = 0;
	int count = 0;
	int error;
	int error;
@@ -2264,27 +2265,27 @@ static struct file *path_openat(int dfd, const char *pathname,
		return ERR_PTR(-ENFILE);
		return ERR_PTR(-ENFILE);


	filp->f_flags = op->open_flag;
	filp->f_flags = op->open_flag;
	nd.intent.open.file = filp;
	nd->intent.open.file = filp;
	nd.intent.open.flags = open_to_namei_flags(op->open_flag);
	nd->intent.open.flags = open_to_namei_flags(op->open_flag);
	nd.intent.open.create_mode = op->mode;
	nd->intent.open.create_mode = op->mode;


	error = path_init(dfd, pathname, flags | LOOKUP_PARENT, &nd, &base);
	error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
	if (unlikely(error))
	if (unlikely(error))
		goto out_filp;
		goto out_filp;


	current->total_link_count = 0;
	current->total_link_count = 0;
	error = link_path_walk(pathname, &nd);
	error = link_path_walk(pathname, nd);
	if (unlikely(error))
	if (unlikely(error))
		goto out_filp;
		goto out_filp;


	filp = do_last(&nd, &path, op, pathname);
	filp = do_last(nd, &path, op, pathname);
	while (unlikely(!filp)) { /* trailing symlink */
	while (unlikely(!filp)) { /* trailing symlink */
		struct path link = path;
		struct path link = path;
		struct inode *linki = link.dentry->d_inode;
		struct inode *linki = link.dentry->d_inode;
		void *cookie;
		void *cookie;
		if (!(nd.flags & LOOKUP_FOLLOW) || count++ == 32) {
		if (!(nd->flags & LOOKUP_FOLLOW) || count++ == 32) {
			path_put_conditional(&path, &nd);
			path_put_conditional(&path, nd);
			path_put(&nd.path);
			path_put(&nd->path);
			filp = ERR_PTR(-ELOOP);
			filp = ERR_PTR(-ELOOP);
			break;
			break;
		}
		}
@@ -2299,23 +2300,23 @@ static struct file *path_openat(int dfd, const char *pathname,
		 * have to putname() it when we are done. Procfs-like symlinks
		 * have to putname() it when we are done. Procfs-like symlinks
		 * just set LAST_BIND.
		 * just set LAST_BIND.
		 */
		 */
		nd.flags |= LOOKUP_PARENT;
		nd->flags |= LOOKUP_PARENT;
		nd.flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
		nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
		error = __do_follow_link(&link, &nd, &cookie);
		error = __do_follow_link(&link, nd, &cookie);
		if (unlikely(error))
		if (unlikely(error))
			filp = ERR_PTR(error);
			filp = ERR_PTR(error);
		else
		else
			filp = do_last(&nd, &path, op, pathname);
			filp = do_last(nd, &path, op, pathname);
		if (!IS_ERR(cookie) && linki->i_op->put_link)
		if (!IS_ERR(cookie) && linki->i_op->put_link)
			linki->i_op->put_link(link.dentry, &nd, cookie);
			linki->i_op->put_link(link.dentry, nd, cookie);
		path_put(&link);
		path_put(&link);
	}
	}
out:
out:
	if (nd.root.mnt && !(nd.flags & LOOKUP_ROOT))
	if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT))
		path_put(&nd.root);
		path_put(&nd->root);
	if (base)
	if (base)
		fput(base);
		fput(base);
	release_open_intent(&nd);
	release_open_intent(nd);
	return filp;
	return filp;


out_filp:
out_filp:
@@ -2326,16 +2327,39 @@ out_filp:
struct file *do_filp_open(int dfd, const char *pathname,
struct file *do_filp_open(int dfd, const char *pathname,
		const struct open_flags *op, int flags)
		const struct open_flags *op, int flags)
{
{
	struct nameidata nd;
	struct file *filp;
	struct file *filp;


	filp = path_openat(dfd, pathname, op, flags | LOOKUP_RCU);
	filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);
	if (unlikely(filp == ERR_PTR(-ECHILD)))
	if (unlikely(filp == ERR_PTR(-ECHILD)))
		filp = path_openat(dfd, pathname, op, flags);
		filp = path_openat(dfd, pathname, &nd, op, flags);
	if (unlikely(filp == ERR_PTR(-ESTALE)))
	if (unlikely(filp == ERR_PTR(-ESTALE)))
		filp = path_openat(dfd, pathname, op, flags | LOOKUP_REVAL);
		filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_REVAL);
	return filp;
	return filp;
}
}


struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
		const char *name, const struct open_flags *op, int flags)
{
	struct nameidata nd;
	struct file *file;

	nd.root.mnt = mnt;
	nd.root.dentry = dentry;

	flags |= LOOKUP_ROOT;

	if (dentry->d_inode->i_op->follow_link)
		return ERR_PTR(-ELOOP);

	file = path_openat(-1, name, &nd, op, flags | LOOKUP_RCU);
	if (unlikely(file == ERR_PTR(-ECHILD)))
		file = path_openat(-1, name, &nd, op, flags);
	if (unlikely(file == ERR_PTR(-ESTALE)))
		file = path_openat(-1, name, &nd, op, flags | LOOKUP_REVAL);
	return file;
}

/**
/**
 * lookup_create - lookup a dentry, creating it if it doesn't exist
 * lookup_create - lookup a dentry, creating it if it doesn't exist
 * @nd: nameidata info
 * @nd: nameidata info
+4 −17
Original line number Original line Diff line number Diff line
@@ -22,30 +22,17 @@


static struct file *do_open(char *name, int flags)
static struct file *do_open(char *name, int flags)
{
{
	struct nameidata nd;
	struct vfsmount *mnt;
	struct vfsmount *mnt;
	int error;
	struct file *file;


	mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
	mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
	if (IS_ERR(mnt))
	if (IS_ERR(mnt))
		return (struct file *)mnt;
		return (struct file *)mnt;


	error = vfs_path_lookup(mnt->mnt_root, mnt, name, 0, &nd);
	file = file_open_root(mnt->mnt_root, mnt, name, flags);
	mntput(mnt);	/* drop do_kern_mount reference */
	if (error)
		return ERR_PTR(error);

	if (flags == O_RDWR)
		error = may_open(&nd.path, MAY_READ|MAY_WRITE, flags);
	else
		error = may_open(&nd.path, MAY_WRITE, flags);


	if (!error)
	mntput(mnt);	/* drop do_kern_mount reference */
		return dentry_open(nd.path.dentry, nd.path.mnt, flags,
	return file;
				   current_cred());

	path_put(&nd.path);
	return ERR_PTR(error);
}
}


static struct {
static struct {
+14 −0
Original line number Original line Diff line number Diff line
@@ -959,6 +959,20 @@ struct file *filp_open(const char *filename, int flags, int mode)
}
}
EXPORT_SYMBOL(filp_open);
EXPORT_SYMBOL(filp_open);


struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
			    const char *filename, int flags)
{
	struct open_flags op;
	int lookup = build_open_flags(flags, 0, &op);
	if (flags & O_CREAT)
		return ERR_PTR(-EINVAL);
	if (!filename && (flags & O_DIRECTORY))
		if (!dentry->d_inode->i_op->lookup)
			return ERR_PTR(-ENOTDIR);
	return do_file_open_root(dentry, mnt, filename, &op, lookup);
}
EXPORT_SYMBOL(file_open_root);

long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
{
{
	struct open_flags op;
	struct open_flags op;
Loading