Przeglądaj źródła

LibCore: Propagate errors from `Stream::*_entire_buffer`

Tim Schumacher 2 lat temu
rodzic
commit
9a3e95785e

+ 1 - 2
Meta/Lagom/Tools/CodeGenerators/LibWeb/GeneratorUtil.h

@@ -59,7 +59,6 @@ ErrorOr<JsonValue> read_entire_file_as_json(StringView filename)
     auto file = TRY(Core::Stream::File::open(filename, Core::Stream::OpenMode::Read));
     auto json_size = TRY(file->size());
     auto json_data = TRY(ByteBuffer::create_uninitialized(json_size));
-    if (!file->read_entire_buffer(json_data.bytes()))
-        return Error::from_string_literal("Failed to read json file.");
+    TRY(file->read_entire_buffer(json_data.bytes()));
     return JsonValue::from_string(json_data);
 }

+ 7 - 7
Tests/LibCore/TestLibCoreStream.cpp

@@ -87,17 +87,17 @@ TEST_CASE(file_seeking_around)
 
     EXPECT(!file->seek(500, Core::Stream::SeekMode::SetPosition).is_error());
     EXPECT_EQ(file->tell().release_value(), 500);
-    EXPECT(file->read_entire_buffer(buffer));
+    EXPECT(!file->read_entire_buffer(buffer).is_error());
     EXPECT_EQ(buffer_contents, expected_seek_contents1);
 
     EXPECT(!file->seek(234, Core::Stream::SeekMode::FromCurrentPosition).is_error());
     EXPECT_EQ(file->tell().release_value(), 750);
-    EXPECT(file->read_entire_buffer(buffer));
+    EXPECT(!file->read_entire_buffer(buffer).is_error());
     EXPECT_EQ(buffer_contents, expected_seek_contents2);
 
     EXPECT(!file->seek(-105, Core::Stream::SeekMode::FromEndPosition).is_error());
     EXPECT_EQ(file->tell().release_value(), 8597);
-    EXPECT(file->read_entire_buffer(buffer));
+    EXPECT(!file->read_entire_buffer(buffer).is_error());
     EXPECT_EQ(buffer_contents, expected_seek_contents3);
 }
 
@@ -120,7 +120,7 @@ TEST_CASE(file_adopt_fd)
 
     EXPECT(!file->seek(500, Core::Stream::SeekMode::SetPosition).is_error());
     EXPECT_EQ(file->tell().release_value(), 500);
-    EXPECT(file->read_entire_buffer(buffer));
+    EXPECT(!file->read_entire_buffer(buffer).is_error());
     EXPECT_EQ(buffer_contents, expected_seek_contents1);
 
     // A single seek & read test should be fine for now.
@@ -218,7 +218,7 @@ TEST_CASE(tcp_socket_write)
     auto server_socket = maybe_server_socket.release_value();
     EXPECT(!server_socket->set_blocking(true).is_error());
 
-    EXPECT(client_socket->write_entire_buffer({ sent_data.characters_without_null_termination(), sent_data.length() }));
+    EXPECT(!client_socket->write_entire_buffer({ sent_data.characters_without_null_termination(), sent_data.length() }).is_error());
     client_socket->close();
 
     auto maybe_receive_buffer = ByteBuffer::create_uninitialized(64);
@@ -282,7 +282,7 @@ TEST_CASE(udp_socket_read_write)
     auto client_socket = maybe_client_socket.release_value();
 
     EXPECT(client_socket->is_open());
-    EXPECT(client_socket->write_entire_buffer({ sent_data.characters_without_null_termination(), sent_data.length() }));
+    EXPECT(!client_socket->write_entire_buffer({ sent_data.characters_without_null_termination(), sent_data.length() }).is_error());
 
     // FIXME: UDPServer::receive sadly doesn't give us a way to block on it,
     // currently.
@@ -400,7 +400,7 @@ TEST_CASE(local_socket_write)
             EXPECT(!maybe_client_socket.is_error());
             auto client_socket = maybe_client_socket.release_value();
 
-            EXPECT(client_socket->write_entire_buffer({ sent_data.characters_without_null_termination(), sent_data.length() }));
+            EXPECT(!client_socket->write_entire_buffer({ sent_data.characters_without_null_termination(), sent_data.length() }).is_error());
             client_socket->close();
 
             return 0;

+ 1 - 2
Tests/LibCpp/test-cpp-parser.cpp

