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