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.
14 #include <linux/capability.h>
15 #include <linux/prctl.h>
16 #include <private/android_filesystem_config.h>
24 #include "wpa_debug.h"
28 static struct dl_list alloc_list;
30 #define ALLOC_MAGIC 0xa84ef1b2
31 #define FREED_MAGIC 0x67fd487a
33 struct os_alloc_trace {
40 #endif /* WPA_TRACE */
43 void os_sleep(os_time_t sec, os_time_t usec)
52 int os_get_time(struct os_time *t)
56 res = gettimeofday(&tv, NULL);
63 int os_mktime(int year, int month, int day, int hour, int min, int sec,
67 time_t t_local, t1, t2;
70 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
71 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
75 memset(&tm, 0, sizeof(tm));
76 tm.tm_year = year - 1900;
77 tm.tm_mon = month - 1;
83 t_local = mktime(&tm);
85 /* figure out offset to UTC */
86 tm1 = localtime(&t_local);
89 tm1 = gmtime(&t_local);
98 *t = (os_time_t) t_local - tz_offset;
103 int os_gmtime(os_time_t t, struct os_tm *tm)
111 tm->sec = tm2->tm_sec;
112 tm->min = tm2->tm_min;
113 tm->hour = tm2->tm_hour;
114 tm->day = tm2->tm_mday;
115 tm->month = tm2->tm_mon + 1;
116 tm->year = tm2->tm_year + 1900;
123 static int os_daemon(int nochdir, int noclose)
130 devnull = open("/dev/null", O_RDWR);
134 if (dup2(devnull, STDIN_FILENO) < 0) {
139 if (dup2(devnull, STDOUT_FILENO) < 0) {
144 if (dup2(devnull, STDERR_FILENO) < 0) {
151 #else /* __APPLE__ */
152 #define os_daemon daemon
153 #endif /* __APPLE__ */
160 #endif /* __FreeBSD__ */
162 int os_daemonize(const char *pid_file)
164 #if defined(__uClinux__) || defined(__sun__)
166 #else /* defined(__uClinux__) || defined(__sun__) */
171 pfh = pidfile_open(pid_file, 0600, &otherpid);
173 if (errno == EEXIST) {
174 errx(1, "Daemon already running, pid: %jd.",
177 warn("Cannot open or create pidfile.");
179 #endif /* __FreeBSD__ */
181 if (os_daemon(0, 0)) {
185 #endif /* __FreeBSD__ */
191 FILE *f = fopen(pid_file, "w");
193 fprintf(f, "%u\n", getpid());
197 #else /* __FreeBSD__ */
199 #endif /* __FreeBSD__ */
202 #endif /* defined(__uClinux__) || defined(__sun__) */
206 void os_daemonize_terminate(const char *pid_file)
213 int os_get_random(unsigned char *buf, size_t len)
218 f = fopen("/dev/urandom", "rb");
220 printf("Could not open /dev/urandom.\n");
224 rc = fread(buf, 1, len, f);
227 return rc != len ? -1 : 0;
231 unsigned long os_random(void)
237 char * os_rel2abs_path(const char *rel_path)
239 char *buf = NULL, *cwd, *ret;
240 size_t len = 128, cwd_len, rel_len, ret_len;
243 if (rel_path[0] == '/')
244 return os_strdup(rel_path);
247 buf = os_malloc(len);
250 cwd = getcwd(buf, len);
254 if (last_errno != ERANGE)
265 cwd_len = os_strlen(cwd);
266 rel_len = os_strlen(rel_path);
267 ret_len = cwd_len + 1 + rel_len + 1;
268 ret = os_malloc(ret_len);
270 os_memcpy(ret, cwd, cwd_len);
272 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
273 ret[ret_len - 1] = '\0';
280 int os_program_init(void)
284 * We ignore errors here since errors are normal if we
285 * are already running as non-root.
287 gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
288 struct __user_cap_header_struct header;
289 struct __user_cap_data_struct cap;
291 setgroups(sizeof(groups)/sizeof(groups[0]), groups);
293 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
298 header.version = _LINUX_CAPABILITY_VERSION;
300 cap.effective = cap.permitted =
301 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
303 capset(&header, &cap);
307 dl_list_init(&alloc_list);
308 #endif /* WPA_TRACE */
313 void os_program_deinit(void)
316 struct os_alloc_trace *a;
317 unsigned long total = 0;
318 dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
320 if (a->magic != ALLOC_MAGIC) {
321 wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
323 a, a->magic, (unsigned long) a->len);
326 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
327 a, (unsigned long) a->len);
328 wpa_trace_dump("memleak", a);
331 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
332 (unsigned long) total);
333 #endif /* WPA_TRACE */
337 int os_setenv(const char *name, const char *value, int overwrite)
339 return setenv(name, value, overwrite);
343 int os_unsetenv(const char *name)
345 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
350 return unsetenv(name);
355 char * os_readfile(const char *name, size_t *len)
361 f = fopen(name, "rb");
365 if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
370 if (fseek(f, 0, SEEK_SET) < 0) {
375 buf = os_malloc(*len);
381 if (fread(buf, 1, *len, f) != *len) {
394 void * os_zalloc(size_t size)
396 return calloc(1, size);
398 #endif /* WPA_TRACE */
401 size_t os_strlcpy(char *dest, const char *src, size_t siz)
407 /* Copy string up to the maximum size of the dest buffer */
408 while (--left != 0) {
409 if ((*dest++ = *s++) == '\0')
415 /* Not enough room for the string; force NUL-termination */
419 ; /* determine total src string length */
428 void * os_malloc(size_t size)
430 struct os_alloc_trace *a;
431 a = malloc(sizeof(*a) + size);
434 a->magic = ALLOC_MAGIC;
435 dl_list_add(&alloc_list, &a->list);
442 void * os_realloc(void *ptr, size_t size)
444 struct os_alloc_trace *a;
449 return os_malloc(size);
451 a = (struct os_alloc_trace *) ptr - 1;
452 if (a->magic != ALLOC_MAGIC) {
453 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
455 a->magic == FREED_MAGIC ? " (already freed)" : "");
456 wpa_trace_show("Invalid os_realloc() call");
465 os_memcpy(n, a + 1, copy_len);
471 void os_free(void *ptr)
473 struct os_alloc_trace *a;
477 a = (struct os_alloc_trace *) ptr - 1;
478 if (a->magic != ALLOC_MAGIC) {
479 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
481 a->magic == FREED_MAGIC ? " (already freed)" : "");
482 wpa_trace_show("Invalid os_free() call");
485 dl_list_del(&a->list);
486 a->magic = FREED_MAGIC;
488 wpa_trace_check_ref(ptr);
493 void * os_zalloc(size_t size)
495 void *ptr = os_malloc(size);
497 os_memset(ptr, 0, size);
502 char * os_strdup(const char *s)
507 d = os_malloc(len + 1);
510 os_memcpy(d, s, len);
515 #endif /* WPA_TRACE */