Write a memory area into the savestate. Returns the size of the area in bytes */
| 1609 | |
| 1610 | /* Write a memory area into the savestate. Returns the size of the area in bytes */ |
| 1611 | static size_t writeSaveFiles(SaveStateSaving &state) |
| 1612 | { |
| 1613 | size_t total_size = 0; |
| 1614 | |
| 1615 | for (auto it = SaveFileList::begin(); it != SaveFileList::end(); it++) { |
| 1616 | const std::unique_ptr<SaveFile>& savefile = *it; |
| 1617 | /* Don't map if file was closed and removed (TODO: handle this!) */ |
| 1618 | if (savefile->fd == 0) |
| 1619 | continue; |
| 1620 | |
| 1621 | /* Also, skip if we are handling the savefile using our custom |
| 1622 | * stream (SaveFileStream), which maps its content in memory. So, it |
| 1623 | * is already saved through the memory dumping process. */ |
| 1624 | if (savefile->fd >= FIRST_SAVEFILE_STREAM_FD) |
| 1625 | continue; |
| 1626 | |
| 1627 | Area area; |
| 1628 | area.flags = Area::AREA_SAVEFILE; |
| 1629 | area.fd = savefile->fd; |
| 1630 | strncpy(area.name, savefile->filename.c_str(), Area::FILENAMESIZE-1); |
| 1631 | |
| 1632 | /* Get current file length and map at least this amount of bytes */ |
| 1633 | struct stat filestat; |
| 1634 | int rv = fstat(area.fd, &filestat); |
| 1635 | |
| 1636 | if (rv < 0) |
| 1637 | continue; |
| 1638 | |
| 1639 | area.size = filestat.st_size; |
| 1640 | |
| 1641 | if (area.size == 0) { |
| 1642 | LOG(LL_DEBUG, LCF_CHECKPOINT | LCF_FILEIO, " Don't map empty/missing file %s with fd %d", savefile->filename.c_str(), savefile->fd); |
| 1643 | continue; |
| 1644 | } |
| 1645 | |
| 1646 | area.addr = mmap(nullptr, area.size, PROT_READ, MAP_PRIVATE | MAP_FILE, savefile->fd, 0); |
| 1647 | |
| 1648 | if (area.addr == MAP_FAILED) { |
| 1649 | LOG(LL_DEBUG, LCF_CHECKPOINT | LCF_FILEIO, " Cound not map file %s with fd %d and size %zu", savefile->filename.c_str(), savefile->fd, area.size); |
| 1650 | continue; |
| 1651 | } |
| 1652 | |
| 1653 | LOG(LL_DEBUG, LCF_CHECKPOINT | LCF_FILEIO, "Save savefile %s with fd %d and size %zu", savefile->filename.c_str(), savefile->fd, area.size); |
| 1654 | |
| 1655 | /* Map the original file */ |
| 1656 | int orig_fd = -1; |
| 1657 | size_t orig_file_mapped_size = 0; |
| 1658 | void* orig_file_mapped_addr = MAP_FAILED; |
| 1659 | |
| 1660 | rv = stat(savefile->filename.c_str(), &filestat); |
| 1661 | |
| 1662 | if (rv < 0) |
| 1663 | LOG(LL_DEBUG, LCF_CHECKPOINT | LCF_FILEIO, " No original savefile to use"); |
| 1664 | else if (! S_ISREG(filestat.st_mode) || (filestat.st_size == 0)) |
| 1665 | LOG(LL_DEBUG, LCF_CHECKPOINT | LCF_FILEIO, " Original file is missing or not regular, skip it"); |
| 1666 | else { |
| 1667 | orig_fd = open(savefile->filename.c_str(), O_RDONLY); |
| 1668 |
no test coverage detected