diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 315 |
1 files changed, 171 insertions, 144 deletions
diff --git a/fs/namei.c b/fs/namei.c index 4b491b431990..c1178880f23c 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1796,7 +1796,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1796 | if (err) | 1796 | if (err) |
1797 | return err; | 1797 | return err; |
1798 | } | 1798 | } |
1799 | if (!d_is_directory(nd->path.dentry)) { | 1799 | if (!d_can_lookup(nd->path.dentry)) { |
1800 | err = -ENOTDIR; | 1800 | err = -ENOTDIR; |
1801 | break; | 1801 | break; |
1802 | } | 1802 | } |
@@ -1817,7 +1817,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1817 | struct dentry *root = nd->root.dentry; | 1817 | struct dentry *root = nd->root.dentry; |
1818 | struct inode *inode = root->d_inode; | 1818 | struct inode *inode = root->d_inode; |
1819 | if (*name) { | 1819 | if (*name) { |
1820 | if (!d_is_directory(root)) | 1820 | if (!d_can_lookup(root)) |
1821 | return -ENOTDIR; | 1821 | return -ENOTDIR; |
1822 | retval = inode_permission(inode, MAY_EXEC); | 1822 | retval = inode_permission(inode, MAY_EXEC); |
1823 | if (retval) | 1823 | if (retval) |
@@ -1873,7 +1873,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1873 | dentry = f.file->f_path.dentry; | 1873 | dentry = f.file->f_path.dentry; |
1874 | 1874 | ||
1875 | if (*name) { | 1875 | if (*name) { |
1876 | if (!d_is_directory(dentry)) { | 1876 | if (!d_can_lookup(dentry)) { |
1877 | fdput(f); | 1877 | fdput(f); |
1878 | return -ENOTDIR; | 1878 | return -ENOTDIR; |
1879 | } | 1879 | } |
@@ -1955,7 +1955,7 @@ static int path_lookupat(int dfd, const char *name, | |||
1955 | err = complete_walk(nd); | 1955 | err = complete_walk(nd); |
1956 | 1956 | ||
1957 | if (!err && nd->flags & LOOKUP_DIRECTORY) { | 1957 | if (!err && nd->flags & LOOKUP_DIRECTORY) { |
1958 | if (!d_is_directory(nd->path.dentry)) { | 1958 | if (!d_can_lookup(nd->path.dentry)) { |
1959 | path_put(&nd->path); | 1959 | path_put(&nd->path); |
1960 | err = -ENOTDIR; | 1960 | err = -ENOTDIR; |
1961 | } | 1961 | } |
@@ -2414,11 +2414,11 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) | |||
2414 | IS_IMMUTABLE(inode) || IS_SWAPFILE(inode)) | 2414 | IS_IMMUTABLE(inode) || IS_SWAPFILE(inode)) |
2415 | return -EPERM; | 2415 | return -EPERM; |
2416 | if (isdir) { | 2416 | if (isdir) { |
2417 | if (!d_is_directory(victim) && !d_is_autodir(victim)) | 2417 | if (!d_is_dir(victim)) |
2418 | return -ENOTDIR; | 2418 | return -ENOTDIR; |
2419 | if (IS_ROOT(victim)) | 2419 | if (IS_ROOT(victim)) |
2420 | return -EBUSY; | 2420 | return -EBUSY; |
2421 | } else if (d_is_directory(victim) || d_is_autodir(victim)) | 2421 | } else if (d_is_dir(victim)) |
2422 | return -EISDIR; | 2422 | return -EISDIR; |
2423 | if (IS_DEADDIR(dir)) | 2423 | if (IS_DEADDIR(dir)) |
2424 | return -ENOENT; | 2424 | return -ENOENT; |
@@ -3016,11 +3016,10 @@ finish_open: | |||
3016 | } | 3016 | } |
3017 | audit_inode(name, nd->path.dentry, 0); | 3017 | audit_inode(name, nd->path.dentry, 0); |
3018 | error = -EISDIR; | 3018 | error = -EISDIR; |
3019 | if ((open_flag & O_CREAT) && | 3019 | if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry)) |
3020 | (d_is_directory(nd->path.dentry) || d_is_autodir(nd->path.dentry))) | ||
3021 | goto out; | 3020 | goto out; |
3022 | error = -ENOTDIR; | 3021 | error = -ENOTDIR; |
3023 | if ((nd->flags & LOOKUP_DIRECTORY) && !d_is_directory(nd->path.dentry)) | 3022 | if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry)) |
3024 | goto out; | 3023 | goto out; |
3025 | if (!S_ISREG(nd->inode->i_mode)) | 3024 | if (!S_ISREG(nd->inode->i_mode)) |
3026 | will_truncate = false; | 3025 | will_truncate = false; |
@@ -3744,7 +3743,7 @@ exit1: | |||
3744 | slashes: | 3743 | slashes: |
3745 | if (d_is_negative(dentry)) | 3744 | if (d_is_negative(dentry)) |
3746 | error = -ENOENT; | 3745 | error = -ENOENT; |
3747 | else if (d_is_directory(dentry) || d_is_autodir(dentry)) | 3746 | else if (d_is_dir(dentry)) |
3748 | error = -EISDIR; | 3747 | error = -EISDIR; |
3749 | else | 3748 | else |
3750 | error = -ENOTDIR; | 3749 | error = -ENOTDIR; |
@@ -3974,7 +3973,28 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname | |||
3974 | return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0); | 3973 | return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0); |
3975 | } | 3974 | } |
3976 | 3975 | ||
3977 | /* | 3976 | /** |
3977 | * vfs_rename - rename a filesystem object | ||
3978 | * @old_dir: parent of source | ||
3979 | * @old_dentry: source | ||
3980 | * @new_dir: parent of destination | ||
3981 | * @new_dentry: destination | ||
3982 | * @delegated_inode: returns an inode needing a delegation break | ||
3983 | * @flags: rename flags | ||
3984 | * | ||
3985 | * The caller must hold multiple mutexes--see lock_rename()). | ||
3986 | * | ||
3987 | * If vfs_rename discovers a delegation in need of breaking at either | ||
3988 | * the source or destination, it will return -EWOULDBLOCK and return a | ||
3989 | * reference to the inode in delegated_inode. The caller should then | ||
3990 | * break the delegation and retry. Because breaking a delegation may | ||
3991 | * take a long time, the caller should drop all locks before doing | ||
3992 | * so. | ||
3993 | * | ||
3994 | * Alternatively, a caller may pass NULL for delegated_inode. This may | ||
3995 | * be appropriate for callers that expect the underlying filesystem not | ||
3996 | * to be NFS exported. | ||
3997 | * | ||
3978 | * The worst of all namespace operations - renaming directory. "Perverted" | 3998 | * The worst of all namespace operations - renaming directory. "Perverted" |
3979 | * doesn't even start to describe it. Somebody in UCB had a heck of a trip... | 3999 | * doesn't even start to describe it. Somebody in UCB had a heck of a trip... |
3980 | * Problems: | 4000 | * Problems: |
@@ -4002,163 +4022,139 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname | |||
4002 | * ->i_mutex on parents, which works but leads to some truly excessive | 4022 | * ->i_mutex on parents, which works but leads to some truly excessive |
4003 | * locking]. | 4023 | * locking]. |
4004 | */ | 4024 | */ |
4005 | static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, | 4025 | int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
4006 | struct inode *new_dir, struct dentry *new_dentry) | 4026 | struct inode *new_dir, struct dentry *new_dentry, |
4027 | struct inode **delegated_inode, unsigned int flags) | ||
4007 | { | 4028 | { |
4008 | int error = 0; | 4029 | int error; |
4030 | bool is_dir = d_is_dir(old_dentry); | ||
4031 | const unsigned char *old_name; | ||
4032 | struct inode *source = old_dentry->d_inode; | ||
4009 | struct inode *target = new_dentry->d_inode; | 4033 | struct inode *target = new_dentry->d_inode; |
4034 | bool new_is_dir = false; | ||
4010 | unsigned max_links = new_dir->i_sb->s_max_links; | 4035 | unsigned max_links = new_dir->i_sb->s_max_links; |
4011 | 4036 | ||
4037 | if (source == target) | ||
4038 | return 0; | ||
4039 | |||
4040 | error = may_delete(old_dir, old_dentry, is_dir); | ||
4041 | if (error) | ||
4042 | return error; | ||
4043 | |||
4044 | if (!target) { | ||
4045 | error = may_create(new_dir, new_dentry); | ||
4046 | } else { | ||
4047 | new_is_dir = d_is_dir(new_dentry); | ||
4048 | |||
4049 | if (!(flags & RENAME_EXCHANGE)) | ||
4050 | error = may_delete(new_dir, new_dentry, is_dir); | ||
4051 | else | ||
4052 | error = may_delete(new_dir, new_dentry, new_is_dir); | ||
4053 | } | ||
4054 | if (error) | ||
4055 | return error; | ||
4056 | |||
4057 | if (!old_dir->i_op->rename) | ||
4058 | return -EPERM; | ||
4059 | |||
4060 | if (flags && !old_dir->i_op->rename2) | ||
4061 | return -EINVAL; | ||
4062 | |||
4012 | /* | 4063 | /* |
4013 | * If we are going to change the parent - check write permissions, | 4064 | * If we are going to change the parent - check write permissions, |
4014 | * we'll need to flip '..'. | 4065 | * we'll need to flip '..'. |
4015 | */ | 4066 | */ |
4016 | if (new_dir != old_dir) { | 4067 | if (new_dir != old_dir) { |
4017 | error = inode_permission(old_dentry->d_inode, MAY_WRITE); | 4068 | if (is_dir) { |
4018 | if (error) | 4069 | error = inode_permission(source, MAY_WRITE); |
4019 | return error; | 4070 | if (error) |
4071 | return error; | ||
4072 | } | ||
4073 | if ((flags & RENAME_EXCHANGE) && new_is_dir) { | ||
4074 | error = inode_permission(target, MAY_WRITE); | ||
4075 | if (error) | ||
4076 | return error; | ||
4077 | } | ||
4020 | } | 4078 | } |
4021 | 4079 | ||
4022 | error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry); | 4080 | error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry, |
4081 | flags); | ||
4023 | if (error) | 4082 | if (error) |
4024 | return error; | 4083 | return error; |
4025 | 4084 | ||
4085 | old_name = fsnotify_oldname_init(old_dentry->d_name.name); | ||
4026 | dget(new_dentry); | 4086 | dget(new_dentry); |
4027 | if (target) | 4087 | if (!is_dir || (flags & RENAME_EXCHANGE)) |
4088 | lock_two_nondirectories(source, target); | ||
4089 | else if (target) | ||
4028 | mutex_lock(&target->i_mutex); | 4090 | mutex_lock(&target->i_mutex); |
4029 | 4091 | ||
4030 | error = -EBUSY; | 4092 | error = -EBUSY; |
4031 | if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry)) | 4093 | if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry)) |
4032 | goto out; | 4094 | goto out; |
4033 | 4095 | ||
4034 | error = -EMLINK; | 4096 | if (max_links && new_dir != old_dir) { |
4035 | if (max_links && !target && new_dir != old_dir && | 4097 | error = -EMLINK; |
4036 | new_dir->i_nlink >= max_links) | 4098 | if (is_dir && !new_is_dir && new_dir->i_nlink >= max_links) |
4037 | goto out; | 4099 | goto out; |
4038 | 4100 | if ((flags & RENAME_EXCHANGE) && !is_dir && new_is_dir && | |
4039 | if (target) | 4101 | old_dir->i_nlink >= max_links) |
4102 | goto out; | ||
4103 | } | ||
4104 | if (is_dir && !(flags & RENAME_EXCHANGE) && target) | ||
4040 | shrink_dcache_parent(new_dentry); | 4105 | shrink_dcache_parent(new_dentry); |
4041 | error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); | 4106 | if (!is_dir) { |
4042 | if (error) | 4107 | error = try_break_deleg(source, delegated_inode); |
4043 | goto out; | 4108 | if (error) |
4044 | 4109 | goto out; | |
4045 | if (target) { | ||
4046 | target->i_flags |= S_DEAD; | ||
4047 | dont_mount(new_dentry); | ||
4048 | } | 4110 | } |
4049 | out: | 4111 | if (target && !new_is_dir) { |
4050 | if (target) | ||
4051 | mutex_unlock(&target->i_mutex); | ||
4052 | dput(new_dentry); | ||
4053 | if (!error) | ||
4054 | if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) | ||
4055 | d_move(old_dentry,new_dentry); | ||
4056 | return error; | ||
4057 | } | ||
4058 | |||
4059 | static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, | ||
4060 | struct inode *new_dir, struct dentry *new_dentry, | ||
4061 | struct inode **delegated_inode) | ||
4062 | { | ||
4063 | struct inode *target = new_dentry->d_inode; | ||
4064 | struct inode *source = old_dentry->d_inode; | ||
4065 | int error; | ||
4066 | |||
4067 | error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry); | ||
4068 | if (error) | ||
4069 | return error; | ||
4070 | |||
4071 | dget(new_dentry); | ||
4072 | lock_two_nondirectories(source, target); | ||
4073 | |||
4074 | error = -EBUSY; | ||
4075 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) | ||
4076 | goto out; | ||
4077 | |||
4078 | error = try_break_deleg(source, delegated_inode); | ||
4079 | if (error) | ||
4080 | goto out; | ||
4081 | if (target) { | ||
4082 | error = try_break_deleg(target, delegated_inode); | 4112 | error = try_break_deleg(target, delegated_inode); |
4083 | if (error) | 4113 | if (error) |
4084 | goto out; | 4114 | goto out; |
4085 | } | 4115 | } |
4086 | error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); | 4116 | if (!flags) { |
4117 | error = old_dir->i_op->rename(old_dir, old_dentry, | ||
4118 | new_dir, new_dentry); | ||
4119 | } else { | ||
4120 | error = old_dir->i_op->rename2(old_dir, old_dentry, | ||
4121 | new_dir, new_dentry, flags); | ||
4122 | } | ||
4087 | if (error) | 4123 | if (error) |
4088 | goto out; | 4124 | goto out; |
4089 | 4125 | ||
4090 | if (target) | 4126 | if (!(flags & RENAME_EXCHANGE) && target) { |
4127 | if (is_dir) | ||
4128 | target->i_flags |= S_DEAD; | ||
4091 | dont_mount(new_dentry); | 4129 | dont_mount(new_dentry); |
4092 | if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) | 4130 | } |
4093 | d_move(old_dentry, new_dentry); | 4131 | if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) { |
4132 | if (!(flags & RENAME_EXCHANGE)) | ||
4133 | d_move(old_dentry, new_dentry); | ||
4134 | else | ||
4135 | d_exchange(old_dentry, new_dentry); | ||
4136 | } | ||
4094 | out: | 4137 | out: |
4095 | unlock_two_nondirectories(source, target); | 4138 | if (!is_dir || (flags & RENAME_EXCHANGE)) |
4139 | unlock_two_nondirectories(source, target); | ||
4140 | else if (target) | ||
4141 | mutex_unlock(&target->i_mutex); | ||
4096 | dput(new_dentry); | 4142 | dput(new_dentry); |
4097 | return error; | 4143 | if (!error) { |
4098 | } | ||
4099 | |||
4100 | /** | ||
4101 | * vfs_rename - rename a filesystem object | ||
4102 | * @old_dir: parent of source | ||
4103 | * @old_dentry: source | ||
4104 | * @new_dir: parent of destination | ||
4105 | * @new_dentry: destination | ||
4106 | * @delegated_inode: returns an inode needing a delegation break | ||
4107 | * | ||
4108 | * The caller must hold multiple mutexes--see lock_rename()). | ||
4109 | * | ||
4110 | * If vfs_rename discovers a delegation in need of breaking at either | ||
4111 | * the source or destination, it will return -EWOULDBLOCK and return a | ||
4112 | * reference to the inode in delegated_inode. The caller should then | ||
4113 | * break the delegation and retry. Because breaking a delegation may | ||
4114 | * take a long time, the caller should drop all locks before doing | ||
4115 | * so. | ||
4116 | * | ||
4117 | * Alternatively, a caller may pass NULL for delegated_inode. This may | ||
4118 | * be appropriate for callers that expect the underlying filesystem not | ||
4119 | * to be NFS exported. | ||
4120 | */ | ||
4121 | int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
4122 | struct inode *new_dir, struct dentry *new_dentry, | ||
4123 | struct inode **delegated_inode) | ||
4124 | { | ||
4125 | int error; | ||
4126 | int is_dir = d_is_directory(old_dentry) || d_is_autodir(old_dentry); | ||
4127 | const unsigned char *old_name; | ||
4128 | |||
4129 | if (old_dentry->d_inode == new_dentry->d_inode) | ||
4130 | return 0; | ||
4131 | |||
4132 | error = may_delete(old_dir, old_dentry, is_dir); | ||
4133 | if (error) | ||
4134 | return error; | ||
4135 | |||
4136 | if (!new_dentry->d_inode) | ||
4137 | error = may_create(new_dir, new_dentry); | ||
4138 | else | ||
4139 | error = may_delete(new_dir, new_dentry, is_dir); | ||
4140 | if (error) | ||
4141 | return error; | ||
4142 | |||
4143 | if (!old_dir->i_op->rename) | ||
4144 | return -EPERM; | ||
4145 | |||
4146 | old_name = fsnotify_oldname_init(old_dentry->d_name.name); | ||
4147 | |||
4148 | if (is_dir) | ||
4149 | error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry); | ||
4150 | else | ||
4151 | error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,delegated_inode); | ||
4152 | if (!error) | ||
4153 | fsnotify_move(old_dir, new_dir, old_name, is_dir, | 4144 | fsnotify_move(old_dir, new_dir, old_name, is_dir, |
4154 | new_dentry->d_inode, old_dentry); | 4145 | !(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry); |
4146 | if (flags & RENAME_EXCHANGE) { | ||
4147 | fsnotify_move(new_dir, old_dir, old_dentry->d_name.name, | ||
4148 | new_is_dir, NULL, new_dentry); | ||
4149 | } | ||
4150 | } | ||
4155 | fsnotify_oldname_free(old_name); | 4151 | fsnotify_oldname_free(old_name); |
4156 | 4152 | ||
4157 | return error; | 4153 | return error; |
4158 | } | 4154 | } |
4159 | 4155 | ||
4160 | SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | 4156 | SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname, |
4161 | int, newdfd, const char __user *, newname) | 4157 | int, newdfd, const char __user *, newname, unsigned int, flags) |
4162 | { | 4158 | { |
4163 | struct dentry *old_dir, *new_dir; | 4159 | struct dentry *old_dir, *new_dir; |
4164 | struct dentry *old_dentry, *new_dentry; | 4160 | struct dentry *old_dentry, *new_dentry; |
@@ -4170,6 +4166,13 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | |||
4170 | unsigned int lookup_flags = 0; | 4166 | unsigned int lookup_flags = 0; |
4171 | bool should_retry = false; | 4167 | bool should_retry = false; |
4172 | int error; | 4168 | int error; |
4169 | |||
4170 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) | ||
4171 | return -EINVAL; | ||
4172 | |||
4173 | if ((flags & RENAME_NOREPLACE) && (flags & RENAME_EXCHANGE)) | ||
4174 | return -EINVAL; | ||
4175 | |||
4173 | retry: | 4176 | retry: |
4174 | from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags); | 4177 | from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags); |
4175 | if (IS_ERR(from)) { | 4178 | if (IS_ERR(from)) { |
@@ -4193,6 +4196,8 @@ retry: | |||
4193 | goto exit2; | 4196 | goto exit2; |
4194 | 4197 | ||
4195 | new_dir = newnd.path.dentry; | 4198 | new_dir = newnd.path.dentry; |
4199 | if (flags & RENAME_NOREPLACE) | ||
4200 | error = -EEXIST; | ||
4196 | if (newnd.last_type != LAST_NORM) | 4201 | if (newnd.last_type != LAST_NORM) |
4197 | goto exit2; | 4202 | goto exit2; |
4198 | 4203 | ||
@@ -4202,7 +4207,8 @@ retry: | |||
4202 | 4207 | ||
4203 | oldnd.flags &= ~LOOKUP_PARENT; | 4208 | oldnd.flags &= ~LOOKUP_PARENT; |
4204 | newnd.flags &= ~LOOKUP_PARENT; | 4209 | newnd.flags &= ~LOOKUP_PARENT; |
4205 | newnd.flags |= LOOKUP_RENAME_TARGET; | 4210 | if (!(flags & RENAME_EXCHANGE)) |
4211 | newnd.flags |= LOOKUP_RENAME_TARGET; | ||
4206 | 4212 | ||
4207 | retry_deleg: | 4213 | retry_deleg: |
4208 | trap = lock_rename(new_dir, old_dir); | 4214 | trap = lock_rename(new_dir, old_dir); |
@@ -4215,34 +4221,49 @@ retry_deleg: | |||
4215 | error = -ENOENT; | 4221 | error = -ENOENT; |
4216 | if (d_is_negative(old_dentry)) | 4222 | if (d_is_negative(old_dentry)) |
4217 | goto exit4; | 4223 | goto exit4; |
4224 | new_dentry = lookup_hash(&newnd); | ||
4225 | error = PTR_ERR(new_dentry); | ||
4226 | if (IS_ERR(new_dentry)) | ||
4227 | goto exit4; | ||
4228 | error = -EEXIST; | ||
4229 | if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) | ||
4230 | goto exit5; | ||
4231 | if (flags & RENAME_EXCHANGE) { | ||
4232 | error = -ENOENT; | ||
4233 | if (d_is_negative(new_dentry)) | ||
4234 | goto exit5; | ||
4235 | |||
4236 | if (!d_is_dir(new_dentry)) { | ||
4237 | error = -ENOTDIR; | ||
4238 | if (newnd.last.name[newnd.last.len]) | ||
4239 | goto exit5; | ||
4240 | } | ||
4241 | } | ||
4218 | /* unless the source is a directory trailing slashes give -ENOTDIR */ | 4242 | /* unless the source is a directory trailing slashes give -ENOTDIR */ |
4219 | if (!d_is_directory(old_dentry) && !d_is_autodir(old_dentry)) { | 4243 | if (!d_is_dir(old_dentry)) { |
4220 | error = -ENOTDIR; | 4244 | error = -ENOTDIR; |
4221 | if (oldnd.last.name[oldnd.last.len]) | 4245 | if (oldnd.last.name[oldnd.last.len]) |
4222 | goto exit4; | 4246 | goto exit5; |
4223 | if (newnd.last.name[newnd.last.len]) | 4247 | if (!(flags & RENAME_EXCHANGE) && newnd.last.name[newnd.last.len]) |
4224 | goto exit4; | 4248 | goto exit5; |
4225 | } | 4249 | } |
4226 | /* source should not be ancestor of target */ | 4250 | /* source should not be ancestor of target */ |
4227 | error = -EINVAL; | 4251 | error = -EINVAL; |
4228 | if (old_dentry == trap) | 4252 | if (old_dentry == trap) |
4229 | goto exit4; | 4253 | goto exit5; |
4230 | new_dentry = lookup_hash(&newnd); | ||
4231 | error = PTR_ERR(new_dentry); | ||
4232 | if (IS_ERR(new_dentry)) | ||
4233 | goto exit4; | ||
4234 | /* target should not be an ancestor of source */ | 4254 | /* target should not be an ancestor of source */ |
4235 | error = -ENOTEMPTY; | 4255 | if (!(flags & RENAME_EXCHANGE)) |
4256 | error = -ENOTEMPTY; | ||
4236 | if (new_dentry == trap) | 4257 | if (new_dentry == trap) |
4237 | goto exit5; | 4258 | goto exit5; |
4238 | 4259 | ||
4239 | error = security_path_rename(&oldnd.path, old_dentry, | 4260 | error = security_path_rename(&oldnd.path, old_dentry, |
4240 | &newnd.path, new_dentry); | 4261 | &newnd.path, new_dentry, flags); |
4241 | if (error) | 4262 | if (error) |
4242 | goto exit5; | 4263 | goto exit5; |
4243 | error = vfs_rename(old_dir->d_inode, old_dentry, | 4264 | error = vfs_rename(old_dir->d_inode, old_dentry, |
4244 | new_dir->d_inode, new_dentry, | 4265 | new_dir->d_inode, new_dentry, |
4245 | &delegated_inode); | 4266 | &delegated_inode, flags); |
4246 | exit5: | 4267 | exit5: |
4247 | dput(new_dentry); | 4268 | dput(new_dentry); |
4248 | exit4: | 4269 | exit4: |
@@ -4272,9 +4293,15 @@ exit: | |||
4272 | return error; | 4293 | return error; |
4273 | } | 4294 | } |
4274 | 4295 | ||
4296 | SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | ||
4297 | int, newdfd, const char __user *, newname) | ||
4298 | { | ||
4299 | return sys_renameat2(olddfd, oldname, newdfd, newname, 0); | ||
4300 | } | ||
4301 | |||
4275 | SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname) | 4302 | SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname) |
4276 | { | 4303 | { |
4277 | return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname); | 4304 | return sys_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0); |
4278 | } | 4305 | } |
4279 | 4306 | ||
4280 | int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) | 4307 | int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) |