Coverage Report

Created: 2026-06-15 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupd/fwupd-error.c
Line
Count
Source
1
/*
2
 * Copyright 2015-2016 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#include "config.h"
8
9
#include <gio/gio.h>
10
11
#include "fwupd-common.h"
12
#include "fwupd-error.h"
13
14
/**
15
 * fwupd_error_to_string:
16
 * @error: an enumerated error, e.g. %FWUPD_ERROR_VERSION_NEWER
17
 *
18
 * Converts an enumerated error to a string.
19
 *
20
 * Returns: identifier string
21
 *
22
 * Since: 0.7.0
23
 **/
24
const gchar *
25
fwupd_error_to_string(FwupdError error)
26
990
{
27
990
  if (error == FWUPD_ERROR_INTERNAL)
28
45
    return FWUPD_DBUS_INTERFACE ".Internal";
29
945
  if (error == FWUPD_ERROR_VERSION_NEWER)
30
45
    return FWUPD_DBUS_INTERFACE ".VersionNewer";
31
900
  if (error == FWUPD_ERROR_VERSION_SAME)
32
45
    return FWUPD_DBUS_INTERFACE ".VersionSame";
33
855
  if (error == FWUPD_ERROR_ALREADY_PENDING)
34
45
    return FWUPD_DBUS_INTERFACE ".AlreadyPending";
35
810
  if (error == FWUPD_ERROR_AUTH_FAILED)
36
45
    return FWUPD_DBUS_INTERFACE ".AuthFailed";
37
765
  if (error == FWUPD_ERROR_READ)
38
45
    return FWUPD_DBUS_INTERFACE ".Read";
39
720
  if (error == FWUPD_ERROR_WRITE)
40
45
    return FWUPD_DBUS_INTERFACE ".Write";
41
675
  if (error == FWUPD_ERROR_INVALID_FILE)
42
45
    return FWUPD_DBUS_INTERFACE ".InvalidFile";
43
630
  if (error == FWUPD_ERROR_NOT_FOUND)
44
45
    return FWUPD_DBUS_INTERFACE ".NotFound";
45
585
  if (error == FWUPD_ERROR_NOTHING_TO_DO)
46
45
    return FWUPD_DBUS_INTERFACE ".NothingToDo";
47
540
  if (error == FWUPD_ERROR_NOT_SUPPORTED)
48
45
    return FWUPD_DBUS_INTERFACE ".NotSupported";
49
495
  if (error == FWUPD_ERROR_SIGNATURE_INVALID)
50
45
    return FWUPD_DBUS_INTERFACE ".SignatureInvalid";
51
450
  if (error == FWUPD_ERROR_AC_POWER_REQUIRED)
52
45
    return FWUPD_DBUS_INTERFACE ".AcPowerRequired";
53
405
  if (error == FWUPD_ERROR_PERMISSION_DENIED)
54
45
    return FWUPD_DBUS_INTERFACE ".PermissionDenied";
55
360
  if (error == FWUPD_ERROR_BROKEN_SYSTEM)
56
45
    return FWUPD_DBUS_INTERFACE ".BrokenSystem";
57
315
  if (error == FWUPD_ERROR_BATTERY_LEVEL_TOO_LOW)
58
45
    return FWUPD_DBUS_INTERFACE ".BatteryLevelTooLow";
59
270
  if (error == FWUPD_ERROR_NEEDS_USER_ACTION)
60
45
    return FWUPD_DBUS_INTERFACE ".NeedsUserAction";
61
225
  if (error == FWUPD_ERROR_AUTH_EXPIRED)
62
45
    return FWUPD_DBUS_INTERFACE ".AuthExpired";
63
180
  if (error == FWUPD_ERROR_INVALID_DATA)
64
45
    return FWUPD_DBUS_INTERFACE ".InvalidData";
65
135
  if (error == FWUPD_ERROR_TIMED_OUT)
66
45
    return FWUPD_DBUS_INTERFACE ".TimedOut";
67
90
  if (error == FWUPD_ERROR_BUSY)
68
45
    return FWUPD_DBUS_INTERFACE ".Busy";
69
45
  if (error == FWUPD_ERROR_NOT_REACHABLE)
70
45
    return FWUPD_DBUS_INTERFACE ".NotReachable";
71
0
  return NULL;
72
45
}
73
74
/**
75
 * fwupd_error_from_string:
76
 * @error: (nullable): a string, e.g. `org.freedesktop.fwupd.VersionNewer`
77
 *
78
 * Converts a string to an enumerated error.
79
 *
80
 * Returns: enumerated value
81
 *
82
 * Since: 0.7.0
83
 **/
