27 #define _LARGEFILE64_SOURCE 1
36 #if defined(_WIN32) || _POSIX_C_SOURCE >= 200112L
50 static ssize_t file_read(
struct io_handle *handle,
void *buf,
size_t nbytes);
51 static ssize_t file_write(
52 struct io_handle *handle,
const void *buf,
size_t nbytes);
53 static int file_flush(
struct io_handle *handle);
55 static ssize_t file_pread(
struct io_handle *handle,
void *buf,
size_t nbytes,
57 static ssize_t file_pwrite(
struct io_handle *handle,
const void *buf,
61 .size =
sizeof(
struct file),
62 .fini = &default_fini,
67 .pwrite = &file_pwrite };
70 static ssize_t _file_read(
struct io_handle *handle,
void *buf,
size_t nbytes,
72 static ssize_t _file_write(
struct io_handle *handle,
const void *buf,
97 DWORD dwDesiredAccess = 0;
99 dwDesiredAccess |= FILE_READ_DATA;
101 dwDesiredAccess |= FILE_APPEND_DATA;
103 dwDesiredAccess |= FILE_WRITE_DATA;
107 DWORD dwCreationDisposition
117 HANDLE fd = CreateFileA(path, dwDesiredAccess, 0, NULL,
118 dwCreationDisposition, FILE_FLAG_OVERLAPPED, NULL);
140 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
146 fd = open(path, oflag, mode);
147 }
while (fd == -1 && errno == EINTR);
150 if (fd == INVALID_HANDLE_VALUE) {
158 goto error_alloc_handle;
178 #endif // _WIN32 || _POSIX_C_SOURCE >= 200112L
188 assert(handle->
vtab);
194 return handle->
vtab->
seek(handle, offset, whence);
205 assert(handle->
vtab);
211 return handle->
vtab->
pread(handle, buf, nbytes, offset);
222 assert(handle->
vtab);
228 return handle->
vtab->
pwrite(handle, buf, nbytes, offset);
231 #if defined(_WIN32) || _POSIX_C_SOURCE >= 200112L
234 file_read(
struct io_handle *handle,
void *buf,
size_t nbytes)
242 return _file_read(handle, buf, nbytes, current);
248 result = read(handle->
fd, buf, nbytes);
249 }
while (result == -1 && errno == EINTR);
255 file_write(
struct io_handle *handle,
const void *buf,
size_t nbytes)
264 current = UINT64_MAX;
270 return _file_write(handle, buf, nbytes, current);
276 result = write(handle->fd, buf, nbytes);
277 }
while (result == -1 && errno == EINTR);
288 return FlushFileBuffers(handle->
fd) ? 0 : -1;
294 result = fsync(handle->
fd);
295 }
while (result == -1 && errno == EINTR);
311 default: SetLastError(ERROR_INVALID_PARAMETER);
return -1;
315 li.QuadPart = offset;
316 li.LowPart = SetFilePointer(
317 handle->
fd, li.LowPart, &li.HighPart, dwMoveMethod);
318 if (li.LowPart == INVALID_SET_FILE_POINTER)
326 default: errno = EINVAL;
return -1;
329 #if defined(__linux__)
330 return lseek64(handle->
fd, offset, whence);
332 return lseek(handle->
fd, offset, whence);
346 ssize_t result = _file_read(handle, buf, nbytes, offset);
358 result = pread(handle->
fd, buf, nbytes, offset);
359 }
while (result == -1 && errno == EINTR);
365 file_pwrite(
struct io_handle *handle,
const void *buf,
size_t nbytes,
374 ssize_t result = _file_write(handle, buf, nbytes, offset);
386 result = pwrite(handle->
fd, buf, nbytes, offset);
387 }
while (result == -1 && errno == EINTR);
399 DWORD dwErrCode = GetLastError();
402 li.QuadPart = offset;
403 OVERLAPPED overlapped = { 0 };
404 overlapped.Offset = li.LowPart;
405 overlapped.OffsetHigh = li.HighPart;
406 overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
407 if (!overlapped.hEvent) {
408 dwErrCode = GetLastError();
409 goto error_CreateEvent;
412 DWORD dwNumberOfBytesRead = 0;
415 if (ReadFile(handle->
fd, buf, nbytes, &dwNumberOfBytesRead,
420 if (GetLastError() != ERROR_IO_PENDING) {
421 dwErrCode = GetLastError();
426 if (!GetOverlappedResult(handle->
fd, &overlapped, &dwNumberOfBytesRead,
429 dwErrCode = GetLastError();
430 goto error_GetOverlappedResult;
434 CloseHandle(overlapped.hEvent);
435 SetLastError(dwErrCode);
436 return dwNumberOfBytesRead;
438 error_GetOverlappedResult:
440 CloseHandle(overlapped.hEvent);
442 SetLastError(dwErrCode);
447 _file_write(
struct io_handle *handle,
const void *buf,
size_t nbytes,
452 DWORD dwErrCode = GetLastError();
455 li.QuadPart = offset;
456 OVERLAPPED overlapped = { 0 };
457 overlapped.Offset = li.LowPart;
458 overlapped.OffsetHigh = li.HighPart;
459 overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
460 if (!overlapped.hEvent) {
461 dwErrCode = GetLastError();
462 goto error_CreateEvent;
465 DWORD dwNumberOfBytesWritten = 0;
468 if (WriteFile(handle->
fd, buf, nbytes, &dwNumberOfBytesWritten,
473 if (GetLastError() != ERROR_IO_PENDING) {
474 dwErrCode = GetLastError();
475 goto error_WriteFile;
479 if (!GetOverlappedResult(handle->
fd, &overlapped,
480 &dwNumberOfBytesWritten, TRUE)) {
482 dwErrCode = GetLastError();
483 goto error_GetOverlappedResult;
487 CloseHandle(overlapped.hEvent);
488 SetLastError(dwErrCode);
489 return dwNumberOfBytesWritten;
491 error_GetOverlappedResult:
493 CloseHandle(overlapped.hEvent);
495 SetLastError(dwErrCode);
501 #endif // _WIN32 || _POSIX_C_SOURCE >= 200112L