4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Time Zone processing.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials are licensed and made available under
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the terms and conditions of the BSD License that accompanies this distribution.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Portions derived from the NIH time zone package file, localtime.c,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which contains the following notice:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This file is in the public domain, so clarified as of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetBSD: localtime.c,v 1.39 2006/03/22 14:01:30 christos Exp
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <LibConfig.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <ctype.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <fcntl.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <stdio.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <stdlib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <string.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <time.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <unistd.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "tzfile.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "TimeVals.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef WILDABBR
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Someone might make incorrect use of a time zone abbreviation:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** 1. They might reference tzname[0] before calling tzset (explicitly
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** or implicitly).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** 2. They might reference tzname[1] before calling tzset (explicitly
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** or implicitly).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** 3. They might reference tzname[1] after setting to a time zone
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** in which Daylight Saving Time is never observed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** 4. They might reference tzname[0] after setting to a time zone
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** in which Standard Time is never observed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** 5. They might reference tm.TM_ZONE after calling offtime.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** What's best to do in the above cases is open to debate;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** for now, we just set things up so that in any of the five cases
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** WILDABBR is used. Another possibility: initialize tzname[0] to the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** string "tzname[0] used before set", and similarly for the other cases.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** And another: initialize tzname[0] to "ERA", with an explanation in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** manual page of what this "time zone abbreviation" means (doing this so
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** that tzname[0] has the "normal" length of three characters).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define WILDABBR " "
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif /* !defined WILDABBR */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncconst char wildabbr[9] = "WILDABBR";
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncconst char gmt[4] = "GMT";
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstruct state * lclptr = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstruct state * gmtptr = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef TZ_STRLEN_MAX
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define TZ_STRLEN_MAX 255
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif /* !defined TZ_STRLEN_MAX */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic char lcl_TZname[TZ_STRLEN_MAX + 1];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int lcl_is_set = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//static int gmt_is_set = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncchar * tzname[2] = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (char *)__UNCONST(wildabbr),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (char *)__UNCONST(wildabbr)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynclong int timezone = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncint daylight = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef NO_ZONEINFO_FILES
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** Get first 4 characters of codep as a 32-bit integer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The first character of codep becomes the MSB of the resultant integer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic INT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncdetzcode(const char * const codep)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register INT32 result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** The first character must be sign extended on systems with >32bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** longs. This was solved differently in the master tzcode sources
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** (the fix first appeared in tzcode95c.tar.gz). But I believe
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** that this implementation is superior.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define SIGN_EXTEND_CHAR(x) ((signed char) x)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync result = (SIGN_EXTEND_CHAR(codep[0]) << 24) \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync | (codep[1] & 0xff) << 16 \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync | (codep[2] & 0xff) << 8
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync | (codep[3] & 0xff);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif /* NO_ZONEINFO_FILES */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncsettzname (void)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register struct state * const sp = lclptr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync tzname[0] = (char *)__UNCONST(wildabbr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync tzname[1] = (char *)__UNCONST(wildabbr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync daylight = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync timezone = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (sp == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync tzname[0] = tzname[1] = (char *)__UNCONST(gmt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->typecnt; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const struct ttinfo * const ttisp = &sp->ttis[i];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync tzname[ttisp->tt_isdst] =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &sp->chars[ttisp->tt_abbrind];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ttisp->tt_isdst)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync daylight = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (i == 0 || !ttisp->tt_isdst)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync timezone = -(ttisp->tt_gmtoff);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** And to get the latest zone names into tzname. . .
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->timecnt; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const struct ttinfo * const ttisp =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &sp->ttis[ sp->types[i] ];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync tzname[ttisp->tt_isdst] =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &sp->chars[ttisp->tt_abbrind];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a pointer into a time zone string, scan until a character that is not
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** a valid character in a zone name is found. Return a pointer to that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** character.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncgetzname(register const char *strp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register char c;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync c != '+')
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a pointer into a time zone string, extract a number from that string.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Check that the number is within a specified range; if it is not, return
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Otherwise, return a pointer to the first character not part of the number.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncgetnum(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const char *strp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int * const nump,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const int min,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const int max
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register char c;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int num;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (strp == NULL || !is_digit(c = *strp))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync num = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync num = num * 10 + (c - '0');
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (num > max)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL; /* illegal value */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync c = *++strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (is_digit(c));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (num < min)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL; /* illegal value */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *nump = num;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a pointer into a time zone string, extract a number of seconds,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** in hh[:mm[:ss]] form, from the string.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** If any error occurs, return NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Otherwise, return a pointer to the first character not part of the number
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** of seconds.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncgetsecs(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const char *strp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LONG32 * const secsp
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int num;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** "M10.4.6/26", which does not conform to Posix,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** but which specifies the equivalent of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** ``02:00 on the first Sunday on or after 23 Oct''.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (strp == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *secsp = (long)(num * SECSPERHOUR);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*strp == ':') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (strp == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *secsp += num * SECSPERMIN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*strp == ':') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* `SECSPERMIN' allows for leap seconds. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &num, 0, SECSPERMIN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (strp == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *secsp += num;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a pointer into a time zone string, extract an offset, in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** [+-]hh[:mm[:ss]] form, from the string.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** If any error occurs, return NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Otherwise, return a pointer to the first character not part of the time.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncgetoffset(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const char *strp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LONG32 * const offsetp
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int neg = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*strp == '-') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync neg = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (*strp == '+')
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getsecs(strp, offsetp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (strp == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL; /* illegal time */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (neg)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *offsetp = -*offsetp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a pointer into a time zone string, extract a rule in the form
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** date[/time]. See POSIX section 8 for the format of "date" and "time".
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** If a valid rule is not found, return NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Otherwise, return a pointer to the first character not part of the rule.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncgetrule(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *strp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register struct rule * const rulep
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*strp == 'J') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Julian day.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rulep->r_type = JULIAN_DAY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (*strp == 'M') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Month, week, day.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (strp == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*strp++ != '.')
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &rulep->r_week, 1, 5);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (strp == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*strp++ != '.')
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (is_digit(*strp)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Day of year.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rulep->r_type = DAY_OF_YEAR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else return NULL; /* invalid format */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (strp == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*strp == '/') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Time specified.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getsecs(strp, &rulep->r_time);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return strp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctzload(register const char *name, register struct state * const sp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifndef NO_ZONEINFO_FILES
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const char * p;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int fid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (name == NULL && (name = TZDEFAULT) == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int doaccess;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Section 4.9.1 of the C standard says that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** "FILENAME_MAX expands to an integral constant expression
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** that is the size needed for an array of char large enough
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** to hold the longest file name string that the implementation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** guarantees can be opened."
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync char fullname[FILENAME_MAX + 1];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (name[0] == ':')
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync doaccess = name[0] == '/';
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!doaccess) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((p = TZDIR) == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void) strcpy(fullname, p); /* XXX strcpy is safe */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void) strcat(fullname, "/"); /* XXX strcat is safe */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void) strcat(fullname, name); /* XXX strcat is safe */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Set doaccess if '.' (as in "../") shows up in name.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (strchr(name, '.') != NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync doaccess = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name = fullname;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (doaccess && access(name, R_OK) != 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * XXX potential security problem here if user of a set-id
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * program has set TZ (which is passed in as name) here,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * and uses a race condition trick to defeat the access(2)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * above.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((fid = open(name, OPEN_MODE)) == -1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct tzhead * tzhp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync union {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct tzhead tzhead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync char buf[sizeof *sp + sizeof *tzhp];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } u;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int ttisstdcnt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int ttisgmtcnt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync i = read(fid, u.buf, sizeof u.buf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (close(fid) != 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->timecnt + /* types */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->typecnt * (4 + 2) + /* ttinfos */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->charcnt + /* chars */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->leapcnt * (4 + 4) + /* lsinfos */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisstdcnt + /* ttisstds */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisgmtcnt) /* ttisgmts */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->timecnt; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ats[i] = detzcode(p);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync p += 4;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->timecnt; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->types[i] = (unsigned char) *p++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (sp->types[i] >= sp->typecnt)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->typecnt; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register struct ttinfo * ttisp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp = &sp->ttis[i];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp->tt_gmtoff = detzcode(p);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync p += 4;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp->tt_isdst = (unsigned char) *p++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp->tt_abbrind = (unsigned char) *p++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ttisp->tt_abbrind < 0 ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp->tt_abbrind > sp->charcnt)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->charcnt; ++i)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->chars[i] = *p++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->chars[i] = '\0'; /* ensure '\0' at end */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->leapcnt; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register struct lsinfo * lsisp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lsisp = &sp->lsis[i];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lsisp->ls_trans = detzcode(p);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync p += 4;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lsisp->ls_corr = detzcode(p);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync p += 4;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->typecnt; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register struct ttinfo * ttisp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp = &sp->ttis[i];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ttisstdcnt == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp->tt_ttisstd = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp->tt_ttisstd = *p++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ttisp->tt_ttisstd != TRUE &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp->tt_ttisstd != FALSE)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->typecnt; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register struct ttinfo * ttisp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp = &sp->ttis[i];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ttisgmtcnt == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp->tt_ttisgmt = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp->tt_ttisgmt = *p++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ttisp->tt_ttisgmt != TRUE &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisp->tt_ttisgmt != FALSE)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else /* ! NO_ZONEINFO_FILES */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** year, a rule, and the offset from UTC at the time that rule takes effect,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** calculate the Epoch-relative time that rule takes effect.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctime_t
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctranstime(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const time_t janfirst,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const int year,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const struct rule * const rulep,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const LONG32 offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int leapyear;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register time_t value;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int d, m1, yy0, yy1, yy2, dow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INITIALIZE(value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync leapyear = isleap(year);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (rulep->r_type) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case JULIAN_DAY:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** years.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** In non-leap years, or if the day number is 59 or less, just
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** add SECSPERDAY times the day number-1 to the time of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** January 1, midnight, to get the day.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (leapyear && rulep->r_day >= 60)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync value += SECSPERDAY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DAY_OF_YEAR:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** n - day of year.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Just add SECSPERDAY times the day number to the time of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** January 1, midnight, to get the day.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync value = janfirst + rulep->r_day * SECSPERDAY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case MONTH_NTH_DAY_OF_WEEK:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Mm.n.d - nth "dth day" of month m.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync value = janfirst;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < rulep->r_mon - 1; ++i)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync value += mon_lengths[leapyear][i] * SECSPERDAY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Use Zeller's Congruence to get day-of-week of first day of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** month.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync m1 = (rulep->r_mon + 9) % 12 + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync yy1 = yy0 / 100;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync yy2 = yy0 % 100;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dow = ((26 * m1 - 2) / 10 +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (dow < 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dow += DAYSPERWEEK;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** "dow" is the day-of-week of the first day of the month. Get
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** the day-of-month (zero-origin) of the first "dow" day of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** month.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync d = rulep->r_day - dow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (d < 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync d += DAYSPERWEEK;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 1; i < rulep->r_week; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (d + DAYSPERWEEK >=
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mon_lengths[leapyear][rulep->r_mon - 1])
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync d += DAYSPERWEEK;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** "d" is the day-of-month (zero-origin) of the day we want.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync value += d * SECSPERDAY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** question. To get the Epoch-relative time of the specified local
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** time on that day, add the transition time and the current offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** from UTC.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return value + rulep->r_time + offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a POSIX section 8-style TZ string, fill in the rule tables as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** appropriate.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctzparse(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char * name,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct state * const sp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const int lastditch
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *stdname;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *dstname;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync size_t stdlen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync size_t dstlen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LONG32 stdoffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LONG32 dstoffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync time_t *atp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync unsigned char *typep;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync char *cp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int load_result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dstname = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync stdname = name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (lastditch) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync stdlen = strlen(name); /* length of standard zone name */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name += stdlen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (stdlen >= sizeof sp->chars)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync stdlen = (sizeof sp->chars) - 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync stdoffset = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name = getzname(name);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync stdlen = name - stdname;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (stdlen < 3)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*name == '\0')
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name = getoffset(name, &stdoffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (name == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync load_result = tzload(TZDEFRULES, sp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (load_result != 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->leapcnt = 0; /* so, we're off a little */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*name != '\0') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dstname = name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name = getzname(name);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dstlen = name - dstname; /* length of DST zone name */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (dstlen < 3)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*name != '\0' && *name != ',' && *name != ';') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name = getoffset(name, &dstoffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (name == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else dstoffset = stdoffset - SECSPERHOUR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*name == '\0' && load_result != 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name = TZDEFRULESTRING;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*name == ',' || *name == ';') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct rule start;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct rule end;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int year;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register time_t janfirst;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync time_t starttime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync time_t endtime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((name = getrule(name, &start)) == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*name++ != ',')
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((name = getrule(name, &end)) == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*name != '\0')
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->typecnt = 2; /* standard time and DST */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Two transitions per year, from EPOCH_YEAR to 2037.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (sp->timecnt > TZ_MAX_TIMES)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[0].tt_gmtoff = -dstoffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[0].tt_isdst = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[0].tt_abbrind = (int)stdlen + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[1].tt_gmtoff = -stdoffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[1].tt_isdst = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[1].tt_abbrind = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync atp = sp->ats;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync typep = sp->types;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync janfirst = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (year = EPOCH_YEAR; year <= 2037; ++year) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync starttime = transtime(janfirst, year, &start,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync stdoffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync endtime = transtime(janfirst, year, &end,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dstoffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (starttime > endtime) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *atp++ = endtime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *typep++ = 1; /* DST ends */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *atp++ = starttime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *typep++ = 0; /* DST begins */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *atp++ = starttime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *typep++ = 0; /* DST begins */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *atp++ = endtime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *typep++ = 1; /* DST ends */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync janfirst += year_lengths[isleap(year)] *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SECSPERDAY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register LONG32 theirstdoffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register LONG32 theiroffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int j;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*name != '\0')
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Initial values of theirstdoffset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync theirstdoffset = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->timecnt; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync j = sp->types[i];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!sp->ttis[j].tt_isdst) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync theirstdoffset =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync -sp->ttis[j].tt_gmtoff;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Initially we're assumed to be in standard time.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync theiroffset = theirstdoffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Now juggle transition times and types
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** tracking offsets as you do.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < sp->timecnt; ++i) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync j = sp->types[i];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->types[i] = (unsigned char)sp->ttis[j].tt_isdst;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (sp->ttis[j].tt_ttisgmt) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* No adjustment to transition time */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** If summer time is in effect, and the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** transition time was not specified as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** standard time, add the summer time
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** offset to the transition time;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** otherwise, add the standard time
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** offset to the transition time.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Transitions from DST to DDST
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** will effectively disappear since
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** POSIX provides for only one DST
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** offset.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ats[i] += stdoffset -
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync theirstdoffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync theiroffset = -sp->ttis[j].tt_gmtoff;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!sp->ttis[j].tt_isdst)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync theirstdoffset = theiroffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Finally, fill in ttis.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** ttisstd and ttisgmt need not be handled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[0].tt_gmtoff = -stdoffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[0].tt_isdst = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[0].tt_abbrind = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[1].tt_gmtoff = -dstoffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[1].tt_isdst = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[1].tt_abbrind = (int)stdlen + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->typecnt = 2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dstlen = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->typecnt = 1; /* only standard time */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->timecnt = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[0].tt_gmtoff = -stdoffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[0].tt_isdst = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->ttis[0].tt_abbrind = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->charcnt = (int)stdlen + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (dstlen != 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->charcnt += (int)dstlen + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((size_t) sp->charcnt > sizeof sp->chars)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cp = sp->chars;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void) strncpy(cp, stdname, stdlen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cp += stdlen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *cp++ = '\0';
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (dstlen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void) strncpy(cp, dstname, dstlen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(cp + dstlen) = '\0';
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncvoid
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncgmtload(struct state * const sp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (tzload(gmt, sp) != 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void) tzparse(gmt, sp, TRUE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctzsetwall(void)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (lcl_is_set < 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lcl_is_set = -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (lclptr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lclptr = (struct state *) malloc(sizeof *lclptr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (lclptr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync settzname(); /* all we can do */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (tzload((char *) NULL, lclptr) != 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gmtload(lclptr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync settzname();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncvoid
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctzset(void)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const char * name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name = getenv("TZ");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (name == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync tzsetwall();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lcl_is_set = strlen(name) < sizeof lcl_TZname;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (lcl_is_set)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void)strncpyX(lcl_TZname, name, sizeof(lcl_TZname));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (lclptr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lclptr = (struct state *) malloc(sizeof *lclptr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (lclptr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync settzname(); /* all we can do */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*name == '\0') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** User wants it fast rather than right.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lclptr->leapcnt = 0; /* so, we're off a little */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lclptr->timecnt = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lclptr->typecnt = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lclptr->ttis[0].tt_isdst = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lclptr->ttis[0].tt_gmtoff = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lclptr->ttis[0].tt_abbrind = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void)strncpyX(lclptr->chars, gmt, sizeof(lclptr->chars));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (tzload(name, lclptr) != 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void) gmtload(lclptr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync settzname();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}