Commit 6ac08709 authored by Al Viro's avatar Al Viro

path_openat(): take O_PATH handling out of do_last()

do_last() and lookup_open() simpler that way and so does O_PATH
itself.  As it bloody well should: we find what the pathname
resolves to, same way as in stat() et.al. and associate it with
FMODE_PATH struct file.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3b0a3c1a
...@@ -3019,7 +3019,7 @@ static int lookup_open(struct nameidata *nd, struct path *path, ...@@ -3019,7 +3019,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
goto out_no_open; goto out_no_open;
} }
if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) { if (dir_inode->i_op->atomic_open) {
return atomic_open(nd, dentry, path, file, op, got_write, return atomic_open(nd, dentry, path, file, op, got_write,
need_lookup, opened); need_lookup, opened);
} }
...@@ -3219,7 +3219,7 @@ static int do_last(struct nameidata *nd, ...@@ -3219,7 +3219,7 @@ static int do_last(struct nameidata *nd,
return error; return error;
} }
audit_inode(nd->name, nd->path.dentry, 0); audit_inode(nd->name, nd->path.dentry, 0);
if (unlikely(d_is_symlink(nd->path.dentry)) && !(open_flag & O_PATH)) { if (unlikely(d_is_symlink(nd->path.dentry))) {
error = -ELOOP; error = -ELOOP;
goto out; goto out;
} }
...@@ -3239,11 +3239,9 @@ static int do_last(struct nameidata *nd, ...@@ -3239,11 +3239,9 @@ static int do_last(struct nameidata *nd,
got_write = true; got_write = true;
} }
finish_open_created: finish_open_created:
if (likely(!(open_flag & O_PATH))) { error = may_open(&nd->path, acc_mode, open_flag);
error = may_open(&nd->path, acc_mode, open_flag); if (error)
if (error) goto out;
goto out;
}
BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */ BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
error = vfs_open(&nd->path, file, current_cred()); error = vfs_open(&nd->path, file, current_cred());
if (!error) { if (!error) {
...@@ -3357,6 +3355,18 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags, ...@@ -3357,6 +3355,18 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
return error; return error;
} }
static int do_o_path(struct nameidata *nd, unsigned flags, struct file *file)
{
struct path path;
int error = path_lookupat(nd, flags, &path);
if (!error) {
audit_inode(nd->name, path.dentry, 0);
error = vfs_open(&path, file, current_cred());
path_put(&path);
}
return error;
}
static struct file *path_openat(struct nameidata *nd, static struct file *path_openat(struct nameidata *nd,
const struct open_flags *op, unsigned flags) const struct open_flags *op, unsigned flags)
{ {
...@@ -3376,6 +3386,13 @@ static struct file *path_openat(struct nameidata *nd, ...@@ -3376,6 +3386,13 @@ static struct file *path_openat(struct nameidata *nd,
goto out2; goto out2;
} }
if (unlikely(file->f_flags & O_PATH)) {
error = do_o_path(nd, flags, file);
if (!error)
opened |= FILE_OPENED;
goto out2;
}
s = path_init(nd, flags); s = path_init(nd, flags);
if (IS_ERR(s)) { if (IS_ERR(s)) {
put_filp(file); put_filp(file);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment