]> granicus.if.org Git - sudo/commitdiff
Use futimens() and utimensat() instead of futimes() and utimes().
authorTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 2 Mar 2015 20:58:50 +0000 (13:58 -0700)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 2 Mar 2015 20:58:50 +0000 (13:58 -0700)
20 files changed:
MANIFEST
config.h.in
configure
configure.ac
include/sudo_compat.h
include/sudo_util.h
lib/util/Makefile.in
lib/util/gettime.c [moved from plugins/sudoers/gettime.c with 87% similarity]
lib/util/util.exp.in
lib/util/utimens.c [new file with mode: 0644]
lib/util/utimes.c [deleted file]
mkdep.pl
plugins/sudoers/Makefile.in
plugins/sudoers/boottime.c
plugins/sudoers/sudoers.h
plugins/sudoers/timestamp.c
plugins/sudoers/visudo.c
src/Makefile.in
src/sesh.c
src/sudo_edit.c

index aeee9d1b2b3a03f9cffced9e4b212bfed89c6c67..69063841e5f5fefede2c4db1272076279538d5b2 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -93,6 +93,7 @@ lib/util/getgrouplist.c
 lib/util/gethostname.c
 lib/util/getline.c
 lib/util/getopt_long.c
+lib/util/gettime.c
 lib/util/gidlist.c
 lib/util/glob.c
 lib/util/inet_ntop.c
@@ -170,7 +171,7 @@ lib/util/sudo_dso.c
 lib/util/term.c
 lib/util/ttysize.c
 lib/util/util.exp.in
-lib/util/utimes.c
+lib/util/utimens.c
 lib/zlib/Makefile.in
 lib/zlib/adler32.c
 lib/zlib/compress.c
@@ -257,7 +258,6 @@ plugins/sudoers/find_path.c
 plugins/sudoers/getdate.c
 plugins/sudoers/getdate.y
 plugins/sudoers/getspwuid.c
-plugins/sudoers/gettime.c
 plugins/sudoers/goodpath.c
 plugins/sudoers/gram.c
 plugins/sudoers/gram.h
index ef1282c0490d76403f81d8ec1dcde8f1ceb60c1e..f7dcb7844593823e662fa5c145aadcc7a0732ec0 100644 (file)
 /* Define to 1 if you have the `futime' function. */
 #undef HAVE_FUTIME
 
+/* Define to 1 if you have the `futimens' function. */
+#undef HAVE_FUTIMENS
+
 /* Define to 1 if you have the `futimes' function. */
 #undef HAVE_FUTIMES
 
 /* Define to 1 if you have the <util.h> header file. */
 #undef HAVE_UTIL_H
 
+/* Define to 1 if you have the `utimensat' function. */
+#undef HAVE_UTIMENSAT
+
 /* Define to 1 if you have the `utimes' function. */
 #undef HAVE_UTIMES
 
index 6687cefe99653715396703622692cf07a7207c87..f00428d973de5d55eda5330ebb7656ba902519c4 100755 (executable)
--- a/configure
+++ b/configure
@@ -18939,54 +18939,74 @@ done
 fi
 done
 
-for ac_func in utimes
+for ac_func in utimensat
 do :
-  ac_fn_c_check_func "$LINENO" "utimes" "ac_cv_func_utimes"
-if test "x$ac_cv_func_utimes" = xyes; then :
+  ac_fn_c_check_func "$LINENO" "utimensat" "ac_cv_func_utimensat"
+if test "x$ac_cv_func_utimensat" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_UTIMES 1
+#define HAVE_UTIMENSAT 1
 _ACEOF
 
-    for ac_func in futimes futimesat
+else
+
+    case " $LIBOBJS " in
+  *" utimens.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS utimens.$ac_objext"
+ ;;
+esac
+
+
+    for _sym in sudo_utimensat; do
+       COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+    done
+
+    for ac_func in utimes
 do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  ac_fn_c_check_func "$LINENO" "utimes" "ac_cv_func_utimes"
+if test "x$ac_cv_func_utimes" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_UTIMES 1
 _ACEOF
- break
+
+fi
+done
+
+
 fi
 done
 
+for ac_func in futimens
+do :
+  ac_fn_c_check_func "$LINENO" "futimens" "ac_cv_func_futimens"
+if test "x$ac_cv_func_futimens" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_FUTIMENS 1
+_ACEOF
 
 else
 
     case " $LIBOBJS " in
-  *" utimes.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS utimes.$ac_objext"
+  *" utimens.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS utimens.$ac_objext"
  ;;
 esac
 
 
-    for _sym in sudo_utimes; do
+    for _sym in sudo_futimens; do
        COMPAT_EXP="${COMPAT_EXP}${_sym}
 "
     done
 
-    for ac_func in futime
+    for ac_func in futimes futimesat futime
 do :
-  ac_fn_c_check_func "$LINENO" "futime" "ac_cv_func_futime"
-if test "x$ac_cv_func_futime" = xyes; then :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_FUTIME 1
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
 _ACEOF
-
-    for _sym in sudo_futimes; do
-       COMPAT_EXP="${COMPAT_EXP}${_sym}
-"
-    done
-
+ break
 fi
 done
 
@@ -19295,7 +19315,7 @@ if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
 
        $as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
 
-       SUDOERS_LIBS="${SUDOERS_LIBS} -lrt"
+       LIBS="${LIBS} -lrt"
 
 fi
 
index 00f262d3ef5fe54bd8f653c9b22c2159e544ea5f..d975058d6ac5571bf01a33243588b79b927337cd 100644 (file)
@@ -2495,12 +2495,15 @@ AC_INCLUDES_DEFAULT
 ], [
     AC_CHECK_FUNCS([sysinfo], [AC_CHECK_HEADERS([sys/systeminfo.h])])
 ])
