LCOV - code coverage report
Current view: top level - lib/sifp - sss_sifp_parser.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 205 310 66.1 %
Date: 2015-10-19 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Pavel Březina <pbrezina@redhat.com>
       4             : 
       5             :     Copyright (C) 2014 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include <dbus/dbus.h>
      22             : #include <string.h>
      23             : #include <dhash.h>
      24             : 
      25             : #include "lib/sifp/sss_sifp.h"
      26             : #include "lib/sifp/sss_sifp_private.h"
      27             : 
      28             : #define check_dbus_arg(iter, type, ret, done) do { \
      29             :     if (dbus_message_iter_get_arg_type((iter)) != (type)) { \
      30             :         ret = SSS_SIFP_INTERNAL_ERROR; \
      31             :         goto done; \
      32             :     } \
      33             : } while (0)
      34             : 
      35             : #define parse_basic(ctx, iter, ret, attr_type, dbus_type, \
      36             :                     data_type, field, done) \
      37             : do { \
      38             :     dbus_type val; \
      39             :     dbus_message_iter_get_basic(iter, &val); \
      40             :     attr->type = attr_type; \
      41             :     attr->data.field = _alloc_zero(ctx, data_type, 1); \
      42             :     \
      43             :     if (attr->data.field == NULL) { \
      44             :         ret = SSS_SIFP_OUT_OF_MEMORY; \
      45             :         goto done; \
      46             :     } \
      47             :     \
      48             :     attr->data.field[0] = val; \
      49             :     attr->num_values = 1; \
      50             :     \
      51             :     ret = SSS_SIFP_OK; \
      52             : } while (0)
      53             : 
      54             : #define parse_array(ctx, iter, ret, attr_type, dbus_type, \
      55             :                     data_type, field, done) \
      56             : do { \
      57             :     dbus_type val; \
      58             :     unsigned int i; \
      59             :     \
      60             :     attr->type = attr_type; \
      61             :     if (attr->num_values == 0) { \
      62             :         attr->data.field = NULL; \
      63             :         ret = SSS_SIFP_OK; \
      64             :         goto done; \
      65             :     } \
      66             :     \
      67             :     attr->data.field = _alloc_zero(ctx, data_type, attr->num_values); \
      68             :     if (attr->data.field == NULL) { \
      69             :         ret = SSS_SIFP_OUT_OF_MEMORY; \
      70             :         goto done; \
      71             :     } \
      72             :     \
      73             :     for (i = 0; i < attr->num_values; i++) { \
      74             :         dbus_message_iter_get_basic(iter, &val); \
      75             :         attr->data.field[i] = val; \
      76             :         \
      77             :         if (!dbus_message_iter_next(iter) && i + 1 < attr->num_values) { \
      78             :             ret = SSS_SIFP_INTERNAL_ERROR; \
      79             :             goto done; \
      80             :         } \
      81             :     } \
      82             :     \
      83             :     ret = SSS_SIFP_OK; \
      84             : } while (0)
      85             : 
      86             : static unsigned int
      87          20 : sss_sifp_get_array_length(DBusMessageIter *iter)
      88             : {
      89             :     DBusMessageIter array_iter;
      90             :     unsigned int size;
      91             : 
      92          20 :     dbus_message_iter_recurse(iter, &array_iter);
      93             : 
      94          20 :     if (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_INVALID) {
      95           8 :         return 0;
      96             :     }
      97             : 
      98          12 :     size = 0;
      99             :     do {
     100          46 :         size++;
     101          46 :     } while (dbus_message_iter_next(&array_iter));
     102             : 
     103          12 :     return size;
     104             : }
     105             : 
     106           1 : static void hash_delete_cb(hash_entry_t *item,
     107             :                            hash_destroy_enum type,
     108             :                            void *pvt)
     109             : {
     110           1 :     sss_sifp_ctx *ctx = (sss_sifp_ctx*)pvt;
     111           1 :     char **values = (char**)(item->value.ptr);
     112             :     int i;
     113             : 
     114           1 :     if (values == NULL) {
     115           0 :         return;
     116             :     }
     117             : 
     118           2 :     for (i = 0; values[i] != NULL; i++) {
     119           1 :         _free(ctx, values[i]);
     120           1 :         values[i] = NULL;
     121             :     }
     122             : 
     123           1 :     _free(ctx, values);
     124           1 :     item->value.ptr = NULL;
     125             : }
     126             : 
     127             : static sss_sifp_error
     128           1 : sss_sifp_parse_dict(sss_sifp_ctx *ctx,
     129             :                     DBusMessageIter *iter,
     130             :                     hash_table_t *table)
     131             : {
     132             :     DBusMessageIter dict_iter;
     133             :     DBusMessageIter array_iter;
     134             :     sss_sifp_error ret;
     135             :     hash_key_t table_key;
     136             :     hash_value_t table_value;
     137           1 :     const char *key = NULL;
     138           1 :     const char *value = NULL;
     139           1 :     char **values = NULL;
     140             :     unsigned int i;
     141             :     unsigned int num_values;
     142             :     int hret;
     143             : 
     144           1 :     dbus_message_iter_recurse(iter, &dict_iter);
     145             : 
     146             :     /* get the key */
     147           1 :     check_dbus_arg(&dict_iter, DBUS_TYPE_STRING, ret, done);
     148           1 :     dbus_message_iter_get_basic(&dict_iter, &key);
     149             : 
     150           1 :     table_key.type = HASH_KEY_STRING;
     151           1 :     table_key.str = sss_sifp_strdup(ctx, key);
     152           1 :     if (table_key.str == NULL) {
     153           0 :         ret = SSS_SIFP_OUT_OF_MEMORY;
     154           0 :         goto done;
     155             :     }
     156             : 
     157           1 :     if (!dbus_message_iter_next(&dict_iter)) {
     158           0 :         ret = SSS_SIFP_INTERNAL_ERROR;
     159           0 :         goto done;
     160             :     }
     161             : 
     162             :     /* now read the value */
     163           1 :     switch (dbus_message_iter_get_arg_type(&dict_iter)) {
     164             :     case DBUS_TYPE_STRING:
     165           1 :         dbus_message_iter_get_basic(&dict_iter, &value);
     166           1 :         values = _alloc_zero(ctx, char *, 2);
     167           1 :         if (values == NULL) {
     168           0 :             ret = SSS_SIFP_OUT_OF_MEMORY;
     169           0 :             goto done;
     170             :         }
     171             : 
     172           1 :         values[0] = sss_sifp_strdup(ctx, value);
     173           1 :         if (values[0] == NULL) {
     174           0 :             ret = SSS_SIFP_OUT_OF_MEMORY;
     175           0 :             goto done;
     176             :         }
     177             : 
     178           1 :         values[1] = NULL;
     179             : 
     180           1 :         ret = SSS_SIFP_OK;
     181           1 :         break;
     182             :     case DBUS_TYPE_ARRAY:
     183           0 :         num_values = sss_sifp_get_array_length(&dict_iter);
     184           0 :         if (num_values == 0) {
     185           0 :             values = NULL;
     186           0 :             ret = SSS_SIFP_OK;
     187           0 :             goto done;
     188             :         }
     189             : 
     190           0 :         if (dbus_message_iter_get_element_type(&dict_iter)
     191             :                 != DBUS_TYPE_STRING) {
     192           0 :             ret = SSS_SIFP_NOT_SUPPORTED;
     193           0 :             goto done;
     194             :         }
     195             : 
     196           0 :         dbus_message_iter_recurse(&dict_iter, &array_iter);
     197             : 
     198           0 :         values = _alloc_zero(ctx, char*, num_values + 1);
     199           0 :         if (values == NULL) {
     200           0 :             ret = SSS_SIFP_OUT_OF_MEMORY;
     201           0 :             goto done;
     202             :         }
     203             : 
     204           0 :         for (i = 0; i < num_values; i++) {
     205           0 :             dbus_message_iter_get_basic(&array_iter, &value);
     206           0 :             values[i] = sss_sifp_strdup(ctx, value);
     207           0 :             if (values[i] == NULL) {
     208           0 :                 ret = SSS_SIFP_OUT_OF_MEMORY;
     209           0 :                 goto done;
     210             :             }
     211             : 
     212           0 :             dbus_message_iter_next(&array_iter);
     213             :         }
     214             : 
     215           0 :         ret = SSS_SIFP_OK;
     216           0 :         break;
     217             :     default:
     218           0 :         ret = SSS_SIFP_NOT_SUPPORTED;
     219           0 :         break;
     220             :     }
     221             : 
     222           1 :     table_value.type = HASH_VALUE_PTR;
     223           1 :     table_value.ptr = values;
     224             : 
     225           1 :     hret = hash_enter(table, &table_key, &table_value);
     226           1 :     if (hret == HASH_ERROR_NO_MEMORY) {
     227           0 :         ret = SSS_SIFP_OUT_OF_MEMORY;
     228           1 :     } else if (hret != HASH_SUCCESS) {
     229           0 :         ret = SSS_SIFP_INTERNAL_ERROR;
     230             :     }
     231             : 
     232             : done:
     233           1 :     if (table_key.str != NULL) {
     234           1 :         _free(ctx, table_key.str);
     235             :     }
     236             : 
     237           1 :     if (ret != SSS_SIFP_OK) {
     238           0 :         if (values != NULL) {
     239           0 :             for (i = 0; values[i] != NULL; i++) {
     240           0 :                 _free(ctx, values[i]);
     241             :             }
     242           0 :             _free(ctx, values);
     243             :         }
     244             :     }
     245             : 
     246           1 :     return ret;
     247             : }
     248             : 
     249             : static sss_sifp_error
     250          24 : sss_sifp_parse_basic(sss_sifp_ctx *ctx,
     251             :                      DBusMessageIter *iter,
     252             :                      sss_sifp_attr *attr)
     253             : {
     254             :     sss_sifp_error ret;
     255             : 
     256          24 :     switch (dbus_message_iter_get_arg_type(iter)) {
     257             :     case DBUS_TYPE_BOOLEAN:
     258           1 :         parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_BOOL,
     259             :                     dbus_bool_t, bool, boolean, done);
     260          25 :         break;
     261             :     case DBUS_TYPE_INT16:
     262           1 :         parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_INT16,
     263             :                     int16_t, int16_t, int16, done);
     264           1 :         break;
     265             :     case DBUS_TYPE_UINT16:
     266           1 :         parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_UINT16,
     267             :                     uint16_t, uint16_t, uint16, done);
     268           1 :         break;
     269             :     case DBUS_TYPE_INT32:
     270           1 :         parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_INT32,
     271             :                     int32_t, int32_t, int32, done);
     272           1 :         break;
     273             :     case DBUS_TYPE_UINT32:
     274           8 :         parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_UINT32,
     275             :                     uint32_t, uint32_t, uint32, done);
     276           8 :         break;
     277             :     case DBUS_TYPE_INT64:
     278           1 :         parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_INT64,
     279             :                     int64_t, int64_t, int64, done);
     280           1 :         break;
     281             :     case DBUS_TYPE_UINT64:
     282           1 :         parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_UINT64,
     283             :                     uint64_t, uint64_t, uint64, done);
     284           1 :         break;
     285             :     case DBUS_TYPE_STRING:
     286             :     case DBUS_TYPE_OBJECT_PATH: ;
     287          10 :         const char *val = NULL;
     288             : 
     289          10 :         dbus_message_iter_get_basic(iter, &val);
     290             : 
     291          10 :         attr->type = SSS_SIFP_ATTR_TYPE_STRING;
     292          10 :         attr->data.str = _alloc_zero(ctx, char*, 1);
     293          10 :         if (attr->data.str == NULL) { \
     294           0 :             ret = SSS_SIFP_OUT_OF_MEMORY;
     295           0 :             goto done;
     296             :         }
     297             : 
     298          10 :         attr->data.str[0] = sss_sifp_strdup(ctx, val);
     299          10 :         if (attr->data.str[0] == NULL) {
     300           0 :             _free(ctx, attr->data.str);
     301           0 :             ret = SSS_SIFP_OUT_OF_MEMORY;
     302           0 :             goto done;
     303             :         }
     304             : 
     305          10 :         attr->num_values = 1;
     306             : 
     307          10 :         ret = SSS_SIFP_OK;
     308          10 :         break;
     309             :     default:
     310           0 :         ret = SSS_SIFP_INVALID_ARGUMENT;
     311           0 :         break;
     312             :     }
     313             : 
     314             : done:
     315          24 :     return ret;
     316             : }
     317             : 
     318             : static sss_sifp_error
     319          15 : sss_sifp_parse_array(sss_sifp_ctx *ctx,
     320             :                      DBusMessageIter *iter,
     321             :                      sss_sifp_attr *attr)
     322             : {
     323             :     DBusMessageIter array_iter;
     324             :     sss_sifp_error ret;
     325             :     int hret;
     326             : 
     327          15 :     attr->num_values = sss_sifp_get_array_length(iter);
     328          15 :     dbus_message_iter_recurse(iter, &array_iter);
     329             : 
     330          15 :     switch (dbus_message_iter_get_element_type(iter)) {
     331             :     case DBUS_TYPE_BOOLEAN:
     332           3 :         parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_BOOL,
     333             :                     dbus_bool_t, bool, boolean, done);
     334           9 :         break;
     335             :     case DBUS_TYPE_INT16:
     336           0 :         parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_INT16,
     337             :                     int16_t, int16_t, int16, done);
     338           0 :         break;
     339             :     case DBUS_TYPE_UINT16:
     340           0 :         parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_UINT16,
     341             :                     uint16_t, uint16_t, uint16, done);
     342           0 :         break;
     343             :     case DBUS_TYPE_INT32:
     344           3 :         parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_INT32,
     345             :                     int32_t, int32_t, int32, done);
     346           1 :         break;
     347             :     case DBUS_TYPE_UINT32:
     348           3 :         parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_UINT32,
     349             :                     uint32_t, uint32_t, uint32, done);
     350           1 :         break;
     351             :     case DBUS_TYPE_INT64:
     352           3 :         parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_INT64,
     353             :                     int64_t, int64_t, int64, done);
     354           1 :         break;
     355             :     case DBUS_TYPE_UINT64:
     356           3 :         parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_UINT64,
     357             :                     uint64_t, uint64_t, uint64, done);
     358           1 :         break;
     359             :     case DBUS_TYPE_STRING:
     360             :     case DBUS_TYPE_OBJECT_PATH: ;
     361             :         const char *val;
     362             :         unsigned int i;
     363             : 
     364           4 :         attr->type = SSS_SIFP_ATTR_TYPE_STRING;
     365           4 :         if (attr->num_values == 0) {
     366           2 :             attr->data.str = NULL;
     367           2 :             ret = SSS_SIFP_OK;
     368           2 :             goto done;
     369             :         }
     370             : 
     371           2 :         attr->data.str = _alloc_zero(ctx, char *, attr->num_values);
     372           2 :         if (attr->data.str == NULL) {
     373           0 :             ret = SSS_SIFP_OUT_OF_MEMORY;
     374           0 :             goto done;
     375             :         }
     376             : 
     377          10 :         for (i = 0; i < attr->num_values; i++) {
     378           8 :             dbus_message_iter_get_basic(&array_iter, &val);
     379           8 :             attr->data.str[i] = sss_sifp_strdup(ctx, val);
     380           8 :             if (attr->data.str[i] == NULL) {
     381           0 :                 ret = SSS_SIFP_OUT_OF_MEMORY;
     382           0 :                 goto done;
     383             :             }
     384             : 
     385           8 :             if (!dbus_message_iter_next(&array_iter)
     386           2 :                     && i + 1 < attr->num_values) {
     387           0 :                 ret = SSS_SIFP_INTERNAL_ERROR;
     388           0 :                 goto done;
     389             :             }
     390             :         }
     391             : 
     392           2 :         ret = SSS_SIFP_OK;
     393           2 :         break;
     394             :     case DBUS_TYPE_DICT_ENTRY:
     395           1 :         attr->type = SSS_SIFP_ATTR_TYPE_STRING_DICT;
     396           1 :         if (attr->num_values == 0) {
     397           0 :             attr->data.str_dict = NULL;
     398           0 :             ret = SSS_SIFP_OK;
     399           0 :             goto done;
     400             :         }
     401             : 
     402           2 :         hret = hash_create_ex(10, &(attr->data.str_dict), 0, 0, 0, 0,
     403           1 :                               ctx->alloc_fn, ctx->free_fn, ctx->alloc_pvt,
     404             :                               hash_delete_cb, ctx);
     405           1 :         if (hret != HASH_SUCCESS) {
     406           0 :             ret = SSS_SIFP_OUT_OF_MEMORY;
     407           0 :             goto done;
     408             :         }
     409             : 
     410           2 :         for (i = 0; i < attr->num_values; i++) {
     411           1 :             ret = sss_sifp_parse_dict(ctx, &array_iter, attr->data.str_dict);
     412           1 :             if (ret != SSS_SIFP_OK) {
     413           0 :                 _free(ctx, attr->data.str_dict);
     414           0 :                 goto done;
     415             :             }
     416             : 
     417           1 :             if (!dbus_message_iter_next(&array_iter)
     418           1 :                     && i + 1 < attr->num_values) {
     419           0 :                 ret = SSS_SIFP_INTERNAL_ERROR;
     420           0 :                 goto done;
     421             :             }
     422             :         }
     423             : 
     424           1 :         ret = SSS_SIFP_OK;
     425           1 :         break;
     426             :     default:
     427           0 :         ret = SSS_SIFP_INVALID_ARGUMENT;
     428           0 :         break;
     429             :     }
     430             : 
     431             : done:
     432          15 :     if (ret != SSS_SIFP_OK) {
     433           0 :         if (attr->type == SSS_SIFP_ATTR_TYPE_STRING && attr->data.str != NULL) {
     434           0 :             for (unsigned int i = 0;
     435           0 :                  attr->data.str[i] != NULL && i < attr->num_values;
     436           0 :                  i++) {
     437           0 :                 _free(ctx, attr->data.str[i]);
     438             :             }
     439           0 :             _free(ctx, attr->data.str);
     440           0 :         } else if (attr->type == SSS_SIFP_ATTR_TYPE_STRING_DICT
     441           0 :                     && attr->data.str_dict != NULL) {
     442           0 :             hash_destroy(attr->data.str_dict);
     443           0 :             attr->data.str_dict = NULL;
     444             :         }
     445             :     }
     446             : 
     447          15 :     return ret;
     448             : }
     449             : 
     450             : static sss_sifp_error
     451          39 : sss_sifp_parse_variant(sss_sifp_ctx *ctx,
     452             :                        DBusMessageIter *iter,
     453             :                        sss_sifp_attr *attr)
     454             : {
     455             :     DBusMessageIter variant_iter;
     456             :     sss_sifp_error ret;
     457             :     int type;
     458             : 
     459          39 :     check_dbus_arg(iter, DBUS_TYPE_VARIANT, ret, done);
     460             : 
     461          39 :     dbus_message_iter_recurse(iter, &variant_iter);
     462             : 
     463          39 :     type = dbus_message_iter_get_arg_type(&variant_iter);
     464          39 :     if (dbus_type_is_basic(type)) {
     465          24 :         ret = sss_sifp_parse_basic(ctx, &variant_iter, attr);
     466             :     } else {
     467             :         /* container types */
     468          15 :         switch (type) {
     469             :         /* case DBUS_TYPE_DICT_ENTRY may only be contained within an array
     470             :          * in variant */
     471             :         case DBUS_TYPE_ARRAY:
     472          15 :             ret = sss_sifp_parse_array(ctx, &variant_iter, attr);;
     473          15 :             break;
     474             :         default:
     475           0 :             ret = SSS_SIFP_NOT_SUPPORTED;
     476           0 :             break;
     477             :         }
     478             :     }
     479             : 
     480             : done:
     481          39 :     return ret;
     482             : }
     483             : 
     484             : /**
     485             :  * DBusMessage format:
     486             :  * variant:value
     487             :  *
     488             :  * Iterator has to point to the variant but not inside the variant.
     489             :  */
     490             : static sss_sifp_error
     491          39 : sss_sifp_parse_single_attr(sss_sifp_ctx *ctx,
     492             :                            const char *name,
     493             :                            DBusMessageIter *iter,
     494             :                            sss_sifp_attr **_attr)
     495             : {
     496          39 :     sss_sifp_attr *attr = NULL;
     497             :     sss_sifp_error ret;
     498             : 
     499          39 :     attr = _alloc_zero(ctx, sss_sifp_attr, 1);
     500          39 :     if (attr == NULL) {
     501           0 :         ret = SSS_SIFP_OUT_OF_MEMORY;
     502           0 :         goto done;
     503             :     }
     504             : 
     505          39 :     attr->name = sss_sifp_strdup(ctx, name);
     506          39 :     if (attr->name == NULL) {
     507           0 :         _free(ctx, attr);
     508           0 :         ret = SSS_SIFP_OUT_OF_MEMORY;
     509           0 :         goto done;
     510             :     }
     511             : 
     512          39 :     ret = sss_sifp_parse_variant(ctx, iter, attr);
     513          39 :     if (ret != SSS_SIFP_OK) {
     514           0 :         _free(ctx, attr->name);
     515           0 :         _free(ctx, attr);
     516             :     }
     517             : 
     518          39 :     *_attr = attr;
     519             : 
     520             : done:
     521          39 :     return ret;
     522             : }
     523             : 
     524             : /**
     525             :  * DBusMessage format:
     526             :  * variant:value
     527             :  */
     528             : sss_sifp_error
     529          27 : sss_sifp_parse_attr(sss_sifp_ctx *ctx,
     530             :                     const char *name,
     531             :                     DBusMessage *msg,
     532             :                     sss_sifp_attr ***_attrs)
     533             : {
     534          27 :     sss_sifp_attr **attrs = NULL;
     535             :     DBusMessageIter iter;
     536             :     sss_sifp_error ret;
     537             : 
     538          27 :     dbus_message_iter_init(msg, &iter);
     539             : 
     540          27 :     attrs = _alloc_zero(ctx, sss_sifp_attr *, 2);
     541          27 :     if (attrs == NULL) {
     542           0 :         ret = SSS_SIFP_OUT_OF_MEMORY;
     543           0 :         goto done;
     544             :     }
     545             : 
     546          27 :     ret = sss_sifp_parse_single_attr(ctx, name, &iter, &attrs[0]);
     547          27 :     if (ret != SSS_SIFP_OK) {
     548           0 :         goto done;
     549             :     }
     550             : 
     551          27 :     *_attrs = attrs;
     552             : 
     553          27 :     ret = SSS_SIFP_OK;
     554             : 
     555             : done:
     556          27 :     if (ret != SSS_SIFP_OK) {
     557           0 :         sss_sifp_free_attrs(ctx, &attrs);
     558             :     }
     559             : 
     560          27 :     return ret;
     561             : }
     562             : 
     563             : /**
     564             :  * DBusMessage format:
     565             :  * array of dict_entry(string:attr_name, variant:value)
     566             :  */
     567             : sss_sifp_error
     568           5 : sss_sifp_parse_attr_list(sss_sifp_ctx *ctx,
     569             :                          DBusMessage *msg,
     570             :                          sss_sifp_attr ***_attrs)
     571             : {
     572             :     DBusMessageIter iter;
     573             :     DBusMessageIter array_iter;
     574             :     DBusMessageIter dict_iter;
     575           5 :     sss_sifp_attr **attrs = NULL;
     576           5 :     const char *name = NULL;
     577             :     unsigned int num_values;
     578             :     sss_sifp_error ret;
     579             :     unsigned int i;
     580             : 
     581           5 :     dbus_message_iter_init(msg, &iter);
     582             : 
     583           5 :     check_dbus_arg(&iter, DBUS_TYPE_ARRAY, ret, done);
     584             : 
     585           5 :     if (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
     586           0 :         ret = SSS_SIFP_INTERNAL_ERROR;
     587           0 :         goto done;
     588             :     }
     589             : 
     590           5 :     num_values = sss_sifp_get_array_length(&iter);
     591           5 :     attrs = _alloc_zero(ctx, sss_sifp_attr *, num_values + 1);
     592           5 :     if (attrs == NULL) {
     593           0 :         ret = SSS_SIFP_OUT_OF_MEMORY;
     594           0 :         goto done;
     595             :     }
     596             : 
     597           5 :     dbus_message_iter_recurse(&iter, &array_iter);
     598             : 
     599          17 :     for (i = 0; i < num_values; i++) {
     600          12 :         dbus_message_iter_recurse(&array_iter, &dict_iter);
     601             : 
     602             :         /* get the key */
     603          12 :         check_dbus_arg(&dict_iter, DBUS_TYPE_STRING, ret, done);
     604          12 :         dbus_message_iter_get_basic(&dict_iter, &name);
     605             : 
     606          12 :         if (!dbus_message_iter_next(&dict_iter)) {
     607           0 :             ret = SSS_SIFP_INTERNAL_ERROR;
     608           0 :             goto done;
     609             :         }
     610             : 
     611             :         /* now read the value */
     612          12 :         check_dbus_arg(&dict_iter, DBUS_TYPE_VARIANT, ret, done);
     613             : 
     614          12 :         ret = sss_sifp_parse_single_attr(ctx, name, &dict_iter, &attrs[i]);
     615          12 :         if (ret != SSS_SIFP_OK) {
     616           0 :             goto done;
     617             :         }
     618             : 
     619          12 :         dbus_message_iter_next(&array_iter);
     620             :     }
     621             : 
     622           5 :     *_attrs = attrs;
     623           5 :     ret = SSS_SIFP_OK;
     624             : 
     625             : done:
     626           5 :     if (ret != SSS_SIFP_OK) {
     627           0 :         sss_sifp_free_attrs(ctx, &attrs);
     628             :     }
     629             : 
     630           5 :     return ret;
     631             : }
     632             : 
     633             : sss_sifp_error
     634           5 : sss_sifp_parse_object_path(sss_sifp_ctx *ctx,
     635             :                            DBusMessage *msg,
     636             :                            char **_object_path)
     637             : {
     638           5 :     char *object_path = NULL;
     639           5 :     const char *dbus_path = NULL;
     640             :     DBusError dbus_error;
     641             :     dbus_bool_t bret;
     642             :     sss_sifp_error ret;
     643             : 
     644           5 :     dbus_error_init(&dbus_error);
     645             : 
     646           5 :     bret = dbus_message_get_args(msg, &dbus_error,
     647             :                                  DBUS_TYPE_OBJECT_PATH, &dbus_path,
     648             :                                  DBUS_TYPE_INVALID);
     649           5 :     if (!bret) {
     650           1 :         sss_sifp_set_io_error(ctx, &dbus_error);
     651           1 :         ret = SSS_SIFP_IO_ERROR;
     652           1 :         goto done;
     653             :     }
     654             : 
     655           4 :     object_path = sss_sifp_strdup(ctx, dbus_path);
     656           4 :     if (object_path == NULL) {
     657           0 :         ret = SSS_SIFP_OUT_OF_MEMORY;
     658           0 :         goto done;
     659             :     }
     660             : 
     661           4 :     *_object_path = object_path;
     662           4 :     ret = SSS_SIFP_OK;
     663             : 
     664             : done:
     665           5 :     dbus_error_free(&dbus_error);
     666             : 
     667           5 :     return ret;
     668             : }
     669             : 
     670             : sss_sifp_error
     671           5 : sss_sifp_parse_object_path_list(sss_sifp_ctx *ctx,
     672             :                                 DBusMessage *msg,
     673             :                                 char ***_object_paths)
     674             : {
     675           5 :     char **object_paths = NULL;
     676           5 :     char **dbus_paths = NULL;
     677             :     int num_paths;
     678             :     DBusError dbus_error;
     679             :     dbus_bool_t bret;
     680             :     sss_sifp_error ret;
     681             :     int i;
     682             : 
     683           5 :     dbus_error_init(&dbus_error);
     684             : 
     685           5 :     bret = dbus_message_get_args(msg, &dbus_error,
     686             :                                  DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH,
     687             :                                  &dbus_paths, &num_paths,
     688             :                                  DBUS_TYPE_INVALID);
     689           5 :     if (!bret) {
     690           1 :         sss_sifp_set_io_error(ctx, &dbus_error);
     691           1 :         ret = SSS_SIFP_IO_ERROR;
     692           1 :         goto done;
     693             :     }
     694             : 
     695           4 :     object_paths = _alloc_zero(ctx, char *, num_paths + 1);
     696           4 :     if (object_paths == NULL) {
     697           0 :         ret = SSS_SIFP_OUT_OF_MEMORY;
     698           0 :         goto done;
     699             :     }
     700             : 
     701          12 :     for (i = 0; i < num_paths; i++) {
     702           8 :         object_paths[i] = sss_sifp_strdup(ctx, dbus_paths[i]);
     703           8 :         if (object_paths[i] == NULL) {
     704           0 :             ret = SSS_SIFP_OUT_OF_MEMORY;
     705           0 :             goto done;
     706             :         }
     707             :     }
     708             : 
     709           4 :     *_object_paths = object_paths;
     710           4 :     ret = SSS_SIFP_OK;
     711             : 
     712             : done:
     713           5 :     dbus_error_free(&dbus_error);
     714           5 :     dbus_free_string_array(dbus_paths);
     715             : 
     716           5 :     if (ret != SSS_SIFP_OK && object_paths != NULL) {
     717           0 :         sss_sifp_free_string_array(ctx, &object_paths);
     718             :     }
     719             : 
     720           5 :     return ret;
     721             : }

Generated by: LCOV version 1.10