|
24 | 24 | #include <stdio.h>
|
25 | 25 | #include <stdlib.h>
|
26 | 26 | #include <string.h>
|
| 27 | +#ifndef _WIN32 |
27 | 28 | #include <sys/mman.h>
|
| 29 | +#endif |
28 | 30 | #include <sys/stat.h>
|
29 | 31 | #include <unistd.h>
|
30 | 32 |
|
@@ -346,6 +348,7 @@ LY_VCODE_INSTREXP_len(const char *str)
|
346 | 348 | return len;
|
347 | 349 | }
|
348 | 350 |
|
| 351 | +#ifdef HAVE_MMAP |
349 | 352 | LY_ERR
|
350 | 353 | ly_mmap(struct ly_ctx *ctx, int fd, size_t *length, void **addr)
|
351 | 354 | {
|
@@ -404,6 +407,71 @@ ly_munmap(void *addr, size_t length)
|
404 | 407 | return LY_SUCCESS;
|
405 | 408 | }
|
406 | 409 |
|
| 410 | +#else |
| 411 | + |
| 412 | +LY_ERR |
| 413 | +ly_mmap(struct ly_ctx *ctx, int fd, size_t *length, void **addr) |
| 414 | +{ |
| 415 | + struct stat sb; |
| 416 | + size_t m; |
| 417 | + |
| 418 | + assert(length); |
| 419 | + assert(addr); |
| 420 | + assert(fd >= 0); |
| 421 | + |
| 422 | + if (fstat(fd, &sb) == -1) { |
| 423 | + LOGERR(ctx, LY_ESYS, "Failed to stat the file descriptor (%s) for the mmap().", strerror(errno)); |
| 424 | + return LY_ESYS; |
| 425 | + } |
| 426 | + if (!S_ISREG(sb.st_mode)) { |
| 427 | + LOGERR(ctx, LY_EINVAL, "File to mmap() is not a regular file."); |
| 428 | + return LY_ESYS; |
| 429 | + } |
| 430 | + if (!sb.st_size) { |
| 431 | + *addr = NULL; |
| 432 | + return LY_SUCCESS; |
| 433 | + } |
| 434 | + /* On Windows, the mman-win32 mmap() emulation uses CreateFileMapping and MapViewOfFile, and these functions |
| 435 | + * do not allow mapping more than "length of file" bytes for PROT_READ. Remapping existing mappings is not allowed, either. |
| 436 | + * At that point the path of least resistance is just reading the file in as-is. */ |
| 437 | + m = sb.st_size + 1; |
| 438 | + char *buf = calloc(m, 1); |
| 439 | + |
| 440 | + if (!buf) { |
| 441 | + LOGERR(ctx, LY_ESYS, "ly_mmap: malloc() failed (%s).", strerror(errno)); |
| 442 | + } |
| 443 | + *addr = buf; |
| 444 | + *length = m; |
| 445 | + |
| 446 | + lseek(fd, 0, SEEK_SET); |
| 447 | + ssize_t to_read = m - 1; |
| 448 | + |
| 449 | + while (to_read > 0) { |
| 450 | + ssize_t n = read(fd, buf, to_read); |
| 451 | + if (n == 0) { |
| 452 | + return LY_SUCCESS; |
| 453 | + } else if (n < 0) { |
| 454 | + if (errno == EINTR) { |
| 455 | + continue; // can I get this on Windows? |
| 456 | + } |
| 457 | + LOGERR(ctx, LY_ESYS, "ly_mmap: read() failed (%s).", strerror(errno)); |
| 458 | + } |
| 459 | + to_read -= n; |
| 460 | + buf += n; |
| 461 | + } |
| 462 | + return LY_SUCCESS; |
| 463 | +} |
| 464 | + |
| 465 | +LY_ERR |
| 466 | +ly_munmap(void *addr, size_t length) |
| 467 | +{ |
| 468 | + (void)length; |
| 469 | + free(addr); |
| 470 | + return LY_SUCCESS; |
| 471 | +} |
| 472 | + |
| 473 | +#endif |
| 474 | + |
407 | 475 | LY_ERR
|
408 | 476 | ly_strcat(char **dest, const char *format, ...)
|
409 | 477 | {
|
|
0 commit comments