utimens(2) system call
Variant of utime(2) with struct timespec (with ns precision) instead of time_t values; also allows for tv_nsec members the values UTIME_NOW (force update to current time) or UTIME_OMIT (allow to set either atim or mtim independently.) Provides a superset of utimes(2), futimes(2), lutimes(2), and futimens(2). Provides the same subset of utimensat(2) as does NetBSD 6. Also import utimens() and lutimeNS() from NetBSD-current.
This commit is contained in:
parent
88414c568c
commit
9131e98a7d
19 changed files with 385 additions and 16 deletions
|
@ -97,6 +97,7 @@
|
||||||
#define GETPROCNR 104 /* to PM */
|
#define GETPROCNR 104 /* to PM */
|
||||||
#define ISSETUGID 106 /* to PM: ask if process is tainted */
|
#define ISSETUGID 106 /* to PM: ask if process is tainted */
|
||||||
#define GETEPINFO_O 107 /* to PM: get pid/uid/gid of an endpoint */
|
#define GETEPINFO_O 107 /* to PM: get pid/uid/gid of an endpoint */
|
||||||
|
#define UTIMENS 108 /* to FS: [f]utimens(); also [fl]utimes */
|
||||||
#define SRV_KILL 111 /* to PM: special kill call for RS */
|
#define SRV_KILL 111 /* to PM: special kill call for RS */
|
||||||
|
|
||||||
#define GCOV_FLUSH 112 /* flush gcov data from server to gcov files */
|
#define GCOV_FLUSH 112 /* flush gcov data from server to gcov files */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $NetBSD: Makefile.inc,v 1.184 2012/04/12 22:08:32 christos Exp $
|
# $NetBSD: Makefile.inc,v 1.185 2012/11/03 19:39:21 christos Exp $
|
||||||
# from: @(#)Makefile.inc 8.6 (Berkeley) 5/4/95
|
# from: @(#)Makefile.inc 8.6 (Berkeley) 5/4/95
|
||||||
|
|
||||||
# gen sources
|
# gen sources
|
||||||
|
@ -48,8 +48,8 @@ SRCS+= _errno.c alarm.c alphasort.c arc4random.c assert.c basename.c clock.c \
|
||||||
sigset.c sigsetops.c sleep.c \
|
sigset.c sigsetops.c sleep.c \
|
||||||
stringlist.c sysconf.c \
|
stringlist.c sysconf.c \
|
||||||
syslog.c telldir.c time.c \
|
syslog.c telldir.c time.c \
|
||||||
times.c toascii.c tolower_.c ttyname.c ttyslot.c \
|
times.c toascii.c tolower_.c ttyname.c ttyslot.c toupper_.c ualarm.c \
|
||||||
toupper_.c ualarm.c ulimit.c uname.c unvis.c usleep.c utime.c utmp.c \
|
ulimit.c uname.c unvis.c usleep.c utime.c utimens.c utmp.c \
|
||||||
utmpx.c valloc.c vis.c wait.c waitpid.c warn.c warnx.c \
|
utmpx.c valloc.c vis.c wait.c waitpid.c warn.c warnx.c \
|
||||||
vwarn.c vwarnx.c verr.c verrx.c wordexp.c
|
vwarn.c vwarnx.c verr.c verrx.c wordexp.c
|
||||||
.endif
|
.endif
|
||||||
|
|
53
lib/libc/gen/utimens.c
Normal file
53
lib/libc/gen/utimens.c
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/* $NetBSD: utimens.c,v 1.1 2012/11/03 19:39:21 christos Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2012 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: utimens.c,v 1.1 2012/11/03 19:39:21 christos Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include "namespace.h"
|
||||||
|
|
||||||
|
#define _INCOMPLETE_XOPEN_C063
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
utimens(const char *path, const struct timespec *times)
|
||||||
|
{
|
||||||
|
return utimensat(AT_FDCWD, path, times, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lutimens(const char *path, const struct timespec *times)
|
||||||
|
{
|
||||||
|
return utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
|
||||||
|
}
|
|
@ -69,9 +69,6 @@ timer_delete
|
||||||
timer_gettime
|
timer_gettime
|
||||||
timer_settime
|
timer_settime
|
||||||
undelete
|
undelete
|
||||||
utimes
|
|
||||||
lutimes
|
|
||||||
futimes
|
|
||||||
utrace
|
utrace
|
||||||
uuidgen
|
uuidgen
|
||||||
vadvise
|
vadvise
|
||||||
|
|
|
@ -17,6 +17,7 @@ SRCS+= accept.c access.c adjtime.c bind.c brk.c sbrk.c m_closefrom.c getsid.c \
|
||||||
vectorio.c shutdown.c sigaction.c sigpending.c sigreturn.c sigsuspend.c\
|
vectorio.c shutdown.c sigaction.c sigpending.c sigreturn.c sigsuspend.c\
|
||||||
sigprocmask.c socket.c socketpair.c stat.c statvfs.c symlink.c \
|
sigprocmask.c socket.c socketpair.c stat.c statvfs.c symlink.c \
|
||||||
sync.c syscall.c sysuname.c truncate.c umask.c unlink.c write.c \
|
sync.c syscall.c sysuname.c truncate.c umask.c unlink.c write.c \
|
||||||
|
utimensat.c utimes.c futimes.c lutimes.c futimens.c \
|
||||||
_exit.c _ucontext.c environ.c __getcwd.c vfork.c sizeup.c init.c
|
_exit.c _ucontext.c environ.c __getcwd.c vfork.c sizeup.c init.c
|
||||||
|
|
||||||
# Minix specific syscalls.
|
# Minix specific syscalls.
|
||||||
|
|
23
lib/libc/sys-minix/futimens.c
Normal file
23
lib/libc/sys-minix/futimens.c
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include "namespace.h"
|
||||||
|
#include <lib.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
int futimens(int fd, const struct timespec tv[2])
|
||||||
|
{
|
||||||
|
message m;
|
||||||
|
static const struct timespec now[2] = { {0, UTIME_NOW}, {0, UTIME_NOW} };
|
||||||
|
|
||||||
|
if (tv == NULL) tv = now;
|
||||||
|
|
||||||
|
m.m2_i1 = fd;
|
||||||
|
m.m2_l1 = tv[0].tv_sec;
|
||||||
|
m.m2_l2 = tv[1].tv_sec;
|
||||||
|
m.m2_i2 = tv[0].tv_nsec;
|
||||||
|
m.m2_i3 = tv[1].tv_nsec;
|
||||||
|
m.m2_p1 = NULL;
|
||||||
|
m.m2_s1 = 0;
|
||||||
|
|
||||||
|
return(_syscall(VFS_PROC_NR, UTIMENS, &m));
|
||||||
|
}
|
31
lib/libc/sys-minix/futimes.c
Normal file
31
lib/libc/sys-minix/futimes.c
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include "namespace.h"
|
||||||
|
#include <lib.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#ifdef __weak_alias
|
||||||
|
__weak_alias(futimes, __futimes50)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int futimes(int fd, const struct timeval tv[2])
|
||||||
|
{
|
||||||
|
message m;
|
||||||
|
|
||||||
|
m.m2_i1 = fd;
|
||||||
|
if (tv == NULL) {
|
||||||
|
m.m2_l1 = m.m2_l2 = 0;
|
||||||
|
m.m2_i2 = m.m2_i3 = UTIME_NOW;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m.m2_l1 = tv[0].tv_sec;
|
||||||
|
m.m2_l2 = tv[1].tv_sec;
|
||||||
|
m.m2_i2 = tv[0].tv_usec * 1000;
|
||||||
|
m.m2_i3 = tv[1].tv_usec * 1000;
|
||||||
|
}
|
||||||
|
m.m2_p1 = NULL;
|
||||||
|
m.m2_s1 = 0;
|
||||||
|
|
||||||
|
return(_syscall(VFS_PROC_NR, UTIMENS, &m));
|
||||||
|
}
|
36
lib/libc/sys-minix/lutimes.c
Normal file
36
lib/libc/sys-minix/lutimes.c
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include "namespace.h"
|
||||||
|
#include <lib.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef __weak_alias
|
||||||
|
__weak_alias(lutimes, __lutimes50)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int lutimes(const char *name, const struct timeval tv[2])
|
||||||
|
{
|
||||||
|
message m;
|
||||||
|
|
||||||
|
if (name == NULL) return EINVAL;
|
||||||
|
if (name[0] == '\0') return ENOENT; /* X/Open requirement */
|
||||||
|
m.m2_i1 = strlen(name) + 1;
|
||||||
|
m.m2_p1 = (char *) __UNCONST(name);
|
||||||
|
if (tv == NULL) {
|
||||||
|
m.m2_l1 = m.m2_l2 = 0;
|
||||||
|
m.m2_i2 = m.m2_i3 = UTIME_NOW;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m.m2_l1 = tv[0].tv_sec;
|
||||||
|
m.m2_l2 = tv[1].tv_sec;
|
||||||
|
m.m2_i2 = tv[0].tv_usec * 1000;
|
||||||
|
m.m2_i3 = tv[1].tv_usec * 1000;
|
||||||
|
}
|
||||||
|
m.m2_s1 = AT_SYMLINK_NOFOLLOW;
|
||||||
|
|
||||||
|
return(_syscall(VFS_PROC_NR, UTIMENS, &m));
|
||||||
|
}
|
43
lib/libc/sys-minix/utimensat.c
Normal file
43
lib/libc/sys-minix/utimensat.c
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include "namespace.h"
|
||||||
|
#include <lib.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* Implement a very large but not complete subset of the utimensat()
|
||||||
|
* Posix:2008/XOpen-7 function.
|
||||||
|
* Are handled the following cases:
|
||||||
|
* . utimensat(AT_FDCWD, "/some/absolute/path", , )
|
||||||
|
* . utimensat(AT_FDCWD, "some/path", , )
|
||||||
|
* . utimensat(fd, "/some/absolute/path", , ) although fd is useless here
|
||||||
|
* Are not handled the following cases:
|
||||||
|
* . utimensat(fd, "some/path", , ) path to a file relative to some open fd
|
||||||
|
*/
|
||||||
|
int utimensat(int fd, const char *name, const struct timespec tv[2],
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
message m;
|
||||||
|
static const struct timespec now[2] = { {0, UTIME_NOW}, {0, UTIME_NOW} };
|
||||||
|
|
||||||
|
if (tv == NULL) tv = now;
|
||||||
|
|
||||||
|
if (name == NULL) return EINVAL;
|
||||||
|
if (name[0] == '\0') return ENOENT; /* POSIX requirement */
|
||||||
|
if (fd != AT_FDCWD && name[0] != '/') return EINVAL; /* Not supported */
|
||||||
|
m.m2_i1 = strlen(name) + 1;
|
||||||
|
m.m2_p1 = (char *) __UNCONST(name);
|
||||||
|
m.m2_l1 = tv[0].tv_sec;
|
||||||
|
m.m2_l2 = tv[1].tv_sec;
|
||||||
|
m.m2_i2 = tv[0].tv_nsec;
|
||||||
|
m.m2_i3 = tv[1].tv_nsec;
|
||||||
|
if ((unsigned)flags > SHRT_MAX)
|
||||||
|
return EINVAL;
|
||||||
|
else
|
||||||
|
m.m2_s1 = flags;
|
||||||
|
|
||||||
|
return(_syscall(VFS_PROC_NR, UTIMENS, &m));
|
||||||
|
}
|
35
lib/libc/sys-minix/utimes.c
Normal file
35
lib/libc/sys-minix/utimes.c
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include "namespace.h"
|
||||||
|
#include <lib.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef __weak_alias
|
||||||
|
__weak_alias(utimes, __utimes50)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int utimes(const char *name, const struct timeval tv[2])
|
||||||
|
{
|
||||||
|
message m;
|
||||||
|
|
||||||
|
if (name == NULL) return EINVAL;
|
||||||
|
if (name[0] == '\0') return ENOENT; /* X/Open requirement */
|
||||||
|
m.m2_i1 = strlen(name) + 1;
|
||||||
|
m.m2_p1 = (char *) __UNCONST(name);
|
||||||
|
if (tv == NULL) {
|
||||||
|
m.m2_l1 = m.m2_l2 = 0;
|
||||||
|
m.m2_i2 = m.m2_i3 = UTIME_NOW;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m.m2_l1 = tv[0].tv_sec;
|
||||||
|
m.m2_l2 = tv[1].tv_sec;
|
||||||
|
m.m2_i2 = tv[0].tv_usec * 1000;
|
||||||
|
m.m2_i3 = tv[1].tv_usec * 1000;
|
||||||
|
}
|
||||||
|
m.m2_s1 = 0;
|
||||||
|
|
||||||
|
return(_syscall(VFS_PROC_NR, UTIMENS, &m));
|
||||||
|
}
|
|
@ -119,7 +119,7 @@ int (*call_vec[])(void) = {
|
||||||
no_sys, /* 105 = unused */
|
no_sys, /* 105 = unused */
|
||||||
do_get, /* 106 = issetugid */
|
do_get, /* 106 = issetugid */
|
||||||
do_getepinfo_o, /* 107 = getepinfo XXX: old implementation*/
|
do_getepinfo_o, /* 107 = getepinfo XXX: old implementation*/
|
||||||
no_sys, /* 108 = unused */
|
no_sys, /* 108 = (utimens) */
|
||||||
no_sys, /* 109 = unused */
|
no_sys, /* 109 = unused */
|
||||||
no_sys, /* 110 = unused */
|
no_sys, /* 110 = unused */
|
||||||
do_srv_kill, /* 111 = srv_kill */
|
do_srv_kill, /* 111 = srv_kill */
|
||||||
|
|
|
@ -43,6 +43,10 @@
|
||||||
#define utime_file m2_p1
|
#define utime_file m2_p1
|
||||||
#define utime_length m2_i1
|
#define utime_length m2_i1
|
||||||
#define utime_strlen m2_i2
|
#define utime_strlen m2_i2
|
||||||
|
#define utimens_fd m2_i1
|
||||||
|
#define utimens_ansec m2_i2
|
||||||
|
#define utimens_mnsec m2_i3
|
||||||
|
#define utimens_flags m2_s1
|
||||||
#define whence m2_i2
|
#define whence m2_i2
|
||||||
#define svrctl_req m2_i1
|
#define svrctl_req m2_i1
|
||||||
#define svrctl_argp m2_p1
|
#define svrctl_argp m2_p1
|
||||||
|
|
|
@ -280,6 +280,7 @@ int do_lstat(void);
|
||||||
|
|
||||||
/* time.c */
|
/* time.c */
|
||||||
int do_utime(void);
|
int do_utime(void);
|
||||||
|
int do_utimens(void);
|
||||||
|
|
||||||
/* tll.c */
|
/* tll.c */
|
||||||
void tll_downgrade(tll_t *tllp);
|
void tll_downgrade(tll_t *tllp);
|
||||||
|
|
|
@ -123,7 +123,7 @@ int (*call_vec[])(void) = {
|
||||||
no_sys, /* 105 = unused */
|
no_sys, /* 105 = unused */
|
||||||
no_sys, /* 106 = unused */
|
no_sys, /* 106 = unused */
|
||||||
no_sys, /* 107 = (getepinfo) */
|
no_sys, /* 107 = (getepinfo) */
|
||||||
no_sys, /* 108 = unused */
|
do_utimens, /* 108 = utimens */
|
||||||
no_sys, /* 109 = unused */
|
no_sys, /* 109 = unused */
|
||||||
no_sys, /* 110 = unused */
|
no_sys, /* 110 = unused */
|
||||||
no_sys, /* 111 = (srv_kill) */
|
no_sys, /* 111 = (srv_kill) */
|
||||||
|
|
|
@ -2,12 +2,15 @@
|
||||||
*
|
*
|
||||||
* The entry points into this file are
|
* The entry points into this file are
|
||||||
* do_utime: perform the UTIME system call
|
* do_utime: perform the UTIME system call
|
||||||
|
* do_utimens: perform the UTIMENS system call
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include <minix/callnr.h>
|
#include <minix/callnr.h>
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "fproc.h"
|
#include "fproc.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
|
@ -16,10 +19,13 @@
|
||||||
#include <minix/vfsif.h>
|
#include <minix/vfsif.h>
|
||||||
#include "vmnt.h"
|
#include "vmnt.h"
|
||||||
|
|
||||||
|
#define UTIMENS_STYLE 0 /* utimes(2)/utimensat(2) style, named file */
|
||||||
|
#define FUTIMENS_STYLE 1 /* futimens(2)/futimes(2) style, file desc. */
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_utime *
|
* do_utime *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_utime()
|
int do_utime(void)
|
||||||
{
|
{
|
||||||
/* Perform the utime(name, timep) system call. */
|
/* Perform the utime(name, timep) system call. */
|
||||||
int r;
|
int r;
|
||||||
|
@ -72,3 +78,136 @@ int do_utime()
|
||||||
put_vnode(vp);
|
put_vnode(vp);
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_utimens *
|
||||||
|
*===========================================================================*/
|
||||||
|
int do_utimens(void)
|
||||||
|
{
|
||||||
|
/* Perform the utimens(name, times, flag) system call, and its friends.
|
||||||
|
* Implement a very large but not complete subset of the utimensat()
|
||||||
|
* Posix:2008/XOpen-7 function.
|
||||||
|
* Are handled all the following cases:
|
||||||
|
* . utimensat(AT_FDCWD, "/some/absolute/path", , )
|
||||||
|
* . utimensat(AT_FDCWD, "some/path", , )
|
||||||
|
* . utimens("anything", ) really special case of the above two
|
||||||
|
* . lutimens("anything", ) also really special case of the above
|
||||||
|
* . utimensat(fd, "/some/absolute/path", , ) although fd is useless here
|
||||||
|
* . futimens(fd, )
|
||||||
|
* Are not handled the following cases:
|
||||||
|
* . utimensat(fd, "some/path", , ) path to a file relative to some open fd
|
||||||
|
*/
|
||||||
|
int r, kind, lookup_flags;
|
||||||
|
struct vnode *vp;
|
||||||
|
struct filp *filp = NULL; /* initialization required by clueless GCC */
|
||||||
|
struct vmnt *vmp;
|
||||||
|
struct timespec actim, modtim, now, newactim, newmodtim;
|
||||||
|
char fullpath[PATH_MAX];
|
||||||
|
struct lookup resolve;
|
||||||
|
vir_bytes vname;
|
||||||
|
size_t vname_length;
|
||||||
|
|
||||||
|
/* The case times==NULL is handled by the caller, replaced with UTIME_NOW */
|
||||||
|
actim.tv_sec = job_m_in.utime_actime;
|
||||||
|
actim.tv_nsec = job_m_in.utimens_ansec;
|
||||||
|
modtim.tv_sec = job_m_in.utime_modtime;
|
||||||
|
modtim.tv_nsec = job_m_in.utimens_mnsec;
|
||||||
|
|
||||||
|
if (job_m_in.utime_file != NULL) {
|
||||||
|
kind = UTIMENS_STYLE;
|
||||||
|
if (job_m_in.utimens_flags & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
return EINVAL; /* unknown flag */
|
||||||
|
/* Temporarily open the file */
|
||||||
|
vname = (vir_bytes) job_m_in.utime_file;
|
||||||
|
vname_length = (size_t) job_m_in.utime_length;
|
||||||
|
if (job_m_in.utimens_flags & AT_SYMLINK_NOFOLLOW)
|
||||||
|
lookup_flags = PATH_RET_SYMLINK;
|
||||||
|
else
|
||||||
|
lookup_flags = PATH_NOFLAGS;
|
||||||
|
lookup_init(&resolve, fullpath, lookup_flags, &vmp, &vp);
|
||||||
|
resolve.l_vmnt_lock = VMNT_READ;
|
||||||
|
resolve.l_vnode_lock = VNODE_READ;
|
||||||
|
/* Temporarily open the file */
|
||||||
|
if (fetch_name(vname, vname_length, fullpath) != OK) return(err_code);
|
||||||
|
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
kind = FUTIMENS_STYLE;
|
||||||
|
/* Change timestamps on already-opened fd. Is it valid? */
|
||||||
|
if (job_m_in.utimens_flags != 0)
|
||||||
|
return EINVAL; /* unknown flag */
|
||||||
|
if ((filp = get_filp(job_m_in.utimens_fd, VNODE_READ)) == NULL)
|
||||||
|
return err_code;
|
||||||
|
vp = filp->filp_vno;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = OK;
|
||||||
|
/* Only the owner of a file or the super user can change timestamps. */
|
||||||
|
if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM;
|
||||||
|
/* Need write permission (or super user) to 'touch' the file */
|
||||||
|
if (r != OK && actim.tv_nsec == UTIME_NOW
|
||||||
|
&& modtim.tv_nsec == UTIME_NOW) r = forbidden(fp, vp, W_BIT);
|
||||||
|
if (read_only(vp) != OK) r = EROFS; /* Not even su can touch if R/O */
|
||||||
|
|
||||||
|
if (r == OK) {
|
||||||
|
/* Do we need to ask for current time? */
|
||||||
|
if (actim.tv_nsec == UTIME_NOW
|
||||||
|
|| actim.tv_nsec == UTIME_OMIT
|
||||||
|
|| modtim.tv_nsec == UTIME_NOW
|
||||||
|
|| modtim.tv_nsec == UTIME_OMIT) {
|
||||||
|
now = clock_timespec();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build the request */
|
||||||
|
switch (actim.tv_nsec) {
|
||||||
|
case UTIME_NOW:
|
||||||
|
newactim = now;
|
||||||
|
break;
|
||||||
|
case UTIME_OMIT:
|
||||||
|
newactim.tv_nsec = UTIME_OMIT;
|
||||||
|
/* Be nice with old FS, put a sensible value in
|
||||||
|
* otherwise not used field for seconds
|
||||||
|
*/
|
||||||
|
newactim.tv_sec = now.tv_sec;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ( (unsigned)actim.tv_nsec >= 1000000000)
|
||||||
|
r = EINVAL;
|
||||||
|
else
|
||||||
|
newactim = actim;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (modtim.tv_nsec) {
|
||||||
|
case UTIME_NOW:
|
||||||
|
newmodtim = now;
|
||||||
|
break;
|
||||||
|
case UTIME_OMIT:
|
||||||
|
newmodtim.tv_nsec = UTIME_OMIT;
|
||||||
|
/* Be nice with old FS, put a sensible value */
|
||||||
|
newmodtim.tv_sec = now.tv_sec;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ( (unsigned)modtim.tv_nsec >= 1000000000)
|
||||||
|
r = EINVAL;
|
||||||
|
else
|
||||||
|
newmodtim = modtim;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == OK)
|
||||||
|
/* Issue request */
|
||||||
|
r = req_utime(vp->v_fs_e, vp->v_inode_nr, &newactim, &newmodtim);
|
||||||
|
|
||||||
|
if (kind == UTIMENS_STYLE) {
|
||||||
|
/* Close the temporary */
|
||||||
|
unlock_vnode(vp);
|
||||||
|
unlock_vmnt(vmp);
|
||||||
|
put_vnode(vp);
|
||||||
|
}
|
||||||
|
else { /* Change timestamps on opened fd. */
|
||||||
|
unlock_filp(filp);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
|
@ -185,14 +185,18 @@ struct flock {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constants for X/Open Extended API set 2 (a.k.a. C063)
|
* Constants for X/Open Extended API set 2 (a.k.a. C063)
|
||||||
|
* linkat(2) - also part of Posix-2008/XPG7
|
||||||
*/
|
*/
|
||||||
#if defined(_INCOMPLETE_XOPEN_C063) || defined(_KERNEL)
|
#if (_POSIX_C_SOURCE - 0) >= 200809L || (_XOPEN_SOURCE - 0) >= 700 || \
|
||||||
|
defined(_NETBSD_SOURCE)
|
||||||
|
#if defined(_INCOMPLETE_XOPEN_C063) || defined(_KERNEL) || defined(__minix)
|
||||||
#define AT_FDCWD -100 /* Use cwd for relative link target */
|
#define AT_FDCWD -100 /* Use cwd for relative link target */
|
||||||
#define AT_EACCESS 0x100 /* Use euig/egid for access checks */
|
#define AT_EACCESS 0x100 /* Use euid/egid for access checks */
|
||||||
#define AT_SYMLINK_NOFOLLOW 0x200 /* Do not follow symlinks */
|
#define AT_SYMLINK_NOFOLLOW 0x200 /* Do not follow symlinks */
|
||||||
#define AT_SYMLINK_FOLLOW 0x400 /* Follow symlinks */
|
#define AT_SYMLINK_FOLLOW 0x400 /* Follow symlinks */
|
||||||
#define AT_REMOVEDIR 0x800 /* Remove directory only */
|
#define AT_REMOVEDIR 0x800 /* Remove directory only */
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef _KERNEL
|
#ifndef _KERNEL
|
||||||
|
|
|
@ -295,7 +295,6 @@ int lchflags(const char *, unsigned long);
|
||||||
int lchmod(const char *, mode_t);
|
int lchmod(const char *, mode_t);
|
||||||
#endif /* defined(_NETBSD_SOURCE) && !defined(__minix) */
|
#endif /* defined(_NETBSD_SOURCE) && !defined(__minix) */
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
#ifndef __LIBC12_SOURCE__
|
#ifndef __LIBC12_SOURCE__
|
||||||
/*
|
/*
|
||||||
* X/Open Extended API set 2 (a.k.a. C063)
|
* X/Open Extended API set 2 (a.k.a. C063)
|
||||||
|
@ -315,7 +314,6 @@ int lutimens(const char *, const struct timespec *);
|
||||||
int futimens(int, const struct timespec *);
|
int futimens(int, const struct timespec *);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif /* !__minix */
|
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -283,13 +283,14 @@ int gettimeofday(struct timeval * __restrict, void *__restrict);
|
||||||
int setitimer(int, const struct itimerval * __restrict,
|
int setitimer(int, const struct itimerval * __restrict,
|
||||||
struct itimerval * __restrict) __RENAME(__setitimer50);
|
struct itimerval * __restrict) __RENAME(__setitimer50);
|
||||||
#endif /* _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE || _NETBSD_SOURCE */
|
#endif /* _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE || _NETBSD_SOURCE */
|
||||||
|
#if defined(_XOPEN_SOURCE) || defined(_NETBSD_SOURCE)
|
||||||
|
int utimes(const char *, const struct timeval [2]) __RENAME(__utimes50);
|
||||||
|
#endif /* _XOPEN_SOURCE || _NETBSD_SOURCE */
|
||||||
|
|
||||||
#if defined(_NETBSD_SOURCE) || defined(HAVE_NBTOOL_CONFIG_H)
|
#if defined(_NETBSD_SOURCE) || defined(HAVE_NBTOOL_CONFIG_H)
|
||||||
int adjtime(const struct timeval *, struct timeval *) __RENAME(__adjtime50);
|
int adjtime(const struct timeval *, struct timeval *) __RENAME(__adjtime50);
|
||||||
#ifndef __minix
|
|
||||||
int futimes(int, const struct timeval [2]) __RENAME(__futimes50);
|
int futimes(int, const struct timeval [2]) __RENAME(__futimes50);
|
||||||
int lutimes(const char *, const struct timeval [2]) __RENAME(__lutimes50);
|
int lutimes(const char *, const struct timeval [2]) __RENAME(__lutimes50);
|
||||||
#endif /* !__minix */
|
|
||||||
int settimeofday(const struct timeval * __restrict,
|
int settimeofday(const struct timeval * __restrict,
|
||||||
const void *__restrict) __RENAME(__settimeofday50);
|
const void *__restrict) __RENAME(__settimeofday50);
|
||||||
#endif /* _NETBSD_SOURCE */
|
#endif /* _NETBSD_SOURCE */
|
||||||
|
|
|
@ -142,10 +142,12 @@ lchown(const char *path, uid_t owner, gid_t group)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
utimes(const char *path, const struct timeval times[2])
|
fake_utimes(const char *path, const struct timeval times[2])
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#undef utimes
|
||||||
|
#define utimes(path, times) fake_utimes(path, times)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in a new issue