27 #define _LARGEFILE64_SOURCE 1
39 #if _POSIX_C_SOURCE >= 200112L
41 #if _POSIX_MAPPED_FILES >= 200112L
54 HANDLE hFileMappingObject;
57 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
75 void *ptr = malloc(
sizeof(
struct __frbuf));
82 __frbuf_free(
void *ptr)
88 __frbuf_init(
struct __frbuf *buf,
const char *filename)
94 buf->hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
96 FILE_ATTRIBUTE_READONLY | FILE_FLAG_NO_BUFFERING, NULL);
97 if (buf->hFile == INVALID_HANDLE_VALUE)
100 buf->hFileMappingObject = INVALID_HANDLE_VALUE;
101 buf->lpBaseAddress = NULL;
102 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
103 buf->
fd = open(filename, O_RDONLY | O_CLOEXEC);
107 buf->
addr = MAP_FAILED;
110 buf->stream = fopen(filename,
"rb");
119 __frbuf_fini(
struct __frbuf *buf)
124 CloseHandle(buf->hFile);
125 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
137 frbuf_t *buf = __frbuf_alloc();
140 goto error_alloc_buf;
143 if (!__frbuf_init(buf, filename)) {
172 LARGE_INTEGER FileSize;
173 if (!GetFileSizeEx(buf->hFile, &FileSize))
175 return FileSize.QuadPart;
176 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
179 if (fstat64(buf->
fd, &stat) == -1)
183 if (fstat(buf->
fd, &stat) == -1)
188 long offset = ftell(buf->stream);
196 if (fseek(buf->stream, 0, SEEK_END)) {
201 long size = ftell(buf->stream);
204 fseek(buf->stream, offset, SEEK_SET);
217 LARGE_INTEGER li = { .QuadPart = 0 };
218 if (!SetFilePointerEx(buf->hFile, li, &li, FILE_CURRENT))
221 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
223 return lseek64(buf->
fd, 0, SEEK_CUR);
225 return lseek(buf->
fd, 0, SEEK_CUR);
228 long pos = ftell(buf->stream);
246 LARGE_INTEGER li = { .QuadPart = pos };
247 if (!SetFilePointerEx(buf->hFile, li, &li, FILE_BEGIN))
250 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
252 return lseek64(buf->
fd, pos, SEEK_SET);
254 return lseek(buf->
fd, pos, SEEK_SET);
257 if (pos > LONG_MAX) {
261 if (fseek(buf->stream, pos, SEEK_SET)) {
273 assert(ptr || !size);
279 DWORD nNumberOfBytesRead;
280 if (!ReadFile(buf->hFile, ptr, size, &nNumberOfBytesRead, NULL))
282 return nNumberOfBytesRead;
283 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
286 result = read(buf->
fd, ptr, size);
287 while (result == -1 && errno == EINTR);
290 size_t result = fread(ptr, 1, size, buf->stream);
291 if (result != size && ferror(buf->stream)) {
304 assert(ptr || !size);
316 DWORD dwErrCode = GetLastError();
321 dwErrCode = GetLastError();
325 DWORD nNumberOfBytesRead;
326 OVERLAPPED Overlapped = { 0 };
327 ULARGE_INTEGER uli = { .QuadPart = pos };
328 Overlapped.Offset = uli.LowPart;
329 Overlapped.OffsetHigh = uli.HighPart;
331 if (!ReadFile(buf->hFile, ptr, size, &nNumberOfBytesRead,
335 dwErrCode = GetLastError();
339 result = nNumberOfBytesRead;
343 dwErrCode = GetLastError();
345 SetLastError(dwErrCode);
347 #elif _POSIX_C_SOURCE >= 200112L && !defined(__NEWLIB__)
351 result = pread64(buf->
fd, ptr, size, pos);
354 result = pread(buf->
fd, ptr, size, pos);
356 while (result == -1 && errno == EINTR);
376 if (result == -1 || (
size_t)result != size)
400 if (pos > (intmax_t)size) {
407 size =
MIN((uintmax_t)size, *psize);
412 SYSTEM_INFO SystemInfo;
413 GetSystemInfo(&SystemInfo);
414 DWORD off = pos % SystemInfo.dwAllocationGranularity;
415 if ((uintmax_t)size > (uintmax_t)(SIZE_MAX - off)) {
416 dwErrCode = ERROR_INVALID_PARAMETER;
420 ULARGE_INTEGER MaximumSize = { .QuadPart = pos + size };
421 buf->hFileMappingObject = CreateFileMapping(buf->hFile, NULL,
422 PAGE_READONLY, MaximumSize.HighPart,
423 MaximumSize.LowPart, NULL);
424 if (buf->hFileMappingObject == INVALID_HANDLE_VALUE) {
425 dwErrCode = GetLastError();
426 goto error_CreateFileMapping;
429 ULARGE_INTEGER FileOffset = { .QuadPart = pos - off };
430 buf->lpBaseAddress = MapViewOfFile(buf->hFileMappingObject,
431 FILE_MAP_READ, FileOffset.HighPart, FileOffset.LowPart,
432 (SIZE_T)(off + size));
433 if (!buf->lpBaseAddress) {
434 dwErrCode = GetLastError();
435 goto error_MapViewOfFile;
439 *psize = (size_t)size;
441 return (
char *)buf->lpBaseAddress + off;
444 CloseHandle(buf->hFileMappingObject);
445 buf->hFileMappingObject = INVALID_HANDLE_VALUE;
446 error_CreateFileMapping:
448 SetLastError(dwErrCode);
450 #elif _POSIX_MAPPED_FILES >= 200112L
451 long page_size = sysconf(_SC_PAGE_SIZE);
454 intmax_t off = pos % page_size;
455 if ((uintmax_t)size > (uintmax_t)(SIZE_MAX - off)) {
461 buf->
addr = mmap64(NULL, off + size, PROT_READ, MAP_SHARED, buf->
fd,
465 buf->
addr = mmap(NULL, off + size, PROT_READ, MAP_SHARED, buf->
fd,
468 if (buf->
addr == MAP_FAILED)
470 buf->
len = off + size;
475 return (
char *)buf->
addr + off;
479 buf->map = malloc(size);
482 goto error_malloc_map;
485 ssize_t result =
frbuf_pread(buf, buf->map, size, pos);
514 if (buf->hFileMappingObject != INVALID_HANDLE_VALUE) {
515 DWORD dwErrCode = GetLastError();
516 if (!UnmapViewOfFile(buf->lpBaseAddress)) {
518 dwErrCode = GetLastError();
520 if (!CloseHandle(buf->hFileMappingObject) && !result) {
522 dwErrCode = GetLastError();
524 SetLastError(dwErrCode);
526 buf->hFileMappingObject = INVALID_HANDLE_VALUE;
527 buf->lpBaseAddress = NULL;
529 #elif _POSIX_MAPPED_FILES >= 200112L
530 if (buf->
addr != MAP_FAILED) {
531 result = munmap(buf->
addr, buf->
len);
533 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.