Use common driver code for Linux hwaddr get/set
[hostap-gosc2009.git] / src / utils / os_unix.c
blobcb23f72074c2af639569ed8bfb82939eac49a63d
1 /*
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
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #include "os.h"
19 #ifdef WPA_TRACE
21 #include "common.h"
22 #include "list.h"
23 #include "wpa_debug.h"
24 #include "trace.h"
26 static struct dl_list alloc_list;
28 #define ALLOC_MAGIC 0xa84ef1b2
29 #define FREED_MAGIC 0x67fd487a
31 struct os_alloc_trace {
32 unsigned int magic;
33 struct dl_list list;
34 size_t len;
35 WPA_TRACE_INFO
38 #endif /* WPA_TRACE */
41 void os_sleep(os_time_t sec, os_time_t usec)
43 if (sec)
44 sleep(sec);
45 if (usec)
46 usleep(usec);
50 int os_get_time(struct os_time *t)
52 int res;
53 struct timeval tv;
54 res = gettimeofday(&tv, NULL);
55 t->sec = tv.tv_sec;
56 t->usec = tv.tv_usec;
57 return res;
61 int os_mktime(int year, int month, int day, int hour, int min, int sec,
62 os_time_t *t)
64 struct tm tm, *tm1;
65 time_t t_local, t1, t2;
66 os_time_t tz_offset;
68 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
69 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
70 sec > 60)
71 return -1;
73 memset(&tm, 0, sizeof(tm));
74 tm.tm_year = year - 1900;
75 tm.tm_mon = month - 1;
76 tm.tm_mday = day;
77 tm.tm_hour = hour;
78 tm.tm_min = min;
79 tm.tm_sec = sec;
81 t_local = mktime(&tm);
83 /* figure out offset to UTC */
84 tm1 = localtime(&t_local);
85 if (tm1) {
86 t1 = mktime(tm1);
87 tm1 = gmtime(&t_local);
88 if (tm1) {
89 t2 = mktime(tm1);
90 tz_offset = t2 - t1;
91 } else
92 tz_offset = 0;
93 } else
94 tz_offset = 0;
96 *t = (os_time_t) t_local - tz_offset;
97 return 0;
101 #ifdef __APPLE__
102 #include <fcntl.h>
103 static int os_daemon(int nochdir, int noclose)
105 int devnull;
107 if (chdir("/") < 0)
108 return -1;
110 devnull = open("/dev/null", O_RDWR);
111 if (devnull < 0)
112 return -1;
114 if (dup2(devnull, STDIN_FILENO) < 0) {
115 close(devnull);
116 return -1;
119 if (dup2(devnull, STDOUT_FILENO) < 0) {
120 close(devnull);
121 return -1;
124 if (dup2(devnull, STDERR_FILENO) < 0) {
125 close(devnull);
126 return -1;
129 return 0;
131 #else /* __APPLE__ */
132 #define os_daemon daemon
133 #endif /* __APPLE__ */
136 int os_daemonize(const char *pid_file)
138 #ifdef __uClinux__
139 return -1;
140 #else /* __uClinux__ */
141 if (os_daemon(0, 0)) {
142 perror("daemon");
143 return -1;
146 if (pid_file) {
147 FILE *f = fopen(pid_file, "w");
148 if (f) {
149 fprintf(f, "%u\n", getpid());
150 fclose(f);
154 return -0;
155 #endif /* __uClinux__ */
159 void os_daemonize_terminate(const char *pid_file)
161 if (pid_file)
162 unlink(pid_file);
166 int os_get_random(unsigned char *buf, size_t len)
168 FILE *f;
169 size_t rc;
171 f = fopen("/dev/urandom", "rb");
172 if (f == NULL) {
173 printf("Could not open /dev/urandom.\n");
174 return -1;
177 rc = fread(buf, 1, len, f);
178 fclose(f);
180 return rc != len ? -1 : 0;
184 unsigned long os_random(void)
186 return random();
190 char * os_rel2abs_path(const char *rel_path)
192 char *buf = NULL, *cwd, *ret;
193 size_t len = 128, cwd_len, rel_len, ret_len;
194 int last_errno;
196 if (rel_path[0] == '/')
197 return os_strdup(rel_path);
199 for (;;) {
200 buf = os_malloc(len);
201 if (buf == NULL)
202 return NULL;
203 cwd = getcwd(buf, len);
204 if (cwd == NULL) {
205 last_errno = errno;
206 os_free(buf);
207 if (last_errno != ERANGE)
208 return NULL;
209 len *= 2;
210 if (len > 2000)
211 return NULL;
212 } else {
213 buf[len - 1] = '\0';
214 break;
218 cwd_len = os_strlen(cwd);
219 rel_len = os_strlen(rel_path);
220 ret_len = cwd_len + 1 + rel_len + 1;
221 ret = os_malloc(ret_len);
222 if (ret) {
223 os_memcpy(ret, cwd, cwd_len);
224 ret[cwd_len] = '/';
225 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
226 ret[ret_len - 1] = '\0';
228 os_free(buf);
229 return ret;
233 int os_program_init(void)
235 #ifdef WPA_TRACE
236 dl_list_init(&alloc_list);
237 #endif /* WPA_TRACE */
238 return 0;
242 void os_program_deinit(void)
244 #ifdef WPA_TRACE
245 struct os_alloc_trace *a;
246 unsigned long total = 0;
247 dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
248 total += a->len;
249 if (a->magic != ALLOC_MAGIC) {
250 wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
251 "len %lu",
252 a, a->magic, (unsigned long) a->len);
253 continue;
255 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
256 a, (unsigned long) a->len);
257 wpa_trace_dump("memleak", a);
259 if (total)
260 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
261 (unsigned long) total);
262 #endif /* WPA_TRACE */
266 int os_setenv(const char *name, const char *value, int overwrite)
268 return setenv(name, value, overwrite);
272 int os_unsetenv(const char *name)
274 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
275 defined(__OpenBSD__)
276 unsetenv(name);
277 return 0;
278 #else
279 return unsetenv(name);
280 #endif
284 char * os_readfile(const char *name, size_t *len)
286 FILE *f;
287 char *buf;
289 f = fopen(name, "rb");
290 if (f == NULL)
291 return NULL;
293 fseek(f, 0, SEEK_END);
294 *len = ftell(f);
295 fseek(f, 0, SEEK_SET);
297 buf = os_malloc(*len);
298 if (buf == NULL) {
299 fclose(f);
300 return NULL;
303 if (fread(buf, 1, *len, f) != *len) {
304 fclose(f);
305 os_free(buf);
306 return NULL;
309 fclose(f);
311 return buf;
315 #ifndef WPA_TRACE
316 void * os_zalloc(size_t size)
318 return calloc(1, size);
320 #endif /* WPA_TRACE */
323 size_t os_strlcpy(char *dest, const char *src, size_t siz)
325 const char *s = src;
326 size_t left = siz;
328 if (left) {
329 /* Copy string up to the maximum size of the dest buffer */
330 while (--left != 0) {
331 if ((*dest++ = *s++) == '\0')
332 break;
336 if (left == 0) {
337 /* Not enough room for the string; force NUL-termination */
338 if (siz != 0)
339 *dest = '\0';
340 while (*s++)
341 ; /* determine total src string length */
344 return s - src - 1;
348 #ifdef WPA_TRACE
350 void * os_malloc(size_t size)
352 struct os_alloc_trace *a;
353 a = malloc(sizeof(*a) + size);
354 if (a == NULL)
355 return NULL;
356 a->magic = ALLOC_MAGIC;
357 dl_list_add(&alloc_list, &a->list);
358 a->len = size;
359 wpa_trace_record(a);
360 return a + 1;
364 void * os_realloc(void *ptr, size_t size)
366 struct os_alloc_trace *a;
367 size_t copy_len;
368 void *n;
370 if (ptr == NULL)
371 return os_malloc(size);
373 a = ptr - sizeof(*a);
374 if (a->magic != ALLOC_MAGIC) {
375 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
376 a, a->magic,
377 a->magic == FREED_MAGIC ? " (already freed)" : "");
378 wpa_trace_show("Invalid os_realloc() call");
379 abort();
381 n = os_malloc(size);
382 if (n == NULL)
383 return NULL;
384 copy_len = a->len;
385 if (copy_len > size)
386 copy_len = size;
387 os_memcpy(n, a + 1, copy_len);
388 os_free(ptr);
389 return n;
393 void os_free(void *ptr)
395 struct os_alloc_trace *a;
397 if (ptr == NULL)
398 return;
399 a = ptr - sizeof(*a);
400 if (a->magic != ALLOC_MAGIC) {
401 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
402 a, a->magic,
403 a->magic == FREED_MAGIC ? " (already freed)" : "");
404 wpa_trace_show("Invalid os_free() call");
405 abort();
407 dl_list_del(&a->list);
408 a->magic = FREED_MAGIC;
410 wpa_trace_check_ref(ptr);
411 free(a);
415 void * os_zalloc(size_t size)
417 void *ptr = os_malloc(size);
418 if (ptr)
419 os_memset(ptr, 0, size);
420 return ptr;
424 char * os_strdup(const char *s)
426 size_t len;
427 char *d;
428 len = os_strlen(s);
429 d = os_malloc(len + 1);
430 if (d == NULL)
431 return NULL;
432 os_memcpy(d, s, len);
433 d[len] = '\0';
434 return d;
437 #endif /* WPA_TRACE */