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