--- old/usr/src/lib/libc/port/mapfile-vers	Mon Sep 14 14:49:07 2020
+++ new/usr/src/lib/libc/port/mapfile-vers	Mon Sep 14 14:49:07 2020
@@ -78,6 +78,12 @@
 $add amd64
 $endif
 
+SYMBOL_VERSION ILLUMOS_0.34 {
+    protected:
+	futimes;
+	lutimes;
+} ILLUMOS_0.33;
+
 SYMBOL_VERSION ILLUMOS_0.33 {
     protected:
 	c16rtomb;
--- old/usr/src/lib/libc/port/sys/utimesys.c	Mon Sep 14 14:49:07 2020
+++ new/usr/src/lib/libc/port/sys/utimesys.c	Mon Sep 14 14:49:07 2020
@@ -24,6 +24,10 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
+ */
+
 #include "lint.h"
 #include <string.h>
 #include <utime.h>
@@ -67,8 +71,8 @@
 	return (utimensat(AT_FDCWD, path, tsp, 0));
 }
 
-int
-utimes(const char *path, const struct timeval times[2])
+static int
+utimes_impl(const char *path, const struct timeval times[2], int flag)
 {
 	struct timeval ltimes[2];
 	timespec_t ts[2];
@@ -86,9 +90,21 @@
 		ts[1].tv_nsec = ltimes[1].tv_usec * 1000;
 		tsp = ts;
 	}
-	return (utimensat(AT_FDCWD, path, tsp, 0));
+	return (utimensat(AT_FDCWD, path, tsp, flag));
 }
 
+int
+utimes(const char *path, const struct timeval times[2])
+{
+	return (utimes_impl(path, times, 0));
+}
+
+int
+lutimes(const char *path, const struct timeval times[2])
+{
+	return (utimes_impl(path, times, AT_SYMLINK_NOFOLLOW));
+}
+
 #pragma weak _futimesat = futimesat
 int
 futimesat(int fd, const char *path, const struct timeval times[2])
@@ -114,4 +130,10 @@
 		return (futimens(fd, tsp));
 
 	return (utimensat(fd, path, tsp, 0));
+}
+
+int
+futimes(int fd, const struct timeval times[2])
+{
+	return (futimesat(fd, NULL, times));
 }
--- old/usr/src/man/man2/Makefile	Mon Sep 14 14:49:07 2020
+++ new/usr/src/man/man2/Makefile	Mon Sep 14 14:49:07 2020
@@ -15,6 +15,7 @@
 # Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
 # Copyright (c) 2018, Joyent, Inc.  All rights reserved.
 # Copyright 2017 Peter Tribble
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
 #
 
 include		$(SRC)/Makefile.master
@@ -196,6 +197,7 @@
 		fstat.2				\
 		fstatat.2			\
 		fstatvfs.2			\
+		futimes.2			\
 		futimesat.2			\
 		futimens.2			\
 		getaudit_addr.2			\
@@ -213,6 +215,7 @@
 		lchown.2			\
 		linkat.2			\
 		lstat.2				\
+		lutimes.2			\
 		mkdirat.2			\
 		mknodat.2			\
 		openat.2			\
@@ -396,7 +399,9 @@
 unlinkat.2			:= LINKSRC = unlink.2
 
 futimens.2			:= LINKSRC = utimes.2
+futimes.2			:= LINKSRC = utimes.2
 futimesat.2			:= LINKSRC = utimes.2
+lutimes.2			:= LINKSRC = utimes.2
 utimensat.2			:= LINKSRC = utimes.2
 
 vforkx.2			:= LINKSRC = vfork.2
--- old/usr/src/man/man2/utimes.2	Mon Sep 14 14:49:08 2020
+++ new/usr/src/man/man2/utimes.2	Mon Sep 14 14:49:08 2020
@@ -43,12 +43,12 @@
 .\" Portions Copyright (c) 1992, X/Open Company Limited.  All Rights Reserved.
 .\" Copyright (c) 2009, Sun Microsystems, Inc.  All Rights Reserved.
 .\" Copyright (c) 2014, Joyent, Inc.
+.\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
 .\"
-.TH UTIMES 2 "Dec 20, 2014"
+.TH UTIMES 2 "Sep 06, 2020"
 .SH NAME
-utimes, futimesat \- set file access and modification times
+utimes, lutimes, futimes, futimesat, utimens, utimensat \- set file access and modification times
 .SH SYNOPSIS
-.LP
 .nf
 #include <sys/time.h>
 
@@ -57,6 +57,16 @@
 
 .LP
 .nf
+\fBint\fR \fBlutimes\fR(\fBconst char *\fR\fIpath\fR, \fBconst struct timeval\fR \fItimes\fR[2]);
+.fi
+
+.LP
+.nf
+\fBint\fR \fBfutimes\fR(\fBint\fR \fIfildes\fR, \fBconst struct timeval\fR \fItimes\fR[2]);
+.fi
+
+.LP
+.nf
 \fBint\fR \fBfutimesat\fR(\fBint\fR \fIfildes\fR, \fBconst char *\fR\fIpath\fR,
      \fBconst struct timeval\fR \fItimes\fR[2]);
 .fi
@@ -65,18 +75,27 @@
 .nf
 #include <sys/stat.h>
 
-\fBint\fR \fBfutimens\fR(\fBint\fR \fIfiledes\fR, \fBconst timespec_t\fR \fInstimes[2]\fR);
+\fBint\fR \fBfutimens\fR(\fBint\fR \fIfildes\fR, \fBconst timespec_t\fR \fInstimes[2]\fR);
 
