return error;
}
-/*
- * Be careful about ever adding any more callers of this
- * function. Its flags must be in the namei format, not
- * what get passed to sys_open().
- */
-static int __open_namei_create(struct nameidata *nd, struct path *path,
- int open_flag, int mode)
-{
- int error;
- struct dentry *dir = nd->path.dentry;
-
- if (!IS_POSIXACL(dir->d_inode))
- mode &= ~current_umask();
- error = security_path_mknod(&nd->path, path->dentry, mode, 0);
- if (error)
- goto out_unlock;
- error = vfs_create(dir->d_inode, path->dentry, mode, nd);
-out_unlock:
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(nd->path.dentry);
- nd->path.dentry = path->dentry;
- return error;
-}
-
/*
* Note that while the flag value (low two bits) for sys_open means:
* 00 - read-only
return flag;
}
-static int open_will_truncate(int flag, struct inode *inode)
-{
- /*
- * We'll never write to the fs underlying
- * a device file.
- */
- if (special_file(inode->i_mode))
- return 0;
- return (flag & O_TRUNC);
-}
-
/*
* Handle the last step of open()
*/
const struct open_flags *op, const char *pathname)
{
struct dentry *dir = nd->path.dentry;
+ struct dentry *dentry;
int open_flag = op->open_flag;
- int will_truncate;
+ int will_truncate = open_flag & O_TRUNC;
int want_write = 0;
int skip_perm = 0;
struct file *filp;
mutex_lock(&dir->d_inode->i_mutex);
- path->dentry = lookup_hash(nd);
- path->mnt = nd->path.mnt;
-
- error = PTR_ERR(path->dentry);
- if (IS_ERR(path->dentry)) {
+ dentry = lookup_hash(nd);
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry)) {
mutex_unlock(&dir->d_inode->i_mutex);
goto exit;
}
+ path->dentry = dentry;
+ path->mnt = nd->path.mnt;
+
if (IS_ERR(nd->intent.open.file)) {
error = PTR_ERR(nd->intent.open.file);
goto exit_mutex_unlock;
}
/* Negative dentry, just create the file */
- if (!path->dentry->d_inode) {
+ if (!dentry->d_inode) {
+ int mode = op->mode;
+ if (!IS_POSIXACL(dir->d_inode))
+ mode &= ~current_umask();
/*
* This write is needed to ensure that a
- * ro->rw transition does not occur between
+ * rw->ro transition does not occur between
* the time when the file is created and when
* a permanent write count is taken through
* the 'struct file' in nameidata_to_filp().
if (error)
goto exit_mutex_unlock;
want_write = 1;
- will_truncate = 0;
- error = __open_namei_create(nd, path, open_flag, op->mode);
- if (error)
- goto exit;
/* Don't check for write permission, don't truncate */
open_flag &= ~O_TRUNC;
+ will_truncate = 0;
skip_perm = 1;
+ error = security_path_mknod(&nd->path, dentry, mode, 0);
+ if (error)
+ goto exit_mutex_unlock;
+ error = vfs_create(dir->d_inode, dentry, mode, nd);
+ if (error)
+ goto exit_mutex_unlock;
+ mutex_unlock(&dir->d_inode->i_mutex);
+ dput(nd->path.dentry);
+ nd->path.dentry = dentry;
goto common;
}
if (S_ISDIR(nd->inode->i_mode))
goto exit;
ok:
- will_truncate = open_will_truncate(open_flag, nd->path.dentry->d_inode);
+ if (!S_ISREG(nd->inode->i_mode))
+ will_truncate = 0;
+
if (will_truncate) {
error = mnt_want_write(nd->path.mnt);
if (error)