⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tzfile.c

📁 Linux下头文件time.h的实现源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 1991-1993,1995-2001,2003,2004,2006, 2007   Free Software Foundation, Inc.   This file is part of the GNU C Library.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307 USA.  */#include <assert.h>#include <limits.h>#include <stdio.h>#include <stdio_ext.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <sys/stat.h>#define	NOID#include <timezone/tzfile.h>int __use_tzfile;static dev_t tzfile_dev;static ino64_t tzfile_ino;static time_t tzfile_mtime;struct ttinfo  {    long int offset;		/* Seconds east of GMT.  */    unsigned char isdst;	/* Used to set tm_isdst.  */    unsigned char idx;		/* Index into `zone_names'.  */    unsigned char isstd;	/* Transition times are in standard time.  */    unsigned char isgmt;	/* Transition times are in GMT.  */  };struct leap  {    time_t transition;		/* Time the transition takes effect.  */    long int change;		/* Seconds of correction to apply.  */  };static void compute_tzname_max (size_t) internal_function;static size_t num_transitions;libc_freeres_ptr (static time_t *transitions);static unsigned char *type_idxs;static size_t num_types;static struct ttinfo *types;static char *zone_names;static long int rule_stdoff;static long int rule_dstoff;static size_t num_leaps;static struct leap *leaps;static char *tzspec;#include <endian.h>#include <byteswap.h>/* Decode the four bytes at PTR as a signed integer in network byte order.  */static inline int__attribute ((always_inline))decode (const void *ptr){  if (BYTE_ORDER == BIG_ENDIAN && sizeof (int) == 4)    return *(const int *) ptr;  if (sizeof (int) == 4)    return bswap_32 (*(const int *) ptr);  const unsigned char *p = ptr;  int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;  result = (result << 8) | *p++;  result = (result << 8) | *p++;  result = (result << 8) | *p++;  result = (result << 8) | *p++;  return result;}static inline int64_t__attribute ((always_inline))decode64 (const void *ptr){  if ((BYTE_ORDER == BIG_ENDIAN))    return *(const int64_t *) ptr;  return bswap_64 (*(const int64_t *) ptr);}void__tzfile_read (const char *file, size_t extra, char **extrap){  static const char default_tzdir[] = TZDIR;  size_t num_isstd, num_isgmt;  register FILE *f;  struct tzhead tzhead;  size_t chars;  register size_t i;  size_t total_size;  size_t types_idx;  size_t leaps_idx;  int was_using_tzfile = __use_tzfile;  int trans_width = 4;  size_t tzspec_len;  if (sizeof (time_t) != 4 && sizeof (time_t) != 8)    abort ();  __use_tzfile = 0;  if (file == NULL)    /* No user specification; use the site-wide default.  */    file = TZDEFAULT;  else if (*file == '\0')    /* User specified the empty string; use UTC with no leap seconds.  */    goto ret_free_transitions;  else    {      /* We must not allow to read an arbitrary file in a setuid	 program.  So we fail for any file which is not in the	 directory hierachy starting at TZDIR	 and which is not the system wide default TZDEFAULT.  */      if (__libc_enable_secure	  && ((*file == '/'	       && memcmp (file, TZDEFAULT, sizeof TZDEFAULT)	       && memcmp (file, default_tzdir, sizeof (default_tzdir) - 1))	      || strstr (file, "../") != NULL))	/* This test is certainly a bit too restrictive but it should	   catch all critical cases.  */	goto ret_free_transitions;    }  if (*file != '/')    {      const char *tzdir;      unsigned int len, tzdir_len;      char *new, *tmp;      tzdir = getenv ("TZDIR");      if (tzdir == NULL || *tzdir == '\0')	{	  tzdir = default_tzdir;	  tzdir_len = sizeof (default_tzdir) - 1;	}      else	tzdir_len = strlen (tzdir);      len = strlen (file) + 1;      new = (char *) __alloca (tzdir_len + 1 + len);      tmp = __mempcpy (new, tzdir, tzdir_len);      *tmp++ = '/';      memcpy (tmp, file, len);      file = new;    }  /* If we were already using tzfile, check whether the file changed.  */  struct stat64 st;  if (was_using_tzfile      && stat64 (file, &st) == 0      && tzfile_ino == st.st_ino && tzfile_dev == st.st_dev      && tzfile_mtime == st.st_mtime)    {      /* Nothing to do.  */      __use_tzfile = 1;      return;    }  /* Note the file is opened with cancellation in the I/O functions     disabled.  */  f = fopen (file, "rc");  if (f == NULL)    goto ret_free_transitions;  /* Get information about the file we are actually using.  */  if (fstat64 (fileno (f), &st) != 0)    {      fclose (f);      goto ret_free_transitions;    }  free ((void *) transitions);  transitions = NULL;  /* Remember the inode and device number and modification time.  */  tzfile_dev = st.st_dev;  tzfile_ino = st.st_ino;  tzfile_mtime = st.st_mtime;  /* No threads reading this stream.  */  __fsetlocking (f, FSETLOCKING_BYCALLER); read_again:  if (__builtin_expect (fread_unlocked ((void *) &tzhead, sizeof (tzhead),					1, f) != 1, 0)      || memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0)    goto lose;  num_transitions = (size_t) decode (tzhead.tzh_timecnt);  num_types = (size_t) decode (tzhead.tzh_typecnt);  chars = (size_t) decode (tzhead.tzh_charcnt);  num_leaps = (size_t) decode (tzhead.tzh_leapcnt);  num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);  num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);  /* For platforms with 64-bit time_t we use the new format if available.  */  if (sizeof (time_t) == 8 && trans_width == 4      && tzhead.tzh_version[0] != '\0')    {      /* We use the 8-byte format.  */      trans_width = 8;      /* Position the stream before the second header.  */      size_t to_skip = (num_transitions * (4 + 1)			+ num_types * 6			+ chars			+ num_leaps * 8			+ num_isstd			+ num_isgmt);      if (fseek (f, to_skip, SEEK_CUR) != 0)	goto lose;      goto read_again;    }  total_size = num_transitions * (sizeof (time_t) + 1);  total_size = ((total_size + __alignof__ (struct ttinfo) - 1)		& ~(__alignof__ (struct ttinfo) - 1));  types_idx = total_size;  total_size += num_types * sizeof (struct ttinfo) + chars;  total_size = ((total_size + __alignof__ (struct leap) - 1)		& ~(__alignof__ (struct leap) - 1));  leaps_idx = total_size;  total_size += num_leaps * sizeof (struct leap);  tzspec_len = (sizeof (time_t) == 8 && trans_width == 8		? st.st_size - (ftello (f)				+ num_transitions * (8 + 1)				+ num_types * 6				+ chars				+ num_leaps * 8				+ num_isstd				+ num_isgmt) - 1 : 0);  /* Allocate enough memory including the extra block requested by the     caller.  */  transitions = (time_t *) malloc (total_size + tzspec_len + extra);  if (transitions == NULL)    goto lose;  type_idxs = (unsigned char *) transitions + (num_transitions					       * sizeof (time_t));  types = (struct ttinfo *) ((char *) transitions + types_idx);  zone_names = (char *) types + num_types * sizeof (struct ttinfo);  leaps = (struct leap *) ((char *) transitions + leaps_idx);  if (sizeof (time_t) == 8 && trans_width == 8)    tzspec = (char *) leaps + num_leaps * sizeof (struct leap) + extra;  else    tzspec = NULL;  if (extra > 0)    *extrap = (char *) &leaps[num_leaps];  if (sizeof (time_t) == 4 || __builtin_expect (trans_width == 8, 1))    {      if (__builtin_expect (fread_unlocked (transitions, trans_width + 1,					    num_transitions, f)			    != num_transitions, 0))	goto lose;    }  else    {      if (__builtin_expect (fread_unlocked (transitions, 4, num_transitions, f)			    != num_transitions, 0)	  || __builtin_expect (fread_unlocked (type_idxs, 1, num_transitions,					       f) != num_transitions, 0))	goto lose;    }  /* Check for bogus indices in the data file, so we can hereafter     safely use type_idxs[T] as indices into `types' and never crash.  */  for (i = 0; i < num_transitions; ++i)    if (__builtin_expect (type_idxs[i] >= num_types, 0))      goto lose;  if ((BYTE_ORDER != BIG_ENDIAN && (sizeof (time_t) == 4 || trans_width == 4))      || (BYTE_ORDER == BIG_ENDIAN && sizeof (time_t) == 8	  && trans_width == 4))    {      /* Decode the transition times, stored as 4-byte integers in	 network (big-endian) byte order.  We work from the end of	 the array so as not to clobber the next element to be	 processed when sizeof (time_t) > 4.  */      i = num_transitions;      while (i-- > 0)	transitions[i] = decode ((char *) transitions + i * 4);    }  else if (BYTE_ORDER != BIG_ENDIAN && sizeof (time_t) == 8)    {      /* Decode the transition times, stored as 8-byte integers in	 network (big-endian) byte order.  */      for (i = 0; i < num_transitions; ++i)	transitions[i] = decode64 ((char *) transitions + i * 8);    }  for (i = 0; i < num_types; ++i)    {      unsigned char x[4];      int c;      if (__builtin_expect (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x),			    0))	goto lose;      c = getc_unlocked (f);      if (__builtin_expect ((unsigned int) c > 1u, 0))	goto lose;      types[i].isdst = c;      c = getc_unlocked (f);      if (__builtin_expect ((size_t) c > chars, 0))	/* Bogus index in data file.  */	goto lose;      types[i].idx = c;      types[i].offset = (long int) decode (x);    }  if (__builtin_expect (fread_unlocked (zone_names, 1, chars, f) != chars, 0))    goto lose;  for (i = 0; i < num_leaps; ++i)    {      unsigned char x[8];      if (__builtin_expect (fread_unlocked (x, 1, trans_width, f)			    != trans_width, 0))	goto lose;      if (sizeof (time_t) == 4 || trans_width == 4)	leaps[i].transition = (time_t) decode (x);      else	leaps[i].transition = (time_t) decode64 (x);      if (__builtin_expect (fread_unlocked (x, 1, 4, f) != 4, 0))	goto lose;      leaps[i].change = (long int) decode (x);    }  for (i = 0; i < num_isstd; ++i)    {      int c = getc_unlocked (f);      if (__builtin_expect (c == EOF, 0))	goto lose;      types[i].isstd = c != 0;    }  while (i < num_types)    types[i++].isstd = 0;  for (i = 0; i < num_isgmt; ++i)    {      int c = getc_unlocked (f);      if (__builtin_expect (c == EOF, 0))	goto lose;      types[i].isgmt = c != 0;    }  while (i < num_types)    types[i++].isgmt = 0;  /* Read the POSIX TZ-style information if possible.  */  if (sizeof (time_t) == 8 && tzspec != NULL)    {      /* Skip over the newline first.  */      if (getc_unlocked (f) != '\n'	  || (fread_unlocked (tzspec, 1, tzspec_len - 1, f)	      != tzspec_len - 1))	tzspec = NULL;      else	tzspec[tzspec_len - 1] = '\0';    }  else if (sizeof (time_t) == 4 && tzhead.tzh_version != '\0')    {      /* Get the TZ string.  */      if (__builtin_expect (fread_unlocked ((void *) &tzhead, sizeof (tzhead),					    1, f) != 1, 0)	  || (memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic))	      != 0))	goto lose;      size_t num_transitions2 = (size_t) decode (tzhead.tzh_timecnt);      size_t num_types2 = (size_t) decode (tzhead.tzh_typecnt);      size_t chars2 = (size_t) decode (tzhead.tzh_charcnt);      size_t num_leaps2 = (size_t) decode (tzhead.tzh_leapcnt);      size_t num_isstd2 = (size_t) decode (tzhead.tzh_ttisstdcnt);      size_t num_isgmt2 = (size_t) decode (tzhead.tzh_ttisgmtcnt);      /* Position the stream before the second header.  */      size_t to_skip = (num_transitions2 * (8 + 1)			+ num_types2 * 6			+ chars2			+ num_leaps2 * 12			+ num_isstd2

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -