| 1433 | // |
| 1434 | |
| 1435 | Status MemoryMapRemap(void* addr, size_t old_size, size_t new_size, int fildes, |
| 1436 | void** new_addr) { |
| 1437 | // should only be called with writable files |
| 1438 | *new_addr = MAP_FAILED; |
| 1439 | #ifdef _WIN32 |
| 1440 | // flags are ignored on windows |
| 1441 | HANDLE fm, h; |
| 1442 | |
| 1443 | if (!UnmapViewOfFile(addr)) { |
| 1444 | return StatusFromMmapErrno("UnmapViewOfFile failed"); |
| 1445 | } |
| 1446 | |
| 1447 | h = reinterpret_cast<HANDLE>(_get_osfhandle(fildes)); |
| 1448 | if (h == INVALID_HANDLE_VALUE) { |
| 1449 | return StatusFromMmapErrno("Cannot get file handle"); |
| 1450 | } |
| 1451 | |
| 1452 | uint64_t new_size64 = new_size; |
| 1453 | LONG new_size_low = static_cast<LONG>(new_size64 & 0xFFFFFFFFUL); |
| 1454 | LONG new_size_high = static_cast<LONG>((new_size64 >> 32) & 0xFFFFFFFFUL); |
| 1455 | |
| 1456 | SetFilePointer(h, new_size_low, &new_size_high, FILE_BEGIN); |
| 1457 | SetEndOfFile(h); |
| 1458 | fm = CreateFileMappingW(h, NULL, PAGE_READWRITE, 0, 0, L""); |
| 1459 | if (fm == NULL) { |
| 1460 | return StatusFromMmapErrno("CreateFileMapping failed"); |
| 1461 | } |
| 1462 | *new_addr = MapViewOfFile(fm, FILE_MAP_WRITE, 0, 0, new_size); |
| 1463 | CloseHandle(fm); |
| 1464 | if (new_addr == NULL) { |
| 1465 | return StatusFromMmapErrno("MapViewOfFile failed"); |
| 1466 | } |
| 1467 | return Status::OK(); |
| 1468 | #elif defined(__linux__) |
| 1469 | if (ftruncate(fildes, new_size) == -1) { |
| 1470 | return StatusFromMmapErrno("ftruncate failed"); |
| 1471 | } |
| 1472 | *new_addr = mremap(addr, old_size, new_size, MREMAP_MAYMOVE); |
| 1473 | if (*new_addr == MAP_FAILED) { |
| 1474 | return StatusFromMmapErrno("mremap failed"); |
| 1475 | } |
| 1476 | return Status::OK(); |
| 1477 | #else |
| 1478 | // we have to close the mmap first, truncate the file to the new size |
| 1479 | // and recreate the mmap |
| 1480 | if (munmap(addr, old_size) == -1) { |
| 1481 | return StatusFromMmapErrno("munmap failed"); |
| 1482 | } |
| 1483 | if (ftruncate(fildes, new_size) == -1) { |
| 1484 | return StatusFromMmapErrno("ftruncate failed"); |
| 1485 | } |
| 1486 | // we set READ / WRITE flags on the new map, since we could only have |
| 1487 | // enlarged a RW map in the first place |
| 1488 | *new_addr = mmap(NULL, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fildes, 0); |
| 1489 | if (*new_addr == MAP_FAILED) { |
| 1490 | return StatusFromMmapErrno("mmap failed"); |
| 1491 | } |
| 1492 | return Status::OK(); |
no test coverage detected