aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/fs/io/FileOutputStream.cxx55
-rw-r--r--src/fs/io/FileOutputStream.hxx12
2 files changed, 67 insertions, 0 deletions
diff --git a/src/fs/io/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx
index f587874a3..82d9c3dc1 100644
--- a/src/fs/io/FileOutputStream.cxx
+++ b/src/fs/io/FileOutputStream.cxx
@@ -197,4 +197,59 @@ FileOutputStream::Cancel()
RemoveFile(GetPath());
}
+#ifdef WIN32
+
+FileOutputStream::FileOutputStream(Path _path, Error &error)
+ :path(_path),
+ handle(CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH,
+ nullptr))
+{
+ if (handle == INVALID_HANDLE_VALUE) {
+ const auto path_utf8 = path.ToUTF8();
+ error.FormatLastError("Failed to create %s",
+ path_utf8.c_str());
+ }
+}
+
+#else
+
+AppendFileOutputStream::AppendFileOutputStream(Path _path, Error &error)
+ :BaseFileOutputStream(_path)
+{
+#ifdef WIN32
+ SetHandle(CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH,
+ nullptr))
+ if (!IsDefined())
+ error.FormatLastError("Failed to append to %s",
+ GetPath().ToUTF8().c_str());
+#else
+ if (!SetFD().Open(GetPath().c_str(),
+ O_WRONLY|O_APPEND))
+ error.FormatErrno("Failed to append to %s",
+ GetPath().c_str());
+#endif
+}
+
+#endif
+
+bool
+AppendFileOutputStream::Commit(gcc_unused Error &error)
+{
+ assert(IsDefined());
+
+#ifdef WIN32
+ return Close();
+#else
+ bool success = Close();
+ if (!success)
+ error.FormatErrno("Failed to commit %s", GetPath().c_str());
+
+ return success;
+#endif
+}
+
#endif
diff --git a/src/fs/io/FileOutputStream.hxx b/src/fs/io/FileOutputStream.hxx
index ce53427e2..9decb6f00 100644
--- a/src/fs/io/FileOutputStream.hxx
+++ b/src/fs/io/FileOutputStream.hxx
@@ -135,4 +135,16 @@ public:
void Cancel();
};
+class AppendFileOutputStream final : public BaseFileOutputStream {
+public:
+ AppendFileOutputStream(Path _path, Error &error);
+
+ ~AppendFileOutputStream() {
+ if (IsDefined())
+ Close();
+ }
+
+ bool Commit(Error &error);
+};
+
#endif