@@ -18,8 +18,7 @@ static DeprecatedString read_all(DeprecatedString const& path)
     auto file = MUST(Core::Stream::File::open(path, Core::Stream::OpenMode::Read));
     auto file_size = MUST(file->size());
     auto content = MUST(ByteBuffer::create_uninitialized(file_size));
-    if (!file->read_entire_buffer(content.bytes()))
-        VERIFY_NOT_REACHED();
+    MUST(file->read_entire_buffer(content.bytes()));
     return DeprecatedString { content.bytes() };
 }
 

+ 1 - 2
Tests/LibCpp/test-cpp-preprocessor.cpp

@@ -17,8 +17,7 @@ static DeprecatedString read_all(DeprecatedString const& path)
     auto file = MUST(Core::Stream::File::open(path, Core::Stream::OpenMode::Read));
     auto file_size = MUST(file->size());
     auto content = MUST(ByteBuffer::create_uninitialized(file_size));
-    if (!file->read_entire_buffer(content.bytes()))
-        VERIFY_NOT_REACHED();
+    MUST(file->read_entire_buffer(content.bytes()));
     return DeprecatedString { content.bytes() };
 }
 

+ 2 - 2
Tests/LibJS/test-test262.cpp

@@ -161,7 +161,7 @@ public:
         }
 
         for (DeprecatedString const& line : lines) {
-            if (!m_output->write_entire_buffer(DeprecatedString::formatted("{}\n", line).bytes()))
+            if (m_output->write_entire_buffer(DeprecatedString::formatted("{}\n", line).bytes()).is_error())
                 break;
         }
 
@@ -427,7 +427,7 @@ void write_per_file(HashMap<size_t, TestResult> const& result_map, Vector<Deprec
     complete_results.set("duration", time_taken_in_ms / 1000.);
     complete_results.set("results", result_object);
 
-    if (!file->write_entire_buffer(complete_results.to_deprecated_string().bytes()))
+    if (file->write_entire_buffer(complete_results.to_deprecated_string().bytes()).is_error())
         warnln("Failed to write per-file");
     file->close();
 }

+ 1 - 2
Tests/LibMarkdown/TestCommonmark.cpp

@@ -22,8 +22,7 @@ TEST_SETUP
     auto file = file_or_error.release_value();
     auto file_size = MUST(file->size());
     auto content = MUST(ByteBuffer::create_uninitialized(file_size));
-    if (!file->read_entire_buffer(content.bytes()))
-        VERIFY_NOT_REACHED();
+    MUST(file->read_entire_buffer(content.bytes()));
     DeprecatedString test_data { content.bytes() };
 
     auto tests = JsonParser(test_data).parse().value().as_array();

+ 3 - 3
Tests/LibTLS/TestTLSHandshake.cpp

@@ -96,17 +96,17 @@ TEST_CASE(test_TLS_hello_handshake)
         loop.quit(0);
     };
 