84
FwupdError
85
fwupd_error_from_string(const gchar *error)
86
0
{
87
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".Internal") == 0)
88
0
    return FWUPD_ERROR_INTERNAL;
89
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".VersionNewer") == 0)
90
0
    return FWUPD_ERROR_VERSION_NEWER;
91
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".VersionSame") == 0)
92
0
    return FWUPD_ERROR_VERSION_SAME;
93
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".AlreadyPending") == 0)
94
0
    return FWUPD_ERROR_ALREADY_PENDING;
95
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".AuthFailed") == 0)
96
0
    return FWUPD_ERROR_AUTH_FAILED;
97
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".Read") == 0)
98
0
    return FWUPD_ERROR_READ;
99
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".Write") == 0)
100
0
    return FWUPD_ERROR_WRITE;
101
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".InvalidFile") == 0)
102
0
    return FWUPD_ERROR_INVALID_FILE;
103
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".InvalidData") == 0)
104
0
    return FWUPD_ERROR_INVALID_DATA;
105
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".NotFound") == 0)
106
0
    return FWUPD_ERROR_NOT_FOUND;
107
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".NothingToDo") == 0)
108
0
    return FWUPD_ERROR_NOTHING_TO_DO;
109
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".NotSupported") == 0)
110
0
    return FWUPD_ERROR_NOT_SUPPORTED;
111
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".SignatureInvalid") == 0)
112
0
    return FWUPD_ERROR_SIGNATURE_INVALID;
113
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".AcPowerRequired") == 0)
114
0
    return FWUPD_ERROR_AC_POWER_REQUIRED;
115
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".PermissionDenied") == 0)
116
0
    return FWUPD_ERROR_PERMISSION_DENIED;
117
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".BrokenSystem") == 0)
118
0
    return FWUPD_ERROR_BROKEN_SYSTEM;
119
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".BatteryLevelTooLow") == 0)
120
0
    return FWUPD_ERROR_BATTERY_LEVEL_TOO_LOW;
121
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".NeedsUserAction") == 0)
122
0
    return FWUPD_ERROR_NEEDS_USER_ACTION;
123
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".AuthExpired") == 0)
124
0
    return FWUPD_ERROR_AUTH_EXPIRED;
125
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".TimedOut") == 0)
126
0
    return FWUPD_ERROR_TIMED_OUT;
127
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".Busy") == 0)
128
0
    return FWUPD_ERROR_BUSY;
129
0
  if (g_strcmp0(error, FWUPD_DBUS_INTERFACE ".NotReachable") == 0)
130
0
    return FWUPD_ERROR_NOT_REACHABLE;
131
0
  return FWUPD_ERROR_LAST;
132
0
}
133
134
/**
135
 * fwupd_error_quark:
136
 *
137
 * An error quark.
138
 *
139
 * Returns: an error quark
140
 *
141
 * Since: 0.1.1
142
 **/
143
GQuark
144
fwupd_error_quark(void)
145
734k
{
146
734k
  static GQuark quark = 0;
147
734k
  if (!quark) {
148
45
    quark = g_quark_from_static_string("FwupdError");
149
1.03k
    for (gint i = 0; i < FWUPD_ERROR_LAST; i++) {
150
990
      g_dbus_error_register_error(quark, i, fwupd_error_to_string(i));
151
990
    }
152
45
  }
153
734k
  return quark;
154
734k
}
155
156
/**
157
 * fwupd_error_convert:
158
 * @perror: (nullable): A #GError, perhaps with domain #GIOError
159
 *
160
 * Convert the error to a #FwupdError, if required.
161
 *
162
 * Since: 2.0.0
163
 **/
