3435 {
3436 if (!current)
3437 throwState("no page has been started");
3438 if (disconnected)
3439 throwState("writer is disconnected");
3440 validatePage(*current, *layout);
3441 if (rewriteLastPage) {
3442 const std::filesystem::path temporary(path.string() + ".sddspp.tmp");
3443 if (std::filesystem::exists(temporary))
3444 throwState("temporary rewrite file already exists: " + temporary.string());
3445 try {
3446 Layout outputLayout = *layout;
3447 BufferedStream output(openOutput(temporary,
3448 compressionFor(path, options.compression), "wb",
3449 options.bufferBytes, options.gzipLevel,
3450 options.lzmaPreset, options.lzmaCheck));
3451 writeLayout(output, outputLayout, options);
3452 std::int64_t number = 0;
3453 Reader source = Reader::open(path);
3454 while (number < pageNumber) {
3455 auto page = source.next();
3456 if (!page)
3457 throwState("source file lost a page during atomic last-page update");
3458 writePageData(output, *page, outputLayout, options, ++number);
3459 }
3460 source.close();
3461 writePageData(output, *current, outputLayout, options, ++number);
3462 output.close();
3463#if defined(_WIN32)
3464 lock.reset();
3465#endif
3466 replaceFile(temporary, path);
3467 identity = fileIdentity(path);
3468 if (options.lockMode != LockMode::None)
3469 lock = acquirePathLock(path, options.lockMode, false);
3470 } catch (...) {
3471 std::error_code ignored;
3472 std::filesystem::remove(temporary, ignored);
3473 throw;
3474 }
3475 snapshotWritten = true;
3476 } else {
3477 if (!stream)
3478 throwState("writer has no output stream");
3479 if (snapshotWritten) {
3480 if (!pageStart || !stream->seekable())
3481 throwState("page update requires a seekable, uncompressed output");
3482 stream->seek(*pageStart);
3483 } else {
3484 pageStart = stream->seekable() ? std::optional<std::uint64_t>(stream->tell())
3485 : std::nullopt;
3486 }
3487 writePageData(*stream, *current, *layout, options, pageNumber + 1);
3488 if (snapshotWritten)
3489 stream->truncate(stream->tell());
3490 snapshotWritten = true;
3491 stream->flush();
3492 }
3493 if (!keepOpen) {
3494 ++pageNumber;
3495 current.reset();
3496 pageStart.reset();
3497 snapshotWritten = false;
3498 }
3499 }