LMS 2012
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
os_unix.c
Go to the documentation of this file.
1 /*
2  * OS specific functions for UNIX/POSIX systems
3  * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
4  *
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.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 
17 #include "os.h"
18 
19 #ifdef WPA_TRACE
20 
21 #include "common.h"
22 #include "list.h"
23 #include "wpa_debug.h"
24 #include "trace.h"
25 
26 static struct dl_list alloc_list;
27 
28 #define ALLOC_MAGIC 0xa84ef1b2
29 #define FREED_MAGIC 0x67fd487a
30 
31 struct os_alloc_trace {
32  unsigned int magic;
33  struct dl_list list;
34  size_t len;
35  WPA_TRACE_INFO
36 };
37 
38 #endif /* WPA_TRACE */
39 
40 
41 void os_sleep(os_time_t sec, os_time_t usec)
42 {
43  if (sec)
44  sleep(sec);
45  if (usec)
46  usleep(usec);
47 }
48 
49 
50 int os_get_time(struct os_time *t)
51 {
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;
58 }
59 
60 
61 int os_mktime(int year, int month, int day, int hour, int min, int sec,
62  os_time_t *t)
63 {
64  struct tm tm, *tm1;
65  time_t t_local, t1, t2;
66  os_time_t tz_offset;
67 
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;
72 
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;
80 
81  t_local = mktime(&tm);
82 
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;
95 
96  *t = (os_time_t) t_local - tz_offset;
97  return 0;
98 }
99 
100 
101 #ifdef __APPLE__
102 #include <fcntl.h>
103 static int os_daemon(int nochdir, int noclose)
104 {
105  int devnull;
106 
107  if (chdir("/") < 0)
108  return -1;
109 
110  devnull = open("/dev/null", O_RDWR);
111  if (devnull < 0)
112  return -1;
113 
114  if (dup2(devnull, STDIN_FILENO) < 0) {
115  close(devnull);
116  return -1;
117  }
118 
119  if (dup2(devnull, STDOUT_FILENO) < 0) {
120  close(devnull);
121  return -1;
122  }
123 
124  if (dup2(devnull, STDERR_FILENO) < 0) {
125  close(devnull);
126  return -1;
127  }
128 
129  return 0;
130 }
131 #else /* __APPLE__ */
132 #define os_daemon daemon
133 #endif /* __APPLE__ */
134 
135 
136 int os_daemonize(const char *pid_file)
137 {
138 #ifdef __uClinux__
139  return -1;
140 #else /* __uClinux__ */
141  if (os_daemon(0, 0)) {
142  perror("daemon");
143  return -1;
144  }
145 
146  if (pid_file) {
147  FILE *f = fopen(pid_file, "w");
148  if (f) {
149  fprintf(f, "%u\n", getpid());
150  fclose(f);
151  }
152  }
153 
154  return -0;
155 #endif /* __uClinux__ */
156 }
157 
158 
159 void os_daemonize_terminate(const char *pid_file)
160 {
161  if (pid_file)
162  unlink(pid_file);
163 }
164 
165 
166 int os_get_random(unsigned char *buf, size_t len)
167 {
168  FILE *f;
169  size_t rc;
170 
171  f = fopen("/dev/urandom", "rb");
172  if (f == NULL) {
173  printf("Could not open /dev/urandom.\n");
174  return -1;
175  }
176 
177  rc = fread(buf, 1, len, f);
178  fclose(f);
179 
180  return rc != len ? -1 : 0;
181 }
182 
183 
184 unsigned long os_random(void)
185 {
186  return random();
187 }
188 
189 
190 char * os_rel2abs_path(const char *rel_path)
191 {
192  char *buf = NULL, *cwd, *ret;
193  size_t len = 128, cwd_len, rel_len, ret_len;
194  int last_errno;
195 
196  if (rel_path[0] == '/')
197  return os_strdup(rel_path);
198 
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;
215  }
216  }
217 
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';
227  }
228  os_free(buf);
229  return ret;
230 }
231 
232 
234 {
235 #ifdef WPA_TRACE
236  dl_list_init(&alloc_list);
237 #endif /* WPA_TRACE */
238  return 0;
239 }
240 
241 
243 {
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;
254  }
255  wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
256  a, (unsigned long) a->len);
257  wpa_trace_dump("memleak", a);
258  }
259  if (total)
260  wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
261  (unsigned long) total);
262 #endif /* WPA_TRACE */
263 }
264 
265 
266 int os_setenv(const char *name, const char *value, int overwrite)
267 {
268  return setenv(name, value, overwrite);
269 }
270 
271 
272 int os_unsetenv(const char *name)
273 {
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
281 }
282 
283 
284 char * os_readfile(const char *name, size_t *len)
285 {
286  FILE *f;
287  char *buf;
288 
289  f = fopen(name, "rb");
290  if (f == NULL)
291  return NULL;
292 
293  fseek(f, 0, SEEK_END);
294  *len = ftell(f);
295  fseek(f, 0, SEEK_SET);
296 
297  buf = os_malloc(*len);
298  if (buf == NULL) {
299  fclose(f);
300  return NULL;
301  }
302 
303  if (fread(buf, 1, *len, f) != *len) {
304  fclose(f);
305  os_free(buf);
306  return NULL;
307  }
308 
309  fclose(f);
310 
311  return buf;
312 }
313 
314 
315 #ifndef WPA_TRACE
316 void * os_zalloc(size_t size)
317 {
318  return calloc(1, size);
319 }
320 #endif /* WPA_TRACE */
321 
322 
323 size_t os_strlcpy(char *dest, const char *src, size_t siz)
324 {
325  const char *s = src;
326  size_t left = siz;
327 
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;
333  }
334  }
335 
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 */
342  }
343 
344  return s - src - 1;
345 }
346 
347 
348 #ifdef WPA_TRACE
349 
350 void * os_malloc(size_t size)
351 {
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;
361 }
362 
363 
364 void * os_realloc(void *ptr, size_t size)
365 {
366  struct os_alloc_trace *a;
367  size_t copy_len;
368  void *n;
369 
370  if (ptr == NULL)
371  return os_malloc(size);
372 
373  a = (struct os_alloc_trace *) ptr - 1;
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();
380  }
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;
390 }
391 
392 
393 void os_free(void *ptr)
394 {
395  struct os_alloc_trace *a;
396 
397  if (ptr == NULL)
398  return;
399  a = (struct os_alloc_trace *) ptr - 1;
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();
406  }
407  dl_list_del(&a->list);
408  a->magic = FREED_MAGIC;
409 
410  wpa_trace_check_ref(ptr);
411  free(a);
412 }
413 
414 
415 void * os_zalloc(size_t size)
416 {
417  void *ptr = os_malloc(size);
418  if (ptr)
419  os_memset(ptr, 0, size);
420  return ptr;
421 }
422 
423 
424 char * os_strdup(const char *s)
425 {
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;
435 }
436 
437 #endif /* WPA_TRACE */
void os_sleep(os_time_t sec, os_time_t usec)
Definition: os_unix.c:41
int os_get_random(unsigned char *buf, size_t len)
Definition: os_unix.c:166
int os_get_time(struct os_time *t)
Definition: os_unix.c:50
Definition: os.h:27
int os_setenv(const char *name, const char *value, int overwrite)
Definition: os_unix.c:266
#define os_memset(s, c, n)
Definition: os.h:413
int os_program_init(void)
Definition: os_unix.c:233
void os_daemonize_terminate(const char *pid_file)
Definition: os_unix.c:159
#define os_strdup(s)
Definition: os.h:401
int os_unsetenv(const char *name)
Definition: os_unix.c:272
unsigned long os_random(void)
Definition: os_unix.c:184
os_time_t usec
Definition: os.h:29
char * os_rel2abs_path(const char *rel_path)
Definition: os_unix.c:190
#define os_malloc(s)
Definition: os.h:389
int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t)
Definition: os_unix.c:61
char * os_readfile(const char *name, size_t *len)
Definition: os_unix.c:284
#define os_memcpy(d, s, n)
Definition: os.h:407
size_t os_strlcpy(char *dest, const char *src, size_t siz)
Definition: os_unix.c:323
#define os_daemon
Definition: os_unix.c:132
void os_program_deinit(void)
Definition: os_unix.c:242
void * os_zalloc(size_t size)
Definition: os_unix.c:316
#define os_realloc(p, s)
Definition: os.h:392
#define os_strlen(s)
Definition: os.h:420
#define os_free(p)
Definition: os.h:395
os_time_t sec
Definition: os.h:28
int os_daemonize(const char *pid_file)
Definition: os_unix.c:136
long os_time_t
Definition: os.h:18
void wpa_printf(int level, const char *fmt,...) PRINTF_FORMAT(2
#define NULL