fs/io/FileOutputStream: use C++ exceptions in constructor

This commit is contained in:
Max Kellermann 2015-12-15 22:26:26 +01:00
parent d29be0f460
commit 24b2198668
9 changed files with 64 additions and 72 deletions

View File

@ -232,11 +232,7 @@ SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path,
if (path_fs.IsNull()) if (path_fs.IsNull())
return false; return false;
FileOutputStream fos(path_fs, error); FileOutputStream fos(path_fs);
if (!fos.IsDefined()) {
TranslatePlaylistError(error);
return false;
}
BufferedOutputStream bos(fos); BufferedOutputStream bos(fos);
@ -403,11 +399,7 @@ spl_append_song(const char *utf8path, const DetachedSong &song, Error &error)
if (path_fs.IsNull()) if (path_fs.IsNull())
return false; return false;
AppendFileOutputStream fos(path_fs, error); AppendFileOutputStream fos(path_fs);
if (!fos.IsDefined()) {
TranslatePlaylistError(error);
return false;
}
if (fos.Tell() / (MPD_PATH_MAX + 1) >= playlist_max_length) { if (fos.Tell() / (MPD_PATH_MAX + 1) >= playlist_max_length) {
error.Set(playlist_domain, int(PlaylistResult::TOO_LARGE), error.Set(playlist_domain, int(PlaylistResult::TOO_LARGE),

View File

@ -80,12 +80,7 @@ spl_save_queue(const char *name_utf8, const Queue &queue, Error &error)
return false; return false;
} }
FileOutputStream fos(path_fs, error); FileOutputStream fos(path_fs);
if (!fos.IsDefined()) {
TranslatePlaylistError(error);
return false;
}
BufferedOutputStream bos(fos); BufferedOutputStream bos(fos);
for (unsigned i = 0; i < queue.GetLength(); i++) for (unsigned i = 0; i < queue.GetLength(); i++)

View File

@ -32,6 +32,8 @@
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "Log.hxx" #include "Log.hxx"
#include <exception>
#include <string.h> #include <string.h>
static constexpr Domain state_file_domain("state_file"); static constexpr Domain state_file_domain("state_file");
@ -87,11 +89,15 @@ StateFile::Write()
FormatDebug(state_file_domain, FormatDebug(state_file_domain,
"Saving state file %s", path_utf8.c_str()); "Saving state file %s", path_utf8.c_str());
Error error; try {
FileOutputStream fos(path, error); Error error;
if (!fos.IsDefined() || !Write(fos, error) || !fos.Commit(error)) { FileOutputStream fos(path);
LogError(error); if (!Write(fos, error) || !fos.Commit(error)) {
return; LogError(error);
return;
}
} catch (const std::exception &e) {
LogError(e);
} }
RememberVersions(); RememberVersions();

View File

@ -379,9 +379,7 @@ SimpleDatabase::Save(Error &error)
LogDebug(simple_db_domain, "writing DB"); LogDebug(simple_db_domain, "writing DB");
FileOutputStream fos(path, error); FileOutputStream fos(path);
if (!fos.IsDefined())
return false;
OutputStream *os = &fos; OutputStream *os = &fos;

View File

@ -129,9 +129,13 @@ UpdateService::Task()
next.discard); next.discard);
if (modified || !next.db->FileExists()) { if (modified || !next.db->FileExists()) {
Error error; try {
if (!next.db->Save(error)) Error error;
LogError(error, "Failed to save database"); if (!next.db->Save(error))
LogError(error, "Failed to save database");
} catch (const std::exception &e) {
LogError(e, "Failed to save database");
}
} }
if (!next.path_utf8.empty()) if (!next.path_utf8.empty())

View File

@ -20,23 +20,14 @@
#include "config.h" #include "config.h"
#include "FileOutputStream.hxx" #include "FileOutputStream.hxx"
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
#include "system/Error.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
FileOutputStream * #include <system_error>
FileOutputStream::Create(Path path, Error &error)
{
FileOutputStream *f = new FileOutputStream(path, error);
if (!f->IsDefined()) {
delete f;
f = nullptr;
}
return f;
}
#ifdef WIN32 #ifdef WIN32
FileOutputStream::FileOutputStream(Path _path, Error &error) FileOutputStream::FileOutputStream(Path _path)
:BaseFileOutputStream(_path) :BaseFileOutputStream(_path)
{ {
SetHandle(CreateFile(_path.c_str(), GENERIC_WRITE, 0, nullptr, SetHandle(CreateFile(_path.c_str(), GENERIC_WRITE, 0, nullptr,
@ -44,7 +35,7 @@ FileOutputStream::FileOutputStream(Path _path, Error &error)
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH,
nullptr)); nullptr));
if (!IsDefined()) if (!IsDefined())
error.FormatLastError("Failed to create %s", throw FormatLastError("Failed to create %s",
GetPath().ToUTF8().c_str()); GetPath().ToUTF8().c_str());
} }
@ -128,7 +119,7 @@ OpenTempFile(FileDescriptor &fd, Path path)
#endif /* HAVE_LINKAT */ #endif /* HAVE_LINKAT */
FileOutputStream::FileOutputStream(Path _path, Error &error) FileOutputStream::FileOutputStream(Path _path)
:BaseFileOutputStream(_path) :BaseFileOutputStream(_path)
{ {
#ifdef HAVE_LINKAT #ifdef HAVE_LINKAT
@ -140,7 +131,7 @@ FileOutputStream::FileOutputStream(Path _path, Error &error)
if (!SetFD().Open(GetPath().c_str(), if (!SetFD().Open(GetPath().c_str(),
O_WRONLY|O_CREAT|O_TRUNC, O_WRONLY|O_CREAT|O_TRUNC,
0666)) 0666))
error.FormatErrno("Failed to create %s", throw FormatErrno("Failed to create %s",
GetPath().c_str()); GetPath().c_str());
#ifdef HAVE_LINKAT #ifdef HAVE_LINKAT
} }
@ -216,7 +207,7 @@ FileOutputStream::Cancel()
#endif #endif
AppendFileOutputStream::AppendFileOutputStream(Path _path, Error &error) AppendFileOutputStream::AppendFileOutputStream(Path _path)
:BaseFileOutputStream(_path) :BaseFileOutputStream(_path)
{ {
#ifdef WIN32 #ifdef WIN32
@ -225,18 +216,19 @@ AppendFileOutputStream::AppendFileOutputStream(Path _path, Error &error)
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH,
nullptr)); nullptr));
if (!IsDefined()) if (!IsDefined())
error.FormatLastError("Failed to append to %s", throw FormatLastError("Failed to append to %s",
GetPath().ToUTF8().c_str()); GetPath().ToUTF8().c_str());
if (!SeekEOF()) { if (!SeekEOF()) {
error.FormatLastError("Failed seek end-of-file of %s", auto code = GetLastError();
GetPath().ToUTF8().c_str());
Close(); Close();
throw FormatLastError(code, "Failed seek end-of-file of %s",
GetPath().ToUTF8().c_str());
} }
#else #else
if (!SetFD().Open(GetPath().c_str(), if (!SetFD().Open(GetPath().c_str(),
O_WRONLY|O_APPEND)) O_WRONLY|O_APPEND))
error.FormatErrno("Failed to append to %s", throw FormatErrno("Failed to append to %s",
GetPath().c_str()); GetPath().c_str());
#endif #endif
} }

