cregit-Linux how code gets into the kernel

Release 4.7 fs/utimes.c

Directory: fs
#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 <asm/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, &times->actime) ||
		    get_user(tv[1].tv_sec, &times->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

PersonTokensPropCommitsCommitProp
miklos szeredimiklos szeredi2890.32%150.00%
michael kerriskmichael kerrisk39.68%150.00%
Total31100.00%2100.00%


static int utimes_common(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 inode_change_ok(), 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 { /* * If times is NULL (or both times are UTIME_NOW), * then we need to check permissions, because * inode_change_ok() won't do it. */ error = -EACCES; if (IS_IMMUTABLE(inode)) goto mnt_drop_write_and_out; if (!inode_owner_or_capable(inode)) { error = inode_permission(inode, MAY_WRITE); if (error) goto mnt_drop_write_and_out; } } 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_and_out: mnt_drop_write(path->mnt); out: return error; }

Contributors

PersonTokensPropCommitsCommitProp
alexey dobriyanalexey dobriyan14341.81%16.25%
ulrich drepperulrich drepper7622.22%16.25%
j. bruce fieldsj. bruce fields349.94%16.25%
michael kerriskmichael kerrisk308.77%318.75%
miklos szeredimiklos szeredi298.48%318.75%
dave hansendave hansen154.39%16.25%
linus torvaldslinus torvalds72.05%16.25%
satyam sharmasatyam sharma41.17%212.50%
al viroal viro30.88%212.50%
serge hallynserge hallyn10.29%16.25%
Total342100.00%16100.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

PersonTokensPropCommitsCommitProp
miklos szeredimiklos szeredi17075.89%112.50%
jeff laytonjeff layton208.93%112.50%
al viroal viro146.25%225.00%
alexey dobriyanalexey dobriyan104.46%112.50%
ulrich drepperulrich drepper73.12%112.50%
jan blunckjan blunck20.89%112.50%
david howellsdavid howells10.45%112.50%
Total224100.00%8100.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(&times, 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

PersonTokensPropCommitsCommitProp
ulrich drepperulrich drepper32231.20%13.85%
alexey dobriyanalexey dobriyan27927.03%13.85%
miklos szeredimiklos szeredi22822.09%415.38%
heiko carstensheiko carstens585.62%27.69%
j. bruce fieldsj. bruce fields343.29%13.85%
michael kerriskmichael kerrisk333.20%311.54%
jeff laytonjeff layton201.94%13.85%
al viroal viro201.94%519.23%
dave hansendave hansen181.74%13.85%
linus torvaldslinus torvalds70.68%13.85%
satyam sharmasatyam sharma40.39%27.69%
adrian bunkadrian bunk30.29%13.85%
david howellsdavid howells30.29%13.85%
jan blunckjan blunck20.19%13.85%
serge hallynserge hallyn10.10%13.85%
Total1032100.00%26100.00%
Directory: fs
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}