1 /* 2 * blob.c - uci <-> blobmsg conversion layer 3 * Copyright (C) 2012-2013 Felix Fietkau <nbd@openwrt.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License version 2.1 7 * as published by the Free Software Foundation 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 */ 14 #include <string.h> 15 #include <stdlib.h> 16 #include <stdio.h> 17 18 #include <libubox/blobmsg.h> 19 #include "uci.h" 20 #include "uci_blob.h" 21 22 static bool 23 uci_attr_to_blob(struct blob_buf *b, const char *str, 24 const char *name, enum blobmsg_type type) 25 { 26 char *err; 27 int intval; 28 long long llval; 29 30 switch (type) { 31 case BLOBMSG_TYPE_STRING: 32 blobmsg_add_string(b, name, str); 33 break; 34 case BLOBMSG_TYPE_BOOL: 35 if (!strcmp(str, "true") || !strcmp(str, "1")) 36 intval = 1; 37 else if (!strcmp(str, "false") || !strcmp(str, "")) 38 intval = 0; 39 else 40 return false; 41 42 blobmsg_add_u8(b, name, intval); 43 break; 44 case BLOBMSG_TYPE_INT32: 45 intval = strtol(str, &err, 0); 46 if (*err) 47 return false; 48 49 blobmsg_add_u32(b, name, intval); 50 break; 51 case BLOBMSG_TYPE_INT64: 52 llval = strtoll(str, &err, 0); 53 if (*err) 54 return false; 55 56 blobmsg_add_u64(b, name, llval); 57 break; 58 default: 59 return false; 60 } 61 return true; 62 } 63 64 static void 65 uci_array_to_blob(struct blob_buf *b, struct uci_option *o, 66 enum blobmsg_type type) 67 { 68 struct uci_element *e; 69 char *str, *next, *word; 70 71 if (o->type == UCI_TYPE_LIST) { 72 uci_foreach_element(&o->v.list, e) { 73 uci_attr_to_blob(b, e->name, NULL, type); 74 } 75 return; 76 } 77 78 str = strdup(o->v.string); 79 next = str; 80 81 while ((word = strsep(&next, " \t")) != NULL) { 82 if (!*word) 83 continue; 84 85 uci_attr_to_blob(b, word, NULL, type); 86 } 87 88 free(str); 89 } 90 91 static int 92 __uci_element_to_blob(struct blob_buf *b, struct uci_element *e, 93 const struct uci_blob_param_list *p) 94 { 95 const struct blobmsg_policy *attr = NULL; 96 struct uci_option *o = uci_to_option(e); 97 unsigned int types = 0; 98 void *array; 99 int i, ret = 0; 100 101 for (i = 0; i < p->n_params; i++) { 102 attr = &p->params[i]; 103 104 if (strcmp(attr->name, e->name) != 0) 105 continue; 106 107 if (attr->type > BLOBMSG_TYPE_LAST) 108 continue; 109 110 if (types & (1 << attr->type)) 111 continue; 112 113 types |= 1 << attr->type; 114 115 if (attr->type == BLOBMSG_TYPE_ARRAY) { 116 int element_type = 0; 117 118 if (p->info) 119 element_type = p->info[i].type; 120 121 if (!element_type) 122 element_type = BLOBMSG_TYPE_STRING; 123 124 array = blobmsg_open_array(b, attr->name); 125 uci_array_to_blob(b, o, element_type); 126 blobmsg_close_array(b, array); 127 ret++; 128 continue; 129 } 130 131 if (o->type == UCI_TYPE_LIST) 132 continue; 133 134 ret += uci_attr_to_blob(b, o->v.string, attr->name, attr->type); 135 } 136 return ret; 137 } 138 139 static int 140 __uci_to_blob(struct blob_buf *b, struct uci_section *s, 141 const struct uci_blob_param_list *p) 142 { 143 struct uci_element *e; 144 int ret = 0; 145 146 uci_foreach_element(&s->options, e) 147 ret += __uci_element_to_blob(b, e, p); 148 149 return ret; 150 } 151 152 int 153 uci_to_blob(struct blob_buf *b, struct uci_section *s, 154 const struct uci_blob_param_list *p) 155 { 156 int ret = 0; 157 int i; 158 159 ret += __uci_to_blob(b, s, p); 160 for (i = 0; i < p->n_next; i++) 161 ret += uci_to_blob(b, s, p->next[i]); 162 163 return ret; 164 } 165 166 bool 167 uci_blob_diff(struct blob_attr **tb1, struct blob_attr **tb2, 168 const struct uci_blob_param_list *config, unsigned long *diff) 169 { 170 bool ret = false; 171 int i; 172 173 for (i = 0; i < config->n_params; i++) { 174 if (!tb1[i] && !tb2[i]) 175 continue; 176 177 if (!!tb1[i] != !!tb2[i]) 178 goto mark; 179 180 if (blob_len(tb1[i]) != blob_len(tb2[i])) 181 goto mark; 182 183 if (memcmp(tb1[i], tb2[i], blob_raw_len(tb1[i])) != 0) 184 goto mark; 185 186 continue; 187 188 mark: 189 ret = true; 190 if (diff) 191 uci_bitfield_set(diff, i); 192 else 193 return ret; 194 } 195 196 return ret; 197 } 198 199 200 static bool 201 __uci_blob_check_equal(struct blob_attr *c1, struct blob_attr *c2, 202 const struct uci_blob_param_list *config) 203 { 204 struct blob_attr **tb1, **tb2; 205 206 if (!!c1 ^ !!c2) 207 return false; 208 209 if (!c1 && !c2) 210 return true; 211 212 tb1 = alloca(config->n_params * sizeof(struct blob_attr *)); 213 blobmsg_parse(config->params, config->n_params, tb1, 214 blob_data(c1), blob_len(c1)); 215 216 tb2 = alloca(config->n_params * sizeof(struct blob_attr *)); 217 blobmsg_parse(config->params, config->n_params, tb2, 218 blob_data(c2), blob_len(c2)); 219 220 return !uci_blob_diff(tb1, tb2, config, NULL); 221 } 222 223 bool 224 uci_blob_check_equal(struct blob_attr *c1, struct blob_attr *c2, 225 const struct uci_blob_param_list *config) 226 { 227 int i; 228 229 if (!__uci_blob_check_equal(c1, c2, config)) 230 return false; 231 232 for (i = 0; i < config->n_next; i++) { 233 if (!__uci_blob_check_equal(c1, c2, config->next[i])) 234 return false; 235 } 236 237 return true; 238 } 239
This page was automatically generated by LXR 0.3.1. • OpenWrt