• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

/build/buildd-opendnssec_1.3.2-1~bpo60+1-mipsel-iYafXM/opendnssec-1.3.2/signer/src/shared/duration.c

Go to the documentation of this file.
00001 /*
00002  * $Id: duration.c 4518 2011-02-24 15:39:09Z matthijs $
00003  *
00004  * Copyright (c) 2009 NLNet Labs. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00016  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00021  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00023  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00025  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  */
00028 
00034 #include "shared/allocator.h"
00035 #include "shared/duration.h"
00036 #include "shared/log.h"
00037 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <time.h>
00042 
00043 static const char* duration_str = "duration";
00044 
00045 
00050 duration_type*
00051 duration_create(void)
00052 {
00053     duration_type* duration;
00054     allocator_type* allocator = allocator_create(malloc, free);
00055     if (!allocator) {
00056         ods_log_error("[%s] cannot create: no allocator available",
00057             duration_str);
00058         return NULL;
00059     }
00060 
00061     duration = (duration_type*) allocator_alloc(allocator,
00062         sizeof(duration_type));
00063     if (!duration) {
00064         ods_log_error("[%s] cannot create: allocator failed", duration_str);
00065         allocator_cleanup(allocator);
00066         return NULL;
00067     }
00068     duration->allocator = allocator;
00069     duration->years = 0;
00070     duration->months = 0;
00071     duration->weeks = 0;
00072     duration->days = 0;
00073     duration->hours = 0;
00074     duration->minutes = 0;
00075     duration->seconds = 0;
00076     return duration;
00077 }
00078 
00079 
00084 int
00085 duration_compare(duration_type* d1, duration_type* d2)
00086 {
00087     if (!d1 && !d2) {
00088         return 0;
00089     }
00090     if (!d1 || !d2) {
00091         return d1?-1:1;
00092     }
00093 
00094     if (d1->years != d2->years) {
00095         return d1->years - d2->years;
00096     }
00097     if (d1->months != d2->months) {
00098         return d1->months - d2->months;
00099     }
00100     if (d1->weeks != d2->weeks) {
00101         return d1->weeks - d2->weeks;
00102     }
00103     if (d1->days != d2->days) {
00104         return d1->days - d2->days;
00105     }
00106     if (d1->hours != d2->hours) {
00107         return d1->hours - d2->hours;
00108     }
00109     if (d1->minutes != d2->minutes) {
00110         return d1->minutes - d2->minutes;
00111     }
00112     if (d1->seconds != d2->seconds) {
00113         return d1->seconds - d2->seconds;
00114     }
00115 
00116     return 0;
00117 }
00118 
00119 
00124 duration_type*
00125 duration_create_from_string(const char* str)
00126 {
00127     duration_type* duration = duration_create();
00128     char* P, *X, *T, *W;
00129     int not_weeks = 0;
00130 
00131     if (!duration) {
00132         ods_log_error("[%s] cannot create from string %s: create failed",
00133             duration_str, str);
00134         return NULL;
00135     }
00136     if (!str) {
00137         return duration;
00138     }
00139 
00140     P = strchr(str, 'P');
00141     if (!P) {
00142         ods_log_error("[%s] cannot create from string %s: P not found",
00143             duration_str, str);
00144         duration_cleanup(duration);
00145         return NULL;
00146     }
00147 
00148     T = strchr(str, 'T');
00149     X = strchr(str, 'Y');
00150     if (X) {
00151         duration->years = atoi(str+1);
00152         str = X;
00153         not_weeks = 1;
00154     }
00155     X = strchr(str, 'M');
00156     if (X && (!T || (size_t) (X-P) < (size_t) (T-P))) {
00157         duration->months = atoi(str+1);
00158         str = X;
00159         not_weeks = 1;
00160     }
00161     X = strchr(str, 'D');
00162     if (X) {
00163         duration->days = atoi(str+1);
00164         str = X;
00165         not_weeks = 1;
00166     }
00167     if (T) {
00168         str = T;
00169         not_weeks = 1;
00170     }
00171     X = strchr(str, 'H');
00172     if (X && T) {
00173         duration->hours = atoi(str+1);
00174         str = X;
00175         not_weeks = 1;
00176     }
00177     X = strrchr(str, 'M');
00178     if (X && T && (size_t) (X-P) > (size_t) (T-P)) {
00179         duration->minutes = atoi(str+1);
00180         str = X;
00181         not_weeks = 1;
00182     }
00183     X = strchr(str, 'S');
00184     if (X && T) {
00185         duration->seconds = atoi(str+1);
00186         str = X;
00187         not_weeks = 1;
00188     }
00189 
00190     W = strchr(str, 'W');
00191     if (W) {
00192         if (not_weeks) {
00193             ods_log_error("[%s] cannot create from string: parse error",
00194                 duration_str, P);
00195             duration_cleanup(duration);
00196             return NULL;
00197         } else {
00198             duration->weeks = atoi(str+1);
00199             str = W;
00200         }
00201     }
00202     return duration;
00203 }
00204 
00205 
00210 static size_t
00211 digits_in_number(time_t duration)
00212 {
00213     uint32_t period = (uint32_t) duration;
00214     size_t count = 0;
00215 
00216     while (period > 0) {
00217         count++;
00218         period /= 10;
00219     }
00220     return count;
00221 }
00222 
00223 
00228 char*
00229 duration2string(duration_type* duration)
00230 {
00231     char* str = NULL, *num = NULL;
00232     size_t count = 2;
00233     int T = 0;
00234 
00235     if (!duration) {
00236         return NULL;
00237     }
00238 
00239     if (duration->years > 0) {
00240         count = count + 1 + digits_in_number(duration->years);
00241     }
00242     if (duration->months > 0) {
00243         count = count + 1 + digits_in_number(duration->months);
00244     }
00245     if (duration->weeks > 0) {
00246         count = count + 1 + digits_in_number(duration->weeks);
00247     }
00248     if (duration->days > 0) {
00249         count = count + 1 + digits_in_number(duration->days);
00250     }
00251     if (duration->hours > 0) {
00252         count = count + 1 + digits_in_number(duration->hours);
00253         T = 1;
00254     }
00255     if (duration->minutes > 0) {
00256         count = count + 1 + digits_in_number(duration->minutes);
00257         T = 1;
00258     }
00259     if (duration->seconds > 0) {
00260         count = count + 1 + digits_in_number(duration->seconds);
00261         T = 1;
00262     }
00263     if (T) {
00264         count++;
00265     }
00266 
00267     str = (char*) calloc(count, sizeof(char));
00268     str[0] = 'P';
00269     str[1] = '\0';
00270 
00271     if (duration->years > 0) {
00272         count = digits_in_number(duration->years);
00273         num = (char*) calloc(count+2, sizeof(char));
00274         snprintf(num, count+2, "%uY", (uint32_t) duration->years);
00275         str = strncat(str, num, count+2);
00276         free((void*) num);
00277     }
00278     if (duration->months > 0) {
00279         count = digits_in_number(duration->months);
00280         num = (char*) calloc(count+2, sizeof(char));
00281         snprintf(num, count+2, "%uM", (uint32_t) duration->months);
00282         str = strncat(str, num, count+2);
00283         free((void*) num);
00284     }
00285     if (duration->weeks > 0) {
00286         count = digits_in_number(duration->weeks);
00287         num = (char*) calloc(count+2, sizeof(char));
00288         snprintf(num, count+2, "%uW", (uint32_t) duration->weeks);
00289         str = strncat(str, num, count+2);
00290         free((void*) num);
00291     }
00292     if (duration->days > 0) {
00293         count = digits_in_number(duration->days);
00294         num = (char*) calloc(count+2, sizeof(char));
00295         snprintf(num, count+2, "%uD", (uint32_t) duration->days);
00296         str = strncat(str, num, count+2);
00297         free((void*) num);
00298     }
00299     if (T) {
00300         str = strncat(str, "T", 1);
00301     }
00302     if (duration->hours > 0) {
00303         count = digits_in_number(duration->hours);
00304         num = (char*) calloc(count+2, sizeof(char));
00305         snprintf(num, count+2, "%uH", (uint32_t) duration->hours);
00306         str = strncat(str, num, count+2);
00307         free((void*) num);
00308     }
00309     if (duration->minutes > 0) {
00310         count = digits_in_number(duration->minutes);
00311         num = (char*) calloc(count+2, sizeof(char));
00312         snprintf(num, count+2, "%uM", (uint32_t) duration->minutes);
00313         str = strncat(str, num, count+2);
00314         free((void*) num);
00315     }
00316     if (duration->seconds > 0) {
00317         count = digits_in_number(duration->seconds);
00318         num = (char*) calloc(count+2, sizeof(char));
00319         snprintf(num, count+2, "%uS", (uint32_t) duration->seconds);
00320         str = strncat(str, num, count+2);
00321         free((void*) num);
00322     }
00323     return str;
00324 }
00325 
00326 
00331 time_t
00332 duration2time(duration_type* duration)
00333 {
00334     time_t period = 0;
00335     char* dstr = NULL;
00336 
00337     if (duration) {
00338         period += (duration->seconds);
00339         period += (duration->minutes)*60;
00340         period += (duration->hours)*3600;
00341         period += (duration->days)*86400;
00342         period += (duration->weeks)*86400*7;
00343         period += (duration->months)*86400*31;
00344         period += (duration->years)*86400*365;
00345 
00346         if (duration->months || duration->years) {
00347             /* [TODO] calculate correct number of days in this month/year */
00348             dstr = duration2string(duration);
00349             ods_log_warning("[%s] converting duration %s to approximate value",
00350                 duration_str, dstr?dstr:"(null)");
00351             free((void*) dstr);
00352         }
00353     }
00354     return period;
00355 }
00356 
00361 time_t
00362 time_minimum(time_t a, time_t b)
00363 {
00364     return (a < b ? a : b);
00365 }
00366 
00371 time_t
00372 time_maximum(time_t a, time_t b)
00373 {
00374     return (a > b ? a : b);
00375 }
00376 
00377 
00382 time_t
00383 ods_rand(time_t mod)
00384 {
00385 #ifdef HAVE_ARC4RANDOM_UNIFORM
00386     return (time_t) (arc4random_uniform((uint32_t) mod+1));
00387 #elif HAVE_ARC4RANDOM
00388     return (time_t) (arc4random() % (unsigned) mod+1);
00389 #else
00390     return (time_t) (random() % (unsigned) mod+1);
00391 #endif
00392 }
00393 
00394 
00395 /* Number of days per month (except for February in leap years). */
00396 static const int mdays[] = {
00397     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
00398 };
00399 
00400 
00401 static int
00402 is_leap_year(int year)
00403 {
00404     return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
00405 }
00406 
00407 
00408 static int
00409 leap_days(int y1, int y2)
00410 {
00411     --y1;
00412     --y2;
00413     return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
00414 }
00415 
00416 
00417 /*
00418  * Code taken from NSD 3.2.5, which is
00419  * code adapted from Python 2.4.1 sources (Lib/calendar.py).
00420  */
00421 static time_t
00422 mktime_from_utc(const struct tm *tm)
00423 {
00424     int year = 1900 + tm->tm_year;
00425     time_t days = 365 * (year - 1970) + leap_days(1970, year);
00426     time_t hours;
00427     time_t minutes;
00428     time_t seconds;
00429     int i;
00430 
00431     for (i = 0; i < tm->tm_mon; ++i) {
00432         days += mdays[i];
00433     }
00434     if (tm->tm_mon > 1 && is_leap_year(year)) {
00435         ++days;
00436     }
00437     days += tm->tm_mday - 1;
00438 
00439     hours = days * 24 + tm->tm_hour;
00440     minutes = hours * 60 + tm->tm_min;
00441     seconds = minutes * 60 + tm->tm_sec;
00442 
00443     return seconds;
00444 }
00445 
00446 
00451 static time_t
00452 timeshift2time(const char *time)
00453 {
00454         /* convert a string in format YYMMDDHHMMSS to time_t */
00455         struct tm tm;
00456         time_t timeshift = 0;
00457 
00458         /* Try to scan the time... */
00459         if (strptime(time, "%Y%m%d%H%M%S", &tm)) {
00460                 timeshift = mktime_from_utc(&tm);
00461         }
00462         return timeshift;
00463 }
00464 
00465 
00470 time_t
00471 time_now(void)
00472 {
00473 #ifdef ENFORCER_TIMESHIFT
00474     const char* env = getenv("ENFORCER_TIMESHIFT");
00475     if (env) {
00476         return timeshift2time(env);
00477     } else
00478 #endif /* ENFORCER_TIMESHIFT */
00479 
00480     return time(NULL);
00481 }
00482 
00483 
00488 uint32_t
00489 time_datestamp(time_t tt, const char* format, char** str)
00490 {
00491     time_t t;
00492     struct tm *tmp;
00493     uint32_t ut = 0;
00494     char outstr[32];
00495 
00496     if (tt) {
00497         t = tt;
00498     } else {
00499         t = time_now();
00500     }
00501 
00502     tmp = localtime(&t);
00503     if (tmp == NULL) {
00504         ods_log_error("[%s] time_datestamp: localtime() failed", duration_str);
00505         return 0;
00506     }
00507 
00508     if (strftime(outstr, sizeof(outstr), format, tmp) == 0) {
00509         ods_log_error("[%s] time_datestamp: strftime() failed", duration_str);
00510         return 0;
00511     }
00512 
00513     ut = (uint32_t) strtoul(outstr, NULL, 10);
00514     if (str) {
00515         *str = strdup(outstr);
00516     }
00517     return ut;
00518 }
00519 
00520 static void
00521 time_itoa_reverse(char* s)
00522 {
00523     int i, j;
00524     char c;
00525 
00526     for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
00527         c = s[i];
00528         s[i] = s[j];
00529         s[j] = c;
00530     }
00531     return;
00532 }
00533 
00534 
00539 void
00540 time_itoa(time_t n, char* s)
00541 {
00542     int i = 0;
00543 
00544     do {       /* generate digits in reverse order */
00545         s[i++] = n % 10 + '0';   /* get next digit */
00546     } while ((n /= 10) > 0);     /* delete it */
00547     s[i] = '\0';
00548     time_itoa_reverse(s);
00549     return;
00550 }
00551 
00552 
00557 void
00558 duration_cleanup(duration_type* duration)
00559 {
00560     allocator_type* allocator;
00561 
00562     if (!duration) {
00563         return;
00564     }
00565     allocator = duration->allocator;
00566     allocator_deallocate(allocator, (void*) duration);
00567     allocator_cleanup(allocator);
00568     return;
00569 }

Generated on Sun Dec 18 2011 11:53:59 for OpenDNSSEC-signer by  doxygen 1.7.1