27#define _LARGEFILE64_SOURCE 1
42#if _POSIX_C_SOURCE >= 200112L
44#if _POSIX_MAPPED_FILES >= 200112L
57 HANDLE hFileMappingObject;
60#elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
78 void *ptr = malloc(
sizeof(
struct __frbuf));
85__frbuf_free(
void *ptr)
91__frbuf_init(
struct __frbuf *buf,
const char *filename)
97 buf->hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
99 FILE_ATTRIBUTE_READONLY | FILE_FLAG_NO_BUFFERING, NULL);
100 if (buf->hFile == INVALID_HANDLE_VALUE)
103 buf->hFileMappingObject = INVALID_HANDLE_VALUE;
104 buf->lpBaseAddress = NULL;
105#elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
106 buf->
fd = open(filename, O_RDONLY | O_CLOEXEC);
110 buf->
addr = MAP_FAILED;
113 buf->stream = fopen(filename,
"rb");
122__frbuf_fini(
struct __frbuf *buf)
127 CloseHandle(buf->hFile);
128#elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
140 frbuf_t *buf = __frbuf_alloc();
143 goto error_alloc_buf;
146 if (!__frbuf_init(buf, filename)) {
175 LARGE_INTEGER FileSize;
176 if (!GetFileSizeEx(buf->hFile, &FileSize))
178 return FileSize.QuadPart;
179#elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
182 if (fstat64(buf->
fd, &stat) == -1)
186 if (fstat(buf->
fd, &stat) == -1)
191 long offset = ftell(buf->stream);
199 if (fseek(buf->stream, 0, SEEK_END)) {
204 long size = ftell(buf->stream);
207 fseek(buf->stream, offset, SEEK_SET);
220 LARGE_INTEGER li = { .QuadPart = 0 };
221 if (!SetFilePointerEx(buf->hFile, li, &li, FILE_CURRENT))
224#elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
226 return lseek64(buf->
fd, 0, SEEK_CUR);
228 return lseek(buf->
fd, 0, SEEK_CUR);
231 long pos = ftell(buf->stream);
249 LARGE_INTEGER li = { .QuadPart = pos };
250 if (!SetFilePointerEx(buf->hFile, li, &li, FILE_BEGIN))
253#elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
255 return lseek64(buf->
fd, pos, SEEK_SET);
257 return lseek(buf->
fd, pos, SEEK_SET);
260 if (pos > LONG_MAX) {
264 if (fseek(buf->stream, pos, SEEK_SET)) {
276 assert(ptr || !size);
282 DWORD nNumberOfBytesRead;
283 if (!ReadFile(buf->hFile, ptr, size, &nNumberOfBytesRead, NULL))
285 return nNumberOfBytesRead;
286#elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
289 result = read(buf->
fd, ptr, size);
290 while (result == -1 && errno == EINTR);
293 size_t result = fread(ptr, 1, size, buf->stream);
294 if (result != size && ferror(buf->stream)) {
307 assert(ptr || !size);
319 DWORD dwErrCode = GetLastError();
324 dwErrCode = GetLastError();
328 DWORD nNumberOfBytesRead;
329 OVERLAPPED Overlapped = { 0 };
330 ULARGE_INTEGER uli = { .QuadPart = pos };
331 Overlapped.Offset = uli.LowPart;
332 Overlapped.OffsetHigh = uli.HighPart;
334 if (!ReadFile(buf->hFile, ptr, size, &nNumberOfBytesRead,
338 dwErrCode = GetLastError();
342 result = nNumberOfBytesRead;
346 dwErrCode = GetLastError();
348 SetLastError(dwErrCode);
350#elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
354 result = pread64(buf->
fd, ptr, size, pos);
357 result = pread(buf->
fd, ptr, size, pos);
359 while (result == -1 && errno == EINTR);
379 if (result == -1 || (
size_t)result != size)
403 if (pos > (intmax_t)size) {
410 size =
MIN((uintmax_t)size, *psize);
415 SYSTEM_INFO SystemInfo;
417 GetSystemInfo(&SystemInfo);
418 DWORD off = pos % SystemInfo.dwAllocationGranularity;
419 if ((uintmax_t)size > (uintmax_t)(SIZE_MAX - off)) {
420 dwErrCode = ERROR_INVALID_PARAMETER;
424 ULARGE_INTEGER MaximumSize = { .QuadPart = pos + size };
425 buf->hFileMappingObject = CreateFileMapping(buf->hFile, NULL,
426 PAGE_READONLY, MaximumSize.HighPart,
427 MaximumSize.LowPart, NULL);
428 if (buf->hFileMappingObject == INVALID_HANDLE_VALUE) {
429 dwErrCode = GetLastError();
430 goto error_CreateFileMapping;
433 ULARGE_INTEGER FileOffset = { .QuadPart = pos - off };
434 buf->lpBaseAddress = MapViewOfFile(buf->hFileMappingObject,
435 FILE_MAP_READ, FileOffset.HighPart, FileOffset.LowPart,
436 (SIZE_T)(off + size));
437 if (!buf->lpBaseAddress) {
438 dwErrCode = GetLastError();
439 goto error_MapViewOfFile;
443 *psize = (size_t)size;
445 return (
char *)buf->lpBaseAddress + off;
448 CloseHandle(buf->hFileMappingObject);
449 buf->hFileMappingObject = INVALID_HANDLE_VALUE;
450error_CreateFileMapping:
452 SetLastError(dwErrCode);
454#elif _POSIX_MAPPED_FILES >= 200112L
455 long page_size = sysconf(_SC_PAGE_SIZE);
458 intmax_t off = pos % page_size;
459 if ((uintmax_t)size > (uintmax_t)(SIZE_MAX - off)) {
465 buf->
addr = mmap64(NULL, off + size, PROT_READ, MAP_SHARED, buf->
fd,
469 buf->
addr = mmap(NULL, off + size, PROT_READ, MAP_SHARED, buf->
fd,
472 if (buf->
addr == MAP_FAILED)
474 buf->
len = off + size;
479 return (
char *)buf->
addr + off;
483 buf->map = malloc(size);
486 goto error_malloc_map;
518 if (buf->hFileMappingObject != INVALID_HANDLE_VALUE) {
519 DWORD dwErrCode = GetLastError();
520 if (!UnmapViewOfFile(buf->lpBaseAddress)) {
522 dwErrCode = GetLastError();
524 if (!CloseHandle(buf->hFileMappingObject) && !result) {
526 dwErrCode = GetLastError();
528 SetLastError(dwErrCode);
530 buf->hFileMappingObject = INVALID_HANDLE_VALUE;
531 buf->lpBaseAddress = NULL;
533#elif _POSIX_MAPPED_FILES >= 200112L
534 if (buf->
addr != MAP_FAILED) {
535 result = munmap(buf->
addr, buf->
len);
537 buf->
addr = MAP_FAILED;
This header file is part of the utilities library; it contains the native and platform-independent er...
@ ERRNUM_INVAL
Invalid argument.
@ ERRNUM_OVERFLOW
Value too large to be stored in data type.
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.
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
int frbuf_unmap(frbuf_t *buf)
Unmaps the current memory map of a read file buffer, if it exists.
intmax_t frbuf_get_size(frbuf_t *buf)
Returns the size (in bytes) of the a read file buffer, or -1 on error.
const void * frbuf_map(frbuf_t *buf, intmax_t pos, size_t *psize)
Maps (part of) the contents of a read file buffer to memory.
intmax_t frbuf_set_pos(frbuf_t *buf, intmax_t pos)
Sets the current offset (in bytes) of a read file buffer with respect to the beginning of the file.
void frbuf_destroy(frbuf_t *buf)
Destroys a read file buffer.
intmax_t frbuf_get_pos(frbuf_t *buf)
Returns the current offset (in bytes) of a read file buffer with respect to the beginning of the file...
ssize_t frbuf_pread(frbuf_t *buf, void *ptr, size_t size, intmax_t pos)
Reads bytes from the specified position in a read file buffer.
frbuf_t * frbuf_create(const char *filename)
Creates a new read file buffer.
ssize_t frbuf_read(frbuf_t *buf, void *ptr, size_t size)
Reads bytes from the current position in a read file buffer.
This header file is part of the utilities library; it contains the read file buffer declarations.
#define MIN(a, b)
Returns the minimum of a and b.
This is the internal header file of the utilities library.
This header file is part of the C11 and POSIX compatibility library; it includes <stdio....
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
An read file buffer struct.
int fd
The file descriptor.
void * addr
The base address of the current file mapping.
size_t len
The length (in bytes) of the mapping at addr.
ptrdiff_t ssize_t
Used for a count of bytes or an error indication.