18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant/hostapd / OS specific functions for Win32 systems
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include <time.h>
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <winsock2.h>
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <wincrypt.h>
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "os.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid os_sleep(os_time_t sec, os_time_t usec)
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sec)
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		Sleep(sec * 1000);
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (usec)
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		Sleep(usec / 1000);
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_get_time(struct os_time *t)
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EPOCHFILETIME (116444736000000000ULL)
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FILETIME ft;
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LARGE_INTEGER li;
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONGLONG tt;
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SYSTEMTIME st;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	GetSystemTime(&st);
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SystemTimeToFileTime(&st, &ft);
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* _WIN32_WCE */
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	GetSystemTimeAsFileTime(&ft);
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	li.LowPart = ft.dwLowDateTime;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	li.HighPart = ft.dwHighDateTime;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tt = (li.QuadPart - EPOCHFILETIME) / 10;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	t->sec = (os_time_t) (tt / 1000000);
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	t->usec = (os_time_t) (tt % 1000000);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_mktime(int year, int month, int day, int hour, int min, int sec,
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      os_time_t *t)
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tm tm, *tm1;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	time_t t_local, t1, t2;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_time_t tz_offset;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sec > 60)
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memset(&tm, 0, sizeof(tm));
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_year = year - 1900;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_mon = month - 1;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_mday = day;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_hour = hour;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_min = min;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_sec = sec;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	t_local = mktime(&tm);
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* figure out offset to UTC */
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm1 = localtime(&t_local);
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tm1) {
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		t1 = mktime(tm1);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tm1 = gmtime(&t_local);
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tm1) {
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			t2 = mktime(tm1);
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tz_offset = t2 - t1;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tz_offset = 0;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tz_offset = 0;
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*t = (os_time_t) t_local - tz_offset;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint os_gmtime(os_time_t t, struct os_tm *tm)
911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct tm *tm2;
931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	time_t t2 = t;
941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm2 = gmtime(&t2);
961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (tm2 == NULL)
971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->sec = tm2->tm_sec;
991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->min = tm2->tm_min;
1001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->hour = tm2->tm_hour;
1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->day = tm2->tm_mday;
1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->month = tm2->tm_mon + 1;
1031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->year = tm2->tm_year + 1900;
1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 0;
1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_daemonize(const char *pid_file)
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO */
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid os_daemonize_terminate(const char *pid_file)
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_get_random(unsigned char *buf, size_t len)
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTPROV prov;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOL ret;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL,
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 CRYPT_VERIFYCONTEXT))
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = CryptGenRandom(prov, len, buf);
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptReleaseContext(prov, 0);
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret ? 0 : -1;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned long os_random(void)
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return rand();
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * os_rel2abs_path(const char *rel_path)
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return _strdup(rel_path);
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_program_init(void)
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NATIVE_WINDOWS
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WSADATA wsaData;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not find a usable WinSock.dll\n");
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid os_program_deinit(void)
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NATIVE_WINDOWS
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WSACleanup();
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_setenv(const char *name, const char *value, int overwrite)
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_unsetenv(const char *name)
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * os_readfile(const char *name, size_t *len)
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FILE *f;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	f = fopen(name, "rb");
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (f == NULL)
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fseek(f, 0, SEEK_END);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = ftell(f);
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fseek(f, 0, SEEK_SET);
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = malloc(*len);
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fclose(f);
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fread(buf, 1, *len, f);
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fclose(f);
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * os_zalloc(size_t size)
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return calloc(1, size);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsize_t os_strlcpy(char *dest, const char *src, size_t siz)
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *s = src;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left = siz;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left) {
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Copy string up to the maximum size of the dest buffer */
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (--left != 0) {
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if ((*dest++ = *s++) == '\0')
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left == 0) {
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Not enough room for the string; force NUL-termination */
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (siz != 0)
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*dest = '\0';
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*s++)
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			; /* determine total src string length */
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return s - src - 1;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
236