From 7f6e1fbc8d463308e374bb7d9b112cd9f452f76e Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Mon, 23 Mar 2015 22:42:07 +0100
Subject: fs/io/FileOutputStream: add class AppendFileOutputStream

---
 src/fs/io/FileOutputStream.cxx | 55 ++++++++++++++++++++++++++++++++++++++++++
 src/fs/io/FileOutputStream.hxx | 12 +++++++++
 2 files changed, 67 insertions(+)

(limited to 'src')

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
-- 
cgit v1.2.3