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;
102 }
else if (flags & IO_FILE_WRITE) {
103 dwDesiredAccess |= FILE_WRITE_DATA;
107 DWORD dwCreationDisposition
113 : (flags & IO_FILE_TRUNCATE) ? TRUNCATE_EXISTING
117 HANDLE fd = CreateFileA(path, dwDesiredAccess, 0, NULL,
118 dwCreationDisposition, FILE_FLAG_OVERLAPPED, NULL);
121 int oflag = (flags &
IO_FILE_READ) && (flags & IO_FILE_WRITE) ? O_RDWR
123 : (flags & IO_FILE_WRITE) ? O_WRONLY
126 if (flags & IO_FILE_APPEND)
128 if (flags & IO_FILE_CREATE) {
130 if (flags & IO_FILE_NO_EXIST)
133 if (flags & IO_FILE_TRUNCATE)
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 int errnum2c(errnum_t errnum)
Transforms a platform-independent error number to a native error code.
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
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.
This is the internal header file of the default implementation of the I/O device handle methods...
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...
This header file is part of the I/O library; it contains the regular file declarations.
Append data to the end of the file.
A seek operation with respect to the current offset in a file.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Create a new file if it does not exists.
io_handle_t io_handle_acquire(io_handle_t handle)
Increments the reference count of an I/O device handle.
Truncate an existing file (ignored if IO_FILE_NO_EXIST is set).
Fail if the file already exists (ignored unless IO_FILE_CREATE is set).
A seek operation with respect to the beginning of a 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.
#define IO_HANDLE_ERROR
The value of an invalid I/O device handle.
const struct io_handle_vtab * vtab
A pointer to the virtual table.
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
The virtual table of an I/O device handle.
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.
A seek operation with respect to the end of a file.
ssize_t(* pread)(struct io_handle *handle, void *buf, size_t nbytes, io_off_t offset)
A pointer to the pread method.
This is the internal header file of the I/O library.
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, IO_FILE_NO_EXIST and IO_FILE_TRUNCATE).
int64_t io_off_t
A file offset type.
int fd
The native file descriptor.
io_handle_t io_open_file(const char *path, int flags)
Opens a regular file.
io_off_t(* seek)(struct io_handle *handle, io_off_t offset, int whence)
A pointer to the seek method.
struct io_handle * io_handle_alloc(const struct io_handle_vtab *vtab)
Allocates a new I/O device handle from a virtual table.
ssize_t(* pwrite)(struct io_handle *handle, const void *buf, size_t nbytes, io_off_t offset)
A pointer to the pwrite method.