LCOV - code coverage report
Current view: top level - src/utils - os_unix.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1401264779 Lines: 136 227 59.9 %
Date: 2014-05-28 Functions: 17 22 77.3 %

          Line data    Source code
       1             : /*
       2             :  * OS specific functions for UNIX/POSIX systems
       3             :  * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include <time.h>
      12             : 
      13             : #ifdef ANDROID
      14             : #include <sys/capability.h>
      15             : #include <linux/prctl.h>
      16             : #include <private/android_filesystem_config.h>
      17             : #endif /* ANDROID */
      18             : 
      19             : #include "os.h"
      20             : #include "common.h"
      21             : 
      22             : #ifdef WPA_TRACE
      23             : 
      24             : #include "wpa_debug.h"
      25             : #include "trace.h"
      26             : #include "list.h"
      27             : 
      28             : static struct dl_list alloc_list;
      29             : 
      30             : #define ALLOC_MAGIC 0xa84ef1b2
      31             : #define FREED_MAGIC 0x67fd487a
      32             : 
      33             : struct os_alloc_trace {
      34             :         unsigned int magic;
      35             :         struct dl_list list;
      36             :         size_t len;
      37             :         WPA_TRACE_INFO
      38             : };
      39             : 
      40             : #endif /* WPA_TRACE */
      41             : 
      42             : 
      43         334 : void os_sleep(os_time_t sec, os_time_t usec)
      44             : {
      45         334 :         if (sec)
      46           0 :                 sleep(sec);
      47         334 :         if (usec)
      48         334 :                 usleep(usec);
      49         334 : }
      50             : 
      51             : 
      52     1692967 : int os_get_time(struct os_time *t)
      53             : {
      54             :         int res;
      55             :         struct timeval tv;
      56     1692967 :         res = gettimeofday(&tv, NULL);
      57     1692967 :         t->sec = tv.tv_sec;
      58     1692967 :         t->usec = tv.tv_usec;
      59     1692967 :         return res;
      60             : }
      61             : 
      62             : 
      63      457907 : int os_get_reltime(struct os_reltime *t)
      64             : {
      65             : #if defined(CLOCK_BOOTTIME)
      66             :         static clockid_t clock_id = CLOCK_BOOTTIME;
      67             : #elif defined(CLOCK_MONOTONIC)
      68             :         static clockid_t clock_id = CLOCK_MONOTONIC;
      69             : #else
      70             :         static clockid_t clock_id = CLOCK_REALTIME;
      71             : #endif
      72             :         struct timespec ts;
      73             :         int res;
      74             : 
      75             :         while (1) {
      76      457907 :                 res = clock_gettime(clock_id, &ts);
      77      457907 :                 if (res == 0) {
      78      457907 :                         t->sec = ts.tv_sec;
      79      457907 :                         t->usec = ts.tv_nsec / 1000;
      80      457907 :                         return 0;
      81             :                 }
      82           0 :                 switch (clock_id) {
      83             : #ifdef CLOCK_BOOTTIME
      84             :                 case CLOCK_BOOTTIME:
      85           0 :                         clock_id = CLOCK_MONOTONIC;
      86           0 :                         break;
      87             : #endif
      88             : #ifdef CLOCK_MONOTONIC
      89             :                 case CLOCK_MONOTONIC:
      90           0 :                         clock_id = CLOCK_REALTIME;
      91           0 :                         break;
      92             : #endif
      93             :                 case CLOCK_REALTIME:
      94           0 :                         return -1;
      95             :                 }
      96           0 :         }
      97             : }
      98             : 
      99             : 
     100           0 : int os_mktime(int year, int month, int day, int hour, int min, int sec,
     101             :               os_time_t *t)
     102             : {
     103             :         struct tm tm, *tm1;
     104             :         time_t t_local, t1, t2;
     105             :         os_time_t tz_offset;
     106             : 
     107           0 :         if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
     108           0 :             hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
     109             :             sec > 60)
     110           0 :                 return -1;
     111             : 
     112           0 :         memset(&tm, 0, sizeof(tm));
     113           0 :         tm.tm_year = year - 1900;
     114           0 :         tm.tm_mon = month - 1;
     115           0 :         tm.tm_mday = day;
     116           0 :         tm.tm_hour = hour;
     117           0 :         tm.tm_min = min;
     118           0 :         tm.tm_sec = sec;
     119             : 
     120           0 :         t_local = mktime(&tm);
     121             : 
     122             :         /* figure out offset to UTC */
     123           0 :         tm1 = localtime(&t_local);
     124           0 :         if (tm1) {
     125           0 :                 t1 = mktime(tm1);
     126           0 :                 tm1 = gmtime(&t_local);
     127           0 :                 if (tm1) {
     128           0 :                         t2 = mktime(tm1);
     129           0 :                         tz_offset = t2 - t1;
     130             :                 } else
     131           0 :                         tz_offset = 0;
     132             :         } else
     133           0 :                 tz_offset = 0;
     134             : 
     135           0 :         *t = (os_time_t) t_local - tz_offset;
     136           0 :         return 0;
     137             : }
     138             : 
     139             : 
     140           6 : int os_gmtime(os_time_t t, struct os_tm *tm)
     141             : {
     142             :         struct tm *tm2;
     143           6 :         time_t t2 = t;
     144             : 
     145           6 :         tm2 = gmtime(&t2);
     146           6 :         if (tm2 == NULL)
     147           0 :                 return -1;
     148           6 :         tm->sec = tm2->tm_sec;
     149           6 :         tm->min = tm2->tm_min;
     150           6 :         tm->hour = tm2->tm_hour;
     151           6 :         tm->day = tm2->tm_mday;
     152           6 :         tm->month = tm2->tm_mon + 1;
     153           6 :         tm->year = tm2->tm_year + 1900;
     154           6 :         return 0;
     155             : }
     156             : 
     157             : 
     158             : #ifdef __APPLE__
     159             : #include <fcntl.h>
     160             : static int os_daemon(int nochdir, int noclose)
     161             : {
     162             :         int devnull;
     163             : 
     164             :         if (chdir("/") < 0)
     165             :                 return -1;
     166             : 
     167             :         devnull = open("/dev/null", O_RDWR);
     168             :         if (devnull < 0)
     169             :                 return -1;
     170             : 
     171             :         if (dup2(devnull, STDIN_FILENO) < 0) {
     172             :                 close(devnull);
     173             :                 return -1;
     174             :         }
     175             : 
     176             :         if (dup2(devnull, STDOUT_FILENO) < 0) {
     177             :                 close(devnull);
     178             :                 return -1;
     179             :         }
     180             : 
     181             :         if (dup2(devnull, STDERR_FILENO) < 0) {
     182             :                 close(devnull);
     183             :                 return -1;
     184             :         }
     185             : 
     186             :         return 0;
     187             : }
     188             : #else /* __APPLE__ */
     189             : #define os_daemon daemon
     190             : #endif /* __APPLE__ */
     191             : 
     192             : 
     193           0 : int os_daemonize(const char *pid_file)
     194             : {
     195             : #if defined(__uClinux__) || defined(__sun__)
     196             :         return -1;
     197             : #else /* defined(__uClinux__) || defined(__sun__) */
     198           0 :         if (os_daemon(0, 0)) {
     199           0 :                 perror("daemon");
     200           0 :                 return -1;
     201             :         }
     202             : 
     203           0 :         if (pid_file) {
     204           0 :                 FILE *f = fopen(pid_file, "w");
     205           0 :                 if (f) {
     206           0 :                         fprintf(f, "%u\n", getpid());
     207           0 :                         fclose(f);
     208             :                 }
     209             :         }
     210             : 
     211           0 :         return -0;
     212             : #endif /* defined(__uClinux__) || defined(__sun__) */
     213             : }
     214             : 
     215             : 
     216           2 : void os_daemonize_terminate(const char *pid_file)
     217             : {
     218           2 :         if (pid_file)
     219           0 :                 unlink(pid_file);
     220           2 : }
     221             : 
     222             : 
     223        8380 : int os_get_random(unsigned char *buf, size_t len)
     224             : {
     225             :         FILE *f;
     226             :         size_t rc;
     227             : 
     228        8380 :         f = fopen("/dev/urandom", "rb");
     229        8380 :         if (f == NULL) {
     230           0 :                 printf("Could not open /dev/urandom.\n");
     231           0 :                 return -1;
     232             :         }
     233             : 
     234        8380 :         rc = fread(buf, 1, len, f);
     235        8380 :         fclose(f);
     236             : 
     237        8380 :         return rc != len ? -1 : 0;
     238             : }
     239             : 
     240             : 
     241        1984 : unsigned long os_random(void)
     242             : {
     243        1984 :         return random();
     244             : }
     245             : 
     246             : 
     247          22 : char * os_rel2abs_path(const char *rel_path)
     248             : {
     249          22 :         char *buf = NULL, *cwd, *ret;
     250          22 :         size_t len = 128, cwd_len, rel_len, ret_len;
     251             :         int last_errno;
     252             : 
     253          22 :         if (!rel_path)
     254          10 :                 return NULL;
     255             : 
     256          12 :         if (rel_path[0] == '/')
     257           6 :                 return os_strdup(rel_path);
     258             : 
     259             :         for (;;) {
     260           6 :                 buf = os_malloc(len);
     261           6 :                 if (buf == NULL)
     262           0 :                         return NULL;
     263           6 :                 cwd = getcwd(buf, len);
     264           6 :                 if (cwd == NULL) {
     265           0 :                         last_errno = errno;
     266           0 :                         os_free(buf);
     267           0 :                         if (last_errno != ERANGE)
     268           0 :                                 return NULL;
     269           0 :                         len *= 2;
     270           0 :                         if (len > 2000)
     271           0 :                                 return NULL;
     272             :                 } else {
     273           6 :                         buf[len - 1] = '\0';
     274           6 :                         break;
     275             :                 }
     276           0 :         }
     277             : 
     278           6 :         cwd_len = os_strlen(cwd);
     279           6 :         rel_len = os_strlen(rel_path);
     280           6 :         ret_len = cwd_len + 1 + rel_len + 1;
     281           6 :         ret = os_malloc(ret_len);
     282           6 :         if (ret) {
     283           6 :                 os_memcpy(ret, cwd, cwd_len);
     284           6 :                 ret[cwd_len] = '/';
     285           6 :                 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
     286           6 :                 ret[ret_len - 1] = '\0';
     287             :         }
     288           6 :         os_free(buf);
     289           6 :         return ret;
     290             : }
     291             : 
     292             : 
     293           7 : int os_program_init(void)
     294             : {
     295             : #ifdef ANDROID
     296             :         /*
     297             :          * We ignore errors here since errors are normal if we
     298             :          * are already running as non-root.
     299             :          */
     300             : #ifdef ANDROID_SETGROUPS_OVERRIDE
     301             :         gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
     302             : #else /* ANDROID_SETGROUPS_OVERRIDE */
     303             :         gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
     304             : #endif /* ANDROID_SETGROUPS_OVERRIDE */
     305             :         struct __user_cap_header_struct header;
     306             :         struct __user_cap_data_struct cap;
     307             : 
     308             :         setgroups(ARRAY_SIZE(groups), groups);
     309             : 
     310             :         prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
     311             : 
     312             :         setgid(AID_WIFI);
     313             :         setuid(AID_WIFI);
     314             : 
     315             :         header.version = _LINUX_CAPABILITY_VERSION;
     316             :         header.pid = 0;
     317             :         cap.effective = cap.permitted =
     318             :                 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
     319             :         cap.inheritable = 0;
     320             :         capset(&header, &cap);
     321             : #endif /* ANDROID */
     322             : 
     323             : #ifdef WPA_TRACE
     324           7 :         dl_list_init(&alloc_list);
     325             : #endif /* WPA_TRACE */
     326           7 :         return 0;
     327             : }
     328             : 
     329             : 
     330           6 : void os_program_deinit(void)
     331             : {
     332             : #ifdef WPA_TRACE
     333             :         struct os_alloc_trace *a;
     334           6 :         unsigned long total = 0;
     335           6 :         dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
     336           0 :                 total += a->len;
     337           0 :                 if (a->magic != ALLOC_MAGIC) {
     338           0 :                         wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
     339             :                                    "len %lu",
     340             :                                    a, a->magic, (unsigned long) a->len);
     341           0 :                         continue;
     342             :                 }
     343           0 :                 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
     344             :                            a, (unsigned long) a->len);
     345           0 :                 wpa_trace_dump("memleak", a);
     346             :         }
     347           6 :         if (total)
     348           0 :                 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
     349             :                            (unsigned long) total);
     350             : #endif /* WPA_TRACE */
     351           6 : }
     352             : 
     353             : 
     354           0 : int os_setenv(const char *name, const char *value, int overwrite)
     355             : {
     356           0 :         return setenv(name, value, overwrite);
     357             : }
     358             : 
     359             : 
     360           0 : int os_unsetenv(const char *name)
     361             : {
     362             : #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
     363             :     defined(__OpenBSD__)
     364             :         unsetenv(name);
     365             :         return 0;
     366             : #else
     367           0 :         return unsetenv(name);
     368             : #endif
     369             : }
     370             : 
     371             : 
     372          13 : char * os_readfile(const char *name, size_t *len)
     373             : {
     374             :         FILE *f;
     375             :         char *buf;
     376             :         long pos;
     377             : 
     378          13 :         f = fopen(name, "rb");
     379          13 :         if (f == NULL)
     380           2 :                 return NULL;
     381             : 
     382          11 :         if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
     383           0 :                 fclose(f);
     384           0 :                 return NULL;
     385             :         }
     386          11 :         *len = pos;
     387          11 :         if (fseek(f, 0, SEEK_SET) < 0) {
     388           0 :                 fclose(f);
     389           0 :                 return NULL;
     390             :         }
     391             : 
     392          11 :         buf = os_malloc(*len);
     393          11 :         if (buf == NULL) {
     394           0 :                 fclose(f);
     395           0 :                 return NULL;
     396             :         }
     397             : 
     398          11 :         if (fread(buf, 1, *len, f) != *len) {
     399           0 :                 fclose(f);
     400           0 :                 os_free(buf);
     401           0 :                 return NULL;
     402             :         }
     403             : 
     404          11 :         fclose(f);
     405             : 
     406          11 :         return buf;
     407             : }
     408             : 
     409             : 
     410           0 : int os_file_exists(const char *fname)
     411             : {
     412           0 :         FILE *f = fopen(fname, "rb");
     413           0 :         if (f == NULL)
     414           0 :                 return 0;
     415           0 :         fclose(f);
     416           0 :         return 1;
     417             : }
     418             : 
     419             : 
     420             : #ifndef WPA_TRACE
     421             : void * os_zalloc(size_t size)
     422             : {
     423             :         return calloc(1, size);
     424             : }
     425             : #endif /* WPA_TRACE */
     426             : 
     427             : 
     428       45175 : size_t os_strlcpy(char *dest, const char *src, size_t siz)
     429             : {
     430       45175 :         const char *s = src;
     431       45175 :         size_t left = siz;
     432             : 
     433       45175 :         if (left) {
     434             :                 /* Copy string up to the maximum size of the dest buffer */
     435      312470 :                 while (--left != 0) {
     436      267119 :                         if ((*dest++ = *s++) == '\0')
     437       44999 :                                 break;
     438             :                 }
     439             :         }
     440             : 
     441       45175 :         if (left == 0) {
     442             :                 /* Not enough room for the string; force NUL-termination */
     443         176 :                 if (siz != 0)
     444         176 :                         *dest = '\0';
     445         176 :                 while (*s++)
     446             :                         ; /* determine total src string length */
     447             :         }
     448             : 
     449       45175 :         return s - src - 1;
     450             : }
     451             : 
     452             : 
     453             : #ifdef WPA_TRACE
     454             : 
     455      876682 : void * os_malloc(size_t size)
     456             : {
     457             :         struct os_alloc_trace *a;
     458      876682 :         a = malloc(sizeof(*a) + size);
     459      876682 :         if (a == NULL)
     460           0 :                 return NULL;
     461      876682 :         a->magic = ALLOC_MAGIC;
     462      876682 :         dl_list_add(&alloc_list, &a->list);
     463      876682 :         a->len = size;
     464      876682 :         wpa_trace_record(a);
     465      876682 :         return a + 1;
     466             : }
     467             : 
     468             : 
     469      175060 : void * os_realloc(void *ptr, size_t size)
     470             : {
     471             :         struct os_alloc_trace *a;
     472             :         size_t copy_len;
     473             :         void *n;
     474             : 
     475      175060 :         if (ptr == NULL)
     476       17478 :                 return os_malloc(size);
     477             : 
     478      157582 :         a = (struct os_alloc_trace *) ptr - 1;
     479      157582 :         if (a->magic != ALLOC_MAGIC) {
     480           0 :                 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
     481             :                            a, a->magic,
     482           0 :                            a->magic == FREED_MAGIC ? " (already freed)" : "");
     483           0 :                 wpa_trace_show("Invalid os_realloc() call");
     484           0 :                 abort();
     485             :         }
     486      157582 :         n = os_malloc(size);
     487      157582 :         if (n == NULL)
     488           0 :                 return NULL;
     489      157582 :         copy_len = a->len;
     490      157582 :         if (copy_len > size)
     491         917 :                 copy_len = size;
     492      157582 :         os_memcpy(n, a + 1, copy_len);
     493      157582 :         os_free(ptr);
     494      157582 :         return n;
     495             : }
     496             : 
     497             : 
     498     1113459 : void os_free(void *ptr)
     499             : {
     500             :         struct os_alloc_trace *a;
     501             : 
     502     1113459 :         if (ptr == NULL)
     503     1350236 :                 return;
     504      876682 :         a = (struct os_alloc_trace *) ptr - 1;
     505      876682 :         if (a->magic != ALLOC_MAGIC) {
     506           0 :                 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
     507             :                            a, a->magic,
     508           0 :                            a->magic == FREED_MAGIC ? " (already freed)" : "");
     509           0 :                 wpa_trace_show("Invalid os_free() call");
     510           0 :                 abort();
     511             :         }
     512      876682 :         dl_list_del(&a->list);
     513      876682 :         a->magic = FREED_MAGIC;
     514             : 
     515      876682 :         wpa_trace_check_ref(ptr);
     516      876682 :         free(a);
     517             : }
     518             : 
     519             : 
     520      217844 : void * os_zalloc(size_t size)
     521             : {
     522      217844 :         void *ptr = os_malloc(size);
     523      217844 :         if (ptr)
     524      217844 :                 os_memset(ptr, 0, size);
     525      217844 :         return ptr;
     526             : }
     527             : 
     528             : 
     529       12026 : char * os_strdup(const char *s)
     530             : {
     531             :         size_t len;
     532             :         char *d;
     533       12026 :         len = os_strlen(s);
     534       12026 :         d = os_malloc(len + 1);
     535       12026 :         if (d == NULL)
     536           0 :                 return NULL;
     537       12026 :         os_memcpy(d, s, len);
     538       12026 :         d[len] = '\0';
     539       12026 :         return d;
     540             : }
     541             : 
     542             : #endif /* WPA_TRACE */

Generated by: LCOV version 1.10