root/ext/fileinfo/libmagic/cdf_time.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cdf_getdays
  2. cdf_getday
  3. cdf_getmonth
  4. cdf_timestamp_to_timespec
  5. cdf_timespec_to_timestamp
  6. cdf_ctime
  7. main

   1 /*-
   2  * Copyright (c) 2008 Christos Zoulas
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  *
  14  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  15  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  16  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24  * POSSIBILITY OF SUCH DAMAGE.
  25  */
  26 
  27 #include "file.h"
  28 
  29 #ifndef lint
  30 FILE_RCSID("@(#)$File: cdf_time.c,v 1.14 2014/04/17 12:44:01 christos Exp $")
  31 #endif
  32 
  33 #include <time.h>
  34 #ifdef TEST
  35 #include <err.h>
  36 #endif
  37 #include <string.h>
  38 
  39 #include "cdf.h"
  40 
  41 #define isleap(y) ((((y) % 4) == 0) && \
  42     ((((y) % 100) != 0) || (((y) % 400) == 0)))
  43 
  44 static const int mdays[] = {
  45     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  46 };
  47 
  48 /*
  49  * Return the number of days between jan 01 1601 and jan 01 of year.
  50  */
  51 static int
  52 cdf_getdays(int year)
  53 {
  54         int days = 0;
  55         int y;
  56 
  57         for (y = CDF_BASE_YEAR; y < year; y++)
  58                 days += isleap(y) + 365;
  59                 
  60         return days;
  61 }
  62 
  63 /*
  64  * Return the day within the month
  65  */
  66 static int
  67 cdf_getday(int year, int days)
  68 {
  69         size_t m;
  70 
  71         for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) {
  72                 int sub = mdays[m] + (m == 1 && isleap(year));
  73                 if (days < sub)
  74                         return days;
  75                 days -= sub;
  76         }
  77         return days;
  78 }
  79 
  80 /* 
  81  * Return the 0...11 month number.
  82  */
  83 static int
  84 cdf_getmonth(int year, int days)
  85 {
  86         size_t m;
  87 
  88         for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) {
  89                 days -= mdays[m];
  90                 if (m == 1 && isleap(year))
  91                         days--;
  92                 if (days <= 0)
  93                         return (int)m;
  94         }
  95         return (int)m;
  96 }
  97 
  98 int
  99 cdf_timestamp_to_timespec(struct timeval *ts, cdf_timestamp_t t)
 100 {
 101         struct tm tm;
 102 #ifdef HAVE_STRUCT_TM_TM_ZONE
 103         static char UTC[] = "UTC";
 104 #endif
 105         int rdays;
 106 
 107         /* XXX 5.14 at least introdced 100 ns intervals, this is to do */
 108         /* Time interval, in microseconds */
 109         ts->tv_usec = (t % CDF_TIME_PREC) * CDF_TIME_PREC;
 110 
 111         t /= CDF_TIME_PREC;
 112         tm.tm_sec = (int)(t % 60);
 113         t /= 60;
 114 
 115         tm.tm_min = (int)(t % 60);
 116         t /= 60;
 117 
 118         tm.tm_hour = (int)(t % 24);
 119         t /= 24;
 120 
 121         /* XXX: Approx */
 122         tm.tm_year = (int)(CDF_BASE_YEAR + (t / 365));
 123 
 124         rdays = cdf_getdays(tm.tm_year);
 125         t -= rdays - 1;
 126         tm.tm_mday = cdf_getday(tm.tm_year, (int)t);
 127         tm.tm_mon = cdf_getmonth(tm.tm_year, (int)t);
 128         tm.tm_wday = 0;
 129         tm.tm_yday = 0;
 130         tm.tm_isdst = 0;
 131 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
 132         tm.tm_gmtoff = 0;
 133 #endif
 134 #ifdef HAVE_STRUCT_TM_TM_ZONE
 135         tm.tm_zone = UTC;
 136 #endif
 137         tm.tm_year -= 1900;
 138         ts->tv_sec = mktime(&tm);
 139         if (ts->tv_sec == -1) {
 140                 errno = EINVAL;
 141                 return -1;
 142         }
 143         return 0;
 144 }
 145 
 146 int
 147 /*ARGSUSED*/
 148 cdf_timespec_to_timestamp(cdf_timestamp_t *t, const struct timeval *ts)
 149 {
 150 #ifndef __lint__
 151         (void)&t;
 152         (void)&ts;
 153 #endif
 154 #ifdef notyet
 155         struct tm tm;
 156         if (gmtime_r(&ts->ts_sec, &tm) == NULL) {
 157                 errno = EINVAL;
 158                 return -1;
 159         }
 160         *t = (ts->ts_usec / CDF_TIME_PREC) * CDF_TIME_PREC;
 161         *t = tm.tm_sec;
 162         *t += tm.tm_min * 60;
 163         *t += tm.tm_hour * 60 * 60;
 164         *t += tm.tm_mday * 60 * 60 * 24;
 165 #endif
 166         return 0;
 167 }
 168 
 169 char *
 170 cdf_ctime(const time_t *sec, char *buf)
 171 {
 172         char *ptr = ctime_r(sec, buf);
 173         if (ptr != NULL)
 174                 return buf;
 175         (void)snprintf(buf, 26, "*Bad* 0x%16.16" INT64_T_FORMAT "x\n",
 176             (long long)*sec);
 177         return buf;
 178 }
 179 
 180 
 181 #ifdef TEST_TIME
 182 int
 183 main(int argc, char *argv[])
 184 {
 185         struct timeval ts;
 186         char buf[25];
 187         static const cdf_timestamp_t tst = 0x01A5E403C2D59C00ULL;
 188         static const char *ref = "Sat Apr 23 01:30:00 1977";
 189         char *p, *q;
 190 
 191         cdf_timestamp_to_timespec(&ts, tst);
 192         p = cdf_ctime(&ts.tv_sec, buf);
 193         if ((q = strchr(p, '\n')) != NULL)
 194                 *q = '\0';
 195         if (strcmp(ref, p) != 0)
 196                 errx(1, "Error date %s != %s\n", ref, p);
 197         return 0;
 198 }
 199 #endif

/* [<][>][^][v][top][bottom][index][help] */