diff options
author | Tim Schumacher <timschumi@gmx.de> | 2023-01-14 13:07:30 +0100 |
---|---|---|
committer | Jelle Raaijmakers <jelle@gmta.nl> | 2023-01-17 23:55:34 +0100 |
commit | 2313460b3e62e724f9135f18efa1c5b381e67bdd (patch) | |
tree | f89c8a3f8712c27b44a1eda3a782cda7c4cdf53c /Userland/Utilities | |
parent | 5320ed0fd61242ec3f7387e5a6f446bf20d74cda (diff) | |
download | serenity-2313460b3e62e724f9135f18efa1c5b381e67bdd.zip |
pro: Use `Core::Stream` for writing contents to the output
We also have to do a little dance with file descriptor numbers, since we
can't just `freopen` a `FILE` struct anymore to redirect to the correct
file.
Diffstat (limited to 'Userland/Utilities')
-rw-r--r-- | Userland/Utilities/pro.cpp | 80 |
1 files changed, 45 insertions, 35 deletions
diff --git a/Userland/Utilities/pro.cpp b/Userland/Utilities/pro.cpp index 7ab62ff5c1..8019570204 100644 --- a/Userland/Utilities/pro.cpp +++ b/Userland/Utilities/pro.cpp @@ -102,52 +102,47 @@ private: bool m_might_be_wrong { false }; }; +/// Wraps a stream to silently ignore writes when the condition isn't true. template<typename ConditionT> -class ConditionalOutputFileStream final : public OutputFileStream { +class ConditionalOutputStream final : public Core::Stream::Stream { public: - template<typename... Args> - ConditionalOutputFileStream(ConditionT&& condition, Args... args) - : OutputFileStream(args...) + ConditionalOutputStream(ConditionT&& condition, Core::Stream::Handle<Core::Stream::Stream> stream) + : m_stream(move(stream)) , m_condition(condition) { } - ~ConditionalOutputFileStream() + virtual ErrorOr<Bytes> read(Bytes) override { - if (!m_condition()) - return; - - if (!m_buffer.is_empty()) { - OutputFileStream::write(m_buffer); - m_buffer.clear(); - } + return Error::from_errno(EBADF); } -private: - size_t write(ReadonlyBytes bytes) override + virtual ErrorOr<size_t> write(ReadonlyBytes bytes) override { - if (!m_condition()) { - write_to_buffer:; - // FIXME: Propagate errors. - if (m_buffer.try_append(bytes.data(), bytes.size()).is_error()) - return 0; + // Pretend that we wrote the whole buffer if the condition is untrue. + if (!m_condition()) return bytes.size(); - } - if (!m_buffer.is_empty()) { - auto size = OutputFileStream::write(m_buffer); - // FIXME: Propagate errors. - m_buffer = MUST(m_buffer.slice(size, m_buffer.size() - size)); - } + return m_stream->write(bytes); + } - if (!m_buffer.is_empty()) - goto write_to_buffer; + virtual bool is_eof() const override + { + return true; + } - return OutputFileStream::write(bytes); + virtual bool is_open() const override + { + return m_stream->is_open(); } + virtual void close() override + { + } + +private: + Core::Stream::Handle<Core::Stream::Stream> m_stream; ConditionT m_condition; - ByteBuffer m_buffer; }; ErrorOr<int> serenity_main(Main::Arguments arguments) @@ -210,6 +205,10 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) args_parser.add_positional_argument(url_str, "URL to download from", "url"); args_parser.parse(arguments); + // If writing to a file was requested, we'll open a new file descriptor with the same number later. + // Until then, we just clone the stdout file descriptor, because we shouldn't be reopening the actual stdout. + int const output_fd = TRY(Core::System::dup(STDOUT_FILENO)); + if (!method_override.is_empty()) { method = method_override; } else if (data) { @@ -243,7 +242,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) RefPtr<Protocol::Request> request; auto protocol_client = TRY(Protocol::RequestClient::try_create()); - auto output_stream = ConditionalOutputFileStream { [&] { return should_save_stream_data; }, stdout }; + auto output_stream = ConditionalOutputStream { [&] { return should_save_stream_data; }, TRY(Core::Stream::File::adopt_fd(output_fd, Core::Stream::OpenMode::Write)) }; // https://httpwg.org/specs/rfc9110.html#authentication auto const has_credentials = !credentials.is_empty(); @@ -343,8 +342,21 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) } while (Core::File::exists(output_name)); } - if (freopen(output_name.characters(), "w", stdout) == nullptr) { - perror("freopen"); + int target_file_fd = open(output_name.characters(), O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (target_file_fd < 0) { + perror("target file open"); + loop.quit(1); + return; + } + + if (dup2(target_file_fd, output_fd) < 0) { + perror("target file dup2"); + loop.quit(1); + return; + } + + if (close(target_file_fd) < 0) { + perror("target file close"); loop.quit(1); return; } @@ -394,7 +406,5 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) dbgln("started request with id {}", request->id()); - auto rc = loop.exec(); - fflush(stdout); - return rc; + return loop.exec(); } |