| 662 | } |
| 663 | |
| 664 | bool mmapEntryByDataOffset(const std::string &zipPath, uint64_t dataOffset, ZipEntryMMap *out) |
| 665 | { |
| 666 | if (out) |
| 667 | *out = {}; |
| 668 | |
| 669 | ZipEntryInfo ent{}; |
| 670 | if (!findEntryInfoByDataOffset(zipPath, dataOffset, &ent)) |
| 671 | return false; |
| 672 | |
| 673 | uint64_t compressedSize = ent.compressedSize; |
| 674 | |
| 675 | int fd = KT_EINTR_RETRY(open(zipPath.c_str(), O_RDONLY)); |
| 676 | if (fd < 0) |
| 677 | return false; |
| 678 | |
| 679 | struct stat st{}; |
| 680 | if (fstat(fd, &st) < 0) |
| 681 | { |
| 682 | KT_EINTR_RETRY(close(fd)); |
| 683 | return false; |
| 684 | } |
| 685 | |
| 686 | uint64_t fileSize = st.st_size; |
| 687 | |
| 688 | if (dataOffset >= fileSize || dataOffset + compressedSize > fileSize) |
| 689 | { |
| 690 | KT_EINTR_RETRY(close(fd)); |
| 691 | return false; |
| 692 | } |
| 693 | |
| 694 | const size_t pageSize = sysconf(_SC_PAGE_SIZE); |
| 695 | uint64_t alignedOffset = dataOffset & ~(uint64_t(pageSize - 1)); |
| 696 | uint64_t offsetDiff = dataOffset - alignedOffset; |
| 697 | uint64_t mapSize = offsetDiff + compressedSize; |
| 698 | |
| 699 | void *map = mmap(nullptr, mapSize, PROT_READ, MAP_PRIVATE, fd, alignedOffset); |
| 700 | |
| 701 | KT_EINTR_RETRY(close(fd)); |
| 702 | |
| 703 | if (!map || map == MAP_FAILED) |
| 704 | return false; |
| 705 | |
| 706 | if (out) |
| 707 | { |
| 708 | out->mappingBase = map; |
| 709 | out->mappingSize = mapSize; |
| 710 | out->data = static_cast<uint8_t *>(map) + offsetDiff; |
| 711 | out->size = compressedSize; |
| 712 | } |
| 713 | |
| 714 | return true; |
| 715 | } |
| 716 | } // namespace Zip |
| 717 | |
| 718 | } // namespace KittyUtils |
no test coverage detected