164
void
165
fwupd_error_convert(GError **perror)
166
0
{
167
0
  GError *error = (perror != NULL) ? *perror : NULL;
168
0
  struct {
169
0
    GQuark domain;
170
0
    gint code;
171
0
    FwupdError fwupd_code;
172
0
  } map[] = {
173
0
      {G_FILE_ERROR, G_FILE_ERROR_ACCES, FWUPD_ERROR_PERMISSION_DENIED},
174
0
      {G_FILE_ERROR, G_FILE_ERROR_AGAIN, FWUPD_ERROR_BUSY},
175
0
      {G_FILE_ERROR, G_FILE_ERROR_BADF, FWUPD_ERROR_INTERNAL},
176
0
      {G_FILE_ERROR, G_FILE_ERROR_EXIST, FWUPD_ERROR_PERMISSION_DENIED},
177
0
      {G_FILE_ERROR, G_FILE_ERROR_FAILED, FWUPD_ERROR_INTERNAL},
178
0
      {G_FILE_ERROR, G_FILE_ERROR_FAULT, FWUPD_ERROR_INTERNAL},
179
0
      {G_FILE_ERROR, G_FILE_ERROR_INTR, FWUPD_ERROR_BUSY},
180
0
      {G_FILE_ERROR, G_FILE_ERROR_INVAL, FWUPD_ERROR_INVALID_DATA},
181
0
      {G_FILE_ERROR, G_FILE_ERROR_IO, FWUPD_ERROR_INTERNAL},
182
0
      {G_FILE_ERROR, G_FILE_ERROR_ISDIR, FWUPD_ERROR_INVALID_FILE},
183
0
      {G_FILE_ERROR, G_FILE_ERROR_LOOP, FWUPD_ERROR_NOT_SUPPORTED},
184
0
      {G_FILE_ERROR, G_FILE_ERROR_MFILE, FWUPD_ERROR_INTERNAL},
185
0
      {G_FILE_ERROR, G_FILE_ERROR_NAMETOOLONG, FWUPD_ERROR_INVALID_DATA},
186
0
      {G_FILE_ERROR, G_FILE_ERROR_NFILE, FWUPD_ERROR_BROKEN_SYSTEM},
187
0
      {G_FILE_ERROR, G_FILE_ERROR_NODEV, FWUPD_ERROR_NOT_SUPPORTED},
188
0
      {G_FILE_ERROR, G_FILE_ERROR_NOENT, FWUPD_ERROR_INVALID_FILE},
189
0
      {G_FILE_ERROR, G_FILE_ERROR_NOSPC, FWUPD_ERROR_BROKEN_SYSTEM},
190
0
      {G_FILE_ERROR, G_FILE_ERROR_NOSYS, FWUPD_ERROR_NOT_SUPPORTED},
191
0
      {G_FILE_ERROR, G_FILE_ERROR_NOTDIR, FWUPD_ERROR_INVALID_FILE},
192
0
      {G_FILE_ERROR, G_FILE_ERROR_NXIO, FWUPD_ERROR_NOT_FOUND},
193
0
      {G_FILE_ERROR, G_FILE_ERROR_PERM, FWUPD_ERROR_PERMISSION_DENIED},
194
0
      {G_FILE_ERROR, G_FILE_ERROR_PIPE, FWUPD_ERROR_NOT_SUPPORTED},
195
0
      {G_FILE_ERROR, G_FILE_ERROR_ROFS, FWUPD_ERROR_NOT_SUPPORTED},
196
0
      {G_FILE_ERROR, G_FILE_ERROR_TXTBSY, FWUPD_ERROR_BUSY},
197
0
      {G_IO_ERROR, G_IO_ERROR_BUSY, FWUPD_ERROR_TIMED_OUT},
198
0
      {G_IO_ERROR, G_IO_ERROR_CANCELLED, FWUPD_ERROR_INTERNAL},
199
0
      {G_IO_ERROR, G_IO_ERROR_FAILED, FWUPD_ERROR_INTERNAL},
200
0
      {G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, FWUPD_ERROR_INVALID_DATA},
201
0
      {G_IO_ERROR, G_IO_ERROR_INVALID_DATA, FWUPD_ERROR_INVALID_DATA},
202
#if GLIB_CHECK_VERSION(2, 74, 0)
203
      {G_IO_ERROR, G_IO_ERROR_NO_SUCH_DEVICE, FWUPD_ERROR_NOT_FOUND},
204
#endif
205
0
      {G_IO_ERROR, G_IO_ERROR_NOT_CONNECTED, FWUPD_ERROR_NOT_FOUND},
206
0
      {G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY, FWUPD_ERROR_NOT_SUPPORTED},
207
0
      {G_IO_ERROR, G_IO_ERROR_NOT_EMPTY, FWUPD_ERROR_NOT_SUPPORTED},
208
0
      {G_IO_ERROR, G_IO_ERROR_NOT_FOUND, FWUPD_ERROR_NOT_FOUND},
209
0
      {G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, FWUPD_ERROR_INTERNAL},
210
0
      {G_IO_ERROR, G_IO_ERROR_NOT_REGULAR_FILE, FWUPD_ERROR_INVALID_DATA},
211
0
      {G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, FWUPD_ERROR_NOT_SUPPORTED},
212
0
      {G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, FWUPD_ERROR_READ},
213
0
      {G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, FWUPD_ERROR_PERMISSION_DENIED},
214
0
      {G_IO_ERROR, G_IO_ERROR_TIMED_OUT, FWUPD_ERROR_TIMED_OUT},
215
0
      {G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, FWUPD_ERROR_TIMED_OUT},
216
0
      {G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, FWUPD_ERROR_NOT_SUPPORTED},
217
0
      {G_IO_ERROR, G_IO_ERROR_DBUS_ERROR, FWUPD_ERROR_NOT_SUPPORTED},
218
0
      {G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_UNKNOWN_ENCODING, FWUPD_ERROR_INVALID_DATA},
219
0
      {G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE, FWUPD_ERROR_INVALID_DATA},
220
0
      {G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, FWUPD_ERROR_INVALID_DATA},
221
0
      {G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND, FWUPD_ERROR_INVALID_DATA},
222
0
      {G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND, FWUPD_ERROR_INVALID_DATA},
223
0
      {G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE, FWUPD_ERROR_INVALID_DATA},
224
0
      {G_MARKUP_ERROR, G_MARKUP_ERROR_BAD_UTF8, FWUPD_ERROR_INVALID_DATA},
225
0
      {G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY, FWUPD_ERROR_INVALID_DATA},
226
0
      {G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, FWUPD_ERROR_INVALID_DATA},
227
0
      {G_MARKUP_ERROR, G_MARKUP_ERROR_MISSING_ATTRIBUTE, FWUPD_ERROR_INVALID_DATA},
228
0
      {G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, FWUPD_ERROR_INVALID_DATA},
229
0
      {G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, FWUPD_ERROR_NOT_SUPPORTED},
230
0
      {G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, FWUPD_ERROR_NOT_SUPPORTED},
231
0
  };
232
233
  /* sanity check */
234
0
  if (error == NULL)
235
0
    return;
236
0
  if (error->domain == FWUPD_ERROR)
237
0
    return;
238
239
  /* special case: G_IO_ERROR_FAILED with "No medium found" from removable devices */
240
0
  if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_FAILED) &&
