aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2024-03-13 10:33:40 +0100
committerGitHub Enterprise <[email protected]>2024-03-13 10:33:40 +0100
commit5fd1bdfafcd1e44162a1a4a978de775660c378a6 (patch)
treeb92b9cc595477075bd02320d0948c2f11e0c0717 /src
parentupdates to signing (diff)
downloadzen-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.cpp10
-rw-r--r--src/zenserver/projectstore/projectstore.cpp10
-rw-r--r--src/zenstore/cas.cpp14
-rw-r--r--src/zenstore/compactcas.cpp15
-rw-r--r--src/zenstore/filecas.cpp15
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;
}