with file times and time of day.
--HG--
branch : 1.7
#include <sys/types.h>
#include <sys/param.h>
+#include <sys/time.h>
#include <sys/stat.h>
#ifndef __TANDEM
# include <sys/file.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
+#if TIME_WITH_SYS_TIME
+# include <time.h>
+#endif
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
-#include <time.h>
#include <pwd.h>
#include <grp.h>
-#ifndef HAVE_TIMESPEC
-# include <emul/timespec.h>
-#endif
#include "sudo.h"
if (def_timestamp_timeout < 0 && sb.st_mtime != 0)
status = TS_CURRENT;
else {
- /* XXX - should use timespec here */
+ /* XXX - should use timeval here */
now = time(NULL);
boottime = get_boottime();
if (def_timestamp_timeout &&
remove_timestamp(remove)
int remove;
{
- struct timespec ts;
+ struct timeval tv;
char *timestampdir, *timestampfile, *path;
int status;
remove = FALSE;
}
} else {
- timespecclear(&ts);
- if (touch(-1, path, &ts) == -1)
+ timerclear(&tv);
+ if (touch(-1, path, &tv) == -1)
error(1, "can't reset %s to Epoch", path);
}
}
#endif /* HAVE___PROGNAME */
#endif /* !HAVE_GETPROGNAME */
-#ifndef timespecclear
-# define timespecclear(ts) (ts)->tv_sec = (ts)->tv_nsec = 0
+#ifndef timerclear
+# define timerclear(ts) (ts)->tv_sec = (ts)->tv_nsec = 0
#endif
-#ifndef timespecisset
-# define timespecisset(ts) ((ts)->tv_sec || (ts)->tv_nsec)
+#ifndef timerisset
+# define timerisset(ts) ((ts)->tv_sec || (ts)->tv_nsec)
#endif
-#ifndef timespecsub
-# define timespecsub(minuend, subrahend, difference) \
- do { \
- (difference)->tv_sec = (minuend)->tv_sec - (subrahend)->tv_sec; \
- (difference)->tv_nsec = (minuend)->tv_nsec - (subrahend)->tv_nsec; \
- if ((difference)->tv_nsec < 0) { \
- (difference)->tv_nsec += 1000000000L; \
- (difference)->tv_sec--; \
- } \
- } while (0)
-#endif
-
#ifndef timeradd
# define timeradd(tv1, tv2, total) \
do { \
} \
} while (0)
#endif
-
#ifndef timersub
# define timersub(minuend, subrahend, difference) \
do { \
/* Define to 1 if you have a timespecsub macro or function that takes two
arguments (not three) */
-#undef HAVE_TIMESPECSUB2
+#undef HAVE_TIMERSUB2
/* Define to 1 if you have the `tzset' function. */
#undef HAVE_TZSET
#undef volatile
/*
- * Macros to pull sec and nsec parts of mtime from struct stat.
- * We need to be able to convert between timeval and timespec
- * so the last 3 digits of tv_nsec are not significant.
+ * Macros to convert ctime and mtime into timevals.
*/
+#define timespec2timeval(_ts, _tv) do { \
+ (_tv)->tv_sec = (_ts)->tv_sec; \
+ (_tv)->tv_usec = (_ts)->tv_nsec / 1000; \
+} while (0)
+
#ifdef HAVE_ST_MTIM
# ifdef HAVE_ST__TIM
-# define mtim_getsec(_x) ((_x).st_mtim.st__tim.tv_sec)
-# define mtim_getnsec(_x) (((_x).st_mtim.st__tim.tv_nsec / 1000) * 1000)
+# define ctim_get(_x, _y) timespec2timeval(&(_x)->st_ctim.st__tim, (_y))
+# define mtim_get(_x, _y) timespec2timeval(&(_x)->st_mtim.st__tim, (_y))
# else
-# define mtim_getsec(_x) ((_x).st_mtim.tv_sec)
-# define mtim_getnsec(_x) (((_x).st_mtim.tv_nsec / 1000) * 1000)
+# define ctim_get(_x, _y) timespec2timeval(&(_x)->st_ctim, (_y))
+# define mtim_get(_x, _y) timespec2timeval(&(_x)->st_mtim, (_y))
# endif
#else
# ifdef HAVE_ST_MTIMESPEC
-# define mtim_getsec(_x) ((_x).st_mtimespec.tv_sec)
-# define mtim_getnsec(_x) (((_x).st_mtimespec.tv_nsec / 1000) * 1000)
+# define ctim_get(_x, _y) timespec2timeval(&(_x)->st_ctimespec, (_y))
+# define mtim_get(_x, _y) timespec2timeval(&(_x)->st_mtimespec, (_y))
# else
-# define mtim_getsec(_x) ((_x).st_mtime)
-# define mtim_getnsec(_x) (0)
+# 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 */
#endif /* HAVE_ST_MTIM */
fi
- { echo "$as_me:$LINENO: checking for two-parameter timespecsub" >&5
-echo $ECHO_N "checking for two-parameter timespecsub... $ECHO_C" >&6; }
+ { echo "$as_me:$LINENO: checking for two-parameter timersub" >&5
+echo $ECHO_N "checking for two-parameter timersub... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
int
main ()
{
-struct timespec ts1, ts2;
-ts1.tv_sec = 1; ts1.tv_nsec = 0; ts2.tv_sec = 0; ts2.tv_nsec = 0;
-#ifndef timespecsub
-#error missing timespecsub
+struct timeval ts1, ts2;
+ts1.tv_sec = 1; ts1.tv_usec = 0; ts2.tv_sec = 0; ts2.tv_usec = 0;
+#ifndef timersub
+#error missing timersub
#endif
-timespecsub(&ts1, &ts2);
+timersub(&ts1, &ts2);
;
return 0;
}
test ! -s conftest.err
} && test -s conftest.$ac_objext; then
cat >>confdefs.h <<\_ACEOF
-#define HAVE_TIMESPECSUB2 1
+#define HAVE_TIMERSUB2 1
_ACEOF
{ echo "$as_me:$LINENO: result: yes" >&5
AC_CHECK_MEMBER([struct stat.st_mtim], [AC_DEFINE(HAVE_ST_MTIM)]
[AC_CHECK_MEMBER([struct stat.st_mtim.st__tim], AC_DEFINE(HAVE_ST__TIM))],
[AC_CHECK_MEMBER([struct stat.st_mtimespec], AC_DEFINE([HAVE_ST_MTIMESPEC]))])
- AC_MSG_CHECKING([for two-parameter timespecsub])
+ AC_MSG_CHECKING([for two-parameter timersub])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
-#include <sys/time.h>]], [[struct timespec ts1, ts2;
-ts1.tv_sec = 1; ts1.tv_nsec = 0; ts2.tv_sec = 0; ts2.tv_nsec = 0;
-#ifndef timespecsub
-#error missing timespecsub
+#include <sys/time.h>]], [[struct timeval ts1, ts2;
+ts1.tv_sec = 1; ts1.tv_usec = 0; ts2.tv_sec = 0; ts2.tv_usec = 0;
+#ifndef timersub
+#error missing timersub
#endif
-timespecsub(&ts1, &ts2);]])], [AC_DEFINE(HAVE_TIMESPECSUB2)
+timersub(&ts1, &ts2);]])], [AC_DEFINE(HAVE_TIMERSUB2)
AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)])
fi
dnl
AH_TEMPLATE(HAVE_ST_MTIMESPEC, [Define to 1 if your struct stat has an st_mtimespec member])
AH_TEMPLATE(HAVE_TERMIOS_H, [Define to 1 if you have the <termios.h> header file and the `tcgetattr' function.])
AH_TEMPLATE(HAVE_TIMESPEC, [Define to 1 if you have struct timespec in sys/time.h])
-AH_TEMPLATE(HAVE_TIMESPECSUB2, [Define to 1 if you have a timespecsub macro or function that takes two arguments (not three)])
+AH_TEMPLATE(HAVE_TIMERSUB2, [Define to 1 if you have a timersub macro or function that takes two arguments (not three)])
AH_TEMPLATE(HAVE___PROGNAME, [Define to 1 if your crt0.o defines the __progname symbol for you.])
AH_TEMPLATE(HOST_IN_LOG, [Define to 1 if you want the hostname to be entered into the log file.])
AH_TEMPLATE(IGNORE_DOT_PATH, [Define to 1 if you want to ignore '.' and empty PATH elements])
#define _SUDO_CONFIG_H])
AH_BOTTOM([/*
- * Macros to pull sec and nsec parts of mtime from struct stat.
- * We need to be able to convert between timeval and timespec
- * so the last 3 digits of tv_nsec are not significant.
+ * Macros to convert ctime and mtime into timevals.
*/
+#define timespec2timeval(_ts, _tv) do { \
+ (_tv)->tv_sec = (_ts)->tv_sec; \
+ (_tv)->tv_usec = (_ts)->tv_nsec / 1000; \
+} while (0)
+
#ifdef HAVE_ST_MTIM
# ifdef HAVE_ST__TIM
-# define mtim_getsec(_x) ((_x).st_mtim.st__tim.tv_sec)
-# define mtim_getnsec(_x) (((_x).st_mtim.st__tim.tv_nsec / 1000) * 1000)
+# define ctim_get(_x, _y) timespec2timeval(&(_x)->st_ctim.st__tim, (_y))
+# define mtim_get(_x, _y) timespec2timeval(&(_x)->st_mtim.st__tim, (_y))
# else
-# define mtim_getsec(_x) ((_x).st_mtim.tv_sec)
-# define mtim_getnsec(_x) (((_x).st_mtim.tv_nsec / 1000) * 1000)
+# define ctim_get(_x, _y) timespec2timeval(&(_x)->st_ctim, (_y))
+# define mtim_get(_x, _y) timespec2timeval(&(_x)->st_mtim, (_y))
# endif
#else
# ifdef HAVE_ST_MTIMESPEC
-# define mtim_getsec(_x) ((_x).st_mtimespec.tv_sec)
-# define mtim_getnsec(_x) (((_x).st_mtimespec.tv_nsec / 1000) * 1000)
+# define ctim_get(_x, _y) timespec2timeval(&(_x)->st_ctimespec, (_y))
+# define mtim_get(_x, _y) timespec2timeval(&(_x)->st_mtimespec, (_y))
# else
-# define mtim_getsec(_x) ((_x).st_mtime)
-# define mtim_getnsec(_x) (0)
+# 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 */
#endif /* HAVE_ST_MTIM */
* Update the access and modify times on an fd or file.
*/
int
-touch(fd, path, tsp)
+touch(fd, path, tvp)
int fd;
char *path;
- struct timespec *tsp;
+ struct timeval *tvp;
{
struct timeval times[2];
- if (tsp != NULL) {
- times[0].tv_sec = times[1].tv_sec = tsp->tv_sec;
- times[0].tv_usec = times[1].tv_usec = tsp->tv_nsec / 1000;
+ if (tvp != NULL) {
+ times[0].tv_sec = times[1].tv_sec = tvp->tv_sec;
+ times[0].tv_usec = times[1].tv_usec = tvp->tv_usec;
}
#if defined(HAVE_FUTIME) || defined(HAVE_FUTIMES)
if (fd != -1)
- return(futimes(fd, tsp ? times : NULL));
+ return(futimes(fd, tvp ? times : NULL));
else
#endif
if (path != NULL)
- return(utimes(path, tsp ? times : NULL));
+ return(utimes(path, tvp ? times : NULL));
else
return(-1);
}
#if TIME_WITH_SYS_TIME
# include <time.h>
#endif
-#ifndef HAVE_TIMESPEC
-# include <emul/timespec.h>
-#endif
#include <compat.h>
* timespecs in struct stat or, otherwise, using time().
*/
int
-gettime(ts)
- struct timespec *ts;
+gettime(tv)
+ struct timeval *tv;
{
int rval;
#if defined(HAVE_GETTIMEOFDAY) && (defined(HAVE_ST_MTIM) || defined(HAVE_ST_MTIMESPEC))
- struct timeval tv;
-
- rval = gettimeofday(&tv, NULL);
- ts->tv_sec = tv.tv_sec;
- ts->tv_nsec = tv.tv_usec * 1000;
+ rval = gettimeofday(tv, NULL);
#else
- rval = (int)time(&ts->tv_sec);
- ts->tv_nsec = 0;
+ rval = (int)time(&tv->tv_sec);
+ tv->tv_usec = 0;
#endif
return (rval);
}
void init_envtables __P((void));
void read_env_file __P((const char *, int));
int lock_file __P((int, int));
-int touch __P((int, char *, struct timespec *));
+int touch __P((int, char *, struct timeval *));
int user_is_exempt __P((void));
void set_fqdn __P((void));
char *sudo_getepw __P((const struct passwd *));
int pam_prep_user __P((struct passwd *));
void zero_bytes __P((volatile void *, size_t));
-int gettime __P((struct timespec *));
+int gettime __P((struct timeval *));
FILE *open_sudoers __P((const char *, int, int *));
void display_privs __P((struct sudo_nss_list *, struct passwd *));
int display_cmnd __P((struct sudo_nss_list *, struct passwd *));
#if TIME_WITH_SYS_TIME
# include <time.h>
#endif
-#ifndef HAVE_TIMESPEC
-# include <emul/timespec.h>
-#endif
#include "sudo.h"
const char *tmpdir;
char **nargv, **ap, *editor, *cp;
char buf[BUFSIZ];
- int error, i, ac, ofd, tfd, nargc, rval, tmplen, wasblank;
+ int rc, i, ac, ofd, tfd, nargc, rval, tmplen, wasblank;
struct stat sb;
- struct timespec ts1, ts2;
+ struct timeval tv, tv1, tv2;
struct tempfile {
char *tfile;
char *ofile;
- struct timespec omtim;
+ struct timeval omtim;
off_t osize;
} *tf;
tf = emalloc2(argc - 1, sizeof(*tf));
zero_bytes(tf, (argc - 1) * sizeof(*tf));
for (i = 0, ap = argv + 1; i < argc - 1 && *ap != NULL; i++, ap++) {
- error = -1;
+ rc = -1;
set_perms(PERM_RUNAS);
if ((ofd = open(*ap, O_RDONLY, 0644)) != -1 || errno == ENOENT) {
if (ofd == -1) {
zero_bytes(&sb, sizeof(sb)); /* new file */
- error = 0;
+ rc = 0;
} else {
#ifdef HAVE_FSTAT
- error = fstat(ofd, &sb);
+ rc = fstat(ofd, &sb);
#else
- error = stat(tf[i].ofile, &sb);
+ rc = stat(tf[i].ofile, &sb);
#endif
}
}
set_perms(PERM_ROOT);
- if (error || (ofd != -1 && !S_ISREG(sb.st_mode))) {
- if (error)
+ if (rc || (ofd != -1 && !S_ISREG(sb.st_mode))) {
+ if (rc)
warning("%s", *ap);
else
warningx("%s: not a regular file", *ap);
continue;
}
tf[i].ofile = *ap;
- tf[i].omtim.tv_sec = mtim_getsec(sb);
- tf[i].omtim.tv_nsec = mtim_getnsec(sb);
+ mtim_get(&sb, &tf[i].omtim);
tf[i].osize = sb.st_size;
if ((cp = strrchr(tf[i].ofile, '/')) != NULL)
cp++;
*/
(void) touch(tfd, NULL, &tf[i].omtim);
#ifdef HAVE_FSTAT
- error = fstat(tfd, &sb);
+ rc = fstat(tfd, &sb);
#else
- error = stat(tf[i].tfile, &sb);
+ rc = stat(tf[i].tfile, &sb);
#endif
- if (!error) {
- tf[i].omtim.tv_sec = mtim_getsec(sb);
- tf[i].omtim.tv_nsec = mtim_getnsec(sb);
- }
+ if (!rc)
+ mtim_get(&sb, &tf[i].omtim);
close(tfd);
}
if (argc == 1)
* Fork and exec the editor with the invoking user's creds,
* keeping track of the time spent in the editor.
*/
- gettime(&ts1);
+ gettime(&tv1);
kidpid = fork();
if (kidpid == -1) {
warning("fork");
break;
}
} while (pid != -1 || errno == EINTR);
- gettime(&ts2);
+ gettime(&tv2);
if (pid == -1 || !WIFEXITED(i))
rval = 1;
else
/* Copy contents of temp files to real ones */
for (i = 0; i < argc - 1; i++) {
- error = -1;
+ rc = -1;
set_perms(PERM_USER);
if ((tfd = open(tf[i].tfile, O_RDONLY, 0644)) != -1) {
#ifdef HAVE_FSTAT
- error = fstat(tfd, &sb);
+ rc = fstat(tfd, &sb);
#else
- error = stat(tf[i].tfile, &sb);
+ rc = stat(tf[i].tfile, &sb);
#endif
}
set_perms(PERM_ROOT);
- if (error || !S_ISREG(sb.st_mode)) {
- if (error)
+ if (rc || !S_ISREG(sb.st_mode)) {
+ if (rc)
warning("%s", tf[i].tfile);
else
warningx("%s: not a regular file", tf[i].tfile);
close(tfd);
continue;
}
- if (tf[i].osize == sb.st_size && tf[i].omtim.tv_sec == mtim_getsec(sb)
- && tf[i].omtim.tv_nsec == mtim_getnsec(sb)) {
+ mtim_get(&sb, &tv);
+ if (tf[i].osize == sb.st_size && timercmp(&tf[i].omtim, &tv, ==)) {
/*
* If mtime and size match but the user spent no measurable
* time in the editor we can't tell if the file was changed.
*/
-#ifdef HAVE_TIMESPECSUB2
- timespecsub(&ts1, &ts2);
+#ifdef HAVE_TIMERSUB2
+ timersub(&tv1, &tv2);
#else
- timespecsub(&ts1, &ts2, &ts2);
+ timersub(&tv1, &tv2, &tv2);
#endif
- if (timespecisset(&ts2)) {
+ if (timerisset(&tv2)) {
warningx("%s unchanged", tf[i].ofile);
unlink(tf[i].tfile);
close(tfd);
#else
# include <varargs.h>
#endif
-#ifndef HAVE_TIMESPEC
-# include <emul/timespec.h>
-#endif
#include "sudo.h"
#include "interfaces.h"
char *cp; /* scratch char pointer */
char buf[PATH_MAX*2]; /* buffer used for copying files */
char linestr[64]; /* string version of lineno */
- struct timespec ts1, ts2; /* time before and after edit */
- struct timespec orig_mtim; /* starting mtime of sudoers file */
+ struct timeval tv, tv1, tv2; /* time before and after edit */
+ struct timeval 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 */
#endif
error(1, "can't stat %s", sp->path);
orig_size = sb.st_size;
- orig_mtim.tv_sec = mtim_getsec(sb);
- orig_mtim.tv_nsec = mtim_getnsec(sb);
+ mtim_get(&sb, &orig_mtim);
/* Create the temp file if needed and set timestamp. */
if (sp->tpath == NULL) {
* XPG4 specifies that vi's exit value is a function of the
* number of errors during editing (?!?!).
*/
- gettime(&ts1);
+ gettime(&tv1);
if (run_command(editor, av) != -1) {
- gettime(&ts2);
+ gettime(&tv2);
/*
* Sanity checks.
*/
/* Set modified bit if use changed the file. */
modified = TRUE;
+ mtim_get(&sb, &tv);
if (orig_size == sb.st_size &&
- orig_mtim.tv_sec == mtim_getsec(sb) &&
- orig_mtim.tv_nsec == mtim_getnsec(sb)) {
+ orig_mtim.tv_sec == tv.tv_sec &&
+ orig_mtim.tv_usec == tv.tv_usec) {
/*
* If mtime and size match but the user spent no measurable
* time in the editor we can't tell if the file was changed.
*/
-#ifdef HAVE_TIMESPECSUB2
- timespecsub(&ts1, &ts2);
+#ifdef HAVE_TIMERSUB2
+ timersub(&tv1, &tv2);
#else
- timespecsub(&ts1, &ts2, &ts2);
+ timersub(&tv1, &tv2, &tv2);
#endif
- if (timespecisset(&ts2))
+ if (timerisset(&tv2))
modified = FALSE;
}