30 static void write(
const std::filesystem::path& path,
31 std::uint64_t partition_id,
32 const std::vector<std::uint8_t>& payload) {
33 std::ofstream out(path, std::ios::binary | std::ios::trunc);
34 if (!out)
throw std::runtime_error(
"failed to open partition file for write");
37 header.
payload_bytes =
static_cast<std::uint64_t
>(payload.size());
38 out.write(
reinterpret_cast<const char*
>(&header),
sizeof(header));
39 if (!payload.empty()) {
40 out.write(
reinterpret_cast<const char*
>(payload.data()),
41 static_cast<std::streamsize
>(payload.size()));
43 if (!out)
throw std::runtime_error(
"failed to write partition file");
46 static std::vector<std::uint8_t>
read(
const std::filesystem::path& path,
47 std::uint64_t expected_partition_id) {
48 std::ifstream in(path, std::ios::binary);
49 if (!in)
throw std::runtime_error(
"failed to open partition file for read");
51 in.read(
reinterpret_cast<char*
>(&header),
sizeof(header));
52 validate_header(header, expected_partition_id);
53 std::vector<std::uint8_t> payload(
static_cast<std::size_t
>(header.payload_bytes));
54 if (!payload.empty()) in.read(
reinterpret_cast<char*
>(payload.data()),
static_cast<std::streamsize
>(payload.size()));
55 if (!in)
throw std::runtime_error(
"truncated partition payload");
60 const std::filesystem::path& path,
61 std::uint64_t expected_partition_id,
62 bool* used_mmap =
nullptr) {
63 if (used_mmap) *used_mmap =
false;
64#if defined(__linux__) || defined(__APPLE__)
65 const int fd = ::open(path.c_str(), O_RDONLY);
68 if (::fstat(fd, &st) == 0 && st.st_size >=
static_cast<off_t
>(
sizeof(
PartitionFileHeader))) {
69 void* addr = ::mmap(
nullptr,
static_cast<std::size_t
>(st.st_size), PROT_READ, MAP_PRIVATE, fd, 0);
70 if (addr != MAP_FAILED) {
72 std::memcpy(&header, addr,
sizeof(header));
74 validate_header(header, expected_partition_id);
75 const auto total =
sizeof(
PartitionFileHeader) +
static_cast<std::size_t
>(header.payload_bytes);
76 if (total >
static_cast<std::size_t
>(st.st_size)) {
77 throw std::runtime_error(
"truncated mmap partition payload");
80 std::vector<std::uint8_t> payload(begin, begin +
static_cast<std::size_t
>(header.payload_bytes));
81 ::munmap(addr,
static_cast<std::size_t
>(st.st_size));
83 if (used_mmap) *used_mmap =
true;
86 ::munmap(addr,
static_cast<std::size_t
>(st.st_size));
95 return read(path, expected_partition_id);