time_utils.c

Go to the documentation of this file.
00001 /*
00002  * This file is part of liberutils.
00003  *
00004  * liberutils is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation, either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * liberutils is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 /**
00019  * Copyright (C) 2009 iRex Technologies B.V.
00020  * All rights reserved.
00021  */
00022 
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <sys/time.h>
00026 #include <assert.h>
00027 #include <unistd.h>
00028 #include <time.h>
00029 #include <glib.h>
00030 //#include <gtk/gtk.h>
00031 
00032 #include <curl/curl.h>
00033 #include <curl/types.h>
00034 #include <curl/easy.h>
00035 
00036 #include "log.h"
00037 #include "time_utils.h"
00038 
00039 #define MINUTES(x) 60*x
00040 #define HOURS(x)   60*60*x
00041 
00042 #define DATE_STRING_LENGTH        64
00043 
00044 #define TZ_FILES_DIR      "/usr/share/zoneinfo/Etc/"
00045 
00046 #define DEFAULT_TIMEZONE_OFFSET   0
00047 #define DEFAULT_TIMEZONE_NAME     "GMT+00:00"
00048 #define DST_FLAG                  "DST"
00049 
00050 
00051 // Header of timezone files, you can find them in /usr/share/zoneinfo
00052 struct tzhead
00053 {
00054     char tzh_magic[4];       /* TZ_MAGIC */
00055     char tzh_reserved[16];   /* reserved for future use */
00056     char tzh_ttisgmtcnt[4];  /* coded number of trans. time flags */
00057     char tzh_ttisstdcnt[4];  /* coded number of trans. time flags */
00058     char tzh_leapcnt[4];     /* coded number of leap seconds */
00059     char tzh_timecnt[4];     /* coded number of transition times */
00060     char tzh_typecnt[4];     /* coded number of local time types */
00061     char tzh_charcnt[4];     /* coded number of abbr. chars */
00062 };
00063 
00064 
00065 typedef struct {
00066     char *memory;
00067     size_t size;
00068 } MemoryStruct;
00069 
00070 
00071 static void *myrealloc(void *ptr, size_t size)
00072 {
00073     if (ptr) return realloc(ptr, size);
00074     else return malloc(size);
00075 }
00076 
00077 
00078 static size_t writer(void *ptr, size_t size, size_t nmemb, void *data)
00079 {
00080     size_t realsize = size * nmemb;
00081     MemoryStruct *mem = (MemoryStruct *)data;
00082 
00083     mem->memory = (char*)myrealloc(mem->memory, mem->size + realsize + 1);
00084     if (mem->memory) 
00085     {
00086         memcpy(&(mem->memory[mem->size]), ptr, realsize);
00087         mem->size += realsize;
00088         mem->memory[mem->size] = 0;
00089     }
00090     return realsize;
00091 }
00092 
00093 
00094 time_t get_server_time()
00095 {
00096     LOGPRINTF("entry");
00097 
00098     MemoryStruct chunk;
00099     chunk.memory = NULL;
00100     chunk.size = 0;
00101 
00102     curl_global_init(CURL_GLOBAL_ALL);
00103     CURL *curl_handle = curl_easy_init();
00104 
00105     curl_easy_setopt(curl_handle, CURLOPT_URL, "http://time.irexnet.com/epoch");
00106     curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer);
00107     curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
00108     curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
00109 
00110     curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_LIMIT, 1);
00111     curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_TIME, 30);
00112     curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 30);
00113 
00114     curl_easy_perform(curl_handle);
00115     curl_easy_cleanup(curl_handle);
00116 
00117     time_t now = 0;
00118     if (chunk.memory != NULL) now = atoi(chunk.memory);
00119 
00120     if (chunk.memory) free(chunk.memory);
00121     curl_global_cleanup();
00122 
00123     return now;
00124 }
00125 
00126 
00127 // returns newly allocated string with current timezone, must be freed by caller
00128 gchar *get_timezone()
00129 {
00130     LOGPRINTF("entry");
00131 
00132     char actual_tzfile[256];
00133     memset(actual_tzfile, 0, sizeof(actual_tzfile));
00134     
00135     // get timezone reference
00136     if (readlink(TZ_FILE, actual_tzfile, sizeof(actual_tzfile)) == -1)
00137     {
00138         ERRORPRINTF("Can't dereference symlink %s, errno [%d][%s]", TZ_FILE, errno, strerror(errno));
00139         return NULL;
00140     }
00141     
00142     // check if it exists
00143     if (!g_file_test(actual_tzfile, G_FILE_TEST_IS_REGULAR))
00144     {
00145         ERRORPRINTF("Can't find symlink target %s", actual_tzfile);
00146         return NULL;
00147     }
00148     
00149     return g_path_get_basename(actual_tzfile);
00150 }
00151 
00152 
00153 gboolean set_timezone(const char* tzname, gboolean is_dst)
00154 {
00155     LOGPRINTF("entry");
00156 
00157     char actual_tzfile[256];
00158 
00159     snprintf(actual_tzfile, 256, "%s%s%s", TZ_FILES_DIR, tzname, is_dst ? DST_FLAG : "");
00160     LOGPRINTF("symlink %s to %s", actual_tzfile, TZ_FILE);
00161     if (g_file_test(TZ_FILE, G_FILE_TEST_EXISTS) && (unlink(TZ_FILE) != 0))
00162     {
00163         ERRORPRINTF("Can't remove %s", TZ_FILE);
00164         return FALSE;
00165     }
00166 
00167     if (symlink(actual_tzfile, TZ_FILE) != 0)
00168     {
00169         ERRORPRINTF("Can't create symlink from %s to %s", actual_tzfile, TZ_FILE);
00170         return FALSE;
00171     }
00172 
00173     return TRUE;    
00174 }
00175 
00176 
00177 // returns index in the timezone table of given tzname and determines DST (optional)
00178 gint get_timezone_index(const char* tzname, gboolean *dst)
00179 {
00180     LOGPRINTF("entry");
00181 
00182     gboolean is_dst;
00183     gint tzindex = -1;
00184     
00185     if (tzname == NULL)
00186     {
00187         tzname = DEFAULT_TIMEZONE_NAME;
00188         WARNPRINTF("No timezone given, use default [%s]", tzname);
00189     }
00190     
00191     int tzlength = strlen(tzname);
00192     is_dst = g_str_has_suffix(tzname, DST_FLAG);
00193     if (is_dst)
00194     {
00195         // ignore DST suffix
00196         tzlength -= strlen(DST_FLAG);
00197     }
00198     
00199     int i;
00200     for (i=0; i<TOTAL_TIMEZONES; i++) 
00201     {
00202         if (strncmp(tzname, timezones[i].tzname, tzlength) == 0)
00203         {
00204             tzindex = i;
00205             break;
00206         }
00207     }
00208 
00209     if (tzindex == -1)
00210     {
00211         WARNPRINTF("Can't find zoneinfo for [%s]", tzname);
00212         tzindex = 12; // default to GMT
00213         is_dst = FALSE;
00214     }
00215     
00216     if (dst)
00217     {
00218         *dst = is_dst;
00219     }
00220     
00221     return tzindex;
00222 }
00223 
00224 
00225 void set_time_utc(time_t utc_time)
00226 {
00227     LOGPRINTF("entry");
00228     
00229     struct timeval tp;
00230     gettimeofday(&tp, NULL);
00231     tp.tv_sec = utc_time;
00232     settimeofday(&tp, NULL);
00233 
00234     system("/sbin/hwclock -w -u");
00235 }
00236 
00237 
00238 gboolean set_time_from_server(void) 
00239 {
00240     LOGPRINTF("entry");
00241     
00242     time_t utc_time = get_server_time();
00243     if (utc_time == 0) {
00244         ERRORPRINTF("Failed to get server time");
00245         return FALSE;
00246     }
00247     
00248     set_time_utc(utc_time);
00249     return TRUE;
00250 }
00251 
Generated by  doxygen 1.6.2-20100208