Project

General

Profile

Submit #2818 » 0001-kernel-Implement-kern_utimes-on-top-of-kern_utimensa.patch

stateless, 05/26/2015 03:58 AM

View differences:

sys/kern/vfs_syscalls.c
static int chroot_refuse_vdir_fds (struct filedesc *fdp);
static int chroot_visible_mnt(struct mount *mp, struct proc *p);
static int getutimes (const struct timeval *, struct timespec *);
static int getutimens (const struct timespec *, struct timespec *, int *);
static int setfown (struct mount *, struct vnode *, uid_t, gid_t);
static int setfmode (struct vnode *, int);
static int setfflags (struct vnode *, int);
......
}
static int
getutimens(const struct timespec *ts, struct timespec *newts, int *nullflag)
{
struct timespec tsnow;
*nullflag = 0;
nanotime(&tsnow);
if (!ts) {
newts[0] = tsnow;
newts[1] = tsnow;
*nullflag = 1;
return (0);
}
newts[0] = ts[0];
newts[1] = ts[1];
if (newts[0].tv_nsec == UTIME_OMIT && newts[1].tv_nsec == UTIME_OMIT)
return (0);
if (newts[0].tv_nsec == UTIME_NOW && newts[1].tv_nsec == UTIME_NOW)
*nullflag = 1;
if (newts[0].tv_nsec == UTIME_OMIT)
newts[0].tv_sec = VNOVAL;
else if (newts[0].tv_nsec == UTIME_NOW)
newts[0] = tsnow;
else if (newts[0].tv_nsec < 0 || newts[0].tv_nsec >= 1000000000ULL)
return (EINVAL);
if (newts[1].tv_nsec == UTIME_OMIT)
newts[1].tv_sec = VNOVAL;
else if (newts[1].tv_nsec == UTIME_NOW)
newts[1] = tsnow;
else if (newts[1].tv_nsec < 0 || newts[1].tv_nsec >= 1000000000ULL)
return (EINVAL);
return (0);
}
static int
setutimes(struct vnode *vp, struct vattr *vattr,
const struct timespec *ts, int nullflag)
{
......
kern_utimes(struct nlookupdata *nd, struct timeval *tptr)
{
struct timespec ts[2];
struct vnode *vp;
struct vattr vattr;
int error;
if ((error = getutimes(tptr, ts)) != 0)
return (error);
/*
* NOTE: utimes() succeeds for the owner even if the file
* is not user-writable.
*/
nd->nl_flags |= NLC_OWN | NLC_WRITE;
if ((error = nlookup(nd)) != 0)
return (error);
if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
return (error);
/*
* note: vget is required for any operation that might mod the vnode
* so VINACTIVE is properly cleared.
*/
if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) {
error = vget(vp, LK_EXCLUSIVE);
if (error == 0) {
error = setutimes(vp, &vattr, ts, (tptr == NULL));
vput(vp);
}
}
vrele(vp);
return (error);
if (tptr)
if ((error = getutimes(tptr, ts)) != 0)
return (error);
return kern_utimensat(nd, tptr ? ts : NULL, 0);
}
/*
......
}
int
kern_utimensat(struct nlookupdata *nd, int fd, const char *path,
const struct timespec *usrts, int flags)
kern_utimensat(struct nlookupdata *nd, const struct timespec *ts, int flags)
{
struct timespec ts[2], tsnow;
struct timespec newts[2];
struct vnode *vp;
struct vattr vattr;
int nullflag = 0;
int nullflag;
int error;
if (flags & ~AT_SYMLINK_NOFOLLOW)
return (EINVAL);
nanotime(&tsnow);
if (!usrts) {
ts[0] = tsnow;
ts[1] = tsnow;
nullflag = 1;
} else {
error = copyin(usrts, ts, sizeof(ts));
if (error)
return (error);
if (ts[0].tv_nsec == UTIME_OMIT && ts[1].tv_nsec == UTIME_OMIT)
return 0;
if (ts[0].tv_nsec == UTIME_NOW && ts[1].tv_nsec == UTIME_NOW)
nullflag = 1;
if (ts[0].tv_nsec == UTIME_OMIT)
ts[0].tv_sec = VNOVAL;
else if (ts[0].tv_nsec == UTIME_NOW)
ts[0] = tsnow;
else if (ts[0].tv_nsec < 0 || ts[0].tv_nsec >= 1000000000ULL)
return (EINVAL);
if (ts[1].tv_nsec == UTIME_OMIT)
ts[1].tv_sec = VNOVAL;
else if (ts[1].tv_nsec == UTIME_NOW)
ts[1] = tsnow;
else if (ts[1].tv_nsec < 0 || ts[1].tv_nsec >= 1000000000ULL)
return (EINVAL);
}
error = getutimens(ts, newts, &nullflag);
if (error)
return (error);
nd->nl_flags |= NLC_OWN | NLC_WRITE;
if ((error = nlookup(nd)) != 0)
......
if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) {
error = vget(vp, LK_EXCLUSIVE);
if (error == 0) {
error = setutimes(vp, &vattr, ts, nullflag);
error = setutimes(vp, &vattr, newts, nullflag);
vput(vp);
}
}
......
int
sys_utimensat(struct utimensat_args *uap)
{
struct timespec ts[2];
struct nlookupdata nd;
struct file *fp;
int error;
int flags;
if (uap->ts) {
error = copyin(uap->ts, ts, sizeof(ts));
if (error)
return (error);
}
flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
error = nlookup_init_at(&nd, &fp, uap->fd, uap->path,
UIO_USERSPACE, flags);
if (error == 0)
error = kern_utimensat(&nd, uap->fd, uap->path,
uap->ts, uap->flags);
error = kern_utimensat(&nd, uap->ts ? ts : NULL, uap->flags);
nlookup_done_at(&nd, fp);
return (error);
}
sys/sys/kern_syscall.h
int kern_symlink(struct nlookupdata *nd, char *path, int mode);
int kern_truncate(struct nlookupdata *nd, off_t length);
int kern_unlink(struct nlookupdata *nd);
int kern_utimensat(struct nlookupdata *nd, int fd, const char *path,
const struct timespec *ts, int flag);
int kern_utimensat(struct nlookupdata *nd, const struct timespec *ts, int flag);
int kern_utimes(struct nlookupdata *nd, struct timeval *tptr);
struct uuid *kern_uuidgen(struct uuid *store, size_t count);
(2-2/2)