]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-error.c
Fixes for vscode/intellisense parsing (#38040)
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-error.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
de1c301e 2
de1c301e 3#include "sd-bus.h"
07630cea 4
b5efdb8a 5#include "alloc-util.h"
cf0fbc49 6#include "bus-error.h"
07630cea 7#include "errno-list.h"
2b2fec7d 8#include "errno-util.h"
07630cea 9#include "string-util.h"
de1c301e 10
96aad8d1 11BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = {
91053fc9
ZJS
12 SD_BUS_ERROR_MAP(SD_BUS_ERROR_FAILED, EACCES),
13 SD_BUS_ERROR_MAP(SD_BUS_ERROR_NO_MEMORY, ENOMEM),
14 SD_BUS_ERROR_MAP(SD_BUS_ERROR_SERVICE_UNKNOWN, EHOSTUNREACH),
15 SD_BUS_ERROR_MAP(SD_BUS_ERROR_NAME_HAS_NO_OWNER, ENXIO),
16 SD_BUS_ERROR_MAP(SD_BUS_ERROR_NO_REPLY, ETIMEDOUT),
17 SD_BUS_ERROR_MAP(SD_BUS_ERROR_IO_ERROR, EIO),
18 SD_BUS_ERROR_MAP(SD_BUS_ERROR_BAD_ADDRESS, EADDRNOTAVAIL),
19 SD_BUS_ERROR_MAP(SD_BUS_ERROR_NOT_SUPPORTED, EOPNOTSUPP),
20 SD_BUS_ERROR_MAP(SD_BUS_ERROR_LIMITS_EXCEEDED, ENOBUFS),
21 SD_BUS_ERROR_MAP(SD_BUS_ERROR_ACCESS_DENIED, EACCES),
22 SD_BUS_ERROR_MAP(SD_BUS_ERROR_AUTH_FAILED, EACCES),
23 SD_BUS_ERROR_MAP(SD_BUS_ERROR_NO_SERVER, EHOSTDOWN),
24 SD_BUS_ERROR_MAP(SD_BUS_ERROR_TIMEOUT, ETIMEDOUT),
25 SD_BUS_ERROR_MAP(SD_BUS_ERROR_NO_NETWORK, ENONET),
26 SD_BUS_ERROR_MAP(SD_BUS_ERROR_ADDRESS_IN_USE, EADDRINUSE),
27 SD_BUS_ERROR_MAP(SD_BUS_ERROR_DISCONNECTED, ECONNRESET),
28 SD_BUS_ERROR_MAP(SD_BUS_ERROR_INVALID_ARGS, EINVAL),
29 SD_BUS_ERROR_MAP(SD_BUS_ERROR_FILE_NOT_FOUND, ENOENT),
30 SD_BUS_ERROR_MAP(SD_BUS_ERROR_FILE_EXISTS, EEXIST),
31 SD_BUS_ERROR_MAP(SD_BUS_ERROR_UNKNOWN_METHOD, EBADR),
32 SD_BUS_ERROR_MAP(SD_BUS_ERROR_UNKNOWN_OBJECT, EBADR),
33 SD_BUS_ERROR_MAP(SD_BUS_ERROR_UNKNOWN_INTERFACE, EBADR),
34 SD_BUS_ERROR_MAP(SD_BUS_ERROR_UNKNOWN_PROPERTY, EBADR),
35 SD_BUS_ERROR_MAP(SD_BUS_ERROR_PROPERTY_READ_ONLY, EROFS),
36 SD_BUS_ERROR_MAP(SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, ESRCH),
37 SD_BUS_ERROR_MAP(SD_BUS_ERROR_INVALID_SIGNATURE, EINVAL),
38 SD_BUS_ERROR_MAP(SD_BUS_ERROR_INCONSISTENT_MESSAGE, EBADMSG),
39 SD_BUS_ERROR_MAP(SD_BUS_ERROR_TIMED_OUT, ETIMEDOUT),
40 SD_BUS_ERROR_MAP(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, ENOENT),
41 SD_BUS_ERROR_MAP(SD_BUS_ERROR_MATCH_RULE_INVALID, EINVAL),
42 SD_BUS_ERROR_MAP(SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, EACCES),
43 SD_BUS_ERROR_MAP(SD_BUS_ERROR_INVALID_FILE_CONTENT, EINVAL),
44 SD_BUS_ERROR_MAP(SD_BUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN, ESRCH),
45 SD_BUS_ERROR_MAP(SD_BUS_ERROR_OBJECT_PATH_IN_USE, EBUSY),
5f86c1f4 46 SD_BUS_ERROR_MAP_END
4a0a7417
ZJS
47};
48
780950a2 49/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section */
a8986035
LP
50extern const sd_bus_error_map __start_SYSTEMD_BUS_ERROR_MAP[];
51extern const sd_bus_error_map __stop_SYSTEMD_BUS_ERROR_MAP[];
4a0a7417 52
5f86c1f4
LP
53/* Additional maps registered with sd_bus_error_add_map() are in this
54 * NULL terminated array */
55static const sd_bus_error_map **additional_error_maps = NULL;
4a0a7417 56
780896a4
LP
57static int bus_error_name_to_errno(const char *name) {
58 const char *p;
59 int r;
60
d319cbea 61 assert_return(name, EINVAL);
780896a4 62
763e20e6 63 p = startswith(name, "System.Error.");
780896a4
LP
64 if (p) {
65 r = errno_from_name(p);
d469dd44 66 if (r < 0)
780896a4
LP
67 return EIO;
68
69 return r;
70 }
71
d469dd44 72 if (additional_error_maps)
d319cbea
MY
73 for (const sd_bus_error_map **map = additional_error_maps; *map; map++)
74 for (const sd_bus_error_map *m = *map;; m++) {
5f86c1f4
LP
75 /* For additional error maps the end marker is actually the end marker */
76 if (m->code == BUS_ERROR_MAP_END_MARKER)
77 break;
78
c7e964c9
ZJS
79 if (streq(m->name, name)) {
80 assert(m->code > 0);
5f86c1f4 81 return m->code;
c7e964c9 82 }
5f86c1f4 83 }
5f86c1f4 84
d319cbea
MY
85 const sd_bus_error_map *elf_map = ALIGN_PTR(__start_SYSTEMD_BUS_ERROR_MAP);
86 while (elf_map < __stop_SYSTEMD_BUS_ERROR_MAP) {
87 /* For magic ELF error maps, the end marker might appear in the middle of things, since
88 * multiple maps might appear in the same section. Hence, let's skip over it, but realign
89 * the pointer to the next 8 byte boundary, which is the selected alignment for the arrays. */
90 if (elf_map->code == BUS_ERROR_MAP_END_MARKER) {
91 elf_map = ALIGN_PTR(elf_map + 1);
5f86c1f4
LP
92 continue;
93 }
94
d319cbea
MY
95 if (streq(elf_map->name, name)) {
96 assert(elf_map->code > 0);
97 return elf_map->code;
c7e964c9 98 }
5f86c1f4 99
d319cbea 100 elf_map++;
5f86c1f4
LP
101 }
102
103 return EIO;
780896a4
LP
104}
105
106static sd_bus_error errno_to_bus_error_const(int error) {
107
108 if (error < 0)
109 error = -error;
110
111 switch (error) {
112
113 case ENOMEM:
114 return BUS_ERROR_OOM;
115
116 case EPERM:
117 case EACCES:
118 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_ACCESS_DENIED, "Access denied");
119
120 case EINVAL:
121 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid argument");
122
123 case ESRCH:
124 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, "No such process");
125
126 case ENOENT:
127 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_NOT_FOUND, "File not found");
128
129 case EEXIST:
130 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "File exists");
131
132 case ETIMEDOUT:
133 case ETIME:
134 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_TIMEOUT, "Timed out");
135
136 case EIO:
137 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_IO_ERROR, "Input/output error");
138
139 case ENETRESET:
140 case ECONNABORTED:
141 case ECONNRESET:
142 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_DISCONNECTED, "Disconnected");
143
15411c0c 144 case EOPNOTSUPP:
780896a4
LP
145 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NOT_SUPPORTED, "Not supported");
146
147 case EADDRNOTAVAIL:
148 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_BAD_ADDRESS, "Address not available");
149
150 case ENOBUFS:
151 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_LIMITS_EXCEEDED, "Limits exceeded");
152
153 case EADDRINUSE:
154 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_ADDRESS_IN_USE, "Address in use");
155
156 case EBADMSG:
157 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Inconsistent message");
158 }
159
160 return SD_BUS_ERROR_NULL;
161}
162
163static int errno_to_bus_error_name_new(int error, char **ret) {
164 const char *name;
165 char *n;
166
167 if (error < 0)
168 error = -error;
169
170 name = errno_to_name(error);
171 if (!name)
172 return 0;
173
b910cc72 174 n = strjoin("System.Error.", name);
780896a4
LP
175 if (!n)
176 return -ENOMEM;
177
178 *ret = n;
179 return 1;
180}
181
fbfa72b0
LP
182bool bus_error_is_dirty(sd_bus_error *e) {
183 if (!e)
780896a4 184 return false;
fbfa72b0 185
79f8d3d2 186 return e->name || e->message || e->_need_free != 0;
fbfa72b0
LP
187}
188
d9f644e2 189_public_ void sd_bus_error_free(sd_bus_error *e) {
de1c301e
LP
190 if (!e)
191 return;
192
79f8d3d2 193 if (e->_need_free > 0) {
de1c301e
LP
194 free((void*) e->name);
195 free((void*) e->message);
196 }
197
e559eca1 198 *e = SD_BUS_ERROR_NULL;
de1c301e
LP
199}
200
d9f644e2 201_public_ int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message) {
f1e7cbae 202 int r;
29ddb38f 203
780896a4 204 if (!name)
29ddb38f 205 return 0;
40ca29a1 206
f1e7cbae
ZJS
207 if (e) {
208 assert_return(!bus_error_is_dirty(e), -EINVAL);
29ddb38f 209
f1e7cbae
ZJS
210 e->name = strdup(name);
211 if (!e->name) {
212 *e = BUS_ERROR_OOM;
213 return -ENOMEM;
214 }
29ddb38f 215
f1e7cbae
ZJS
216 if (message)
217 e->message = strdup(message);
780896a4 218
f1e7cbae
ZJS
219 e->_need_free = 1;
220 }
29ddb38f 221
f1e7cbae
ZJS
222 r = bus_error_name_to_errno(name);
223 assert(r > 0);
224 return -r;
29ddb38f
LP
225}
226
fc69fab5 227_public_ int sd_bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) {
b9c19bc3 228 int r;
de1c301e 229
780896a4 230 if (!name)
de1c301e 231 return 0;
40ca29a1 232
d469dd44
ZJS
233 if (e) {
234 assert_return(!bus_error_is_dirty(e), -EINVAL);
de1c301e 235
d469dd44
ZJS
236 e->name = strdup(name);
237 if (!e->name) {
238 *e = BUS_ERROR_OOM;
239 return -ENOMEM;
240 }
de1c301e 241
12619d0a
ZJS
242 if (format) {
243 _cleanup_free_ char *mesg = NULL;
244
245 /* If we hit OOM on formatting the pretty message, we ignore
246 * this, since we at least managed to write the error name */
247
248 if (vasprintf(&mesg, format, ap) >= 0)
249 e->message = TAKE_PTR(mesg);
250 }
780896a4 251
d469dd44
ZJS
252 e->_need_free = 1;
253 }
de1c301e 254
b9c19bc3
ZJS
255 r = bus_error_name_to_errno(name);
256 assert(r > 0);
257 return -r;
de1c301e
LP
258}
259
d9f644e2 260_public_ int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...) {
b9c19bc3 261 int r;
40ca29a1
LP
262
263 if (format) {
40ca29a1
LP
264 va_list ap;
265
266 va_start(ap, format);
fc69fab5 267 r = sd_bus_error_setfv(e, name, format, ap);
41733186
ZJS
268 if (name)
269 assert(r < 0);
40ca29a1
LP
270 va_end(ap);
271
272 return r;
273 }
274
b9c19bc3 275 r = sd_bus_error_set(e, name, NULL);
41733186
ZJS
276 if (name)
277 assert(r < 0);
b9c19bc3 278 return r;
40ca29a1
LP
279}
280
d9f644e2 281_public_ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) {
89ffcd2a 282
de1c301e
LP
283 if (!sd_bus_error_is_set(e))
284 return 0;
780896a4
LP
285 if (!dest)
286 goto finish;
de1c301e 287
40ca29a1
LP
288 assert_return(!bus_error_is_dirty(dest), -EINVAL);
289
79f8d3d2
LP
290 /*
291 * _need_free < 0 indicates that the error is temporarily const, needs deep copying
292 * _need_free == 0 indicates that the error is perpetually const, needs no deep copying
293 * _need_free > 0 indicates that the error is fully dynamic, needs deep copying
294 */
295
296 if (e->_need_free == 0)
780896a4
LP
297 *dest = *e;
298 else {
299 dest->name = strdup(e->name);
300 if (!dest->name) {
301 *dest = BUS_ERROR_OOM;
de1c301e 302 return -ENOMEM;
de1c301e 303 }
780896a4
LP
304
305 if (e->message)
306 dest->message = strdup(e->message);
307
79f8d3d2 308 dest->_need_free = 1;
89ffcd2a 309 }
de1c301e 310
780896a4
LP
311finish:
312 return -bus_error_name_to_errno(e->name);
de1c301e
LP
313}
314
190128e4
LP
315_public_ int sd_bus_error_move(sd_bus_error *dest, sd_bus_error *e) {
316 int r;
317
318 if (!sd_bus_error_is_set(e)) {
319
320 if (dest)
321 *dest = SD_BUS_ERROR_NULL;
322
323 return 0;
324 }
325
326 r = -bus_error_name_to_errno(e->name);
327
328 if (dest) {
329 *dest = *e;
330 *e = SD_BUS_ERROR_NULL;
331 } else
332 sd_bus_error_free(e);
333
334 return r;
335}
336
d9f644e2 337_public_ int sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) {
780896a4 338 if (!name)
40ca29a1 339 return 0;
780896a4
LP
340 if (!e)
341 goto finish;
40ca29a1
LP
342
343 assert_return(!bus_error_is_dirty(e), -EINVAL);
de1c301e 344
14c24659 345 *e = SD_BUS_ERROR_MAKE_CONST(name, message);
780896a4
LP
346
347finish:
348 return -bus_error_name_to_errno(name);
de1c301e
LP
349}
350
d9f644e2 351_public_ int sd_bus_error_is_set(const sd_bus_error *e) {
de1c301e
LP
352 if (!e)
353 return 0;
354
fbfa72b0 355 return !!e->name;
de1c301e
LP
356}
357
d9f644e2 358_public_ int sd_bus_error_has_name(const sd_bus_error *e, const char *name) {
de1c301e
LP
359 if (!e)
360 return 0;
361
362 return streq_ptr(e->name, name);
363}
364
2b07ec31
ZJS
365_public_ int sd_bus_error_has_names_sentinel(const sd_bus_error *e, ...) {
366 if (!e || !e->name)
780896a4 367 return 0;
40ca29a1 368
2b07ec31
ZJS
369 va_list ap;
370 const char *p;
371
372 va_start(ap, e);
373 while ((p = va_arg(ap, const char *)))
374 if (streq(p, e->name))
375 break;
376 va_end(ap);
377 return !!p;
378}
379
d319cbea 380_public_ int sd_bus_error_get_errno(const sd_bus_error *e) {
2b07ec31 381 if (!e || !e->name)
bc6a6232
LP
382 return 0;
383
780896a4 384 return bus_error_name_to_errno(e->name);
de1c301e
LP
385}
386
780896a4 387static void bus_error_strerror(sd_bus_error *e, int error) {
40ca29a1 388 size_t k = 64;
780896a4 389 char *m;
40ca29a1 390
780896a4 391 assert(e);
eb01ba5d 392
40ca29a1
LP
393 for (;;) {
394 char *x;
eb01ba5d 395
40ca29a1
LP
396 m = new(char, k);
397 if (!m)
780896a4 398 return;
40ca29a1
LP
399
400 errno = 0;
401 x = strerror_r(error, m, k);
402 if (errno == ERANGE || strlen(x) >= k - 1) {
403 free(m);
404 k *= 2;
405 continue;
406 }
eb01ba5d 407
04c553e3 408 if (errno) {
40ca29a1 409 free(m);
780896a4 410 return;
40ca29a1 411 }
eb01ba5d 412
780896a4 413 if (x == m) {
79f8d3d2 414 if (e->_need_free > 0) {
780896a4
LP
415 /* Error is already dynamic, let's just update the message */
416 free((char*) e->message);
417 e->message = x;
418
419 } else {
420 char *t;
421 /* Error was const so far, let's make it dynamic, if we can */
422
423 t = strdup(e->name);
424 if (!t) {
425 free(m);
426 return;
427 }
428
79f8d3d2 429 e->_need_free = 1;
780896a4
LP
430 e->name = t;
431 e->message = x;
432 }
433 } else {
40ca29a1 434 free(m);
eb01ba5d 435
79f8d3d2 436 if (e->_need_free > 0) {
780896a4 437 char *t;
eb01ba5d 438
780896a4
LP
439 /* Error is dynamic, let's hence make the message also dynamic */
440 t = strdup(x);
441 if (!t)
442 return;
eb01ba5d 443
780896a4
LP
444 free((char*) e->message);
445 e->message = t;
446 } else {
447 /* Error is const, hence we can just override */
448 e->message = x;
449 }
450 }
40ca29a1 451
780896a4
LP
452 return;
453 }
40ca29a1
LP
454}
455
780896a4 456_public_ int sd_bus_error_set_errno(sd_bus_error *e, int error) {
40ca29a1
LP
457
458 if (error < 0)
459 error = -error;
460
780896a4
LP
461 if (!e)
462 return -error;
463 if (error == 0)
af46237e 464 return 0;
40ca29a1 465
780896a4 466 assert_return(!bus_error_is_dirty(e), -EINVAL);
40ca29a1 467
780896a4
LP
468 /* First, try a const translation */
469 *e = errno_to_bus_error_const(error);
40ca29a1 470
780896a4
LP
471 if (!sd_bus_error_is_set(e)) {
472 int k;
40ca29a1 473
780896a4 474 /* If that didn't work, try a dynamic one. */
40ca29a1 475
780896a4
LP
476 k = errno_to_bus_error_name_new(error, (char**) &e->name);
477 if (k > 0)
79f8d3d2 478 e->_need_free = 1;
780896a4
LP
479 else if (k < 0) {
480 *e = BUS_ERROR_OOM;
481 return -error;
482 } else
483 *e = BUS_ERROR_FAILED;
40ca29a1
LP
484 }
485
eaaf7465 486 /* Now, fill in the message from strerror_r() if we can */
780896a4
LP
487 bus_error_strerror(e, error);
488 return -error;
40ca29a1
LP
489}
490
07a0d22f 491_public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) {
17972801 492 PROTECT_ERRNO;
40ca29a1
LP
493
494 if (error < 0)
495 error = -error;
496
497 if (!e)
80c19740 498 return -error;
780896a4
LP
499 if (error == 0)
500 return 0;
40ca29a1
LP
501
502 assert_return(!bus_error_is_dirty(e), -EINVAL);
503
780896a4
LP
504 /* First, try a const translation */
505 *e = errno_to_bus_error_const(error);
506
507 if (!sd_bus_error_is_set(e)) {
508 int k;
509
510 /* If that didn't work, try a dynamic one */
511
512 k = errno_to_bus_error_name_new(error, (char**) &e->name);
513 if (k > 0)
79f8d3d2 514 e->_need_free = 1;
780896a4
LP
515 else if (k < 0) {
516 *e = BUS_ERROR_OOM;
517 return -ENOMEM;
518 } else
519 *e = BUS_ERROR_FAILED;
520 }
40ca29a1
LP
521
522 if (format) {
caf4ba83 523 _cleanup_free_ char *m = NULL;
40ca29a1 524
17972801 525 /* Then, let's try to fill in the supplied message */
40ca29a1 526
17972801 527 errno = error; /* Make sure that %m resolves to the specified error */
caf4ba83
YW
528 if (vasprintf(&m, format, ap) < 0)
529 goto fail;
780896a4 530
caf4ba83
YW
531 if (e->_need_free <= 0) {
532 char *t;
780896a4 533
caf4ba83
YW
534 t = strdup(e->name);
535 if (!t)
536 goto fail;
780896a4 537
caf4ba83
YW
538 e->_need_free = 1;
539 e->name = t;
40ca29a1 540 }
caf4ba83
YW
541
542 e->message = TAKE_PTR(m);
543 return -error;
eb01ba5d 544 }
de1c301e 545
caf4ba83 546fail:
eaaf7465 547 /* If that didn't work, use strerror_r() for the message */
780896a4
LP
548 bus_error_strerror(e, error);
549 return -error;
40ca29a1
LP
550}
551
d9f644e2 552_public_ int sd_bus_error_set_errnof(sd_bus_error *e, int error, const char *format, ...) {
40ca29a1
LP
553 int r;
554
80c19740
LP
555 if (error < 0)
556 error = -error;
557
40ca29a1 558 if (!e)
80c19740 559 return -error;
780896a4
LP
560 if (error == 0)
561 return 0;
40ca29a1
LP
562
563 assert_return(!bus_error_is_dirty(e), -EINVAL);
564
565 if (format) {
566 va_list ap;
567
568 va_start(ap, format);
07a0d22f 569 r = sd_bus_error_set_errnofv(e, error, format, ap);
40ca29a1
LP
570 va_end(ap);
571
572 return r;
573 }
574
575 return sd_bus_error_set_errno(e, error);
de1c301e 576}
e3017af9 577
eaaf7465 578const char* _bus_error_message(const sd_bus_error *e, int error, char buf[static ERRNO_BUF_LEN]) {
b0fcb7c0
ZJS
579 /* Sometimes, the D-Bus server is a little bit too verbose with
580 * its error messages, so let's override them here */
581 if (sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED))
582 return "Access denied";
40ca29a1 583
b0fcb7c0
ZJS
584 if (e && e->message)
585 return e->message;
c9b6cb28 586
5cdf13c7 587 return strerror_r(ABS(error), buf, ERRNO_BUF_LEN);
e3017af9 588}
5f86c1f4 589
45ea6583
ZJS
590static bool map_ok(const sd_bus_error_map *map) {
591 for (; map->code != BUS_ERROR_MAP_END_MARKER; map++)
22185cb7 592 if (!map->name || map->code <= 0)
45ea6583
ZJS
593 return false;
594 return true;
595}
596
5f86c1f4 597_public_ int sd_bus_error_add_map(const sd_bus_error_map *map) {
5f86c1f4
LP
598 unsigned n = 0;
599
600 assert_return(map, -EINVAL);
45ea6583 601 assert_return(map_ok(map), -EINVAL);
5f86c1f4 602
45ea6583
ZJS
603 if (additional_error_maps)
604 for (; additional_error_maps[n] != NULL; n++)
5f86c1f4
LP
605 if (additional_error_maps[n] == map)
606 return 0;
5f86c1f4 607
223a67e5 608 if (!GREEDY_REALLOC(additional_error_maps, n + 2))
5f86c1f4
LP
609 return -ENOMEM;
610
223a67e5
YW
611 additional_error_maps[n] = map;
612 additional_error_maps[n+1] = NULL;
5f86c1f4 613
5f86c1f4
LP
614 return 1;
615}