Use futimens() and utimensat() instead of futimes() and utimes().
This commit is contained in:
4
MANIFEST
4
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
|
||||
|
@@ -244,6 +244,9 @@
|
||||
/* 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
|
||||
|
||||
@@ -826,6 +829,9 @@
|
||||
/* 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
|
||||
|
||||
|
88
configure
vendored
88
configure
vendored
@@ -18939,7 +18939,29 @@ done
|
||||
fi
|
||||
done
|
||||
|
||||
for ac_func in utimes
|
||||
for ac_func in utimensat
|
||||
do :
|
||||
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_UTIMENSAT 1
|
||||
_ACEOF
|
||||
|
||||
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 :
|
||||
ac_fn_c_check_func "$LINENO" "utimes" "ac_cv_func_utimes"
|
||||
if test "x$ac_cv_func_utimes" = xyes; then :
|
||||
@@ -18947,7 +18969,36 @@ if test "x$ac_cv_func_utimes" = xyes; then :
|
||||
#define HAVE_UTIMES 1
|
||||
_ACEOF
|
||||
|
||||
for ac_func in futimes futimesat
|
||||
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
|
||||
*" utimens.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS utimens.$ac_objext"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
for _sym in sudo_futimens; do
|
||||
COMPAT_EXP="${COMPAT_EXP}${_sym}
|
||||
"
|
||||
done
|
||||
|
||||
for ac_func in futimes futimesat futime
|
||||
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"
|
||||
@@ -18960,37 +19011,6 @@ fi
|
||||
done
|
||||
|
||||
|
||||
else
|
||||
|
||||
case " $LIBOBJS " in
|
||||
*" utimes.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS utimes.$ac_objext"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
for _sym in sudo_utimes; do
|
||||
COMPAT_EXP="${COMPAT_EXP}${_sym}
|
||||
"
|
||||
done
|
||||
|
||||
for ac_func in futime
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "futime" "ac_cv_func_futime"
|
||||
if test "x$ac_cv_func_futime" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_FUTIME 1
|
||||
_ACEOF
|
||||
|
||||
for _sym in sudo_futimes; do
|
||||
COMPAT_EXP="${COMPAT_EXP}${_sym}
|
||||
"
|
||||
done
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
17
configure.ac
17
configure.ac
@@ -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], [], [
|
||||
|
@@ -189,6 +189,19 @@
|
||||
# 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
|
||||
|
@@ -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
|
||||
@@ -104,24 +104,32 @@
|
||||
#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
|
||||
#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 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
|
||||
# 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)
|
||||
# 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)->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))
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
@@ -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
|
||||
|
198
lib/util/utimens.c
Normal file
198
lib/util/utimens.c
Normal file
@@ -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 */
|
@@ -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) */
|
2
mkdep.pl
2
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;
|
||||
|
@@ -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 \
|
||||
|
@@ -59,13 +59,13 @@
|
||||
#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);
|
||||
|
@@ -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]);
|
||||
|
@@ -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;
|
||||
|
@@ -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(×[0], NULL) == -1) {
|
||||
if (sudo_gettime_real(×[0]) == -1) {
|
||||
sudo_warn(U_("unable to read the clock"));
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (run_command(editor, av) != -1) {
|
||||
if (gettimeofday(×[1], NULL) == -1) {
|
||||
if (sudo_gettime_real(×[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(×[0], ×[1], !=))
|
||||
if (sudo_timespeccmp(×[0], ×[1], !=))
|
||||
modified = false;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
15
src/sesh.c
15
src/sesh.c
@@ -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, ×[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);
|
||||
}
|
||||
|
@@ -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(×[0], ×[1], !=)) {
|
||||
if (sudo_timespeccmp(×[0], ×[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(×[0], ×[1], !=)) {
|
||||
if (sudo_timespeccmp(×[0], ×[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(×[0], NULL) == -1) {
|
||||
if (sudo_gettime_real(×[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(×[1], NULL) == -1) {
|
||||
if (sudo_gettime_real(×[1]) == -1) {
|
||||
sudo_warn(U_("unable to read the clock"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
Reference in New Issue
Block a user