241
0
      g_strstr_len(error->message, -1, "No medium found") != NULL) {
242
0
    error->domain = FWUPD_ERROR;
243
0
    error->code = FWUPD_ERROR_NOT_FOUND;
244
0
    return;
245
0
  }
246
247
  /* convert GError to FwupdError */
248
0
  for (guint i = 0; i < G_N_ELEMENTS(map); i++) {
249
0
    if (g_error_matches(error, map[i].domain, map[i].code)) {
250
0
      error->domain = FWUPD_ERROR;
251
0
      error->code = map[i].fwupd_code;
252
0
      return;
253
0
    }
254
0
  }
255
256
  /* fallback */
257
0
#ifndef SUPPORTED_BUILD
258
0
  g_critical("GError %s:%i sending over D-Bus was not converted to FwupdError",
259
0
       g_quark_to_string(error->domain),
260
0
       error->code);
261
0
#endif
262
0
  error->domain = FWUPD_ERROR;
263
0
  error->code = FWUPD_ERROR_INTERNAL;
264
0
}
265
266
/**
267
 * fwupd_strerror:
268
 *
269
 * Returns an untranslated string corresponding to the given error code, e.g. “no such process”.
270
 *
271
 * Returns: string describing the error code
272
 *
273
 * Since: 2.0.11
274
 **/
275
const gchar *
276
fwupd_strerror(gint errnum) /* nocheck:name */
277
0
{
278
#ifdef HAVE_STRERRORDESC_NP
279
  return strerrordesc_np(errnum);
280
#else
281
0
  return g_strerror(errnum); /* nocheck:blocked */
282
0
#endif
283
0
}