Coverage Report

Created: 2026-07-30 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-stream-input-stream.c
Line
Count
Source
1
/*
2
 * Copyright 2026 Red Hat
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
0
#define G_LOG_DOMAIN "FuStreamInputStream"
8
9
#include "config.h"
10
11
#include "fu-stream-input-stream-private.h"
12
#include "fu-stream-input-stream.h"
13
14
/**
15
 * FuStreamInputStream:
16
 *
17
 * An input stream that wraps a #GInputStream (or subclass) into the
18
 * #FuInputStream type hierarchy.
19
 */
20
21
typedef struct {
22
  GInputStream *base_stream; /* nocheck:blocked */
23
} FuStreamInputStreamPrivate;
24
25
static void
26
fu_stream_input_stream_seekable_iface_init(GSeekableIface *iface);
27
28
106k
G_DEFINE_TYPE_WITH_CODE(FuStreamInputStream,
29
106k
      fu_stream_input_stream,
30
106k
      FU_TYPE_INPUT_STREAM,
31
106k
      G_ADD_PRIVATE(FuStreamInputStream)
32
106k
          G_IMPLEMENT_INTERFACE(G_TYPE_SEEKABLE,
33
106k
              fu_stream_input_stream_seekable_iface_init))
34
106k
35
106k
static gssize
36
106k
fu_stream_input_stream_read(GInputStream *stream,
37
106k
          void *buffer,
38
106k
          gsize count,
39
106k
          GCancellable *cancellable,
40
106k
          GError **error)
41
106k
{
42
39.5k
  FuStreamInputStream *self = FU_STREAM_INPUT_STREAM(stream);
43
39.5k
  FuStreamInputStreamPrivate *priv = fu_stream_input_stream_get_instance_private(self);
44
45
39.5k
  g_return_val_if_fail(priv->base_stream != NULL, -1);
46
47
39.5k
  return g_input_stream_read(priv->base_stream, buffer, count, cancellable, error);
48
39.5k
}
49
50
static goffset
51
fu_stream_input_stream_tell(GSeekable *seekable)
52
0
{
53
0
  FuStreamInputStream *self = FU_STREAM_INPUT_STREAM(seekable);
54
0
  FuStreamInputStreamPrivate *priv = fu_stream_input_stream_get_instance_private(self);
55
56
0
  if (!G_IS_SEEKABLE(priv->base_stream))
57
0
    return 0;
58
59
0
  return g_seekable_tell(G_SEEKABLE(priv->base_stream));
60
0
}
61
62
static gboolean
63
fu_stream_input_stream_can_seek(GSeekable *seekable)
64
16.7k
{
65
16.7k
  FuStreamInputStream *self = FU_STREAM_INPUT_STREAM(seekable);
66
16.7k
  FuStreamInputStreamPrivate *priv = fu_stream_input_stream_get_instance_private(self);
67
68
16.7k
  if (!G_IS_SEEKABLE(priv->base_stream))
69
16.7k
    return FALSE;
70
71
0
  return g_seekable_can_seek(G_SEEKABLE(priv->base_stream));
72
16.7k
}
73
74
static gboolean
75
fu_stream_input_stream_seek(GSeekable *seekable,
76
          goffset offset,
77
          GSeekType type,
78
          GCancellable *cancellable,
79
          GError **error)
80
0
{
81
0
  FuStreamInputStream *self = FU_STREAM_INPUT_STREAM(seekable);
82
0
  FuStreamInputStreamPrivate *priv = fu_stream_input_stream_get_instance_private(self);
83
84
0
  if (!G_IS_SEEKABLE(priv->base_stream)) {
85
0
    g_set_error_literal(error,
86
0
            G_IO_ERROR,
87
0
            G_IO_ERROR_NOT_SUPPORTED,
88
0
            "base stream is not seekable"); /* nocheck:error */
89
0
    return FALSE;
90
0
  }
91
92
0
  return g_seekable_seek(G_SEEKABLE(priv->base_stream), offset, type, cancellable, error);
93
0
}
94
95
static gboolean
96
fu_stream_input_stream_can_truncate(GSeekable *seekable)
97
0
{
98
0
  return FALSE;
99
0
}
100
101
static gboolean
102
fu_stream_input_stream_truncate(GSeekable *seekable,
103
        goffset offset,
104
        GCancellable *cancellable,
105
        GError **error)
