blob: e4b7fdb18ad354f810bc2b292e55acdd5ae8e606 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * wpa_supplicant/hostapd / Internal implementation of OS specific functions
3 * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
4 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file is an example of operating system specific wrapper functions.
9 * This version implements many of the functions internally, so it can be used
10 * to fill in missing functions from the target system C libraries.
11 *
12 * Some of the functions are using standard C library calls in order to keep
13 * this file in working condition to allow the functions to be tested on a
14 * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for
15 * this file to work correctly. Note that these implementations are only
16 * examples and are not optimized for speed.
17 */
18
19#include "includes.h"
20
21#undef OS_REJECT_C_LIB_FUNCTIONS
22#include "os.h"
23
24void os_sleep(os_time_t sec, os_time_t usec)
25{
26 if (sec)
27 sleep(sec);
28 if (usec)
29 usleep(usec);
30}
31
32
33int os_get_time(struct os_time *t)
34{
35 int res;
36 struct timeval tv;
37 res = gettimeofday(&tv, NULL);
38 t->sec = tv.tv_sec;
39 t->usec = tv.tv_usec;
40 return res;
41}
42
43
44int os_mktime(int year, int month, int day, int hour, int min, int sec,
45 os_time_t *t)
46{
47 struct tm tm;
48
49 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
50 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
51 sec > 60)
52 return -1;
53
54 os_memset(&tm, 0, sizeof(tm));
55 tm.tm_year = year - 1900;
56 tm.tm_mon = month - 1;
57 tm.tm_mday = day;
58 tm.tm_hour = hour;
59 tm.tm_min = min;
60 tm.tm_sec = sec;
61
62 *t = (os_time_t) mktime(&tm);
63 return 0;
64}
65
66
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080067int os_gmtime(os_time_t t, struct os_tm *tm)
68{
69 struct tm *tm2;
70 time_t t2 = t;
71
72 tm2 = gmtime(&t2);
73 if (tm2 == NULL)
74 return -1;
75 tm->sec = tm2->tm_sec;
76 tm->min = tm2->tm_min;
77 tm->hour = tm2->tm_hour;
78 tm->day = tm2->tm_mday;
79 tm->month = tm2->tm_mon + 1;
80 tm->year = tm2->tm_year + 1900;
81 return 0;
82}
83
84
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070085int os_daemonize(const char *pid_file)
86{
87 if (daemon(0, 0)) {
88 perror("daemon");
89 return -1;
90 }
91
92 if (pid_file) {
93 FILE *f = fopen(pid_file, "w");
94 if (f) {
95 fprintf(f, "%u\n", getpid());
96 fclose(f);
97 }
98 }
99
100 return -0;
101}
102
103
104void os_daemonize_terminate(const char *pid_file)
105{
106 if (pid_file)
107 unlink(pid_file);
108}
109
110
111int os_get_random(unsigned char *buf, size_t len)
112{
113 FILE *f;
114 size_t rc;
115
116 f = fopen("/dev/urandom", "rb");
117 if (f == NULL) {
118 printf("Could not open /dev/urandom.\n");
119 return -1;
120 }
121
122 rc = fread(buf, 1, len, f);
123 fclose(f);
124
125 return rc != len ? -1 : 0;
126}
127
128
129unsigned long os_random(void)
130{
131 return random();
132}
133
134
135char * os_rel2abs_path(const char *rel_path)
136{
137 char *buf = NULL, *cwd, *ret;
138 size_t len = 128, cwd_len, rel_len, ret_len;
139
140 if (rel_path[0] == '/')
141 return os_strdup(rel_path);
142
143 for (;;) {
144 buf = os_malloc(len);
145 if (buf == NULL)
146 return NULL;
147 cwd = getcwd(buf, len);
148 if (cwd == NULL) {
149 os_free(buf);
150 if (errno != ERANGE) {
151 return NULL;
152 }
153 len *= 2;
154 } else {
155 break;
156 }
157 }
158
159 cwd_len = strlen(cwd);
160 rel_len = strlen(rel_path);
161 ret_len = cwd_len + 1 + rel_len + 1;
162 ret = os_malloc(ret_len);
163 if (ret) {
164 os_memcpy(ret, cwd, cwd_len);
165 ret[cwd_len] = '/';
166 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
167 ret[ret_len - 1] = '\0';
168 }
169 os_free(buf);
170 return ret;
171}
172
173
174int os_program_init(void)
175{
176 return 0;
177}
178
179
180void os_program_deinit(void)
181{
182}
183
184
185int os_setenv(const char *name, const char *value, int overwrite)
186{
187 return setenv(name, value, overwrite);
188}
189
190
191int os_unsetenv(const char *name)
192{
193#if defined(__FreeBSD__) || defined(__NetBSD__)
194 unsetenv(name);
195 return 0;
196#else
197 return unsetenv(name);
198#endif
199}
200
201
202char * os_readfile(const char *name, size_t *len)
203{
204 FILE *f;
205 char *buf;
206
207 f = fopen(name, "rb");
208 if (f == NULL)
209 return NULL;
210
211 fseek(f, 0, SEEK_END);
212 *len = ftell(f);
213 fseek(f, 0, SEEK_SET);
214
215 buf = os_malloc(*len);
216 if (buf == NULL) {
217 fclose(f);
218 return NULL;
219 }
220
221 if (fread(buf, 1, *len, f) != *len) {
222 fclose(f);
223 os_free(buf);
224 return NULL;
225 }
226
227 fclose(f);
228
229 return buf;
230}
231
232
233void * os_zalloc(size_t size)
234{
235 void *n = os_malloc(size);
236 if (n)
237 os_memset(n, 0, size);
238 return n;
239}
240
241
242void * os_malloc(size_t size)
243{
244 return malloc(size);
245}
246
247
248void * os_realloc(void *ptr, size_t size)
249{
250 return realloc(ptr, size);
251}
252
253
254void os_free(void *ptr)
255{
256 free(ptr);
257}
258
259
260void * os_memcpy(void *dest, const void *src, size_t n)
261{
262 char *d = dest;
263 const char *s = src;
264 while (n--)
265 *d++ = *s++;
266 return dest;
267}
268
269
270void * os_memmove(void *dest, const void *src, size_t n)
271{
272 if (dest < src)
273 os_memcpy(dest, src, n);
274 else {
275 /* overlapping areas */
276 char *d = (char *) dest + n;
277 const char *s = (const char *) src + n;
278 while (n--)
279 *--d = *--s;
280 }
281 return dest;
282}
283
284
285void * os_memset(void *s, int c, size_t n)
286{
287 char *p = s;
288 while (n--)
289 *p++ = c;
290 return s;
291}
292
293
294int os_memcmp(const void *s1, const void *s2, size_t n)
295{
296 const unsigned char *p1 = s1, *p2 = s2;
297
298 if (n == 0)
299 return 0;
300
301 while (*p1 == *p2) {
302 p1++;
303 p2++;
304 n--;
305 if (n == 0)
306 return 0;
307 }
308
309 return *p1 - *p2;
310}
311
312
313char * os_strdup(const char *s)
314{
315 char *res;
316 size_t len;
317 if (s == NULL)
318 return NULL;
319 len = os_strlen(s);
320 res = os_malloc(len + 1);
321 if (res)
322 os_memcpy(res, s, len + 1);
323 return res;
324}
325
326
327size_t os_strlen(const char *s)
328{
329 const char *p = s;
330 while (*p)
331 p++;
332 return p - s;
333}
334
335
336int os_strcasecmp(const char *s1, const char *s2)
337{
338 /*
339 * Ignoring case is not required for main functionality, so just use
340 * the case sensitive version of the function.
341 */
342 return os_strcmp(s1, s2);
343}
344
345
346int os_strncasecmp(const char *s1, const char *s2, size_t n)
347{
348 /*
349 * Ignoring case is not required for main functionality, so just use
350 * the case sensitive version of the function.
351 */
352 return os_strncmp(s1, s2, n);
353}
354
355
356char * os_strchr(const char *s, int c)
357{
358 while (*s) {
359 if (*s == c)
360 return (char *) s;
361 s++;
362 }
363 return NULL;
364}
365
366
367char * os_strrchr(const char *s, int c)
368{
369 const char *p = s;
370 while (*p)
371 p++;
372 p--;
373 while (p >= s) {
374 if (*p == c)
375 return (char *) p;
376 p--;
377 }
378 return NULL;
379}
380
381
382int os_strcmp(const char *s1, const char *s2)
383{
384 while (*s1 == *s2) {
385 if (*s1 == '\0')
386 break;
387 s1++;
388 s2++;
389 }
390
391 return *s1 - *s2;
392}
393
394
395int os_strncmp(const char *s1, const char *s2, size_t n)
396{
397 if (n == 0)
398 return 0;
399
400 while (*s1 == *s2) {
401 if (*s1 == '\0')
402 break;
403 s1++;
404 s2++;
405 n--;
406 if (n == 0)
407 return 0;
408 }
409
410 return *s1 - *s2;
411}
412
413
414char * os_strncpy(char *dest, const char *src, size_t n)
415{
416 char *d = dest;
417
418 while (n--) {
419 *d = *src;
420 if (*src == '\0')
421 break;
422 d++;
423 src++;
424 }
425
426 return dest;
427}
428
429
430size_t os_strlcpy(char *dest, const char *src, size_t siz)
431{
432 const char *s = src;
433 size_t left = siz;
434
435 if (left) {
436 /* Copy string up to the maximum size of the dest buffer */
437 while (--left != 0) {
438 if ((*dest++ = *s++) == '\0')
439 break;
440 }
441 }
442
443 if (left == 0) {
444 /* Not enough room for the string; force NUL-termination */
445 if (siz != 0)
446 *dest = '\0';
447 while (*s++)
448 ; /* determine total src string length */
449 }
450
451 return s - src - 1;
452}
453
454
455char * os_strstr(const char *haystack, const char *needle)
456{
457 size_t len = os_strlen(needle);
458 while (*haystack) {
459 if (os_strncmp(haystack, needle, len) == 0)
460 return (char *) haystack;
461 haystack++;
462 }
463
464 return NULL;
465}
466
467
468int os_snprintf(char *str, size_t size, const char *format, ...)
469{
470 va_list ap;
471 int ret;
472
473 /* See http://www.ijs.si/software/snprintf/ for portable
474 * implementation of snprintf.
475 */
476
477 va_start(ap, format);
478 ret = vsnprintf(str, size, format, ap);
479 va_end(ap);
480 if (size > 0)
481 str[size - 1] = '\0';
482 return ret;
483}