-AC_CHECK_FUNCS([utimes], [
-    AC_CHECK_FUNCS([futimes futimesat], [break])
-], [
-    AC_LIBOBJ(utimes)
-    SUDO_APPEND_COMPAT_EXP(sudo_utimes)
-    AC_CHECK_FUNCS([futime], [SUDO_APPEND_COMPAT_EXP(sudo_futimes)])
+AC_CHECK_FUNCS([utimensat], [], [
+    AC_LIBOBJ(utimens)
+    SUDO_APPEND_COMPAT_EXP(sudo_utimensat)
+    AC_CHECK_FUNCS([utimes])
+])
+AC_CHECK_FUNCS([futimens], [], [
+    AC_LIBOBJ(utimens)
+    SUDO_APPEND_COMPAT_EXP(sudo_futimens)
+    AC_CHECK_FUNCS([futimes futimesat futime], [break])
 ])
 SUDO_FUNC_FNMATCH([AC_DEFINE(HAVE_FNMATCH)], [
     AC_LIBOBJ(fnmatch)
@@ -2536,7 +2539,7 @@ AC_CHECK_FUNCS([clock_gettime], [], [
     # On Solaris, clock_gettime is in librt
     AC_CHECK_LIB(rt, clock_gettime, [
        AC_DEFINE(HAVE_CLOCK_GETTIME)
-       SUDOERS_LIBS="${SUDOERS_LIBS} -lrt"
+       LIBS="${LIBS} -lrt"
     ])
 ])
 AC_CHECK_FUNCS([getopt_long], [], [
index c112783d6e5a22e6b91f8311341984f466be5309..dba659634440464e31457321d9824accf52feff9 100644 (file)
 # define S_IRWXU               0000700         /* rwx for owner */
 #endif /* S_IRWXU */
 
+/* For futimens() and utimensat() emulation. */
+#if !defined(HAVE_FUTIMENS) && !defined(HAVE_UTIMENSAT)
+# ifndef UTIME_OMIT
+#  define UTIME_OMIT   -1L
+# endif
+# ifndef UTIME_NOW
+#  define UTIME_NOW    -2L
+# endif
+# ifndef AT_FDCWD
+#  define AT_FDCWD     -100
+# endif
+#endif
+
 /*
  * These should be defined in <unistd.h> but not everyone has them.
  */
@@ -276,14 +289,6 @@ typedef struct sigaction sigaction_t;
 # define HAVE_DIRFD
 #endif
 
-/*
- * Define futimes() in terms of futimesat() if needed.
- */
-#if !defined(HAVE_FUTIMES) && defined(HAVE_FUTIMESAT)
-# define futimes(_f, _tv)      futimesat(_f, NULL, _tv)
-# define HAVE_FUTIMES
-#endif
-
 #if !defined(HAVE_KILLPG) && !defined(killpg)
 # define killpg(s)     kill(-(s))
 #endif
@@ -386,16 +391,16 @@ __dso_public ssize_t sudo_getline(char **bufp, size_t *bufsizep, FILE *fp);
 # undef getline
 # define getline(_a, _b, _c) sudo_getline((_a), (_b), (_c))
 #endif /* HAVE_GETLINE */
-#ifndef HAVE_UTIMES
-__dso_public int sudo_utimes(const char *file, const struct timeval *times);
-# undef utimes
-# define utimes(_a, _b) sudo_utimes((_a), (_b))
-#endif /* HAVE_UTIMES */
-#ifdef HAVE_FUTIME
-__dso_public int sudo_futimes(int fd, const struct timeval *times);
-# undef futimes
-# define futimes(_a, _b) sudo_futimes((_a), (_b))
-#endif /* HAVE_FUTIME */
+#ifndef HAVE_UTIMENSAT
+__dso_public int sudo_utimensat(int fd, const char *file, const struct timespec *times, int flag);
+# undef utimensat
+# define utimensat(_a, _b, _c, _d) sudo_utimensat((_a), (_b), (_c), (_d))
+#endif /* HAVE_UTIMENSAT */
+#ifndef HAVE_FUTIMENS
+__dso_public int sudo_futimens(int fd, const struct timespec *times);
+# undef futimens
+# define futimens(_a, _b) sudo_futimens((_a), (_b))
+#endif /* HAVE_FUTIMENS */
 #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
 __dso_public int sudo_snprintf(char *str, size_t n, char const *fmt, ...) __printflike(3, 4);
 # undef snprintf
index 3237c9e7d1acbb0a9af94e7ba7afee9d414769c2..71402c3ff6a7cd89137b377b0726836e56c398f0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2013-2015 Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #endif
 
 /*
- * Macros to extract ctime and mtime as timevals.
+ * The timespec version of st_mtime may vary on different platforms.
  */
-#ifdef HAVE_ST_MTIM
-# ifdef HAVE_ST__TIM
-#  define ctim_get(_x, _y)     TIMESPEC_TO_TIMEVAL((_y), &(_x)->st_ctim.st__tim)
-#  define mtim_get(_x, _y)     TIMESPEC_TO_TIMEVAL((_y), &(_x)->st_mtim.st__tim)
+#if defined(HAVE_ST_MTIM)
+# if defined(HAVE_ST__TIM)
+#  define SUDO_ST_MTIM         st_mtim.st__tim
 # else
-#  define ctim_get(_x, _y)     TIMESPEC_TO_TIMEVAL((_y), &(_x)->st_ctim)
-#  define mtim_get(_x, _y)     TIMESPEC_TO_TIMEVAL((_y), &(_x)->st_mtim)
+#  define SUDO_ST_MTIM         st_mtim
 # endif
-#else
-# ifdef HAVE_ST_MTIMESPEC
-#  define ctim_get(_x, _y)     TIMESPEC_TO_TIMEVAL((_y), &(_x)->st_ctimespec)
-#  define mtim_get(_x, _y)     TIMESPEC_TO_TIMEVAL((_y), &(_x)->st_mtimespec)
+#elif defined(HAVE_ST_MTIMESPEC)
+# define SUDO_ST_MTIM          st_mtimespec
+#endif
+
+/*
+ * Macro to extract mtime as timespec.
+ * If there is no way to set the timestamp using nanosecond precision,
+ * we only fetch microsecond precision.  Otherwise there is a mismatch
+ * between the timestamp we read and the one we wrote.
+ */
+#if defined(SUDO_ST_MTIM)
+# if defined(HAVE_FUTIMENS) && defined(HAVE_UTIMENSAT)
+#  define mtim_get(_x, _y)     ((_y) = (_x)->SUDO_ST_MTIM)
 # else
-#  define ctim_get(_x, _y)     do { (_y)->tv_sec = (_x)->st_ctime; (_y)->tv_usec = 0; } while (0)
-#  define mtim_get(_x, _y)     do { (_y)->tv_sec = (_x)->st_mtime; (_y)->tv_usec = 0; } while (0)
-# endif /* HAVE_ST_MTIMESPEC */
+#  define mtim_get(_x, _y)     do { (_y).tv_sec = (_x)->SUDO_ST_MTIM.tv_sec; (_y).tv_nsec = ((_x)->SUDO_ST_MTIM.tv_nsec / 1000) * 1000; } while (0)
+# endif
+#else
+# define mtim_get(_x, _y)      do { (_y).tv_sec = (_x)->st_mtime; (_y).tv_nsec = 0; } while (0)
 #endif /* HAVE_ST_MTIM */
 
 /*
@@ -148,6 +156,12 @@ __dso_public int aix_setauthdb_v1(char *user);
 __dso_public char *sudo_gethostname_v1(void);
 #define sudo_gethostname() sudo_gethostname_v1()
 
+/* gettime.c */
+__dso_public int sudo_gettime_mono_v1(struct timespec *ts);
+#define sudo_gettime_mono(_a) sudo_gettime_mono_v1((_a))
+__dso_public int sudo_gettime_real_v1(struct timespec *ts);
+#define sudo_gettime_real(_a) sudo_gettime_real_v1((_a))
+
 /* gidlist.c */
 __dso_public int sudo_parse_gids_v1(const char *gidstr, const gid_t *basegid, GETGROUPS_T **gidsp);
 #define sudo_parse_gids(_a, _b, _c) sudo_parse_gids_v1((_a), (_b), (_c))
index 90958896020222e40c1cece0e8e509d24f560cee..2117aee671a7975464c774351a4f4647f0d791ed 100644 (file)
@@ -96,10 +96,10 @@ DEVEL = @DEVEL@
 
 SHELL = @SHELL@
 
-LTOBJS = alloc.lo event.lo fatal.lo key_val.lo gethostname.lo gidlist.lo \
-        lbuf.lo locking.lo parseln.lo progname.lo secure_path.lo setgroups.lo \
-        strtobool.lo strtoid.lo strtomode.lo sudo_conf.lo sudo_debug.lo \
-        sudo_dso.lo term.lo ttysize.lo @COMMON_OBJS@ @LTLIBOBJS@
+LTOBJS = alloc.lo event.lo fatal.lo key_val.lo gethostname.lo gettime.lo \
+        gidlist.lo lbuf.lo locking.lo parseln.lo progname.lo secure_path.lo \
+        setgroups.lo strtobool.lo strtoid.lo strtomode.lo sudo_conf.lo \
+        sudo_debug.lo sudo_dso.lo term.lo ttysize.lo @COMMON_OBJS@ @LTLIBOBJS@
 
 ATOFOO_TEST_OBJS = atofoo_test.lo locale_stub.lo
 
@@ -375,6 +375,11 @@ getopt_long.lo: $(srcdir)/getopt_long.c $(incdir)/compat/getopt.h \
                 $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
                 $(top_builddir)/config.h
        $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/getopt_long.c
+gettime.lo: $(srcdir)/gettime.c $(incdir)/compat/stdbool.h \
+            $(incdir)/compat/timespec.h $(incdir)/sudo_compat.h \
+            $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h \
+            $(incdir)/sudo_util.h $(top_builddir)/config.h
+       $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/gettime.c
 gidlist.lo: $(srcdir)/gidlist.c $(incdir)/compat/stdbool.h \
             $(incdir)/sudo_alloc.h $(incdir)/sudo_compat.h \
             $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
@@ -530,6 +535,7 @@ ttysize.lo: $(srcdir)/ttysize.c $(incdir)/compat/stdbool.h \
             $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
             $(top_builddir)/config.h
        $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/ttysize.c
-utimes.lo: $(srcdir)/utimes.c $(incdir)/compat/utime.h $(incdir)/sudo_compat.h \
-           $(top_builddir)/config.h
-       $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/utimes.c
+utimens.lo: $(srcdir)/utimens.c $(incdir)/compat/timespec.h \
+            $(incdir)/compat/utime.h $(incdir)/sudo_compat.h \
+            $(top_builddir)/config.h
+       $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/utimens.c
similarity index 87%
rename from plugins/sudoers/gettime.c
rename to lib/util/gettime.c
index 1c9a77d2e95117072a876b722702b4852fe4dc31..04676f50a2473826de0e73e312b17ce01701671f 100644 (file)
@@ -44,7 +44,9 @@
 # include <mach/clock.h>
 #endif
 
-#include "sudoers.h"
+#include "sudo_compat.h"
+#include "sudo_debug.h"
+#include "sudo_util.h"
 
 /* On Linux, CLOCK_MONOTONIC does not run while suspended. */
 #if defined(CLOCK_BOOTTIME)
@@ -55,9 +57,9 @@
 
 #if defined(HAVE_CLOCK_GETTIME)
 int
-sudo_gettime_real(struct timespec *ts)
+sudo_gettime_real_v1(struct timespec *ts)
 {
-    debug_decl(sudo_gettime_real, SUDOERS_DEBUG_UTIL)
+    debug_decl(sudo_gettime_real, SUDO_DEBUG_UTIL)
 
     if (clock_gettime(CLOCK_REALTIME, ts) == -1) {
        struct timeval tv;
@@ -72,10 +74,10 @@ sudo_gettime_real(struct timespec *ts)
 }
 #else
 int
-sudo_gettime_real(struct timespec *ts)
+sudo_gettime_real_v1(struct timespec *ts)
 {
     struct timeval tv;
-    debug_decl(sudo_gettime_real, SUDOERS_DEBUG_UTIL)
+    debug_decl(sudo_gettime_real, SUDO_DEBUG_UTIL)
 
     if (gettimeofday(&tv, NULL) == -1)
        debug_return_int(-1);
@@ -86,10 +88,10 @@ sudo_gettime_real(struct timespec *ts)
 
 #if defined(HAVE_CLOCK_GETTIME) && defined(SUDO_CLOCK_MONOTONIC)
 int
-sudo_gettime_mono(struct timespec *ts)
+sudo_gettime_mono_v1(struct timespec *ts)
 {
     static int has_monoclock = -1;
-    debug_decl(sudo_gettime_mono, SUDOERS_DEBUG_UTIL)
+    debug_decl(sudo_gettime_mono, SUDO_DEBUG_UTIL)
 
     /* Check whether the kernel/libc actually supports CLOCK_MONOTONIC. */
 # ifdef _SC_MONOTONIC_CLOCK
@@ -108,11 +110,11 @@ sudo_gettime_mono(struct timespec *ts)
 }
 #elif defined(__MACH__)
 int
-sudo_gettime_mono(struct timespec *ts)
+sudo_gettime_mono_v1(struct timespec *ts)
 {
     uint64_t abstime, nsec;
     static mach_timebase_info_data_t timebase_info;
-    debug_decl(sudo_gettime_mono, SUDOERS_DEBUG_UTIL)
+    debug_decl(sudo_gettime_mono, SUDO_DEBUG_UTIL)
 
     if (timebase_info.denom == 0)
        (void) mach_timebase_info(&timebase_info);
@@ -124,7 +126,7 @@ sudo_gettime_mono(struct timespec *ts)
 }
 #else
 int
-sudo_gettime_mono(struct timespec *ts)
+sudo_gettime_mono_v1(struct timespec *ts)
 {
     /* No monotonic clock available, use wall clock. */
     return sudo_gettime_real(ts);
index 170ebdd6f788b93df29bf75d1e9abd9dcd6d03dc..55b21e67be1c12c61560aa0758bf0507ddd53f69 100644 (file)
@@ -66,6 +66,8 @@ sudo_fatal_nodebug_v1
 sudo_fatalx_nodebug_v1
 sudo_get_ttysize_v1
 sudo_gethostname_v1
+sudo_gettime_mono_v1
+sudo_gettime_real_v1
 sudo_lbuf_append_quoted_v1
 sudo_lbuf_append_v1
 sudo_lbuf_destroy_v1
diff --git a/lib/util/utimens.c b/lib/util/utimens.c
new file mode 100644 (file)
index 0000000..b2eac19
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2015 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#if !defined(HAVE_FUTIMENS) || !defined(HAVE_UTIMENSAT)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef TIME_WITH_SYS_TIME
+# include <time.h>
+#endif
+#ifndef HAVE_STRUCT_TIMESPEC
+# include "compat/timespec.h"
+#endif
+#ifdef HAVE_UTIME_H
+# include <utime.h>
+#else
+# include "compat/utime.h"
+#endif
+
+#include "sudo_compat.h"
+
+#if !defined(HAVE_FUTIMES) && defined(HAVE_FUTIMESAT)
+# define futimes(_f, _tv)      futimesat(_f, NULL, _tv)
+# define HAVE_FUTIMES
+#endif
+
+#if defined(HAVE_ST_MTIM)
+# ifdef HAVE_ST__TIM
+#  define ATIME_TO_TIMEVAL(_x, _y)     TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_atim.st__tim)
+#  define MTIME_TO_TIMEVAL(_x, _y)     TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_mtim.st__tim)
+# else
+#  define ATIME_TO_TIMEVAL(_x, _y)     TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_atim)
+#  define MTIME_TO_TIMEVAL(_x, _y)     TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_mtim)
+# endif
+#elif defined(HAVE_ST_MTIMESPEC)
+# define ATIME_TO_TIMEVAL(_x, _y)      TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_atimespec)
+# define MTIME_TO_TIMEVAL(_x, _y)      TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_mtimespec)
+#else
+# define ATIME_TO_TIMEVAL(_x, _y)      do { (_x)->tv_sec = (_y)->st_atime; (_x)->tv_usec = 0; } while (0)
+# define MTIME_TO_TIMEVAL(_x, _y)      do { (_x)->tv_sec = (_y)->st_mtime; (_x)->tv_usec = 0; } while (0)
+#endif /* HAVE_ST_MTIM */
+
+/*
+ * Convert the pair of timespec structs passed to futimens() / utimensat()
+ * to a pair of timeval structs, handling UTIME_OMIT and UTIME_NOW.
+ * Returns 0 on success and -1 on failure (setting errno).
+ */
+static int
+utimens_ts_to_tv(int fd, const char *file, const struct timespec *ts,
+    struct timeval *tv)
+{
+    TIMESPEC_TO_TIMEVAL(&tv[0], &ts[0]);
+    TIMESPEC_TO_TIMEVAL(&tv[1], &ts[1]);
+    if (ts[0].tv_nsec == UTIME_OMIT || ts[1].tv_nsec == UTIME_OMIT) {
+       struct stat sb;
+
+       if (fd != -1) {
+           /* For futimens() */
+           if (fstat(fd, &sb) == -1)
+               return -1;
+       } else {
+           /* For utimensat() */
+           if (stat(file, &sb) == -1)
+               return -1;
+       }
+       if (ts[0].tv_nsec == UTIME_OMIT)
+           ATIME_TO_TIMEVAL(&tv[0], &sb);
+       if (ts[1].tv_nsec == UTIME_OMIT)
+           MTIME_TO_TIMEVAL(&tv[1], &sb);
+    }
+    if (ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW) {
+       struct timeval now;
+
+       if (gettimeofday(&now, NULL) == -1)
+           return -1;
+       if (ts[0].tv_nsec == UTIME_NOW)
+           tv[0] = now;
+       if (ts[1].tv_nsec == UTIME_NOW)
+           tv[1] = now;
+    }
+    return 0;
+}
+
+#if defined(HAVE_FUTIMES)
+/*
+ * Emulate futimens() via futimes()
+ */
+int
+sudo_futimens(int fd, const struct timespec *ts)
+{
+    struct timeval tv[2], *times = NULL;
+
+    if (ts != NULL) {
+       if (utimens_ts_to_tv(fd, NULL, ts, tv) == -1)
+           return -1;
+       times = tv;
+    }
+    return futimes(fd, times);
+}
+#elif defined(HAVE_FUTIME)
+/*
+ * Emulate futimens() via futime()
+ */
+int
+sudo_futimens(int fd, const struct timeval *ts)
+{
+    struct utimbuf utb, *times = NULL;
+
+    if (ts != NULL) {
+       struct timeval tv[2];
+
+       if (utimens_ts_to_tv(fd, NULL, ts, tv) == -1)
+           return -1;
+       utb.actime = (time_t)(tv[0].tv_sec + tv[0].tv_usec / 1000000);
+       utb.modtime = (time_t)(tv[1].tv_sec + tv[1].tv_usec / 1000000);
+       times = &utb;
+    }
+    return futime(fd, times);
+}
+#else
+/*
+ * Nothing to do but fail.
+ */
+int
+sudo_futimens(int fd, const struct timeval *ts)
+{
+    errno = ENOSYS;
+    return -1;
+}
+#endif /* HAVE_FUTIMES */
+
+#if defined(HAVE_UTIMES)
+/*
+ * Emulate utimensat() via utimes()
+ */
+int
+sudo_utimensat(int fd, const char *file, const struct timespec *ts, int flag)
+{
+    struct timeval tv[2], *times = NULL;
+
+    if (fd != AT_FDCWD || flag != 0) {
+       errno = ENOTSUP;
+       return -1;
+    }
+
+    if (ts != NULL) {
+       if (utimens_ts_to_tv(-1, file, ts, tv) == -1)
+           return -1;
+       times = tv;
+    }
+    return utimes(file, times);
+}
+#else
+/*
+ * Emulate utimensat() via utime()
+ */
+int
+sudo_utimensat(int fd, const char *file, const struct timespec *ts, int flag)
+{
+    struct utimbuf utb, *times = NULL;
+
+    if (fd != AT_FDCWD || flag != 0) {
+       errno = ENOTSUP;
+       return -1;
+    }
+
+    if (ts != NULL) {
+       struct timeval tv[2];
+
+       if (utimens_ts_to_tv(-1, file, ts, tv) == -1)
+           return -1;
+       utb.actime = (time_t)(tv[0].tv_sec + tv[0].tv_usec / 1000000);
+       utb.modtime = (time_t)(tv[1].tv_sec + tv[1].tv_usec / 1000000);
+       times = &utb;
+    }
+    return utime(file, times);
+}
+#endif /* !HAVE_UTIMES */
+
+#endif /* !HAVE_FUTIMENS && !HAVE_UTIMENSAT */
diff --git a/lib/util/utimes.c b/lib/util/utimes.c
deleted file mode 100644 (file)
index 4104561..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2004-2005, 2007, 2010-2011, 2013, 2014
- *     Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <config.h>
-
-#if !defined(HAVE_UTIMES) || (!defined(HAVE_FUTIMES) && !defined(HAVE_FUTIMESAT))
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <stdio.h>
-#ifdef TIME_WITH_SYS_TIME
-# include <time.h>
-#endif
-
-#ifdef HAVE_UTIME_H
-# include <utime.h>
-#else
-# include "compat/utime.h"
-#endif
-
-#include "sudo_compat.h"
-
-#ifndef HAVE_UTIMES
-/*
- * Emulate utimes() via utime()
- */
-int
-sudo_utimes(const char *file, const struct timeval *times)
-{
-    if (times != NULL) {
-       struct utimbuf utb;
-
-       utb.actime = (time_t)(times[0].tv_sec + times[0].tv_usec / 1000000);
-       utb.modtime = (time_t)(times[1].tv_sec + times[1].tv_usec / 1000000);
-       return utime(file, &utb);
-    } else
-       return utime(file, NULL);
-}
-#endif /* !HAVE_UTIMES */
-
-#ifdef HAVE_FUTIME
-/*
- * Emulate futimes() via futime()
- */
-int
-sudo_futimes(int fd, const struct timeval *times)
-{
-    if (times != NULL) {
-       struct utimbuf utb;
-
-       utb.actime = (time_t)(times[0].tv_sec + times[0].tv_usec / 1000000);
-       utb.modtime = (time_t)(times[1].tv_sec + times[1].tv_usec / 1000000);
-       return futime(fd, &utb);
-    } else
-       return futime(fd, NULL);
-}
-#endif /* HAVE_FUTIME */
-
-#endif /* !HAVE_UTIMES || (!HAVE_FUTIMES && !HAVE_FUTIMESAT) */
index e7af9f0f4cd9e61e40ed7d6124b327c1fa33aaa6..a08069ff44297932647b974d7326cee0406dbde9 100755 (executable)
--- a/mkdep.pl
+++ b/mkdep.pl
@@ -70,7 +70,7 @@ sub mkdep {
     $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo solaris_audit.lo sssd.lo:;
     # XXX - fill in AUTH_OBJS from contents of the auth dir instead
     $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:;
-    $makefile =~ s:\@LTLIBOBJS\@:closefrom.lo fnmatch.lo getaddrinfo.lo getcwd.lo getgrouplist.lo getline.lo getopt_long.lo glob.lo inet_ntop_lo inet_pton.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo pw_dup.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo strtonum.lo utimes.lo:;
+    $makefile =~ s:\@LTLIBOBJS\@:closefrom.lo fnmatch.lo getaddrinfo.lo getcwd.lo getgrouplist.lo getline.lo getopt_long.lo glob.lo inet_ntop_lo inet_pton.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo pw_dup.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo strtonum.lo utimens.lo:;
 
     # Parse OBJS lines
     my %objs;
index 4e132325e45665a27bdf607a6810dd10fd22401f..0e40ec2af2f62fbc7c7a7a5be93b0f45479e02f8 100644 (file)
@@ -143,7 +143,7 @@ LIBPARSESUDOERS_OBJS = alias.lo audit.lo base64.lo defaults.lo hexchar.lo \
                       toke_util.lo
 
 SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo env.lo find_path.lo \
-              gettime.lo goodpath.lo group_plugin.lo interfaces.lo iolog.lo \
+              goodpath.lo group_plugin.lo interfaces.lo iolog.lo \
               iolog_path.lo locale.lo logging.lo logwrap.lo parse.lo \
               policy.lo prompt.lo set_perms.lo sudo_nss.lo sudoers.lo \
               timestamp.lo @SUDOERS_OBJS@
@@ -654,16 +654,6 @@ getspwuid.lo: $(srcdir)/getspwuid.c $(devdir)/def_data.h \
               $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
               $(top_builddir)/config.h $(top_builddir)/pathnames.h
        $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/getspwuid.c
-gettime.lo: $(srcdir)/gettime.c $(devdir)/def_data.h \
-            $(incdir)/compat/stdbool.h $(incdir)/compat/timespec.h \
-            $(incdir)/sudo_alloc.h $(incdir)/sudo_compat.h \
-            $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
-            $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
-            $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
-            $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
-            $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
-            $(top_builddir)/config.h $(top_builddir)/pathnames.h
-       $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/gettime.c
 goodpath.lo: $(srcdir)/goodpath.c $(devdir)/def_data.h \
              $(incdir)/compat/stdbool.h $(incdir)/sudo_alloc.h \
              $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
@@ -1091,14 +1081,14 @@ tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(devdir)/def_data.h \
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/tsgetgrpw.c
 visudo.o: $(srcdir)/visudo.c $(devdir)/def_data.h $(devdir)/gram.h \
           $(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
-          $(incdir)/sudo_alloc.h $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
-          $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
-          $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
-          $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
-          $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/redblack.h \
-          $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
-          $(srcdir)/sudoers_version.h $(top_builddir)/config.h \
-          $(top_builddir)/pathnames.h
+          $(incdir)/compat/timespec.h $(incdir)/sudo_alloc.h \
+          $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+          $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+          $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+          $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+          $(srcdir)/redblack.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+          $(srcdir)/sudoers_debug.h $(srcdir)/sudoers_version.h \
+          $(top_builddir)/config.h $(top_builddir)/pathnames.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/visudo.c
 visudo_json.o: $(srcdir)/visudo_json.c $(devdir)/def_data.h $(devdir)/gram.h \
                $(incdir)/compat/stdbool.h $(incdir)/sudo_alloc.h \
index fd5625cdd37ef4b4205c140b97708e7d6c22739a..ed3664419b402cf37524575e7cdfd42bb0c952c2 100644 (file)
 #include "sudoers.h"
 
 /*
- * Fill in a struct timeval with the time the system booted.
+ * Fill in a struct timespec with the time the system booted.
  * Returns 1 on success and 0 on failure.
  */
 
 #if defined(__linux__)
 bool
-get_boottime(struct timeval *tv)
+get_boottime(struct timespec *ts)
 {
     char *line = NULL;
     size_t linesize = 0;
@@ -81,8 +81,8 @@ get_boottime(struct timeval *tv)
            if (strncmp(line, "btime ", 6) == 0) {
                long long llval = strtonum(line + 6, 1, LLONG_MAX, NULL);
                if (llval > 0) {
-                   tv->tv_sec = (time_t)llval;
-                   tv->tv_usec = 0;
+                   ts->tv_sec = (time_t)llval;
+                   ts->tv_nsec = 0;
                    found = true;
                    break;
                }
@@ -98,17 +98,20 @@ get_boottime(struct timeval *tv)
 #elif defined(HAVE_SYSCTL) && defined(KERN_BOOTTIME)
 
 bool
-get_boottime(struct timeval *tv)
+get_boottime(struct timespec *ts)
 {
     size_t size;
     int mib[2];
+    struct timeval tv;
     debug_decl(get_boottime, SUDOERS_DEBUG_UTIL)
 
     mib[0] = CTL_KERN;
     mib[1] = KERN_BOOTTIME;
-    size = sizeof(*tv);
-    if (sysctl(mib, 2, tv, &size, NULL, 0) != -1)
+    size = sizeof(tv);
+    if (sysctl(mib, 2, &tv, &size, NULL, 0) != -1) {
+       TIMEVAL_TO_TIMESPEC(&tv, ts);
        debug_return_bool(true);
+    }
 
     debug_return_bool(false);
 }
@@ -116,7 +119,7 @@ get_boottime(struct timeval *tv)
 #elif defined(HAVE_GETUTXID)
 
 bool
-get_boottime(struct timeval *tv)
+get_boottime(struct timespec *ts)
 {
     struct utmpx *ut, key;
     debug_decl(get_boottime, SUDOERS_DEBUG_UTIL)
@@ -124,10 +127,8 @@ get_boottime(struct timeval *tv)
     memset(&key, 0, sizeof(key));
     key.ut_type = BOOT_TIME;
     setutxent();
-    if ((ut = getutxid(&key)) != NULL) {
-       tv->tv_sec = ut->ut_tv.tv_sec;
-       tv->tv_usec = ut->ut_tv.tv_usec;
-    }
+    if ((ut = getutxid(&key)) != NULL)
+       TIMEVAL_TO_TIMESPEC(&ut->ut_tv, ts);
     endutxent();
     debug_return_bool(ut != NULL);
 }
@@ -135,7 +136,7 @@ get_boottime(struct timeval *tv)
 #elif defined(HAVE_GETUTID)
 
 bool
-get_boottime(struct timeval *tv)
+get_boottime(struct timespec *ts)
 {
     struct utmp *ut, key;
     debug_decl(get_boottime, SUDOERS_DEBUG_UTIL)
@@ -144,8 +145,8 @@ get_boottime(struct timeval *tv)
     key.ut_type = BOOT_TIME;
     setutent();
     if ((ut = getutid(&key)) != NULL) {
-       tv->tv_sec = ut->ut_time;
-       tv->tv_usec = 0;
+       ts->tv_sec = ut->ut_time;
+       ts->tv_nsec = 0;
     }
     endutent();
     debug_return_bool(ut != NULL);
@@ -154,7 +155,7 @@ get_boottime(struct timeval *tv)
 #else
 
 bool
-get_boottime(struct timeval *tv)
+get_boottime(struct timespec *ts)
 {
     debug_decl(get_boottime, SUDOERS_DEBUG_UTIL)
     debug_return_bool(false);
index af0b79a827affdf20294a520a3264244fb08814a..1d659b5d5804a1400c10bde6fd6e0cacd06bcb95 100644 (file)
@@ -239,10 +239,6 @@ char *expand_prompt(const char *old_prompt, const char *auth_user);
 void remove_timestamp(bool);
 bool set_lectured(void);
 
-/* gettime.c */
-int sudo_gettime_real(struct timespec *ts);
-int sudo_gettime_mono(struct timespec *ts);
-
 /* sudo_auth.c */
 bool sudo_auth_needs_end_session(void);
 int verify_user(struct passwd *pw, char *prompt, int validated);
@@ -315,7 +311,7 @@ void sudo_setspent(void);
 char *get_timestr(time_t, int);
 
 /* boottime.c */
-bool get_boottime(struct timeval *);
+bool get_boottime(struct timespec *);
 
 /* iolog.c */
 bool io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7]);
index a94cd376202df89323ba0701e92f06cfea4957ef..f64e6eb86be2d770ffd63e41a23b4b9086b89477 100644 (file)
@@ -444,10 +444,10 @@ timestamp_status(struct passwd *pw)
 
     /* Ignore and clear time stamp file if mtime predates boot time. */
     if (fstat(fd, &sb) == 0) {
-       struct timeval boottime, mtime;
+       struct timespec boottime, mtime;
 
-       mtim_get(&sb, &mtime);
-       if (get_boottime(&boottime) && sudo_timevalcmp(&mtime, &boottime, <)) {
+       mtim_get(&sb, mtime);
+       if (get_boottime(&boottime) && sudo_timespeccmp(&mtime, &boottime, <)) {
            ignore_result(ftruncate(fd, (off_t)0));
            status = TS_MISSING;
            goto done;
index 4a27a373197866f3989fa040d15c695ec30bbd34..2502bfe3642c084e81badc42e8210cc9b6434c56 100644 (file)
@@ -70,6 +70,9 @@
 #ifdef TIME_WITH_SYS_TIME
 # include <time.h>
 #endif
+#ifndef HAVE_STRUCT_TIMESPEC
+# include "compat/timespec.h"
+#endif
 
 #include "sudoers.h"
 #include "parse.h"
@@ -321,8 +324,8 @@ edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno)
     char *cp;                          /* scratch char pointer */
     char buf[PATH_MAX*2];              /* buffer used for copying files */
     char linestr[64];                  /* string version of lineno */
-    struct timeval tv, times[2];       /* time before and after edit */
-    struct timeval orig_mtim;          /* starting mtime of sudoers file */
+    struct timespec ts, times[2];      /* time before and after edit */
+    struct timespec orig_mtim;         /* starting mtime of sudoers file */
     off_t orig_size;                   /* starting size of sudoers file */
     ssize_t nread;                     /* number of bytes read */
     struct stat sb;                    /* stat buffer */
@@ -332,7 +335,7 @@ edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno)
     if (fstat(sp->fd, &sb) == -1)
        sudo_fatal(U_("unable to stat %s"), sp->path);
     orig_size = sb.st_size;
-    mtim_get(&sb, &orig_mtim);
+    mtim_get(&sb, orig_mtim);
 
     /* Create the temp file if needed and set timestamp. */
     if (sp->tpath == NULL) {
@@ -358,8 +361,8 @@ edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno)
        (void) close(tfd);
     }
     times[0].tv_sec = times[1].tv_sec = orig_mtim.tv_sec;
-    times[0].tv_usec = times[1].tv_usec = orig_mtim.tv_usec;
-    (void) utimes(sp->tpath, times);
+    times[0].tv_nsec = times[1].tv_nsec = orig_mtim.tv_nsec;
+    (void) utimensat(AT_FDCWD, sp->tpath, times, 0);
 
     /* Does the editor support +lineno? */
     if (lineno > 0)
@@ -429,13 +432,13 @@ edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno)
      *  XPG4 specifies that vi's exit value is a function of the
      *  number of errors during editing (?!?!).
      */
-    if (gettimeofday(&times[0], NULL) == -1) {
+    if (sudo_gettime_real(&times[0]) == -1) {
        sudo_warn(U_("unable to read the clock"));
        goto done;
     }
 
     if (run_command(editor, av) != -1) {
-       if (gettimeofday(&times[1], NULL) == -1) {
+       if (sudo_gettime_real(&times[1]) == -1) {
            sudo_warn(U_("unable to read the clock"));
            goto done;
        }
@@ -460,13 +463,13 @@ edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno)
 
     /* Set modified bit if the user changed the file. */
     modified = true;
-    mtim_get(&sb, &tv);
-    if (orig_size == sb.st_size && sudo_timevalcmp(&orig_mtim, &tv, ==)) {
+    mtim_get(&sb, ts);
+    if (orig_size == sb.st_size && sudo_timespeccmp(&orig_mtim, &ts, ==)) {
        /*
         * If mtime and size match but the user spent no measurable
         * time in the editor we can't tell if the file was changed.
         */
-       if (sudo_timevalcmp(&times[0], &times[1], !=))
+       if (sudo_timespeccmp(&times[0], &times[1], !=))
            modified = false;
     }
 
index 6dbf1f2cfb6d17dc82b9922ef24ba8c57426874d..f0a8d6fa07aeb28842e667d2e993634ca5ca78ed 100644 (file)
@@ -349,12 +349,12 @@ sudo.o: $(srcdir)/sudo.c $(incdir)/compat/stdbool.h $(incdir)/sudo_alloc.h \
         $(top_builddir)/pathnames.h ./sudo_usage.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudo.c
 sudo_edit.o: $(srcdir)/sudo_edit.c $(incdir)/compat/stdbool.h \
-             $(incdir)/sudo_alloc.h $(incdir)/sudo_compat.h \
-             $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
-             $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
-             $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
-             $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
-             $(top_builddir)/pathnames.h
+             $(incdir)/compat/timespec.h $(incdir)/sudo_alloc.h \
+             $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+             $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+             $(incdir)/sudo_gettext.h $(incdir)/sudo_queue.h \
+             $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+             $(top_builddir)/config.h $(top_builddir)/pathnames.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudo_edit.c
 sudo_noexec.lo: $(srcdir)/sudo_noexec.c $(incdir)/sudo_compat.h \
                 $(top_builddir)/config.h
index 78eab84b4335510dea82fdcd59716d3877471fe5..ec10ec4e865b4811bf9d734c722bb705800ebfd3 100644 (file)
@@ -121,7 +121,7 @@ sesh_sudoedit(int argc, char *argv[])
     int fd_src, fd_dst, i, oflags_dst, post, ret = SESH_ERR_FAILURE;
     ssize_t nread, nwritten;
     struct stat sb;
-    struct timeval times[2];
+    struct timespec times[2];
     char buf[BUFSIZ];
     debug_decl(sesh_sudoedit, SUDO_DEBUG_EDIT)
 
@@ -206,14 +206,13 @@ sesh_sudoedit(int argc, char *argv[])
                if (fd_src == -1 || fstat(fd_src, &sb) != 0)
                    memset(&sb, 0, sizeof(sb));
                /* Make mtime on temp file match src. */
-               mtim_get(&sb, &times[0]);
+               mtim_get(&sb, times[0]);
                times[1].tv_sec = times[0].tv_sec;
-               times[1].tv_usec = times[0].tv_usec;
-#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIME)
-               (void) futimes(fd_dst, times);
-#else
-               (void) utimes(path_dst, times);
-#endif
+               times[1].tv_nsec = times[0].tv_nsec;
+               if (futimens(fd_dst, times) == -1) {
+                   if (utimensat(AT_FDCWD, path_dst, times, 0) == -1)
+                       sudo_warn("%s", path_dst);
+               }
            }
            close(fd_dst);
        }
index be71fb50137c6831e05846c68c5431e2875d518f..d3cd22b51a24038270a8dc508729f80d1ae27172 100644 (file)
@@ -48,6 +48,9 @@
 #ifdef TIME_WITH_SYS_TIME
 # include <time.h>
 #endif
+#ifndef HAVE_STRUCT_TIMESPEC
+# include "compat/timespec.h"
+#endif
 #ifdef HAVE_SELINUX
 # include <selinux/selinux.h>
 #endif
@@ -63,7 +66,7 @@
 struct tempfile {
     char *tfile;
     char *ofile;
-    struct timeval omtim;
+    struct timespec omtim;
     off_t osize;
 };
 
@@ -174,7 +177,7 @@ sudo_edit_create_tfiles(struct command_details *command_details,
     int i, j, tfd, ofd, rc;
     char buf[BUFSIZ];
     ssize_t nwritten, nread;
-    struct timeval times[2];
+    struct timespec times[2];
     struct stat sb;
     debug_decl(sudo_edit_create_tfiles, SUDO_DEBUG_EDIT)
 
@@ -207,7 +210,7 @@ sudo_edit_create_tfiles(struct command_details *command_details,
        }
        tf[j].ofile = files[i];
        tf[j].osize = sb.st_size;
-       mtim_get(&sb, &tf[j].omtim);
+       mtim_get(&sb, tf[j].omtim);
        sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
            "seteuid(%u)", user_details.uid);
        if (seteuid(user_details.uid) != 0)
@@ -239,19 +242,18 @@ sudo_edit_create_tfiles(struct command_details *command_details,
         * We always update the stashed mtime because the time
         * resolution of the filesystem the temporary file is on may
         * not match that of the filesystem where the file to be edited
-        * resides.  It is OK if futimes() fails since we only use the
+        * resides.  It is OK if futimens() fails since we only use the
         * info to determine whether or not a file has been modified.
         */
        times[0].tv_sec = times[1].tv_sec = tf[j].omtim.tv_sec;
-       times[0].tv_usec = times[1].tv_usec = tf[j].omtim.tv_usec;
-#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIME)
-       (void) futimes(tfd, times);
-#else
-       (void) utimes(tf[j].tfile, times);
-#endif
+       times[0].tv_nsec = times[1].tv_nsec = tf[j].omtim.tv_nsec;
+       if (futimens(tfd, times) == -1) {
+           if (utimensat(AT_FDCWD, tf[j].tfile, times, 0) == -1)
+               sudo_warn("%s", tf[j].tfile);
+       }
        rc = fstat(tfd, &sb);
        if (!rc)
-           mtim_get(&sb, &tf[j].omtim);
+           mtim_get(&sb, tf[j].omtim);
        close(tfd);
        j++;
     }
@@ -264,12 +266,12 @@ sudo_edit_create_tfiles(struct command_details *command_details,
  */
 static int
 sudo_edit_copy_tfiles(struct command_details *command_details,
-    struct tempfile *tf, int nfiles, struct timeval *times)
+    struct tempfile *tf, int nfiles, struct timespec *times)
 {
     int i, tfd, ofd, rc, errors = 0;
     char buf[BUFSIZ];
     ssize_t nwritten, nread;
-    struct timeval tv;
+    struct timespec ts;
     struct stat sb;
     debug_decl(sudo_edit_copy_tfiles, SUDO_DEBUG_EDIT)
 
@@ -298,13 +300,13 @@ sudo_edit_copy_tfiles(struct command_details *command_details,
            errors++;
            continue;
        }
-       mtim_get(&sb, &tv);
-       if (tf[i].osize == sb.st_size && sudo_timevalcmp(&tf[i].omtim, &tv, ==)) {
+       mtim_get(&sb, ts);
+       if (tf[i].osize == sb.st_size && sudo_timespeccmp(&tf[i].omtim, &ts, ==)) {
            /*
             * If mtime and size match but the user spent no measurable
             * time in the editor we can't tell if the file was changed.
             */
-           if (sudo_timevalcmp(&times[0], &times[1], !=)) {
+           if (sudo_timespeccmp(&times[0], &times[1], !=)) {
                sudo_warnx(U_("%s unchanged"), tf[i].ofile);
                unlink(tf[i].tfile);
                close(tfd);
@@ -387,7 +389,7 @@ selinux_edit_create_tfiles(struct command_details *command_details,
        if (stat(ofile, &sb) == -1)
            memset(&sb, 0, sizeof(sb));         /* new file */
        tf[i].osize = sb.st_size;
-       mtim_get(&sb, &tf[i].omtim);
+       mtim_get(&sb, tf[i].omtim);
        /*
         * The temp file must be created by the sesh helper,
         * which uses O_EXCL | O_NOFOLLOW to make this safe.
@@ -442,12 +444,12 @@ selinux_edit_create_tfiles(struct command_details *command_details,
 
 static int
 selinux_edit_copy_tfiles(struct command_details *command_details,
-    struct tempfile *tf, int nfiles, struct timeval *times)
+    struct tempfile *tf, int nfiles, struct timespec *times)
 {
     char **sesh_args, **sesh_ap;
     int i, rc, sesh_nargs, rval = 1;
     struct command_details saved_command_details;
-    struct timeval tv;
+    struct timespec ts;
     struct stat sb;
     debug_decl(selinux_edit_copy_tfiles, SUDO_DEBUG_EDIT)
     
@@ -473,13 +475,13 @@ selinux_edit_copy_tfiles(struct command_details *command_details,
     /* Construct args for sesh -e 1 */
     for (i = 0; i < nfiles; i++) {
        if (stat(tf[i].tfile, &sb) == 0) {
-           mtim_get(&sb, &tv);
-           if (tf[i].osize == sb.st_size && sudo_timevalcmp(&tf[i].omtim, &tv, ==)) {
+           mtim_get(&sb, ts);
+           if (tf[i].osize == sb.st_size && sudo_timespeccmp(&tf[i].omtim, &ts, ==)) {
                /*
                 * If mtime and size match but the user spent no measurable
                 * time in the editor we can't tell if the file was changed.
                 */
-               if (sudo_timevalcmp(&times[0], &times[1], !=)) {
+               if (sudo_timespeccmp(&times[0], &times[1], !=)) {
                    sudo_warnx(U_("%s unchanged"), tf[i].ofile);
                    unlink(tf[i].tfile);
                    continue;
@@ -537,7 +539,7 @@ sudo_edit(struct command_details *command_details)
     char **nargv = NULL, **ap, **files = NULL;
     int errors, i, ac, nargc, rval;
     int editor_argc = 0, nfiles = 0;
-    struct timeval times[2];
+    struct timespec times[2];
     struct tempfile *tf = NULL;
     debug_decl(sudo_edit, SUDO_DEBUG_EDIT)
 
@@ -600,7 +602,7 @@ sudo_edit(struct command_details *command_details)
      * Run the editor with the invoking user's creds,
      * keeping track of the time spent in the editor.
      */
-    if (gettimeofday(&times[0], NULL) == -1) {
+    if (sudo_gettime_real(&times[0]) == -1) {
        sudo_warn(U_("unable to read the clock"));
        goto cleanup;
     }
@@ -613,7 +615,7 @@ sudo_edit(struct command_details *command_details)
     command_details->groups = user_details.groups;
     command_details->argv = nargv;
     rval = run_command(command_details);
-    if (gettimeofday(&times[1], NULL) == -1) {
+    if (sudo_gettime_real(&times[1]) == -1) {
        sudo_warn(U_("unable to read the clock"));
        goto cleanup;
     }