LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-error.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 203 300 67.7 %
Date: 2019-08-23 13:36:53 Functions: 20 21 95.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 128 219 58.4 %

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

Generated by: LCOV version 1.14