2 * OS specific functions for UNIX/POSIX systems
3 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
20 #include <linux/capability.h>
21 #include <linux/prctl.h>
22 #include <private/android_filesystem_config.h>
30 #include "wpa_debug.h"
34 static struct dl_list alloc_list
;
36 #define ALLOC_MAGIC 0xa84ef1b2
37 #define FREED_MAGIC 0x67fd487a
39 struct os_alloc_trace
{
46 #endif /* WPA_TRACE */
49 void os_sleep(os_time_t sec
, os_time_t usec
)
58 int os_get_time(struct os_time
*t
)
62 res
= gettimeofday(&tv
, NULL
);
69 int os_mktime(int year
, int month
, int day
, int hour
, int min
, int sec
,
73 time_t t_local
, t1
, t2
;
76 if (year
< 1970 || month
< 1 || month
> 12 || day
< 1 || day
> 31 ||
77 hour
< 0 || hour
> 23 || min
< 0 || min
> 59 || sec
< 0 ||
81 memset(&tm
, 0, sizeof(tm
));
82 tm
.tm_year
= year
- 1900;
83 tm
.tm_mon
= month
- 1;
89 t_local
= mktime(&tm
);
91 /* figure out offset to UTC */
92 tm1
= localtime(&t_local
);
95 tm1
= gmtime(&t_local
);
104 *t
= (os_time_t
) t_local
- tz_offset
;
109 int os_gmtime(os_time_t t
, struct os_tm
*tm
)
117 tm
->sec
= tm2
->tm_sec
;
118 tm
->min
= tm2
->tm_min
;
119 tm
->hour
= tm2
->tm_hour
;
120 tm
->day
= tm2
->tm_mday
;
121 tm
->month
= tm2
->tm_mon
+ 1;
122 tm
->year
= tm2
->tm_year
+ 1900;
129 static int os_daemon(int nochdir
, int noclose
)
136 devnull
= open("/dev/null", O_RDWR
);
140 if (dup2(devnull
, STDIN_FILENO
) < 0) {
145 if (dup2(devnull
, STDOUT_FILENO
) < 0) {
150 if (dup2(devnull
, STDERR_FILENO
) < 0) {
157 #else /* __APPLE__ */
158 #define os_daemon daemon
159 #endif /* __APPLE__ */
162 int os_daemonize(const char *pid_file
)
164 #if defined(__uClinux__) || defined(__sun__)
166 #else /* defined(__uClinux__) || defined(__sun__) */
167 if (os_daemon(0, 0)) {
173 FILE *f
= fopen(pid_file
, "w");
175 fprintf(f
, "%u\n", getpid());
181 #endif /* defined(__uClinux__) || defined(__sun__) */
185 void os_daemonize_terminate(const char *pid_file
)
192 int os_get_random(unsigned char *buf
, size_t len
)
197 f
= fopen("/dev/urandom", "rb");
199 printf("Could not open /dev/urandom.\n");
203 rc
= fread(buf
, 1, len
, f
);
206 return rc
!= len
? -1 : 0;
210 unsigned long os_random(void)
216 char * os_rel2abs_path(const char *rel_path
)
218 char *buf
= NULL
, *cwd
, *ret
;
219 size_t len
= 128, cwd_len
, rel_len
, ret_len
;
222 if (rel_path
[0] == '/')
223 return os_strdup(rel_path
);
226 buf
= os_malloc(len
);
229 cwd
= getcwd(buf
, len
);
233 if (last_errno
!= ERANGE
)
244 cwd_len
= os_strlen(cwd
);
245 rel_len
= os_strlen(rel_path
);
246 ret_len
= cwd_len
+ 1 + rel_len
+ 1;
247 ret
= os_malloc(ret_len
);
249 os_memcpy(ret
, cwd
, cwd_len
);
251 os_memcpy(ret
+ cwd_len
+ 1, rel_path
, rel_len
);
252 ret
[ret_len
- 1] = '\0';
259 int os_program_init(void)
263 * We ignore errors here since errors are normal if we
264 * are already running as non-root.
266 gid_t groups
[] = { AID_INET
, AID_WIFI
, AID_KEYSTORE
};
267 struct __user_cap_header_struct header
;
268 struct __user_cap_data_struct cap
;
270 setgroups(sizeof(groups
)/sizeof(groups
[0]), groups
);
272 prctl(PR_SET_KEEPCAPS
, 1, 0, 0, 0);
277 header
.version
= _LINUX_CAPABILITY_VERSION
;
279 cap
.effective
= cap
.permitted
=
280 (1 << CAP_NET_ADMIN
) | (1 << CAP_NET_RAW
);
282 capset(&header
, &cap
);
286 dl_list_init(&alloc_list
);
287 #endif /* WPA_TRACE */
292 void os_program_deinit(void)
295 struct os_alloc_trace
*a
;
296 unsigned long total
= 0;
297 dl_list_for_each(a
, &alloc_list
, struct os_alloc_trace
, list
) {
299 if (a
->magic
!= ALLOC_MAGIC
) {
300 wpa_printf(MSG_INFO
, "MEMLEAK[%p]: invalid magic 0x%x "
302 a
, a
->magic
, (unsigned long) a
->len
);
305 wpa_printf(MSG_INFO
, "MEMLEAK[%p]: len %lu",
306 a
, (unsigned long) a
->len
);
307 wpa_trace_dump("memleak", a
);
310 wpa_printf(MSG_INFO
, "MEMLEAK: total %lu bytes",
311 (unsigned long) total
);
312 #endif /* WPA_TRACE */
316 int os_setenv(const char *name
, const char *value
, int overwrite
)
318 return setenv(name
, value
, overwrite
);
322 int os_unsetenv(const char *name
)
324 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
329 return unsetenv(name
);
334 char * os_readfile(const char *name
, size_t *len
)
340 f
= fopen(name
, "rb");
344 if (fseek(f
, 0, SEEK_END
) < 0 || (pos
= ftell(f
)) < 0) {
349 if (fseek(f
, 0, SEEK_SET
) < 0) {
354 buf
= os_malloc(*len
);
360 if (fread(buf
, 1, *len
, f
) != *len
) {
373 void * os_zalloc(size_t size
)
375 return calloc(1, size
);
377 #endif /* WPA_TRACE */
380 size_t os_strlcpy(char *dest
, const char *src
, size_t siz
)
386 /* Copy string up to the maximum size of the dest buffer */
387 while (--left
!= 0) {
388 if ((*dest
++ = *s
++) == '\0')
394 /* Not enough room for the string; force NUL-termination */
398 ; /* determine total src string length */
407 void * os_malloc(size_t size
)
409 struct os_alloc_trace
*a
;
410 a
= malloc(sizeof(*a
) + size
);
413 a
->magic
= ALLOC_MAGIC
;
414 dl_list_add(&alloc_list
, &a
->list
);
421 void * os_realloc(void *ptr
, size_t size
)
423 struct os_alloc_trace
*a
;
428 return os_malloc(size
);
430 a
= (struct os_alloc_trace
*) ptr
- 1;
431 if (a
->magic
!= ALLOC_MAGIC
) {
432 wpa_printf(MSG_INFO
, "REALLOC[%p]: invalid magic 0x%x%s",
434 a
->magic
== FREED_MAGIC
? " (already freed)" : "");
435 wpa_trace_show("Invalid os_realloc() call");
444 os_memcpy(n
, a
+ 1, copy_len
);
450 void os_free(void *ptr
)
452 struct os_alloc_trace
*a
;
456 a
= (struct os_alloc_trace
*) ptr
- 1;
457 if (a
->magic
!= ALLOC_MAGIC
) {
458 wpa_printf(MSG_INFO
, "FREE[%p]: invalid magic 0x%x%s",
460 a
->magic
== FREED_MAGIC
? " (already freed)" : "");
461 wpa_trace_show("Invalid os_free() call");
464 dl_list_del(&a
->list
);
465 a
->magic
= FREED_MAGIC
;
467 wpa_trace_check_ref(ptr
);
472 void * os_zalloc(size_t size
)
474 void *ptr
= os_malloc(size
);
476 os_memset(ptr
, 0, size
);
481 char * os_strdup(const char *s
)
486 d
= os_malloc(len
+ 1);
489 os_memcpy(d
, s
, len
);
494 #endif /* WPA_TRACE */