1/*++
2/* NAME
3/*	timecmp 3
4/* SUMMARY
5/*	compare two time_t values
6/* SYNOPSIS
7/*	#include <timecmp.h>
8/*
9/*	int	timecmp(t1, t2)
10/*	time_t	t1;
11/*	time_t	t2;
12/* DESCRIPTION
13/*	The timecmp() function return an integer greater than, equal to, or
14/*	less than 0, according as the time t1 is greater than, equal to, or
15/*	less than the time t2.  The comparison is made in a manner that is
16/*	insensitive to clock wrap-around, provided the underlying times are
17/*	within half of the time interval between the smallest and largest
18/*	representable time values.
19/* LICENSE
20/* .ad
21/* .fi
22/*	The Secure Mailer license must be distributed with this software.
23/* AUTHOR(S)
24/*	Wietse Venema
25/*	IBM T.J. Watson Research
26/*	P.O. Box 704
27/*	Yorktown Heights, NY 10598, USA
28/*
29/*	Viktor Dukhovni
30/*--*/
31
32#include "timecmp.h"
33
34/* timecmp - wrap-safe time_t comparison */
35
36int     timecmp(time_t t1, time_t t2)
37{
38    time_t  delta = t1 - t2;
39
40    if (delta == 0)
41	return 0;
42
43#define UNSIGNED(type) ( ((type)-1) > ((type)0) )
44
45    /*
46     * With a constant switch value, the compiler will emit only the code for
47     * the correct case, so the signed/unsigned test happens at compile time.
48     */
49    switch (UNSIGNED(time_t) ? 0 : 1) {
50    case 0:
51	return ((2 * delta > delta) ? 1 : -1);
52    case 1:
53	return ((delta > (time_t) 0) ? 1 : -1);
54    }
55}
56
57#ifdef TEST
58#include <assert.h>
59
60 /*
61  * Bit banging!! There is no official constant that defines the INT_MAX
62  * equivalent of the off_t type. Wietse came up with the following macro
63  * that works as long as off_t is some two's complement number.
64  *
65  * Note, however, that C99 permits signed integer representations other than
66  * two's complement.
67  */
68#include <limits.h>
69#define __MAXINT__(T) ((T) (((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ ((T) -1))))
70
71int     main()
72{
73    time_t  now = time((time_t *) 0);
74
75    /* Test that it works for normal times */
76    assert(timecmp(now + 10, now) > 0);
77    assert(timecmp(now, now) == 0);
78    assert(timecmp(now - 10, now) < 0);
79
80    /* Test that it works at a boundary time */
81    if (UNSIGNED(time_t))
82	now = (time_t) -1;
83    else
84	now = __MAXINT__(time_t);
85
86    assert(timecmp(now + 10, now) > 0);
87    assert(timecmp(now, now) == 0);
88    assert(timecmp(now - 10, now) < 0);
89
90    return (0);
91}
92
93#endif
94