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");
124 __frbuf_fini(
struct __frbuf *buf)
129 CloseHandle(buf->hFile);
130 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
142 frbuf_t *buf = __frbuf_alloc();
145 goto error_alloc_buf;
148 if (!__frbuf_init(buf, filename)) {
177 LARGE_INTEGER FileSize;
178 if (!GetFileSizeEx(buf->hFile, &FileSize))
180 return FileSize.QuadPart;
181 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
184 if (fstat64(buf->
fd, &stat) == -1)
188 if (fstat(buf->
fd, &stat) == -1)
193 long offset = ftell(buf->stream);
201 if (fseek(buf->stream, 0, SEEK_END)) {
206 long size = ftell(buf->stream);
209 fseek(buf->stream, offset, SEEK_SET);
222 LARGE_INTEGER li = { .QuadPart = 0 };
223 if (!SetFilePointerEx(buf->hFile, li, &li, FILE_CURRENT))
226 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
228 return lseek64(buf->
fd, 0, SEEK_CUR);
230 return lseek(buf->
fd, 0, SEEK_CUR);
233 long pos = ftell(buf->stream);
251 LARGE_INTEGER li = { .QuadPart = pos };
252 if (!SetFilePointerEx(buf->hFile, li, &li, FILE_BEGIN))
255 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
257 return lseek64(buf->
fd, pos, SEEK_SET);
259 return lseek(buf->
fd, pos, SEEK_SET);
262 if (pos > LONG_MAX) {
266 if (fseek(buf->stream, pos, SEEK_SET)) {
278 assert(ptr || !size);
284 DWORD nNumberOfBytesRead;
285 if (!ReadFile(buf->hFile, ptr, size, &nNumberOfBytesRead, NULL))
287 return nNumberOfBytesRead;
288 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
291 result = read(buf->
fd, ptr, size);
292 while (result == -1 && errno == EINTR);
295 size_t result = fread(ptr, 1, size, buf->stream);
296 if (result != size && ferror(buf->stream)) {
309 assert(ptr || !size);
321 DWORD dwErrCode = GetLastError();
326 dwErrCode = GetLastError();
330 DWORD nNumberOfBytesRead;
331 OVERLAPPED Overlapped = { 0 };
332 ULARGE_INTEGER uli = { .QuadPart = pos };
333 Overlapped.Offset = uli.LowPart;
334 Overlapped.OffsetHigh = uli.HighPart;
336 if (!ReadFile(buf->hFile, ptr, size, &nNumberOfBytesRead,
340 dwErrCode = GetLastError();
344 result = nNumberOfBytesRead;
348 dwErrCode = GetLastError();
350 SetLastError(dwErrCode);
352 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
356 result = pread64(buf->
fd, ptr, size, pos);
359 result = pread(buf->
fd, ptr, size, pos);
361 while (result == -1 && errno == EINTR);
381 if (result == -1 || (
size_t)result != size)
405 if (pos > (intmax_t)size) {
412 size =
MIN((uintmax_t)size, *psize);
417 SYSTEM_INFO SystemInfo;
419 GetSystemInfo(&SystemInfo);
420 DWORD off = pos % SystemInfo.dwAllocationGranularity;
421 if ((uintmax_t)size > (uintmax_t)(SIZE_MAX - off)) {
422 dwErrCode = ERROR_INVALID_PARAMETER;
426 ULARGE_INTEGER MaximumSize = { .QuadPart = pos + size };
427 buf->hFileMappingObject = CreateFileMapping(buf->hFile, NULL,
428 PAGE_READONLY, MaximumSize.HighPart,
429 MaximumSize.LowPart, NULL);
430 if (buf->hFileMappingObject == INVALID_HANDLE_VALUE) {
431 dwErrCode = GetLastError();
432 goto error_CreateFileMapping;
435 ULARGE_INTEGER FileOffset = { .QuadPart = pos - off };
436 buf->lpBaseAddress = MapViewOfFile(buf->hFileMappingObject,
437 FILE_MAP_READ, FileOffset.HighPart, FileOffset.LowPart,
438 (SIZE_T)(off + size));
439 if (!buf->lpBaseAddress) {
440 dwErrCode = GetLastError();
441 goto error_MapViewOfFile;
445 *psize = (size_t)size;
447 return (
char *)buf->lpBaseAddress + off;
450 CloseHandle(buf->hFileMappingObject);
451 buf->hFileMappingObject = INVALID_HANDLE_VALUE;
452 error_CreateFileMapping:
454 SetLastError(dwErrCode);
456 #elif _POSIX_MAPPED_FILES >= 200112L
457 long page_size = sysconf(_SC_PAGE_SIZE);
460 intmax_t off = pos % page_size;
461 if ((uintmax_t)size > (uintmax_t)(SIZE_MAX - off)) {
467 buf->
addr = mmap64(NULL, off + size, PROT_READ, MAP_SHARED, buf->
fd,
471 buf->
addr = mmap(NULL, off + size, PROT_READ, MAP_SHARED, buf->
fd,
474 if (buf->
addr == MAP_FAILED)
476 buf->
len = off + size;
481 return (
char *)buf->
addr + off;
485 buf->map = malloc(size);
488 goto error_malloc_map;
491 ssize_t result =
frbuf_pread(buf, buf->map, size, pos);
520 if (buf->hFileMappingObject != INVALID_HANDLE_VALUE) {
521 DWORD dwErrCode = GetLastError();
522 if (!UnmapViewOfFile(buf->lpBaseAddress)) {
524 dwErrCode = GetLastError();
526 if (!CloseHandle(buf->hFileMappingObject) && !result) {
528 dwErrCode = GetLastError();
530 SetLastError(dwErrCode);
532 buf->hFileMappingObject = INVALID_HANDLE_VALUE;
533 buf->lpBaseAddress = NULL;
535 #elif _POSIX_MAPPED_FILES >= 200112L
536 if (buf->
addr != MAP_FAILED) {
537 result = munmap(buf->
addr, buf->
len);
539 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.
frbuf_t * frbuf_create(const char *filename)
Creates a new read file buffer.
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...
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.
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.
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.