diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/namei.c b/fs/namei.c index ab4e48c4a80a..0e9d186b7f77 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4142,7 +4142,7 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname, bool should_retry = false; int error; - if (flags) + if (flags & ~RENAME_NOREPLACE) return -EINVAL; retry: @@ -4168,6 +4168,8 @@ retry: goto exit2; new_dir = newnd.path.dentry; + if (flags & RENAME_NOREPLACE) + error = -EEXIST; if (newnd.last_type != LAST_NORM) goto exit2; @@ -4190,22 +4192,25 @@ retry_deleg: error = -ENOENT; if (d_is_negative(old_dentry)) goto exit4; + new_dentry = lookup_hash(&newnd); + error = PTR_ERR(new_dentry); + if (IS_ERR(new_dentry)) + goto exit4; + error = -EEXIST; + if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) + goto exit5; /* unless the source is a directory trailing slashes give -ENOTDIR */ if (!d_is_dir(old_dentry)) { error = -ENOTDIR; if (oldnd.last.name[oldnd.last.len]) - goto exit4; + goto exit5; if (newnd.last.name[newnd.last.len]) - goto exit4; + goto exit5; } /* source should not be ancestor of target */ error = -EINVAL; if (old_dentry == trap) - goto exit4; - new_dentry = lookup_hash(&newnd); - error = PTR_ERR(new_dentry); - if (IS_ERR(new_dentry)) - goto exit4; + goto exit5; /* target should not be an ancestor of source */ error = -ENOTEMPTY; if (new_dentry == trap) |