LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-error.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 189 272 69.5 %
Date: 2015-07-29 18:47:03 Functions: 19 19 100.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2013 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include <errno.h>
      23             : #include <stdlib.h>
      24             : #include <stdarg.h>
      25             : #include <stdbool.h>
      26             : #include <string.h>
      27             : #include <stdio.h>
      28             : 
      29             : #include "util.h"
      30             : #include "errno-list.h"
      31             : 
      32             : #include "sd-bus.h"
      33             : #include "bus-error.h"
      34             : 
      35             : BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = {
      36             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Failed",                           EACCES),
      37             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoMemory",                         ENOMEM),
      38             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ServiceUnknown",                   EHOSTUNREACH),
      39             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NameHasNoOwner",                   ENXIO),
      40             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoReply",                          ETIMEDOUT),
      41             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.IOError",                          EIO),
      42             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.BadAddress",                       EADDRNOTAVAIL),
      43             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NotSupported",                     EOPNOTSUPP),
      44             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.LimitsExceeded",                   ENOBUFS),
      45             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AccessDenied",                     EACCES),
      46             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AuthFailed",                       EACCES),
      47             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InteractiveAuthorizationRequired", EACCES),
      48             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoServer",                         EHOSTDOWN),
      49             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Timeout",                          ETIMEDOUT),
      50             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoNetwork",                        ENONET),
      51             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AddressInUse",                     EADDRINUSE),
      52             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Disconnected",                     ECONNRESET),
      53             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidArgs",                      EINVAL),
      54             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.FileNotFound",                     ENOENT),
      55             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.FileExists",                       EEXIST),
      56             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownMethod",                    EBADR),
      57             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownObject",                    EBADR),
      58             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownInterface",                 EBADR),
      59             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownProperty",                  EBADR),
      60             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.PropertyReadOnly",                 EROFS),
      61             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnixProcessIdUnknown",             ESRCH),
      62             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidSignature",                 EINVAL),
      63             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InconsistentMessage",              EBADMSG),
      64             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.TimedOut",                         ETIMEDOUT),
      65             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.MatchRuleInvalid",                 EINVAL),
      66             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidFileContent",               EINVAL),
      67             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.MatchRuleNotFound",                ENOENT),
      68             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown",    ESRCH),
      69             :         SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ObjectPathInUse",                  EBUSY),
      70             :         SD_BUS_ERROR_MAP_END
      71             : };
      72             : 
      73             : /* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section.
      74             :  * Hide them; for currently unknown reasons they get exported to the shared libries
      75             :  * even without being listed in the sym file. */
      76             : extern const sd_bus_error_map __start_BUS_ERROR_MAP[] _hidden_;
      77             : extern const sd_bus_error_map __stop_BUS_ERROR_MAP[] _hidden_;
      78             : 
      79             : /* Additional maps registered with sd_bus_error_add_map() are in this
      80             :  * NULL terminated array */
      81             : static const sd_bus_error_map **additional_error_maps = NULL;
      82             : 
      83          88 : static int bus_error_name_to_errno(const char *name) {
      84             :         const sd_bus_error_map **map, *m;
      85             :         const char *p;
      86             :         int r;
      87             : 
      88          88 :         if (!name)
      89           0 :                 return EINVAL;
      90             : 
      91          88 :         p = startswith(name, "System.Error.");
      92          88 :         if (p) {
      93           7 :                 r = errno_from_name(p);
      94           7 :                 if (r <= 0)
      95           1 :                         return EIO;
      96             : 
      97           6 :                 return r;
      98             :         }
      99             : 
     100          81 :         if (additional_error_maps) {
     101          15 :                 for (map = additional_error_maps; *map; map++) {
     102          30 :                         for (m = *map;; m++) {
     103             :                                 /* For additional error maps the end marker is actually the end marker */
     104          30 :                                 if (m->code == BUS_ERROR_MAP_END_MARKER)
     105           8 :                                         break;
     106             : 
     107          22 :                                 if (streq(m->name, name))
     108           4 :                                         return m->code;
     109          18 :                         }
     110             :                 }
     111             :         }
     112             : 
     113          77 :         m = __start_BUS_ERROR_MAP;
     114        1630 :         while (m < __stop_BUS_ERROR_MAP) {
     115             :                 /* For magic ELF error maps, the end marker might
     116             :                  * appear in the middle of things, since multiple maps
     117             :                  * might appear in the same section. Hence, let's skip
     118             :                  * over it, but realign the pointer to the netx 8byte
     119             :                  * boundary, which is the selected alignment for the
     120             :                  * arrays. */
     121        1548 :                 if (m->code == BUS_ERROR_MAP_END_MARKER) {
     122          56 :                         m = ALIGN8_PTR(m+1);
     123          56 :                         continue;
     124             :                 }
     125             : 
     126        1492 :                 if (streq(m->name, name))
     127          72 :                         return m->code;
     128             : 
     129        1420 :                 m++;
     130             :         }
     131             : 
     132           5 :         return EIO;
     133             : }
     134             : 
     135           2 : static sd_bus_error errno_to_bus_error_const(int error) {
     136             : 
     137           2 :         if (error < 0)
     138           0 :                 error = -error;
     139             : 
     140           2 :         switch (error) {
     141             : 
     142             :         case ENOMEM:
     143           0 :                 return BUS_ERROR_OOM;
     144             : 
     145             :         case EPERM:
     146             :         case EACCES:
     147           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_ACCESS_DENIED, "Access denied");
     148             : 
     149             :         case EINVAL:
     150           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid argument");
     151             : 
     152             :         case ESRCH:
     153           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, "No such process");
     154             : 
     155             :         case ENOENT:
     156           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_NOT_FOUND, "File not found");
     157             : 
     158             :         case EEXIST:
     159           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "File exists");
     160             : 
     161             :         case ETIMEDOUT:
     162             :         case ETIME:
     163           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_TIMEOUT, "Timed out");
     164             : 
     165             :         case EIO:
     166           1 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_IO_ERROR, "Input/output error");
     167             : 
     168             :         case ENETRESET:
     169             :         case ECONNABORTED:
     170             :         case ECONNRESET:
     171           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_DISCONNECTED, "Disconnected");
     172             : 
     173             :         case EOPNOTSUPP:
     174           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NOT_SUPPORTED, "Not supported");
     175             : 
     176             :         case EADDRNOTAVAIL:
     177           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_BAD_ADDRESS, "Address not available");
     178             : 
     179             :         case ENOBUFS:
     180           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_LIMITS_EXCEEDED, "Limits exceeded");
     181             : 
     182             :         case EADDRINUSE:
     183           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_ADDRESS_IN_USE, "Address in use");
     184             : 
     185             :         case EBADMSG:
     186           0 :                 return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Inconsistent message");
     187             :         }
     188             : 
     189           1 :         return SD_BUS_ERROR_NULL;
     190             : }
     191             : 
     192           1 : static int errno_to_bus_error_name_new(int error, char **ret) {
     193             :         const char *name;
     194             :         char *n;
     195             : 
     196           1 :         if (error < 0)
     197           0 :                 error = -error;
     198             : 
     199           1 :         name = errno_to_name(error);
     200           1 :         if (!name)
     201           0 :                 return 0;
     202             : 
     203           1 :         n = strappend("System.Error.", name);
     204           1 :         if (!n)
     205           0 :                 return -ENOMEM;
     206             : 
     207           1 :         *ret = n;
     208           1 :         return 1;
     209             : }
     210             : 
     211          79 : bool bus_error_is_dirty(sd_bus_error *e) {
     212          79 :         if (!e)
     213           2 :                 return false;
     214             : 
     215          77 :         return e->name || e->message || e->_need_free != 0;
     216             : }
     217             : 
     218       62354 : _public_ void sd_bus_error_free(sd_bus_error *e) {
     219       62354 :         if (!e)
     220          21 :                 return;
     221             : 
     222       62333 :         if (e->_need_free > 0) {
     223          37 :                 free((void*) e->name);
     224          37 :                 free((void*) e->message);
     225             :         }
     226             : 
     227       62333 :         e->name = e->message = NULL;
     228       62333 :         e->_need_free = 0;
     229             : }
     230             : 
     231          19 : _public_ int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message) {
     232             : 
     233          19 :         if (!name)
     234           0 :                 return 0;
     235          19 :         if (!e)
     236          18 :                 goto finish;
     237             : 
     238           1 :         assert_return(!bus_error_is_dirty(e), -EINVAL);
     239             : 
     240           1 :         e->name = strdup(name);
     241           1 :         if (!e->name) {
     242           0 :                 *e = BUS_ERROR_OOM;
     243           0 :                 return -ENOMEM;
     244             :         }
     245             : 
     246           1 :         if (message)
     247           1 :                 e->message = strdup(message);
     248             : 
     249           1 :         e->_need_free = 1;
     250             : 
     251             : finish:
     252          19 :         return -bus_error_name_to_errno(name);
     253             : }
     254             : 
     255          51 : int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) {
     256             : 
     257          51 :         if (!name)
     258           0 :                 return 0;
     259          51 :         if (!e)
     260          24 :                 goto finish;
     261             : 
     262          27 :         assert_return(!bus_error_is_dirty(e), -EINVAL);
     263             : 
     264          27 :         e->name = strdup(name);
     265          27 :         if (!e->name) {
     266           0 :                 *e = BUS_ERROR_OOM;
     267           0 :                 return -ENOMEM;
     268             :         }
     269             : 
     270             :         /* If we hit OOM on formatting the pretty message, we ignore
     271             :          * this, since we at least managed to write the error name */
     272          27 :         if (format)
     273          27 :                 (void) vasprintf((char**) &e->message, format, ap);
     274             : 
     275          27 :         e->_need_free = 1;
     276             : 
     277             : finish:
     278          51 :         return -bus_error_name_to_errno(name);
     279             : }
     280             : 
     281          47 : _public_ int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...) {
     282             : 
     283          47 :         if (format) {
     284             :                 int r;
     285             :                 va_list ap;
     286             : 
     287          47 :                 va_start(ap, format);
     288          47 :                 r = bus_error_setfv(e, name, format, ap);
     289          47 :                 va_end(ap);
     290             : 
     291          47 :                 return r;
     292             :         }
     293             : 
     294           0 :         return sd_bus_error_set(e, name, NULL);
     295             : }
     296             : 
     297           8 : _public_ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) {
     298             : 
     299           8 :         if (!sd_bus_error_is_set(e))
     300           0 :                 return 0;
     301           8 :         if (!dest)
     302           0 :                 goto finish;
     303             : 
     304           8 :         assert_return(!bus_error_is_dirty(dest), -EINVAL);
     305             : 
     306             :         /*
     307             :          * _need_free  < 0 indicates that the error is temporarily const, needs deep copying
     308             :          * _need_free == 0 indicates that the error is perpetually const, needs no deep copying
     309             :          * _need_free  > 0 indicates that the error is fully dynamic, needs deep copying
     310             :          */
     311             : 
     312           8 :         if (e->_need_free == 0)
     313           1 :                 *dest = *e;
     314             :         else {
     315           7 :                 dest->name = strdup(e->name);
     316           7 :                 if (!dest->name) {
     317           0 :                         *dest = BUS_ERROR_OOM;
     318           0 :                         return -ENOMEM;
     319             :                 }
     320             : 
     321           7 :                 if (e->message)
     322           7 :                         dest->message = strdup(e->message);
     323             : 
     324           7 :                 dest->_need_free = 1;
     325             :         }
     326             : 
     327             : finish:
     328           8 :         return -bus_error_name_to_errno(e->name);
     329             : }
     330             : 
     331           1 : _public_ int sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) {
     332           1 :         if (!name)
     333           0 :                 return 0;
     334           1 :         if (!e)
     335           0 :                 goto finish;
     336             : 
     337           1 :         assert_return(!bus_error_is_dirty(e), -EINVAL);
     338             : 
     339           1 :         *e = SD_BUS_ERROR_MAKE_CONST(name, message);
     340             : 
     341             : finish:
     342           1 :         return -bus_error_name_to_errno(name);
     343             : }
     344             : 
     345         145 : _public_ int sd_bus_error_is_set(const sd_bus_error *e) {
     346         145 :         if (!e)
     347           0 :                 return 0;
     348             : 
     349         145 :         return !!e->name;
     350             : }
     351             : 
     352          36 : _public_ int sd_bus_error_has_name(const sd_bus_error *e, const char *name) {
     353          36 :         if (!e)
     354           0 :                 return 0;
     355             : 
     356          36 :         return streq_ptr(e->name, name);
     357             : }
     358             : 
     359           9 : _public_ int sd_bus_error_get_errno(const sd_bus_error* e) {
     360           9 :         if (!e)
     361           0 :                 return 0;
     362             : 
     363           9 :         if (!e->name)
     364           0 :                 return 0;
     365             : 
     366           9 :         return bus_error_name_to_errno(e->name);
     367             : }
     368             : 
     369           1 : static void bus_error_strerror(sd_bus_error *e, int error) {
     370           1 :         size_t k = 64;
     371             :         char *m;
     372             : 
     373           1 :         assert(e);
     374             : 
     375             :         for (;;) {
     376             :                 char *x;
     377             : 
     378           1 :                 m = new(char, k);
     379           1 :                 if (!m)
     380           0 :                         return;
     381             : 
     382           1 :                 errno = 0;
     383           1 :                 x = strerror_r(error, m, k);
     384           1 :                 if (errno == ERANGE || strlen(x) >= k - 1) {
     385           0 :                         free(m);
     386           0 :                         k *= 2;
     387           0 :                         continue;
     388             :                 }
     389             : 
     390           1 :                 if (errno) {
     391           0 :                         free(m);
     392           0 :                         return;
     393             :                 }
     394             : 
     395           1 :                 if (x == m) {
     396           0 :                         if (e->_need_free > 0) {
     397             :                                 /* Error is already dynamic, let's just update the message */
     398           0 :                                 free((char*) e->message);
     399           0 :                                 e->message = x;
     400             : 
     401             :                         } else {
     402             :                                 char *t;
     403             :                                 /* Error was const so far, let's make it dynamic, if we can */
     404             : 
     405           0 :                                 t = strdup(e->name);
     406           0 :                                 if (!t) {
     407           0 :                                         free(m);
     408           0 :                                         return;
     409             :                                 }
     410             : 
     411           0 :                                 e->_need_free = 1;
     412           0 :                                 e->name = t;
     413           0 :                                 e->message = x;
     414             :                         }
     415             :                 } else {
     416           1 :                         free(m);
     417             : 
     418           1 :                         if (e->_need_free > 0) {
     419             :                                 char *t;
     420             : 
     421             :                                 /* Error is dynamic, let's hence make the message also dynamic */
     422           1 :                                 t = strdup(x);
     423           1 :                                 if (!t)
     424           0 :                                         return;
     425             : 
     426           1 :                                 free((char*) e->message);
     427           1 :                                 e->message = t;
     428             :                         } else {
     429             :                                 /* Error is const, hence we can just override */
     430           0 :                                 e->message = x;
     431             :                         }
     432             :                 }
     433             : 
     434           1 :                 return;
     435           0 :         }
     436             : }
     437             : 
     438           1 : _public_ int sd_bus_error_set_errno(sd_bus_error *e, int error) {
     439             : 
     440           1 :         if (error < 0)
     441           0 :                 error = -error;
     442             : 
     443           1 :         if (!e)
     444           0 :                 return -error;
     445           1 :         if (error == 0)
     446           0 :                 return -error;
     447             : 
     448           1 :         assert_return(!bus_error_is_dirty(e), -EINVAL);
     449             : 
     450             :         /* First, try a const translation */
     451           1 :         *e = errno_to_bus_error_const(error);
     452             : 
     453           1 :         if (!sd_bus_error_is_set(e)) {
     454             :                 int k;
     455             : 
     456             :                 /* If that didn't work, try a dynamic one. */
     457             : 
     458           1 :                 k = errno_to_bus_error_name_new(error, (char**) &e->name);
     459           1 :                 if (k > 0)
     460           1 :                         e->_need_free = 1;
     461           0 :                 else if (k < 0) {
     462           0 :                         *e = BUS_ERROR_OOM;
     463           0 :                         return -error;
     464             :                 } else
     465           0 :                         *e = BUS_ERROR_FAILED;
     466             :         }
     467             : 
     468             :         /* Now, fill in the message from strerror() if we can */
     469           1 :         bus_error_strerror(e, error);
     470           1 :         return -error;
     471             : }
     472             : 
     473           1 : _public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) {
     474           2 :         PROTECT_ERRNO;
     475             :         int r;
     476             : 
     477           1 :         if (error < 0)
     478           0 :                 error = -error;
     479             : 
     480           1 :         if (!e)
     481           0 :                 return -error;
     482           1 :         if (error == 0)
     483           0 :                 return 0;
     484             : 
     485           1 :         assert_return(!bus_error_is_dirty(e), -EINVAL);
     486             : 
     487             :         /* First, try a const translation */
     488           1 :         *e = errno_to_bus_error_const(error);
     489             : 
     490           1 :         if (!sd_bus_error_is_set(e)) {
     491             :                 int k;
     492             : 
     493             :                 /* If that didn't work, try a dynamic one */
     494             : 
     495           0 :                 k = errno_to_bus_error_name_new(error, (char**) &e->name);
     496           0 :                 if (k > 0)
     497           0 :                         e->_need_free = 1;
     498           0 :                 else if (k < 0) {
     499           0 :                         *e = BUS_ERROR_OOM;
     500           0 :                         return -ENOMEM;
     501             :                 } else
     502           0 :                         *e = BUS_ERROR_FAILED;
     503             :         }
     504             : 
     505           1 :         if (format) {
     506             :                 char *m;
     507             : 
     508             :                 /* Then, let's try to fill in the supplied message */
     509             : 
     510           1 :                 errno = error; /* Make sure that %m resolves to the specified error */
     511           1 :                 r = vasprintf(&m, format, ap);
     512           1 :                 if (r >= 0) {
     513             : 
     514           1 :                         if (e->_need_free <= 0) {
     515             :                                 char *t;
     516             : 
     517           1 :                                 t = strdup(e->name);
     518           1 :                                 if (t) {
     519           1 :                                         e->_need_free = 1;
     520           1 :                                         e->name = t;
     521           1 :                                         e->message = m;
     522           2 :                                         return -error;
     523             :                                 }
     524             : 
     525           0 :                                 free(m);
     526             :                         } else {
     527           0 :                                 free((char*) e->message);
     528           0 :                                 e->message = m;
     529           0 :                                 return -error;
     530             :                         }
     531             :                 }
     532             :         }
     533             : 
     534             :         /* If that didn't work, use strerror() for the message */
     535           0 :         bus_error_strerror(e, error);
     536           0 :         return -error;
     537             : }
     538             : 
     539           1 : _public_ int sd_bus_error_set_errnof(sd_bus_error *e, int error, const char *format, ...) {
     540             :         int r;
     541             : 
     542           1 :         if (error < 0)
     543           0 :                 error = -error;
     544             : 
     545           1 :         if (!e)
     546           0 :                 return -error;
     547           1 :         if (error == 0)
     548           0 :                 return 0;
     549             : 
     550           1 :         assert_return(!bus_error_is_dirty(e), -EINVAL);
     551             : 
     552           1 :         if (format) {
     553             :                 va_list ap;
     554             : 
     555           1 :                 va_start(ap, format);
     556           1 :                 r = sd_bus_error_set_errnofv(e, error, format, ap);
     557           1 :                 va_end(ap);
     558             : 
     559           1 :                 return r;
     560             :         }
     561             : 
     562           0 :         return sd_bus_error_set_errno(e, error);
     563             : }
     564             : 
     565          47 : const char *bus_error_message(const sd_bus_error *e, int error) {
     566             : 
     567          47 :         if (e) {
     568             :                 /* Sometimes the D-Bus server is a little bit too verbose with
     569             :                  * its error messages, so let's override them here */
     570          23 :                 if (sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED))
     571           0 :                         return "Access denied";
     572             : 
     573          23 :                 if (e->message)
     574          21 :                         return e->message;
     575             :         }
     576             : 
     577          26 :         if (error < 0)
     578          24 :                 error = -error;
     579             : 
     580          26 :         return strerror(error);
     581             : }
     582             : 
     583           4 : _public_ int sd_bus_error_add_map(const sd_bus_error_map *map) {
     584           4 :         const sd_bus_error_map **maps = NULL;
     585           4 :         unsigned n = 0;
     586             : 
     587           4 :         assert_return(map, -EINVAL);
     588             : 
     589           4 :         if (additional_error_maps) {
     590           2 :                 for (;; n++) {
     591           5 :                         if (additional_error_maps[n] == NULL)
     592           1 :                                 break;
     593             : 
     594           4 :                         if (additional_error_maps[n] == map)
     595           2 :                                 return 0;
     596           2 :                 }
     597             :         }
     598             : 
     599           2 :         maps = realloc_multiply(additional_error_maps, sizeof(struct sd_bus_error_map*), n + 2);
     600           2 :         if (!maps)
     601           0 :                 return -ENOMEM;
     602             : 
     603             : 
     604           2 :         maps[n] = map;
     605           2 :         maps[n+1] = NULL;
     606             : 
     607           2 :         additional_error_maps = maps;
     608           2 :         return 1;
     609             : }

Generated by: LCOV version 1.11