kern/181459: [patch] Addition of 'futimensat' call allowing to set file time with nanosecond precision
Yuri
yuri at tsoft.com
Wed Aug 21 22:40:01 UTC 2013
>Number: 181459
>Category: kern
>Synopsis: [patch] Addition of 'futimensat' call allowing to set file time with nanosecond precision
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Wed Aug 21 22:40:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator: Yuri
>Release: 10
>Organization:
n/a
>Environment:
>Description:
This patch adds POSIX futimensat function, which is able to set the time of the file with nanosecond precision. Both by name and by file descriptor.
Times are handled internally in struct timespec, but the function allowing to set it was missing.
>How-To-Repeat:
>Fix:
Patch attached with submission follows:
Index: contrib/openbsm/etc/audit_event
===================================================================
--- contrib/openbsm/etc/audit_event (revision 254587)
+++ contrib/openbsm/etc/audit_event (working copy)
@@ -294,6 +294,7 @@
299:AUE_PF_POLICY_FLUSH:Flush IPsec policy rules:ad
300:AUE_PF_POLICY_ALGS:Update IPsec algorithms:ad
301:AUE_PORTFS:portfs:fa
+302:AUE_FUTIMENSAT:futimensat(2):fm
#
# What follows are deprecated Darwin event numbers that may soon^H^H^H^Hnow
# conflict with Solaris events.
Index: lib/libarchive/config_freebsd.h
===================================================================
--- lib/libarchive/config_freebsd.h (revision 254587)
+++ lib/libarchive/config_freebsd.h (working copy)
@@ -111,6 +111,7 @@
#define HAVE_FTRUNCATE 1
#define HAVE_FUTIMES 1
#define HAVE_FUTIMESAT 1
+#define HAVE_FUTIMENSAT 1
#define HAVE_GETEUID 1
#define HAVE_GETGRGID_R 1
#define HAVE_GETGRNAM_R 1
Index: lib/libc/sys/Makefile.inc
===================================================================
--- lib/libc/sys/Makefile.inc (revision 254587)
+++ lib/libc/sys/Makefile.inc (working copy)
@@ -397,6 +397,7 @@
MLINKS+=unlink.2 unlinkat.2
MLINKS+=utimes.2 futimes.2 \
utimes.2 futimesat.2 \
+ utimes.2 futimensat.2 \
utimes.2 lutimes.2
MLINKS+=wait.2 wait3.2 \
wait.2 wait4.2 \
Index: lib/libc/sys/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map (revision 254587)
+++ lib/libc/sys/Symbol.map (working copy)
@@ -342,6 +342,7 @@
fexecve;
fstatat;
futimesat;
+ futimensat;
jail_get;
jail_set;
jail_remove;
Index: lib/libc/sys/cap_rights_limit.2
===================================================================
--- lib/libc/sys/cap_rights_limit.2 (revision 254587)
+++ lib/libc/sys/cap_rights_limit.2 (working copy)
@@ -250,8 +250,10 @@
.It Dv CAP_FUTIMES
Permit
.Xr futimes 2
+,
+.Xr futimesat 2
and
-.Xr futimesat 2 .
+.Xr futimensat 2 .
.It Dv CAP_FUTIMESAT
An alias to
.Dv CAP_FUTIMES .
Index: lib/libc/sys/sigaction.2
===================================================================
--- lib/libc/sys/sigaction.2 (revision 254587)
+++ lib/libc/sys/sigaction.2 (working copy)
@@ -568,6 +568,7 @@
.Fn flsl ,
.Fn flsll ,
.Fn futimesat ,
+.Fn futimensat ,
.Fn pipe2 ,
.Fn strlcat .
.Fn strlcpy ,
Index: lib/libc/sys/utimes.2
===================================================================
--- lib/libc/sys/utimes.2 (revision 254587)
+++ lib/libc/sys/utimes.2 (working copy)
@@ -37,7 +37,8 @@
.Nm utimes ,
.Nm lutimes ,
.Nm futimes ,
-.Nm futimesat
+.Nm futimesat ,
+.Nm futimensat
.Nd set file access and modification times
.Sh LIBRARY
.Lb libc
@@ -51,6 +52,8 @@
.Fn futimes "int fd" "const struct timeval *times"
.Ft int
.Fn futimesat "int fd" "const char *path" "const struct timeval times[2]"
+.Ft int
+.Fn futimensat "int fd" "const char *path" "const struct timespec times[2]"
.Sh DESCRIPTION
The access and modification times of the file named by
.Fa path
@@ -122,6 +125,15 @@
parameter, the current working directory is used and the behavior is identical to
a call to
.Fn utimes .
+.Pp
+The
+.Fn futimensat
+system call sets the file access and modification times with nanosecond precision. Also when
+.Fa path
+argument is
+.Dv NULL ,
+it changes times of the file referenced by
+.Fa fd .
.Sh RETURN VALUES
.Rv -std
.Sh ERRORS
Index: sys/bsm/audit_kevents.h
===================================================================
--- sys/bsm/audit_kevents.h (revision 254587)
+++ sys/bsm/audit_kevents.h (working copy)
@@ -314,6 +314,7 @@
#define AUE_PF_POLICY_FLUSH 299 /* Solaris-specific. */
#define AUE_PF_POLICY_ALGS 300 /* Solaris-specific. */
#define AUE_PORTFS 301 /* Solaris-specific. */
+#define AUE_FUTIMENSAT 302
/*
* Events added for Apple Darwin that potentially collide with future Solaris
Index: sys/kern/capabilities.conf
===================================================================
--- sys/kern/capabilities.conf (revision 254587)
+++ sys/kern/capabilities.conf (working copy)
@@ -452,6 +452,7 @@
fchownat
fstatat
futimesat
+futimensat
linkat
mkdirat
mkfifoat
Index: sys/kern/init_sysent.c
===================================================================
--- sys/kern/init_sysent.c (revision 254587)
+++ sys/kern/init_sysent.c (working copy)
@@ -578,4 +578,5 @@
{ AS(accept4_args), (sy_call_t *)sys_accept4, AUE_ACCEPT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 541 = accept4 */
{ AS(pipe2_args), (sy_call_t *)sys_pipe2, AUE_PIPE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 542 = pipe2 */
{ AS(aio_mlock_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 543 = aio_mlock */
+ { AS(futimensat_args), (sy_call_t *)sys_futimensat, AUE_FUTIMENSAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 544 = futimensat */
};
Index: sys/kern/syscalls.c
===================================================================
--- sys/kern/syscalls.c (revision 254587)
+++ sys/kern/syscalls.c (working copy)
@@ -551,4 +551,5 @@
"accept4", /* 541 = accept4 */
"pipe2", /* 542 = pipe2 */
"aio_mlock", /* 543 = aio_mlock */
+ "futimensat", /* 544 = futimensat */
};
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master (revision 254587)
+++ sys/kern/syscalls.master (working copy)
@@ -978,5 +978,7 @@
int flags); }
542 AUE_PIPE STD { int pipe2(int *fildes, int flags); }
543 AUE_NULL NOSTD { int aio_mlock(struct aiocb *aiocbp); }
+544 AUE_NULL NOSTD { int futimensat(int fd, char *path, \
+ struct timespec *times); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/kern/vfs_syscalls.c
===================================================================
--- sys/kern/vfs_syscalls.c (revision 254587)
+++ sys/kern/vfs_syscalls.c (working copy)
@@ -106,6 +106,8 @@
const struct timespec *, int, int);
static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
struct thread *td);
+static int timesat_common(struct thread *td, int fd,
+ char *path, enum uio_seg pathseg, struct timespec *ts, int nullflag);
/*
* The module initialization routine for POSIX asynchronous I/O will
@@ -3194,6 +3196,11 @@
const char * path;
const struct timeval * times;
};
+struct futimensat_args {
+ int fd;
+ const char * path;
+ const struct timespec * times;
+};
#endif
int
sys_futimesat(struct thread *td, struct futimesat_args *uap)
@@ -3204,6 +3211,35 @@
}
int
+sys_futimensat(struct thread *td, struct futimensat_args *uap)
+{
+
+ struct timespec ts[2];
+ int error;
+
+ if (uap->times == NULL) {
+ vfs_timestamp(&ts[0]);
+ ts[1] = ts[0];
+ } else {
+ if ((error = copyin(uap->times, ts, sizeof(ts))) != 0)
+ return (error);
+
+ if (ts[0].tv_nsec < 0 || ts[0].tv_nsec >= 1000000000 ||
+ ts[1].tv_nsec < 0 || ts[1].tv_nsec >= 1000000000)
+ return (EINVAL);
+ }
+
+ if (uap->path != NULL) {
+ /* if path is set, file is specified by name */
+ return (timesat_common(td, uap->fd, uap->path, UIO_USERSPACE,
+ ts, uap->times == NULL));
+ } else {
+ /* if path is NULL, file is specified by fd */
+ return (kern_futimens(td, uap->fd, ts));
+ }
+}
+
+int
kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
struct timeval *tptr, enum uio_seg tptrseg)
{
@@ -3215,12 +3251,22 @@
kern_utimesat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
struct timeval *tptr, enum uio_seg tptrseg)
{
- struct nameidata nd;
struct timespec ts[2];
int error;
if ((error = getutimes(tptr, tptrseg, ts)) != 0)
return (error);
+
+ return (timesat_common(td, fd, path, pathseg, ts, tptr == NULL));
+}
+
+static int
+timesat_common(struct thread *td, int fd, char *path, enum uio_seg pathseg,
+ struct timespec *ts, int nullflag)
+{
+ struct nameidata nd;
+ int error;
+
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
CAP_FUTIMES, td);
@@ -3227,7 +3273,7 @@
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
+ error = setutimes(td, nd.ni_vp, ts, 2, nullflag);
vrele(nd.ni_vp);
return (error);
}
@@ -3299,12 +3345,21 @@
enum uio_seg tptrseg)
{
struct timespec ts[2];
+ int error;
+
+ if ((error = getutimes(tptr, tptrseg, ts)) != 0)
+ return (error);
+
+ return (kern_futimens(td, fd, ts));
+}
+
+int
+kern_futimens(struct thread *td, int fd, struct timespec *ts)
+{
struct file *fp;
int error;
AUDIT_ARG_FD(fd);
- if ((error = getutimes(tptr, tptrseg, ts)) != 0)
- return (error);
if ((error = getvnode(td->td_proc->p_fd, fd, CAP_FUTIMES, &fp)) != 0)
return (error);
#ifdef AUDIT
@@ -3312,7 +3367,7 @@
AUDIT_ARG_VNODE1(fp->f_vnode);
VOP_UNLOCK(fp->f_vnode, 0);
#endif
- error = setutimes(td, fp->f_vnode, ts, 2, tptr == NULL);
+ error = setutimes(td, fp->f_vnode, ts, 2, ts == NULL);
fdrop(fp, td);
return (error);
}
Index: sys/sys/capability.h
===================================================================
--- sys/sys/capability.h (revision 254587)
+++ sys/sys/capability.h (working copy)
@@ -116,6 +116,7 @@
#define CAP_FSTATFS 0x0000000000020000ULL
#define CAP_FUTIMES 0x0000000000040000ULL
#define CAP_FUTIMESAT CAP_FUTIMES
+#define CAP_FUTIMENSAT CAP_FUTIMES
#define CAP_LINKAT 0x0000000000400000ULL
#define CAP_MKDIRAT 0x0000000000200000ULL
#define CAP_MKFIFOAT 0x0000000000800000ULL
Index: sys/sys/syscall.h
===================================================================
--- sys/sys/syscall.h (revision 254587)
+++ sys/sys/syscall.h (working copy)
@@ -463,4 +463,5 @@
#define SYS_accept4 541
#define SYS_pipe2 542
#define SYS_aio_mlock 543
-#define SYS_MAXSYSCALL 544
+#define SYS_futimensat 544
+#define SYS_MAXSYSCALL 545
Index: sys/sys/syscall.mk
===================================================================
--- sys/sys/syscall.mk (revision 254587)
+++ sys/sys/syscall.mk (working copy)
@@ -364,6 +364,7 @@
fexecve.o \
fstatat.o \
futimesat.o \
+ futimensat.o \
linkat.o \
mkdirat.o \
mkfifoat.o \
Index: sys/sys/syscallsubr.h
===================================================================
--- sys/sys/syscallsubr.h (revision 254587)
+++ sys/sys/syscallsubr.h (working copy)
@@ -104,6 +104,7 @@
int kern_ftruncate(struct thread *td, int fd, off_t length);
int kern_futimes(struct thread *td, int fd, struct timeval *tptr,
enum uio_seg tptrseg);
+int kern_futimens(struct thread *td, int fd, struct timespec *ts);
int kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
long *basep, ssize_t *residp, enum uio_seg bufseg);
int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
Index: sys/sys/sysproto.h
===================================================================
--- sys/sys/sysproto.h (revision 254587)
+++ sys/sys/sysproto.h (working copy)
@@ -1579,6 +1579,11 @@
char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
char times_l_[PADL_(struct timeval *)]; struct timeval * times; char times_r_[PADR_(struct timeval *)];
};
+struct futimensat_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char times_l_[PADL_(struct timespec *)]; struct timespec * times; char times_r_[PADR_(struct timespec *)];
+};
struct linkat_args {
char fd1_l_[PADL_(int)]; int fd1; char fd1_r_[PADR_(int)];
char path1_l_[PADL_(char *)]; char * path1; char path1_r_[PADR_(char *)];
@@ -2160,6 +2165,7 @@
int sys_fexecve(struct thread *, struct fexecve_args *);
int sys_fstatat(struct thread *, struct fstatat_args *);
int sys_futimesat(struct thread *, struct futimesat_args *);
+int sys_futimensat(struct thread *, struct futimensat_args *);
int sys_linkat(struct thread *, struct linkat_args *);
int sys_mkdirat(struct thread *, struct mkdirat_args *);
int sys_mkfifoat(struct thread *, struct mkfifoat_args *);
@@ -2867,6 +2873,7 @@
#define SYS_AUE_fexecve AUE_FEXECVE
#define SYS_AUE_fstatat AUE_FSTATAT
#define SYS_AUE_futimesat AUE_FUTIMESAT
+#define SYS_AUE_futimensat AUE_FUTIMENSAT
#define SYS_AUE_linkat AUE_LINKAT
#define SYS_AUE_mkdirat AUE_MKDIRAT
#define SYS_AUE_mkfifoat AUE_MKFIFOAT
Index: sys/sys/time.h
===================================================================
--- sys/sys/time.h (revision 254587)
+++ sys/sys/time.h (working copy)
@@ -480,6 +480,7 @@
int clock_getcpuclockid2(id_t, int, clockid_t *);
int futimes(int, const struct timeval *);
int futimesat(int, const char *, const struct timeval [2]);
+int futimensat(int, const char *, const struct timespec [2]);
int lutimes(const char *, const struct timeval *);
int settimeofday(const struct timeval *, const struct timezone *);
#endif
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list