-    if (!tls->write_entire_buffer("GET / HTTP/1.1\r\nHost: "_b)) {
+    if (tls->write_entire_buffer("GET / HTTP/1.1\r\nHost: "_b).is_error()) {
         FAIL("write(0) failed");
         return;
     }
 
     auto the_server = DEFAULT_SERVER;
-    if (!tls->write_entire_buffer(the_server.bytes())) {
+    if (tls->write_entire_buffer(the_server.bytes()).is_error()) {
         FAIL("write(1) failed");
         return;
     }
-    if (!tls->write_entire_buffer("\r\nConnection : close\r\n\r\n"_b)) {
+    if (tls->write_entire_buffer("\r\nConnection : close\r\n\r\n"_b).is_error()) {
         FAIL("write(2) failed");
         return;
     }

+ 1 - 1
Userland/Applications/Browser/BrowserWindow.cpp

@@ -471,7 +471,7 @@ ErrorOr<void> BrowserWindow::load_search_engines(GUI::Menu& settings_menu)
     auto search_engines_file = TRY(Core::Stream::File::open(Browser::search_engines_file_path(), Core::Stream::OpenMode::Read));
     auto file_size = TRY(search_engines_file->size());
     auto buffer = TRY(ByteBuffer::create_uninitialized(file_size));
-    if (search_engines_file->read_entire_buffer(buffer)) {
+    if (!search_engines_file->read_entire_buffer(buffer).is_error()) {
         StringView buffer_contents { buffer.bytes() };
         if (auto json = TRY(JsonValue::from_string(buffer_contents)); json.is_array()) {
             auto json_array = json.as_array();

+ 2 - 4
Userland/DevTools/SQLStudio/ScriptEditor.cpp

@@ -44,8 +44,7 @@ ErrorOr<bool> ScriptEditor::save()
 
     auto file = TRY(Core::Stream::File::open(m_path, Core::Stream::OpenMode::Write));
     auto editor_text = text();
-    if (editor_text.length() && !file->write_entire_buffer(editor_text.bytes()))
-        return Error::from_string_literal("Failed to write to file");
+    TRY(file->write_entire_buffer(editor_text.bytes()));
 
     document().set_unmodified();
     return true;
@@ -60,8 +59,7 @@ ErrorOr<bool> ScriptEditor::save_as()
 
     auto file = TRY(Core::Stream::File::open(save_path, Core::Stream::OpenMode::Write));
     auto editor_text = text();
-    if (editor_text.length() && !file->write_entire_buffer(editor_text.bytes()))
-        return Error::from_string_literal("Failed to write to file");
+    TRY(file->write_entire_buffer(editor_text.bytes()));
 
     m_path = save_path;
 

+ 2 - 2
Userland/Libraries/LibCore/InputBitStream.h

@@ -40,7 +40,7 @@ public:
         return m_stream.read(bytes);
     }
     virtual ErrorOr<size_t> write(ReadonlyBytes bytes) override { return m_stream.write(bytes); }
-    virtual bool write_entire_buffer(ReadonlyBytes bytes) override { return m_stream.write_entire_buffer(bytes); }
+    virtual ErrorOr<void> write_entire_buffer(ReadonlyBytes bytes) override { return m_stream.write_entire_buffer(bytes); }
     virtual bool is_eof() const override { return m_stream.is_eof() && !m_current_byte.has_value(); }
     virtual bool is_open() const override { return m_stream.is_open(); }
     virtual void close() override
@@ -155,7 +155,7 @@ public:
         return m_stream.read(bytes);
     }
     virtual ErrorOr<size_t> write(ReadonlyBytes bytes) override { return m_stream.write(bytes); }
-    virtual bool write_entire_buffer(ReadonlyBytes bytes) override { return m_stream.write_entire_buffer(bytes); }
+    virtual ErrorOr<void> write_entire_buffer(ReadonlyBytes bytes) override { return m_stream.write_entire_buffer(bytes); }
     virtual bool is_eof() const override { return m_stream.is_eof() && !m_current_byte.has_value(); }
     virtual bool is_open() const override { return m_stream.is_open(); }
     virtual void close() override

+ 4 - 4
Userland/Libraries/LibCore/MemoryStream.h

@@ -79,13 +79,13 @@ public:
         m_offset += nwritten;
         return nwritten;
     }
-    virtual bool write_entire_buffer(ReadonlyBytes bytes) override
+    virtual ErrorOr<void> write_entire_buffer(ReadonlyBytes bytes) override
     {
         if (remaining() < bytes.size())
-            return false;
+            return Error::from_string_literal("Write of entire buffer ends past the memory area");
 
-        MUST(write(bytes));
-        return true;
+        TRY(write(bytes));
+        return {};
     }
 
     Bytes bytes()

+ 7 - 7
Userland/Libraries/LibCore/Stream.cpp

@@ -23,14 +23,14 @@
 
 namespace Core::Stream {
 
-bool Stream::read_entire_buffer(Bytes buffer)
+ErrorOr<void> Stream::read_entire_buffer(Bytes buffer)
 {
     VERIFY(buffer.size());
 
     size_t nread = 0;
     do {
         if (is_eof())
-            return false;
+            return Error::from_string_literal("Reached end-of-file before filling the entire buffer");
 
         auto result = read(buffer.slice(nread));
         if (result.is_error()) {
@@ -38,13 +38,13 @@ bool Stream::read_entire_buffer(Bytes buffer)
                 continue;
             }
 
-            return false;
+            return result.release_error();
         }
 
         nread += result.value().size();
     } while (nread < buffer.size());
 
-    return true;
+    return {};
 }
 
 ErrorOr<ByteBuffer> Stream::read_until_eof(size_t block_size)
@@ -89,7 +89,7 @@ ErrorOr<void> Stream::discard(size_t discarded_bytes)
     return {};
 }
 
-bool Stream::write_entire_buffer(ReadonlyBytes buffer)
+ErrorOr<void> Stream::write_entire_buffer(ReadonlyBytes buffer)
 {
     VERIFY(buffer.size());
 
@@ -101,13 +101,13 @@ bool Stream::write_entire_buffer(ReadonlyBytes buffer)
                 continue;
             }
 
-            return false;
+            return result.release_error();
         }
 
         nwritten += result.value();
     } while (nwritten < buffer.size());
 
