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