diff --git a/src/fs/io/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx index 7f9baf9f7..421fac249 100644 --- a/src/fs/io/FileOutputStream.cxx +++ b/src/fs/io/FileOutputStream.cxx @@ -30,7 +30,11 @@ FileOutputStream::FileOutputStream(Path _path, Mode _mode) break; case Mode::APPEND_EXISTING: - OpenAppendExisting(); + OpenAppend(false); + break; + + case Mode::APPEND_OR_CREATE: + OpenAppend(true); break; } } @@ -50,10 +54,10 @@ FileOutputStream::OpenCreate() } inline void -FileOutputStream::OpenAppendExisting() +FileOutputStream::OpenAppend(bool create) { handle = CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr, - OPEN_EXISTING, + create ? OPEN_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, nullptr); if (!IsDefined()) @@ -162,9 +166,13 @@ FileOutputStream::OpenCreate() } inline void -FileOutputStream::OpenAppendExisting() +FileOutputStream::OpenAppend(bool create) { - if (!fd.Open(path.c_str(), O_WRONLY|O_APPEND)) + int flags = O_WRONLY|O_APPEND; + if (create) + flags |= O_CREAT; + + if (!fd.Open(path.c_str(), flags)) throw FormatErrno("Failed to append to %s", path.c_str()); } @@ -234,6 +242,7 @@ FileOutputStream::Cancel() break; case Mode::APPEND_EXISTING: + case Mode::APPEND_OR_CREATE: /* can't roll this back */ break; } diff --git a/src/fs/io/FileOutputStream.hxx b/src/fs/io/FileOutputStream.hxx index 3857aa7a5..ff4acaf1e 100644 --- a/src/fs/io/FileOutputStream.hxx +++ b/src/fs/io/FileOutputStream.hxx @@ -69,6 +69,12 @@ public: * not, an exception is thrown. */ APPEND_EXISTING, + + /** + * Like #APPEND_EXISTING, but create the file if it + * does not exist. + */ + APPEND_OR_CREATE, }; private: @@ -98,7 +104,7 @@ public: private: void OpenCreate(); - void OpenAppendExisting(); + void OpenAppend(bool create); bool Close() { assert(IsDefined());