Coverage Report

Created: 2025-06-22 06:29

/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
}