#define _CRT_SECURE_NO_DEPRECATE //rand_s requires _CRT_RAND_S be defined before including stdlib #define _CRT_RAND_S #include #include #include "portability.h" #include #include #include #include #include #include #include #include #include #include #include #include #include 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 toku_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 toku_os_get_phys_memory_size(void) { MEMORYSTATUS memory_status; GlobalMemoryStatus(&memory_status); return memory_status.dwTotalPhys; } int toku_os_get_number_processors(void) { SYSTEM_INFO system_info; GetSystemInfo(&system_info); return system_info.dwNumberOfProcessors; } int toku_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 toku_os_get_pagesize(void) { SYSTEM_INFO system_info; GetSystemInfo(&system_info); return system_info.dwPageSize; } int toku_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 toku_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 toku_os_getpid(void) { #if 0 return _getpid(); #else return GetCurrentProcessId(); #endif } int toku_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 toku_os_lock_file(char *name) { int fd = _sopen(name, O_CREAT, _SH_DENYRW, S_IREAD|S_IWRITE); return fd; } int toku_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 toku_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 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 toku_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; }