dovecot: Rewrote utc_mktime() so it's now MIT licensed. This als...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Sep 23 00:18:51 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/6d15946eccb5
changeset: 6483:6d15946eccb5
user: Timo Sirainen <tss at iki.fi>
date: Sun Sep 23 00:18:47 2007 +0300
description:
Rewrote utc_mktime() so it's now MIT licensed. This also fixes handling
years older than 1970.
diffstat:
3 files changed, 68 insertions(+), 138 deletions(-)
configure.in | 21 +++++
src/lib/utc-mktime.c | 183 +++++++++++++-------------------------------------
src/lib/utc-mktime.h | 2
diffs (250 lines):
diff -r c02c7912fb15 -r 6d15946eccb5 configure.in
--- a/configure.in Sat Sep 22 23:14:30 2007 +0300
+++ b/configure.in Sun Sep 23 00:18:47 2007 +0300
@@ -927,9 +927,9 @@ AC_CACHE_CHECK([how large time_t values
int main() {
FILE *f;
int bits;
- time_t t;
- for (bits = 1, t = 1; t > 0; ++bits, t <<= 1) {
+ for (bits = 1; bits < 64; bits++) {
+ time_t t = ((time_t)1 << bits) - 1;
if (gmtime(&t) == NULL) {
bits--;
break;
@@ -959,6 +959,23 @@ AC_CACHE_CHECK([how large time_t values
],[])
])
AC_DEFINE_UNQUOTED(TIME_T_MAX_BITS, $gmtime_max_time_t, max. time_t bits gmtime() can handle)
+
+AC_CACHE_CHECK([whether time_t is signed],signed_time_t,[
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+ #include <sys/types.h>
+ int main() {
+ /* return 0 if we're signed */
+ exit((time_t)(int)-1 <= 0 ? 0 : 1);
+ }
+ ]])],[
+ signed_time_t=yes
+ ], [
+ signed_time_t=no
+ ])
+])
+if test $signed_time_t = yes; then
+ AC_DEFINE(TIME_T_SIGNED,, Define if your time_t is signed)
+fi
dnl * do we have struct iovec
AC_MSG_CHECKING([for struct iovec])
diff -r c02c7912fb15 -r 6d15946eccb5 src/lib/utc-mktime.c
--- a/src/lib/utc-mktime.c Sat Sep 22 23:14:30 2007 +0300
+++ b/src/lib/utc-mktime.c Sun Sep 23 00:18:47 2007 +0300
@@ -1,148 +1,61 @@
-/*
- * Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The name "Carnegie Mellon University" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For permission or any other legal
- * details, please contact
- * Office of Technology Transfer
- * Carnegie Mellon University
- * 5000 Forbes Avenue
- * Pittsburgh, PA 15213-3890
- * (412) 268-4387, fax: (412) 268-7395
- * tech-transfer at andrew.cmu.edu
- *
- * 4. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Computing Services
- * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
- *
- * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
- * FOR ANY SPECIAL, 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.
- *
- *
- */
-/*
- * Copyright (c) 1987, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Arthur David Olson of the National Cancer Institute.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
-** Adapted from code provided by Robert Elz, who writes:
-** The "best" way to do mktime I think is based on an idea of Bob
-** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
-** It does a binary search of the time_t space. Since time_t's are
-** just 32 bits, its a max of 32 iterations (even at 64 bits it
-** would still be very reasonable).
-*/
+/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "utc-mktime.h"
-static int tmcomp(register const struct tm * const atmp,
- register const struct tm * const btmp)
+static int tm_cmp(const struct tm *tm1, const struct tm *tm2)
{
- register int result;
+ int diff;
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
- (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
- (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
- (result = (atmp->tm_min - btmp->tm_min)) == 0)
- result = atmp->tm_sec - btmp->tm_sec;
- return result;
+ if ((diff = tm1->tm_year - tm2->tm_year) != 0)
+ return diff;
+ if ((diff = tm1->tm_mon - tm2->tm_mon) != 0)
+ return diff;
+ if ((diff = tm1->tm_mday - tm2->tm_mday) != 0)
+ return diff;
+ if ((diff = tm1->tm_hour - tm2->tm_hour) != 0)
+ return diff;
+ if ((diff = tm1->tm_min - tm2->tm_min) != 0)
+ return diff;
+ return tm1->tm_sec - tm2->tm_sec;
}
-time_t utc_mktime(struct tm *tm)
+time_t utc_mktime(const struct tm *tm)
{
- register int dir;
- register int bits;
- register int saved_seconds;
- time_t t;
- struct tm yourtm, *mytm;
+ const struct tm *try_tm;
+ struct tm nosec_tm;
+ time_t t;
+ int bits, dir;
- yourtm = *tm;
- saved_seconds = yourtm.tm_sec;
- yourtm.tm_sec = 0;
- /*
- ** Calculate the number of magnitude bits in a time_t
- ** (this works regardless of whether time_t is
- ** signed or unsigned, though lint complains if unsigned).
- **
- ** We check TIME_T_MAX_BITS beforehand since gmtime() may fail
- ** with large 64bit values in some systems.
- */
- for (bits = 0, t = 1; t > 0 && bits < TIME_T_MAX_BITS-1; bits++)
- t <<= 1;
+ /* we'll do a binary search across the entire valid time_t range.
+ when gmtime()'s output matches the tm parameter, we've found the
+ correct time_t value. this also means that if tm contains invalid
+ values, -1 is returned. */
+#ifdef TIME_T_SIGNED
+ t = 0;
+ bits = TIME_T_MAX_BITS - 1;
+#else
+ t = 1 << (TIME_T_MAX_BITS - 1);
+ bits = TIME_T_MAX_BITS - 2;
+#endif
- /*
- ** If time_t is signed, then 0 is the median value,
- ** if time_t is unsigned, then 1 << bits is median.
- */
- t = (t < 0) ? 0 : ((time_t) 1 << bits);
- for ( ; ; ) {
- mytm = gmtime(&t);
- dir = tmcomp(mytm, &yourtm);
- if (dir != 0) {
- if (bits-- < 0)
- return (time_t)-1;
- if (bits < 0)
- --t;
- else if (dir > 0)
- t -= (time_t) 1 << bits;
- else t += (time_t) 1 << bits;
- continue;
- }
- break;
+ /* we can ignore seconds in checks and add them back when returning */
+ nosec_tm = *tm;
+ nosec_tm.tm_sec = 0;
+
+ for (;; bits--) {
+ try_tm = gmtime(&t);
+ dir = tm_cmp(&nosec_tm, try_tm);
+ if (dir == 0)
+ return t + tm->tm_sec;
+ if (bits < 0)
+ break;
+
+ if (dir < 0)
+ t -= (time_t)1 << bits;
+ else
+ t += (time_t)1 << bits;
}
- t += saved_seconds;
- return t;
+
+ return (time_t)-1;
}
diff -r c02c7912fb15 -r 6d15946eccb5 src/lib/utc-mktime.h
--- a/src/lib/utc-mktime.h Sat Sep 22 23:14:30 2007 +0300
+++ b/src/lib/utc-mktime.h Sun Sep 23 00:18:47 2007 +0300
@@ -5,6 +5,6 @@
/* Like mktime(), but assume that tm is in UTC. Unlike mktime(), values in
tm fields must be in valid range. */
-time_t utc_mktime(struct tm *tm);
+time_t utc_mktime(const struct tm *tm);
#endif
More information about the dovecot-cvs
mailing list