00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
00052 struct tzhead
00053 {
00054 char tzh_magic[4];
00055 char tzh_reserved[16];
00056 char tzh_ttisgmtcnt[4];
00057 char tzh_ttisstdcnt[4];
00058 char tzh_leapcnt[4];
00059 char tzh_timecnt[4];
00060 char tzh_typecnt[4];
00061 char tzh_charcnt[4];
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
00128 gchar *get_timezone()
00129 {
00130 LOGPRINTF("entry");
00131
00132 char actual_tzfile[256];
00133 memset(actual_tzfile, 0, sizeof(actual_tzfile));
00134
00135
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
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
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
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;
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