aboutsummaryrefslogtreecommitdiffstats
path: root/src/fs/io/FileOutputStream.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/io/FileOutputStream.hxx')
-rw-r--r--src/fs/io/FileOutputStream.hxx115
1 files changed, 103 insertions, 12 deletions
diff --git a/src/fs/io/FileOutputStream.hxx b/src/fs/io/FileOutputStream.hxx
index 5b6309957..b182fd03f 100644
--- a/src/fs/io/FileOutputStream.hxx
+++ b/src/fs/io/FileOutputStream.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -25,6 +25,10 @@
#include "fs/AllocatedPath.hxx"
#include "Compiler.h"
+#ifndef WIN32
+#include "system/FileDescriptor.hxx"
+#endif
+
#include <assert.h>
#ifdef WIN32
@@ -33,37 +37,124 @@
class Path;
-class FileOutputStream final : public OutputStream {
- AllocatedPath path;
+class BaseFileOutputStream : public OutputStream {
+ const AllocatedPath path;
#ifdef WIN32
HANDLE handle;
#else
- int fd;
+ FileDescriptor fd;
#endif
-public:
- FileOutputStream(Path _path, Error &error);
+protected:
+#ifdef WIN32
+ template<typename P>
+ BaseFileOutputStream(P &&_path)
+ :path(std::forward<P>(_path)),
+ handle(INVALID_HANDLE_VALUE) {}
+#else
+ template<typename P>
+ BaseFileOutputStream(P &&_path)
+ :path(std::forward<P>(_path)),
+ fd(FileDescriptor::Undefined()) {}
+#endif
- ~FileOutputStream() {
- if (IsDefined())
- Cancel();
+ ~BaseFileOutputStream() {
+ assert(!IsDefined());
}
+#ifdef WIN32
+ void SetHandle(HANDLE _handle) {
+ assert(!IsDefined());
+
+ handle = _handle;
+
+ assert(IsDefined());
+ }
+#else
+ FileDescriptor &SetFD() {
+ assert(!IsDefined());
+
+ return fd;
+ }
+
+ const FileDescriptor &GetFD() const {
+ return fd;
+ }
+#endif
+
+ bool Close() {
+ assert(IsDefined());
+
+#ifdef WIN32
+ CloseHandle(handle);
+ handle = INVALID_HANDLE_VALUE;
+ return true;
+#else
+ return fd.Close();
+#endif
+ }
+
+#ifdef WIN32
+ bool SeekEOF() {
+ return SetFilePointer(handle, 0, nullptr,
+ FILE_END) != 0xffffffff;
+ }
+#endif
+public:
bool IsDefined() const {
#ifdef WIN32
return handle != INVALID_HANDLE_VALUE;
#else
- return fd >= 0;
+ return fd.IsDefined();
#endif
}
- bool Commit(Error &error);
- void Cancel();
+ Path GetPath() const {
+ return path;
+ }
+
+ gcc_pure
+ uint64_t Tell() const;
/* virtual methods from class OutputStream */
bool Write(const void *data, size_t size, Error &error) override;
};
+class FileOutputStream final : public BaseFileOutputStream {
+#ifdef HAVE_LINKAT
+ /**
+ * Was O_TMPFILE used? If yes, then linkat() must be used to
+ * create a link to this file.
+ */
+ bool is_tmpfile;
+#endif
+
+public:
+ FileOutputStream(Path _path, Error &error);
+
+ ~FileOutputStream() {
+ if (IsDefined())
+ Cancel();
+ }
+
+ static FileOutputStream *Create(Path path, Error &error);
+
+ bool Commit(Error &error);
+ void Cancel();
+};
+
+class AppendFileOutputStream final : public BaseFileOutputStream {
+public:
+ AppendFileOutputStream(Path _path, Error &error);
+
+ ~AppendFileOutputStream() {
+ if (IsDefined())
+ Close();
+ }
+
+ bool Commit(Error &error);
+};
+
#endif