View File

@ -102,7 +102,6 @@ protected:
} }
#endif #endif
public:
bool IsDefined() const { bool IsDefined() const {
#ifdef WIN32 #ifdef WIN32
return handle != INVALID_HANDLE_VALUE; return handle != INVALID_HANDLE_VALUE;
@ -111,6 +110,7 @@ public:
#endif #endif
} }
public:
Path GetPath() const { Path GetPath() const {
return path; return path;
} }
@ -132,22 +132,20 @@ class FileOutputStream final : public BaseFileOutputStream {
#endif #endif
public: public:
FileOutputStream(Path _path, Error &error); FileOutputStream(Path _path);
~FileOutputStream() { ~FileOutputStream() {
if (IsDefined()) if (IsDefined())
Cancel(); Cancel();
} }
static FileOutputStream *Create(Path path, Error &error);
bool Commit(Error &error); bool Commit(Error &error);
void Cancel(); void Cancel();
}; };
class AppendFileOutputStream final : public BaseFileOutputStream { class AppendFileOutputStream final : public BaseFileOutputStream {
public: public:
AppendFileOutputStream(Path _path, Error &error); AppendFileOutputStream(Path _path);
~AppendFileOutputStream() { ~AppendFileOutputStream() {
if (IsDefined()) if (IsDefined())

View File

@ -179,7 +179,6 @@ inline bool
RecorderOutput::EncoderToFile(Error &error) RecorderOutput::EncoderToFile(Error &error)
{ {
assert(file != nullptr); assert(file != nullptr);
assert(file->IsDefined());
return EncoderToOutputStream(*file, *encoder, error); return EncoderToOutputStream(*file, *encoder, error);
} }
@ -192,9 +191,12 @@ RecorderOutput::Open(AudioFormat &audio_format, Error &error)
if (!HasDynamicPath()) { if (!HasDynamicPath()) {
assert(!path.IsNull()); assert(!path.IsNull());
file = FileOutputStream::Create(path, error); try {
if (file == nullptr) file = new FileOutputStream(path);
} catch (const std::exception &e) {
error.Set(recorder_domain, e.what());
return false; return false;
}
} else { } else {
/* don't open the file just yet; wait until we have /* don't open the file just yet; wait until we have
a tag that we can use to build the path */ a tag that we can use to build the path */
@ -294,10 +296,13 @@ RecorderOutput::ReopenFormat(AllocatedPath &&new_path, Error &error)
assert(path.IsNull()); assert(path.IsNull());
assert(file == nullptr); assert(file == nullptr);
FileOutputStream *new_file = FileOutputStream *new_file;
FileOutputStream::Create(new_path, error); try {
if (new_file == nullptr) new_file = new FileOutputStream(path);
} catch (const std::exception &e) {
error.Set(recorder_domain, e.what());
return false; return false;
}
AudioFormat new_audio_format = effective_audio_format; AudioFormat new_audio_format = effective_audio_format;
if (!encoder->Open(new_audio_format, error)) { if (!encoder->Open(new_audio_format, error)) {

View File

@ -19,6 +19,7 @@
#include "config.h" #include "config.h"
#include "fs/io/FileOutputStream.hxx" #include "fs/io/FileOutputStream.hxx"
#include "Log.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
#include <unistd.h> #include <unistd.h>
@ -59,20 +60,21 @@ main(int argc, char **argv)
const Path path = Path::FromFS(argv[1]); const Path path = Path::FromFS(argv[1]);
Error error; try {
FileOutputStream fos(path, error); Error error;
if (!fos.IsDefined()) { FileOutputStream fos(path);
fprintf(stderr, "%s\n", error.GetMessage());
if (!Copy(fos, STDIN_FILENO))
return EXIT_FAILURE;
if (!fos.Commit(error)) {
fprintf(stderr, "%s\n", error.GetMessage());
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} catch (const std::exception &e) {
LogError(e);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!Copy(fos, STDIN_FILENO))
return EXIT_FAILURE;
if (!fos.Commit(error)) {
fprintf(stderr, "%s\n", error.GetMessage());
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} }