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;
553 #endif // !LELY_NO_STDIO