| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* time.c - various time routines */
- #include <stdio.h>
- #include <sys/types.h>
- #ifndef _WIN32
- #ifdef AIX
- #include <time.h>
- #else
- #include <sys/time.h>
- #endif
- #endif /* _WIN32 */
- #include "slap.h"
- #include "fe.h"
- LDAP_API(unsigned long) strntoul( char *from, size_t len, int base );
- #define mktime_r(from) mktime (from) /* possible bug: is this thread-safe? */
- static time_t currenttime;
- static int currenttime_set = 0;
- /* XXX currenttime and currenttime_set are used by multiple threads,
- * concurrently (one thread sets them, many threads read them),
- * WITHOUT SYNCHRONIZATION. If assignment to currenttime especially
- * is not atomic, current_time() will return bogus values, and
- * bogus behavior may ensue. We think this isn't a problem, because
- * currenttime is a static variable, and defined first in this module;
- * consequently it's aligned, and doesn't cross cache lines or
- * otherwise run afoul of multiprocessor weirdness that might make
- * assignment to it non-atomic.
- */
- #ifndef HAVE_TIME_R
- PRLock *time_func_mutex;
- int gmtime_r(
- const time_t *timer,
- struct tm *result
- )
- {
- if ( result == NULL ) {
- return -1;
- }
- PR_Lock( time_func_mutex );
- memcpy( (void *) result, (const void *) gmtime( timer ),
- sizeof( struct tm ));
- PR_Unlock( time_func_mutex );
- return 0;
- }
- int localtime_r(
- const time_t *timer,
- struct tm *result
- )
- {
- if ( result == NULL ) {
- return -1;
- }
- PR_Lock( time_func_mutex );
- memcpy( (void *) result, (const void *) localtime( timer ),
- sizeof( struct tm ));
- PR_Unlock( time_func_mutex );
- return 0;
- }
- int ctime_r(
- const time_t *timer,
- char *buffer,
- int buflen
- )
- {
- if (( buffer == NULL ) || ( buflen < 26)) {
- return -1;
- }
- PR_Lock( time_func_mutex );
- memset( buffer, 0, buflen );
- memcpy( buffer, ctime( timer ), 26 );
- PR_Unlock( time_func_mutex );
- return 0;
- }
- #endif /* HAVE_TIME_R */
- char *
- get_timestring(time_t *t)
- {
- char *timebuf;
- #if defined( _WIN32 )
- timebuf = ctime( t );
- #else
- if ( (timebuf = slapi_ch_malloc(32)) == NULL )
- return("No memory for get_timestring");
- CTIME(t, timebuf, 32);
- #endif
- timebuf[strlen(timebuf) - 1] = '\0'; /* strip out return */
- return(timebuf);
- }
- void
- free_timestring(char *timestr)
- {
- #if defined( _WIN32 )
- return;
- #else
- if ( timestr != NULL )
- slapi_ch_free((void**)×tr);
- #endif
- }
- /*
- * poll_current_time() is called at least once every second by the time
- * thread (see daemon.c:time_thread()). current_time() returns the time
- * that poll_current_time() last stored. This approach is used to avoid
- * calling the time() system call many times per second.
- *
- * Note: during server startup, poll_current_time() is not called at all so
- * current_time() just calls through to time() until poll_current_time() starts
- * to be called.
- */
- time_t
- poll_current_time()
- {
- if ( !currenttime_set ) {
- currenttime_set = 1;
- }
- time( ¤ttime );
- return( currenttime );
- }
- time_t
- current_time( void )
- {
- if ( currenttime_set ) {
- return( currenttime );
- } else {
- return( time( (time_t *)0 ));
- }
- }
- time_t
- time_plus_sec (time_t l, long r)
- /* return the point in time 'r' seconds after 'l'. */
- {
- /* On many (but not all) platforms this is simply l + r;
- perhaps it would be better to implement it that way. */
- struct tm t;
- if (r == 0) return l; /* performance optimization */
- #ifdef _WIN32
- {
- struct tm *pt = localtime( &l );
- memcpy(&t, pt, sizeof(struct tm) );
- }
- #else
- localtime_r (&l, &t);
- #endif
- /* Conceptually, we want to do: t.tm_sec += r;
- but to avoid overflowing fields: */
- r += t.tm_sec; t.tm_sec = r % 60; r /= 60;
- r += t.tm_min; t.tm_min = r % 60; r /= 60;
- r += t.tm_hour; t.tm_hour = r % 24; r /= 24;
- t.tm_mday += r; /* may be > 31; mktime_r() must handle this */
- /* These constants are chosen to work when the maximum
- field values are 127 (the worst case) or more.
- Perhaps this is excessively conservative. */
- return mktime_r (&t);
- }
- char*
- format_localTime (time_t from)
- /* return a newly-allocated string containing the given time, expressed
- in the syntax of a generalizedTime, except without the time zone. */
- {
- char* into;
- struct tm t;
- #ifdef _WIN32
- {
- struct tm *pt = localtime( &from );
- memcpy(&t, pt, sizeof(struct tm) );
- }
- #else
- localtime_r (&from, &t);
- #endif
- into = slapi_ch_smprintf("%.4li%.2i%.2i%.2i%.2i%.2i",
- 1900L + t.tm_year, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.
- tm_sec);
- return into;
- }
- time_t
- read_localTime (struct berval* from)
- /* the inverse of write_localTime */
- {
- return (read_genTime(from));
- }
- time_t
- parse_localTime (char* from)
- /* the inverse of format_localTime */
- {
- return (parse_genTime(from));
- }
- void
- write_localTime (time_t from, struct berval* into)
- /* like format_localTime, except it returns a berval */
- {
- into->bv_val = format_localTime (from);
- into->bv_len = 14; /* strlen (into->bv_val) */
- }
- /*
- * Function: strntoul
- *
- * Returns: the value of "from", converted to an unsigned long integer.
- *
- * Arguments: from - a pointer to the string to be converted.
- * len - the maximum number of characters to process.
- * base - the base to use for conversion. See strtoul(3).
- *
- * Returns: See strtoul(3).
- */
- LDAP_API(unsigned long) strntoul( char *from, size_t len, int base )
- {
- unsigned long result;
- char c = from[ len ];
- from[ len ] = '\0';
- result = strtoul( from, NULL, base );
- from[ len ] = c;
- return result;
- }
- /*
- * New time functions.
- * The format and write functions, express time as
- * generalizedTime (in the Z form).
- * The parse and read functions, can read either
- * localTime or generalizedTime.
- */
- char *
- format_genTime (time_t from)
- /* return a newly-allocated string containing the given time, expressed
- in the syntax of a generalizedTime. */
- {
- char* into;
- struct tm t;
- #ifdef _WIN32
- {
- struct tm *pt = gmtime( &from );
- memcpy(&t, pt, sizeof(struct tm) );
- }
- #else
- gmtime_r (&from, &t);
- #endif
- into = slapi_ch_malloc (20);
- strftime(into, 20, "%Y%m%d%H%M%SZ", &t);
- return into;
- }
- void
- write_genTime (time_t from, struct berval* into)
- /* like format_localTime, except it returns a berval */
- {
- into->bv_val = format_genTime (from);
- into->bv_len = strlen (into->bv_val);
- }
- time_t
- read_genTime(struct berval*from)
- {
- struct tm t;
- time_t retTime;
- time_t diffsec = 0;
- int i, gflag = 0, havesec = 0;
-
- memset (&t, 0, sizeof(t));
- t.tm_isdst = -1;
- t.tm_year = strntoul (from->bv_val , 4, 10) - 1900L;
- t.tm_mon = strntoul (from->bv_val + 4, 2, 10) - 1;
- t.tm_mday = strntoul (from->bv_val + 6, 2, 10);
- t.tm_hour = strntoul (from->bv_val + 8, 2, 10);
- t.tm_min = strntoul (from->bv_val + 10, 2, 10);
- i =12;
- /*
- * the string can end with Z or -xxxx or +xxxx
- * or before to have the Z/+/- we may have two digits for the seconds.
- * If there's no Z/+/-, it means it's been expressed as local time
- * (not standard).
- */
- while (from->bv_val[i]) {
- switch (from->bv_val[i]) {
- case 'Z':
- case 'z':
- gflag = 1;
- ++i;
- break;
- case '+': /* Offset from GMT is on 4 digits */
- i++;
- diffsec -= strntoul (from->bv_val + i, 4, 10);
- gflag = 1;
- i += 4;
- break;
- case '-': /* Offset from GMT is on 4 digits */
- i++;
- diffsec += strntoul (from->bv_val + i, 4, 10);
- gflag = 1;
- i += 4;
- break;
- default:
- if (havesec){
- /* Ignore milliseconds */
- i++;
- } else {
- t.tm_sec = strntoul (from->bv_val + i, 2, 10);
- havesec = 1;
- i += 2;
- }
- } /* end switch */
- }
- if (gflag){
- PRTime pt;
- PRExplodedTime expt = {0};
- unsigned long year = strntoul (from->bv_val , 4, 10);
- expt.tm_year = (PRInt16)year;
- expt.tm_month = t.tm_mon;
- expt.tm_mday = t.tm_mday;
- expt.tm_hour = t.tm_hour;
- expt.tm_min = t.tm_min;
- expt.tm_sec = t.tm_sec;
- /* This is a GMT time */
- expt.tm_params.tp_gmt_offset = 0;
- expt.tm_params.tp_dst_offset = 0;
- /* PRTime is expressed in microseconds */
- pt = PR_ImplodeTime(&expt) / 1000000L;
- retTime = (time_t)pt;
- return (retTime + diffsec);
- } else {
- return mktime_r (&t);
- }
- }
- time_t
- parse_genTime (char* from)
- /* the inverse of format_genTime
- * Because read_localTime has been rewriten to take into
- * account generalizedTime, parse_time is similar to parse_localTime.
- * The new call is
- */
- {
- struct berval tbv;
- tbv.bv_val = from;
- tbv.bv_len = strlen (from);
- return read_genTime(&tbv);
- }
|