blob: 8a52a6849e4b4083b5d6ba0a6c787346714890a7 [file] [log] [blame]
Bruce Cran9277ec12012-02-20 19:28:39 +00001/* 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>
Bruce Cranad9c0fb2012-08-21 15:45:57 +020010#include <string.h>
Bruce Cran9277ec12012-02-20 19:28:39 +000011#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"
Bruce Cran671b0602013-01-21 10:57:59 -070023#include "../../lib/hweight.h"
Bruce Cran9277ec12012-02-20 19:28:39 +000024
Bruce Cran21c75382012-08-15 20:24:24 +020025extern unsigned long mtime_since_now(struct timeval *);
26extern void fio_gettime(struct timeval *, void *);
27
Bruce Cranad9c0fb2012-08-21 15:45:57 +020028/* 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
Bruce Cran671b0602013-01-21 10:57:59 -070046int GetNumLogicalProcessors(void)
47{
48 SYSTEM_LOGICAL_PROCESSOR_INFORMATION *processor_info = NULL;
49 DWORD len = 0;
50 DWORD num_processors = 0;
51 DWORD error = 0;
52 DWORD i;
53
54 while (!GetLogicalProcessorInformation(processor_info, &len)) {
55 error = GetLastError();
56 if (error == ERROR_INSUFFICIENT_BUFFER)
57 processor_info = malloc(len);
58 else {
59 log_err("Error: GetLogicalProcessorInformation failed: %d\n", error);
60 return -1;
61 }
62
63 if (processor_info == NULL) {
64 log_err("Error: failed to allocate memory for GetLogicalProcessorInformation");
65 return -1;
66 }
67 }
68
69 for (i = 0; i < len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); i++)
70 {
71 if (processor_info[i].Relationship == RelationProcessorCore)
Jens Axboe4ee47af2013-01-21 12:28:42 -070072 num_processors += hweight64(processor_info[i].ProcessorMask);
Bruce Cran671b0602013-01-21 10:57:59 -070073 }
74
75 free(processor_info);
76 return num_processors;
77}
78
Bruce Cran9277ec12012-02-20 19:28:39 +000079long sysconf(int name)
80{
Bruce Cran671b0602013-01-21 10:57:59 -070081 long val = -1;
Bruce Cran01d26952013-02-06 20:27:27 +000082 long val2 = -1;
Bruce Cran9277ec12012-02-20 19:28:39 +000083 SYSTEM_INFO sysInfo;
84 MEMORYSTATUSEX status;
85
86 switch (name)
87 {
88 case _SC_NPROCESSORS_ONLN:
Bruce Cran671b0602013-01-21 10:57:59 -070089 val = GetNumLogicalProcessors();
90 if (val == -1)
Bruce Cran01d26952013-02-06 20:27:27 +000091 log_err("sysconf(_SC_NPROCESSORS_ONLN) failed\n");
Bruce Cran671b0602013-01-21 10:57:59 -070092
Bruce Cran9277ec12012-02-20 19:28:39 +000093 break;
94
95 case _SC_PAGESIZE:
96 GetSystemInfo(&sysInfo);
97 val = sysInfo.dwPageSize;
98 break;
99
100 case _SC_PHYS_PAGES:
101 status.dwLength = sizeof(status);
Bruce Cran01d26952013-02-06 20:27:27 +0000102 val2 = sysconf(_SC_PAGESIZE);
103 if (GlobalMemoryStatusEx(&status) && val2 != -1)
104 val = status.ullTotalPhys / val2;
105 else
106 log_err("sysconf(_SC_PHYS_PAGES) failed\n");
Bruce Cran9277ec12012-02-20 19:28:39 +0000107 break;
108 default:
109 log_err("sysconf(%d) is not implemented\n", name);
110 break;
111 }
112
113 return val;
114}
115
116char *dl_error = NULL;
117
118int dlclose(void *handle)
119{
120 return !FreeLibrary((HMODULE)handle);
121}
122
123void *dlopen(const char *file, int mode)
124{
125 HMODULE hMod;
126
127 hMod = LoadLibrary(file);
128 if (hMod == INVALID_HANDLE_VALUE)
129 dl_error = (char*)"LoadLibrary failed";
130 else
131 dl_error = NULL;
132
133 return hMod;
134}
135
136void *dlsym(void *handle, const char *name)
137{
138 FARPROC fnPtr;
139
140 fnPtr = GetProcAddress((HMODULE)handle, name);
141 if (fnPtr == NULL)
142 dl_error = (char*)"GetProcAddress failed";
143 else
144 dl_error = NULL;
145
146 return fnPtr;
147}
148
149char *dlerror(void)
150{
151 return dl_error;
152}
153
154int gettimeofday(struct timeval *restrict tp, void *restrict tzp)
155{
156 FILETIME fileTime;
Bruce Cran9576f612012-08-17 15:10:04 +0200157 uint64_t unix_time, windows_time;
158 const uint64_t MILLISECONDS_BETWEEN_1601_AND_1970 = 11644473600000;
Bruce Cran9277ec12012-02-20 19:28:39 +0000159
Bruce Cranfc0b8302012-02-20 21:03:48 +0100160 /* Ignore the timezone parameter */
Bruce Cran9277ec12012-02-20 19:28:39 +0000161 (void)tzp;
162
163 /*
164 * Windows time is stored as the number 100 ns intervals since January 1 1601.
165 * Conversion details from http://www.informit.com/articles/article.aspx?p=102236&seqNum=3
166 * Its precision is 100 ns but accuracy is only one clock tick, or normally around 15 ms.
167 */
168 GetSystemTimeAsFileTime(&fileTime);
Bruce Cran9576f612012-08-17 15:10:04 +0200169 windows_time = ((uint64_t)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime;
Bruce Cran9277ec12012-02-20 19:28:39 +0000170 /* Divide by 10,000 to convert to ms and subtract the time between 1601 and 1970 */
171 unix_time = (((windows_time)/10000) - MILLISECONDS_BETWEEN_1601_AND_1970);
172 /* unix_time is now the number of milliseconds since 1970 (the Unix epoch) */
173 tp->tv_sec = unix_time / 1000;
174 tp->tv_usec = (unix_time % 1000) * 1000;
175 return 0;
176}
177
Bruce Cran9277ec12012-02-20 19:28:39 +0000178int sigaction(int sig, const struct sigaction *act,
179 struct sigaction *oact)
180{
Bruce Crane5b8f912012-02-22 19:56:22 +0000181 int rc = 0;
182 void (*prev_handler)(int);
183
184 prev_handler = signal(sig, act->sa_handler);
185 if (oact != NULL)
186 oact->sa_handler = prev_handler;
187
188 if (prev_handler == SIG_ERR)
189 rc = -1;
190
191 return rc;
Bruce Cran9277ec12012-02-20 19:28:39 +0000192}
193
194int lstat(const char * path, struct stat * buf)
195{
196 return stat(path, buf);
197}
198
199void *mmap(void *addr, size_t len, int prot, int flags,
200 int fildes, off_t off)
201{
202 DWORD vaProt = 0;
203 void* allocAddr = NULL;
204
205 if (prot & PROT_NONE)
206 vaProt |= PAGE_NOACCESS;
207
208 if ((prot & PROT_READ) && !(prot & PROT_WRITE))
209 vaProt |= PAGE_READONLY;
210
211 if (prot & PROT_WRITE)
212 vaProt |= PAGE_READWRITE;
213
214 if ((flags & MAP_ANON) | (flags & MAP_ANONYMOUS))
215 {
216 allocAddr = VirtualAlloc(addr, len, MEM_COMMIT, vaProt);
217 }
218
219 return allocAddr;
220}
221
222int munmap(void *addr, size_t len)
223{
224 return !VirtualFree(addr, 0, MEM_RELEASE);
225}
226
227int fork(void)
228{
229 log_err("%s is not implemented\n", __func__);
230 errno = ENOSYS;
231 return (-1);
232}
233
234pid_t setsid(void)
235{
236 log_err("%s is not implemented\n", __func__);
237 errno = ENOSYS;
238 return (-1);
239}
240
Bruce Cranad9c0fb2012-08-21 15:45:57 +0200241static HANDLE log_file = INVALID_HANDLE_VALUE;
242
Bruce Cran9277ec12012-02-20 19:28:39 +0000243void openlog(const char *ident, int logopt, int facility)
244{
Bruce Cranad9c0fb2012-08-21 15:45:57 +0200245 if (log_file == INVALID_HANDLE_VALUE)
246 log_file = CreateFileA("syslog.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
Bruce Cran9277ec12012-02-20 19:28:39 +0000247}
248
249void closelog(void)
250{
Bruce Cranad9c0fb2012-08-21 15:45:57 +0200251 CloseHandle(log_file);
252 log_file = INVALID_HANDLE_VALUE;
253}
254
255void syslog(int priority, const char *message, ... /* argument */)
256{
257 va_list v;
258 int len;
259 char *output;
260 DWORD bytes_written;
261
262 if (log_file == INVALID_HANDLE_VALUE) {
263 log_file = CreateFileA("syslog.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
264 }
265
266 if (log_file == INVALID_HANDLE_VALUE) {
267 log_err("syslog: failed to open log file\n");
268 return;
269 }
270
271 va_start(v, message);
272 len = _vscprintf(message, v);
273 output = malloc(len + sizeof(char));
Bruce Cran98dc2db2012-10-03 19:46:46 +0200274 vsprintf(output, message, v);
Bruce Cranad9c0fb2012-08-21 15:45:57 +0200275 WriteFile(log_file, output, len, &bytes_written, NULL);
276 va_end(v);
Bruce Cran98dc2db2012-10-03 19:46:46 +0200277 free(output);
Bruce Cran9277ec12012-02-20 19:28:39 +0000278}
279
280int kill(pid_t pid, int sig)
281{
282 errno = ESRCH;
283 return (-1);
284}
285
Bruce Cranfc0b8302012-02-20 21:03:48 +0100286/*
287 * This is assumed to be used only by the network code,
288 * and so doesn't try and handle any of the other cases
289 */
Bruce Cran9277ec12012-02-20 19:28:39 +0000290int fcntl(int fildes, int cmd, ...)
291{
Bruce Cranfc0b8302012-02-20 21:03:48 +0100292 /*
293 * non-blocking mode doesn't work the same as in BSD sockets,
294 * so ignore it.
295 */
Bruce Cran9277ec12012-02-20 19:28:39 +0000296#if 0
297 va_list ap;
298 int val, opt, status;
299
300 if (cmd == F_GETFL)
301 return 0;
302 else if (cmd != F_SETFL) {
303 errno = EINVAL;
304 return (-1);
305 }
306
307 va_start(ap, 1);
308
309 opt = va_arg(ap, int);
310 if (opt & O_NONBLOCK)
311 val = 1;
312 else
313 val = 0;
314
315 status = ioctlsocket((SOCKET)fildes, opt, &val);
316
317 if (status == SOCKET_ERROR) {
318 errno = EINVAL;
319 val = -1;
320 }
321
322 va_end(ap);
323
324 return val;
325#endif
326return 0;
327}
328
329/*
330 * Get the value of a local clock source.
331 * This implementation supports 2 clocks: CLOCK_MONOTONIC provides high-accuracy
332 * relative time, while CLOCK_REALTIME provides a low-accuracy wall time.
333 */
334int clock_gettime(clockid_t clock_id, struct timespec *tp)
335{
336 int rc = 0;
337
338 if (clock_id == CLOCK_MONOTONIC)
339 {
340 static LARGE_INTEGER freq = {{0,0}};
341 LARGE_INTEGER counts;
342
343 QueryPerformanceCounter(&counts);
344 if (freq.QuadPart == 0)
345 QueryPerformanceFrequency(&freq);
346
347 tp->tv_sec = counts.QuadPart / freq.QuadPart;
348 /* Get the difference between the number of ns stored
349 * in 'tv_sec' and that stored in 'counts' */
Bruce Cran9576f612012-08-17 15:10:04 +0200350 uint64_t t = tp->tv_sec * freq.QuadPart;
Bruce Cran9277ec12012-02-20 19:28:39 +0000351 t = counts.QuadPart - t;
352 /* 't' now contains the number of cycles since the last second.
353 * We want the number of nanoseconds, so multiply out by 1,000,000,000
354 * and then divide by the frequency. */
355 t *= 1000000000;
356 tp->tv_nsec = t / freq.QuadPart;
357 }
358 else if (clock_id == CLOCK_REALTIME)
359 {
360 /* clock_gettime(CLOCK_REALTIME,...) is just an alias for gettimeofday with a
361 * higher-precision field. */
362 struct timeval tv;
363 gettimeofday(&tv, NULL);
364 tp->tv_sec = tv.tv_sec;
365 tp->tv_nsec = tv.tv_usec * 1000;
366 } else {
367 errno = EINVAL;
368 rc = -1;
369 }
370
371 return rc;
372}
373
374int mlock(const void * addr, size_t len)
375{
376 return !VirtualLock((LPVOID)addr, len);
377}
378
379int munlock(const void * addr, size_t len)
380{
381 return !VirtualUnlock((LPVOID)addr, len);
382}
383
384pid_t waitpid(pid_t pid, int *stat_loc, int options)
385{
386 log_err("%s is not implemented\n", __func__);
387 errno = ENOSYS;
388 return -1;
389}
390
391int usleep(useconds_t useconds)
392{
393 Sleep(useconds / 1000);
394 return 0;
395}
396
397char *basename(char *path)
398{
399 static char name[MAX_PATH];
400 int i;
401
402 if (path == NULL || strlen(path) == 0)
403 return (char*)".";
404
405 i = strlen(path) - 1;
406
Bruce Cran9576f612012-08-17 15:10:04 +0200407 while (path[i] != '\\' && path[i] != '/' && i >= 0)
Bruce Cran9277ec12012-02-20 19:28:39 +0000408 i--;
409
Bruce Cran9576f612012-08-17 15:10:04 +0200410 strncpy(name, path + i + 1, MAX_PATH);
Bruce Cran9277ec12012-02-20 19:28:39 +0000411
412 return name;
413}
414
Bruce Cran9277ec12012-02-20 19:28:39 +0000415int ftruncate(int fildes, off_t length)
416{
417 BOOL bSuccess;
Bruce Cran9576f612012-08-17 15:10:04 +0200418 int64_t prev_pos = _telli64(fildes);
419 _lseeki64(fildes, length, SEEK_SET);
Bruce Cran9277ec12012-02-20 19:28:39 +0000420 HANDLE hFile = (HANDLE)_get_osfhandle(fildes);
421 bSuccess = SetEndOfFile(hFile);
Bruce Cran9576f612012-08-17 15:10:04 +0200422 _lseeki64(fildes, prev_pos, SEEK_SET);
Bruce Cran9277ec12012-02-20 19:28:39 +0000423 return !bSuccess;
424}
425
426int fsync(int fildes)
427{
428 HANDLE hFile = (HANDLE)_get_osfhandle(fildes);
429 return !FlushFileBuffers(hFile);
430}
431
432int nFileMappings = 0;
433HANDLE fileMappings[1024];
434
435int shmget(key_t key, size_t size, int shmflg)
436{
437 int mapid = -1;
Bruce Crand3987942012-06-08 08:12:20 +0200438 uint32_t size_low = size & 0xFFFFFFFF;
439 uint32_t size_high = ((uint64_t)size) >> 32;
440 HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, (PAGE_EXECUTE_READWRITE | SEC_RESERVE), size_high, size_low, NULL);
Bruce Cran9277ec12012-02-20 19:28:39 +0000441 if (hMapping != NULL) {
442 fileMappings[nFileMappings] = hMapping;
443 mapid = nFileMappings;
444 nFileMappings++;
445 } else {
446 errno = ENOSYS;
447 }
448
449 return mapid;
450}
451
452void *shmat(int shmid, const void *shmaddr, int shmflg)
453{
454 void* mapAddr;
455 MEMORY_BASIC_INFORMATION memInfo;
456 mapAddr = MapViewOfFile(fileMappings[shmid], FILE_MAP_ALL_ACCESS, 0, 0, 0);
457 VirtualQuery(mapAddr, &memInfo, sizeof(memInfo));
458 mapAddr = VirtualAlloc(mapAddr, memInfo.RegionSize, MEM_COMMIT, PAGE_READWRITE);
459 return mapAddr;
460}
461
462int shmdt(const void *shmaddr)
463{
464 return !UnmapViewOfFile(shmaddr);
465}
466
467int shmctl(int shmid, int cmd, struct shmid_ds *buf)
468{
469 if (cmd == IPC_RMID) {
470 fileMappings[shmid] = INVALID_HANDLE_VALUE;
471 return 0;
472 } else {
473 log_err("%s is not implemented\n", __func__);
474 }
475 return (-1);
476}
477
478int setuid(uid_t uid)
479{
480 log_err("%s is not implemented\n", __func__);
481 errno = ENOSYS;
482 return (-1);
483}
484
485int setgid(gid_t gid)
486{
487 log_err("%s is not implemented\n", __func__);
488 errno = ENOSYS;
489 return (-1);
490}
491
492int nice(int incr)
493{
494 if (incr != 0) {
495 errno = EINVAL;
496 return -1;
497 }
498
499 return 0;
500}
501
502int getrusage(int who, struct rusage *r_usage)
503{
Bruce Cran9576f612012-08-17 15:10:04 +0200504 const uint64_t SECONDS_BETWEEN_1601_AND_1970 = 11644473600;
Bruce Cran9277ec12012-02-20 19:28:39 +0000505 FILETIME cTime, eTime, kTime, uTime;
506 time_t time;
Huadong Liu7732a092013-01-24 14:07:20 -0700507 HANDLE h;
Bruce Cran9277ec12012-02-20 19:28:39 +0000508
509 memset(r_usage, 0, sizeof(*r_usage));
510
Huadong Liu7732a092013-01-24 14:07:20 -0700511 if (who == RUSAGE_SELF) {
512 h = GetCurrentProcess();
513 GetProcessTimes(h, &cTime, &eTime, &kTime, &uTime);
514 } else if (who == RUSAGE_THREAD) {
515 h = GetCurrentThread();
516 GetThreadTimes(h, &cTime, &eTime, &kTime, &uTime);
517 } else {
518 log_err("fio: getrusage %d is not implemented\n", who);
519 return -1;
520 }
521
Bruce Cran9576f612012-08-17 15:10:04 +0200522 time = ((uint64_t)uTime.dwHighDateTime << 32) + uTime.dwLowDateTime;
Bruce Cran9277ec12012-02-20 19:28:39 +0000523 /* Divide by 10,000,000 to get the number of seconds and move the epoch from
524 * 1601 to 1970 */
525 time = (time_t)(((time)/10000000) - SECONDS_BETWEEN_1601_AND_1970);
526 r_usage->ru_utime.tv_sec = time;
527 /* getrusage() doesn't care about anything other than seconds, so set tv_usec to 0 */
528 r_usage->ru_utime.tv_usec = 0;
Bruce Cran9576f612012-08-17 15:10:04 +0200529 time = ((uint64_t)kTime.dwHighDateTime << 32) + kTime.dwLowDateTime;
Bruce Cran9277ec12012-02-20 19:28:39 +0000530 /* Divide by 10,000,000 to get the number of seconds and move the epoch from
531 * 1601 to 1970 */
532 time = (time_t)(((time)/10000000) - SECONDS_BETWEEN_1601_AND_1970);
533 r_usage->ru_stime.tv_sec = time;
534 r_usage->ru_stime.tv_usec = 0;
535 return 0;
536}
537
Bruce Cran2277d5d2012-12-06 20:33:14 +0100538int posix_fadvise(int fd, off_t offset, off_t len, int advice)
539{
540 return 0;
541}
542
Bruce Cran9277ec12012-02-20 19:28:39 +0000543int posix_madvise(void *addr, size_t len, int advice)
544{
545 log_err("%s is not implemented\n", __func__);
546 return ENOSYS;
547}
548
Bruce Cranfc0b8302012-02-20 21:03:48 +0100549/* Windows doesn't support advice for memory pages. Just ignore it. */
Bruce Cran9277ec12012-02-20 19:28:39 +0000550int msync(void *addr, size_t len, int flags)
551{
Bruce Cran9277ec12012-02-20 19:28:39 +0000552 errno = ENOSYS;
553 return -1;
554}
555
556int fdatasync(int fildes)
557{
558 return fsync(fildes);
559}
560
561ssize_t pwrite(int fildes, const void *buf, size_t nbyte,
562 off_t offset)
563{
Bruce Cran9576f612012-08-17 15:10:04 +0200564 int64_t pos = _telli64(fildes);
565 ssize_t len = _write(fildes, buf, nbyte);
566 _lseeki64(fildes, pos, SEEK_SET);
Bruce Cran9277ec12012-02-20 19:28:39 +0000567 return len;
568}
569
570ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset)
571{
Bruce Cran9576f612012-08-17 15:10:04 +0200572 int64_t pos = _telli64(fildes);
Bruce Cran9277ec12012-02-20 19:28:39 +0000573 ssize_t len = read(fildes, buf, nbyte);
Bruce Cran9576f612012-08-17 15:10:04 +0200574 _lseeki64(fildes, pos, SEEK_SET);
Bruce Cran9277ec12012-02-20 19:28:39 +0000575 return len;
576}
577
578ssize_t readv(int fildes, const struct iovec *iov, int iovcnt)
579{
580 log_err("%s is not implemented\n", __func__);
581 errno = ENOSYS;
582 return (-1);
583}
584
585ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)
586{
587 log_err("%s is not implemented\n", __func__);
588 errno = ENOSYS;
589 return (-1);
590}
591
592long long strtoll(const char *restrict str, char **restrict endptr,
593 int base)
594{
595 return _strtoi64(str, endptr, base);
596}
597
Bruce Cran9277ec12012-02-20 19:28:39 +0000598int poll(struct pollfd fds[], nfds_t nfds, int timeout)
599{
600 struct timeval tv;
601 struct timeval *to = NULL;
602 fd_set readfds, writefds, exceptfds;
603 int i;
604 int rc;
605
Bruce Cran3f457be2012-10-10 13:37:41 +0100606 if (timeout != -1) {
Bruce Cranf9a58c22012-04-04 08:35:13 -0600607 to = &tv;
Bruce Cran3f457be2012-10-10 13:37:41 +0100608 to->tv_sec = timeout / 1000;
609 to->tv_usec = (timeout % 1000) * 1000;
610 }
Bruce Cran9277ec12012-02-20 19:28:39 +0000611
612 FD_ZERO(&readfds);
613 FD_ZERO(&writefds);
614 FD_ZERO(&exceptfds);
615
616 for (i = 0; i < nfds; i++)
617 {
618 if (fds[i].fd < 0) {
619 fds[i].revents = 0;
620 continue;
621 }
622
623 if (fds[i].events & POLLIN)
624 FD_SET(fds[i].fd, &readfds);
625
626 if (fds[i].events & POLLOUT)
627 FD_SET(fds[i].fd, &writefds);
628
Bruce Cranf9a58c22012-04-04 08:35:13 -0600629 FD_SET(fds[i].fd, &exceptfds);
Bruce Cran9277ec12012-02-20 19:28:39 +0000630 }
631
632 rc = select(nfds, &readfds, &writefds, &exceptfds, to);
633
634 if (rc != SOCKET_ERROR) {
635 for (i = 0; i < nfds; i++)
636 {
637 if (fds[i].fd < 0) {
638 continue;
639 }
640
641 if ((fds[i].events & POLLIN) && FD_ISSET(fds[i].fd, &readfds))
642 fds[i].revents |= POLLIN;
643
644 if ((fds[i].events & POLLOUT) && FD_ISSET(fds[i].fd, &writefds))
645 fds[i].revents |= POLLOUT;
646
647 if (FD_ISSET(fds[i].fd, &exceptfds))
648 fds[i].revents |= POLLHUP;
649 }
650 }
651
652 return rc;
653}
654
655int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
656{
Bruce Cran21c75382012-08-15 20:24:24 +0200657 struct timeval tv;
658 DWORD ms_remaining;
659 DWORD ms_total = (rqtp->tv_sec * 1000) + (rqtp->tv_nsec / 1000000.0);
660
661 if (ms_total == 0)
662 ms_total = 1;
663
664 ms_remaining = ms_total;
665
666 /* Since Sleep() can sleep for less than the requested time, add a loop to
667 ensure we only return after the requested length of time has elapsed */
668 do {
669 fio_gettime(&tv, NULL);
670 Sleep(ms_remaining);
671 ms_remaining = ms_total - mtime_since_now(&tv);
672 } while (ms_remaining > 0 && ms_remaining < ms_total);
673
674 /* this implementation will never sleep for less than the requested time */
675 if (rmtp != NULL) {
676 rmtp->tv_sec = 0;
677 rmtp->tv_nsec = 0;
678 }
679
680 return 0;
Bruce Cran9277ec12012-02-20 19:28:39 +0000681}
682
683DIR *opendir(const char *dirname)
684{
Bruce Cran01d26952013-02-06 20:27:27 +0000685 struct dirent_ctx *dc = NULL;
Bruce Cranad9c0fb2012-08-21 15:45:57 +0200686
Bruce Cran01d26952013-02-06 20:27:27 +0000687 /* See if we can open it. If not, we'll return an error here */
688 HANDLE file = CreateFileA(dirname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
689 if (file != INVALID_HANDLE_VALUE) {
690 CloseHandle(file);
691 dc = (struct dirent_ctx*)malloc(sizeof(struct dirent_ctx));
692 StringCchCopyA(dc->dirname, MAX_PATH, dirname);
693 dc->find_handle = INVALID_HANDLE_VALUE;
694 } else {
695 DWORD error = GetLastError();
696 if (error == ERROR_FILE_NOT_FOUND)
697 errno = ENOENT;
Bruce Cranad9c0fb2012-08-21 15:45:57 +0200698
Bruce Cran01d26952013-02-06 20:27:27 +0000699 else if (error == ERROR_PATH_NOT_FOUND)
700 errno = ENOTDIR;
701 else if (error == ERROR_TOO_MANY_OPEN_FILES)
702 errno = ENFILE;
703 else if (error == ERROR_ACCESS_DENIED)
704 errno = EACCES;
705 else
706 errno = error;
707 }
Bruce Cranad9c0fb2012-08-21 15:45:57 +0200708
Bruce Cran01d26952013-02-06 20:27:27 +0000709 return dc;
Bruce Cran9277ec12012-02-20 19:28:39 +0000710}
711
712int closedir(DIR *dirp)
713{
Bruce Cran01d26952013-02-06 20:27:27 +0000714 if (dirp != NULL && dirp->find_handle != INVALID_HANDLE_VALUE)
715 FindClose(dirp->find_handle);
Bruce Cranad9c0fb2012-08-21 15:45:57 +0200716
Bruce Cran01d26952013-02-06 20:27:27 +0000717 free(dirp);
718 return 0;
Bruce Cran9277ec12012-02-20 19:28:39 +0000719}
720
721struct dirent *readdir(DIR *dirp)
722{
Bruce Cranad9c0fb2012-08-21 15:45:57 +0200723 static struct dirent de;
724 WIN32_FIND_DATA find_data;
725
726 if (dirp == NULL)
727 return NULL;
728
729 if (dirp->find_handle == INVALID_HANDLE_VALUE) {
730 char search_pattern[MAX_PATH];
731 StringCchPrintfA(search_pattern, MAX_PATH, "%s\\*", dirp->dirname);
732 dirp->find_handle = FindFirstFileA(search_pattern, &find_data);
733 if (dirp->find_handle == INVALID_HANDLE_VALUE)
734 return NULL;
735 } else {
736 if (!FindNextFile(dirp->find_handle, &find_data))
737 return NULL;
738 }
739
740 StringCchCopyA(de.d_name, MAX_PATH, find_data.cFileName);
741 de.d_ino = 0;
742
743 return &de;
Bruce Cran9277ec12012-02-20 19:28:39 +0000744}
745
746uid_t geteuid(void)
747{
748 log_err("%s is not implemented\n", __func__);
749 errno = ENOSYS;
750 return -1;
751}
752
Bruce Cran9277ec12012-02-20 19:28:39 +0000753const char* inet_ntop(int af, const void *restrict src,
754 char *restrict dst, socklen_t size)
755{
756 INT status = SOCKET_ERROR;
757 WSADATA wsd;
758 char *ret = NULL;
759
760 if (af != AF_INET && af != AF_INET6) {
761 errno = EAFNOSUPPORT;
762 return NULL;
763 }
764
765 WSAStartup(MAKEWORD(2,2), &wsd);
766
767 if (af == AF_INET) {
768 struct sockaddr_in si;
769 DWORD len = size;
770 memset(&si, 0, sizeof(si));
771 si.sin_family = af;
772 memcpy(&si.sin_addr, src, sizeof(si.sin_addr));
773 status = WSAAddressToString((struct sockaddr*)&si, sizeof(si), NULL, dst, &len);
774 } else if (af == AF_INET6) {
775 struct sockaddr_in6 si6;
776 DWORD len = size;
777 memset(&si6, 0, sizeof(si6));
778 si6.sin6_family = af;
779 memcpy(&si6.sin6_addr, src, sizeof(si6.sin6_addr));
780 status = WSAAddressToString((struct sockaddr*)&si6, sizeof(si6), NULL, dst, &len);
781 }
782
783 if (status != SOCKET_ERROR)
784 ret = dst;
785 else
786 errno = ENOSPC;
787
788 WSACleanup();
Bruce Cran3f457be2012-10-10 13:37:41 +0100789
Bruce Cran9277ec12012-02-20 19:28:39 +0000790 return ret;
791}
792
Bruce Cran9277ec12012-02-20 19:28:39 +0000793int inet_pton(int af, const char *restrict src, void *restrict dst)
794{
795 INT status = SOCKET_ERROR;
796 WSADATA wsd;
797 int ret = 1;
798
799 if (af != AF_INET && af != AF_INET6) {
800 errno = EAFNOSUPPORT;
801 return -1;
802 }
803
804 WSAStartup(MAKEWORD(2,2), &wsd);
805
806 if (af == AF_INET) {
807 struct sockaddr_in si;
808 INT len = sizeof(si);
809 memset(&si, 0, sizeof(si));
810 si.sin_family = af;
811 status = WSAStringToAddressA((char*)src, af, NULL, (struct sockaddr*)&si, &len);
812 if (status != SOCKET_ERROR)
813 memcpy(dst, &si.sin_addr, sizeof(si.sin_addr));
814 } else if (af == AF_INET6) {
815 struct sockaddr_in6 si6;
816 INT len = sizeof(si6);
817 memset(&si6, 0, sizeof(si6));
818 si6.sin6_family = af;
819 status = WSAStringToAddressA((char*)src, af, NULL, (struct sockaddr*)&si6, &len);
820 if (status != SOCKET_ERROR)
821 memcpy(dst, &si6.sin6_addr, sizeof(si6.sin6_addr));
822 }
823
824 if (status == SOCKET_ERROR) {
825 errno = ENOSPC;
826 ret = 0;
827 }
828
829 WSACleanup();
830
831 return ret;
832}