-\fBint\fR \fButimensat\fR(\fBint\fR \fIfiledes\fR, \fBconst char *\fR\fIpath\fR,
+\fBint\fR \fButimensat\fR(\fBint\fR \fIfildes\fR, \fBconst char *\fR\fIpath\fR,
     \fBconst timespec_t\fR \fInstimes[2]\fR, \fBint\fR \fIflag\fR);
 
 .SH DESCRIPTION
-.LP
 The \fButimes()\fR function sets the access and modification times of the file
 pointed to by the \fIpath\fR argument to the value of the \fItimes\fR argument.
 It allows time specifications accurate to the microsecond.
 .sp
 .LP
+The \fBlutimes()\fR function operates like \fButimes()\fR except if \fIpath\fR
+points to a symbolic link; in that case \fBlutimes()\fR changes the access and
+modifications times of the link, while \fButimes()\fR changes the file that
+is referenced by the link.
+.sp
+.LP
+The \fBfutimes()\fR function sets the access and modification times of the
+file referenced by the file descriptor \fIfildes\fR.
+.sp
+.LP
 The \fBfutimesat()\fR function also sets access and modification times.  See
 \fBfsattr\fR(5). If \fIpath\fR is a relative path name, however,
 \fBfutimesat()\fR resolves the path relative to the \fIfildes\fR argument
@@ -84,7 +103,7 @@
 \fBAT_FDCWD\fR, defined in <\fBfcntl.h\fR>, \fBfutimesat()\fR resolves the path
 relative to the current working directory.  If \fIpath\fR is a null pointer,
 \fBfutimesat()\fR sets the access and modification times on the file referenced
-by \fIfildes\fR. The \fIfildes\fR argument is ignored even when
+by \fIfildes\fR. The \fIfildes\fR argument is ignored if
 \fBfutimesat()\fR is provided with an absolute path.
 .sp
 .LP
@@ -107,28 +126,28 @@
 modification times; however, instead of taking \fBstruct timeval\fR, they take
 \fBtimespec_t\fR which allows for nanosecond granularity. The \fBfutimens()\fR
 function sets the access and modification times on the file descriptor
-referenced by \fIfiledes\fR.
+referenced by \fIfildes\fR.
 .sp
 .LP
 The \fButimensat()\fR function determines the file to set the access and
-modification times in an similar way to \fBfutemsat()\fR. If the argument
-\fIpath\fR is an absolute path, then the argument \fIfiledes\fR is ignored;
+modification times in an similar way to \fBfutimesat()\fR. If the argument
+\fIpath\fR is an absolute path, then the argument \fIfildes\fR is ignored;
 otherwise, \fIpath\fR is interpreted as a path relative to the directory
-specified by \fIfiledes\fR. If \fIfiledes\fR is set to \fBAT_FDCWD\fR, then
+specified by \fIfildes\fR. If \fIfildes\fR is set to \fBAT_FDCWD\fR, then
 \fIpath\fR is resolved relative to the current working directory. The behavior
 when encountering symbolic links may be controlled by the value of the
 \fIflag\fR argument. If the value of flag is the constant
 \fBAT_SYMLINK_NOFOLLOW\fR, then when a symbolic link is encountered while
 resolving a path, it will not be followed. Otherwise, the value of \fIflag\fR
-should be \fB0\fR.
+should be \fB0\fR. Note that, unlike \fBfutimesat()\fR, \fButimensat()\fR
+does not accept a null pointer for the \fIpath\fR argument.
 .SH RETURN VALUES
-.LP
 Upon successful completion, \fB0\fR is returned.  Otherwise, \fB\(mi1\fR is
 returned, \fBerrno\fR is set to indicate the error, and the file times will not
 be affected.
 .SH ERRORS
-.LP
-The \fButimes()\fR, \fBfutimesat()\fR, \fBfutimens()\fR, and \fButimensat()\fR
+The \fButimes()\fR, \fBlutimes()\fR, \fBfutimes()\fR, \fBfutimesat()\fR,
+\fBfutimens()\fR, and \fButimensat()\fR
 functions will fail if:
 .sp
 .ne 2
@@ -147,9 +166,7 @@
 \fB\fBEFAULT\fR\fR
 .ad
 .RS 16n
-The \fIpath\fR or \fItimes\fR argument points to an illegal address. For
-\fBfutimesat()\fR, \fIpath\fR might have the value \fINULL\fR if the
-\fIfildes\fR argument refers to a valid open file descriptor.
+The \fIpath\fR or \fItimes\fR argument points to an illegal address.
 .RE
 
 .sp
@@ -159,6 +176,7 @@
 .ad
 .RS 16n
 A signal was caught during the execution of the \fButimes()\fR,
+\fBlutimes()\fR, \fBfutimes()\fR,
 \fBfutimesat()\fR, \fBfutimens()\fR, or \fButimensat()\fR functions.
 .RE
 
@@ -270,7 +288,6 @@
 .RE
 
 .SH ATTRIBUTES
-.LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
 
@@ -290,6 +307,5 @@
 .LP
 For \fButimes()\fR, \fButimensat()\fR and \fBfutimensat()\fR, see \fBstandards\fR(5).
 .SH SEE ALSO
-.LP
-\fBfutimens\fR(2), \fBstat\fR(2), \fButime\fR(2), \fBattributes\fR(5),
+fBstat\fR(2), \fButime\fR(2), \fBattributes\fR(5),
 \fBfsattr\fR(5), \fBstandards\fR(5)
--- old/usr/src/man/man3head/Makefile	Mon Sep 14 14:49:08 2020
+++ new/usr/src/man/man3head/Makefile	Mon Sep 14 14:49:08 2020
@@ -13,6 +13,7 @@
 # Copyright 2011, Richard Lowe
 # Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2014 Garrett D'Amore <garrett@damore.org>
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
 #
 
 include		$(SRC)/Makefile.master
@@ -93,6 +94,7 @@
 		time.h.3head		\
 		timeb.h.3head		\
 		times.h.3head		\
+		timespec.3head		\
 		types.h.3head		\
 		types32.h.3head		\
 		uchar.h.3head		\
@@ -273,6 +275,9 @@
 		time.3head		\
 		timeb.3head		\
 		times.3head		\
+		timeval.3head		\
+		TIMEVAL_TO_TIMESPEC.3head \
+		TIMESPEC_TO_TIMEVAL.3head \
 		types.3head		\
 		types32.3head		\
 		ucontext.3head		\
@@ -451,6 +456,10 @@
 time.3head		:= LINKSRC = time.h.3head
 timeb.3head		:= LINKSRC = timeb.h.3head
 times.3head		:= LINKSRC = times.h.3head
+timespec.3head		:= LINKSRC = time.h.3head
+timeval.3head		:= LINKSRC = timespec.3head
+TIMEVAL_TO_TIMESPEC.3head := LINKSRC = timespec.3head
+TIMESPEC_TO_TIMEVAL.3head := LINKSRC = timespec.3head
 types.3head		:= LINKSRC = types.h.3head
 types32.3head		:= LINKSRC = types32.h.3head
 ucontext.3head		:= LINKSRC = ucontext.h.3head
--- /dev/null	Mon Sep 14 14:49:08 2020
+++ new/usr/src/man/man3head/timespec.3head	Mon Sep 14 14:49:08 2020
@@ -0,0 +1,106 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source.  A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
+.\"
+.Dd Sep 06, 2020
+.Dt timespec 3HEAD
+.Os
+.Sh NAME
+.Nm timespec ,
+.Nm timeval ,
+.Nm TIMESPEC_TO_TIMEVAL ,
+.Nm TIMEVAL_TO_TIMESPEC
+.Nd time structures and conversion
+.Sh SYNOPSIS
+.In sys/time.h
+.Ft void
+.Fo TIMESPEC_TO_TIMEVAL
+.Fa "struct timeval *tv"
+.Fa "const struct timespec *ts"
+.Fc
+.Ft void
+.Fo TIMEVAL_TO_TIMESPEC
+.Fa "const struct timeval *tv"
+.Fa "struct timespec *ts"
+.Fc
+.Sh DESCRIPTION
+The
+.Vt timeval
+and
+.Vt timespec
+structures are declared in the
+.In time.h
+and
+.In sys/time.h
+headers respectively:
+.Bd -literal -offset indent
+typedef struct timespec {
+	time_t		tv_sec;		/* seconds */
+	long		tv_nsec;	/* and nanoseconds */
+} timespec_t;
+
+struct timeval {
+	time_t		tv_sec;		/* seconds */
+	suseconds_t	tv_usec;	/* and microseconds */
+};
+.Ed
+.Pp
+In both cases, the
+.Fa tv_sec
+member represents elapsed time in whole seconds.
+The
+.Fa tv_nsec
+and
+.Fa tv_usec
+members represent the rest of the elapsed time in nanoseconds and
+microseconds respectively, depending on the structure.
+.Pp
+The
+.Dv TIMEVAL_TO_TIMESPEC
+macro can be used to convert a
+.Vt struct timeval
+structure to a
+.Vt struct timespec
+structure, while the
+.Dv TIMESPEC_TO_TIMEVAL
+macro works in the opposite direction.
+.Pp
+When converting from a
+.Vt struct timespec
+to a
+.Vt struct timeval
+structure, the
+.Fa tv_nsec
+member is truncated, losing precision.
+When converting from a
+.Vt struct timeval
+to a
+.Vt struct timespec
+structure, the
+.Fa tv_usec
+member is multiplied by 1000 to reach the precision of the target
+structure.
+The
+.Fa tv_sec
+member is always preserved, no matter which conversion is performed.
+.Pp
+Note that the
+.Dv TIMEVAL_TO_TIMESPEC
+and
+.Dv TIMESPEC_TO_TIMEVAL
+macros are non-standard but are commonly found on UNIX and UNIX-like systems.
+.Sh INTERFACE STABILITY
+.Sy Committed
+.Sh MT-LEVEL
+.Sy MT-Safe
+.Sh SEE ALSO
+.Xr time.h 3HEAD
--- old/usr/src/man/man3lib/libc.3lib	Mon Sep 14 14:49:08 2020
+++ new/usr/src/man/man3lib/libc.3lib	Mon Sep 14 14:49:09 2020
@@ -7,7 +7,7 @@
 .\"  See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with
 .\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
 .\" Copyright 2011 by Delphix.  All rights reserved.
-.TH LIBC 3LIB "Feb 14, 2020"
+.TH LIBC 3LIB "Sep 06, 2020"
 .SH NAME
 libc \- C library
 .SH DESCRIPTION
@@ -261,130 +261,131 @@
 \fBftok\fR	\fBftruncate\fR
 \fBftrylockfile\fR	\fBftw\fR
 \fBfunc_to_decimal\fR	\fBfunlockfile\fR
-\fBfutimens\fR	\fBfutimesat\fR
-\fBfwide\fR	\fBfwprintf\fR
-\fBfwrite\fR	\fBfwscanf\fR
-\fBgconvert\fR	\fBgcvt\fR
-\fBgetacct\fR	\fBgetattrat\fR
-\fBgetc\fR	\fBgetc_unlocked\fR
-\fBgetchar\fR	\fBgetchar_unlocked\fR
-\fBgetcontext\fR	\fBgetcpuid\fR
-\fBgetcwd\fR	\fBgetdate\fR
-\fBgetdate_err\fR	\fBgetdents\fR
-\fBgetdtablesize\fR	\fBgetegid\fR
-\fBgetenv\fR	\fBgeteuid\fR
-\fBgetexecname\fR	\fBgetextmntent\fR
-\fBgetgid\fR	\fBgetgrent\fR
-\fBgetgrent_r\fR	\fBgetgrgid\fR
-\fBgetgrgid_r\fR	\fBgetgrnam\fR
-\fBgetgrnam_r\fR	\fBgetgroups\fR
-\fBgethomelgroup\fR	\fBgethostid\fR
-\fBgethostname\fR	\fBgethrtime\fR
-\fBgethrvtime\fR	\fBgetisax\fR
-\fBgetitimer\fR	\fBgetloadavg\fR
-\fBgetlogin\fR	\fBgetlogin_r\fR
-\fBgetmntany\fR	\fBgetmntent\fR
-\fBgetmsg\fR	\fBget_nprocs\fR
-\fBget_nprocs_conf\fR	\fBgetnetgrent\fR
-\fBgetnetgrent_r\fR	\fBgetopt\fR
-\fBgetopt_clip\fR	\fBgetopt_long\fR
-\fBgetopt_long_only\fR	\fBgetpagesize\fR
-\fBgetpagesizes\fR	\fBgetpass\fR
-\fBgetpassphrase\fR	\fBgetpeerucred\fR
-\fBgetpflags\fR	\fBgetpgid\fR
-\fBgetpgrp\fR	\fBgetpid\fR
-\fBgetpmsg\fR	\fBgetppid\fR
-\fBgetppriv\fR	\fBgetpriority\fR
-\fBgetprogname\fR	\fBgetprojid\fR
-\fBgetpw\fR	\fBgetpwent\fR
-\fBgetpwent_r\fR	\fBgetpwnam\fR
-\fBgetpwnam_r\fR	\fBgetpwuid\fR
-\fBgetpwuid_r\fR	\fBgetrctl\fR
-\fBgetrlimit\fR	\fBgetrusage\fR
-\fBgets\fR	\fBgetsid\fR
-\fBgetspent\fR	\fBgetspent_r\fR
-\fBgetspnam\fR	\fBgetspnam_r\fR
-\fBgetsubopt\fR	\fBgettaskid\fR
-\fBgettext\fR	\fBgettimeofday\fR
-\fBgettxt\fR	\fBgetuid\fR
-\fBgetusershell\fR	\fBgetustack\fR
-\fBgetutent\fR	\fBgetutid\fR
-\fBgetutline\fR	\fBgetutmp\fR
-\fBgetutmpx\fR	\fBgetutxent\fR
-\fBgetutxid\fR	\fBgetutxline\fR
-\fBgetvfsany\fR	\fBgetvfsent\fR
-\fBgetvfsfile\fR	\fBgetvfsspec\fR
-\fBgetw\fR	\fBgetwc\fR
-\fBgetwc_l\fR	\fBgetwchar\fR
-\fBgetwchar_l\fR	\fBgetwd\fR
-\fBgetwidth\fR	\fBgetws\fR
-\fBgetzoneid\fR	\fBgetzoneidbyname\fR
-\fBgetzonenamebyid\fR	\fBglob\fR
-\fBglobfree\fR	\fBgmtime\fR
-\fBgmtime_r\fR	\fBgrantpt\fR
-\fBgsignal\fR	\fBhasmntopt\fR
-\fBhcreate\fR	\fBhdestroy\fR
-\fBhsearch\fR	\fBiconv\fR
-\fBiconv_close\fR	\fBiconv_open\fR
-\fBimaxabs\fR	\fBimaxdiv\fR
-\fBindex\fR	\fBinitgroups\fR
-\fBinitstate\fR	\fBinnetgr\fR
-\fBinsque\fR	\fBioctl\fR
-\fBis_system_labeled\fR	\fBisaexec\fR
-\fBisalnum\fR	\fBisalnum_l\fR
-\fBisalpha\fR	\fBisalpha_l\fR
-\fBisascii\fR	\fBisastream\fR
-\fBisatty\fR	\fBisblank\fR
-\fBisblank_l\fR	\fBiscntrl\fR
-\fBiscntrl_l\fR	\fBisdigit\fR
-\fBisdigit_l\fR	\fBisenglish\fR
-\fBisgraph\fR	\fBisgraph_l\fR
-\fBisideogram\fR	\fBislower\fR
-\fBislower_l\fR	\fBisnan\fR
-\fBisnand\fR	\fBisnanf\fR
-\fBisnumber\fR	\fBisphonogram\fR
-\fBisprint\fR	\fBisprint_l\fR
-\fBispunct\fR	\fBispunct_l\fR
-\fBissetugid\fR	\fBisspace\fR
-\fBisspace_l\fR	\fBisspecial\fR
-\fBisupper\fR	\fBisupper_l\fR
-\fBiswalnum\fR	\fBiswalnum_l\fR
-\fBiswalpha\fR	\fBiswalpha_l\fR
-\fBiswblank\fR	\fBiswblank_l\fR
-\fBiswcntrl\fR	\fBiswcntrl_l\fR
-\fBiswctype\fR	\fBiswctype_l\fR
-\fBiswdigit\fR	\fBiswdigit_l\fR
-\fBiswideogram\fR	\fBiswideogram_l\fR
-\fBiswgraph\fR	\fBiswgraph_l\fR
-\fBiswhexnumber\fR	\fBiswhexnumber_l\fR
-\fBiswlower\fR	\fBiswlower_l\fR
-\fBiswnumber\fR	\fBiswnumber_l\fR
-\fBiswphonogram\fR	\fBiswphonogram_l\fR
-\fBiswprint\fR	\fBiswprint_l\fR
-\fBiswpunct\fR	\fBiswpunct_l\fR
-\fBiswspace\fR	\fBiswspace_l\fR
-\fBiswspecial\fR	\fBiswspecial_l\fR
-\fBiswupper\fR	\fBiswupper_l\fR
-\fBiswxdigit\fR	\fBiswxdigit_l\fR
-\fBisxdigit\fR	\fBisxdigit_l\fR
-\fBjrand48\fR	\fBkill\fR
-\fBkillpg\fR	\fBl64a\fR
-\fBlabs\fR	\fBladd\fR
-\fBlchown\fR	\fBlckpwdf\fR
-\fBlcong48\fR	\fBldexp\fR
-\fBldivide\fR	\fBlexp10\fR
-\fBlfind\fR	\fBlfmt\fR
-\fBlink\fR	\fBlinkat\fR
-\fBlio_listio\fR	\fBllabs\fR
-\fBlldiv\fR	\fBllog10\fR
-\fBllseek\fR	\fBlltostr\fR
-\fBlocaleconv\fR	\fBlocaltime\fR
-\fBlocaltime_r\fR	\fBlockf\fR
-\fBlogb\fR	\fBlone\fR
-\fBlongjmp\fR	\fBlrand48\fR
-\fBlsearch\fR	\fBlseek\fR
-\fBlshiftl\fR	\fBlstat\fR
-\fBlsub\fR	\fBlten\fR
+\fBfutimens\fR	\fBfutimes\fR
+\fBfutimesat\fR	\fBfwide\fR
+\fBfwprintf\fR	\fBfwrite\fR
+\fBfwscanf\fR	\fBgconvert\fR
+\fBgcvt\fR	\fBgetacct\fR
+\fBgetattrat\fR	\fBgetc\fR
+\fBgetc_unlocked\fR	\fBgetchar\fR
+\fBgetchar_unlocked\fR	\fBgetcontext\fR
+\fBgetcpuid\fR	\fBgetcwd\fR
+\fBgetdate\fR	\fBgetdate_err\fR
+\fBgetdents\fR	\fBgetdtablesize\fR
+\fBgetegid\fR	\fBgetenv\fR
+\fBgeteuid\fR	\fBgetexecname\fR
+\fBgetextmntent\fR	\fBgetgid\fR
+\fBgetgrent\fR	\fBgetgrent_r\fR
+\fBgetgrgid\fR	\fBgetgrgid_r\fR
+\fBgetgrnam\fR	\fBgetgrnam_r\fR
+\fBgetgroups\fR	\fBgethomelgroup\fR
+\fBgethostid\fR	\fBgethostname\fR
+\fBgethrtime\fR	\fBgethrvtime\fR
+\fBgetisax\fR	\fBgetitimer\fR
+\fBgetloadavg\fR	\fBgetlogin\fR
+\fBgetlogin_r\fR	\fBgetmntany\fR
+\fBgetmntent\fR	\fBgetmsg\fR
+\fBget_nprocs\fR	\fBget_nprocs_conf\fR
+\fBgetnetgrent\fR	\fBgetnetgrent_r\fR
+\fBgetopt\fR	\fBgetopt_clip\fR
+\fBgetopt_long\fR	\fBgetopt_long_only\fR
+\fBgetpagesize\fR	\fBgetpagesizes\fR
+\fBgetpass\fR	\fBgetpassphrase\fR
+\fBgetpeerucred\fR	\fBgetpflags\fR
+\fBgetpgid\fR	\fBgetpgrp\fR
+\fBgetpid\fR	\fBgetpmsg\fR
+\fBgetppid\fR	\fBgetppriv\fR
+\fBgetpriority\fR	\fBgetprogname\fR
+\fBgetprojid\fR	\fBgetpw\fR
+\fBgetpwent\fR	\fBgetpwent_r\fR
+\fBgetpwnam\fR	\fBgetpwnam_r\fR
+\fBgetpwuid\fR	\fBgetpwuid_r\fR
+\fBgetrctl\fR	\fBgetrlimit\fR
+\fBgetrusage\fR	\fBgets\fR
+\fBgetsid\fR	\fBgetspent\fR
+\fBgetspent_r\fR	\fBgetspnam\fR
+\fBgetspnam_r\fR	\fBgetsubopt\fR
+\fBgettaskid\fR	\fBgettext\fR
+\fBgettimeofday\fR	\fBgettxt\fR
+\fBgetuid\fR	\fBgetusershell\fR
+\fBgetustack\fR	\fBgetutent\fR
+\fBgetutid\fR	\fBgetutline\fR
+\fBgetutmp\fR	\fBgetutmpx\fR
+\fBgetutxent\fR	\fBgetutxid\fR
+\fBgetutxline\fR	\fBgetvfsany\fR
+\fBgetvfsent\fR	\fBgetvfsfile\fR
+\fBgetvfsspec\fR	\fBgetw\fR
+\fBgetwc\fR	\fBgetwc_l\fR
+\fBgetwchar\fR	\fBgetwchar_l\fR
+\fBgetwd\fR	\fBgetwidth\fR
+\fBgetws\fR	\fBgetzoneid\fR
+\fBgetzoneidbyname\fR	\fBgetzonenamebyid\fR
+\fBglob\fR	\fBglobfree\fR
+\fBgmtime\fR	\fBgmtime_r\fR
+\fBgrantpt\fR	\fBgsignal\fR
+\fBhasmntopt\fR	\fBhcreate\fR
+\fBhdestroy\fR	\fBhsearch\fR
+\fBiconv\fR	\fBiconv_close\fR
+\fBiconv_open\fR	\fBimaxabs\fR
+\fBimaxdiv\fR	\fBindex\fR
+\fBinitgroups\fR	\fBinitstate\fR
+\fBinnetgr\fR	\fBinsque\fR
+\fBioctl\fR	\fBis_system_labeled\fR
+\fBisaexec\fR	\fBisalnum\fR
+\fBisalnum_l\fR	\fBisalpha\fR
+\fBisalpha_l\fR	\fBisascii\fR
+\fBisastream\fR	\fBisatty\fR
+\fBisblank\fR	\fBisblank_l\fR
+\fBiscntrl\fR	\fBiscntrl_l\fR
+\fBisdigit\fR	\fBisdigit_l\fR
+\fBisenglish\fR	\fBisgraph\fR
+\fBisgraph_l\fR	\fBisideogram\fR
+\fBislower\fR	\fBislower_l\fR
+\fBisnan\fR	\fBisnand\fR
+\fBisnanf\fR	\fBisnumber\fR
+\fBisphonogram\fR	\fBisprint\fR
+\fBisprint_l\fR	\fBispunct\fR
+\fBispunct_l\fR	\fBissetugid\fR
+\fBisspace\fR	\fBisspace_l\fR
+\fBisspecial\fR	\fBisupper\fR
+\fBisupper_l\fR	\fBiswalnum\fR
+\fBiswalnum_l\fR	\fBiswalpha\fR
+\fBiswalpha_l\fR	\fBiswblank\fR
+\fBiswblank_l\fR	\fBiswcntrl\fR
+\fBiswcntrl_l\fR	\fBiswctype\fR
+\fBiswctype_l\fR	\fBiswdigit\fR
+\fBiswdigit_l\fR	\fBiswideogram\fR
+\fBiswideogram_l\fR	\fBiswgraph\fR
+\fBiswgraph_l\fR	\fBiswhexnumber\fR
+\fBiswhexnumber_l\fR	\fBiswlower\fR
+\fBiswlower_l\fR	\fBiswnumber\fR
+\fBiswnumber_l\fR	\fBiswphonogram\fR
+\fBiswphonogram_l\fR	\fBiswprint\fR
+\fBiswprint_l\fR	\fBiswpunct\fR
+\fBiswpunct_l\fR	\fBiswspace\fR
+\fBiswspace_l\fR	\fBiswspecial\fR
+\fBiswspecial_l\fR	\fBiswupper\fR
+\fBiswupper_l\fR	\fBiswxdigit\fR
+\fBiswxdigit_l\fR	\fBisxdigit\fR
+\fBisxdigit_l\fR	\fBjrand48\fR
+\fBkill\fR	\fBkillpg\fR
+\fBl64a\fR	\fBlabs\fR
+\fBladd\fR	\fBlchown\fR
+\fBlckpwdf\fR	\fBlcong48\fR
+\fBldexp\fR	\fBldivide\fR
+\fBlexp10\fR	\fBlfind\fR
+\fBlfmt\fR	\fBlink\fR
+\fBlinkat\fR	\fBlio_listio\fR
+\fBllabs\fR	\fBlldiv\fR
+\fBllog10\fR	\fBllseek\fR
+\fBlltostr\fR	\fBlocaleconv\fR
+\fBlocaltime\fR	\fBlocaltime_r\fR
+\fBlockf\fR	\fBlogb\fR
+\fBlone\fR	\fBlongjmp\fR
+\fBlrand48\fR	\fBlsearch\fR
+\fBlseek\fR	\fBlshiftl\fR
+\fBlstat\fR	\fBlsub\fR
+\fBlten\fR	\fBlutimes\fR
 \fBlzero\fR	\fBmadvise\fR
 \fBmakecontext\fR	\fBmakeutx\fR
 \fBmalloc\fR	\fBmblen\fR
--- old/usr/src/pkg/manifests/system-header.mf	Mon Sep 14 14:49:09 2020
+++ new/usr/src/pkg/manifests/system-header.mf	Mon Sep 14 14:49:09 2020
@@ -28,6 +28,7 @@
 # Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
 # Copyright 2020 Joyent, Inc.
 # Copyright 2019 Peter Tribble.
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
 #
 
 set name=pkg.fmri value=pkg:/system/header@$(PKGVERS)
@@ -1909,6 +1910,7 @@
 file path=usr/share/man/man3head/time.h.3head
 file path=usr/share/man/man3head/timeb.h.3head
 file path=usr/share/man/man3head/times.h.3head
+file path=usr/share/man/man3head/timespec.3head
 file path=usr/share/man/man3head/types.h.3head
 file path=usr/share/man/man3head/types32.h.3head
 file path=usr/share/man/man3head/uchar.h.3head
@@ -2113,6 +2115,10 @@
 link path=usr/share/man/man3head/TAILQ_PREV.3head target=queue.h.3head
 link path=usr/share/man/man3head/TAILQ_REMOVE.3head target=queue.h.3head
 link path=usr/share/man/man3head/TAILQ_SWAP.3head target=queue.h.3head
+link path=usr/share/man/man3head/TIMESPEC_TO_TIMEVAL.3head \
+    target=timespec.3head
+link path=usr/share/man/man3head/TIMEVAL_TO_TIMESPEC.3head \
+    target=timespec.3head
 link path=usr/share/man/man3head/acct.3head target=acct.h.3head
 link path=usr/share/man/man3head/aio.3head target=aio.h.3head
 link path=usr/share/man/man3head/ar.3head target=ar.h.3head
@@ -2186,6 +2192,7 @@
 link path=usr/share/man/man3head/time.3head target=time.h.3head
 link path=usr/share/man/man3head/timeb.3head target=timeb.h.3head
 link path=usr/share/man/man3head/times.3head target=times.h.3head
+link path=usr/share/man/man3head/timeval.3head target=timespec.3head
 link path=usr/share/man/man3head/types.3head target=types.h.3head
 link path=usr/share/man/man3head/types32.3head target=types32.h.3head
 link path=usr/share/man/man3head/ucontext.3head target=ucontext.h.3head
--- old/usr/src/pkg/manifests/system-kernel.man2.inc	Mon Sep 14 14:49:10 2020
+++ new/usr/src/pkg/manifests/system-kernel.man2.inc	Mon Sep 14 14:49:10 2020
@@ -15,6 +15,7 @@
 # Copyright 2013, OmniTI Computer Consulting, Inc.
 # Copyright 2017 Peter Tribble
 # Copyright 2018, Joyent, Inc.
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
 #
 
 file path=usr/share/man/man2/Intro.2
@@ -192,6 +193,7 @@
 link path=usr/share/man/man2/fstatat.2 target=stat.2
 link path=usr/share/man/man2/fstatvfs.2 target=statvfs.2
 link path=usr/share/man/man2/futimens.2 target=utimes.2
+link path=usr/share/man/man2/futimes.2 target=utimes.2
 link path=usr/share/man/man2/futimesat.2 target=utimes.2
 link path=usr/share/man/man2/getaudit_addr.2 target=getaudit.2
 link path=usr/share/man/man2/getegid.2 target=getuid.2
@@ -205,9 +207,10 @@
 link path=usr/share/man/man2/getrctl.2 target=setrctl.2
 link path=usr/share/man/man2/gettaskid.2 target=settaskid.2
 link path=usr/share/man/man2/intro.2 target=Intro.2
-link path=usr/share/man/man2/linkat.2 target=link.2
 link path=usr/share/man/man2/lchown.2 target=chown.2
+link path=usr/share/man/man2/linkat.2 target=link.2
 link path=usr/share/man/man2/lstat.2 target=stat.2
+link path=usr/share/man/man2/lutimes.2 target=utimes.2
 link path=usr/share/man/man2/mkdirat.2 target=mkdir.2
 link path=usr/share/man/man2/mknodat.2 target=mknod.2
 link path=usr/share/man/man2/openat.2 target=open.2
--- old/usr/src/pkg/manifests/system-test-libctest.mf	Mon Sep 14 14:49:10 2020
+++ new/usr/src/pkg/manifests/system-test-libctest.mf	Mon Sep 14 14:49:10 2020
@@ -14,6 +14,7 @@
 # Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
 # Copyright 2015 Garrett D'Amore <garrett@damore.org>
 # Copyright 2018 Joyent, Inc.
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
 #
 
 set name=pkg.fmri value=pkg:/system/test/libctest@$(PKGVERS)
@@ -189,6 +190,8 @@
 file path=opt/libc-tests/tests/timespec_get.64 mode=0555
 file path=opt/libc-tests/tests/uchar.32 mode=0555
 file path=opt/libc-tests/tests/uchar.64 mode=0555
+file path=opt/libc-tests/tests/utimes.32 mode=0555
+file path=opt/libc-tests/tests/utimes.64 mode=0555
 file path=opt/libc-tests/tests/wcsncasecmp-7344.32 mode=0555
 file path=opt/libc-tests/tests/wcsncasecmp-7344.64 mode=0555
 file path=opt/libc-tests/tests/wcsncasecmp-7350.32 mode=0555
--- old/usr/src/prototypes/prototype.man3x	Mon Sep 14 14:49:10 2020
+++ new/usr/src/prototypes/prototype.man3x	Mon Sep 14 14:49:10 2020
@@ -59,7 +59,7 @@
 A Reason why ERRNO2 could occur.
 .El
 .Sh INTERFACE STABILITY
-.\" Indicate the stability per attribute(5). One of:
+.\" Indicate the stability per attributes(5). One of:
 .\" .Sy Committed
 .\" .Sy Uncommitted
 .\" .Sy Volatile
--- old/usr/src/test/libc-tests/cfg/symbols/sys_time_h.cfg	Mon Sep 14 14:49:10 2020
+++ new/usr/src/test/libc-tests/cfg/symbols/sys_time_h.cfg	Mon Sep 14 14:49:10 2020
@@ -11,6 +11,7 @@
 
 #
 # Copyright 2015 Garrett D'Amore <garrett@damore.org>
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
 #
 
 #
@@ -40,3 +41,16 @@
 	int						|\
 	const char *; const struct timeval [2]		|\
 	sys/time.h | -POSIX+ -XPG3+ SUS+
+
+func |	lutimes						|\
+	int						|\
+	const char *; const struct timeval [2]		|\
+	sys/time.h | -ALL
+
+func |	futimes						|\
+	int						|\
+	int; const struct timeval [2]			|\
+	sys/time.h | -ALL
+
+define | TIMEVAL_TO_TIMESPEC | | sys/time.h | -ALL
+define | TIMESPEC_TO_TIMEVAL | | sys/time.h | -ALL
--- old/usr/src/test/libc-tests/runfiles/default.run	Mon Sep 14 14:49:11 2020
+++ new/usr/src/test/libc-tests/runfiles/default.run	Mon Sep 14 14:49:11 2020
@@ -13,6 +13,7 @@
 # Copyright (c) 2012 by Delphix. All rights reserved.
 # Copyright 2014 Garrett D'Amore <garrett@damore.org>
 # Copyright 2019 Joyent, Inc.
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
 #
 
 [DEFAULT]
@@ -116,6 +117,8 @@
 [/opt/libc-tests/tests/timespec_get.64]
 [/opt/libc-tests/tests/uchar.32]
 [/opt/libc-tests/tests/uchar.64]
+[/opt/libc-tests/tests/utimes.32]
+[/opt/libc-tests/tests/utimes.64]
 
 [/opt/libc-tests/tests/pthread_attr_get_np]
 
--- old/usr/src/test/libc-tests/tests/Makefile	Mon Sep 14 14:49:11 2020
+++ new/usr/src/test/libc-tests/tests/Makefile	Mon Sep 14 14:49:11 2020
@@ -13,6 +13,7 @@
 # Copyright (c) 2012 by Delphix. All rights reserved.
 # Copyright 2015 Garrett D'Amore <garrett@damore.org>
 # Copyright 2019 Joyent, Inc.
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
 #
 
 SUBDIRS = \
@@ -52,7 +53,8 @@
 	wcsncasecmp \
 	wcsncasecmp-7344 \
 	wcsncasecmp-7350 \
-	uchar
+	uchar \
+	utimes
 
 SCRIPTS = \
 	quick_exit \
--- /dev/null	Mon Sep 14 14:49:11 2020
+++ new/usr/src/test/libc-tests/tests/utimes.c	Mon Sep 14 14:49:11 2020
@@ -0,0 +1,521 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
+ */
+
+/*
+ * Test the implementation of the various *utimes() and *utimens() functions
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+timespec_t testtimes[] = {
+	{
+		.tv_sec = 1280793678,
+		.tv_nsec = 123456789
+	},
+	{
+		.tv_sec = 1492732800,
+		.tv_nsec = 17
+	},
+	{
+		.tv_sec = 1320796855,
+		.tv_nsec = 9
+	},
+	{
+		.tv_sec = 1498953611,
+		.tv_nsec = 987654321
+	}
+};
+
+enum ttype {
+	UTIMES,
+	LUTIMES,
+	FUTIMES,
+	FUTIMESAT,
+	FUTIMENS,
+	UTIMENSAT
+};
+
+static bool
+compare_times(struct stat *st, bool trunc, timespec_t *atim, timespec_t *mtim,
+    bool invert)
+{
+	bool ret = true;
+
+	if (st->st_atim.tv_sec != atim->tv_sec) {
+		ret = false;
+	} else if (st->st_atim.tv_nsec != (
+	    trunc ? atim->tv_nsec / 1000 * 1000 : atim->tv_nsec)) {
+		ret = false;
+	} else if (st->st_mtim.tv_sec != mtim->tv_sec) {
+		ret = false;
+	} else if (st->st_mtim.tv_nsec != (
+	    trunc ? mtim->tv_nsec / 1000 * 1000 : mtim->tv_nsec)) {
+		ret = false;
+	}
+
+	if ((!ret && !invert) || (ret && invert)) {
+		printf("    actual atime: %ld.%.9ld\n",
+		    st->st_atim.tv_sec, st->st_atim.tv_nsec);
+		printf("    actual mtime: %ld.%.9ld\n",
+		    st->st_mtim.tv_sec, st->st_mtim.tv_nsec);
+	}
+
+	return (ret);
+}
+
+static bool
+compare_filetime(char *path, bool trunc, timespec_t *atim, timespec_t *mtim,
+    bool invert)
+{
+	struct stat st;
+
+	if (stat(path, &st) == -1)
+		err(EXIT_FAILURE, "stat %s", path);
+
+	return (compare_times(&st, trunc, atim, mtim, invert));
+}
+
+static bool
+compare_linktime(char *path, bool trunc, timespec_t *atim, timespec_t *mtim,
+    bool invert)
+{
+	struct stat st;
+
+	if (lstat(path, &st) == -1)
+		err(EXIT_FAILURE, "lstat %s", path);
+
+	return (compare_times(&st, trunc, atim, mtim, invert));
+}
+
+static bool
+reset(char *path, timespec_t *atim, timespec_t *mtim)
+{
+	if (utimes(path, NULL) == -1)
+		err(EXIT_FAILURE, "utimes reset");
+	if (compare_filetime(path, true, atim, mtim, true)) {
+		warnx("reset failed");
+		return (false);
+	}
+	return (true);
+}
+
+static bool
+reset_link(char *lpath, timespec_t *atim, timespec_t *mtim)
+{
+	if (lutimes(lpath, NULL) == -1)
+		err(EXIT_FAILURE, "lutimes reset");
+	if (compare_linktime(lpath, true, atim, mtim, true)) {
+		warnx("link reset failed");
+		return (false);
+	}
+	return (true);
+}
+
+static bool
+runtest(enum ttype fn, char *dir, timespec_t *atim, timespec_t *mtim)
+{
+	char path[MAXPATHLEN + 1];
+	char lpath[MAXPATHLEN + 1];
+	struct timespec ts[2];
+	struct timeval tv[2];
+	int fd, lfd, dfd, ret = true;
+
+	ts[0] = *atim;
+	ts[1] = *mtim;
+	TIMESPEC_TO_TIMEVAL(&tv[0], &ts[0]);
+	TIMESPEC_TO_TIMEVAL(&tv[1], &ts[1]);
+
+	if (snprintf(path, sizeof (path), "%s/file", dir) >= sizeof (path))
+		err(EXIT_FAILURE, "snprintf failed to build file path");
+
+	if ((fd = open(path, O_CREAT, 0644)) == -1)
+		err(EXIT_FAILURE, "open file %s", path);
+
+	if (snprintf(lpath, sizeof (lpath), "%s/link", dir) >= sizeof (path))
+		err(EXIT_FAILURE, "snprintf failed to build link path");
+
+	if (symlink(path, lpath) == -1)
+		err(EXIT_FAILURE, "link(%s)", lpath);
+
+	if ((lfd = open(lpath, O_RDWR)) == -1)
+		err(EXIT_FAILURE, "open link(%s)", lpath);
+
+	if ((dfd = open(dir, O_DIRECTORY|O_RDONLY)) == -1)
+		err(EXIT_FAILURE, "open dir(%s)", dir);
+
+	switch (fn) {
+	case UTIMES:
+		printf("..... utimes()\n");
+
+		if (utimes(path, tv) == -1)
+			err(EXIT_FAILURE, "utimes(%s)", path);
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed on file");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* repeat against symbolic link path */
+		if (utimes(lpath, tv) == -1)
+			err(EXIT_FAILURE, "utimes(%s), link", lpath);
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed on file through link");
+			ret = false;
+		}
+
+		break;
+
+	case LUTIMES:
+		printf("..... lutimes()\n");
+
+		/* Use lutimes() against a plain file */
+		if (lutimes(path, tv) == -1)
+			err(EXIT_FAILURE, "lutimes(%s)", path);
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed on file");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* Set the time on the link, not on the target */
+		if (lutimes(lpath, tv) == -1)
+			err(EXIT_FAILURE, "lutimes(%s)", lpath);
+		if (!compare_linktime(lpath, true, atim, mtim, false)) {
+			warnx("link time is incorrect");
+			ret = false;
+		}
+		if (compare_filetime(path, true, atim, mtim, true)) {
+			warnx("target time was updated incorrectly");
+			ret = false;
+		}
+
+		/* Reset the time on the path and link to the current time */
+		if (!reset(path, atim, mtim) || !reset_link(lpath, atim, mtim))
+			ret = false;
+
+		/* and modify the target */
+		if (utimes(path, tv) == -1)
+			err(EXIT_FAILURE, "utimes(%s)", path);
+		/* Now the target should match but the link should not */
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("target time is incorrect");
+			ret = false;
+		}
+		if (compare_linktime(lpath, true, atim, mtim, true)) {
+			warnx("link time was updated incorrectly");
+			ret = false;
+		}
+		break;
+
+	case FUTIMES:
+		printf("..... futimes()\n");
+
+		if (futimes(fd, tv) == -1)
+			err(EXIT_FAILURE, "futimes(%s)", path);
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed on file");
+			ret = false;
+		}
+
+		break;
+
+	case FUTIMESAT: {
+		int rfd;
+		printf("..... futimesat()\n");
+
+		/* NULL path, should modify the file for 'fd' */
+		if (futimesat(fd, NULL, tv) == -1)
+			err(EXIT_FAILURE, "futimesat(fd, NULL)");
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed with null path");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* random descriptor, FQ path, descriptor is ignored */
+		if ((rfd = open("/dev/null", O_RDONLY)) == -1)
+			err(EXIT_FAILURE, "open(/dev/null)");
+		if (futimesat(rfd, path, tv) == -1)
+			err(EXIT_FAILURE, "futimesat(dnfd, %s)", path);
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed with random descriptor and fq path");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* repeat against symbolic link path */
+		if (futimesat(rfd, lpath, tv) == -1)
+			err(EXIT_FAILURE, "futimesat(dnfd, %s), link", lpath);
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed through link with "
+			    "random descriptor, fq path");
+			ret = false;
+		}
+
+		(void) close(rfd);
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* relative to a directory */
+		if (futimesat(dfd, "file", tv) == -1)
+			err(EXIT_FAILURE, "futimesat(dir, file)", path);
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed relative to a directory");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* repeat against symbolic link path */
+		if (futimesat(dfd, "link", tv) == -1)
+			err(EXIT_FAILURE, "futimesat(dir, link)");
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed through link relative to a directory");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* AT_FDCWD */
+		if (fchdir(dfd) == -1)
+			err(EXIT_FAILURE, "fchdir(%s)", dir);
+		if (futimesat(AT_FDCWD, "file", tv) == -1)
+			err(EXIT_FAILURE, "futimesat(AT_FDCWD, file)", path);
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed with AT_FDCWD relative");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* repeat against symbolic link path */
+		if (futimesat(AT_FDCWD, "link", tv) == -1)
+			err(EXIT_FAILURE, "futimesat(AT_FDCWD, link)");
+		if (!compare_filetime(path, true, atim, mtim, false)) {
+			warnx("failed through link with AT_FDCWD relative");
+			ret = false;
+		}
+
+		break;
+	}
+
+	case FUTIMENS:
+		printf("..... futimens()\n");
+		if (futimens(fd, ts) == -1)
+			err(EXIT_FAILURE, "futimesns(%s)", path);
+		if (!compare_filetime(path, false, atim, mtim, false)) {
+			warnx("failed with plain file fd");
+			ret = false;
+		}
+
+		break;
+
+	case UTIMENSAT: {
+		int rfd;
+
+		printf("..... utimensat()\n");
+
+		/* NULL path, expect EFAULT (cf. futimesat()) */
+		if (utimensat(fd, NULL, ts, 0) != -1 || errno != EFAULT) {
+			warnx("null path should return EFAULT but got %d/%s",
+			    errno, strerror(errno));
+			ret = false;
+		}
+
+		/* random descriptor, FQ path, descriptor is ignored */
+		if ((rfd = open("/dev/null", O_RDONLY)) == -1)
+			err(EXIT_FAILURE, "open(/dev/null)");
+		if (utimensat(rfd, path, ts, 0) == -1)
+			err(EXIT_FAILURE, "utimensat(dnfd, %s)", path);
+		if (!compare_filetime(path, false, atim, mtim, false)) {
+			warnx("failed with random descriptor, fq path");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* repeat against symbolic link path */
+		if (utimensat(rfd, lpath, ts, 0) == -1)
+			err(EXIT_FAILURE, "utimensat(dnfd, link %s)", lpath);
+		if (!compare_filetime(path, false, atim, mtim, false)) {
+			warnx("failed against link with random descriptor, "
+			    "fq path");
+			ret = false;
+		}
+
+		(void) close(rfd);
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* relative to a directory */
+		if (utimensat(dfd, "file", ts, 0) == -1)
+			err(EXIT_FAILURE, "utimensat(dir, file)", path);
+		if (!compare_filetime(path, false, atim, mtim, false)) {
+			warnx("failed relative to a directory");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* repeat against symbolic link path */
+		if (utimensat(dfd, "link", ts, 0) == -1)
+			err(EXIT_FAILURE, "utimensat(dir, link)", path);
+		if (!compare_filetime(path, false, atim, mtim, false)) {
+			warnx("failed through link relative to a directory");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* AT_FDCWD */
+		if (fchdir(dfd) == -1)
+			err(EXIT_FAILURE, "fchdir(%s)", dir);
+		if (utimensat(AT_FDCWD, "file", ts, 0) == -1)
+			err(EXIT_FAILURE, "utimensat(AT_FDCWD, file)");
+		if (!compare_filetime(path, false, atim, mtim, false)) {
+			warnx("failed with AT_FDCWD relative");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/* repeat against symbolic link path */
+		if (utimensat(AT_FDCWD, "link", ts, 0) == -1)
+			err(EXIT_FAILURE, "utimensat(AT_FDCWD, link)");
+		if (!compare_filetime(path, false, atim, mtim, false)) {
+			warnx("failed through link with AT_FDCWD relative");
+			ret = false;
+		}
+
+		if (!reset(path, atim, mtim))
+			ret = false;
+
+		/*
+		 * Check that none of the above operations have changed the
+		 * timestamp on the link.
+		 */
+		if (compare_linktime(lpath, true, atim, mtim, true)) {
+			warnx("link timestamp was unexpectedly modified");
+			ret = false;
+		}
+
+		/* Set the time on the link, not on the target */
+		if (utimensat(AT_FDCWD, "link", ts, AT_SYMLINK_NOFOLLOW) == -1)
+			err(EXIT_FAILURE, "utimensat(AT_FDCWD, lflag)");
+		if (!compare_linktime(lpath, false, atim, mtim, false)) {
+			warnx("link time is incorrect");
+			ret = false;
+		}
+		if (compare_filetime(path, false, atim, mtim, true)) {
+			warnx("target time was updated incorrectly");
+			ret = false;
+		}
+		}
+		break;
+	}
+
+	(void) close(dfd);
+	(void) close(lfd);
+	(void) close(fd);
+
+	if (unlink(lpath) == -1)
+		err(EXIT_FAILURE, "unlink(%s)", lpath);
+	if (unlink(path) == -1)
+		err(EXIT_FAILURE, "unlink(%s)", path);
+
+	if (!ret)
+		warnx("Test failed");
+
+	return (ret);
+}
+
+static bool
+runtests(char *dir, timespec_t *atim, timespec_t *mtim)
+{
+	bool ret = true;
+
+	printf("Testing:\n... atime: %ld.%.9ld\n... mtime: %ld.%.9ld\n",
+	    atim->tv_sec, atim->tv_nsec, mtim->tv_sec, mtim->tv_nsec);
+
+	if (!runtest(UTIMES, dir, atim, mtim))
+		ret = false;
+	if (!runtest(LUTIMES, dir, atim, mtim))
+		ret = false;
+	if (!runtest(FUTIMES, dir, atim, mtim))
+		ret = false;
+	if (!runtest(FUTIMESAT, dir, atim, mtim))
+		ret = false;
+	if (!runtest(FUTIMENS, dir, atim, mtim))
+		ret = false;
+	if (!runtest(UTIMENSAT, dir, atim, mtim))
+		ret = false;
+
+	return (ret);
+}
+
+int
+main(void)
+{
+	char dir[] = "/tmp/utimes.XXXXXX";
+	int ret = EXIT_SUCCESS;
+	int i;
+
+	if (mkdtemp(dir) == NULL)
+		err(EXIT_FAILURE, "failed to create temporary directory");
+
+	for (i = 0; i < ARRAY_SIZE(testtimes); i += 2) {
+		if (!runtests(dir, &testtimes[i], &testtimes[i + 1]))
+			ret = EXIT_FAILURE;
+	}
+
+	/*
+	 * Some tests will have changed directory into 'dir' to test the
+	 * AT_FDCWD case. Change back to / to avoid EBUSY when removing dir.
+	 */
+	if (chdir("/") == -1)
+		err(EXIT_FAILURE, "chdir(/)");
+	if (rmdir(dir) == -1)
+		err(EXIT_FAILURE, "rmdir %s", dir);
+
+	return (ret);
+}
--- old/usr/src/uts/common/sys/time.h	Mon Sep 14 14:49:11 2020
+++ new/usr/src/uts/common/sys/time.h	Mon Sep 14 14:49:12 2020
@@ -15,6 +15,8 @@
  * Use is subject to license terms.
  *
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ *
+ * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
  */
 
 /*
@@ -356,14 +358,14 @@
 extern	time_t		tod_to_utc(todinfo_t);
 extern	int		hr_clock_lock(void);
 extern	void		hr_clock_unlock(int);
-extern	hrtime_t 	gethrtime(void);
-extern	hrtime_t 	gethrtime_unscaled(void);
+extern	hrtime_t	gethrtime(void);
+extern	hrtime_t	gethrtime_unscaled(void);
 extern	hrtime_t	gethrtime_max(void);
 extern	hrtime_t	gethrtime_waitfree(void);
 extern	void		scalehrtime(hrtime_t *);
 extern	uint64_t	unscalehrtime(hrtime_t);
-extern	void 		gethrestime(timespec_t *);
-extern	time_t 		gethrestime_sec(void);
+extern	void		gethrestime(timespec_t *);
+extern	time_t		gethrestime_sec(void);
 extern	void		gethrestime_lasttick(timespec_t *);
 extern	void		hrt2ts(hrtime_t, timestruc_t *);
 extern	hrtime_t	ts2hrt(const timestruc_t *);
@@ -399,6 +401,7 @@
 
 int getitimer(int, struct itimerval *);
 int utimes(const char *, const struct timeval *);
+
 #if defined(_XPG4_2)
 int setitimer(int, const struct itimerval *_RESTRICT_KYWD,
 	struct itimerval *_RESTRICT_KYWD);
@@ -409,6 +412,22 @@
 
 #endif /* !defined(_KERNEL) ... defined(_XPG4_2) */
 
+#if !defined(_KERNEL) && !defined(_STRICT_SYMBOLS)
+int futimes(int, const struct timeval *);
+int lutimes(const char *, const struct timeval *);
+
+#define	TIMESPEC_TO_TIMEVAL(tv, ts) { \
+	(tv)->tv_sec = (ts)->tv_sec; \
+	(tv)->tv_usec = (ts)->tv_nsec / 1000; \
+}
+
+#define	TIMEVAL_TO_TIMESPEC(tv, ts) { \
+	(ts)->tv_sec = (tv)->tv_sec; \
+	(ts)->tv_nsec = (tv)->tv_usec * 1000; \
+}
+
+#endif /* !defined(_KERNEL) && !defined(_STRICT_SYMBOLS) */
+
 /*
  * gettimeofday() and settimeofday() were included in SVr4 due to their
  * common use in BSD based applications.  They were to be included exactly