106
0
{
107
0
  g_set_error_literal(error,
108
0
          FWUPD_ERROR,
109
0
          FWUPD_ERROR_NOT_SUPPORTED,
110
0
          "cannot truncate FuStreamInputStream");
111
0
  return FALSE;
112
0
}
113
114
static void
115
fu_stream_input_stream_seekable_iface_init(GSeekableIface *iface)
116
4
{
117
4
  iface->tell = fu_stream_input_stream_tell;
118
4
  iface->can_seek = fu_stream_input_stream_can_seek;
119
4
  iface->seek = fu_stream_input_stream_seek;
120
4
  iface->can_truncate = fu_stream_input_stream_can_truncate;
121
4
  iface->truncate_fn = fu_stream_input_stream_truncate;
122
4
}
123
124
static void
125
fu_stream_input_stream_finalize(GObject *object)
126
16.7k
{
127
16.7k
  FuStreamInputStream *self = FU_STREAM_INPUT_STREAM(object);
128
16.7k
  FuStreamInputStreamPrivate *priv = fu_stream_input_stream_get_instance_private(self);
129
16.7k
  g_clear_object(&priv->base_stream);
130
16.7k
  G_OBJECT_CLASS(fu_stream_input_stream_parent_class)->finalize(object);
131
16.7k
}
132
133
static void
134
fu_stream_input_stream_class_init(FuStreamInputStreamClass *klass)
135
4
{
136
4
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
137
4
  GInputStreamClass *istream_class = G_INPUT_STREAM_CLASS(klass); /* nocheck:blocked */
138
4
  object_class->finalize = fu_stream_input_stream_finalize;
139
4
  istream_class->read_fn = fu_stream_input_stream_read;
140
4
}
141
142
static void
143
fu_stream_input_stream_init(FuStreamInputStream *self)
144
16.7k
{
145
16.7k
}
146
147
/**
148
 * fu_stream_input_stream_set_base_stream:
149
 * @self: a #FuStreamInputStream
150
 * @base_stream: (transfer none): a #GInputStream
151
 *
152
 * Sets the underlying #GInputStream that this stream wraps.
153
 * The @base_stream is reffed.
154
 * This is intended for use by subclasses during construction.
155
 *
156
 * Since: 2.0.7
157
 **/
158
void
159
fu_stream_input_stream_set_base_stream(FuStreamInputStream *self, GInputStream *base_stream)
160
16.7k
{
161
16.7k
  FuStreamInputStreamPrivate *priv = fu_stream_input_stream_get_instance_private(self);
162
163
16.7k
  g_return_if_fail(FU_IS_STREAM_INPUT_STREAM(self));
164
16.7k
  g_return_if_fail(G_IS_INPUT_STREAM(base_stream));
165
166
16.7k
  g_set_object(&priv->base_stream, base_stream);
167
16.7k
}
168
169
/**
170
 * fu_stream_input_stream_from_stream:
171
 * @stream: (transfer none): a #GInputStream
172
 *
173
 * Wraps a #GInputStream and returns a #FuStreamInputStream. The @stream
174
 * is reffed and future operations on this input stream apply to the
175
 * underlying #GInputStream.
176
 *
177
 * Returns: (transfer full): a #FuStreamInputStream, or %NULL on error
178
 *
179
 * Since: 2.0.7
180
 **/
181
FuInputStream *
182
fu_stream_input_stream_from_stream(GInputStream *stream)
183
0
{
184
0
  g_autoptr(FuStreamInputStream) self = NULL;
185
186
0
  g_return_val_if_fail(G_IS_INPUT_STREAM(stream), NULL);
187
188
0
  self = g_object_new(FU_TYPE_STREAM_INPUT_STREAM, NULL);
189
0
  fu_stream_input_stream_set_base_stream(self, stream);
190
191
0
  return FU_INPUT_STREAM(g_steal_pointer(&self));
192
0
}