Submit #2818 » 0001-kernel-Implement-kern_utimes-on-top-of-kern_utimensa.patch
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);
|
||
- « Previous
- 1
- 2
- Next »