mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 06:44:16 +01:00
421 lines
9.7 KiB
C
421 lines
9.7 KiB
C
|
#define _CRT_SECURE_NO_DEPRECATE
|
||
|
|
||
|
//rand_s requires _CRT_RAND_S be defined before including stdlib
|
||
|
#define _CRT_RAND_S
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include "portability.h"
|
||
|
#include <dirent.h>
|
||
|
#include <assert.h>
|
||
|
#include <direct.h>
|
||
|
#include <errno.h>
|
||
|
#include <io.h>
|
||
|
#include <malloc.h>
|
||
|
#include <process.h>
|
||
|
#include <share.h>
|
||
|
#include <stdio.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <Crtdbg.h>
|
||
|
|
||
|
struct __toku_windir {
|
||
|
struct dirent ent;
|
||
|
struct _finddatai64_t data;
|
||
|
intptr_t handle;
|
||
|
BOOL finished;
|
||
|
};
|
||
|
|
||
|
DIR*
|
||
|
opendir(const char *name) {
|
||
|
char *format = NULL;
|
||
|
DIR *result = malloc(sizeof(*result));
|
||
|
int r;
|
||
|
if (!result) {
|
||
|
r = ENOMEM;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
format = malloc(strlen(name)+2+1); //2 for /*, 1 for '\0'
|
||
|
if (!format) {
|
||
|
r = ENOMEM;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
strcpy(format, name);
|
||
|
if (format[strlen(format)-1]=='/') format[strlen(format)-1]='\0';
|
||
|
strcat(format, "/*");
|
||
|
result->handle = _findfirsti64(format, &result->data);
|
||
|
// printf("%s:%d %p %d\n", __FILE__, __LINE__, result->handle, errno); fflush(stdout);
|
||
|
if (result->handle==-1L) {
|
||
|
if (errno==ENOENT) {
|
||
|
int64_t r_stat;
|
||
|
//ENOENT can mean a good directory with no files, OR
|
||
|
//a directory that does not exist.
|
||
|
struct _stat64 buffer;
|
||
|
format[strlen(format)-3] = '\0'; //Strip the "/*"
|
||
|
r_stat = _stati64(format, &buffer);
|
||
|
if (r_stat==0) {
|
||
|
//Empty directory.
|
||
|
result->finished = TRUE;
|
||
|
r = 0;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
}
|
||
|
r = errno;
|
||
|
assert(r!=0);
|
||
|
goto cleanup;
|
||
|
}
|
||
|
result->finished = FALSE;
|
||
|
r = 0;
|
||
|
cleanup:
|
||
|
if (r!=0) {
|
||
|
if (result) free(result);
|
||
|
result = NULL;
|
||
|
}
|
||
|
if (format) free(format);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
struct dirent*
|
||
|
readdir(DIR *dir) {
|
||
|
struct dirent *result;
|
||
|
int r;
|
||
|
if (dir->finished) {
|
||
|
errno = ENOENT;
|
||
|
result = NULL;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
assert(dir->handle!=-1L);
|
||
|
strcpy(dir->ent.d_name, dir->data.name);
|
||
|
if (dir->data.attrib&_A_SUBDIR) dir->ent.d_type=DT_DIR;
|
||
|
else dir->ent.d_type=DT_REG;
|
||
|
r = _findnexti64(dir->handle, &dir->data);
|
||
|
if (r==-1L) dir->finished = TRUE;
|
||
|
result = &dir->ent;
|
||
|
cleanup:
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
closedir(DIR *dir) {
|
||
|
int r;
|
||
|
if (dir->handle==-1L) r = 0;
|
||
|
else r = _findclose(dir->handle);
|
||
|
free(dir);
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
fsync(int fildes) {
|
||
|
int r = _commit(fildes);
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_get_file_size(int fildes, int64_t *size) {
|
||
|
struct _stat64 sbuf;
|
||
|
int r = _fstati64(fildes, &sbuf);
|
||
|
if (r==0) {
|
||
|
*size = sbuf.st_size;
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
uint64_t
|
||
|
os_get_phys_memory_size(void) {
|
||
|
MEMORYSTATUS memory_status;
|
||
|
GlobalMemoryStatus(&memory_status);
|
||
|
return memory_status.dwTotalPhys;
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
os_get_number_processors(void) {
|
||
|
SYSTEM_INFO system_info;
|
||
|
GetSystemInfo(&system_info);
|
||
|
return system_info.dwNumberOfProcessors;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_get_number_active_processors(void) {
|
||
|
SYSTEM_INFO system_info;
|
||
|
DWORD mask, n;
|
||
|
GetSystemInfo(&system_info);
|
||
|
mask = system_info.dwActiveProcessorMask;
|
||
|
for (n=0; mask; mask >>= 1)
|
||
|
n += mask & 1;
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_get_pagesize(void) {
|
||
|
SYSTEM_INFO system_info;
|
||
|
GetSystemInfo(&system_info);
|
||
|
return system_info.dwPageSize;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_get_unique_file_id(int fildes, struct fileid *id) {
|
||
|
int r;
|
||
|
BY_HANDLE_FILE_INFORMATION info;
|
||
|
HANDLE filehandle;
|
||
|
|
||
|
memset(id, 0, sizeof(*id));
|
||
|
filehandle = (HANDLE)_get_osfhandle(fildes);
|
||
|
if (filehandle==INVALID_HANDLE_VALUE) {
|
||
|
r = errno; assert(r!=0);
|
||
|
goto cleanup;
|
||
|
}
|
||
|
r = GetFileInformationByHandle(filehandle, &info);
|
||
|
if (r==0) { //0 is error here.
|
||
|
r = GetLastError(); assert(r!=0);
|
||
|
goto cleanup;
|
||
|
}
|
||
|
id->st_dev = info.dwVolumeSerialNumber;
|
||
|
id->st_ino = info.nFileIndexHigh;
|
||
|
id->st_ino <<= 32;
|
||
|
id->st_ino |= info.nFileIndexLow;
|
||
|
id->st_creat = info.ftCreationTime.dwHighDateTime;
|
||
|
id->st_creat <<= 32;
|
||
|
id->st_creat |= info.ftCreationTime.dwLowDateTime;
|
||
|
r = 0;
|
||
|
cleanup:
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
convert_filetime_timeval(FILETIME ft, struct timeval *tv) {
|
||
|
ULARGE_INTEGER t;
|
||
|
|
||
|
t.u.HighPart = ft.dwHighDateTime;
|
||
|
t.u.LowPart = ft.dwLowDateTime;
|
||
|
t.QuadPart /= 10;
|
||
|
if (tv) {
|
||
|
tv->tv_sec = t.QuadPart / 1000000;
|
||
|
tv->tv_usec = t.QuadPart % 1000000;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_get_process_times(struct timeval *usertime, struct timeval *kerneltime) {
|
||
|
FILETIME w_createtime, w_exittime, w_usertime, w_kerneltime;
|
||
|
|
||
|
if (GetProcessTimes(GetCurrentProcess(), &w_createtime, &w_exittime, &w_kerneltime, &w_usertime)) {
|
||
|
convert_filetime_timeval(w_usertime, usertime);
|
||
|
convert_filetime_timeval(w_kerneltime, kerneltime);
|
||
|
return 0;
|
||
|
}
|
||
|
return GetLastError();
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_getpid(void) {
|
||
|
#if 0
|
||
|
return _getpid();
|
||
|
#else
|
||
|
return GetCurrentProcessId();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_gettid(void) {
|
||
|
return GetCurrentThreadId();
|
||
|
}
|
||
|
|
||
|
int
|
||
|
gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||
|
FILETIME ft;
|
||
|
ULARGE_INTEGER t;
|
||
|
|
||
|
GetSystemTimeAsFileTime(&ft);
|
||
|
t.u.LowPart = ft.dwLowDateTime;
|
||
|
t.u.HighPart = ft.dwHighDateTime;
|
||
|
t.QuadPart -= 116444736000000000i64;
|
||
|
t.QuadPart /= 10;
|
||
|
if (tv) {
|
||
|
tv->tv_sec = t.QuadPart / 1000000;
|
||
|
tv->tv_usec = t.QuadPart % 1000000;
|
||
|
}
|
||
|
if (tz) {
|
||
|
assert(0);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_lock_file(char *name) {
|
||
|
int fd = _sopen(name, O_CREAT, _SH_DENYRW, S_IREAD|S_IWRITE);
|
||
|
return fd;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_unlock_file(int fildes) {
|
||
|
int r = close(fildes);
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
int64_t
|
||
|
pread(int fildes, void *buf, size_t nbyte, int64_t offset) {
|
||
|
int64_t r = _lseeki64(fildes, offset, SEEK_SET);
|
||
|
if (r>=0) {
|
||
|
assert(r==offset);
|
||
|
r = read(fildes, buf, nbyte);
|
||
|
}
|
||
|
// printf("%s: %d %p %u %I64d %I64d\n", __FUNCTION__, fildes, buf, nbyte, offset, r); fflush(stdout);
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
int64_t
|
||
|
pwrite(int fildes, const void *buf, size_t nbyte, int64_t offset) {
|
||
|
int64_t r = _lseeki64(fildes, offset, SEEK_SET);
|
||
|
if (r>=0) {
|
||
|
assert(r==offset);
|
||
|
r = write(fildes, buf, nbyte);
|
||
|
}
|
||
|
// printf("%s: %d %p %u %I64d %I64d\n", __FUNCTION__, fildes, buf, nbyte, offset, r); fflush(stdout);
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_mkdir(const char *pathname, mode_t mode) {
|
||
|
int r = mkdir(pathname);
|
||
|
UNUSED_WARNING(mode);
|
||
|
if (r!=0) r = errno;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
unsigned int
|
||
|
sleep(unsigned int seconds) {
|
||
|
unsigned int m = seconds / 1000000;
|
||
|
unsigned int n = seconds % 1000000;
|
||
|
unsigned int i;
|
||
|
for (i=0; i<m; i++)
|
||
|
Sleep(1000000*1000);
|
||
|
Sleep(n*1000);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
usleep(unsigned int useconds) {
|
||
|
unsigned int m = useconds / 1000;
|
||
|
unsigned int n = useconds % 1000;
|
||
|
if (m == 0 && n > 0)
|
||
|
m = 1;
|
||
|
Sleep(m);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void printfParameterHandler(const wchar_t* expression,
|
||
|
const wchar_t* function, const wchar_t* file,
|
||
|
unsigned int line, uintptr_t pReserved) {
|
||
|
fwprintf(stderr, L"Invalid parameter detected in function %s."
|
||
|
L" File: %s Line: %d\n"
|
||
|
L"Expression: %s\n", function, file, line, expression);
|
||
|
}
|
||
|
|
||
|
static void ignoreParameterHandler(const wchar_t* expression,
|
||
|
const wchar_t* function, const wchar_t* file,
|
||
|
unsigned int line, uintptr_t pReserved) {
|
||
|
UNUSED_WARNING(expression);
|
||
|
UNUSED_WARNING(function);
|
||
|
UNUSED_WARNING(file);
|
||
|
UNUSED_WARNING(line);
|
||
|
UNUSED_WARNING(pReserved);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
os_initialize_settings(int verbosity) {
|
||
|
int r;
|
||
|
static int initialized = 0;
|
||
|
assert(initialized==0);
|
||
|
initialized=1;
|
||
|
if (verbosity>0)
|
||
|
_set_invalid_parameter_handler(printfParameterHandler);
|
||
|
else
|
||
|
_set_invalid_parameter_handler(ignoreParameterHandler);
|
||
|
#if defined(_DEBUG)
|
||
|
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
|
||
|
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
|
||
|
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
|
||
|
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
|
||
|
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
|
||
|
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
|
||
|
#endif
|
||
|
r = 0;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
long int
|
||
|
random(void) {
|
||
|
u_int32_t r;
|
||
|
errno_t r_error = rand_s(&r);
|
||
|
assert(r_error==0);
|
||
|
//Should return 0 to 2**31-1 instead of 2**32-1
|
||
|
r >>= 1;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
//TODO: Implement srandom to modify the way rand_s works (IF POSSIBLE).. or
|
||
|
//reimplement random.
|
||
|
void
|
||
|
srandom(unsigned int seed) {
|
||
|
UNUSED_WARNING(seed);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
setenv(const char *name, const char *value, int overwrite) {
|
||
|
char buf[2]; //Need a dummy buffer
|
||
|
BOOL exists = TRUE;
|
||
|
int r = GetEnvironmentVariable(name, buf, sizeof(buf));
|
||
|
if (r==0) {
|
||
|
r = GetLastError();
|
||
|
if (r==ERROR_ENVVAR_NOT_FOUND) exists = FALSE;
|
||
|
else {
|
||
|
errno = r;
|
||
|
r = -1;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
}
|
||
|
if (overwrite || !exists) {
|
||
|
r = SetEnvironmentVariable(name, value);
|
||
|
if (r==0) {
|
||
|
errno = GetLastError();
|
||
|
r = -1;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
}
|
||
|
r = 0;
|
||
|
cleanup:
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
unsetenv(const char *name) {
|
||
|
int r = SetEnvironmentVariable(name, NULL);
|
||
|
if (r==0) { //0 is failure
|
||
|
r = -1;
|
||
|
errno = GetLastError();
|
||
|
}
|
||
|
else r = 0;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
ftruncate(int fd, int64_t offset) {
|
||
|
HANDLE h;
|
||
|
BOOL b;
|
||
|
int r;
|
||
|
|
||
|
h = (HANDLE) _get_osfhandle(fd);
|
||
|
if (h == INVALID_HANDLE_VALUE)
|
||
|
return -1;
|
||
|
r = _lseeki64(fd, 0, SEEK_SET);
|
||
|
if (r != 0)
|
||
|
return -2;
|
||
|
b = SetEndOfFile(h);
|
||
|
if (!b)
|
||
|
return -3;
|
||
|
return 0;
|
||
|
}
|
||
|
|