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())
return false;
FileOutputStream fos(path_fs, error);
if (!fos.IsDefined()) {
TranslatePlaylistError(error);
return false;
}
FileOutputStream fos(path_fs);
BufferedOutputStream bos(fos);
@ -403,11 +399,7 @@ spl_append_song(const char *utf8path, const DetachedSong &song, Error &error)
if (path_fs.IsNull())
return false;
AppendFileOutputStream fos(path_fs, error);
if (!fos.IsDefined()) {
TranslatePlaylistError(error);
return false;
}
AppendFileOutputStream fos(path_fs);
if (fos.Tell() / (MPD_PATH_MAX + 1) >= playlist_max_length) {
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;
}
FileOutputStream fos(path_fs, error);
if (!fos.IsDefined()) {
TranslatePlaylistError(error);
return false;
}
FileOutputStream fos(path_fs);
BufferedOutputStream bos(fos);
for (unsigned i = 0; i < queue.GetLength(); i++)

View File

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

View File

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

View File

@ -129,9 +129,13 @@ UpdateService::Task()
next.discard);
if (modified || !next.db->FileExists()) {
Error error;
if (!next.db->Save(error))
LogError(error, "Failed to save database");
try {
Error error;
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())

View File

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

View File

@ -102,7 +102,6 @@ protected:
}
#endif
public:
bool IsDefined() const {
#ifdef WIN32
return handle != INVALID_HANDLE_VALUE;
@ -111,6 +110,7 @@ public:
#endif
}
public:
Path GetPath() const {
return path;
}
@ -132,22 +132,20 @@ class FileOutputStream final : public BaseFileOutputStream {
#endif
public:
FileOutputStream(Path _path, Error &error);
FileOutputStream(Path _path);
~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(Path _path);
~AppendFileOutputStream() {
if (IsDefined())

View File

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

View File

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