Mercurial > dovecot > original-hg > dovecot-1.2
changeset 492:efa46e28a0d7 HEAD
Fixes to timezone handling which were handling quite badly. added
ioloop_timezone which gets updated with ioloop_time. Changed some GMT
references to UTC. Timezone offsets are in minutes now everywhere instead of
seconds. Fixes for unsigned time_t.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 24 Oct 2002 03:15:38 +0300 |
parents | a18cfbfbdad4 |
children | 293aac070c2c |
files | src/imap/cmd-append.c src/lib-imap/imap-date.c src/lib-imap/imap-date.h src/lib-index/mbox/mbox-append.c src/lib-index/mbox/mbox-from.c src/lib-index/mbox/mbox-index.c src/lib-mail/rfc822-date.c src/lib-mail/rfc822-date.h src/lib-storage/index/index-copy.c src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/maildir/maildir-storage.h src/lib-storage/index/mbox/mbox-save.c src/lib-storage/index/mbox/mbox-storage.h src/lib-storage/mail-storage.h src/lib/Makefile.am src/lib/gmtoff.c src/lib/gmtoff.h src/lib/ioloop.c src/lib/ioloop.h src/lib/utc-mktime.c src/lib/utc-mktime.h src/lib/utc-offset.c src/lib/utc-offset.h |
diffstat | 23 files changed, 330 insertions(+), 140 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/cmd-append.c Thu Oct 24 00:07:37 2002 +0300 +++ b/src/imap/cmd-append.c Thu Oct 24 03:15:38 2002 +0300 @@ -7,6 +7,8 @@ #include "imap-parser.h" #include "imap-date.h" +#include <sys/time.h> + /* Returns -1 = error, 0 = need more data, 1 = successful. flags and internal_date may be NULL as a result, but mailbox and msg_size are always set when successful. */ @@ -78,7 +80,7 @@ const char *custom_flags[MAIL_CUSTOM_FLAGS_COUNT]; const char *mailbox, *internal_date_str; uoff_t msg_size; - int failed; + int failed, timezone_offset; /* <mailbox> [<flags>] [<internal date>] <message literal> */ switch (validate_args(client, &mailbox, &flags_list, @@ -106,7 +108,9 @@ if (internal_date_str == NULL) { /* no time given, default to now. */ internal_date = ioloop_time; - } else if (!imap_parse_datetime(internal_date_str, &internal_date)) { + timezone_offset = ioloop_timezone.tz_minuteswest; + } else if (!imap_parse_datetime(internal_date_str, &internal_date, + &timezone_offset)) { client_send_tagline(client, "BAD Invalid internal date."); return TRUE; } @@ -126,7 +130,8 @@ o_buffer_flush(client->outbuf); /* save the mail */ - failed = !box->save(box, flags, custom_flags, internal_date, + failed = !box->save(box, flags, custom_flags, + internal_date, timezone_offset, client->inbuf, msg_size); box->close(box);
--- a/src/lib-imap/imap-date.c Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-imap/imap-date.c Thu Oct 24 03:15:38 2002 +0300 @@ -1,7 +1,8 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "gmtoff.h" +#include "utc-offset.h" +#include "utc-mktime.h" #include <ctype.h> @@ -20,7 +21,7 @@ !i_isdigit(str[3]) || !i_isdigit(str[4])) return 0; - offset = (str[1]-'0') * 1000 + (str[2]-'0') * 100 + + offset = (str[1]-'0') * 10*60 + (str[2]-'0') * 60 + (str[3]-'0') * 10 + (str[4]-'0'); return *str == '+' ? offset : -offset; } @@ -79,7 +80,7 @@ int imap_parse_date(const char *str, time_t *time) { - struct tm tm; + struct tm tm, *tml; str = imap_parse_date_internal(str, &tm); if (str == NULL) @@ -87,13 +88,18 @@ tm.tm_isdst = -1; *time = mktime(&tm); - return *time >= 0; + if (*time == (time_t)-1) + return FALSE; + + /* get it to UTC */ + tml = localtime(time); + *time -= utc_offset(tml, *time); + return TRUE; } -int imap_parse_datetime(const char *str, time_t *time) +int imap_parse_datetime(const char *str, time_t *time, int *timezone_offset) { struct tm tm; - int zone_offset; str = imap_parse_date_internal(str, &tm); if (str == NULL) @@ -122,44 +128,49 @@ str += 3; /* timezone */ - zone_offset = parse_timezone(str); + *timezone_offset = parse_timezone(str); tm.tm_isdst = -1; - *time = mktime(&tm); - if (*time < 0) + *time = utc_mktime(&tm); + if (*time == (time_t)-1) return FALSE; - *time -= zone_offset * 60; + *time -= *timezone_offset * 60; return TRUE; } +const char *imap_to_datetime_internal(struct tm *tm, int timezone_offset) +{ + int negative; + + if (timezone_offset >= 0) + negative = 0; + else { + negative = 1; + timezone_offset = -timezone_offset; + } + + return t_strdup_printf("%02d-%s-%04d %02d:%02d:%02d %c%02d%02d", + tm->tm_mday, month_names[tm->tm_mon], + tm->tm_year+1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + negative ? '-' : '+', + timezone_offset / 60, timezone_offset % 60); +} + +const char *imap_to_datetime_offset(time_t time, int timezone_offset) +{ + struct tm *tm; + + time += timezone_offset; + tm = gmtime(&time); + return imap_to_datetime_internal(tm, timezone_offset); +} + const char *imap_to_datetime(time_t time) { struct tm *tm; - int offset, negative; tm = localtime(&time); - offset = gmtoff(tm, time); - if (offset >= 0) - negative = 0; - else { - negative = 1; - offset = -offset; - } - offset /= 60; - - return t_strdup_printf("%02d-%s-%04d %02d:%02d:%02d %c%02d%02d", - tm->tm_mday, month_names[tm->tm_mon], - tm->tm_year+1900, - tm->tm_hour, tm->tm_min, tm->tm_sec, - negative ? '-' : '+', offset / 60, offset % 60); + return imap_to_datetime_internal(tm, utc_offset(tm, time)); } - -const char *imap_to_date(time_t time) -{ - struct tm *tm; - - tm = localtime(&time); - return t_strdup_printf("%d-%s-%04d", tm->tm_mday, - month_names[tm->tm_mon], tm->tm_year+1900); -}
--- a/src/lib-imap/imap-date.h Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-imap/imap-date.h Thu Oct 24 03:15:38 2002 +0300 @@ -1,10 +1,15 @@ #ifndef __IMAP_DATE_H #define __IMAP_DATE_H +/* Parses IMAP date/time string. time_t is filled with UTC date. + timezone_offset is filled with parsed timezone. If no timezone is given, + local timezone is assumed. */ int imap_parse_date(const char *str, time_t *time); -int imap_parse_datetime(const char *str, time_t *time); +int imap_parse_datetime(const char *str, time_t *time, int *timezone_offset); +/* Returns given UTC time in given timezone. */ +const char *imap_to_datetime_offset(time_t time, int timezone_offset); +/* Returns given UTC time in local timezone. */ const char *imap_to_datetime(time_t time); -const char *imap_to_date(time_t time); #endif
--- a/src/lib-index/mbox/mbox-append.c Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-index/mbox/mbox-append.c Thu Oct 24 03:15:38 2002 +0300 @@ -60,7 +60,7 @@ /* parse the From-line */ internal_date = mbox_from_parse_date((char *) data, size); - if (internal_date <= 0) + if (internal_date == (time_t)-1) internal_date = ioloop_time; i_buffer_skip(inbuf, pos+1);
--- a/src/lib-index/mbox/mbox-from.c Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-index/mbox/mbox-from.c Thu Oct 24 03:15:38 2002 +0300 @@ -26,7 +26,7 @@ /* From <sender> <date> <moreinfo> */ if (strncmp(msg, "From ", 5) != 0) - return 0; + return (time_t)-1; msg_end = msg + size; @@ -38,7 +38,7 @@ /* next 24 chars are the date in asctime() format, eg. "Thu Nov 29 22:33:52 2001" */ if (msg+24 > msg_end) - return 0; + return (time_t)-1; memset(&tm, 0, sizeof(tm)); @@ -54,43 +54,43 @@ } if (i == 12 || msg[3] != ' ') - return 0; + return (time_t)-1; msg += 4; /* day */ if (msg[0] == ' ') { if (!i_isdigit(msg[1]) || msg[2] != ' ') - return 0; + return (time_t)-1; tm.tm_mday = msg[1]-'0'; } else { if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ' ') - return 0; + return (time_t)-1; tm.tm_mday = (msg[0]-'0') * 10 + (msg[1]-'0'); } msg += 3; /* hour */ if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ':') - return 0; + return (time_t)-1; tm.tm_hour = (msg[0]-'0') * 10 + (msg[1]-'0'); msg += 3; /* minute */ if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ':') - return 0; + return (time_t)-1; tm.tm_min = (msg[0]-'0') * 10 + (msg[1]-'0'); msg += 3; /* second */ if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ' ') - return 0; + return (time_t)-1; tm.tm_sec = (msg[0]-'0') * 10 + (msg[1]-'0'); msg += 3; /* year */ if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || !i_isdigit(msg[2]) || !i_isdigit(msg[3])) - return 0; + return (time_t)-1; tm.tm_year = (msg[0]-'0') * 1000 + (msg[1]-'0') * 100 + (msg[2]-'0') * 10 + (msg[3]-'0') - 1900;
--- a/src/lib-index/mbox/mbox-index.c Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-index/mbox/mbox-index.c Thu Oct 24 03:15:38 2002 +0300 @@ -395,7 +395,7 @@ msg += startpos; i -= startpos; return mbox_from_parse_date((char *) msg, - size) != 0; + size) != (time_t)-1; } } }
--- a/src/lib-mail/rfc822-date.c Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-mail/rfc822-date.c Thu Oct 24 03:15:38 2002 +0300 @@ -1,7 +1,8 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "gmtoff.h" +#include "utc-offset.h" +#include "utc-mktime.h" #include "rfc822-date.h" #include "rfc822-tokenize.h" @@ -196,14 +197,15 @@ /* timezone */ if (tok == NULL || tok->token != 'A') return FALSE; - *timezone_offset = parse_timezone(tok->ptr, tok->len); tm.tm_isdst = -1; - *time = mktime(&tm); - if (*time < 0) + *time = utc_mktime(&tm); + if (*time == (time_t)-1) return FALSE; + *time -= *timezone_offset; + return TRUE; } @@ -213,14 +215,13 @@ int offset, negative; tm = localtime(&time); - offset = gmtoff(tm, time); + offset = utc_offset(tm, time); if (offset >= 0) negative = 0; else { negative = 1; offset = -offset; } - offset /= 60; return t_strdup_printf("%s, %02d %s %04d %02d:%02d:%02d %c%02d%02d", weekday_names[tm->tm_wday],
--- a/src/lib-mail/rfc822-date.h Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-mail/rfc822-date.h Thu Oct 24 03:15:38 2002 +0300 @@ -1,9 +1,8 @@ #ifndef __RFC822_DATE #define __RFC822_DATE -/* Parses RFC822 date/time string. time_t is filled with the date without - any timezone changes. timezone_offset is filled with the timezone's - difference to UTC in minutes. */ +/* Parses RFC822 date/time string. timezone_offset is filled with the + timezone's difference to UTC in minutes. */ int rfc822_parse_date(const char *str, time_t *time, int *timezone_offset); /* Create RFC822 date/time string from given time in local timezone. */
--- a/src/lib-storage/index/index-copy.c Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-storage/index/index-copy.c Thu Oct 24 03:15:38 2002 +0300 @@ -27,7 +27,7 @@ /* save it in destination mailbox */ failed = !ctx->dest->save(ctx->dest, rec->msg_flags, - ctx->custom_flags, rec->internal_date, + ctx->custom_flags, rec->internal_date, 0, inbuf, inbuf->v_size); i_buffer_unref(inbuf);
--- a/src/lib-storage/index/maildir/maildir-save.c Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-storage/index/maildir/maildir-save.c Thu Oct 24 03:15:38 2002 +0300 @@ -78,6 +78,7 @@ int maildir_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[], time_t internal_date, + int timezone_offset __attr_unused__, IBuffer *data, uoff_t data_size) { IndexMailbox *ibox = (IndexMailbox *) box; @@ -110,7 +111,11 @@ /* set the internal_date by modifying mtime */ buf.actime = ioloop_time; buf.modtime = internal_date; - (void)utime(tmp_path, &buf); + if (utime(tmp_path, &buf) < 0) { + /* just warn, don't bother actually failing */ + mail_storage_set_critical(box->storage, "utime() failed for " + "%s: %m", tmp_path); + } /* move the file into new/ directory - syncing will pick it up from there */
--- a/src/lib-storage/index/maildir/maildir-storage.h Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-storage/index/maildir/maildir-storage.h Thu Oct 24 03:15:38 2002 +0300 @@ -6,7 +6,8 @@ int maildir_storage_copy(Mailbox *box, Mailbox *destbox, const char *messageset, int uidset); int maildir_storage_save(Mailbox *box, MailFlags flags, - const char *custom_flags[], time_t internal_date, + const char *custom_flags[], + time_t internal_date, int timezone_offset, IBuffer *data, uoff_t data_size); int maildir_find_mailboxes(MailStorage *storage, const char *mask,
--- a/src/lib-storage/index/mbox/mbox-save.c Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-storage/index/mbox/mbox-save.c Thu Oct 24 03:15:38 2002 +0300 @@ -87,6 +87,7 @@ sender = t_strconcat(storage->user, "@", my_hostdomain, NULL); + /* save in local timezone, no matter what it was given with */ line = mbox_from_create(sender, internal_date); len = strlen(line); @@ -148,7 +149,8 @@ } int mbox_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[], - time_t internal_date, IBuffer *data, uoff_t data_size) + time_t internal_date, int timezone_offset __attr_unused__, + IBuffer *data, uoff_t data_size) { IndexMailbox *ibox = (IndexMailbox *) box; MailFlags real_flags;
--- a/src/lib-storage/index/mbox/mbox-storage.h Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-storage/index/mbox/mbox-storage.h Thu Oct 24 03:15:38 2002 +0300 @@ -6,7 +6,8 @@ int mbox_storage_copy(Mailbox *box, Mailbox *destbox, const char *messageset, int uidset); int mbox_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[], - time_t internal_date, IBuffer *data, uoff_t data_size); + time_t internal_date, int timezone_offset, + IBuffer *data, uoff_t data_size); int mbox_find_mailboxes(MailStorage *storage, const char *mask, MailboxFunc func, void *context);
--- a/src/lib-storage/mail-storage.h Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib-storage/mail-storage.h Thu Oct 24 03:15:38 2002 +0300 @@ -158,9 +158,12 @@ int (*search)(Mailbox *box, MailSearchArg *args, OBuffer *outbuf, int uid_result); - /* Save a new mail into mailbox. */ + /* Save a new mail into mailbox. timezone_offset specifies the + timezone in minutes which internal_date was originally given + with. */ int (*save)(Mailbox *box, MailFlags flags, const char *custom_flags[], - time_t internal_date, IBuffer *data, uoff_t data_size); + time_t internal_date, int timezone_offset, + IBuffer *data, uoff_t data_size); /* Returns TRUE if mailbox is now in inconsistent state, meaning that the message IDs etc. may have changed - only way to recover this
--- a/src/lib/Makefile.am Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib/Makefile.am Thu Oct 24 03:15:38 2002 +0300 @@ -18,7 +18,6 @@ fdpass.c \ file-lock.c \ file-set-size.c \ - gmtoff.c \ hash.c \ hex-binary.c \ hostpid.c \ @@ -50,6 +49,8 @@ temp-string.c \ unlink-directory.c \ unlink-lockfiles.c \ + utc-offset.c \ + utc-mktime.c \ write-full.c noinst_HEADERS = \ @@ -60,7 +61,6 @@ fdpass.h \ file-lock.h \ file-set-size.h \ - gmtoff.h \ hash.h \ hex-binary.h \ hostpid.h \ @@ -87,6 +87,8 @@ temp-string.h \ unlink-directory.h \ unlink-lockfiles.h \ + utc-offset.h \ + utc-mktime.h \ write-full.h EXTRA_DIST = \
--- a/src/lib/gmtoff.c Thu Oct 24 00:07:37 2002 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - compat.c : Compatibility functions for OSes not having them - - Copyright (c) 2002 Timo Sirainen - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "lib.h" -#include "gmtoff.h" - -#include <time.h> - -#undef HAVE_TM_GMTOFF - -int gmtoff(struct tm *tm, time_t t __attr_unused__) -{ -#ifdef HAVE_TM_GMTOFF - return tm->tm_gmtoff; -#else - struct tm ltm, gtm; - int offset; - - /* gmtime() overwrites tm, so we need to copy it elsewhere */ - ltm = *tm; - tm = gmtime(&t); - gtm = *tm; - - /* max offset of 24 hours */ - if (ltm.tm_yday < gtm.tm_yday) - offset = -24 * 3600; - else if (ltm.tm_yday > gtm.tm_yday) - offset = 24 * 3600; - else - offset = 0; - - offset += (ltm.tm_hour - gtm.tm_hour) * 3600; - offset += (ltm.tm_min - gtm.tm_min) * 60; - - /* restore overwritten tm */ - *tm = ltm; - return offset; -#endif -}
--- a/src/lib/gmtoff.h Thu Oct 24 00:07:37 2002 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#ifndef __GMTOFF_H -#define __GMTOFF_H - -#include <time.h> - -/* Returns GMT offset in seconds. */ -int gmtoff(struct tm *tm, time_t t); - -#endif
--- a/src/lib/ioloop.c Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib/ioloop.c Thu Oct 24 03:15:38 2002 +0300 @@ -37,6 +37,7 @@ time_t ioloop_time = 0; struct timeval ioloop_timeval; +struct timezone ioloop_timezone; static IOLoop current_ioloop = NULL; @@ -253,7 +254,7 @@ struct timeval tv; int t_id; - gettimeofday(&ioloop_timeval, NULL); + gettimeofday(&ioloop_timeval, &ioloop_timezone); ioloop_time = ioloop_timeval.tv_sec; if (ioloop->timeouts == NULL || !ioloop->timeouts->run_now) @@ -306,7 +307,7 @@ IOLoop ioloop; /* initialize time */ - gettimeofday(&ioloop_timeval, NULL); + gettimeofday(&ioloop_timeval, &ioloop_timezone); ioloop_time = ioloop_timeval.tv_sec; ioloop = p_new(pool, struct _IOLoop, 1);
--- a/src/lib/ioloop.h Thu Oct 24 00:07:37 2002 +0300 +++ b/src/lib/ioloop.h Thu Oct 24 03:15:38 2002 +0300 @@ -17,6 +17,7 @@ Can be used instead of time(NULL). */ extern time_t ioloop_time; extern struct timeval ioloop_timeval; +extern struct timezone ioloop_timezone; /* I/O listeners - you can create different handlers for IO_READ and IO_WRITE, but make sure you don't create multiple handlers of same type, it's not
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/utc-mktime.c Thu Oct 24 03:15:38 2002 +0300 @@ -0,0 +1,145 @@ +/* mkgmtime.c - make time corresponding to a GMT timeval struct + $Id$ + + * 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@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). +*/ + +#include "utc-mktime.h" + +static int tmcomp(register const struct tm * const atmp, + register const struct tm * const btmp) +{ + register int result; + + 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; +} + +time_t utc_mktime(struct tm *tm) +{ + register int dir; + register int bits; + register int saved_seconds; + time_t t; + struct tm yourtm, *mytm; + + 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). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** 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; + } + t += saved_seconds; + return t; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/utc-mktime.h Thu Oct 24 03:15:38 2002 +0300 @@ -0,0 +1,10 @@ +#ifndef __UTC_MKTIME_H +#define __UTC_MKTIME_H + +#include <time.h> + +/* 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); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/utc-offset.c Thu Oct 24 03:15:38 2002 +0300 @@ -0,0 +1,59 @@ +/* + compat.c : Compatibility functions for OSes not having them + + Copyright (c) 2002 Timo Sirainen + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "lib.h" +#include "utc-offset.h" + +#include <sys/time.h> + +int utc_offset(struct tm *tm, time_t t __attr_unused__) +{ +#ifdef HAVE_TM_GMTOFF + return (int) (tm->tm_gmtoff/60); +#else + struct tm ltm, gtm; + int offset; + + /* gmtime() overwrites tm, so we need to copy it elsewhere */ + ltm = *tm; + tm = gmtime(&t); + gtm = *tm; + + /* max offset of 24 hours */ + if (ltm.tm_yday < gtm.tm_yday) + offset = -24 * 60; + else if (ltm.tm_yday > gtm.tm_yday) + offset = 24 * 60; + else + offset = 0; + + offset += (ltm.tm_hour - gtm.tm_hour) * 60; + offset += (ltm.tm_min - gtm.tm_min); + + /* restore overwritten tm */ + *tm = ltm; + return offset; +#endif +}