Fix Windows build warnings.
[fio.git] / os / windows / posix.c
CommitLineData
9277ec14
BC
1/* This file contains functions which implement those POSIX and Linux functions
2 * that MinGW and Microsoft don't provide. The implementations contain just enough
3 * functionality to support fio.
4 */
5
6#include <arpa/inet.h>
7#include <netinet/in.h>
8#include <windows.h>
9#include <stddef.h>
ad9c0fbc 10#include <string.h>
9277ec14
BC
11#include <stdlib.h>
12#include <unistd.h>
13#include <dirent.h>
14#include <pthread.h>
15#include <semaphore.h>
16#include <sys/shm.h>
17#include <sys/mman.h>
18#include <sys/uio.h>
19#include <sys/resource.h>
20#include <sys/poll.h>
21
22#include "../os-windows.h"
671b0600 23#include "../../lib/hweight.h"
9277ec14 24
21c75387
BC
25extern unsigned long mtime_since_now(struct timeval *);
26extern void fio_gettime(struct timeval *, void *);
27
ad9c0fbc
BC
28/* These aren't defined in the MinGW headers */
29HRESULT WINAPI StringCchCopyA(
30 char *pszDest,
31 size_t cchDest,
32 const char *pszSrc);
33
34HRESULT WINAPI StringCchPrintfA(
35 char *pszDest,
36 size_t cchDest,
37 const char *pszFormat,
38 ...);
39
40int vsprintf_s(
41 char *buffer,
42 size_t numberOfElements,
43 const char *format,
44 va_list argptr);
45
10a6b3c6
BC
46int win_to_posix_error(DWORD winerr)
47{
48 switch (winerr)
49 {
50 case ERROR_FILE_NOT_FOUND: return ENOENT;
51 case ERROR_PATH_NOT_FOUND: return ENOENT;
52 case ERROR_ACCESS_DENIED: return EACCES;
53 case ERROR_INVALID_HANDLE: return EBADF;
54 case ERROR_NOT_ENOUGH_MEMORY: return ENOMEM;
55 case ERROR_INVALID_DATA: return EINVAL;
56 case ERROR_OUTOFMEMORY: return ENOMEM;
57 case ERROR_INVALID_DRIVE: return ENODEV;
58 case ERROR_NOT_SAME_DEVICE: return EXDEV;
59 case ERROR_WRITE_PROTECT: return EROFS;
60 case ERROR_BAD_UNIT: return ENODEV;
61 case ERROR_SHARING_VIOLATION: return EACCES;
62 case ERROR_LOCK_VIOLATION: return EACCES;
63 case ERROR_SHARING_BUFFER_EXCEEDED: return ENOLCK;
64 case ERROR_HANDLE_DISK_FULL: return ENOSPC;
65 case ERROR_NOT_SUPPORTED: return ENOSYS;
66 case ERROR_FILE_EXISTS: return EEXIST;
67 case ERROR_CANNOT_MAKE: return EPERM;
68 case ERROR_INVALID_PARAMETER: return EINVAL;
69 case ERROR_NO_PROC_SLOTS: return EAGAIN;
70 case ERROR_BROKEN_PIPE: return EPIPE;
71 case ERROR_OPEN_FAILED: return EIO;
72 case ERROR_NO_MORE_SEARCH_HANDLES: return ENFILE;
73 case ERROR_CALL_NOT_IMPLEMENTED: return ENOSYS;
74 case ERROR_INVALID_NAME: return ENOENT;
75 case ERROR_WAIT_NO_CHILDREN: return ECHILD;
76 case ERROR_CHILD_NOT_COMPLETE: return EBUSY;
77 case ERROR_DIR_NOT_EMPTY: return ENOTEMPTY;
78 case ERROR_SIGNAL_REFUSED: return EIO;
79 case ERROR_BAD_PATHNAME: return ENOENT;
80 case ERROR_SIGNAL_PENDING: return EBUSY;
81 case ERROR_MAX_THRDS_REACHED: return EAGAIN;
82 case ERROR_BUSY: return EBUSY;
83 case ERROR_ALREADY_EXISTS: return EEXIST;
84 case ERROR_NO_SIGNAL_SENT: return EIO;
85 case ERROR_FILENAME_EXCED_RANGE: return EINVAL;
86 case ERROR_META_EXPANSION_TOO_LONG: return EINVAL;
87 case ERROR_INVALID_SIGNAL_NUMBER: return EINVAL;
88 case ERROR_THREAD_1_INACTIVE: return EINVAL;
89 case ERROR_BAD_PIPE: return EINVAL;
90 case ERROR_PIPE_BUSY: return EBUSY;
91 case ERROR_NO_DATA: return EPIPE;
92 case ERROR_MORE_DATA: return EAGAIN;
93 case ERROR_DIRECTORY: return ENOTDIR;
94 case ERROR_PIPE_CONNECTED: return EBUSY;
95 case ERROR_NO_TOKEN: return EINVAL;
96 case ERROR_PROCESS_ABORTED: return EFAULT;
97 case ERROR_BAD_DEVICE: return ENODEV;
98 case ERROR_BAD_USERNAME: return EINVAL;
99 case ERROR_OPEN_FILES: return EAGAIN;
100 case ERROR_ACTIVE_CONNECTIONS: return EAGAIN;
101 case ERROR_DEVICE_IN_USE: return EAGAIN;
102 case ERROR_INVALID_AT_INTERRUPT_TIME: return EINTR;
103 case ERROR_IO_DEVICE: return EIO;
104 case ERROR_NOT_OWNER: return EPERM;
105 case ERROR_END_OF_MEDIA: return ENOSPC;
106 case ERROR_EOM_OVERFLOW: return ENOSPC;
107 case ERROR_BEGINNING_OF_MEDIA: return ESPIPE;
108 case ERROR_SETMARK_DETECTED: return ESPIPE;
109 case ERROR_NO_DATA_DETECTED: return ENOSPC;
110 case ERROR_POSSIBLE_DEADLOCK: return EDEADLOCK;
111 case ERROR_CRC: return EIO;
112 case ERROR_NEGATIVE_SEEK: return EINVAL;
113 case ERROR_DISK_FULL: return ENOSPC;
114 case ERROR_NOACCESS: return EFAULT;
115 case ERROR_FILE_INVALID: return ENXIO;
116 }
117
118 return winerr;
119}
120
671b0600
BC
121int GetNumLogicalProcessors(void)
122{
123 SYSTEM_LOGICAL_PROCESSOR_INFORMATION *processor_info = NULL;
124 DWORD len = 0;
125 DWORD num_processors = 0;
126 DWORD error = 0;
127 DWORD i;
128
129 while (!GetLogicalProcessorInformation(processor_info, &len)) {
130 error = GetLastError();
131 if (error == ERROR_INSUFFICIENT_BUFFER)
132 processor_info = malloc(len);
133 else {
134 log_err("Error: GetLogicalProcessorInformation failed: %d\n", error);
135 return -1;
136 }
137
138 if (processor_info == NULL) {
139 log_err("Error: failed to allocate memory for GetLogicalProcessorInformation");
140 return -1;
141 }
142 }
143
144 for (i = 0; i < len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); i++)
145 {
146 if (processor_info[i].Relationship == RelationProcessorCore)
4ee47af0 147 num_processors += hweight64(processor_info[i].ProcessorMask);
671b0600
BC
148 }
149
150 free(processor_info);
151 return num_processors;
152}
153
9277ec14
BC
154long sysconf(int name)
155{
671b0600 156 long val = -1;
01d26955 157 long val2 = -1;
9277ec14
BC
158 SYSTEM_INFO sysInfo;
159 MEMORYSTATUSEX status;
160
161 switch (name)
162 {
163 case _SC_NPROCESSORS_ONLN:
671b0600
BC
164 val = GetNumLogicalProcessors();
165 if (val == -1)
01d26955 166 log_err("sysconf(_SC_NPROCESSORS_ONLN) failed\n");
671b0600 167
9277ec14
BC
168 break;
169
170 case _SC_PAGESIZE:
171 GetSystemInfo(&sysInfo);
172 val = sysInfo.dwPageSize;
173 break;
174
175 case _SC_PHYS_PAGES:
176 status.dwLength = sizeof(status);
01d26955
BC
177 val2 = sysconf(_SC_PAGESIZE);
178 if (GlobalMemoryStatusEx(&status) && val2 != -1)
179 val = status.ullTotalPhys / val2;
180 else
181 log_err("sysconf(_SC_PHYS_PAGES) failed\n");
9277ec14
BC
182 break;
183 default:
184 log_err("sysconf(%d) is not implemented\n", name);
185 break;
186 }
187
188 return val;
189}
190
191char *dl_error = NULL;
192
193int dlclose(void *handle)
194{
195 return !FreeLibrary((HMODULE)handle);
196}
197
198void *dlopen(const char *file, int mode)
199{
200 HMODULE hMod;
201
202 hMod = LoadLibrary(file);
203 if (hMod == INVALID_HANDLE_VALUE)
204 dl_error = (char*)"LoadLibrary failed";
205 else
206 dl_error = NULL;
207
208 return hMod;
209}
210
211void *dlsym(void *handle, const char *name)
212{
213 FARPROC fnPtr;
214
215 fnPtr = GetProcAddress((HMODULE)handle, name);
216 if (fnPtr == NULL)
217 dl_error = (char*)"GetProcAddress failed";
218 else
219 dl_error = NULL;
220
221 return fnPtr;
222}
223
224char *dlerror(void)
225{
226 return dl_error;
227}
228
229int gettimeofday(struct timeval *restrict tp, void *restrict tzp)
230{
231 FILETIME fileTime;
9576f613
BC
232 uint64_t unix_time, windows_time;
233 const uint64_t MILLISECONDS_BETWEEN_1601_AND_1970 = 11644473600000;
9277ec14 234
fc0b830f 235 /* Ignore the timezone parameter */
9277ec14
BC
236 (void)tzp;
237
238 /*
239 * Windows time is stored as the number 100 ns intervals since January 1 1601.
240 * Conversion details from http://www.informit.com/articles/article.aspx?p=102236&seqNum=3
241 * Its precision is 100 ns but accuracy is only one clock tick, or normally around 15 ms.
242 */
243 GetSystemTimeAsFileTime(&fileTime);
9576f613 244 windows_time = ((uint64_t)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime;
9277ec14
BC
245 /* Divide by 10,000 to convert to ms and subtract the time between 1601 and 1970 */
246 unix_time = (((windows_time)/10000) - MILLISECONDS_BETWEEN_1601_AND_1970);
247 /* unix_time is now the number of milliseconds since 1970 (the Unix epoch) */
248 tp->tv_sec = unix_time / 1000;
249 tp->tv_usec = (unix_time % 1000) * 1000;
250 return 0;
251}
252
9277ec14
BC
253int sigaction(int sig, const struct sigaction *act,
254 struct sigaction *oact)
255{
e5b8f91c
BC
256 int rc = 0;
257 void (*prev_handler)(int);
258
259 prev_handler = signal(sig, act->sa_handler);
260 if (oact != NULL)
261 oact->sa_handler = prev_handler;
262
263 if (prev_handler == SIG_ERR)
264 rc = -1;
265
266 return rc;
9277ec14
BC
267}
268
269int lstat(const char * path, struct stat * buf)
270{
271 return stat(path, buf);
272}
273
274void *mmap(void *addr, size_t len, int prot, int flags,
275 int fildes, off_t off)
276{
277 DWORD vaProt = 0;
278 void* allocAddr = NULL;
279
280 if (prot & PROT_NONE)
281 vaProt |= PAGE_NOACCESS;
282
283 if ((prot & PROT_READ) && !(prot & PROT_WRITE))
284 vaProt |= PAGE_READONLY;
285
286 if (prot & PROT_WRITE)
287 vaProt |= PAGE_READWRITE;
288
289 if ((flags & MAP_ANON) | (flags & MAP_ANONYMOUS))
290 {
291 allocAddr = VirtualAlloc(addr, len, MEM_COMMIT, vaProt);
10a6b3c6
BC
292 if (allocAddr == NULL)
293 errno = win_to_posix_error(GetLastError());
9277ec14
BC
294 }
295
296 return allocAddr;
297}
298
299int munmap(void *addr, size_t len)
300{
10a6b3c6
BC
301 if (!VirtualFree(addr, 0, MEM_RELEASE)) {
302 errno = win_to_posix_error(GetLastError());
303 return -1;
304 }
305
306 return 0;
9277ec14
BC
307}
308
309int fork(void)
310{
311 log_err("%s is not implemented\n", __func__);
312 errno = ENOSYS;
10a6b3c6 313 return -1;
9277ec14
BC
314}
315
316pid_t setsid(void)
317{
318 log_err("%s is not implemented\n", __func__);
319 errno = ENOSYS;
10a6b3c6 320 return -1;
9277ec14
BC
321}
322
ad9c0fbc
BC
323static HANDLE log_file = INVALID_HANDLE_VALUE;
324
9277ec14
BC
325void openlog(const char *ident, int logopt, int facility)
326{
ad9c0fbc
BC
327 if (log_file == INVALID_HANDLE_VALUE)
328 log_file = CreateFileA("syslog.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
9277ec14
BC
329}
330
331void closelog(void)
332{
ad9c0fbc
BC
333 CloseHandle(log_file);
334 log_file = INVALID_HANDLE_VALUE;
335}
336
337void syslog(int priority, const char *message, ... /* argument */)
338{
339 va_list v;
340 int len;
341 char *output;
342 DWORD bytes_written;
343
344 if (log_file == INVALID_HANDLE_VALUE) {
345 log_file = CreateFileA("syslog.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
346 }
347
348 if (log_file == INVALID_HANDLE_VALUE) {
349 log_err("syslog: failed to open log file\n");
350 return;
351 }
352
353 va_start(v, message);
354 len = _vscprintf(message, v);
355 output = malloc(len + sizeof(char));
98dc2db5 356 vsprintf(output, message, v);
ad9c0fbc
BC
357 WriteFile(log_file, output, len, &bytes_written, NULL);
358 va_end(v);
98dc2db5 359 free(output);
9277ec14
BC
360}
361
362int kill(pid_t pid, int sig)
363{
364 errno = ESRCH;
10a6b3c6 365 return -1;
9277ec14
BC
366}
367
fc0b830f
BC
368/*
369 * This is assumed to be used only by the network code,
370 * and so doesn't try and handle any of the other cases
371 */
9277ec14
BC
372int fcntl(int fildes, int cmd, ...)
373{
fc0b830f
BC
374 /*
375 * non-blocking mode doesn't work the same as in BSD sockets,
376 * so ignore it.
377 */
9277ec14
BC
378#if 0
379 va_list ap;
380 int val, opt, status;
381
382 if (cmd == F_GETFL)
383 return 0;
384 else if (cmd != F_SETFL) {
385 errno = EINVAL;
10a6b3c6 386 return -1;
9277ec14
BC
387 }
388
389 va_start(ap, 1);
390
391 opt = va_arg(ap, int);
392 if (opt & O_NONBLOCK)
393 val = 1;
394 else
395 val = 0;
396
397 status = ioctlsocket((SOCKET)fildes, opt, &val);
398
399 if (status == SOCKET_ERROR) {
400 errno = EINVAL;
401 val = -1;
402 }
403
404 va_end(ap);
405
406 return val;
407#endif
408return 0;
409}
410
411/*
412 * Get the value of a local clock source.
413 * This implementation supports 2 clocks: CLOCK_MONOTONIC provides high-accuracy
414 * relative time, while CLOCK_REALTIME provides a low-accuracy wall time.
415 */
416int clock_gettime(clockid_t clock_id, struct timespec *tp)
417{
418 int rc = 0;
419
420 if (clock_id == CLOCK_MONOTONIC)
421 {
422 static LARGE_INTEGER freq = {{0,0}};
423 LARGE_INTEGER counts;
5aa23eb8 424 uint64_t t;
9277ec14
BC
425
426 QueryPerformanceCounter(&counts);
427 if (freq.QuadPart == 0)
428 QueryPerformanceFrequency(&freq);
429
430 tp->tv_sec = counts.QuadPart / freq.QuadPart;
431 /* Get the difference between the number of ns stored
432 * in 'tv_sec' and that stored in 'counts' */
5aa23eb8 433 t = tp->tv_sec * freq.QuadPart;
9277ec14
BC
434 t = counts.QuadPart - t;
435 /* 't' now contains the number of cycles since the last second.
436 * We want the number of nanoseconds, so multiply out by 1,000,000,000
437 * and then divide by the frequency. */
438 t *= 1000000000;
439 tp->tv_nsec = t / freq.QuadPart;
440 }
441 else if (clock_id == CLOCK_REALTIME)
442 {
443 /* clock_gettime(CLOCK_REALTIME,...) is just an alias for gettimeofday with a
444 * higher-precision field. */
445 struct timeval tv;
446 gettimeofday(&tv, NULL);
447 tp->tv_sec = tv.tv_sec;
448 tp->tv_nsec = tv.tv_usec * 1000;
449 } else {
450 errno = EINVAL;
451 rc = -1;
452 }
453
454 return rc;
455}
456
457int mlock(const void * addr, size_t len)
458{
10a6b3c6
BC
459 SIZE_T min, max;
460 BOOL success;
461 HANDLE process = GetCurrentProcess();
462
463 success = GetProcessWorkingSetSize(process, &min, &max);
464 if (!success) {
465 errno = win_to_posix_error(GetLastError());
466 return -1;
467 }
468
469 min += len;
470 max += len;
471 success = SetProcessWorkingSetSize(process, min, max);
472 if (!success) {
473 errno = win_to_posix_error(GetLastError());
474 return -1;
475 }
476
477 success = VirtualLock((LPVOID)addr, len);
478 if (!success) {
479 errno = win_to_posix_error(GetLastError());
480 return -1;
481 }
482
483 return 0;
9277ec14
BC
484}
485
486int munlock(const void * addr, size_t len)
487{
10a6b3c6
BC
488 BOOL success = VirtualUnlock((LPVOID)addr, len);
489 if (!success) {
490 errno = win_to_posix_error(GetLastError());
491 return -1;
492 }
493
494 return 0;
9277ec14
BC
495}
496
497pid_t waitpid(pid_t pid, int *stat_loc, int options)
498{
499 log_err("%s is not implemented\n", __func__);
500 errno = ENOSYS;
501 return -1;
502}
503
504int usleep(useconds_t useconds)
505{
506 Sleep(useconds / 1000);
507 return 0;
508}
509
510char *basename(char *path)
511{
512 static char name[MAX_PATH];
513 int i;
514
515 if (path == NULL || strlen(path) == 0)
516 return (char*)".";
517
518 i = strlen(path) - 1;
519
9576f613 520 while (path[i] != '\\' && path[i] != '/' && i >= 0)
9277ec14
BC
521 i--;
522
9576f613 523 strncpy(name, path + i + 1, MAX_PATH);
9277ec14
BC
524
525 return name;
526}
527
9277ec14
BC
528int fsync(int fildes)
529{
530 HANDLE hFile = (HANDLE)_get_osfhandle(fildes);
10a6b3c6
BC
531 if (!FlushFileBuffers(hFile)) {
532 errno = win_to_posix_error(GetLastError());
533 return -1;
534 }
535
536 return 0;
9277ec14
BC
537}
538
539int nFileMappings = 0;
540HANDLE fileMappings[1024];
541
542int shmget(key_t key, size_t size, int shmflg)
543{
544 int mapid = -1;
d3987946
BC
545 uint32_t size_low = size & 0xFFFFFFFF;
546 uint32_t size_high = ((uint64_t)size) >> 32;
547 HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, (PAGE_EXECUTE_READWRITE | SEC_RESERVE), size_high, size_low, NULL);
9277ec14
BC
548 if (hMapping != NULL) {
549 fileMappings[nFileMappings] = hMapping;
550 mapid = nFileMappings;
551 nFileMappings++;
552 } else {
553 errno = ENOSYS;
554 }
555
556 return mapid;
557}
558
559void *shmat(int shmid, const void *shmaddr, int shmflg)
560{
561 void* mapAddr;
562 MEMORY_BASIC_INFORMATION memInfo;
563 mapAddr = MapViewOfFile(fileMappings[shmid], FILE_MAP_ALL_ACCESS, 0, 0, 0);
10a6b3c6
BC
564 if (mapAddr == NULL) {
565 errno = win_to_posix_error(GetLastError());
566 return (void*)-1;
567 }
568
569 if (VirtualQuery(mapAddr, &memInfo, sizeof(memInfo)) == 0) {
570 errno = win_to_posix_error(GetLastError());
571 return (void*)-1;
572 }
573
9277ec14 574 mapAddr = VirtualAlloc(mapAddr, memInfo.RegionSize, MEM_COMMIT, PAGE_READWRITE);
10a6b3c6
BC
575 if (mapAddr == NULL) {
576 errno = win_to_posix_error(GetLastError());
577 return (void*)-1;
578 }
579
9277ec14
BC
580 return mapAddr;
581}
582
583int shmdt(const void *shmaddr)
584{
10a6b3c6
BC
585 if (!UnmapViewOfFile(shmaddr)) {
586 errno = win_to_posix_error(GetLastError());
587 return -1;
588 }
589
590 return 0;
9277ec14
BC
591}
592
593int shmctl(int shmid, int cmd, struct shmid_ds *buf)
594{
595 if (cmd == IPC_RMID) {
596 fileMappings[shmid] = INVALID_HANDLE_VALUE;
597 return 0;
598 } else {
599 log_err("%s is not implemented\n", __func__);
600 }
10a6b3c6
BC
601 errno = ENOSYS;
602 return -1;
9277ec14
BC
603}
604
605int setuid(uid_t uid)
606{
607 log_err("%s is not implemented\n", __func__);
608 errno = ENOSYS;
10a6b3c6 609 return -1;
9277ec14
BC
610}
611
612int setgid(gid_t gid)
613{
614 log_err("%s is not implemented\n", __func__);
615 errno = ENOSYS;
10a6b3c6 616 return -1;
9277ec14
BC
617}
618
619int nice(int incr)
620{
621 if (incr != 0) {
622 errno = EINVAL;
623 return -1;
624 }
625
626 return 0;
627}
628
629int getrusage(int who, struct rusage *r_usage)
630{
9576f613 631 const uint64_t SECONDS_BETWEEN_1601_AND_1970 = 11644473600;
9277ec14
BC
632 FILETIME cTime, eTime, kTime, uTime;
633 time_t time;
7732a09b 634 HANDLE h;
9277ec14
BC
635
636 memset(r_usage, 0, sizeof(*r_usage));
637
7732a09b
HL
638 if (who == RUSAGE_SELF) {
639 h = GetCurrentProcess();
640 GetProcessTimes(h, &cTime, &eTime, &kTime, &uTime);
641 } else if (who == RUSAGE_THREAD) {
642 h = GetCurrentThread();
643 GetThreadTimes(h, &cTime, &eTime, &kTime, &uTime);
644 } else {
645 log_err("fio: getrusage %d is not implemented\n", who);
646 return -1;
647 }
648
9576f613 649 time = ((uint64_t)uTime.dwHighDateTime << 32) + uTime.dwLowDateTime;
9277ec14
BC
650 /* Divide by 10,000,000 to get the number of seconds and move the epoch from
651 * 1601 to 1970 */
652 time = (time_t)(((time)/10000000) - SECONDS_BETWEEN_1601_AND_1970);
653 r_usage->ru_utime.tv_sec = time;
654 /* getrusage() doesn't care about anything other than seconds, so set tv_usec to 0 */
655 r_usage->ru_utime.tv_usec = 0;
9576f613 656 time = ((uint64_t)kTime.dwHighDateTime << 32) + kTime.dwLowDateTime;
9277ec14
BC
657 /* Divide by 10,000,000 to get the number of seconds and move the epoch from
658 * 1601 to 1970 */
659 time = (time_t)(((time)/10000000) - SECONDS_BETWEEN_1601_AND_1970);
660 r_usage->ru_stime.tv_sec = time;
661 r_usage->ru_stime.tv_usec = 0;
662 return 0;
663}
664
2277d5d5
BC
665int posix_fadvise(int fd, off_t offset, off_t len, int advice)
666{
667 return 0;
668}
669
9277ec14
BC
670int posix_madvise(void *addr, size_t len, int advice)
671{
672 log_err("%s is not implemented\n", __func__);
673 return ENOSYS;
674}
675
fc0b830f 676/* Windows doesn't support advice for memory pages. Just ignore it. */
9277ec14
BC
677int msync(void *addr, size_t len, int flags)
678{
9277ec14
BC
679 errno = ENOSYS;
680 return -1;
681}
682
683int fdatasync(int fildes)
684{
685 return fsync(fildes);
686}
687
688ssize_t pwrite(int fildes, const void *buf, size_t nbyte,
689 off_t offset)
690{
9576f613
BC
691 int64_t pos = _telli64(fildes);
692 ssize_t len = _write(fildes, buf, nbyte);
693 _lseeki64(fildes, pos, SEEK_SET);
9277ec14
BC
694 return len;
695}
696
697ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset)
698{
9576f613 699 int64_t pos = _telli64(fildes);
9277ec14 700 ssize_t len = read(fildes, buf, nbyte);
9576f613 701 _lseeki64(fildes, pos, SEEK_SET);
9277ec14
BC
702 return len;
703}
704
705ssize_t readv(int fildes, const struct iovec *iov, int iovcnt)
706{
707 log_err("%s is not implemented\n", __func__);
708 errno = ENOSYS;
10a6b3c6 709 return -1;
9277ec14
BC
710}
711
712ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)
713{
714 log_err("%s is not implemented\n", __func__);
715 errno = ENOSYS;
10a6b3c6 716 return -1;
9277ec14
BC
717}
718
719long long strtoll(const char *restrict str, char **restrict endptr,
720 int base)
721{
722 return _strtoi64(str, endptr, base);
723}
724
9277ec14
BC
725int poll(struct pollfd fds[], nfds_t nfds, int timeout)
726{
727 struct timeval tv;
728 struct timeval *to = NULL;
729 fd_set readfds, writefds, exceptfds;
730 int i;
731 int rc;
732
3f457bea 733 if (timeout != -1) {
f9a58c2a 734 to = &tv;
3f457bea
BC
735 to->tv_sec = timeout / 1000;
736 to->tv_usec = (timeout % 1000) * 1000;
737 }
9277ec14
BC
738
739 FD_ZERO(&readfds);
740 FD_ZERO(&writefds);
741 FD_ZERO(&exceptfds);
742
743 for (i = 0; i < nfds; i++)
744 {
745 if (fds[i].fd < 0) {
746 fds[i].revents = 0;
747 continue;
748 }
749
750 if (fds[i].events & POLLIN)
751 FD_SET(fds[i].fd, &readfds);
752
753 if (fds[i].events & POLLOUT)
754 FD_SET(fds[i].fd, &writefds);
755
f9a58c2a 756 FD_SET(fds[i].fd, &exceptfds);
9277ec14
BC
757 }
758
759 rc = select(nfds, &readfds, &writefds, &exceptfds, to);
760
761 if (rc != SOCKET_ERROR) {
762 for (i = 0; i < nfds; i++)
763 {
764 if (fds[i].fd < 0) {
765 continue;
766 }
767
768 if ((fds[i].events & POLLIN) && FD_ISSET(fds[i].fd, &readfds))
769 fds[i].revents |= POLLIN;
770
771 if ((fds[i].events & POLLOUT) && FD_ISSET(fds[i].fd, &writefds))
772 fds[i].revents |= POLLOUT;
773
774 if (FD_ISSET(fds[i].fd, &exceptfds))
775 fds[i].revents |= POLLHUP;
776 }
777 }
778
779 return rc;
780}
781
782int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
783{
21c75387
BC
784 struct timeval tv;
785 DWORD ms_remaining;
786 DWORD ms_total = (rqtp->tv_sec * 1000) + (rqtp->tv_nsec / 1000000.0);
787
788 if (ms_total == 0)
789 ms_total = 1;
790
791 ms_remaining = ms_total;
792
793 /* Since Sleep() can sleep for less than the requested time, add a loop to
794 ensure we only return after the requested length of time has elapsed */
795 do {
796 fio_gettime(&tv, NULL);
797 Sleep(ms_remaining);
798 ms_remaining = ms_total - mtime_since_now(&tv);
799 } while (ms_remaining > 0 && ms_remaining < ms_total);
800
801 /* this implementation will never sleep for less than the requested time */
802 if (rmtp != NULL) {
803 rmtp->tv_sec = 0;
804 rmtp->tv_nsec = 0;
805 }
806
807 return 0;
9277ec14
BC
808}
809
810DIR *opendir(const char *dirname)
811{
01d26955
BC
812 struct dirent_ctx *dc = NULL;
813
814 /* See if we can open it. If not, we'll return an error here */
815 HANDLE file = CreateFileA(dirname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
816 if (file != INVALID_HANDLE_VALUE) {
817 CloseHandle(file);
818 dc = (struct dirent_ctx*)malloc(sizeof(struct dirent_ctx));
819 StringCchCopyA(dc->dirname, MAX_PATH, dirname);
820 dc->find_handle = INVALID_HANDLE_VALUE;
821 } else {
822 DWORD error = GetLastError();
823 if (error == ERROR_FILE_NOT_FOUND)
824 errno = ENOENT;
825
826 else if (error == ERROR_PATH_NOT_FOUND)
827 errno = ENOTDIR;
828 else if (error == ERROR_TOO_MANY_OPEN_FILES)
829 errno = ENFILE;
830 else if (error == ERROR_ACCESS_DENIED)
831 errno = EACCES;
832 else
833 errno = error;
834 }
835
836 return dc;
9277ec14
BC
837}
838
839int closedir(DIR *dirp)
840{
01d26955
BC
841 if (dirp != NULL && dirp->find_handle != INVALID_HANDLE_VALUE)
842 FindClose(dirp->find_handle);
ad9c0fbc 843
01d26955
BC
844 free(dirp);
845 return 0;
9277ec14
BC
846}
847
848struct dirent *readdir(DIR *dirp)
849{
ad9c0fbc
BC
850 static struct dirent de;
851 WIN32_FIND_DATA find_data;
852
853 if (dirp == NULL)
854 return NULL;
855
856 if (dirp->find_handle == INVALID_HANDLE_VALUE) {
857 char search_pattern[MAX_PATH];
858 StringCchPrintfA(search_pattern, MAX_PATH, "%s\\*", dirp->dirname);
859 dirp->find_handle = FindFirstFileA(search_pattern, &find_data);
860 if (dirp->find_handle == INVALID_HANDLE_VALUE)
861 return NULL;
862 } else {
863 if (!FindNextFile(dirp->find_handle, &find_data))
864 return NULL;
865 }
866
867 StringCchCopyA(de.d_name, MAX_PATH, find_data.cFileName);
868 de.d_ino = 0;
869
870 return &de;
9277ec14
BC
871}
872
873uid_t geteuid(void)
874{
875 log_err("%s is not implemented\n", __func__);
876 errno = ENOSYS;
877 return -1;
878}
879
9277ec14
BC
880const char* inet_ntop(int af, const void *restrict src,
881 char *restrict dst, socklen_t size)
882{
883 INT status = SOCKET_ERROR;
884 WSADATA wsd;
885 char *ret = NULL;
886
887 if (af != AF_INET && af != AF_INET6) {
888 errno = EAFNOSUPPORT;
889 return NULL;
890 }
891
892 WSAStartup(MAKEWORD(2,2), &wsd);
893
894 if (af == AF_INET) {
895 struct sockaddr_in si;
896 DWORD len = size;
897 memset(&si, 0, sizeof(si));
898 si.sin_family = af;
899 memcpy(&si.sin_addr, src, sizeof(si.sin_addr));
900 status = WSAAddressToString((struct sockaddr*)&si, sizeof(si), NULL, dst, &len);
901 } else if (af == AF_INET6) {
902 struct sockaddr_in6 si6;
903 DWORD len = size;
904 memset(&si6, 0, sizeof(si6));
905 si6.sin6_family = af;
906 memcpy(&si6.sin6_addr, src, sizeof(si6.sin6_addr));
907 status = WSAAddressToString((struct sockaddr*)&si6, sizeof(si6), NULL, dst, &len);
908 }
909
910 if (status != SOCKET_ERROR)
911 ret = dst;
912 else
913 errno = ENOSPC;
914
915 WSACleanup();
3f457bea 916
9277ec14
BC
917 return ret;
918}
919
920int inet_pton(int af, const char *restrict src, void *restrict dst)
921{
922 INT status = SOCKET_ERROR;
923 WSADATA wsd;
924 int ret = 1;
925
926 if (af != AF_INET && af != AF_INET6) {
927 errno = EAFNOSUPPORT;
928 return -1;
929 }
930
931 WSAStartup(MAKEWORD(2,2), &wsd);
932
933 if (af == AF_INET) {
934 struct sockaddr_in si;
935 INT len = sizeof(si);
936 memset(&si, 0, sizeof(si));
937 si.sin_family = af;
938 status = WSAStringToAddressA((char*)src, af, NULL, (struct sockaddr*)&si, &len);
939 if (status != SOCKET_ERROR)
940 memcpy(dst, &si.sin_addr, sizeof(si.sin_addr));
941 } else if (af == AF_INET6) {
942 struct sockaddr_in6 si6;
943 INT len = sizeof(si6);
944 memset(&si6, 0, sizeof(si6));
945 si6.sin6_family = af;
946 status = WSAStringToAddressA((char*)src, af, NULL, (struct sockaddr*)&si6, &len);
947 if (status != SOCKET_ERROR)
948 memcpy(dst, &si6.sin6_addr, sizeof(si6.sin6_addr));
949 }
950
951 if (status == SOCKET_ERROR) {
952 errno = ENOSPC;
953 ret = 0;
954 }
955
956 WSACleanup();
957
958 return ret;
959}