LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-gvariant.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 127 150 84.7 %
Date: 2019-08-22 15:41:25 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <string.h>
       5             : 
       6             : #include "sd-bus.h"
       7             : 
       8             : #include "bus-gvariant.h"
       9             : #include "bus-signature.h"
      10             : #include "bus-type.h"
      11             : 
      12         139 : int bus_gvariant_get_size(const char *signature) {
      13             :         const char *p;
      14         139 :         int sum = 0, r;
      15             : 
      16             :         /* For fixed size structs. Fails for variable size structs. */
      17             : 
      18         139 :         p = signature;
      19         259 :         while (*p != 0) {
      20             :                 size_t n;
      21             : 
      22         174 :                 r = signature_element_length(p, &n);
      23         174 :                 if (r < 0)
      24          54 :                         return r;
      25         173 :                 else {
      26         173 :                         char t[n+1];
      27             : 
      28         173 :                         memcpy(t, p, n);
      29         173 :                         t[n] = 0;
      30             : 
      31         173 :                         r = bus_gvariant_get_alignment(t);
      32         173 :                         if (r < 0)
      33           0 :                                 return r;
      34             : 
      35         173 :                         sum = ALIGN_TO(sum, r);
      36             :                 }
      37             : 
      38         173 :                 switch (*p) {
      39             : 
      40          19 :                 case SD_BUS_TYPE_BOOLEAN:
      41             :                 case SD_BUS_TYPE_BYTE:
      42          19 :                         sum += 1;
      43          19 :                         break;
      44             : 
      45           2 :                 case SD_BUS_TYPE_INT16:
      46             :                 case SD_BUS_TYPE_UINT16:
      47           2 :                         sum += 2;
      48           2 :                         break;
      49             : 
      50          60 :                 case SD_BUS_TYPE_INT32:
      51             :                 case SD_BUS_TYPE_UINT32:
      52             :                 case SD_BUS_TYPE_UNIX_FD:
      53          60 :                         sum += 4;
      54          60 :                         break;
      55             : 
      56          14 :                 case SD_BUS_TYPE_INT64:
      57             :                 case SD_BUS_TYPE_UINT64:
      58             :                 case SD_BUS_TYPE_DOUBLE:
      59          14 :                         sum += 8;
      60          14 :                         break;
      61             : 
      62          39 :                 case SD_BUS_TYPE_STRUCT_BEGIN:
      63             :                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
      64          39 :                         if (n == 2) {
      65             :                                 /* unary type () has fixed size of 1 */
      66           0 :                                 r = 1;
      67          39 :                         } else {
      68          39 :                                 char t[n-1];
      69             : 
      70          39 :                                 memcpy(t, p + 1, n - 2);
      71          39 :                                 t[n - 2] = 0;
      72             : 
      73          39 :                                 r = bus_gvariant_get_size(t);
      74          39 :                                 if (r < 0)
      75          14 :                                         return r;
      76             :                         }
      77             : 
      78          25 :                         sum += r;
      79          25 :                         break;
      80             :                 }
      81             : 
      82          39 :                 case SD_BUS_TYPE_STRING:
      83             :                 case SD_BUS_TYPE_OBJECT_PATH:
      84             :                 case SD_BUS_TYPE_SIGNATURE:
      85             :                 case SD_BUS_TYPE_ARRAY:
      86             :                 case SD_BUS_TYPE_VARIANT:
      87          39 :                         return -EINVAL;
      88             : 
      89           0 :                 default:
      90           0 :                         assert_not_reached("Unknown signature type");
      91             :                 }
      92             : 
      93         120 :                 p += n;
      94             :         }
      95             : 
      96          85 :         r = bus_gvariant_get_alignment(signature);
      97          85 :         if (r < 0)
      98           0 :                 return r;
      99             : 
     100          85 :         return ALIGN_TO(sum, r);
     101             : }
     102             : 
     103         562 : int bus_gvariant_get_alignment(const char *signature) {
     104         562 :         size_t alignment = 1;
     105             :         const char *p;
     106             :         int r;
     107             : 
     108         562 :         p = signature;
     109        1300 :         while (*p != 0 && alignment < 8) {
     110             :                 size_t n;
     111             :                 int a;
     112             : 
     113         739 :                 r = signature_element_length(p, &n);
     114         739 :                 if (r < 0)
     115           1 :                         return r;
     116             : 
     117         738 :                 switch (*p) {
     118             : 
     119         191 :                 case SD_BUS_TYPE_BYTE:
     120             :                 case SD_BUS_TYPE_BOOLEAN:
     121             :                 case SD_BUS_TYPE_STRING:
     122             :                 case SD_BUS_TYPE_OBJECT_PATH:
     123             :                 case SD_BUS_TYPE_SIGNATURE:
     124         191 :                         a = 1;
     125         191 :                         break;
     126             : 
     127           9 :                 case SD_BUS_TYPE_INT16:
     128             :                 case SD_BUS_TYPE_UINT16:
     129           9 :                         a = 2;
     130           9 :                         break;
     131             : 
     132         265 :                 case SD_BUS_TYPE_INT32:
     133             :                 case SD_BUS_TYPE_UINT32:
     134             :                 case SD_BUS_TYPE_UNIX_FD:
     135         265 :                         a = 4;
     136         265 :                         break;
     137             : 
     138         110 :                 case SD_BUS_TYPE_INT64:
     139             :                 case SD_BUS_TYPE_UINT64:
     140             :                 case SD_BUS_TYPE_DOUBLE:
     141             :                 case SD_BUS_TYPE_VARIANT:
     142         110 :                         a = 8;
     143         110 :                         break;
     144             : 
     145          21 :                 case SD_BUS_TYPE_ARRAY: {
     146          21 :                         char t[n];
     147             : 
     148          21 :                         memcpy(t, p + 1, n - 1);
     149          21 :                         t[n - 1] = 0;
     150             : 
     151          21 :                         a = bus_gvariant_get_alignment(t);
     152          21 :                         break;
     153             :                 }
     154             : 
     155         142 :                 case SD_BUS_TYPE_STRUCT_BEGIN:
     156         142 :                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
     157         142 :                         char t[n-1];
     158             : 
     159         142 :                         memcpy(t, p + 1, n - 2);
     160         142 :                         t[n - 2] = 0;
     161             : 
     162         142 :                         a = bus_gvariant_get_alignment(t);
     163         142 :                         break;
     164             :                 }
     165             : 
     166           0 :                 default:
     167           0 :                         assert_not_reached("Unknown signature type");
     168             :                 }
     169             : 
     170         738 :                 if (a < 0)
     171           0 :                         return a;
     172             : 
     173         738 :                 assert(a > 0 && a <= 8);
     174         738 :                 if ((size_t) a > alignment)
     175         454 :                         alignment = (size_t) a;
     176             : 
     177         738 :                 p += n;
     178             :         }
     179             : 
     180         561 :         return alignment;
     181             : }
     182             : 
     183         126 : int bus_gvariant_is_fixed_size(const char *signature) {
     184             :         const char *p;
     185             :         int r;
     186             : 
     187         126 :         assert(signature);
     188             : 
     189         126 :         p = signature;
     190         205 :         while (*p != 0) {
     191             :                 size_t n;
     192             : 
     193         154 :                 r = signature_element_length(p, &n);
     194         154 :                 if (r < 0)
     195          75 :                         return r;
     196             : 
     197         153 :                 switch (*p) {
     198             : 
     199          64 :                 case SD_BUS_TYPE_STRING:
     200             :                 case SD_BUS_TYPE_OBJECT_PATH:
     201             :                 case SD_BUS_TYPE_SIGNATURE:
     202             :                 case SD_BUS_TYPE_ARRAY:
     203             :                 case SD_BUS_TYPE_VARIANT:
     204          64 :                         return 0;
     205             : 
     206          72 :                 case SD_BUS_TYPE_BYTE:
     207             :                 case SD_BUS_TYPE_BOOLEAN:
     208             :                 case SD_BUS_TYPE_INT16:
     209             :                 case SD_BUS_TYPE_UINT16:
     210             :                 case SD_BUS_TYPE_INT32:
     211             :                 case SD_BUS_TYPE_UINT32:
     212             :                 case SD_BUS_TYPE_UNIX_FD:
     213             :                 case SD_BUS_TYPE_INT64:
     214             :                 case SD_BUS_TYPE_UINT64:
     215             :                 case SD_BUS_TYPE_DOUBLE:
     216          72 :                         break;
     217             : 
     218          17 :                 case SD_BUS_TYPE_STRUCT_BEGIN:
     219          17 :                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
     220          17 :                         char t[n-1];
     221             : 
     222          17 :                         memcpy(t, p + 1, n - 2);
     223          17 :                         t[n - 2] = 0;
     224             : 
     225          17 :                         r = bus_gvariant_is_fixed_size(t);
     226          17 :                         if (r <= 0)
     227          10 :                                 return r;
     228           7 :                         break;
     229             :                 }
     230             : 
     231           0 :                 default:
     232           0 :                         assert_not_reached("Unknown signature type");
     233             :                 }
     234             : 
     235          79 :                 p += n;
     236             :         }
     237             : 
     238          51 :         return true;
     239             : }
     240             : 
     241          37 : size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) {
     242          37 :         if (sz + extra <= 0xFF)
     243          34 :                 return 1;
     244           3 :         else if (sz + extra*2 <= 0xFFFF)
     245           3 :                 return 2;
     246           0 :         else if (sz + extra*4 <= 0xFFFFFFFF)
     247           0 :                 return 4;
     248             :         else
     249           0 :                 return 8;
     250             : }
     251             : 
     252          35 : size_t bus_gvariant_read_word_le(void *p, size_t sz) {
     253             :         union {
     254             :                 uint16_t u16;
     255             :                 uint32_t u32;
     256             :                 uint64_t u64;
     257             :         } x;
     258             : 
     259          35 :         assert(p);
     260             : 
     261          35 :         if (sz == 1)
     262          34 :                 return *(uint8_t*) p;
     263             : 
     264           1 :         memcpy(&x, p, sz);
     265             : 
     266           1 :         if (sz == 2)
     267           1 :                 return le16toh(x.u16);
     268           0 :         else if (sz == 4)
     269           0 :                 return le32toh(x.u32);
     270           0 :         else if (sz == 8)
     271           0 :                 return le64toh(x.u64);
     272             : 
     273           0 :         assert_not_reached("unknown word width");
     274             : }
     275             : 
     276          21 : void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) {
     277             :         union {
     278             :                 uint16_t u16;
     279             :                 uint32_t u32;
     280             :                 uint64_t u64;
     281             :         } x;
     282             : 
     283          21 :         assert(p);
     284          21 :         assert(sz == 8 || (value < (1ULL << (sz*8))));
     285             : 
     286          21 :         if (sz == 1) {
     287          20 :                 *(uint8_t*) p = value;
     288          20 :                 return;
     289           1 :         } else if (sz == 2)
     290           1 :                 x.u16 = htole16((uint16_t) value);
     291           0 :         else if (sz == 4)
     292           0 :                 x.u32 = htole32((uint32_t) value);
     293           0 :         else if (sz == 8)
     294           0 :                 x.u64 = htole64((uint64_t) value);
     295             :         else
     296           0 :                 assert_not_reached("unknown word width");
     297             : 
     298           1 :         memcpy(p, &x, sz);
     299             : }

Generated by: LCOV version 1.14