diff options
| author | Dan Engelbrecht <[email protected]> | 2024-03-13 10:33:40 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2024-03-13 10:33:40 +0100 |
| commit | 5fd1bdfafcd1e44162a1a4a978de775660c378a6 (patch) | |
| tree | b92b9cc595477075bd02320d0948c2f11e0c0717 /src | |
| parent | updates to signing (diff) | |
| download | zen-5fd1bdfafcd1e44162a1a4a978de775660c378a6.tar.xz zen-5fd1bdfafcd1e44162a1a4a978de775660c378a6.zip | |
fix potential partially written files (#2)
* Make sure WriteFile() does not leave incomplete files
* use TemporaryFile and MoveTemporaryIntoPlace to avoid leaving partial files on error
Diffstat (limited to 'src')
| -rw-r--r-- | src/zencore/filesystem.cpp | 10 | ||||
| -rw-r--r-- | src/zenserver/projectstore/projectstore.cpp | 10 | ||||
| -rw-r--r-- | src/zenstore/cas.cpp | 14 | ||||
| -rw-r--r-- | src/zenstore/compactcas.cpp | 15 | ||||
| -rw-r--r-- | src/zenstore/filecas.cpp | 15 |
5 files changed, 47 insertions, 17 deletions
diff --git a/src/zencore/filesystem.cpp b/src/zencore/filesystem.cpp index 29ec14e0c..3e94b550f 100644 --- a/src/zencore/filesystem.cpp +++ b/src/zencore/filesystem.cpp @@ -811,11 +811,17 @@ WriteFile(std::filesystem::path Path, const IoBuffer* const* Data, size_t Buffer hRes = Outfile.Write(DataPtr, gsl::narrow_cast<uint32_t>(WriteSize)); if (FAILED(hRes)) { + Outfile.Close(); + std::error_code DummyEc; + std::filesystem::remove(Path, DummyEc); ThrowSystemException(hRes, fmt::format("File write failed for '{}'", Path).c_str()); } #else if (write(Fd, DataPtr, WriteSize) != int64_t(WriteSize)) { + close(Fd); + std::error_code DummyEc; + std::filesystem::remove(Path, DummyEc); ThrowLastError(fmt::format("File write failed for '{}'", Path)); } #endif // ZEN_PLATFORM_WINDOWS @@ -825,7 +831,9 @@ WriteFile(std::filesystem::path Path, const IoBuffer* const* Data, size_t Buffer } } -#if !ZEN_PLATFORM_WINDOWS +#if ZEN_PLATFORM_WINDOWS + Outfile.Close(); +#else close(Fd); #endif } diff --git a/src/zenserver/projectstore/projectstore.cpp b/src/zenserver/projectstore/projectstore.cpp index b255ac9e6..47f8b7357 100644 --- a/src/zenserver/projectstore/projectstore.cpp +++ b/src/zenserver/projectstore/projectstore.cpp @@ -817,10 +817,7 @@ ProjectStore::Oplog::Write() ZEN_INFO("persisting config for oplog '{}' in project '{}' to {}", m_OplogId, m_OuterProject->Identifier, StateFilePath); - BasicFile Blob; - Blob.Open(StateFilePath, BasicFile::Mode::kTruncate); - Blob.Write(Mem.Data(), Mem.Size(), 0); - Blob.Flush(); + WriteFile(StateFilePath, IoBuffer(IoBuffer::Wrap, Mem.GetData(), Mem.GetSize())); } void @@ -1489,10 +1486,7 @@ ProjectStore::Project::Write() ZEN_INFO("persisting config for project '{}' to {}", Identifier, ProjectStateFilePath); - BasicFile Blob; - Blob.Open(ProjectStateFilePath, BasicFile::Mode::kTruncate); - Blob.Write(Mem.Data(), Mem.Size(), 0); - Blob.Flush(); + WriteFile(ProjectStateFilePath, IoBuffer(IoBuffer::Wrap, Mem.GetData(), Mem.GetSize())); } void diff --git a/src/zenstore/cas.cpp b/src/zenstore/cas.cpp index f1a141ca0..4f137744b 100644 --- a/src/zenstore/cas.cpp +++ b/src/zenstore/cas.cpp @@ -214,9 +214,19 @@ CasImpl::UpdateManifest() ZEN_TRACE("Writing new manifest to '{}'", ManifestPath); - BasicFile Marker; - Marker.Open(ManifestPath.c_str(), BasicFile::Mode::kTruncate); + TemporaryFile Marker; + std::error_code Ec; + Marker.CreateTemporary(ManifestPath.parent_path(), Ec); + if (Ec) + { + throw std::system_error(Ec, fmt::format("Failed to create temp file for cas manifest at '{}'", ManifestPath)); + } Marker.Write(m_ManifestObject.GetBuffer(), 0); + Marker.MoveTemporaryIntoPlace(ManifestPath, Ec); + if (Ec) + { + throw std::system_error(Ec, fmt::format("Failed to move temp file '{}' to '{}'", Marker.GetPath(), ManifestPath)); + } } CasStore::InsertResult diff --git a/src/zenstore/compactcas.cpp b/src/zenstore/compactcas.cpp index c8fb41ffc..17cf20e35 100644 --- a/src/zenstore/compactcas.cpp +++ b/src/zenstore/compactcas.cpp @@ -910,8 +910,13 @@ CasContainerStrategy::MakeIndexSnapshot() } } - BasicFile ObjectIndexFile; - ObjectIndexFile.Open(IndexPath, BasicFile::Mode::kTruncate); + TemporaryFile ObjectIndexFile; + std::error_code Ec; + ObjectIndexFile.CreateTemporary(IndexPath.parent_path(), Ec); + if (Ec) + { + throw std::system_error(Ec, fmt::format("Failed to create temp file for index snapshot at '{}'", IndexPath)); + } CasDiskIndexHeader Header = {.EntryCount = Entries.size(), .LogPosition = IndexLogPosition, .PayloadAlignment = gsl::narrow<uint32_t>(m_PayloadAlignment)}; @@ -921,7 +926,11 @@ CasContainerStrategy::MakeIndexSnapshot() ObjectIndexFile.Write(&Header, sizeof(CasDiskIndexHeader), 0); ObjectIndexFile.Write(Entries.data(), Entries.size() * sizeof(CasDiskIndexEntry), sizeof(CasDiskIndexHeader)); ObjectIndexFile.Flush(); - ObjectIndexFile.Close(); + ObjectIndexFile.MoveTemporaryIntoPlace(IndexPath, Ec); + if (Ec) + { + throw std::system_error(Ec, fmt::format("Failed to move temp file '{}' to '{}'", ObjectIndexFile.GetPath(), IndexPath)); + } EntryCount = Entries.size(); m_LogFlushPosition = IndexLogPosition; } diff --git a/src/zenstore/filecas.cpp b/src/zenstore/filecas.cpp index af0a3a176..428183827 100644 --- a/src/zenstore/filecas.cpp +++ b/src/zenstore/filecas.cpp @@ -1179,8 +1179,13 @@ FileCasStrategy::MakeIndexSnapshot() } } - BasicFile ObjectIndexFile; - ObjectIndexFile.Open(IndexPath, BasicFile::Mode::kTruncate); + TemporaryFile ObjectIndexFile; + std::error_code Ec; + ObjectIndexFile.CreateTemporary(IndexPath.parent_path(), Ec); + if (Ec) + { + throw std::system_error(Ec, fmt::format("Failed to create temp file for index snapshot at '{}'", IndexPath)); + } filecas::impl::FileCasIndexHeader Header = {.EntryCount = Entries.size(), .LogPosition = IndexLogPosition}; Header.Checksum = filecas::impl::FileCasIndexHeader::ComputeChecksum(Header); @@ -1188,7 +1193,11 @@ FileCasStrategy::MakeIndexSnapshot() ObjectIndexFile.Write(&Header, sizeof(filecas::impl::FileCasIndexHeader), 0); ObjectIndexFile.Write(Entries.data(), Entries.size() * sizeof(FileCasIndexEntry), sizeof(filecas::impl::FileCasIndexHeader)); ObjectIndexFile.Flush(); - ObjectIndexFile.Close(); + ObjectIndexFile.MoveTemporaryIntoPlace(IndexPath, Ec); + if (Ec) + { + throw std::system_error(Ec, fmt::format("Failed to move temp file '{}' to '{}'", ObjectIndexFile.GetPath(), IndexPath)); + } EntryCount = Entries.size(); m_LogFlushPosition = IndexLogPosition; } |