Release 4.11 fs/utimes.c
#include <linux/compiler.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/linkage.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/utime.h>
#include <linux/syscalls.h>
#include <linux/uaccess.h>
#include <asm/unistd.h>
#ifdef __ARCH_WANT_SYS_UTIME
/*
* sys_utime() can be implemented in user-level using sys_utimes().
* Is this for backwards compatibility? If so, why not move it
* into the appropriate arch directory (for those architectures that
* need it).
*/
/* 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.
*/
SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times)
{
struct timespec tv[2];
if (times) {
if (get_user(tv[0].tv_sec, ×->actime) ||
get_user(tv[1].tv_sec, ×->modtime))
return -EFAULT;
tv[0].tv_nsec = 0;
tv[1].tv_nsec = 0;
}
return do_utimes(AT_FDCWD, filename, times ? tv : NULL, 0);
}
#endif
static bool nsec_valid(long nsec)
{
if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
return true;
return nsec >= 0 && nsec <= 999999999;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Miklos Szeredi | 28 | 90.32% | 1 | 50.00% |
Michael Kerrisk | 3 | 9.68% | 1 | 50.00% |
Total | 31 | 100.00% | 2 | 100.00% |
static int utimes_common(const struct path *path, struct timespec *times)
{
int error;
struct iattr newattrs;
struct inode *inode = path->dentry->d_inode;
struct inode *delegated_inode = NULL;
error = mnt_want_write(path->mnt);
if (error)
goto out;
if (times && times[0].tv_nsec == UTIME_NOW &&
times[1].tv_nsec == UTIME_NOW)
times = NULL;
newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
if (times) {
if (times[0].tv_nsec == UTIME_OMIT)
newattrs.ia_valid &= ~ATTR_ATIME;
else if (times[0].tv_nsec != UTIME_NOW) {
newattrs.ia_atime.tv_sec = times[0].tv_sec;
newattrs.ia_atime.tv_nsec = times[0].tv_nsec;
newattrs.ia_valid |= ATTR_ATIME_SET;
}
if (times[1].tv_nsec == UTIME_OMIT)
newattrs.ia_valid &= ~ATTR_MTIME;
else if (times[1].tv_nsec != UTIME_NOW) {
newattrs.ia_mtime.tv_sec = times[1].tv_sec;
newattrs.ia_mtime.tv_nsec = times[1].tv_nsec;
newattrs.ia_valid |= ATTR_MTIME_SET;
}
/*
* Tell setattr_prepare(), that this is an explicit time
* update, even if neither ATTR_ATIME_SET nor ATTR_MTIME_SET
* were used.
*/
newattrs.ia_valid |= ATTR_TIMES_SET;
} else {
newattrs.ia_valid |= ATTR_TOUCH;
}
retry_deleg:
inode_lock(inode);
error = notify_change(path->dentry, &newattrs, &delegated_inode);
inode_unlock(inode);
if (delegated_inode) {
error = break_deleg_wait(&delegated_inode);
if (!error)
goto retry_deleg;
}
mnt_drop_write(path->mnt);
out:
return error;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Alexey Dobriyan | 117 | 38.36% | 1 | 7.14% |
Ulrich Drepper | 76 | 24.92% | 1 | 7.14% |
J. Bruce Fields | 34 | 11.15% | 1 | 7.14% |
Miklos Szeredi | 33 | 10.82% | 4 | 28.57% |
Michael Kerrisk | 28 | 9.18% | 2 | 14.29% |
Dave Hansen | 11 | 3.61% | 1 | 7.14% |
Al Viro | 3 | 0.98% | 2 | 14.29% |
Linus Torvalds | 2 | 0.66% | 1 | 7.14% |
Jan Kara | 1 | 0.33% | 1 | 7.14% |
Total | 305 | 100.00% | 14 | 100.00% |
/*
* 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 timespec *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)
goto out;
if (filename == NULL && dfd != AT_FDCWD) {
struct fd f;
if (flags & AT_SYMLINK_NOFOLLOW)
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;
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;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Miklos Szeredi | 170 | 75.89% | 1 | 12.50% |
Jeff Layton | 20 | 8.93% | 1 | 12.50% |
Al Viro | 14 | 6.25% | 2 | 25.00% |
Alexey Dobriyan | 10 | 4.46% | 1 | 12.50% |
Ulrich Drepper | 7 | 3.12% | 1 | 12.50% |
Jan Blunck | 2 | 0.89% | 1 | 12.50% |
David Howells | 1 | 0.45% | 1 | 12.50% |
Total | 224 | 100.00% | 8 | 100.00% |
SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename,
struct timespec __user *, utimes, int, flags)
{
struct timespec tstimes[2];
if (utimes) {
if (copy_from_user(&tstimes, utimes, sizeof(tstimes)))
return -EFAULT;
/* Nothing to do, we must not even check the path. */
if (tstimes[0].tv_nsec == UTIME_OMIT &&
tstimes[1].tv_nsec == UTIME_OMIT)
return 0;
}
return do_utimes(dfd, filename, utimes ? tstimes : NULL, flags);
}
SYSCALL_DEFINE3(futimesat, int, dfd, const char __user *, filename,
struct timeval __user *, utimes)
{
struct timeval times[2];
struct timespec tstimes[2];
if (utimes) {
if (copy_from_user(×, utimes, sizeof(times)))
return -EFAULT;
/* This test is needed to catch all invalid values. If we
would test only in do_utimes we would miss those invalid
values truncated by the multiplication with 1000. Note
that we also catch UTIME_{NOW,OMIT} here which are only
valid for utimensat. */
if (times[0].tv_usec >= 1000000 || times[0].tv_usec < 0 ||
times[1].tv_usec >= 1000000 || times[1].tv_usec < 0)
return -EINVAL;
tstimes[0].tv_sec = times[0].tv_sec;
tstimes[0].tv_nsec = 1000 * times[0].tv_usec;
tstimes[1].tv_sec = times[1].tv_sec;
tstimes[1].tv_nsec = 1000 * times[1].tv_usec;
}
return do_utimes(dfd, filename, utimes ? tstimes : NULL, 0);
}
SYSCALL_DEFINE2(utimes, char __user *, filename,
struct timeval __user *, utimes)
{
return sys_futimesat(AT_FDCWD, filename, utimes);
}
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ulrich Drepper | 322 | 32.36% | 1 | 4.00% |
Alexey Dobriyan | 252 | 25.33% | 1 | 4.00% |
Miklos Szeredi | 232 | 23.32% | 5 | 20.00% |
Heiko Carstens | 58 | 5.83% | 2 | 8.00% |
J. Bruce Fields | 34 | 3.42% | 1 | 4.00% |
Michael Kerrisk | 31 | 3.12% | 2 | 8.00% |
Al Viro | 20 | 2.01% | 5 | 20.00% |
Jeff Layton | 20 | 2.01% | 1 | 4.00% |
Dave Hansen | 14 | 1.41% | 1 | 4.00% |
Linus Torvalds | 3 | 0.30% | 2 | 8.00% |
David Howells | 3 | 0.30% | 1 | 4.00% |
Adrian Bunk | 3 | 0.30% | 1 | 4.00% |
Jan Blunck | 2 | 0.20% | 1 | 4.00% |
Jan Kara | 1 | 0.10% | 1 | 4.00% |
Total | 995 | 100.00% | 25 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.