/** * GMyth Library * * @file gmyth/gmyth_util.c * * @brief

This component provides utility functions. * * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. * @author Hallyson Luiz de Morais Melo * *//* * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 Lesser 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 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define _XOPEN_SOURCE #define _XOPEN_SOURCE_EXTENDED #define __USE_MISC #include #include #include #include #include #include "gmyth.h" #if !GLIB_CHECK_VERSION (2, 10, 0) gchar * g_time_val_to_iso8601 (GTimeVal *time_); gboolean g_time_val_from_iso8601 (const gchar *iso_date, GTimeVal *time_); void g_date_set_time_val (GDate *date, GTimeVal *timeval); #endif static GStaticMutex mutex = G_STATIC_MUTEX_INIT; /** Converts a time_t struct in a GString at ISO standard format * (e.g. 2006-07-20T09:56:41). * * The returned GString memory should be deallocated from * the calling function. * * @param time_value the time value to be converted * @return GString* the converted isoformat string */ GString* gmyth_util_time_to_isoformat (time_t time_value) { struct tm tm_time; GString *result; g_static_mutex_lock ( &mutex ); if (localtime_r(&time_value, &tm_time) == NULL) { g_static_mutex_unlock ( &mutex ); g_warning ("gmyth_util_time_to_isoformat convertion error!\n"); return NULL; } result = g_string_sized_new(20); g_string_printf(result, "%04d-%02d-%02dT%02d:%02d:%02d", tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec); gmyth_debug( "Result (ISO 8601) = %s", result->str ); g_static_mutex_unlock ( &mutex ); return result; } /** Converts a time_t struct in a GString at ISO standard format * (e.g. 2006-07-20T09:56:41). * * The returned GString memory should be deallocated from * the calling function. * * @param time_value the GTimeValue to be converted * @return GString* the converted isoformat string */ gchar* gmyth_util_time_to_isoformat_from_time_val_fmt ( const gchar *fmt_string, const GTimeVal* time_val ) { gchar *result = NULL; struct tm *tm_time = NULL; gint buffer_len = 0; g_return_val_if_fail( fmt_string != NULL, NULL ); g_return_val_if_fail( time_val != NULL, NULL ); time_t time = time_val->tv_sec;// + (gint)( time_val->tv_usec / G_USEC_PER_SEC ); tm_time = g_malloc0( sizeof(struct tm) ); g_static_mutex_lock ( &mutex ); if ( NULL == localtime_r( &time, tm_time ) ) { g_warning ("gmyth_util_time_to_isoformat convertion error!\n"); } else { // we first check the return of strftime to allocate a buffer of the correct size buffer_len = strftime( NULL, SSIZE_MAX, fmt_string, tm_time ); if ( buffer_len > 0 ) { result = g_malloc0( buffer_len + 1 ); if( result == NULL ){ g_static_mutex_unlock ( &mutex ); g_warning ("gmyth_util_time_to_isoformat convertion error!\n"); return NULL; } strftime( result, buffer_len + 1, fmt_string, tm_time ); gmyth_debug( "Dateline (ISO result): %s", result ); } } gmyth_debug( "Result (strftime) = %s", result ); //strptime( result, "%Y-%m-%dT%H:%M:%SZ", tm_time ); //strftime( result, strlen(result), fmt_string, tm_time ); g_static_mutex_unlock ( &mutex ); gmyth_debug( "Result (ISO 8601) = %s", result ); return result; } /** Converts a time_t struct in a GString at ISO standard format * (e.g. 2006-07-20 09:56:41). * * The returned GString memory should be deallocated from * the calling function. * * @param time_value the GTimeValue to be converted * @return GString* the converted isoformat string */ gchar* gmyth_util_time_to_isoformat_from_time_val ( const GTimeVal* time ) { gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%d %H:%M:%S", time ); //result[10] = ' '; //result[ strlen(result) - 1] = '\0'; return result; } /** Converts a time_t struct in a GString at ISO standard format 2 * (e.g. 2006-07-20T09:56:41). * * The returned GString memory should be deallocated from * the calling function. * * @param time_value the GTimeValue to be converted * @return GString* the converted isoformat string */ gchar* gmyth_util_time_to_mythformat_from_time_val ( const GTimeVal* time ) { gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%dT%H:%M:%S", time ); return result; } /** Converts a time_t struct in a GString at ISO standard format * (e.g. 2006-07-20T09:56:41). * * The returned GString memory should be deallocated from * the calling function. * * @param time_value the GTimeValue to be converted * @return GString* the converted isoformat string */ gchar* gmyth_util_time_to_string_only_date ( const GTimeVal* time ) { gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%d", time ); //result[10] = ' '; //result[ strlen(result) - 1] = '\0'; return result; } /** Converts a time_t struct in a GString at ISO standard format * (e.g. 2006-07-20T09:56:41). * * The returned GString memory should be deallocated from * the calling function. * * @param time_value the GTimeValue to be converted * @return GString* the converted isoformat string */ gchar* gmyth_util_time_to_string_only_time ( const GTimeVal* time ) { gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%H:%M:%S", time ); //result[10] = ' '; //result[ strlen(result) - 1] = '\0'; return result; } /** Converts a time_t struct in a GString to the following * format (e.g. 2006-07-20 09:56:41). * * The returned GString memory should be deallocated from * the calling function. * * @param time_value the time value to be converted * @return GString* the converted string */ GString* gmyth_util_time_to_string (time_t time_value) { GString *result = gmyth_util_time_to_isoformat (time_value); result->str[10] = ' '; result->str[ strlen(result->str) - 1] = '\0'; return result; } /** Converts a time_t struct in a GString to the following * format (e.g. 2006-07-20 09:56:41). * * The returned GString memory should be deallocated from * the calling function. * * @param time_value the time value to be converted * @return GString* the converted string */ gchar* gmyth_util_time_to_string_from_time_val ( const GTimeVal *time_val ) { gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt ( "%Y-%m-%d %H:%M:%S", time_val ); //result[10] = ' '; return result; } /** Converts a GString in the following format * (e.g. 2006-07-20 09:56:41) to a time_t struct. * * @param time_str the string to be converted * @return time_t the time converted value */ time_t gmyth_util_string_to_time (GString* time_str) { gint year, month, day, hour, min, sec; gmyth_debug( "[%s] time_str = %s. [%s]", __FUNCTION__, time_str != NULL ? time_str->str : "[time string is NULL!]", time_str->str ); if ( sscanf (time_str->str, "%04d-%02d-%02d %02d:%02d:%02d", &year, &month, &day, &hour, &min, &sec) < 3 ) { g_warning ("GMythUtil: isoformat_to_time converter error!\n"); return 0; } g_static_mutex_lock ( &mutex ); struct tm* tm_time = g_malloc0( sizeof(struct tm) ); tm_time->tm_year = year - 1900; tm_time->tm_mon = month - 1; tm_time->tm_mday = day; tm_time->tm_hour = hour; tm_time->tm_min = min; tm_time->tm_sec = sec; g_static_mutex_unlock ( &mutex ); return mktime( tm_time ); } /** Converts a GString in the following format * (e.g. 2006-07-20 09:56:41) to a time_t struct. * * @param time_str the string to be converted * @return time_t the time converted value */ struct tm* gmyth_util_time_val_to_date ( const GTimeVal* time ) { struct tm *date = g_malloc0( sizeof( struct tm ) ); time_t time_micros = time->tv_sec;// + (gint)( time->tv_usec / G_USEC_PER_SEC ); if ( NULL == date ) { g_warning ( "GMythUtil: GDate *gmyth_util_time_val_to_date (GTimeVal* time) - converter error!\n" ); return NULL; } if ( NULL == localtime_r( &time_micros, date ) ) { g_warning ( "gmyth_util_time_to_isoformat convertion error!\n" ); return NULL; } gmyth_debug( "Converted from GTimeVal == %s to GDate", asctime( date ) ); return date; } /** Converts a GString in the following format * (e.g. 2006-07-20 09:56:41) to a time_t struct. * * @param time_str the string to be converted * @return time_t the time converted value */ GTimeVal* gmyth_util_string_to_time_val_fmt ( const gchar *fmt_string, const gchar* time_str ) { GTimeVal *time = g_new0( GTimeVal, 1 ); struct tm* tm_time = NULL; time_t time_micros; gint result; gmyth_debug( "[%s] time_str = %s. [%s]", time_str, time_str != NULL ? time_str : "[time string is NULL!]", time_str ); if ( NULL == time_str ) { g_warning ("GMythUtil: isoformat_to_time converter error!\n"); return NULL; } g_static_mutex_lock ( &mutex ); tm_time = g_malloc0( sizeof(struct tm) ); /* we first check the return of strftime to allocate a buffer of the correct size */ result = strptime( time_str, "%Y-%m-%dT%H:%M:%S", tm_time ); if ( NULL == result ) { /* we first check the return of strftime to allocate a buffer of the correct size */ result = strptime( time_str, "%Y-%m-%dT%H:%M:%SZ", tm_time ); if ( NULL == result ) { /* we first check the return of strftime to allocate a buffer of the correct size */ result = strptime( time_str, "%Y-%m-%d %H:%M:%S", tm_time ); if ( NULL == result ) { g_static_mutex_unlock ( &mutex ); gmyth_debug( "Dateline (ISO result): %s", result ); time = NULL; //goto done; } } } time_micros = mktime( tm_time ); time->tv_sec = time_micros; // + (gint)( time_val->tv_usec / G_USEC_PER_SEC ); gmyth_debug( "After mktime call... = %s", asctime(tm_time) ); g_static_mutex_unlock ( &mutex ); return time; } /** Converts a GString in the following format * (e.g. 2006-07-20 09:56:41) to a time_t struct. * * @param time_str the string to be converted * @return time_t the time converted value */ GTimeVal* gmyth_util_string_to_time_val ( const gchar* time_str ) { GTimeVal *time = gmyth_util_string_to_time_val_fmt ( "%Y-%m-%d %H:%M:%S", time_str ); return time; } /** Decodes a long long variable from the string list * format of the myhtprotocol. * * @param strlist the string list of mythprotocol values * @param offset the list node offset of the long long variable * @return gint64 the long long converted value */ gint64 gmyth_util_decode_long_long(GMythStringList *strlist, guint offset) { gint64 ret_value = 0LL; g_return_val_if_fail( strlist != NULL, ret_value ); if ( offset > gmyth_string_list_length( strlist )) g_printerr( "[%s] Offset is greater than the Stringlist (offset = %d)!\n", __FUNCTION__, offset ); g_return_val_if_fail( offset < gmyth_string_list_length( strlist ), ret_value ); gint l1 = gmyth_string_list_get_int( strlist, offset ); gint l2 = gmyth_string_list_get_int( strlist, offset + 1 ); ret_value = (l2 /*& 0xffffffffLL*/) | ( (gint64)l1 << 32 ); return ret_value; } gboolean gmyth_util_file_exists (GMythBackendInfo *backend_info, const gchar* filename) { GMythSocket *socket; gboolean res; socket = gmyth_socket_new (); res = gmyth_socket_connect_to_backend (socket, backend_info->hostname, backend_info->port, TRUE); if (res == TRUE) { GMythStringList *slist; GMythProgramInfo *program = NULL; program = gmyth_program_info_new(); program->pathname = g_string_new (filename); slist = gmyth_string_list_new (); gmyth_string_list_append_char_array (slist, "QUERY_CHECKFILE"); gmyth_program_info_to_string_list (program, slist); gmyth_socket_sendreceive_stringlist (socket, slist); res = (gmyth_string_list_get_int (slist, 0) == 1); g_object_unref (program); g_object_unref (slist); gmyth_socket_close_connection (socket); } g_object_unref (socket); return res; } #if !GLIB_CHECK_VERSION (2, 10, 0) /* Hacked from glib 2.10 */ static time_t mktime_utc (struct tm *tm) { time_t retval; #ifndef HAVE_TIMEGM static const gint days_before[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; #endif #ifndef HAVE_TIMEGM if (tm->tm_mon < 0 || tm->tm_mon > 11) return (time_t) -1; retval = (tm->tm_year - 70) * 365; retval += (tm->tm_year - 68) / 4; retval += days_before[tm->tm_mon] + tm->tm_mday - 1; if (tm->tm_year % 4 == 0 && tm->tm_mon < 2) retval -= 1; retval = ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 + tm->tm_sec; #else retval = timegm (tm); #endif /* !HAVE_TIMEGM */ return retval; } gboolean g_time_val_from_iso8601 (const gchar *iso_date, GTimeVal *time_) { struct tm tm; long val; g_return_val_if_fail (iso_date != NULL, FALSE); g_return_val_if_fail (time_ != NULL, FALSE); val = strtoul (iso_date, (char **)&iso_date, 10); if (*iso_date == '-') { /* YYYY-MM-DD */ tm.tm_year = val - 1900; iso_date++; tm.tm_mon = strtoul (iso_date, (char **)&iso_date, 10) - 1; if (*iso_date++ != '-') return FALSE; tm.tm_mday = strtoul (iso_date, (char **)&iso_date, 10); } else { /* YYYYMMDD */ tm.tm_mday = val % 100; tm.tm_mon = (val % 10000) / 100 - 1; tm.tm_year = val / 10000 - 1900; } if (*iso_date++ != 'T') return FALSE; val = strtoul (iso_date, (char **)&iso_date, 10); if (*iso_date == ':') { /* hh:mm:ss */ tm.tm_hour = val; iso_date++; tm.tm_min = strtoul (iso_date, (char **)&iso_date, 10); if (*iso_date++ != ':') return FALSE; tm.tm_sec = strtoul (iso_date, (char **)&iso_date, 10); } else { /* hhmmss */ tm.tm_sec = val % 100; tm.tm_min = (val % 10000) / 100; tm.tm_hour = val / 10000; } time_->tv_sec = mktime_utc (&tm); time_->tv_usec = 1; if (*iso_date == '.') time_->tv_usec = strtoul (iso_date + 1, (char **)&iso_date, 10); if (*iso_date == '+' || *iso_date == '-') { gint sign = (*iso_date == '+') ? -1 : 1; val = 60 * strtoul (iso_date + 1, (char **)&iso_date, 10); if (*iso_date == ':') val = 60 * val + strtoul (iso_date + 1, NULL, 10); else val = 60 * (val / 100) + (val % 100); time_->tv_sec += (time_t) (val * sign); } return TRUE; } gchar * g_time_val_to_iso8601 (GTimeVal *time_) { gchar *retval; g_return_val_if_fail (time_->tv_usec >= 0 && time_->tv_usec < G_USEC_PER_SEC, NULL); #define ISO_8601_LEN 21 #define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ" retval = g_new0 (gchar, ISO_8601_LEN + 1); strftime (retval, ISO_8601_LEN, ISO_8601_FORMAT, gmtime (&(time_->tv_sec))); return retval; } /* Hacked from glib 2.10 */ void g_date_set_time_t (GDate *date, time_t timet) { struct tm tm; g_return_if_fail (date != NULL); #ifdef HAVE_LOCALTIME_R localtime_r (&timet, &tm); #else { struct tm *ptm = localtime (&timet); if (ptm == NULL) { /* Happens at least in Microsoft's C library if you pass a * negative time_t. Use 2000-01-01 as default date. */ #ifndef G_DISABLE_CHECKS g_return_if_fail_warning (G_LOG_DOMAIN, "g_date_set_time", "ptm != NULL"); #endif tm.tm_mon = 0; tm.tm_mday = 1; tm.tm_year = 100; } else memcpy ((void *) &tm, (void *) ptm, sizeof(struct tm)); } #endif date->julian = FALSE; date->month = tm.tm_mon + 1; date->day = tm.tm_mday; date->year = tm.tm_year + 1900; g_return_if_fail (g_date_valid_dmy (date->day, date->month, date->year)); date->dmy = TRUE; } void g_date_set_time_val (GDate *date, GTimeVal *timeval) { g_date_set_time_t (date, (time_t) timeval->tv_sec); } #endif