diff options
Diffstat (limited to 'src/core/basetypes/MCWin32.cpp')
-rw-r--r-- | src/core/basetypes/MCWin32.cpp | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/src/core/basetypes/MCWin32.cpp b/src/core/basetypes/MCWin32.cpp new file mode 100644 index 00000000..3ff085ec --- /dev/null +++ b/src/core/basetypes/MCWin32.cpp @@ -0,0 +1,211 @@ +#include "MCWin32.h" + +FILE * mailcore::win32_fopen(const char * filename, const char * mode) +{ + FILE * f = NULL; + int r = fopen_s(&f, filename->fileSystemRepresentation(), "rb"); + if (r != 0) { + return NULL; + } + return f; +} + +static const unsigned __int64 epoch = ((unsigned __int64)116444736000000000ULL); +/* +* timezone information is stored outside the kernel so tzp isn't used anymore. + +* +* Note: this function is not for Win32 high precision timing purpose. See +* elapsed_time(). +*/ +int mailcore::win32_gettimeofday(struct timeval * tp, struct timezone * tzp) +{ + // WARNING - tzp is ignored in this implementation. + FILETIME file_time; + SYSTEMTIME system_time; + ULARGE_INTEGER ularge; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + ularge.LowPart = file_time.dwLowDateTime; + ularge.HighPart = file_time.dwHighDateTime; + + tp->tv_sec = (long)((ularge.QuadPart - epoch) / 10000000L); + tp->tv_usec = (long)(system_time.wMilliseconds * 1000); + + return 0; +} + +static int is_leap(unsigned y) { + y += 1900; + return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0); +} + +time_t mailcore::win32_timegm(struct tm *tm) { + static const unsigned ndays[2][12] = { + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } + }; + time_t res = 0; + int i; + + for (i = 70; i < tm->tm_year; ++i) + res += is_leap(i) ? 366 : 365; + + for (i = 0; i < tm->tm_mon; ++i) + res += ndays[is_leap(tm->tm_year)][i]; + res += tm->tm_mday - 1; + res *= 24; + res += tm->tm_hour; + res *= 60; + res += tm->tm_min; + res *= 60; + res += tm->tm_sec; + return res; +} + +struct tm * mailcore::win32_gmtime_r(const time_t *clock, struct tm *result) +{ + return gmtime_s(result, clock); +} + +struct tm * mailcore::win32_localtime_r(const time_t *clock, struct tm *result) +{ + return localtime_s(result, clock); +} + +char * mailcore::win32_strcasestr(const char * s, const char * find) +{ + char c, sc; + size_t len; + + if ((c = *find++) != 0) { + c = tolower((unsigned char)c); + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return (NULL); + } while ((char)tolower((unsigned char)sc) != c); + } while (strncasecmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} + +int mailcore::win32_vasprintf(char **strp, const char *fmt, va_list ap) +{ + int r = -1, size = _vscprintf(fmt, ap); + + if ((size >= 0) && (size < INT_MAX)) { + *strp = (char *) malloc(size + 1); + if (* strp) { + r = vsnprintf_s(* strp, size + 1, _TRUNCATE, fmt, ap); + if ((r < 0) || (r > size)) + { + free(* strp); + r = -1; + } + } + } + else { + * strp = 0; + } + + return r; +} + +int mailcore::win32_snprintf(char * str, size_t size, const char * format, ...) +{ + va_list argp; + + va_start(argp, format); + int result = vsnprintf_s(str, size, _TRUNCATE, format, argp); + va_end(argp); + + return result; +} + +long mailcore::win32_random(void) +{ + unsigned int randValue; + rand_s(&randValue); + return randValue; +} + +pid_t mailcore::win32_getpid(void) +{ + return GetCurrentProcessId(); +} + +static const char padchar[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +char * mailcore::win32_mkdtemp(char *name_template) +{ + register char *start, *trv, *suffp; + char *pad; + struct stat sbuf; + int rval; + + for (trv = path; *trv; ++trv); + suffp = trv; + --trv; + if (trv < path) { + errno = EINVAL; + return NULL; + } + + /* Fill space with random characters */ + /* + * I hope this is random enough. The orginal implementation + * uses arc4random(3) which is not available everywhere. + */ + while (*trv == 'X') { + //int randv = g_random_int_range(0, sizeof(padchar) - 1); + int randv = mailcore::win32_random() % sizeof(padchar); + *trv-- = padchar[randv]; + } + start = trv + 1; + + /* + * check the target directory. + */ + for (;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + rval = stat(path, &sbuf); + *trv = '/'; + if (rval != 0) + return NULL; + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return NULL; + } + break; + } + } + + for (;;) { + if (mkdir(path, 0700) == 0) + return path; + if (errno != EEXIST) + return NULL; + + /* If we have a collision, cycle through the space of filenames */ + for (trv = start;;) { + if (*trv == '\0' || trv == suffp) + return NULL; + pad = strchr(padchar, *trv); + if (pad == NULL || !*++pad) + *trv++ = padchar[0]; + else { + *trv++ = *pad; + break; + } + } + } +} + |