1189251Ssam/* 2189251Ssam * wpa_supplicant/hostapd / Internal implementation of OS specific functions 3189251Ssam * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam * 8189251Ssam * This file is an example of operating system specific wrapper functions. 9189251Ssam * This version implements many of the functions internally, so it can be used 10189251Ssam * to fill in missing functions from the target system C libraries. 11189251Ssam * 12189251Ssam * Some of the functions are using standard C library calls in order to keep 13189251Ssam * this file in working condition to allow the functions to be tested on a 14189251Ssam * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for 15189251Ssam * this file to work correctly. Note that these implementations are only 16189251Ssam * examples and are not optimized for speed. 17189251Ssam */ 18189251Ssam 19189251Ssam#include "includes.h" 20189251Ssam 21189251Ssam#undef OS_REJECT_C_LIB_FUNCTIONS 22189251Ssam#include "os.h" 23189251Ssam 24189251Ssamvoid os_sleep(os_time_t sec, os_time_t usec) 25189251Ssam{ 26189251Ssam if (sec) 27189251Ssam sleep(sec); 28189251Ssam if (usec) 29189251Ssam usleep(usec); 30189251Ssam} 31189251Ssam 32189251Ssam 33189251Ssamint os_get_time(struct os_time *t) 34189251Ssam{ 35189251Ssam int res; 36189251Ssam struct timeval tv; 37189251Ssam res = gettimeofday(&tv, NULL); 38189251Ssam t->sec = tv.tv_sec; 39189251Ssam t->usec = tv.tv_usec; 40189251Ssam return res; 41189251Ssam} 42189251Ssam 43189251Ssam 44189251Ssamint os_mktime(int year, int month, int day, int hour, int min, int sec, 45189251Ssam os_time_t *t) 46189251Ssam{ 47189251Ssam struct tm tm; 48189251Ssam 49189251Ssam if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || 50189251Ssam hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || 51189251Ssam sec > 60) 52189251Ssam return -1; 53189251Ssam 54189251Ssam os_memset(&tm, 0, sizeof(tm)); 55189251Ssam tm.tm_year = year - 1900; 56189251Ssam tm.tm_mon = month - 1; 57189251Ssam tm.tm_mday = day; 58189251Ssam tm.tm_hour = hour; 59189251Ssam tm.tm_min = min; 60189251Ssam tm.tm_sec = sec; 61189251Ssam 62189251Ssam *t = (os_time_t) mktime(&tm); 63189251Ssam return 0; 64189251Ssam} 65189251Ssam 66189251Ssam 67252726Srpauloint os_gmtime(os_time_t t, struct os_tm *tm) 68252726Srpaulo{ 69252726Srpaulo struct tm *tm2; 70252726Srpaulo time_t t2 = t; 71252726Srpaulo 72252726Srpaulo tm2 = gmtime(&t2); 73252726Srpaulo if (tm2 == NULL) 74252726Srpaulo return -1; 75252726Srpaulo tm->sec = tm2->tm_sec; 76252726Srpaulo tm->min = tm2->tm_min; 77252726Srpaulo tm->hour = tm2->tm_hour; 78252726Srpaulo tm->day = tm2->tm_mday; 79252726Srpaulo tm->month = tm2->tm_mon + 1; 80252726Srpaulo tm->year = tm2->tm_year + 1900; 81252726Srpaulo return 0; 82252726Srpaulo} 83252726Srpaulo 84252726Srpaulo 85189251Ssamint os_daemonize(const char *pid_file) 86189251Ssam{ 87189251Ssam if (daemon(0, 0)) { 88189251Ssam perror("daemon"); 89189251Ssam return -1; 90189251Ssam } 91189251Ssam 92189251Ssam if (pid_file) { 93189251Ssam FILE *f = fopen(pid_file, "w"); 94189251Ssam if (f) { 95189251Ssam fprintf(f, "%u\n", getpid()); 96189251Ssam fclose(f); 97189251Ssam } 98189251Ssam } 99189251Ssam 100189251Ssam return -0; 101189251Ssam} 102189251Ssam 103189251Ssam 104189251Ssamvoid os_daemonize_terminate(const char *pid_file) 105189251Ssam{ 106189251Ssam if (pid_file) 107189251Ssam unlink(pid_file); 108189251Ssam} 109189251Ssam 110189251Ssam 111189251Ssamint os_get_random(unsigned char *buf, size_t len) 112189251Ssam{ 113189251Ssam FILE *f; 114189251Ssam size_t rc; 115189251Ssam 116189251Ssam f = fopen("/dev/urandom", "rb"); 117189251Ssam if (f == NULL) { 118189251Ssam printf("Could not open /dev/urandom.\n"); 119189251Ssam return -1; 120189251Ssam } 121189251Ssam 122189251Ssam rc = fread(buf, 1, len, f); 123189251Ssam fclose(f); 124189251Ssam 125189251Ssam return rc != len ? -1 : 0; 126189251Ssam} 127189251Ssam 128189251Ssam 129189251Ssamunsigned long os_random(void) 130189251Ssam{ 131189251Ssam return random(); 132189251Ssam} 133189251Ssam 134189251Ssam 135189251Ssamchar * os_rel2abs_path(const char *rel_path) 136189251Ssam{ 137189251Ssam char *buf = NULL, *cwd, *ret; 138189251Ssam size_t len = 128, cwd_len, rel_len, ret_len; 139189251Ssam 140189251Ssam if (rel_path[0] == '/') 141189251Ssam return os_strdup(rel_path); 142189251Ssam 143189251Ssam for (;;) { 144189251Ssam buf = os_malloc(len); 145189251Ssam if (buf == NULL) 146189251Ssam return NULL; 147189251Ssam cwd = getcwd(buf, len); 148189251Ssam if (cwd == NULL) { 149189251Ssam os_free(buf); 150189251Ssam if (errno != ERANGE) { 151189251Ssam return NULL; 152189251Ssam } 153189251Ssam len *= 2; 154189251Ssam } else { 155189251Ssam break; 156189251Ssam } 157189251Ssam } 158189251Ssam 159189251Ssam cwd_len = strlen(cwd); 160189251Ssam rel_len = strlen(rel_path); 161189251Ssam ret_len = cwd_len + 1 + rel_len + 1; 162189251Ssam ret = os_malloc(ret_len); 163189251Ssam if (ret) { 164189251Ssam os_memcpy(ret, cwd, cwd_len); 165189251Ssam ret[cwd_len] = '/'; 166189251Ssam os_memcpy(ret + cwd_len + 1, rel_path, rel_len); 167189251Ssam ret[ret_len - 1] = '\0'; 168189251Ssam } 169189251Ssam os_free(buf); 170189251Ssam return ret; 171189251Ssam} 172189251Ssam 173189251Ssam 174189251Ssamint os_program_init(void) 175189251Ssam{ 176189251Ssam return 0; 177189251Ssam} 178189251Ssam 179189251Ssam 180189251Ssamvoid os_program_deinit(void) 181189251Ssam{ 182189251Ssam} 183189251Ssam 184189251Ssam 185189251Ssamint os_setenv(const char *name, const char *value, int overwrite) 186189251Ssam{ 187189251Ssam return setenv(name, value, overwrite); 188189251Ssam} 189189251Ssam 190189251Ssam 191189251Ssamint os_unsetenv(const char *name) 192189251Ssam{ 193189251Ssam#if defined(__FreeBSD__) || defined(__NetBSD__) 194189251Ssam unsetenv(name); 195189251Ssam return 0; 196189251Ssam#else 197189251Ssam return unsetenv(name); 198189251Ssam#endif 199189251Ssam} 200189251Ssam 201189251Ssam 202189251Ssamchar * os_readfile(const char *name, size_t *len) 203189251Ssam{ 204189251Ssam FILE *f; 205189251Ssam char *buf; 206189251Ssam 207189251Ssam f = fopen(name, "rb"); 208189251Ssam if (f == NULL) 209189251Ssam return NULL; 210189251Ssam 211189251Ssam fseek(f, 0, SEEK_END); 212189251Ssam *len = ftell(f); 213189251Ssam fseek(f, 0, SEEK_SET); 214189251Ssam 215189251Ssam buf = os_malloc(*len); 216189251Ssam if (buf == NULL) { 217189251Ssam fclose(f); 218189251Ssam return NULL; 219189251Ssam } 220189251Ssam 221214734Srpaulo if (fread(buf, 1, *len, f) != *len) { 222214734Srpaulo fclose(f); 223214734Srpaulo os_free(buf); 224214734Srpaulo return NULL; 225214734Srpaulo } 226214734Srpaulo 227189251Ssam fclose(f); 228189251Ssam 229189251Ssam return buf; 230189251Ssam} 231189251Ssam 232189251Ssam 233189251Ssamvoid * os_zalloc(size_t size) 234189251Ssam{ 235189251Ssam void *n = os_malloc(size); 236189251Ssam if (n) 237189251Ssam os_memset(n, 0, size); 238189251Ssam return n; 239189251Ssam} 240189251Ssam 241189251Ssam 242189251Ssamvoid * os_malloc(size_t size) 243189251Ssam{ 244189251Ssam return malloc(size); 245189251Ssam} 246189251Ssam 247189251Ssam 248189251Ssamvoid * os_realloc(void *ptr, size_t size) 249189251Ssam{ 250189251Ssam return realloc(ptr, size); 251189251Ssam} 252189251Ssam 253189251Ssam 254189251Ssamvoid os_free(void *ptr) 255189251Ssam{ 256189251Ssam free(ptr); 257189251Ssam} 258189251Ssam 259189251Ssam 260189251Ssamvoid * os_memcpy(void *dest, const void *src, size_t n) 261189251Ssam{ 262189251Ssam char *d = dest; 263189251Ssam const char *s = src; 264189251Ssam while (n--) 265189251Ssam *d++ = *s++; 266189251Ssam return dest; 267189251Ssam} 268189251Ssam 269189251Ssam 270189251Ssamvoid * os_memmove(void *dest, const void *src, size_t n) 271189251Ssam{ 272189251Ssam if (dest < src) 273189251Ssam os_memcpy(dest, src, n); 274189251Ssam else { 275189251Ssam /* overlapping areas */ 276189251Ssam char *d = (char *) dest + n; 277189251Ssam const char *s = (const char *) src + n; 278189251Ssam while (n--) 279189251Ssam *--d = *--s; 280189251Ssam } 281189251Ssam return dest; 282189251Ssam} 283189251Ssam 284189251Ssam 285189251Ssamvoid * os_memset(void *s, int c, size_t n) 286189251Ssam{ 287189251Ssam char *p = s; 288189251Ssam while (n--) 289189251Ssam *p++ = c; 290189251Ssam return s; 291189251Ssam} 292189251Ssam 293189251Ssam 294189251Ssamint os_memcmp(const void *s1, const void *s2, size_t n) 295189251Ssam{ 296189251Ssam const unsigned char *p1 = s1, *p2 = s2; 297189251Ssam 298189251Ssam if (n == 0) 299189251Ssam return 0; 300189251Ssam 301189251Ssam while (*p1 == *p2) { 302189251Ssam p1++; 303189251Ssam p2++; 304189251Ssam n--; 305189251Ssam if (n == 0) 306189251Ssam return 0; 307189251Ssam } 308189251Ssam 309189251Ssam return *p1 - *p2; 310189251Ssam} 311189251Ssam 312189251Ssam 313189251Ssamchar * os_strdup(const char *s) 314189251Ssam{ 315189251Ssam char *res; 316189251Ssam size_t len; 317189251Ssam if (s == NULL) 318189251Ssam return NULL; 319189251Ssam len = os_strlen(s); 320189251Ssam res = os_malloc(len + 1); 321189251Ssam if (res) 322189251Ssam os_memcpy(res, s, len + 1); 323189251Ssam return res; 324189251Ssam} 325189251Ssam 326189251Ssam 327189251Ssamsize_t os_strlen(const char *s) 328189251Ssam{ 329189251Ssam const char *p = s; 330189251Ssam while (*p) 331189251Ssam p++; 332189251Ssam return p - s; 333189251Ssam} 334189251Ssam 335189251Ssam 336189251Ssamint os_strcasecmp(const char *s1, const char *s2) 337189251Ssam{ 338189251Ssam /* 339189251Ssam * Ignoring case is not required for main functionality, so just use 340189251Ssam * the case sensitive version of the function. 341189251Ssam */ 342189251Ssam return os_strcmp(s1, s2); 343189251Ssam} 344189251Ssam 345189251Ssam 346189251Ssamint os_strncasecmp(const char *s1, const char *s2, size_t n) 347189251Ssam{ 348189251Ssam /* 349189251Ssam * Ignoring case is not required for main functionality, so just use 350189251Ssam * the case sensitive version of the function. 351189251Ssam */ 352189251Ssam return os_strncmp(s1, s2, n); 353189251Ssam} 354189251Ssam 355189251Ssam 356189251Ssamchar * os_strchr(const char *s, int c) 357189251Ssam{ 358189251Ssam while (*s) { 359189251Ssam if (*s == c) 360189251Ssam return (char *) s; 361189251Ssam s++; 362189251Ssam } 363189251Ssam return NULL; 364189251Ssam} 365189251Ssam 366189251Ssam 367189251Ssamchar * os_strrchr(const char *s, int c) 368189251Ssam{ 369189251Ssam const char *p = s; 370189251Ssam while (*p) 371189251Ssam p++; 372189251Ssam p--; 373189251Ssam while (p >= s) { 374189251Ssam if (*p == c) 375189251Ssam return (char *) p; 376189251Ssam p--; 377189251Ssam } 378189251Ssam return NULL; 379189251Ssam} 380189251Ssam 381189251Ssam 382189251Ssamint os_strcmp(const char *s1, const char *s2) 383189251Ssam{ 384189251Ssam while (*s1 == *s2) { 385189251Ssam if (*s1 == '\0') 386189251Ssam break; 387189251Ssam s1++; 388189251Ssam s2++; 389189251Ssam } 390189251Ssam 391189251Ssam return *s1 - *s2; 392189251Ssam} 393189251Ssam 394189251Ssam 395189251Ssamint os_strncmp(const char *s1, const char *s2, size_t n) 396189251Ssam{ 397189251Ssam if (n == 0) 398189251Ssam return 0; 399189251Ssam 400189251Ssam while (*s1 == *s2) { 401189251Ssam if (*s1 == '\0') 402189251Ssam break; 403189251Ssam s1++; 404189251Ssam s2++; 405189251Ssam n--; 406189251Ssam if (n == 0) 407189251Ssam return 0; 408189251Ssam } 409189251Ssam 410189251Ssam return *s1 - *s2; 411189251Ssam} 412189251Ssam 413189251Ssam 414189251Ssamchar * os_strncpy(char *dest, const char *src, size_t n) 415189251Ssam{ 416189251Ssam char *d = dest; 417189251Ssam 418189251Ssam while (n--) { 419189251Ssam *d = *src; 420189251Ssam if (*src == '\0') 421189251Ssam break; 422189251Ssam d++; 423189251Ssam src++; 424189251Ssam } 425189251Ssam 426189251Ssam return dest; 427189251Ssam} 428189251Ssam 429189251Ssam 430189251Ssamsize_t os_strlcpy(char *dest, const char *src, size_t siz) 431189251Ssam{ 432189251Ssam const char *s = src; 433189251Ssam size_t left = siz; 434189251Ssam 435189251Ssam if (left) { 436189251Ssam /* Copy string up to the maximum size of the dest buffer */ 437189251Ssam while (--left != 0) { 438189251Ssam if ((*dest++ = *s++) == '\0') 439189251Ssam break; 440189251Ssam } 441189251Ssam } 442189251Ssam 443189251Ssam if (left == 0) { 444189251Ssam /* Not enough room for the string; force NUL-termination */ 445189251Ssam if (siz != 0) 446189251Ssam *dest = '\0'; 447189251Ssam while (*s++) 448189251Ssam ; /* determine total src string length */ 449189251Ssam } 450189251Ssam 451189251Ssam return s - src - 1; 452189251Ssam} 453189251Ssam 454189251Ssam 455189251Ssamchar * os_strstr(const char *haystack, const char *needle) 456189251Ssam{ 457189251Ssam size_t len = os_strlen(needle); 458189251Ssam while (*haystack) { 459189251Ssam if (os_strncmp(haystack, needle, len) == 0) 460189251Ssam return (char *) haystack; 461189251Ssam haystack++; 462189251Ssam } 463189251Ssam 464189251Ssam return NULL; 465189251Ssam} 466189251Ssam 467189251Ssam 468189251Ssamint os_snprintf(char *str, size_t size, const char *format, ...) 469189251Ssam{ 470189251Ssam va_list ap; 471189251Ssam int ret; 472189251Ssam 473189251Ssam /* See http://www.ijs.si/software/snprintf/ for portable 474189251Ssam * implementation of snprintf. 475189251Ssam */ 476189251Ssam 477189251Ssam va_start(ap, format); 478189251Ssam ret = vsnprintf(str, size, format, ap); 479189251Ssam va_end(ap); 480189251Ssam if (size > 0) 481189251Ssam str[size - 1] = '\0'; 482189251Ssam return ret; 483189251Ssam} 484