/src/fwupd/libfwupdplugin/fu-output-stream.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2025 Richard Hughes <richard@hughsie.com> |
3 | | * |
4 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
5 | | */ |
6 | | |
7 | 0 | #define G_LOG_DOMAIN "FuOutputStream" |
8 | | |
9 | | #include "config.h" |
10 | | |
11 | | #include "fu-bytes.h" |
12 | | #include "fu-output-stream.h" |
13 | | |
14 | | /** |
15 | | * fu_output_stream_from_path: |
16 | | * @path: a filename |
17 | | * @error: (nullable): optional return location for an error |
18 | | * |
19 | | * Opens the file as an output stream. |
20 | | * |
21 | | * Returns: (transfer full): a #GOutputStream, or %NULL on error |
22 | | * |
23 | | * Since: 2.0.12 |
24 | | **/ |
25 | | GOutputStream * |
26 | | fu_output_stream_from_path(const gchar *path, GError **error) |
27 | 0 | { |
28 | 0 | g_autoptr(GFile) file = NULL; |
29 | 0 | g_autoptr(GFileOutputStream) stream = NULL; |
30 | |
|
31 | 0 | g_return_val_if_fail(path != NULL, NULL); |
32 | 0 | g_return_val_if_fail(error == NULL || *error == NULL, NULL); |
33 | | |
34 | 0 | file = g_file_new_for_path(path); |
35 | 0 | stream = g_file_replace(file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error); |
36 | 0 | if (stream == NULL) { |
37 | 0 | fwupd_error_convert(error); |
38 | 0 | return NULL; |
39 | 0 | } |
40 | 0 | return G_OUTPUT_STREAM(g_steal_pointer(&stream)); |
41 | 0 | } |
42 | | |
43 | | /** |
44 | | * fu_output_stream_write_bytes: |
45 | | * @stream: a #GOutputStream |
46 | | * @bytes: a #GBytes |
47 | | * @progress: (nullable): optional #FuProgress |
48 | | * @error: (nullable): optional return location for an error |
49 | | * |
50 | | * Write bytes into the stream, retrying as required. Will block during the operation. |
51 | | * |
52 | | * Returns: %TRUE for success |
53 | | * |
54 | | * Since: 2.0.12 |
55 | | **/ |
56 | | gboolean |
57 | | fu_output_stream_write_bytes(GOutputStream *stream, |
58 | | GBytes *bytes, |
59 | | FuProgress *progress, |
60 | | GError **error) |
61 | 0 | { |
62 | 0 | gsize bufsz; |
63 | 0 | gsize total_written = 0; |
64 | |
|
65 | 0 | g_return_val_if_fail(G_IS_OUTPUT_STREAM(stream), FALSE); |
66 | 0 | g_return_val_if_fail(bytes != NULL, FALSE); |
67 | 0 | g_return_val_if_fail(progress == NULL || FU_IS_PROGRESS(progress), FALSE); |
68 | 0 | g_return_val_if_fail(error == NULL || *error == NULL, FALSE); |
69 | | |
70 | 0 | bufsz = g_bytes_get_size(bytes); |
71 | 0 | do { |
72 | 0 | gssize wrote; |
73 | 0 | g_autoptr(GBytes) fw_data = NULL; |
74 | |
|
75 | 0 | fw_data = fu_bytes_new_offset(bytes, total_written, bufsz - total_written, error); |
76 | 0 | if (fw_data == NULL) |
77 | 0 | return FALSE; |
78 | 0 | wrote = g_output_stream_write_bytes(stream, fw_data, NULL, error); |
79 | 0 | if (wrote < 0) { |
80 | 0 | fwupd_error_convert(error); |
81 | 0 | return FALSE; |
82 | 0 | } |
83 | 0 | total_written += wrote; |
84 | |
|
85 | 0 | if (progress != NULL) |
86 | 0 | fu_progress_set_percentage_full(progress, total_written, bufsz); |
87 | 0 | } while (total_written < bufsz); |
88 | 0 | if (total_written != bufsz) { |
89 | 0 | g_set_error(error, |
90 | 0 | FWUPD_ERROR, |
91 | 0 | FWUPD_ERROR_WRITE, |
92 | 0 | "only wrote 0x%x of 0x%x", |
93 | 0 | (guint)total_written, |
94 | 0 | (guint)bufsz); |
95 | 0 | return FALSE; |
96 | 0 | } |
97 | | |
98 | | /* success */ |
99 | 0 | return TRUE; |
100 | 0 | } |