xref: /dflybsd-src/contrib/wpa_supplicant/src/utils/os_unix.c (revision 3ff40c12445a6f5918b9c6e9c7031bc0cb8786d1)
16d49e1aeSJan Lentfer /*
2*3ff40c12SJohn Marino  * OS specific functions for UNIX/POSIX systems
3*3ff40c12SJohn Marino  * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer  *
5*3ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
6*3ff40c12SJohn Marino  * See README for more details.
76d49e1aeSJan Lentfer  */
86d49e1aeSJan Lentfer 
96d49e1aeSJan Lentfer #include "includes.h"
106d49e1aeSJan Lentfer 
11*3ff40c12SJohn Marino #include <time.h>
12*3ff40c12SJohn Marino 
13*3ff40c12SJohn Marino #ifdef ANDROID
14*3ff40c12SJohn Marino #include <sys/capability.h>
15*3ff40c12SJohn Marino #include <linux/prctl.h>
16*3ff40c12SJohn Marino #include <private/android_filesystem_config.h>
17*3ff40c12SJohn Marino #endif /* ANDROID */
18*3ff40c12SJohn Marino 
196d49e1aeSJan Lentfer #include "os.h"
20*3ff40c12SJohn Marino #include "common.h"
21*3ff40c12SJohn Marino 
22*3ff40c12SJohn Marino #ifdef WPA_TRACE
23*3ff40c12SJohn Marino 
24*3ff40c12SJohn Marino #include "wpa_debug.h"
25*3ff40c12SJohn Marino #include "trace.h"
26*3ff40c12SJohn Marino #include "list.h"
27*3ff40c12SJohn Marino 
28*3ff40c12SJohn Marino static struct dl_list alloc_list;
29*3ff40c12SJohn Marino 
30*3ff40c12SJohn Marino #define ALLOC_MAGIC 0xa84ef1b2
31*3ff40c12SJohn Marino #define FREED_MAGIC 0x67fd487a
32*3ff40c12SJohn Marino 
33*3ff40c12SJohn Marino struct os_alloc_trace {
34*3ff40c12SJohn Marino 	unsigned int magic;
35*3ff40c12SJohn Marino 	struct dl_list list;
36*3ff40c12SJohn Marino 	size_t len;
37*3ff40c12SJohn Marino 	WPA_TRACE_INFO
38*3ff40c12SJohn Marino };
39*3ff40c12SJohn Marino 
40*3ff40c12SJohn Marino #endif /* WPA_TRACE */
41*3ff40c12SJohn Marino 
426d49e1aeSJan Lentfer 
436d49e1aeSJan Lentfer void os_sleep(os_time_t sec, os_time_t usec)
446d49e1aeSJan Lentfer {
456d49e1aeSJan Lentfer 	if (sec)
466d49e1aeSJan Lentfer 		sleep(sec);
476d49e1aeSJan Lentfer 	if (usec)
486d49e1aeSJan Lentfer 		usleep(usec);
496d49e1aeSJan Lentfer }
506d49e1aeSJan Lentfer 
516d49e1aeSJan Lentfer 
526d49e1aeSJan Lentfer int os_get_time(struct os_time *t)
536d49e1aeSJan Lentfer {
546d49e1aeSJan Lentfer 	int res;
556d49e1aeSJan Lentfer 	struct timeval tv;
566d49e1aeSJan Lentfer 	res = gettimeofday(&tv, NULL);
576d49e1aeSJan Lentfer 	t->sec = tv.tv_sec;
586d49e1aeSJan Lentfer 	t->usec = tv.tv_usec;
596d49e1aeSJan Lentfer 	return res;
606d49e1aeSJan Lentfer }
616d49e1aeSJan Lentfer 
626d49e1aeSJan Lentfer 
63*3ff40c12SJohn Marino int os_get_reltime(struct os_reltime *t)
64*3ff40c12SJohn Marino {
65*3ff40c12SJohn Marino #if defined(CLOCK_BOOTTIME)
66*3ff40c12SJohn Marino 	static clockid_t clock_id = CLOCK_BOOTTIME;
67*3ff40c12SJohn Marino #elif defined(CLOCK_MONOTONIC)
68*3ff40c12SJohn Marino 	static clockid_t clock_id = CLOCK_MONOTONIC;
69*3ff40c12SJohn Marino #else
70*3ff40c12SJohn Marino 	static clockid_t clock_id = CLOCK_REALTIME;
71*3ff40c12SJohn Marino #endif
72*3ff40c12SJohn Marino 	struct timespec ts;
73*3ff40c12SJohn Marino 	int res;
74*3ff40c12SJohn Marino 
75*3ff40c12SJohn Marino 	while (1) {
76*3ff40c12SJohn Marino 		res = clock_gettime(clock_id, &ts);
77*3ff40c12SJohn Marino 		if (res == 0) {
78*3ff40c12SJohn Marino 			t->sec = ts.tv_sec;
79*3ff40c12SJohn Marino 			t->usec = ts.tv_nsec / 1000;
80*3ff40c12SJohn Marino 			return 0;
81*3ff40c12SJohn Marino 		}
82*3ff40c12SJohn Marino 		switch (clock_id) {
83*3ff40c12SJohn Marino #ifdef CLOCK_BOOTTIME
84*3ff40c12SJohn Marino 		case CLOCK_BOOTTIME:
85*3ff40c12SJohn Marino 			clock_id = CLOCK_MONOTONIC;
86*3ff40c12SJohn Marino 			break;
87*3ff40c12SJohn Marino #endif
88*3ff40c12SJohn Marino #ifdef CLOCK_MONOTONIC
89*3ff40c12SJohn Marino 		case CLOCK_MONOTONIC:
90*3ff40c12SJohn Marino 			clock_id = CLOCK_REALTIME;
91*3ff40c12SJohn Marino 			break;
92*3ff40c12SJohn Marino #endif
93*3ff40c12SJohn Marino 		case CLOCK_REALTIME:
94*3ff40c12SJohn Marino 			return -1;
95*3ff40c12SJohn Marino 		}
96*3ff40c12SJohn Marino 	}
97*3ff40c12SJohn Marino }
98*3ff40c12SJohn Marino 
99*3ff40c12SJohn Marino 
1006d49e1aeSJan Lentfer int os_mktime(int year, int month, int day, int hour, int min, int sec,
1016d49e1aeSJan Lentfer 	      os_time_t *t)
1026d49e1aeSJan Lentfer {
1036d49e1aeSJan Lentfer 	struct tm tm, *tm1;
1046d49e1aeSJan Lentfer 	time_t t_local, t1, t2;
1056d49e1aeSJan Lentfer 	os_time_t tz_offset;
1066d49e1aeSJan Lentfer 
1076d49e1aeSJan Lentfer 	if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
1086d49e1aeSJan Lentfer 	    hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
1096d49e1aeSJan Lentfer 	    sec > 60)
1106d49e1aeSJan Lentfer 		return -1;
1116d49e1aeSJan Lentfer 
1126d49e1aeSJan Lentfer 	memset(&tm, 0, sizeof(tm));
1136d49e1aeSJan Lentfer 	tm.tm_year = year - 1900;
1146d49e1aeSJan Lentfer 	tm.tm_mon = month - 1;
1156d49e1aeSJan Lentfer 	tm.tm_mday = day;
1166d49e1aeSJan Lentfer 	tm.tm_hour = hour;
1176d49e1aeSJan Lentfer 	tm.tm_min = min;
1186d49e1aeSJan Lentfer 	tm.tm_sec = sec;
1196d49e1aeSJan Lentfer 
1206d49e1aeSJan Lentfer 	t_local = mktime(&tm);
1216d49e1aeSJan Lentfer 
1226d49e1aeSJan Lentfer 	/* figure out offset to UTC */
1236d49e1aeSJan Lentfer 	tm1 = localtime(&t_local);
1246d49e1aeSJan Lentfer 	if (tm1) {
1256d49e1aeSJan Lentfer 		t1 = mktime(tm1);
1266d49e1aeSJan Lentfer 		tm1 = gmtime(&t_local);
1276d49e1aeSJan Lentfer 		if (tm1) {
1286d49e1aeSJan Lentfer 			t2 = mktime(tm1);
1296d49e1aeSJan Lentfer 			tz_offset = t2 - t1;
1306d49e1aeSJan Lentfer 		} else
1316d49e1aeSJan Lentfer 			tz_offset = 0;
1326d49e1aeSJan Lentfer 	} else
1336d49e1aeSJan Lentfer 		tz_offset = 0;
1346d49e1aeSJan Lentfer 
1356d49e1aeSJan Lentfer 	*t = (os_time_t) t_local - tz_offset;
1366d49e1aeSJan Lentfer 	return 0;
1376d49e1aeSJan Lentfer }
1386d49e1aeSJan Lentfer 
1396d49e1aeSJan Lentfer 
140*3ff40c12SJohn Marino int os_gmtime(os_time_t t, struct os_tm *tm)
141*3ff40c12SJohn Marino {
142*3ff40c12SJohn Marino 	struct tm *tm2;
143*3ff40c12SJohn Marino 	time_t t2 = t;
144*3ff40c12SJohn Marino 
145*3ff40c12SJohn Marino 	tm2 = gmtime(&t2);
146*3ff40c12SJohn Marino 	if (tm2 == NULL)
147*3ff40c12SJohn Marino 		return -1;
148*3ff40c12SJohn Marino 	tm->sec = tm2->tm_sec;
149*3ff40c12SJohn Marino 	tm->min = tm2->tm_min;
150*3ff40c12SJohn Marino 	tm->hour = tm2->tm_hour;
151*3ff40c12SJohn Marino 	tm->day = tm2->tm_mday;
152*3ff40c12SJohn Marino 	tm->month = tm2->tm_mon + 1;
153*3ff40c12SJohn Marino 	tm->year = tm2->tm_year + 1900;
154*3ff40c12SJohn Marino 	return 0;
155*3ff40c12SJohn Marino }
156*3ff40c12SJohn Marino 
157*3ff40c12SJohn Marino 
1586d49e1aeSJan Lentfer #ifdef __APPLE__
1596d49e1aeSJan Lentfer #include <fcntl.h>
1606d49e1aeSJan Lentfer static int os_daemon(int nochdir, int noclose)
1616d49e1aeSJan Lentfer {
1626d49e1aeSJan Lentfer 	int devnull;
1636d49e1aeSJan Lentfer 
1646d49e1aeSJan Lentfer 	if (chdir("/") < 0)
1656d49e1aeSJan Lentfer 		return -1;
1666d49e1aeSJan Lentfer 
1676d49e1aeSJan Lentfer 	devnull = open("/dev/null", O_RDWR);
1686d49e1aeSJan Lentfer 	if (devnull < 0)
1696d49e1aeSJan Lentfer 		return -1;
1706d49e1aeSJan Lentfer 
1716d49e1aeSJan Lentfer 	if (dup2(devnull, STDIN_FILENO) < 0) {
1726d49e1aeSJan Lentfer 		close(devnull);
1736d49e1aeSJan Lentfer 		return -1;
1746d49e1aeSJan Lentfer 	}
1756d49e1aeSJan Lentfer 
1766d49e1aeSJan Lentfer 	if (dup2(devnull, STDOUT_FILENO) < 0) {
1776d49e1aeSJan Lentfer 		close(devnull);
1786d49e1aeSJan Lentfer 		return -1;
1796d49e1aeSJan Lentfer 	}
1806d49e1aeSJan Lentfer 
1816d49e1aeSJan Lentfer 	if (dup2(devnull, STDERR_FILENO) < 0) {
1826d49e1aeSJan Lentfer 		close(devnull);
1836d49e1aeSJan Lentfer 		return -1;
1846d49e1aeSJan Lentfer 	}
1856d49e1aeSJan Lentfer 
1866d49e1aeSJan Lentfer 	return 0;
1876d49e1aeSJan Lentfer }
1886d49e1aeSJan Lentfer #else /* __APPLE__ */
1896d49e1aeSJan Lentfer #define os_daemon daemon
1906d49e1aeSJan Lentfer #endif /* __APPLE__ */
1916d49e1aeSJan Lentfer 
1926d49e1aeSJan Lentfer 
1936d49e1aeSJan Lentfer int os_daemonize(const char *pid_file)
1946d49e1aeSJan Lentfer {
195*3ff40c12SJohn Marino #if defined(__uClinux__) || defined(__sun__)
1966d49e1aeSJan Lentfer 	return -1;
197*3ff40c12SJohn Marino #else /* defined(__uClinux__) || defined(__sun__) */
1986d49e1aeSJan Lentfer 	if (os_daemon(0, 0)) {
1996d49e1aeSJan Lentfer 		perror("daemon");
2006d49e1aeSJan Lentfer 		return -1;
2016d49e1aeSJan Lentfer 	}
2026d49e1aeSJan Lentfer 
2036d49e1aeSJan Lentfer 	if (pid_file) {
2046d49e1aeSJan Lentfer 		FILE *f = fopen(pid_file, "w");
2056d49e1aeSJan Lentfer 		if (f) {
2066d49e1aeSJan Lentfer 			fprintf(f, "%u\n", getpid());
2076d49e1aeSJan Lentfer 			fclose(f);
2086d49e1aeSJan Lentfer 		}
2096d49e1aeSJan Lentfer 	}
2106d49e1aeSJan Lentfer 
2116d49e1aeSJan Lentfer 	return -0;
212*3ff40c12SJohn Marino #endif /* defined(__uClinux__) || defined(__sun__) */
2136d49e1aeSJan Lentfer }
2146d49e1aeSJan Lentfer 
2156d49e1aeSJan Lentfer 
2166d49e1aeSJan Lentfer void os_daemonize_terminate(const char *pid_file)
2176d49e1aeSJan Lentfer {
2186d49e1aeSJan Lentfer 	if (pid_file)
2196d49e1aeSJan Lentfer 		unlink(pid_file);
2206d49e1aeSJan Lentfer }
2216d49e1aeSJan Lentfer 
2226d49e1aeSJan Lentfer 
2236d49e1aeSJan Lentfer int os_get_random(unsigned char *buf, size_t len)
2246d49e1aeSJan Lentfer {
2256d49e1aeSJan Lentfer 	FILE *f;
2266d49e1aeSJan Lentfer 	size_t rc;
2276d49e1aeSJan Lentfer 
2286d49e1aeSJan Lentfer 	f = fopen("/dev/urandom", "rb");
2296d49e1aeSJan Lentfer 	if (f == NULL) {
2306d49e1aeSJan Lentfer 		printf("Could not open /dev/urandom.\n");
2316d49e1aeSJan Lentfer 		return -1;
2326d49e1aeSJan Lentfer 	}
2336d49e1aeSJan Lentfer 
2346d49e1aeSJan Lentfer 	rc = fread(buf, 1, len, f);
2356d49e1aeSJan Lentfer 	fclose(f);
2366d49e1aeSJan Lentfer 
2376d49e1aeSJan Lentfer 	return rc != len ? -1 : 0;
2386d49e1aeSJan Lentfer }
2396d49e1aeSJan Lentfer 
2406d49e1aeSJan Lentfer 
2416d49e1aeSJan Lentfer unsigned long os_random(void)
2426d49e1aeSJan Lentfer {
2436d49e1aeSJan Lentfer 	return random();
2446d49e1aeSJan Lentfer }
2456d49e1aeSJan Lentfer 
2466d49e1aeSJan Lentfer 
2476d49e1aeSJan Lentfer char * os_rel2abs_path(const char *rel_path)
2486d49e1aeSJan Lentfer {
2496d49e1aeSJan Lentfer 	char *buf = NULL, *cwd, *ret;
2506d49e1aeSJan Lentfer 	size_t len = 128, cwd_len, rel_len, ret_len;
2516d49e1aeSJan Lentfer 	int last_errno;
2526d49e1aeSJan Lentfer 
253*3ff40c12SJohn Marino 	if (!rel_path)
254*3ff40c12SJohn Marino 		return NULL;
255*3ff40c12SJohn Marino 
2566d49e1aeSJan Lentfer 	if (rel_path[0] == '/')
257*3ff40c12SJohn Marino 		return os_strdup(rel_path);
2586d49e1aeSJan Lentfer 
2596d49e1aeSJan Lentfer 	for (;;) {
260*3ff40c12SJohn Marino 		buf = os_malloc(len);
2616d49e1aeSJan Lentfer 		if (buf == NULL)
2626d49e1aeSJan Lentfer 			return NULL;
2636d49e1aeSJan Lentfer 		cwd = getcwd(buf, len);
2646d49e1aeSJan Lentfer 		if (cwd == NULL) {
2656d49e1aeSJan Lentfer 			last_errno = errno;
266*3ff40c12SJohn Marino 			os_free(buf);
2676d49e1aeSJan Lentfer 			if (last_errno != ERANGE)
2686d49e1aeSJan Lentfer 				return NULL;
2696d49e1aeSJan Lentfer 			len *= 2;
2706d49e1aeSJan Lentfer 			if (len > 2000)
2716d49e1aeSJan Lentfer 				return NULL;
2726d49e1aeSJan Lentfer 		} else {
2736d49e1aeSJan Lentfer 			buf[len - 1] = '\0';
2746d49e1aeSJan Lentfer 			break;
2756d49e1aeSJan Lentfer 		}
2766d49e1aeSJan Lentfer 	}
2776d49e1aeSJan Lentfer 
278*3ff40c12SJohn Marino 	cwd_len = os_strlen(cwd);
279*3ff40c12SJohn Marino 	rel_len = os_strlen(rel_path);
2806d49e1aeSJan Lentfer 	ret_len = cwd_len + 1 + rel_len + 1;
281*3ff40c12SJohn Marino 	ret = os_malloc(ret_len);
2826d49e1aeSJan Lentfer 	if (ret) {
283*3ff40c12SJohn Marino 		os_memcpy(ret, cwd, cwd_len);
2846d49e1aeSJan Lentfer 		ret[cwd_len] = '/';
285*3ff40c12SJohn Marino 		os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
2866d49e1aeSJan Lentfer 		ret[ret_len - 1] = '\0';
2876d49e1aeSJan Lentfer 	}
288*3ff40c12SJohn Marino 	os_free(buf);
2896d49e1aeSJan Lentfer 	return ret;
2906d49e1aeSJan Lentfer }
2916d49e1aeSJan Lentfer 
2926d49e1aeSJan Lentfer 
2936d49e1aeSJan Lentfer int os_program_init(void)
2946d49e1aeSJan Lentfer {
295*3ff40c12SJohn Marino #ifdef ANDROID
296*3ff40c12SJohn Marino 	/*
297*3ff40c12SJohn Marino 	 * We ignore errors here since errors are normal if we
298*3ff40c12SJohn Marino 	 * are already running as non-root.
299*3ff40c12SJohn Marino 	 */
300*3ff40c12SJohn Marino #ifdef ANDROID_SETGROUPS_OVERRIDE
301*3ff40c12SJohn Marino 	gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
302*3ff40c12SJohn Marino #else /* ANDROID_SETGROUPS_OVERRIDE */
303*3ff40c12SJohn Marino 	gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
304*3ff40c12SJohn Marino #endif /* ANDROID_SETGROUPS_OVERRIDE */
305*3ff40c12SJohn Marino 	struct __user_cap_header_struct header;
306*3ff40c12SJohn Marino 	struct __user_cap_data_struct cap;
307*3ff40c12SJohn Marino 
308*3ff40c12SJohn Marino 	setgroups(ARRAY_SIZE(groups), groups);
309*3ff40c12SJohn Marino 
310*3ff40c12SJohn Marino 	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
311*3ff40c12SJohn Marino 
312*3ff40c12SJohn Marino 	setgid(AID_WIFI);
313*3ff40c12SJohn Marino 	setuid(AID_WIFI);
314*3ff40c12SJohn Marino 
315*3ff40c12SJohn Marino 	header.version = _LINUX_CAPABILITY_VERSION;
316*3ff40c12SJohn Marino 	header.pid = 0;
317*3ff40c12SJohn Marino 	cap.effective = cap.permitted =
318*3ff40c12SJohn Marino 		(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
319*3ff40c12SJohn Marino 	cap.inheritable = 0;
320*3ff40c12SJohn Marino 	capset(&header, &cap);
321*3ff40c12SJohn Marino #endif /* ANDROID */
322*3ff40c12SJohn Marino 
323*3ff40c12SJohn Marino #ifdef WPA_TRACE
324*3ff40c12SJohn Marino 	dl_list_init(&alloc_list);
325*3ff40c12SJohn Marino #endif /* WPA_TRACE */
3266d49e1aeSJan Lentfer 	return 0;
3276d49e1aeSJan Lentfer }
3286d49e1aeSJan Lentfer 
3296d49e1aeSJan Lentfer 
3306d49e1aeSJan Lentfer void os_program_deinit(void)
3316d49e1aeSJan Lentfer {
332*3ff40c12SJohn Marino #ifdef WPA_TRACE
333*3ff40c12SJohn Marino 	struct os_alloc_trace *a;
334*3ff40c12SJohn Marino 	unsigned long total = 0;
335*3ff40c12SJohn Marino 	dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
336*3ff40c12SJohn Marino 		total += a->len;
337*3ff40c12SJohn Marino 		if (a->magic != ALLOC_MAGIC) {
338*3ff40c12SJohn Marino 			wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
339*3ff40c12SJohn Marino 				   "len %lu",
340*3ff40c12SJohn Marino 				   a, a->magic, (unsigned long) a->len);
341*3ff40c12SJohn Marino 			continue;
342*3ff40c12SJohn Marino 		}
343*3ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
344*3ff40c12SJohn Marino 			   a, (unsigned long) a->len);
345*3ff40c12SJohn Marino 		wpa_trace_dump("memleak", a);
346*3ff40c12SJohn Marino 	}
347*3ff40c12SJohn Marino 	if (total)
348*3ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
349*3ff40c12SJohn Marino 			   (unsigned long) total);
350*3ff40c12SJohn Marino #endif /* WPA_TRACE */
3516d49e1aeSJan Lentfer }
3526d49e1aeSJan Lentfer 
3536d49e1aeSJan Lentfer 
3546d49e1aeSJan Lentfer int os_setenv(const char *name, const char *value, int overwrite)
3556d49e1aeSJan Lentfer {
3566d49e1aeSJan Lentfer 	return setenv(name, value, overwrite);
3576d49e1aeSJan Lentfer }
3586d49e1aeSJan Lentfer 
3596d49e1aeSJan Lentfer 
3606d49e1aeSJan Lentfer int os_unsetenv(const char *name)
3616d49e1aeSJan Lentfer {
3626d49e1aeSJan Lentfer #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
3636d49e1aeSJan Lentfer     defined(__OpenBSD__)
3646d49e1aeSJan Lentfer 	unsetenv(name);
3656d49e1aeSJan Lentfer 	return 0;
3666d49e1aeSJan Lentfer #else
3676d49e1aeSJan Lentfer 	return unsetenv(name);
3686d49e1aeSJan Lentfer #endif
3696d49e1aeSJan Lentfer }
3706d49e1aeSJan Lentfer 
3716d49e1aeSJan Lentfer 
3726d49e1aeSJan Lentfer char * os_readfile(const char *name, size_t *len)
3736d49e1aeSJan Lentfer {
3746d49e1aeSJan Lentfer 	FILE *f;
3756d49e1aeSJan Lentfer 	char *buf;
376*3ff40c12SJohn Marino 	long pos;
3776d49e1aeSJan Lentfer 
3786d49e1aeSJan Lentfer 	f = fopen(name, "rb");
3796d49e1aeSJan Lentfer 	if (f == NULL)
3806d49e1aeSJan Lentfer 		return NULL;
3816d49e1aeSJan Lentfer 
382*3ff40c12SJohn Marino 	if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
383*3ff40c12SJohn Marino 		fclose(f);
384*3ff40c12SJohn Marino 		return NULL;
385*3ff40c12SJohn Marino 	}
386*3ff40c12SJohn Marino 	*len = pos;
387*3ff40c12SJohn Marino 	if (fseek(f, 0, SEEK_SET) < 0) {
388*3ff40c12SJohn Marino 		fclose(f);
389*3ff40c12SJohn Marino 		return NULL;
390*3ff40c12SJohn Marino 	}
3916d49e1aeSJan Lentfer 
392*3ff40c12SJohn Marino 	buf = os_malloc(*len);
3936d49e1aeSJan Lentfer 	if (buf == NULL) {
3946d49e1aeSJan Lentfer 		fclose(f);
3956d49e1aeSJan Lentfer 		return NULL;
3966d49e1aeSJan Lentfer 	}
3976d49e1aeSJan Lentfer 
3986d49e1aeSJan Lentfer 	if (fread(buf, 1, *len, f) != *len) {
3996d49e1aeSJan Lentfer 		fclose(f);
400*3ff40c12SJohn Marino 		os_free(buf);
4016d49e1aeSJan Lentfer 		return NULL;
4026d49e1aeSJan Lentfer 	}
4036d49e1aeSJan Lentfer 
4046d49e1aeSJan Lentfer 	fclose(f);
4056d49e1aeSJan Lentfer 
4066d49e1aeSJan Lentfer 	return buf;
4076d49e1aeSJan Lentfer }
4086d49e1aeSJan Lentfer 
4096d49e1aeSJan Lentfer 
410*3ff40c12SJohn Marino #ifndef WPA_TRACE
4116d49e1aeSJan Lentfer void * os_zalloc(size_t size)
4126d49e1aeSJan Lentfer {
4136d49e1aeSJan Lentfer 	return calloc(1, size);
4146d49e1aeSJan Lentfer }
415*3ff40c12SJohn Marino #endif /* WPA_TRACE */
4166d49e1aeSJan Lentfer 
4176d49e1aeSJan Lentfer 
4186d49e1aeSJan Lentfer size_t os_strlcpy(char *dest, const char *src, size_t siz)
4196d49e1aeSJan Lentfer {
4206d49e1aeSJan Lentfer 	const char *s = src;
4216d49e1aeSJan Lentfer 	size_t left = siz;
4226d49e1aeSJan Lentfer 
4236d49e1aeSJan Lentfer 	if (left) {
4246d49e1aeSJan Lentfer 		/* Copy string up to the maximum size of the dest buffer */
4256d49e1aeSJan Lentfer 		while (--left != 0) {
4266d49e1aeSJan Lentfer 			if ((*dest++ = *s++) == '\0')
4276d49e1aeSJan Lentfer 				break;
4286d49e1aeSJan Lentfer 		}
4296d49e1aeSJan Lentfer 	}
4306d49e1aeSJan Lentfer 
4316d49e1aeSJan Lentfer 	if (left == 0) {
4326d49e1aeSJan Lentfer 		/* Not enough room for the string; force NUL-termination */
4336d49e1aeSJan Lentfer 		if (siz != 0)
4346d49e1aeSJan Lentfer 			*dest = '\0';
4356d49e1aeSJan Lentfer 		while (*s++)
4366d49e1aeSJan Lentfer 			; /* determine total src string length */
4376d49e1aeSJan Lentfer 	}
4386d49e1aeSJan Lentfer 
4396d49e1aeSJan Lentfer 	return s - src - 1;
4406d49e1aeSJan Lentfer }
441*3ff40c12SJohn Marino 
442*3ff40c12SJohn Marino 
443*3ff40c12SJohn Marino #ifdef WPA_TRACE
444*3ff40c12SJohn Marino 
445*3ff40c12SJohn Marino void * os_malloc(size_t size)
446*3ff40c12SJohn Marino {
447*3ff40c12SJohn Marino 	struct os_alloc_trace *a;
448*3ff40c12SJohn Marino 	a = malloc(sizeof(*a) + size);
449*3ff40c12SJohn Marino 	if (a == NULL)
450*3ff40c12SJohn Marino 		return NULL;
451*3ff40c12SJohn Marino 	a->magic = ALLOC_MAGIC;
452*3ff40c12SJohn Marino 	dl_list_add(&alloc_list, &a->list);
453*3ff40c12SJohn Marino 	a->len = size;
454*3ff40c12SJohn Marino 	wpa_trace_record(a);
455*3ff40c12SJohn Marino 	return a + 1;
456*3ff40c12SJohn Marino }
457*3ff40c12SJohn Marino 
458*3ff40c12SJohn Marino 
459*3ff40c12SJohn Marino void * os_realloc(void *ptr, size_t size)
460*3ff40c12SJohn Marino {
461*3ff40c12SJohn Marino 	struct os_alloc_trace *a;
462*3ff40c12SJohn Marino 	size_t copy_len;
463*3ff40c12SJohn Marino 	void *n;
464*3ff40c12SJohn Marino 
465*3ff40c12SJohn Marino 	if (ptr == NULL)
466*3ff40c12SJohn Marino 		return os_malloc(size);
467*3ff40c12SJohn Marino 
468*3ff40c12SJohn Marino 	a = (struct os_alloc_trace *) ptr - 1;
469*3ff40c12SJohn Marino 	if (a->magic != ALLOC_MAGIC) {
470*3ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
471*3ff40c12SJohn Marino 			   a, a->magic,
472*3ff40c12SJohn Marino 			   a->magic == FREED_MAGIC ? " (already freed)" : "");
473*3ff40c12SJohn Marino 		wpa_trace_show("Invalid os_realloc() call");
474*3ff40c12SJohn Marino 		abort();
475*3ff40c12SJohn Marino 	}
476*3ff40c12SJohn Marino 	n = os_malloc(size);
477*3ff40c12SJohn Marino 	if (n == NULL)
478*3ff40c12SJohn Marino 		return NULL;
479*3ff40c12SJohn Marino 	copy_len = a->len;
480*3ff40c12SJohn Marino 	if (copy_len > size)
481*3ff40c12SJohn Marino 		copy_len = size;
482*3ff40c12SJohn Marino 	os_memcpy(n, a + 1, copy_len);
483*3ff40c12SJohn Marino 	os_free(ptr);
484*3ff40c12SJohn Marino 	return n;
485*3ff40c12SJohn Marino }
486*3ff40c12SJohn Marino 
487*3ff40c12SJohn Marino 
488*3ff40c12SJohn Marino void os_free(void *ptr)
489*3ff40c12SJohn Marino {
490*3ff40c12SJohn Marino 	struct os_alloc_trace *a;
491*3ff40c12SJohn Marino 
492*3ff40c12SJohn Marino 	if (ptr == NULL)
493*3ff40c12SJohn Marino 		return;
494*3ff40c12SJohn Marino 	a = (struct os_alloc_trace *) ptr - 1;
495*3ff40c12SJohn Marino 	if (a->magic != ALLOC_MAGIC) {
496*3ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
497*3ff40c12SJohn Marino 			   a, a->magic,
498*3ff40c12SJohn Marino 			   a->magic == FREED_MAGIC ? " (already freed)" : "");
499*3ff40c12SJohn Marino 		wpa_trace_show("Invalid os_free() call");
500*3ff40c12SJohn Marino 		abort();
501*3ff40c12SJohn Marino 	}
502*3ff40c12SJohn Marino 	dl_list_del(&a->list);
503*3ff40c12SJohn Marino 	a->magic = FREED_MAGIC;
504*3ff40c12SJohn Marino 
505*3ff40c12SJohn Marino 	wpa_trace_check_ref(ptr);
506*3ff40c12SJohn Marino 	free(a);
507*3ff40c12SJohn Marino }
508*3ff40c12SJohn Marino 
509*3ff40c12SJohn Marino 
510*3ff40c12SJohn Marino void * os_zalloc(size_t size)
511*3ff40c12SJohn Marino {
512*3ff40c12SJohn Marino 	void *ptr = os_malloc(size);
513*3ff40c12SJohn Marino 	if (ptr)
514*3ff40c12SJohn Marino 		os_memset(ptr, 0, size);
515*3ff40c12SJohn Marino 	return ptr;
516*3ff40c12SJohn Marino }
517*3ff40c12SJohn Marino 
518*3ff40c12SJohn Marino 
519*3ff40c12SJohn Marino char * os_strdup(const char *s)
520*3ff40c12SJohn Marino {
521*3ff40c12SJohn Marino 	size_t len;
522*3ff40c12SJohn Marino 	char *d;
523*3ff40c12SJohn Marino 	len = os_strlen(s);
524*3ff40c12SJohn Marino 	d = os_malloc(len + 1);
525*3ff40c12SJohn Marino 	if (d == NULL)
526*3ff40c12SJohn Marino 		return NULL;
527*3ff40c12SJohn Marino 	os_memcpy(d, s, len);
528*3ff40c12SJohn Marino 	d[len] = '\0';
529*3ff40c12SJohn Marino 	return d;
530*3ff40c12SJohn Marino }
531*3ff40c12SJohn Marino 
532*3ff40c12SJohn Marino #endif /* WPA_TRACE */
533