2 * OS specific functions for UNIX/POSIX systems
3 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
15 #include <sys/capability.h>
16 #include <sys/prctl.h>
17 #include <private/android_filesystem_config.h>
25 #include "wpa_debug.h"
29 static struct dl_list alloc_list;
31 #define ALLOC_MAGIC 0xa84ef1b2
32 #define FREED_MAGIC 0x67fd487a
34 struct os_alloc_trace {
41 #endif /* WPA_TRACE */
44 void os_sleep(os_time_t sec, os_time_t usec)
53 int os_get_time(struct os_time *t)
57 res = gettimeofday(&tv, NULL);
64 int os_get_reltime(struct os_reltime *t)
66 #if defined(CLOCK_BOOTTIME)
67 static clockid_t clock_id = CLOCK_BOOTTIME;
68 #elif defined(CLOCK_MONOTONIC)
69 static clockid_t clock_id = CLOCK_MONOTONIC;
71 static clockid_t clock_id = CLOCK_REALTIME;
77 res = clock_gettime(clock_id, &ts);
80 t->usec = ts.tv_nsec / 1000;
86 clock_id = CLOCK_MONOTONIC;
89 #ifdef CLOCK_MONOTONIC
91 clock_id = CLOCK_REALTIME;
101 int os_mktime(int year, int month, int day, int hour, int min, int sec,
105 time_t t_local, t1, t2;
108 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
109 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
113 memset(&tm, 0, sizeof(tm));
114 tm.tm_year = year - 1900;
115 tm.tm_mon = month - 1;
121 t_local = mktime(&tm);
123 /* figure out offset to UTC */
124 tm1 = localtime(&t_local);
127 tm1 = gmtime(&t_local);
136 *t = (os_time_t) t_local - tz_offset;
141 int os_gmtime(os_time_t t, struct os_tm *tm)
149 tm->sec = tm2->tm_sec;
150 tm->min = tm2->tm_min;
151 tm->hour = tm2->tm_hour;
152 tm->day = tm2->tm_mday;
153 tm->month = tm2->tm_mon + 1;
154 tm->year = tm2->tm_year + 1900;
161 static int os_daemon(int nochdir, int noclose)
168 devnull = open("/dev/null", O_RDWR);
172 if (dup2(devnull, STDIN_FILENO) < 0) {
177 if (dup2(devnull, STDOUT_FILENO) < 0) {
182 if (dup2(devnull, STDERR_FILENO) < 0) {
189 #else /* __APPLE__ */
190 #define os_daemon daemon
191 #endif /* __APPLE__ */
194 int os_daemonize(const char *pid_file)
196 #if defined(__uClinux__) || defined(__sun__)
198 #else /* defined(__uClinux__) || defined(__sun__) */
199 if (os_daemon(0, 0)) {
205 FILE *f = fopen(pid_file, "w");
207 fprintf(f, "%u\n", getpid());
213 #endif /* defined(__uClinux__) || defined(__sun__) */
217 void os_daemonize_terminate(const char *pid_file)
224 int os_get_random(unsigned char *buf, size_t len)
229 f = fopen("/dev/urandom", "rb");
231 printf("Could not open /dev/urandom.\n");
235 rc = fread(buf, 1, len, f);
238 return rc != len ? -1 : 0;
242 unsigned long os_random(void)
248 char * os_rel2abs_path(const char *rel_path)
250 char *buf = NULL, *cwd, *ret;
251 size_t len = 128, cwd_len, rel_len, ret_len;
257 if (rel_path[0] == '/')
258 return os_strdup(rel_path);
261 buf = os_malloc(len);
264 cwd = getcwd(buf, len);
268 if (last_errno != ERANGE)
279 cwd_len = os_strlen(cwd);
280 rel_len = os_strlen(rel_path);
281 ret_len = cwd_len + 1 + rel_len + 1;
282 ret = os_malloc(ret_len);
284 os_memcpy(ret, cwd, cwd_len);
286 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
287 ret[ret_len - 1] = '\0';
294 int os_program_init(void)
298 * We ignore errors here since errors are normal if we
299 * are already running as non-root.
301 #ifdef ANDROID_SETGROUPS_OVERRIDE
302 gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
303 #else /* ANDROID_SETGROUPS_OVERRIDE */
304 gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
305 #endif /* ANDROID_SETGROUPS_OVERRIDE */
306 struct __user_cap_header_struct header;
307 struct __user_cap_data_struct cap;
309 setgroups(ARRAY_SIZE(groups), groups);
311 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
316 header.version = _LINUX_CAPABILITY_VERSION;
318 cap.effective = cap.permitted =
319 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
321 capset(&header, &cap);
325 dl_list_init(&alloc_list);
326 #endif /* WPA_TRACE */
331 void os_program_deinit(void)
334 struct os_alloc_trace *a;
335 unsigned long total = 0;
336 dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
338 if (a->magic != ALLOC_MAGIC) {
339 wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
341 a, a->magic, (unsigned long) a->len);
344 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
345 a, (unsigned long) a->len);
346 wpa_trace_dump("memleak", a);
349 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
350 (unsigned long) total);
351 #endif /* WPA_TRACE */
355 int os_setenv(const char *name, const char *value, int overwrite)
357 return setenv(name, value, overwrite);
361 int os_unsetenv(const char *name)
363 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
368 return unsetenv(name);
373 char * os_readfile(const char *name, size_t *len)
379 f = fopen(name, "rb");
383 if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
388 if (fseek(f, 0, SEEK_SET) < 0) {
393 buf = os_malloc(*len);
399 if (fread(buf, 1, *len, f) != *len) {
411 int os_file_exists(const char *fname)
413 FILE *f = fopen(fname, "rb");
422 void * os_zalloc(size_t size)
424 return calloc(1, size);
426 #endif /* WPA_TRACE */
429 size_t os_strlcpy(char *dest, const char *src, size_t siz)
435 /* Copy string up to the maximum size of the dest buffer */
436 while (--left != 0) {
437 if ((*dest++ = *s++) == '\0')
443 /* Not enough room for the string; force NUL-termination */
447 ; /* determine total src string length */
454 int os_memcmp_const(const void *a, const void *b, size_t len)
461 for (res = 0, i = 0; i < len; i++)
462 res |= aa[i] ^ bb[i];
470 void * os_malloc(size_t size)
472 struct os_alloc_trace *a;
473 a = malloc(sizeof(*a) + size);
476 a->magic = ALLOC_MAGIC;
477 dl_list_add(&alloc_list, &a->list);
484 void * os_realloc(void *ptr, size_t size)
486 struct os_alloc_trace *a;
491 return os_malloc(size);
493 a = (struct os_alloc_trace *) ptr - 1;
494 if (a->magic != ALLOC_MAGIC) {
495 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
497 a->magic == FREED_MAGIC ? " (already freed)" : "");
498 wpa_trace_show("Invalid os_realloc() call");
507 os_memcpy(n, a + 1, copy_len);
513 void os_free(void *ptr)
515 struct os_alloc_trace *a;
519 a = (struct os_alloc_trace *) ptr - 1;
520 if (a->magic != ALLOC_MAGIC) {
521 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
523 a->magic == FREED_MAGIC ? " (already freed)" : "");
524 wpa_trace_show("Invalid os_free() call");
527 dl_list_del(&a->list);
528 a->magic = FREED_MAGIC;
530 wpa_trace_check_ref(ptr);
535 void * os_zalloc(size_t size)
537 void *ptr = os_malloc(size);
539 os_memset(ptr, 0, size);
544 char * os_strdup(const char *s)
549 d = os_malloc(len + 1);
552 os_memcpy(d, s, len);
557 #endif /* WPA_TRACE */
560 int os_exec(const char *program, const char *arg, int wait_completion)
572 /* run the external command in the child process */
573 const int MAX_ARG = 30;
574 char *_program, *_arg, *pos;
575 char *argv[MAX_ARG + 1];
578 _program = os_strdup(program);
579 _arg = os_strdup(arg);
585 while (i < MAX_ARG && pos && *pos) {
591 pos = os_strchr(pos, ' ');
597 execv(program, argv);
605 if (wait_completion) {
606 /* wait for the child process to complete in the parent */
607 waitpid(pid, &pid_status, 0);