LTP GCOV extension - code coverage report
Current view: directory - and-httpd/src - date.c
Test: And-httpd coverage
Date: 2006-09-11 Instrumented lines: 143
Code covered: 84.6 % Executed lines: 121

       1                 : /*
       2                 :  *  Copyright (C) 2004, 2005, 2006  James Antill
       3                 :  *
       4                 :  *  This library is free software; you can redistribute it and/or
       5                 :  *  modify it under the terms of the GNU Lesser General Public
       6                 :  *  License as published by the Free Software Foundation; either
       7                 :  *  version 2 of the License, or (at your option) any later version.
       8                 :  *
       9                 :  *  This library is distributed in the hope that it will be useful,
      10                 :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12                 :  *  Lesser General Public License for more details.
      13                 :  *
      14                 :  *  You should have received a copy of the GNU Lesser General Public
      15                 :  *  License along with this library; if not, write to the Free Software
      16                 :  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17                 :  *
      18                 :  *  email: james@and.org
      19                 :  */
      20                 : /* date text generating functions ... stop glibc some spending all the time
      21                 :  * doing stat() on /etc/localtime */
      22                 :    
      23                 : #define EX_UTILS_NO_FUNCS 1
      24                 : #include "ex_utils.h"
      25                 : 
      26                 : #include "date.h"
      27                 : 
      28                 : #include "mk.h"
      29                 : 
      30                 : #include <limits.h> /* CHAR_BIT */
      31                 : 
      32                 : #ifndef FALSE
      33                 : # define FALSE 0
      34                 : #endif
      35                 : 
      36                 : #ifndef TRUE
      37                 : # define TRUE 1
      38                 : #endif
      39                 : 
      40                 : void date_free(Date_store *data)
      41             596 : {
      42             596 :   F(data);
      43             596 : }
      44                 : 
      45                 : Date_store *date_make(void)
      46             656 : {
      47             656 :   Date_store *data = MK(sizeof(Date_store));
      48             656 :   unsigned int num = 0;
      49                 : 
      50             656 :   if (!data)
      51               0 :     return (NULL);
      52                 : 
      53                 :   if (COMPILE_DEBUG)
      54             328 :     data->tmt = DATE__TYPE_TM_UNKNOWN;
      55                 : 
      56             656 :   data->saved_count = DATE__CACHE_NUM - 1;
      57                 : 
      58            3936 :   while (num < DATE__CACHE_NUM)
      59            2624 :     data->saved_val[num++] = -1;
      60                 : 
      61             656 :   return (data);
      62                 : }
      63                 : 
      64                 : static const struct tm *date__srch(Date_store *data, time_t val)
      65          212367 : {
      66          212367 :   unsigned int num = 0;
      67                 : 
      68          106234 :   ASSERT(malloc_check_sz_mem(data, sizeof(Date_store)) || TRUE);
      69                 : 
      70          106234 :   ASSERT((data->tmt == DATE__TYPE_TM_GMT) ||
      71                 :          (data->tmt == DATE__TYPE_TM_LOC));
      72                 :   
      73          643486 :   while (num < DATE__CACHE_NUM)
      74                 :   {
      75          530781 :     if (data->saved_val[num] == val)
      76          205795 :       return (data->saved_tm + num);
      77                 :     
      78          324986 :     ++num;
      79                 :   }
      80                 :   
      81            6572 :   return (NULL);
      82                 : }
      83                 : 
      84                 : #define DATE__GET(x) do {                              \
      85                 :       num = (data->saved_count + 1) % DATE__CACHE_NUM; \
      86                 :                                                        \
      87                 :       data->saved_val[num] = -1;                       \
      88                 :       if (! x (&val, data->saved_tm + num))            \
      89                 :         return (NULL);                                 \
      90                 :       data->saved_val[num] = val;                      \
      91                 :       data->saved_count    = num;                      \
      92                 :     } while (FALSE)
      93                 :     
      94                 : const struct tm *date_gmtime(Date_store *data, time_t val)
      95          144454 : {
      96          144454 :   unsigned int num = 0;
      97          144454 :   const struct tm *ret = NULL;
      98                 : 
      99           72263 :   if (COMPILE_DEBUG && (data->tmt == DATE__TYPE_TM_UNKNOWN))
     100              22 :     data->tmt = DATE__TYPE_TM_GMT;
     101                 :   
     102           72263 :   ASSERT(data->tmt == DATE__TYPE_TM_GMT);
     103                 :   
     104          144454 :   if ((ret = date__srch(data, val)))
     105          138612 :     return (ret);
     106                 : 
     107            5842 :   DATE__GET(gmtime_r);
     108                 :   
     109            5842 :   return (data->saved_tm + num);
     110                 : }
     111                 : 
     112                 : const struct tm *date_localtime(Date_store *data, time_t val)
     113           67913 : {
     114           67913 :   unsigned int num = 0;
     115           67913 :   const struct tm *ret = NULL;
     116                 :   
     117           33971 :   if (COMPILE_DEBUG && (data->tmt == DATE__TYPE_TM_UNKNOWN))
     118              22 :     data->tmt = DATE__TYPE_TM_LOC;
     119                 :   
     120           33971 :   ASSERT(data->tmt == DATE__TYPE_TM_LOC);
     121                 :   
     122           67913 :   if ((ret = date__srch(data, val)))
     123           67183 :     return (ret);
     124                 :   
     125             730 :   DATE__GET(localtime_r);
     126                 :   
     127             730 :   return (data->saved_tm + num);
     128                 : }
     129                 : #undef DATE__GET
     130                 : 
     131                 : 
     132                 : static const char date__days_shrt[7][4] =
     133                 : {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
     134                 : static const char date__days_full[7][10] =
     135                 : {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
     136                 :  "Saturday"};
     137                 : static const char date__months[12][4] =
     138                 : {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
     139                 :  "Sep", "Oct", "Nov", "Dec"};
     140                 : 
     141                 : /* stupid roll your own string API, but what ya gonna do... */
     142                 : #define CP_BEG() do { ptr = data->ret_buf;                              \
     143                 :       ASSERT(memset(ptr, 0xbe, DATE__RET_SZ));                          \
     144                 :     } while (FALSE)
     145                 : #define CP(x, n) do {                                                   \
     146                 :       memcpy(ptr, x, n); ptr += (n);                                    \
     147                 :       ASSERT((ptr >=  data->ret_buf) &&                                 \
     148                 :              (ptr <= (data->ret_buf + DATE__RET_SZ))); } while (FALSE)
     149                 : #define CP_LEN(x) CP(x, strlen(x))
     150                 : #define CP_NUM(x) do {                                  \
     151                 :       unsigned int num = (x);                           \
     152                 :       char buf[sizeof(unsigned int) * CHAR_BIT];        \
     153                 :       char *tmp = buf + sizeof(buf);                    \
     154                 :                                                         \
     155                 :       while (num)                                       \
     156                 :       {                                                 \
     157                 :         *--tmp = '0' + (num % 10);                      \
     158                 :         num /= 10;                                      \
     159                 :       }                                                 \
     160                 :       if ((tmp - buf) != sizeof(buf))                   \
     161                 :         CP(tmp, sizeof(buf) - (tmp - buf));             \
     162                 :       else                                              \
     163                 :         CP_LEN("0");                                    \
     164                 :     } while (FALSE)
     165                 : #define CP_02NUM(x) do {                        \
     166                 :       if ((x) < 10)                             \
     167                 :         CP_LEN("0");                            \
     168                 :       CP_NUM(x);                                \
     169                 :     } while (FALSE)
     170                 : #define CP__2NUM(x) do {                        \
     171                 :       if ((x) < 10)                             \
     172                 :         CP_LEN(" ");                            \
     173                 :       CP_NUM(x);                                \
     174                 :     } while (FALSE)
     175                 : 
     176                 : #define CP_END() CP("", 1)
     177                 : 
     178                 : /* we do all of this "locally" due to POSIX requiring strftime to call tzset()
     179                 :    Glibc then compounds that by stat()'ing */
     180                 : const char *date_rfc1123(Date_store *data, time_t val)
     181          100678 : {
     182          100678 :   const struct tm *tm = NULL;
     183          100678 :   char *ptr = NULL;
     184                 :   
     185          100678 :   if (!(tm = date_gmtime(data, val)))
     186               0 :     err(EXIT_FAILURE, "gmtime_r(%s)", "%a, %d %h %Y %T GMT");
     187                 : 
     188          100678 :   CP_BEG();
     189          100678 :   CP(date__days_shrt[tm->tm_wday], 3); /* %a */
     190          100678 :   CP_LEN(", ");
     191          100678 :   CP_02NUM(tm->tm_mday); /* %d */
     192          100678 :   CP_LEN(" ");
     193          100678 :   CP(date__months[tm->tm_mon], 3); /* %h */
     194          100678 :   CP_LEN(" ");
     195          100678 :   CP_NUM(tm->tm_year + 1900); /* %Y */
     196          100678 :   CP_LEN(" ");
     197          100678 :   CP_02NUM(tm->tm_hour); /* %T */
     198          100678 :   CP_LEN(":");
     199          100678 :   CP_02NUM(tm->tm_min);
     200          100678 :   CP_LEN(":");
     201          100678 :   CP_02NUM(tm->tm_sec);
     202          100678 :   CP_LEN(" GMT");
     203          100678 :   CP_END();
     204                 :   
     205          100678 :   return (data->ret_buf);
     206                 : }
     207                 : const char *date_rfc850(Date_store *data, time_t val)
     208           21944 : {
     209           21944 :   const struct tm *tm = NULL;
     210           21944 :   char *ptr = NULL;
     211                 :   
     212           21944 :   if (!(tm = date_gmtime(data, val)))
     213               0 :     err(EXIT_FAILURE, "gmtime_r(%s)", "%A, %d-%h-%y %T GMT");
     214                 :   
     215           21944 :   CP_BEG();
     216           21944 :   CP_LEN(date__days_full[tm->tm_wday]); /* %A */
     217           21944 :   CP_LEN(", ");
     218           21944 :   CP_02NUM(tm->tm_mday); /* %d */
     219           21944 :   CP_LEN("-");
     220           21944 :   CP(date__months[tm->tm_mon], 3); /* %h */
     221           21944 :   CP_LEN("-");
     222           21944 :   CP_02NUM(tm->tm_year % 100); /* %y */
     223           21944 :   CP_LEN(" ");
     224           21944 :   CP_02NUM(tm->tm_hour); /* %T */
     225           21944 :   CP_LEN(":");
     226           21944 :   CP_02NUM(tm->tm_min);
     227           21944 :   CP_LEN(":");
     228           21944 :   CP_02NUM(tm->tm_sec);
     229           21944 :   CP_LEN(" GMT");
     230           21944 :   CP_END();
     231                 :   
     232           21944 :   return (data->ret_buf);
     233                 : }
     234                 : const char *date_asctime(Date_store *data, time_t val)
     235           21800 : {
     236           21800 :   const struct tm *tm = NULL;
     237           21800 :   char *ptr = NULL;
     238                 :   
     239           21800 :   if (!(tm = date_gmtime(data, val)))
     240               0 :     err(EXIT_FAILURE, "gmtime_r(%s)", "%a %h %e %T %Y");
     241                 : 
     242           21800 :   CP_BEG();
     243           21800 :   CP(date__days_shrt[tm->tm_wday], 3); /* %a */
     244           21800 :   CP_LEN(" ");
     245           21800 :   CP(date__months[tm->tm_mon], 3); /* %h */
     246           21800 :   CP_LEN(" ");
     247           21800 :   CP__2NUM(tm->tm_mday); /* %e */
     248           21800 :   CP_LEN(" ");
     249           21800 :   CP_02NUM(tm->tm_hour); /* %T */
     250           21800 :   CP_LEN(":");
     251           21800 :   CP_02NUM(tm->tm_min);
     252           21800 :   CP_LEN(":");
     253           21800 :   CP_02NUM(tm->tm_sec);
     254           21800 :   CP_LEN(" ");
     255           21800 :   CP_NUM(tm->tm_year + 1900); /* %Y */
     256           21800 :   CP_END();
     257                 :   
     258           21800 :   return (data->ret_buf);
     259                 : }
     260                 : const char *date_syslog_trad(Date_store *data, time_t val)
     261               0 : {
     262               0 :   const struct tm *tm = NULL;
     263               0 :   char *ptr = NULL;
     264                 :   
     265               0 :   if (!(tm = date_localtime(data, val)))
     266               0 :     err(EXIT_FAILURE, "localtime_r(%s)", "%h %e %T");
     267                 : 
     268               0 :   CP_BEG();
     269               0 :   CP(date__months[tm->tm_mon], 3); /* %h */
     270               0 :   CP_LEN(" ");
     271               0 :   CP__2NUM(tm->tm_mday); /* %e */
     272               0 :   CP_LEN(" ");
     273               0 :   CP_02NUM(tm->tm_hour); /* %T */
     274               0 :   CP_LEN(":");
     275               0 :   CP_02NUM(tm->tm_min);
     276               0 :   CP_LEN(":");
     277               0 :   CP_02NUM(tm->tm_sec);
     278               0 :   CP_END();
     279                 :   
     280               0 :   return (data->ret_buf);
     281                 : }
     282                 : 
     283                 : const char *date_syslog_yr(Date_store *data, time_t val)
     284           67913 : {
     285           67913 :   const struct tm *tm = NULL;
     286           67913 :   char *ptr = NULL;
     287                 :   
     288           67913 :   if (!(tm = date_localtime(data, val)))
     289               0 :     err(EXIT_FAILURE, "localtime_r(%s)", "%h %e %T");
     290                 : 
     291           67913 :   CP_BEG();
     292           67913 :   CP_NUM(tm->tm_year + 1900); /* %Y */
     293           67913 :   CP_LEN(" ");
     294           67913 :   CP(date__months[tm->tm_mon], 3); /* %h */
     295           67913 :   CP_LEN(" ");
     296           67913 :   CP__2NUM(tm->tm_mday); /* %e */
     297           67913 :   CP_LEN(" ");
     298           67913 :   CP_02NUM(tm->tm_hour); /* %T */
     299           67913 :   CP_LEN(":");
     300           67913 :   CP_02NUM(tm->tm_min);
     301           67913 :   CP_LEN(":");
     302           67913 :   CP_02NUM(tm->tm_sec);
     303           67913 :   CP_END();
     304                 :   
     305           67913 :   return (data->ret_buf);
     306                 : }
     307                 : 
     308                 : #if 0
     309                 : #define VPREFIX(vstr, p, l, cstr)                                       \
     310                 :     (((l) >= CLEN(cstr)) &&                                             \
     311                 :      vstr_cmp_buf_eq(vstr, p, CLEN(cstr), cstr, CLEN(cstr)))
     312                 : 
     313                 : /* see rfc2616 3.3.1 -- full date parser */
     314                 : static time_t date__parse_http(Date_storage *date,
     315                 :                                Vstr_base *s1, size_t pos, size_t len,
     316                 :                                time_t val)
     317                 : {
     318                 :   const struct tm *tm = date_gmtime(date, &val);
     319                 :   unsigned int scan = 0;
     320                 : 
     321                 :   if (!tm) return (-1);
     322                 : 
     323                 :   switch (len)
     324                 :   {
     325                 :     case 4 + 1 + 9 + 1 + 8 + 1 + 3: /* rfc1123 format - should be most common */
     326                 :     {
     327                 :       scan = 0;
     328                 :       while (scan < 7)
     329                 :       {
     330                 :         if (VPREFIX(s1, pos, len, http__date_days_shrt[scan]))
     331                 :           break;
     332                 :         ++scan;
     333                 :       }
     334                 :       len -= 3; pos += 3;
     335                 :       
     336                 :       if (!VPREFIX(s1, pos, len, ", "))
     337                 :         return (-1);
     338                 :       len -= CLEN(", "); pos += CLEN(", ");
     339                 : 
     340                 :       tm->tm_mday = http__date_parse_2d(s1, pos, len, 1, 31);
     341                 :       
     342                 :       if (!VPREFIX(s1, pos, len, " "))
     343                 :         return (-1);
     344                 :       len -= CLEN(" "); pos += CLEN(" ");
     345                 : 
     346                 :       scan = 0;
     347                 :       while (scan < 12)
     348                 :       {
     349                 :         if (VPREFIX(s1, pos, len, http__date_months[scan]))
     350                 :           break;
     351                 :         ++scan;
     352                 :       }
     353                 :       len -= 3; pos += 3;
     354                 :       
     355                 :       tm->tm_mon = scan;
     356                 :       
     357                 :       if (!VPREFIX(s1, pos, len, " "))
     358                 :         return (-1);
     359                 :       len -= CLEN(" "); pos += CLEN(" ");
     360                 : 
     361                 :       tm->tm_year = http__date_parse_4d(s1, pos, len);
     362                 : 
     363                 :       if (!VPREFIX(s1, pos, len, " "))
     364                 :         return (-1);
     365                 :       len -= CLEN(" "); pos += CLEN(" ");
     366                 : 
     367                 :       tm->tm_hour = http__date_parse2d(s1, pos, len, 0, 23);
     368                 :       if (!VPREFIX(s1, pos, len, ":"))
     369                 :         return (-1);
     370                 :       len -= CLEN(":"); pos += CLEN(":");
     371                 :       tm->tm_min  = http__date_parse2d(s1, pos, len, 0, 59);
     372                 :       if (!VPREFIX(s1, pos, len, ":"))
     373                 :         return (-1);
     374                 :       len -= CLEN(":"); pos += CLEN(":");
     375                 :       tm->tm_sec  = http__date_parse2d(s1, pos, len, 0, 61);
     376                 :       
     377                 :       if (!VPREFIX(s1, pos, len, " GMT"))
     378                 :         return (-1);
     379                 :     }
     380                 :     return (mktime(tm));
     381                 : 
     382                 :     case  7 + 1 + 7 + 1 + 8 + 1 + 3:
     383                 :     case  8 + 1 + 7 + 1 + 8 + 1 + 3:
     384                 :     case  9 + 1 + 7 + 1 + 8 + 1 + 3:
     385                 :     case 10 + 1 + 7 + 1 + 8 + 1 + 3: /* rfc850 format */
     386                 :     {
     387                 :       size_t match_len = 0;
     388                 :       
     389                 :       scan = 0;
     390                 :       while (scan < 7)
     391                 :       {
     392                 :         match_len = CLEN(http__date_days_full[scan]);
     393                 :         if (VPREFIX(s1, pos, len, http__date_days_full[scan]))
     394                 :           break;
     395                 :         ++scan;
     396                 :       }
     397                 :       len -= match_len; pos += match_len;
     398                 : 
     399                 :       return (-1);
     400                 :     }
     401                 :     return (mktime(tm));
     402                 : 
     403                 :     case  3 + 1 + 6 + 1 + 8 + 1 + 4: /* asctime format */
     404                 :     {
     405                 :       scan = 0;
     406                 :       while (scan < 7)
     407                 :       {
     408                 :         if (VPREFIX(s1, pos, len, http__date_days_shrt[scan]))
     409                 :           break;
     410                 :         ++scan;
     411                 :       }
     412                 :       len -= 3; pos += 3;
     413                 :       
     414                 :       return (-1);
     415                 :     }
     416                 :     return (mktime(tm));
     417                 :   }
     418                 :   
     419                 :   return (-1);  
     420                 : }
     421                 : #endif

Generated by: LTP GCOV extension version 1.4