diff options
author | Christoph Hellwig <hch@lst.de> | 2020-06-07 18:26:37 +0200 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2020-07-31 08:16:01 +0200 |
commit | 9d4b74aee80436d067d79a6c32ebb544b0ae5460 (patch) | |
tree | ea89c9c48a6adb7b19dcb52cd93ea6f4d85ca206 /fs/utimes.c | |
parent | 863b67e15177a7cd0c27b3e36e42fe7907dec9bd (diff) |
fs: refactor do_utimes
Split out one helper each for path vs fd based operations.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/utimes.c')
-rw-r--r-- | fs/utimes.c | 100 |
1 files changed, 54 insertions, 46 deletions
diff --git a/fs/utimes.c b/fs/utimes.c index b7b927502d6e..c667517b6eb1 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -70,6 +70,57 @@ out: return error; } +static int do_utimes_path(int dfd, const char __user *filename, + struct timespec64 *times, int flags) +{ + struct path path; + int lookup_flags = 0, error; + + if (times && + (!nsec_valid(times[0].tv_nsec) || !nsec_valid(times[1].tv_nsec))) + return -EINVAL; + if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) + return -EINVAL; + + if (!(flags & AT_SYMLINK_NOFOLLOW)) + lookup_flags |= LOOKUP_FOLLOW; + if (flags & AT_EMPTY_PATH) + lookup_flags |= LOOKUP_EMPTY; + +retry: + error = user_path_at(dfd, filename, lookup_flags, &path); + if (error) + return error; + + error = utimes_common(&path, times); + path_put(&path); + if (retry_estale(error, lookup_flags)) { + lookup_flags |= LOOKUP_REVAL; + goto retry; + } + + return error; +} + +static int do_utimes_fd(int fd, struct timespec64 *times, int flags) +{ + struct fd f; + int error; + + if (times && + (!nsec_valid(times[0].tv_nsec) || !nsec_valid(times[1].tv_nsec))) + return -EINVAL; + if (flags) + return -EINVAL; + + f = fdget(fd); + if (!f.file) + return -EBADF; + error = utimes_common(&f.file->f_path, times); + fdput(f); + return error; +} + /* * do_utimes - change times on filename or file descriptor * @dfd: open file descriptor, -1 or AT_FDCWD @@ -88,52 +139,9 @@ out: long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, int flags) { - int error = -EINVAL; - - if (times && (!nsec_valid(times[0].tv_nsec) || - !nsec_valid(times[1].tv_nsec))) { - goto out; - } - - if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) - goto out; - - if (filename == NULL && dfd != AT_FDCWD) { - struct fd f; - - if (flags) - goto out; - - f = fdget(dfd); - error = -EBADF; - if (!f.file) - goto out; - - error = utimes_common(&f.file->f_path, times); - fdput(f); - } else { - struct path path; - int lookup_flags = 0; - - if (!(flags & AT_SYMLINK_NOFOLLOW)) - lookup_flags |= LOOKUP_FOLLOW; - if (flags & AT_EMPTY_PATH) - lookup_flags |= LOOKUP_EMPTY; -retry: - error = user_path_at(dfd, filename, lookup_flags, &path); - if (error) - goto out; - - error = utimes_common(&path, times); - path_put(&path); - if (retry_estale(error, lookup_flags)) { - lookup_flags |= LOOKUP_REVAL; - goto retry; - } - } - -out: - return error; + if (filename == NULL && dfd != AT_FDCWD) + return do_utimes_fd(dfd, times, flags); + return do_utimes_path(dfd, filename, times, flags); } SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, |