Commit 9d4b74ae authored by Christoph Hellwig's avatar Christoph Hellwig

fs: refactor do_utimes

Split out one helper each for path vs fd based operations.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 863b67e1
......@@ -70,59 +70,27 @@ static int utimes_common(const struct path *path, struct timespec64 *times)
return error;
}
/*
* do_utimes - change times on filename or file descriptor
* @dfd: open file descriptor, -1 or AT_FDCWD
* @filename: path name or NULL
* @times: new times or NULL
* @flags: zero or more flags (only AT_SYMLINK_NOFOLLOW for the moment)
*
* If filename is NULL and dfd refers to an open file, then operate on
* the file. Otherwise look up filename, possibly using dfd as a
* starting point.
*
* If times==NULL, set access and modification to current time,
* must be owner or have write permission.
* Else, update from *times, must be owner or super user.
*/
long do_utimes(int dfd, const char __user *filename, struct timespec64 *times,
int flags)
static int do_utimes_path(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;
}
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))
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;
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)
goto out;
return error;
error = utimes_common(&path, times);
path_put(&path);
......@@ -130,12 +98,52 @@ long do_utimes(int dfd, const char __user *filename, struct timespec64 *times,
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
}
out:
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
* @filename: path name or NULL
* @times: new times or NULL
* @flags: zero or more flags (only AT_SYMLINK_NOFOLLOW for the moment)
*
* If filename is NULL and dfd refers to an open file, then operate on
* the file. Otherwise look up filename, possibly using dfd as a
* starting point.
*
* If times==NULL, set access and modification to current time,
* must be owner or have write permission.
* Else, update from *times, must be owner or super user.
*/
long do_utimes(int dfd, const char __user *filename, struct timespec64 *times,
int flags)
{
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,
struct __kernel_timespec __user *, utimes, int, flags)
{
......
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