blob: dbe9504936210488da4e76ff82a0fc78d6dead9c [file] [log] [blame]
/******************************************************************************
*(C) Copyright 2008 Marvell International Ltd.
* All Rights Reserved
******************************************************************************/
/*****************************************************************************
* Utility Library
*
* DESCRIPTION
* Time utility functions. These wrapper functions provide the
* following benefits:
*
* - Report failures using utlError() so you don't need to every time
* you call gettimeofday() and strftime().
*
* - Provides a standardized string format for dates and times.
*
* - Wraps the system call "gettimeofday()" such that if it is interrupted
* due to receipt of a signal, that it is propertly restarted.
*
* EXAMPLE USAGE
*
* {
* utlAbsoluteTime_T time;
* char buf[50];
*
* if (utlCurrentTime(&time) != utlSUCCESS)
* <handle error here>
*
* if (utlFormatTime(buf, utlNumberOf(buf), &time) != utlSUCCESS)
* <handle error here>
*
* if (utlFormatDate(buf, utlNumberOf(buf), &time) != utlSUCCESS)
* <handle error here>
*
* if (utlFormatDateTime(buf, utlNumberOf(buf), &time) != utlSUCCESS)
* <handle error here>
* }
*
*****************************************************************************/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "utlTypes.h"
#include "utlError.h"
#include "utlTime.h"
/*---------------------------------------------------------------------------*
* FUNCTION
* utlCurrentTime(time_p)
* INPUT
* time_p == pointer to an empty utlAbsoluteTime_T structure
* OUTPUT
* none
* RETURNS
* utlSUCCESS for success, utlFAILED for failure
* DESCRIPTION
* Fetches the current system time since the system epoch.
*---------------------------------------------------------------------------*/
utlReturnCode_T utlCurrentTime(const utlAbsoluteTime_P time_p)
{
utlAssert(time_p != NULL);
#ifdef USE_POSIX_API
{
struct timespec curr_time;
/*--- fetch current time (since epoch) ---*/
for (;; )
{
if (clock_gettime(CLOCK_REALTIME, &curr_time) == 0)
break;
if (errno != EINTR)
{
utlError(utlCurrentTime, "Call to %s() failed, errno=%d", "clock_gettime", errno);
return utlFAILED;
}
}
time_p->seconds = curr_time.tv_sec;
time_p->nanoseconds = curr_time.tv_nsec;
}
#else
{
struct timeval curr_time;
/*--- fetch current time (since epoch) ---*/
for (;; )
{
if (gettimeofday(&curr_time, NULL) == 0)
break;
if (errno != EINTR)
{
utlError(utlCurrentTime1, "Call to %s() failed, errno=%d", "gettimeofday", errno);
return utlFAILED;
}
}
time_p->seconds = curr_time.tv_sec;
time_p->nanoseconds = curr_time.tv_usec * 1000;
}
#endif
return utlSUCCESS;
}
/*---------------------------------------------------------------------------*
* FUNCTION
* utlFormatTime(buf_p, n, time_p)
* INPUT
* buf_p == pointer to an empty character buffer
* n == number of characters that `buf_p' can hold
* time_p == pointer to an empty utlAbsoluteTime_T structure
* OUTPUT
* buf_p == the formatted time
* RETURNS
* utlSUCCESS for success, utlFAILED for failure
* DESCRIPTION
* Generates a Formated time string.
*---------------------------------------------------------------------------*/
utlReturnCode_T utlFormatTime( char *buf_p,
const size_t n,
const utlAbsoluteTime_P2c time_p)
{
time_t seconds;
size_t length;
seconds = time_p->seconds;
/*--- convert seconds-since-epoch into a tm structure, then a time string ---*/
if (strftime(buf_p, n, "%H:%M:%S", gmtime(&seconds)) <= 0)
{
utlError(utlFormatTime, "Call to %s() failed", "strftime");
return utlFAILED;
}
length = strlen(buf_p);
/*--- enough room for fractional seconds? ---*/
if (length < n)
{
char frac[20];
(void)sprintf(frac, ".%09d UTC", time_p->nanoseconds);
strncat(buf_p, frac, n - length);
length += strlen(frac);
if (length >= n)
*(buf_p + n - 1) = '\0';
}
return utlSUCCESS;
}
/*---------------------------------------------------------------------------*
* FUNCTION
* utlFormatDate(buf_p, n, time_p)
* INPUT
* buf_p == pointer to an empty character buffer
* n == number of characters that `buf_p' can hold
* time_p == pointer to an empty utlAbsoluteTime_T structure
* OUTPUT
* buf_p == the formatted time
* RETURNS
* utlSUCCESS for success, utlFAILED for failure
* DESCRIPTION
* Generates a Formated date string.
*---------------------------------------------------------------------------*/
utlReturnCode_T utlFormatDate( char *buf_p,
const size_t n,
const utlAbsoluteTime_P2c time_p)
{
time_t seconds;
size_t length;
seconds = time_p->seconds;
/*--- convert seconds-since-epoch into a tm structure, then a date string ---*/
if (strftime(buf_p, n, "%G-%m-%d", gmtime(&seconds)) <= 0)
{
utlError(utlFormatDate, "Call to %s() failed", "strftime");
return utlFAILED;
}
length = strlen(buf_p);
/*--- enough room for timezone info? ---*/
if (length < n)
{
strncat(buf_p, " UTC", n - length);
length += strlen(" UTC");
if (length >= n)
*(buf_p + n - 1) = '\0';
}
return utlSUCCESS;
}
/*---------------------------------------------------------------------------*
* FUNCTION
* utlFormatDateTime(buf_p, n, time_p)
* INPUT
* buf_p == pointer to an empty character buffer
* n == number of characters that `buf_p' can hold
* time_p == pointer to an empty utlAbsoluteTime_T structure
* OUTPUT
* buf_p == the formatted time
* RETURNS
* utlSUCCESS for success, utlFAILED for failure
* DESCRIPTION
* Generates a Formated date/time string.
*---------------------------------------------------------------------------*/
utlReturnCode_T utlFormatDateTime( char *buf_p,
const size_t n,
const utlAbsoluteTime_P2c time_p)
{
time_t seconds;
size_t length;
seconds = time_p->seconds;
/*--- convert seconds-since-epoch into a tm structure, then a time string ---*/
if (strftime(buf_p, n, "%G-%m-%d %H:%M:%S", gmtime(&seconds)) <= 0)
{
utlError(utlFormatDateTime, "Call to %s() failed", "strftime");
return utlFAILED;
}
length = strlen(buf_p);
/*--- enough room for fractional seconds and timezone info? ---*/
if (length < n)
{
char frac[20];
(void)sprintf(frac, ".%09d UTC", time_p->nanoseconds);
strncat(buf_p, frac, n - length);
length += strlen(frac);
if (length >= n)
*(buf_p + n - 1) = '\0';
}
return utlSUCCESS;
}
/*---------------------------------------------------------------------------*
* FUNCTION
* utlPause(period_p)
* INPUT
* period_p == pointer to an empty utlRelativeTime_T structure
* OUTPUT
* buf_p == the formatted time
* RETURNS
* utlSUCCESS for succes, utlFAILED for failure
* DESCRIPTION
* Pauses execution for the specified period of time. Note that this
* call blocks for the duration of the time-out.
*---------------------------------------------------------------------------*/
utlReturnCode_T utlPause(const utlRelativeTime_P2c period_p)
{
utlAssert(period_p != NULL);
#ifdef USE_POSIX_API
{
struct timespec timeout;
timeout.tv_sec = period_p->seconds;
timeout.tv_nsec = period_p->nanoseconds;
/*--- uninterrupted sleep ---*/
for (;; )
{
struct timespec time_left;
time_left.tv_sec = 0;
time_left.tv_nsec = 0;
if (nanosleep(&timeout, &time_left) == 0)
break;
if (errno != EINTR)
{
utlError(utlPause, "Call to %s() failed, errno=%d", "nanosleep", errno);
return utlFAILED;
}
timeout = time_left;
}
}
#else
{
struct timeval timeout;
timeout.tv_sec = period_p->seconds;
timeout.tv_usec = period_p->nanoseconds / 1000;
if (select(0, NULL, NULL, NULL, &timeout) == -1)
{
utlError(utlPause1, "call to select failed: %s", strerror(errno));
return utlFAILED;
}
}
#endif
return utlSUCCESS;
}
#ifdef utlTEST
/*---------------------------------------------------------------------------*
* FUNCTION
* timeTest()
* INPUT
* none
* OUTPUT
* none
* RETURNS
* "true" for pass, "false" for failure
*---------------------------------------------------------------------------*/
bool timeTest(void)
{
utlAbsoluteTime_T time;
char buf[50];
/*--- test utlCurrentTime() ---------------------------------------------*/
if (utlCurrentTime(&time) != utlSUCCESS)
{
(void)fprintf(stderr, "timeTest: utlCurrentTime() failed\n");
return false;
}
/*--- test utlFormatTime() ---------------------------------------------*/
if (utlFormatTime(buf, sizeof(buf), &time) != utlSUCCESS)
{
(void)fprintf(stderr, "timeTest: utlFormatTime() failed\n");
return false;
}
printf("time: %s\n", buf);
/*--- test utlFormatDate() ---------------------------------------------*/
if (utlFormatDate(buf, sizeof(buf), &time) != utlSUCCESS)
{
(void)fprintf(stderr, "timeTest: utlFormatTime() failed\n");
return false;
}
printf("date: %s\n", buf);
/*--- test utlFormatDateTime() -----------------------------------------*/
if (utlFormatDateTime(buf, sizeof(buf), &time) != utlSUCCESS)
{
(void)fprintf(stderr, "timeTest: utlFormatTime() failed\n");
return false;
}
printf("date & time: %s\n", buf);
return true;
}
#endif /* utlTEST */