diff options
Diffstat (limited to 'src/fs/io/FileOutputStream.hxx')
-rw-r--r-- | src/fs/io/FileOutputStream.hxx | 115 |
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 |