27 #define _LARGEFILE64_SOURCE 1
40 #if _WIN32 || _POSIX_C_SOURCE >= 200112L
54 static ssize_t file_read(
struct io_handle *handle,
void *buf,
size_t nbytes);
55 static ssize_t file_write(
56 struct io_handle *handle,
const void *buf,
size_t nbytes);
57 static int file_flush(
struct io_handle *handle);
59 static ssize_t file_pread(
struct io_handle *handle,
void *buf,
size_t nbytes,
61 static ssize_t file_pwrite(
struct io_handle *handle,
const void *buf,
65 .size =
sizeof(
struct file),
66 .fini = &default_fini,
71 .pwrite = &file_pwrite };
74 static ssize_t _file_read(
struct io_handle *handle,
void *buf,
size_t nbytes,
76 static ssize_t _file_write(
struct io_handle *handle,
const void *buf,
101 DWORD dwDesiredAccess = 0;
103 dwDesiredAccess |= FILE_READ_DATA;
105 dwDesiredAccess |= FILE_APPEND_DATA;
107 dwDesiredAccess |= FILE_WRITE_DATA;
111 DWORD dwCreationDisposition
121 HANDLE fd = CreateFileA(path, dwDesiredAccess, 0, NULL,
122 dwCreationDisposition, FILE_FLAG_OVERLAPPED, NULL);
144 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
150 fd = open(path, oflag, mode);
151 }
while (fd == -1 && errno == EINTR);
154 if (fd == INVALID_HANDLE_VALUE) {
162 goto error_alloc_handle;
182 #endif // _WIN32 || _POSIX_C_SOURCE >= 200112L
192 assert(handle->
vtab);
198 return handle->
vtab->
seek(handle, offset, whence);
209 assert(handle->
vtab);
215 return handle->
vtab->
pread(handle, buf, nbytes, offset);
226 assert(handle->
vtab);
232 return handle->
vtab->
pwrite(handle, buf, nbytes, offset);
235 #if _WIN32 || _POSIX_C_SOURCE >= 200112L
238 file_read(
struct io_handle *handle,
void *buf,
size_t nbytes)
246 return _file_read(handle, buf, nbytes, current);
252 result = read(handle->
fd, buf, nbytes);
253 }
while (result == -1 && errno == EINTR);
259 file_write(
struct io_handle *handle,
const void *buf,
size_t nbytes)
268 current = UINT64_MAX;
274 return _file_write(handle, buf, nbytes, current);
280 result = write(handle->fd, buf, nbytes);
281 }
while (result == -1 && errno == EINTR);
292 return FlushFileBuffers(handle->
fd) ? 0 : -1;
298 result = fsync(handle->
fd);
299 }
while (result == -1 && errno == EINTR);
315 default: SetLastError(ERROR_INVALID_PARAMETER);
return -1;
319 li.QuadPart = offset;
320 li.LowPart = SetFilePointer(
321 handle->
fd, li.LowPart, &li.HighPart, dwMoveMethod);
322 if (li.LowPart == INVALID_SET_FILE_POINTER)
330 default: errno = EINVAL;
return -1;
333 #if defined(__linux__)
334 return lseek64(handle->
fd, offset, whence);
336 return lseek(handle->
fd, offset, whence);
350 ssize_t result = _file_read(handle, buf, nbytes, offset);
362 result = pread(handle->
fd, buf, nbytes, offset);
363 }
while (result == -1 && errno == EINTR);
369 file_pwrite(
struct io_handle *handle,
const void *buf,
size_t nbytes,
378 ssize_t result = _file_write(handle, buf, nbytes, offset);
390 result = pwrite(handle->
fd, buf, nbytes, offset);
391 }
while (result == -1 && errno == EINTR);
403 DWORD dwErrCode = GetLastError();
406 li.QuadPart = offset;
407 OVERLAPPED overlapped = { 0 };
408 overlapped.Offset = li.LowPart;
409 overlapped.OffsetHigh = li.HighPart;
410 overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
411 if (!overlapped.hEvent) {
412 dwErrCode = GetLastError();
413 goto error_CreateEvent;
416 DWORD dwNumberOfBytesRead = 0;
419 if (ReadFile(handle->
fd, buf, nbytes, &dwNumberOfBytesRead,
424 if (GetLastError() != ERROR_IO_PENDING) {
425 dwErrCode = GetLastError();
430 if (!GetOverlappedResult(handle->
fd, &overlapped, &dwNumberOfBytesRead,
433 dwErrCode = GetLastError();
434 goto error_GetOverlappedResult;
438 CloseHandle(overlapped.hEvent);
439 SetLastError(dwErrCode);
440 return dwNumberOfBytesRead;
442 error_GetOverlappedResult:
444 CloseHandle(overlapped.hEvent);
446 SetLastError(dwErrCode);
451 _file_write(
struct io_handle *handle,
const void *buf,
size_t nbytes,
456 DWORD dwErrCode = GetLastError();
459 li.QuadPart = offset;
460 OVERLAPPED overlapped = { 0 };
461 overlapped.Offset = li.LowPart;
462 overlapped.OffsetHigh = li.HighPart;
463 overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
464 if (!overlapped.hEvent) {
465 dwErrCode = GetLastError();
466 goto error_CreateEvent;
469 DWORD dwNumberOfBytesWritten = 0;
472 if (WriteFile(handle->
fd, buf, nbytes, &dwNumberOfBytesWritten,
477 if (GetLastError() != ERROR_IO_PENDING) {
478 dwErrCode = GetLastError();
479 goto error_WriteFile;
483 if (!GetOverlappedResult(handle->
fd, &overlapped,
484 &dwNumberOfBytesWritten, TRUE)) {
486 dwErrCode = GetLastError();
487 goto error_GetOverlappedResult;
491 CloseHandle(overlapped.hEvent);
492 SetLastError(dwErrCode);
493 return dwNumberOfBytesWritten;
495 error_GetOverlappedResult:
497 CloseHandle(overlapped.hEvent);
499 SetLastError(dwErrCode);
505 #endif // _WIN32 || _POSIX_C_SOURCE >= 200112L
507 #endif // !LELY_NO_STDIO