27#define _LARGEFILE64_SOURCE 1
40#if _WIN32 || _POSIX_C_SOURCE >= 200112L
56 struct io_handle *handle,
const void *buf,
size_t nbytes);
57static int file_flush(
struct io_handle *handle);
65 .size =
sizeof(
struct file),
66 .fini = &default_fini,
71 .pwrite = &file_pwrite };
98 flags &= ~IO_FILE_TRUNCATE;
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;
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
238file_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);
259file_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);
369file_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;
442error_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;
495error_GetOverlappedResult:
497 CloseHandle(overlapped.hEvent);
499 SetLastError(dwErrCode);
This is the internal header file of the default implementation of the I/O device handle methods.
int errnum2c(errnum_t errnum)
Transforms a platform-independent error number to a native error code.
@ ERRNUM_SPIPE
Invalid seek.
@ ERRNUM_BADF
Bad file descriptor.
@ ERRNUM_INVAL
Invalid argument.
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
ssize_t io_pwrite(io_handle_t handle, const void *buf, size_t nbytes, io_off_t offset)
Performs a write operation at the specified offset, without updating the file pointer.
io_off_t io_seek(io_handle_t handle, io_off_t offset, int whence)
Moves the current read/write offset of an open file.
ssize_t io_pread(io_handle_t handle, void *buf, size_t nbytes, io_off_t offset)
Performs a read operation at the specified offset, without updating the file pointer.
io_handle_t io_open_file(const char *path, int flags)
Opens a regular file.
This header file is part of the I/O library; it contains the regular file declarations.
@ IO_FILE_READ
Open a file for reading.
@ IO_FILE_CREATE
Create a new file if it does not exists.
@ IO_FILE_APPEND
Append data to the end of the file.
@ IO_FILE_TRUNCATE
Truncate an existing file (ignored if IO_FILE_NO_EXIST is set).
@ IO_FILE_NO_EXIST
Fail if the file already exists (ignored unless IO_FILE_CREATE is set).
@ IO_FILE_WRITE
Open a file for writing.
@ IO_SEEK_CURRENT
A seek operation with respect to the current offset in a file.
@ IO_SEEK_BEGIN
A seek operation with respect to the beginning of a file.
@ IO_SEEK_END
A seek operation with respect to the end of a file.
struct io_handle * io_handle_alloc(const struct io_handle_vtab *vtab)
Allocates a new I/O device handle from a virtual table.
int64_t io_off_t
A file offset type.
@ IO_TYPE_FILE
A regular file.
io_handle_t io_handle_acquire(io_handle_t handle)
Increments the reference count of an I/O device handle.
#define IO_HANDLE_ERROR
The value of an invalid I/O device handle.
This is the internal header file of the Windows-specific I/O declarations.
struct io_handle base
The I/O device base handle.
int flags
The file flags (any combination of IO_FILE_READ, IO_FILE_WRITE, IO_FILE_APPEND, IO_FILE_CREATE,...
The virtual table of an I/O device handle.
ssize_t(* pread)(struct io_handle *handle, void *buf, size_t nbytes, io_off_t offset)
A pointer to the pread method.
int type
The type of the device (one of IO_TYPE_CAN, IO_TYPE_FILE, IO_TYPE_PIPE, IO_TYPE_SERIAL or IO_TYPE_SOC...
io_off_t(* seek)(struct io_handle *handle, io_off_t offset, int whence)
A pointer to the seek method.
ssize_t(* pwrite)(struct io_handle *handle, const void *buf, size_t nbytes, io_off_t offset)
A pointer to the pwrite method.
int fd
The native file descriptor.
const struct io_handle_vtab * vtab
A pointer to the virtual table.
ptrdiff_t ssize_t
Used for a count of bytes or an error indication.