-    return true;
+    return {};
 }
 
 ErrorOr<off_t> SeekableStream::tell() const

+ 3 - 3
Userland/Libraries/LibCore/Stream.h

@@ -35,7 +35,7 @@ public:
     virtual ErrorOr<Bytes> read(Bytes) = 0;
     /// Tries to fill the entire buffer through reading. Returns whether the
     /// buffer was filled without an error.
-    virtual bool read_entire_buffer(Bytes);
+    virtual ErrorOr<void> read_entire_buffer(Bytes);
     /// Reads the stream until EOF, storing the contents into a ByteBuffer which
     /// is returned once EOF is encountered. The block size determines the size
     /// of newly allocated chunks while reading.
@@ -51,7 +51,7 @@ public:
     virtual ErrorOr<size_t> write(ReadonlyBytes) = 0;
     /// Same as write, but does not return until either the entire buffer
     /// contents are written or an error occurs.
-    virtual bool write_entire_buffer(ReadonlyBytes);
+    virtual ErrorOr<void> write_entire_buffer(ReadonlyBytes);
 
     // This is a wrapper around `write_entire_buffer` that is compatible with
     // `write_or_error`. This is required by some templated code in LibProtocol
@@ -59,7 +59,7 @@ public:
     // TODO: Fully port or wrap `Request::stream_into_impl` into `Core::Stream` and remove this.
     bool write_or_error(ReadonlyBytes buffer)
     {
-        return write_entire_buffer(buffer);
+        return !write_entire_buffer(buffer).is_error();
     }
 
     /// Returns whether the stream has reached the end of file. For sockets,

+ 1 - 1
Userland/Libraries/LibGemini/Job.cpp

@@ -75,7 +75,7 @@ bool Job::can_read() const
 
 bool Job::write(ReadonlyBytes bytes)
 {
-    return m_socket->write_entire_buffer(bytes);
+    return !m_socket->write_entire_buffer(bytes).is_error();
 }
 
 void Job::flush_received_buffers()

+ 1 - 1
Userland/Libraries/LibHTTP/Job.cpp

@@ -220,7 +220,7 @@ void Job::on_socket_connected()
         dbgln("{}", DeprecatedString::copy(raw_request));
     }
 
-    bool success = m_socket->write_entire_buffer(raw_request);
+    bool success = !m_socket->write_entire_buffer(raw_request).is_error();
     if (!success)
         deferred_invoke([this] { did_fail(Core::NetworkJob::Error::TransmissionFailed); });
 

+ 5 - 5
Userland/Libraries/LibTLS/HandshakeClient.cpp

@@ -141,11 +141,11 @@ bool TLSv12::compute_master_secret_from_pre_master_secret(size_t length)
 
     if constexpr (TLS_SSL_KEYLOG_DEBUG) {
         auto file = MUST(Core::Stream::File::open("/home/anon/ssl_keylog"sv, Core::Stream::OpenMode::Append | Core::Stream::OpenMode::Write));
-        VERIFY(file->write_entire_buffer("CLIENT_RANDOM "sv.bytes()));
-        VERIFY(file->write_entire_buffer(encode_hex({ m_context.local_random, 32 }).bytes()));
-        VERIFY(file->write_entire_buffer(" "sv.bytes()));
-        VERIFY(file->write_entire_buffer(encode_hex(m_context.master_key).bytes()));
-        VERIFY(file->write_entire_buffer("\n"sv.bytes()));
+        MUST(file->write_entire_buffer("CLIENT_RANDOM "sv.bytes()));
+        MUST(file->write_entire_buffer(encode_hex({ m_context.local_random, 32 }).bytes()));
+        MUST(file->write_entire_buffer(" "sv.bytes()));
+        MUST(file->write_entire_buffer(encode_hex(m_context.master_key).bytes()));
+        MUST(file->write_entire_buffer("\n"sv.bytes()));
     }
 
     expand_key();

+ 1 - 1
Userland/Libraries/LibWebSocket/Impl/WebSocketImplSerenity.cpp

@@ -21,7 +21,7 @@ bool WebSocketImplSerenity::can_read_line()
 
 bool WebSocketImplSerenity::send(ReadonlyBytes bytes)
 {
-    return m_socket->write_entire_buffer(bytes);
+    return !m_socket->write_entire_buffer(bytes).is_error();
 }
 
 bool WebSocketImplSerenity::eof()