FileOutputStream.hxx 2.93 KB
Newer Older
1
/*
2
 * Copyright 2003-2016 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef MPD_FILE_OUTPUT_STREAM_HXX
#define MPD_FILE_OUTPUT_STREAM_HXX

#include "check.h"
#include "OutputStream.hxx"
#include "fs/AllocatedPath.hxx"
26
#include "Compiler.h"
27

28 29 30 31
#ifndef WIN32
#include "system/FileDescriptor.hxx"
#endif

32 33 34 35 36 37 38 39
#include <assert.h>

#ifdef WIN32
#include <windows.h>
#endif

class Path;

40
class BaseFileOutputStream : public OutputStream {
41
	const AllocatedPath path;
42 43 44 45

#ifdef WIN32
	HANDLE handle;
#else
46
	FileDescriptor fd;
47 48
#endif

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
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

	~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
	}

98 99
#ifdef WIN32
	bool SeekEOF() {
100 101
		return SetFilePointer(handle, 0, nullptr,
				      FILE_END) != 0xffffffff;
102 103 104
	}
#endif

105 106 107 108 109 110 111 112
	bool IsDefined() const {
#ifdef WIN32
		return handle != INVALID_HANDLE_VALUE;
#else
		return fd.IsDefined();
#endif
	}

113
public:
114 115 116 117
	Path GetPath() const {
		return path;
	}

118 119 120
	gcc_pure
	uint64_t Tell() const;

121
	/* virtual methods from class OutputStream */
122
	void Write(const void *data, size_t size) override;
123 124 125
};

class FileOutputStream final : public BaseFileOutputStream {
126 127 128 129 130 131 132 133
#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

134
public:
135
	FileOutputStream(Path _path);
136 137 138 139 140 141

	~FileOutputStream() {
		if (IsDefined())
			Cancel();
	}

142
	void Commit();
143 144 145
	void Cancel();
};

146 147
class AppendFileOutputStream final : public BaseFileOutputStream {
public:
148
	AppendFileOutputStream(Path _path);
149 150 151 152 153 154

	~AppendFileOutputStream() {
		if (IsDefined())
			Close();
	}

155
	void Commit();
156 157
};

158
#endif