• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <io.h>
2 #include <math.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <unistd.h>
6 #include "iwcfg.h"
7 
8 #define _NANOSECONDS_PER_TICK     100ULL
9 #define _NANOSECONDS_PER_SECOND   1000000000ULL
10 #define _TICKS_PER_SECOND         10000000ULL
11 #define _TICKS_PER_MILLISECOND    10000ULL
12 #define _SEC_TO_UNIX_EPOCH        11644473600ULL
13 #define _TICKS_TO_UNIX_EPOCH (_TICKS_PER_SECOND * _SEC_TO_UNIX_EPOCH)
14 #define _TIMESPEC2MS(IW_ts) ((IW_ts).tv_sec * 1000) + (uint64_t) round((IW_ts).tv_nsec / 1.0e6)
15 
_iwp_filetime2ticks(const FILETIME * ft)16 IW_INLINE uint64_t _iwp_filetime2ticks(const FILETIME *ft) {
17   uint64_t ticks = ((uint64_t) ft->dwHighDateTime << 32) + ft->dwLowDateTime;
18   if (ticks < _TICKS_TO_UNIX_EPOCH) {
19     return 0;
20   }
21   ticks -= _TICKS_TO_UNIX_EPOCH;
22   return ticks;
23 }
24 
_iwp_filetime2timespec(const FILETIME * ft,struct timespec * spec)25 IW_INLINE void _iwp_filetime2timespec(const FILETIME *ft, struct timespec *spec) {
26   uint64_t ticks = _iwp_filetime2ticks(ft);
27   spec->tv_sec = ticks / _TICKS_PER_SECOND;
28   spec->tv_nsec = (ticks % _TICKS_PER_SECOND) * _NANOSECONDS_PER_TICK;
29 }
30 
_iwp_filetime2millisecons(const FILETIME * ft)31 IW_INLINE uint64_t _iwp_filetime2millisecons(const FILETIME *ft) {
32   uint64_t ticks = _iwp_filetime2ticks(ft);
33   return ticks / _TICKS_PER_MILLISECOND;
34 }
35 
iwp_clock_get_time(int clock_id,struct timespec * spec)36 iwrc iwp_clock_get_time(int clock_id, struct timespec* spec) {
37   int rci = clock_gettime(clock_id, spec);
38   if (rci) {
39     return iwrc_set_errno(IW_ERROR_ERRNO, errno);
40   }
41   return 0;
42 }
43 
iwp_current_time_ms(uint64_t * time,bool monotonic)44 iwrc iwp_current_time_ms(uint64_t *time, bool monotonic) {
45   FILETIME ft;
46   GetSystemTimeAsFileTime(&ft);
47   *time = _iwp_filetime2millisecons(&ft);
48   return 0;
49 }
50 
iwp_fsync(HANDLE h)51 iwrc iwp_fsync(HANDLE h) {
52   if (INVALIDHANDLE(h)) {
53     return IW_ERROR_INVALID_HANDLE;
54   }
55   if (!FlushFileBuffers(h)) {
56     return iwrc_set_werror(IW_ERROR_IO_ERRNO, GetLastError());
57   }
58   return 0;
59 }
60 
iwp_fdatasync(HANDLE fh)61 iwrc iwp_fdatasync(HANDLE fh) {
62   return iwp_fsync(fh);
63 }
64 
65 static SYSTEM_INFO sysinfo;
66 
_iwp_getsysinfo()67 static void _iwp_getsysinfo() {
68   GetSystemInfo(&sysinfo);
69 }
70 
iwp_page_size(void)71 size_t iwp_page_size(void) {
72   return sysinfo.dwPageSize;
73 }
74 
iwp_alloc_unit(void)75 size_t iwp_alloc_unit(void) {
76   return sysinfo.dwAllocationGranularity;
77 }
78 
iwp_num_cpu_cores()79 uint16_t iwp_num_cpu_cores() {
80   return sysinfo.dwNumberOfProcessors;
81 }
82 
iwp_ftruncate(HANDLE fh,off_t len)83 iwrc iwp_ftruncate(HANDLE fh, off_t len) {
84   LARGE_INTEGER size;
85   size.QuadPart = len;
86   if (!SetFilePointerEx(fh, size, NULL, FILE_BEGIN)) {
87     return iwrc_set_werror(IW_ERROR_IO_ERRNO, GetLastError());
88   }
89   if (!SetEndOfFile(fh)) {
90     return iwrc_set_werror(IW_ERROR_IO_ERRNO, GetLastError());
91   }
92   return 0;
93 }
94 
iwp_fallocate(HANDLE fh,off_t len)95 iwrc iwp_fallocate(HANDLE fh, off_t len) {
96   return iwp_ftruncate(fh, len);
97 }
98 
iwp_sleep(uint64_t ms)99 iwrc iwp_sleep(uint64_t ms) {
100   iwrc rc = 0;
101   struct timespec req;
102   req.tv_sec = ms / 1000UL;
103   req.tv_nsec = (ms % 1000UL) * 1000UL * 1000UL;
104   if (nanosleep(&req, NULL)) {
105     rc = iwrc_set_errno(IW_ERROR_THREADING_ERRNO, errno);
106   }
107   return rc;
108 }
109 
iwp_fstat(const char * path,IWP_FILE_STAT * fs)110 iwrc iwp_fstat(const char *path, IWP_FILE_STAT *fs) {
111   memset(fs, 0, sizeof(*fs));
112   struct stat st = {0};
113   if (stat(path, &st)) {
114     return (errno == ENOENT) ? IW_ERROR_NOT_EXISTS : iwrc_set_errno(IW_ERROR_IO_ERRNO, errno);
115   }
116   fs->atime = 1000ULL * st.st_atime;
117   fs->mtime = 1000ULL * st.st_mtime;
118   fs->ctime = 1000ULL * st.st_ctime;
119   fs->size = st.st_size;
120   if (S_ISREG(st.st_mode)) {
121     fs->ftype = IWP_TYPE_FILE;
122   } else if (S_ISDIR(st.st_mode)) {
123     fs->ftype = IWP_TYPE_DIR;
124   } else {
125     fs->ftype = IWP_OTHER;
126   }
127   return 0;
128 }
129 
iwp_fstath(HANDLE fh,IWP_FILE_STAT * fs)130 iwrc iwp_fstath(HANDLE fh, IWP_FILE_STAT *fs) {
131   memset(fs, 0, sizeof(*fs));
132   BY_HANDLE_FILE_INFORMATION info;
133   if (INVALIDHANDLE(fh)) {
134     return IW_ERROR_INVALID_HANDLE;
135   }
136   if (!GetFileInformationByHandle(fh, &info)) {
137     uint32_t err = GetLastError();
138     if (err == ERROR_FILE_NOT_FOUND)  {
139       return IW_ERROR_NOT_EXISTS;
140     }
141     return iwrc_set_werror(IW_ERROR_IO_ERRNO, GetLastError());
142   }
143   fs->atime = _iwp_filetime2millisecons(&info.ftLastAccessTime);
144   fs->ctime = _iwp_filetime2millisecons(&info.ftCreationTime);
145   fs->mtime = _iwp_filetime2millisecons(&info.ftLastWriteTime);
146   ULARGE_INTEGER ul = {
147     .LowPart = info.nFileSizeLow,
148     .HighPart = info.nFileSizeHigh
149   };
150   fs->size = ul.QuadPart;
151   if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
152     fs->ftype = IWP_TYPE_DIR;
153   } else {
154     fs->ftype = IWP_TYPE_FILE;
155   }
156   return 0;
157 }
158 
iwp_closefh(HANDLE fh)159 iwrc iwp_closefh(HANDLE fh) {
160   if (INVALIDHANDLE(fh)) {
161     return 0;
162   }
163   if (!CloseHandle(fh)) {
164     return iwrc_set_werror(IW_ERROR_IO_ERRNO, GetLastError());
165   }
166   return 0;
167 }
168 
iwp_flock(HANDLE fh,iwp_lockmode lmode)169 iwrc iwp_flock(HANDLE fh, iwp_lockmode lmode) {
170   if (INVALIDHANDLE(fh)) {
171     return IW_ERROR_INVALID_HANDLE;
172   }
173   if (lmode == IWP_NOLOCK) {
174     return 0;
175   }
176   DWORD type = 0; /* shared lock with waiting */
177   OVERLAPPED offset = {0};
178   if (lmode & IWP_WLOCK) type = LOCKFILE_EXCLUSIVE_LOCK;
179   if (lmode & IWP_NBLOCK) type |= LOCKFILE_FAIL_IMMEDIATELY;
180   if (!LockFileEx(fh, type, 0, ULONG_MAX, ULONG_MAX, &offset)) {
181     return iwrc_set_werror(IW_ERROR_ERRNO, GetLastError());
182   }
183   return 0;
184 }
185 
iwp_unlock(HANDLE fh)186 iwrc iwp_unlock(HANDLE fh) {
187   if (INVALIDHANDLE(fh)) {
188     return IW_ERROR_INVALID_HANDLE;
189   }
190   OVERLAPPED offset = {0};
191   if (!UnlockFileEx(fh, 0, ULONG_MAX, ULONG_MAX, &offset)) {
192     return iwrc_set_werror(IW_ERROR_ERRNO, GetLastError());
193   } else {
194     return 0;
195   }
196 }
197 
iwp_pread(HANDLE fh,off_t off,void * buf,size_t siz,size_t * sp)198 iwrc iwp_pread(HANDLE fh, off_t off, void *buf, size_t siz, size_t *sp) {
199   if (INVALIDHANDLE(fh)) {
200     return IW_ERROR_INVALID_HANDLE;
201   }
202   if (!buf || !sp) {
203     return IW_ERROR_INVALID_ARGS;
204   }
205   DWORD rdb;
206   ULARGE_INTEGER bigint;
207   OVERLAPPED offset = {0};
208   bigint.QuadPart = off;
209   offset.Offset = bigint.LowPart;
210   offset.OffsetHigh = bigint.HighPart;
211   if (!ReadFile(fh, buf, siz, &rdb, &offset)) {
212     uint32_t err = GetLastError();
213     if (err == ERROR_HANDLE_EOF) {
214       *sp = rdb;
215       return 0;
216     }
217     *sp = 0;
218     return iwrc_set_werror(IW_ERROR_IO_ERRNO, err);
219   }
220   *sp = rdb;
221   return 0;
222 }
223 
iwp_read(HANDLE fh,void * buf,size_t siz,size_t * sp)224 iwrc iwp_read(HANDLE fh, void *buf, size_t siz, size_t *sp) {
225   if (INVALIDHANDLE(fh)) {
226     return IW_ERROR_INVALID_HANDLE;
227   }
228   if (!buf || !sp) {
229     return IW_ERROR_INVALID_ARGS;
230   }
231   DWORD rdb;
232   if (!ReadFile(fh, buf, siz, &rdb, NULL)) {
233     uint32_t err = GetLastError();
234     if (err == ERROR_HANDLE_EOF) {
235       *sp = rdb;
236       return 0;
237     }
238     *sp = 0;
239     return iwrc_set_werror(IW_ERROR_IO_ERRNO, err);
240   }
241   *sp = rdb;
242   return 0;
243 }
244 
iwp_pwrite(HANDLE fh,off_t off,const void * buf,size_t siz,size_t * sp)245 iwrc iwp_pwrite(HANDLE fh, off_t off, const void *buf, size_t siz, size_t *sp) {
246   if (INVALIDHANDLE(fh)) {
247     return IW_ERROR_INVALID_HANDLE;
248   }
249   if (!buf || !sp) {
250     return IW_ERROR_INVALID_ARGS;
251   }
252   DWORD wrb;
253   ULARGE_INTEGER bigint;
254   OVERLAPPED offset = {0};
255   bigint.QuadPart = off;
256   offset.Offset = bigint.LowPart;
257   offset.OffsetHigh = bigint.HighPart;
258   if (!WriteFile(fh, buf, siz, &wrb, &offset)) {
259     *sp = 0;
260     return iwrc_set_werror(IW_ERROR_IO_ERRNO, GetLastError());
261   }
262   *sp = wrb;
263   return 0;
264 }
265 
iwp_write(HANDLE fh,const void * buf,size_t size)266 iwrc iwp_write(HANDLE fh, const void *buf, size_t size) {
267   if (INVALIDHANDLE(fh)) {
268     return IW_ERROR_INVALID_HANDLE;
269   }
270   DWORD written;
271   if (!WriteFile(fh, buf, size, &written, NULL)) {
272     return iwrc_set_werror(IW_ERROR_IO_ERRNO, GetLastError());
273   }
274   return 0;
275 }
276 
iwp_lseek(HANDLE fh,off_t offset,iwp_seek_origin origin,off_t * pos)277 iwrc iwp_lseek(HANDLE fh, off_t offset, iwp_seek_origin origin, off_t *pos) {
278   if (INVALIDHANDLE(fh)) {
279     return IW_ERROR_INVALID_HANDLE;
280   }
281   if (pos) {
282     *pos = 0;
283   }
284   int w;
285   LARGE_INTEGER loff, noff;
286   loff.QuadPart = offset;
287   if (origin == IWP_SEEK_CUR) {
288     w = FILE_CURRENT;
289   } else if (origin == IWP_SEEK_END) {
290     w = FILE_END;
291   } else {
292     w = FILE_BEGIN;
293   }
294   if (!SetFilePointerEx(fh, loff, &noff, w)) {
295     return iwrc_set_werror(IW_ERROR_IO_ERRNO, GetLastError());
296   }
297   if (pos) {
298     *pos = noff.QuadPart;
299   }
300   return 0;
301 }
302 
iwp_tmpdir(char * out,size_t len)303 size_t iwp_tmpdir(char *out, size_t len) {
304   return GetTempPathA(len, out);
305 }
306 
_iwp_init_impl()307 static iwrc _iwp_init_impl() {
308   _iwp_getsysinfo();
309   return 0;
310 }
311