$search
00001 /* 00002 * OS specific functions for UNIX/POSIX systems 00003 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "os.h" 00018 00019 #ifdef WPA_TRACE 00020 00021 #include "common.h" 00022 #include "list.h" 00023 #include "wpa_debug.h" 00024 #include "trace.h" 00025 00026 static struct dl_list alloc_list; 00027 00028 #define ALLOC_MAGIC 0xa84ef1b2 00029 #define FREED_MAGIC 0x67fd487a 00030 00031 struct os_alloc_trace { 00032 unsigned int magic; 00033 struct dl_list list; 00034 size_t len; 00035 WPA_TRACE_INFO 00036 }; 00037 00038 #endif /* WPA_TRACE */ 00039 00040 00041 void os_sleep(os_time_t sec, os_time_t usec) 00042 { 00043 if (sec) 00044 sleep(sec); 00045 if (usec) 00046 usleep(usec); 00047 } 00048 00049 00050 int os_get_time(struct os_time *t) 00051 { 00052 int res; 00053 struct timeval tv; 00054 res = gettimeofday(&tv, NULL); 00055 t->sec = tv.tv_sec; 00056 t->usec = tv.tv_usec; 00057 return res; 00058 } 00059 00060 00061 int os_mktime(int year, int month, int day, int hour, int min, int sec, 00062 os_time_t *t) 00063 { 00064 struct tm tm, *tm1; 00065 time_t t_local, t1, t2; 00066 os_time_t tz_offset; 00067 00068 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || 00069 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || 00070 sec > 60) 00071 return -1; 00072 00073 memset(&tm, 0, sizeof(tm)); 00074 tm.tm_year = year - 1900; 00075 tm.tm_mon = month - 1; 00076 tm.tm_mday = day; 00077 tm.tm_hour = hour; 00078 tm.tm_min = min; 00079 tm.tm_sec = sec; 00080 00081 t_local = mktime(&tm); 00082 00083 /* figure out offset to UTC */ 00084 tm1 = localtime(&t_local); 00085 if (tm1) { 00086 t1 = mktime(tm1); 00087 tm1 = gmtime(&t_local); 00088 if (tm1) { 00089 t2 = mktime(tm1); 00090 tz_offset = t2 - t1; 00091 } else 00092 tz_offset = 0; 00093 } else 00094 tz_offset = 0; 00095 00096 *t = (os_time_t) t_local - tz_offset; 00097 return 0; 00098 } 00099 00100 00101 #ifdef __APPLE__ 00102 #include <fcntl.h> 00103 static int os_daemon(int nochdir, int noclose) 00104 { 00105 int devnull; 00106 00107 if (chdir("/") < 0) 00108 return -1; 00109 00110 devnull = open("/dev/null", O_RDWR); 00111 if (devnull < 0) 00112 return -1; 00113 00114 if (dup2(devnull, STDIN_FILENO) < 0) { 00115 close(devnull); 00116 return -1; 00117 } 00118 00119 if (dup2(devnull, STDOUT_FILENO) < 0) { 00120 close(devnull); 00121 return -1; 00122 } 00123 00124 if (dup2(devnull, STDERR_FILENO) < 0) { 00125 close(devnull); 00126 return -1; 00127 } 00128 00129 return 0; 00130 } 00131 #else /* __APPLE__ */ 00132 #define os_daemon daemon 00133 #endif /* __APPLE__ */ 00134 00135 00136 int os_daemonize(const char *pid_file) 00137 { 00138 #ifdef __uClinux__ 00139 return -1; 00140 #else /* __uClinux__ */ 00141 if (os_daemon(0, 0)) { 00142 perror("daemon"); 00143 return -1; 00144 } 00145 00146 if (pid_file) { 00147 FILE *f = fopen(pid_file, "w"); 00148 if (f) { 00149 fprintf(f, "%u\n", getpid()); 00150 fclose(f); 00151 } 00152 } 00153 00154 return -0; 00155 #endif /* __uClinux__ */ 00156 } 00157 00158 00159 void os_daemonize_terminate(const char *pid_file) 00160 { 00161 if (pid_file) 00162 unlink(pid_file); 00163 } 00164 00165 00166 int os_get_random(unsigned char *buf, size_t len) 00167 { 00168 FILE *f; 00169 size_t rc; 00170 00171 f = fopen("/dev/urandom", "rb"); 00172 if (f == NULL) { 00173 printf("Could not open /dev/urandom.\n"); 00174 return -1; 00175 } 00176 00177 rc = fread(buf, 1, len, f); 00178 fclose(f); 00179 00180 return rc != len ? -1 : 0; 00181 } 00182 00183 00184 unsigned long os_random(void) 00185 { 00186 return random(); 00187 } 00188 00189 00190 char * os_rel2abs_path(const char *rel_path) 00191 { 00192 char *buf = NULL, *cwd, *ret; 00193 size_t len = 128, cwd_len, rel_len, ret_len; 00194 int last_errno; 00195 00196 if (rel_path[0] == '/') 00197 return os_strdup(rel_path); 00198 00199 for (;;) { 00200 buf = os_malloc(len); 00201 if (buf == NULL) 00202 return NULL; 00203 cwd = getcwd(buf, len); 00204 if (cwd == NULL) { 00205 last_errno = errno; 00206 os_free(buf); 00207 if (last_errno != ERANGE) 00208 return NULL; 00209 len *= 2; 00210 if (len > 2000) 00211 return NULL; 00212 } else { 00213 buf[len - 1] = '\0'; 00214 break; 00215 } 00216 } 00217 00218 cwd_len = os_strlen(cwd); 00219 rel_len = os_strlen(rel_path); 00220 ret_len = cwd_len + 1 + rel_len + 1; 00221 ret = os_malloc(ret_len); 00222 if (ret) { 00223 os_memcpy(ret, cwd, cwd_len); 00224 ret[cwd_len] = '/'; 00225 os_memcpy(ret + cwd_len + 1, rel_path, rel_len); 00226 ret[ret_len - 1] = '\0'; 00227 } 00228 os_free(buf); 00229 return ret; 00230 } 00231 00232 00233 int os_program_init(void) 00234 { 00235 #ifdef WPA_TRACE 00236 dl_list_init(&alloc_list); 00237 #endif /* WPA_TRACE */ 00238 return 0; 00239 } 00240 00241 00242 void os_program_deinit(void) 00243 { 00244 #ifdef WPA_TRACE 00245 struct os_alloc_trace *a; 00246 unsigned long total = 0; 00247 dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) { 00248 total += a->len; 00249 if (a->magic != ALLOC_MAGIC) { 00250 wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x " 00251 "len %lu", 00252 a, a->magic, (unsigned long) a->len); 00253 continue; 00254 } 00255 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu", 00256 a, (unsigned long) a->len); 00257 wpa_trace_dump("memleak", a); 00258 } 00259 if (total) 00260 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes", 00261 (unsigned long) total); 00262 #endif /* WPA_TRACE */ 00263 } 00264 00265 00266 int os_setenv(const char *name, const char *value, int overwrite) 00267 { 00268 return setenv(name, value, overwrite); 00269 } 00270 00271 00272 int os_unsetenv(const char *name) 00273 { 00274 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \ 00275 defined(__OpenBSD__) 00276 unsetenv(name); 00277 return 0; 00278 #else 00279 return unsetenv(name); 00280 #endif 00281 } 00282 00283 00284 char * os_readfile(const char *name, size_t *len) 00285 { 00286 FILE *f; 00287 char *buf; 00288 00289 f = fopen(name, "rb"); 00290 if (f == NULL) 00291 return NULL; 00292 00293 fseek(f, 0, SEEK_END); 00294 *len = ftell(f); 00295 fseek(f, 0, SEEK_SET); 00296 00297 buf = os_malloc(*len); 00298 if (buf == NULL) { 00299 fclose(f); 00300 return NULL; 00301 } 00302 00303 if (fread(buf, 1, *len, f) != *len) { 00304 fclose(f); 00305 os_free(buf); 00306 return NULL; 00307 } 00308 00309 fclose(f); 00310 00311 return buf; 00312 } 00313 00314 00315 #ifndef WPA_TRACE 00316 void * os_zalloc(size_t size) 00317 { 00318 return calloc(1, size); 00319 } 00320 #endif /* WPA_TRACE */ 00321 00322 00323 size_t os_strlcpy(char *dest, const char *src, size_t siz) 00324 { 00325 const char *s = src; 00326 size_t left = siz; 00327 00328 if (left) { 00329 /* Copy string up to the maximum size of the dest buffer */ 00330 while (--left != 0) { 00331 if ((*dest++ = *s++) == '\0') 00332 break; 00333 } 00334 } 00335 00336 if (left == 0) { 00337 /* Not enough room for the string; force NUL-termination */ 00338 if (siz != 0) 00339 *dest = '\0'; 00340 while (*s++) 00341 ; /* determine total src string length */ 00342 } 00343 00344 return s - src - 1; 00345 } 00346 00347 00348 #ifdef WPA_TRACE 00349 00350 void * os_malloc(size_t size) 00351 { 00352 struct os_alloc_trace *a; 00353 a = malloc(sizeof(*a) + size); 00354 if (a == NULL) 00355 return NULL; 00356 a->magic = ALLOC_MAGIC; 00357 dl_list_add(&alloc_list, &a->list); 00358 a->len = size; 00359 wpa_trace_record(a); 00360 return a + 1; 00361 } 00362 00363 00364 void * os_realloc(void *ptr, size_t size) 00365 { 00366 struct os_alloc_trace *a; 00367 size_t copy_len; 00368 void *n; 00369 00370 if (ptr == NULL) 00371 return os_malloc(size); 00372 00373 a = ptr - sizeof(*a); 00374 if (a->magic != ALLOC_MAGIC) { 00375 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s", 00376 a, a->magic, 00377 a->magic == FREED_MAGIC ? " (already freed)" : ""); 00378 wpa_trace_show("Invalid os_realloc() call"); 00379 abort(); 00380 } 00381 n = os_malloc(size); 00382 if (n == NULL) 00383 return NULL; 00384 copy_len = a->len; 00385 if (copy_len > size) 00386 copy_len = size; 00387 os_memcpy(n, a + 1, copy_len); 00388 os_free(ptr); 00389 return n; 00390 } 00391 00392 00393 void os_free(void *ptr) 00394 { 00395 struct os_alloc_trace *a; 00396 00397 if (ptr == NULL) 00398 return; 00399 a = ptr - sizeof(*a); 00400 if (a->magic != ALLOC_MAGIC) { 00401 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s", 00402 a, a->magic, 00403 a->magic == FREED_MAGIC ? " (already freed)" : ""); 00404 wpa_trace_show("Invalid os_free() call"); 00405 abort(); 00406 } 00407 dl_list_del(&a->list); 00408 a->magic = FREED_MAGIC; 00409 00410 wpa_trace_check_ref(ptr); 00411 free(a); 00412 } 00413 00414 00415 void * os_zalloc(size_t size) 00416 { 00417 void *ptr = os_malloc(size); 00418 if (ptr) 00419 os_memset(ptr, 0, size); 00420 return ptr; 00421 } 00422 00423 00424 char * os_strdup(const char *s) 00425 { 00426 size_t len; 00427 char *d; 00428 len = os_strlen(s); 00429 d = os_malloc(len + 1); 00430 if (d == NULL) 00431 return NULL; 00432 os_memcpy(d, s, len); 00433 d[len] = '\0'; 00434 return d; 00435 } 00436 00437 #endif /* WPA_TRACE */