Line data Source code
1 : /*
2 : INI LIBRARY
3 :
4 : Value interpretation functions for single values
5 : and corresponding memory cleanup functions.
6 :
7 : Copyright (C) Dmitri Pal <dpal@redhat.com> 2012
8 :
9 : INI Library is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : INI Library is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with INI Library. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "config.h"
24 : #include <stdio.h>
25 : #include <errno.h>
26 : #include <string.h>
27 : #include <stdlib.h>
28 : #include <ctype.h>
29 : #include "trace.h"
30 : #include "collection.h"
31 : #include "collection_tools.h"
32 : #include "ini_defines.h"
33 : #include "ini_config_priv.h"
34 : #include "ini_configobj.h"
35 : #include "ini_valueobj.h"
36 :
37 : /* Macro co convert to HEX value */
38 : #define HEXVAL(c) (isdigit(c) ? (c - '0') : (tolower(c) - 'a') + 10)
39 :
40 59 : static int is_same_section(struct ini_cfgobj *ini_config,
41 : const char *section)
42 : {
43 59 : int len = 0;
44 :
45 : TRACE_FLOW_ENTRY();
46 :
47 : /* If section is not defined it is different */
48 59 : if (ini_config->section == NULL) {
49 : TRACE_FLOW_RETURN(0);
50 : return 0;
51 : }
52 :
53 23 : len = strlen(section);
54 :
55 : /* If values are same this is the same section */
56 23 : if ((strncasecmp(ini_config->section, section, ini_config->section_len) == 0) &&
57 : (ini_config->section_len == len)) {
58 : TRACE_FLOW_RETURN(1);
59 : return 1;
60 : }
61 :
62 : /* Otherwise the values are different */
63 : TRACE_FLOW_RETURN(0);
64 : return 0;
65 : }
66 :
67 111 : static int is_same_name(struct ini_cfgobj *ini_config,
68 : const char *name,
69 : int name_len)
70 : {
71 : TRACE_FLOW_ENTRY();
72 :
73 : /* If name is not defined it is different */
74 111 : if (ini_config->name == NULL) {
75 : TRACE_FLOW_RETURN(0);
76 : return 0;
77 : }
78 :
79 : /* If values are same this is the same value */
80 35 : if ((strncasecmp(ini_config->name, name, ini_config->name_len) == 0) &&
81 : (ini_config->name_len == name_len)) {
82 : TRACE_FLOW_RETURN(1);
83 : return 1;
84 : }
85 :
86 : /* Otherwise the values are different */
87 : TRACE_FLOW_RETURN(0);
88 : return 0;
89 : }
90 :
91 :
92 : /* Function to get value object from the configuration handle */
93 59 : int ini_get_config_valueobj(const char *section,
94 : const char *name,
95 170 : struct ini_cfgobj *ini_config,
96 : int mode,
97 : struct value_obj **vo)
98 : {
99 59 : int error = EOK;
100 59 : struct collection_item *section_handle = NULL;
101 59 : struct collection_item *item = NULL;
102 59 : struct collection_item *last_found = NULL;
103 : const char *to_find;
104 59 : char default_section[] = INI_DEFAULT_SECTION;
105 59 : uint64_t hash = 0;
106 59 : int len = 0, name_len = 0;
107 :
108 : TRACE_FLOW_ENTRY();
109 :
110 : /* Do we have the accepting memory ? */
111 59 : if (vo == NULL) {
112 : TRACE_ERROR_NUMBER("Invalid argument vo.", EINVAL);
113 : return EINVAL;
114 : }
115 :
116 59 : *vo = NULL;
117 :
118 59 : if (ini_config == NULL) {
119 : TRACE_ERROR_NUMBER("Invalid argument ini_config.", EINVAL);
120 : return EINVAL;
121 : }
122 :
123 59 : if ((mode < INI_GET_FIRST_VALUE) ||
124 : (mode > INI_GET_LAST_VALUE)) {
125 : TRACE_ERROR_NUMBER("Invalid argument mode:", mode);
126 : return EINVAL;
127 : }
128 :
129 : /* Do we have a name ? */
130 59 : if (name == NULL) {
131 : TRACE_ERROR_NUMBER("Name is NULL it will not be found.", EINVAL);
132 : return EINVAL;
133 : }
134 :
135 : /* Empty section means look for the default one */
136 59 : if (section == NULL) to_find = default_section;
137 59 : else to_find = section;
138 :
139 : TRACE_INFO_STRING("Getting Name:", name);
140 : TRACE_INFO_STRING("In Section:", to_find);
141 :
142 : /* Make sure we start over if this is the first value */
143 59 : if (mode == INI_GET_FIRST_VALUE) ini_config_clean_state(ini_config);
144 :
145 : /* Are we looking in the same section ? */
146 59 : if (!is_same_section(ini_config, to_find)) {
147 :
148 : /* This is a different section */
149 38 : ini_config_clean_state(ini_config);
150 :
151 : /* Get Subcollection */
152 38 : error = col_get_collection_reference(ini_config->cfg, §ion_handle, to_find);
153 : /* Check error */
154 38 : if (error && (error != ENOENT)) {
155 : TRACE_ERROR_NUMBER("Failed to get section", error);
156 : return error;
157 : }
158 :
159 : /* Did we find a section */
160 38 : if ((error == ENOENT) || (section_handle == NULL)) {
161 : /* We have not found section - return success */
162 : TRACE_FLOW_EXIT();
163 : return EOK;
164 : }
165 :
166 : /* Create an iterator */
167 37 : error = col_bind_iterator(&(ini_config->iterator),
168 : section_handle,
169 : COL_TRAVERSE_ONELEVEL);
170 : /* Make sure we free the section we found */
171 37 : col_destroy_collection(section_handle);
172 : /* Check error */
173 37 : if (error) {
174 : TRACE_ERROR_NUMBER("Failed to bind to section", error);
175 : return error;
176 : }
177 :
178 : /* Save section */
179 37 : ini_config->section_len = strlen(to_find);
180 37 : ini_config->section = strndup(to_find, ini_config->section_len);
181 : /* Check error */
182 37 : if (ini_config->section == NULL) {
183 : TRACE_ERROR_NUMBER("Failed to save section name ", ENOMEM);
184 0 : ini_config_clean_state(ini_config);
185 0 : return ENOMEM;
186 : }
187 : }
188 :
189 58 : hash = col_make_hash(name, 0, &name_len);
190 :
191 : /* Check if this is the same name */
192 116 : if (!is_same_name(ini_config, name, name_len)) {
193 : TRACE_INFO_STRING("Saved name:", ini_config->name);
194 : TRACE_INFO_STRING("Passed name:", name);
195 : TRACE_INFO_NUMBER("Length of the saved name", ini_config->name_len);
196 : TRACE_INFO_NUMBER("Length of the passed name", name_len);
197 40 : col_rewind_iterator(ini_config->iterator);
198 40 : free(ini_config->name);
199 40 : ini_config->name = NULL;
200 40 : ini_config->name_len = 0;
201 : }
202 :
203 : /* Iterate through the section */
204 : do {
205 :
206 : /* Loop through a collection */
207 382 : error = col_iterate_collection(ini_config->iterator, &item);
208 382 : if (error) {
209 : TRACE_ERROR_NUMBER("Failed to iterate", error);
210 0 : ini_config_clean_state(ini_config);
211 0 : return error;
212 : }
213 :
214 : /* Are we done ? */
215 382 : if (item == NULL) {
216 : /* We looped to the end and found last value */
217 6 : if ((mode == INI_GET_LAST_VALUE) && (last_found)) {
218 1 : item = last_found;
219 1 : break;
220 : }
221 : /* There is nothing left to look for */
222 5 : ini_config_clean_state(ini_config);
223 : TRACE_FLOW_EXIT();
224 5 : return EOK;
225 : }
226 :
227 432 : if ((hash == col_get_item_hash(item)) &&
228 112 : (strncasecmp(col_get_item_property(item, &len), name, name_len) == 0) &&
229 56 : (len == name_len)) {
230 : TRACE_INFO_STRING("Item is found", name);
231 56 : last_found = item;
232 56 : if (mode == INI_GET_LAST_VALUE) continue;
233 : break;
234 : }
235 : }
236 : while(1);
237 :
238 106 : if (!is_same_name(ini_config, name, name_len)) {
239 : /* Save name */
240 39 : ini_config->name_len = name_len;
241 39 : ini_config->name = strndup(name, name_len);
242 : /* Check error */
243 39 : if (ini_config->name == NULL) {
244 : TRACE_ERROR_NUMBER("Failed to save key name ", ENOMEM);
245 0 : ini_config_clean_state(ini_config);
246 0 : return ENOMEM;
247 : }
248 : }
249 :
250 53 : *vo = *((struct value_obj **)(col_get_item_data(item)));
251 :
252 : TRACE_FLOW_EXIT();
253 53 : return error;
254 : }
255 :
256 : /* Get long long value from config value object */
257 6 : static long long ini_get_llong_config_value(struct value_obj *vo,
258 : int strict,
259 : long long def,
260 : int *error)
261 : {
262 : int err;
263 : const char *str;
264 : char *endptr;
265 6 : long long val = 0;
266 :
267 : TRACE_FLOW_ENTRY();
268 :
269 : /* Do we have the vo ? */
270 6 : if (vo == NULL) {
271 : TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
272 0 : if (error) *error = EINVAL;
273 0 : return def;
274 : }
275 :
276 6 : if (error) *error = EOK;
277 :
278 : /* Get value - no error checking as we checked it above
279 : * and there is no other reson the function could fail.
280 : */
281 6 : value_get_concatenated(vo, &str);
282 :
283 : /* Try to parse the value */
284 6 : errno = 0;
285 6 : val = strtoll(str, &endptr, 10);
286 6 : err = errno;
287 :
288 : /* Check for various possible errors */
289 6 : if (err != 0) {
290 : TRACE_ERROR_NUMBER("Conversion failed", err);
291 0 : if (error) *error = err;
292 0 : return def;
293 : }
294 :
295 : /* Other error cases */
296 6 : if ((endptr == str) || (strict && (*endptr != '\0'))) {
297 : TRACE_ERROR_NUMBER("More characters or nothing processed", EIO);
298 1 : if (error) *error = EIO;
299 1 : return def;
300 : }
301 :
302 : TRACE_FLOW_NUMBER("ini_get_llong_config_value returning", (long)val);
303 : return val;
304 : }
305 :
306 : /* Get unsigned long long value from config value object */
307 4 : static unsigned long long ini_get_ullong_config_value(struct value_obj *vo,
308 : int strict,
309 : unsigned long long def,
310 : int *error)
311 : {
312 : int err;
313 : const char *str;
314 : char *endptr;
315 4 : unsigned long long val = 0;
316 :
317 : TRACE_FLOW_ENTRY();
318 :
319 : /* Do we have the vo ? */
320 4 : if (vo == NULL) {
321 : TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
322 0 : if (error) *error = EINVAL;
323 0 : return def;
324 : }
325 :
326 4 : if (error) *error = EOK;
327 :
328 : /* Get value - no error checking as we checked it above
329 : * and there is no other reson the function could fail.
330 : */
331 4 : value_get_concatenated(vo, &str);
332 :
333 4 : errno = 0;
334 4 : val = strtoull(str, &endptr, 10);
335 4 : err = errno;
336 :
337 : /* Check for various possible errors */
338 4 : if (err != 0) {
339 : TRACE_ERROR_NUMBER("Conversion failed", err);
340 0 : if (error) *error = err;
341 0 : return def;
342 : }
343 :
344 : /* Other error cases */
345 4 : if ((endptr == str) || (strict && (*endptr != '\0'))) {
346 : TRACE_ERROR_NUMBER("More characters or nothing processed", EIO);
347 0 : if (error) *error = EIO;
348 0 : return def;
349 : }
350 :
351 : TRACE_FLOW_NUMBER("ini_get_ullong_config_value returning", val);
352 : return val;
353 : }
354 :
355 :
356 : /* Get integer value from config value */
357 3 : int ini_get_int_config_value(struct value_obj *vo,
358 : int strict,
359 : int def,
360 : int *error)
361 : {
362 3 : long long val = 0;
363 3 : int err = 0;
364 :
365 : TRACE_FLOW_ENTRY();
366 :
367 3 : val = ini_get_llong_config_value(vo, strict, def, &err);
368 3 : if (err == 0) {
369 2 : if ((val > INT_MAX) || (val < INT_MIN)) {
370 : TRACE_ERROR_NUMBER("Value is out of range", ERANGE);
371 0 : val = def;
372 0 : err = ERANGE;
373 : }
374 : }
375 :
376 3 : if (error) *error = err;
377 :
378 : TRACE_FLOW_NUMBER("ini_get_int_config_value returning", (int)val);
379 3 : return (int)val;
380 : }
381 :
382 : /* Get unsigned integer value from config value object */
383 1 : unsigned ini_get_unsigned_config_value(struct value_obj *vo,
384 : int strict,
385 : unsigned def,
386 : int *error)
387 : {
388 1 : unsigned long long val = 0;
389 1 : int err = 0;
390 :
391 : TRACE_FLOW_ENTRY();
392 :
393 1 : val = ini_get_ullong_config_value(vo, strict, def, &err);
394 1 : if (err == 0) {
395 1 : if (val > UINT_MAX) {
396 : TRACE_ERROR_NUMBER("Value is out of range", ERANGE);
397 0 : val = def;
398 0 : err = ERANGE;
399 : }
400 : }
401 :
402 1 : if (error) *error = err;
403 :
404 : TRACE_FLOW_NUMBER("ini_get_unsigned_config_value returning",
405 : (unsigned)val);
406 1 : return (unsigned)val;
407 : }
408 :
409 : /* Get long value from config value object */
410 1 : long ini_get_long_config_value(struct value_obj *vo,
411 : int strict,
412 : long def,
413 : int *error)
414 : {
415 1 : long long val = 0;
416 1 : int err = 0;
417 :
418 : TRACE_FLOW_ENTRY();
419 :
420 1 : val = ini_get_llong_config_value(vo, strict, def, &err);
421 : if (err == 0) {
422 : if ((val > LONG_MAX) || (val < LONG_MIN)) {
423 : TRACE_ERROR_NUMBER("Value is out of range", ERANGE);
424 : val = def;
425 : err = ERANGE;
426 : }
427 : }
428 :
429 1 : if (error) *error = err;
430 :
431 : TRACE_FLOW_NUMBER("ini_get_long_config_value returning",
432 : (long)val);
433 1 : return (long)val;
434 : }
435 :
436 : /* Get unsigned long value from config value object */
437 1 : unsigned long ini_get_ulong_config_value(struct value_obj *vo,
438 : int strict,
439 : unsigned long def,
440 : int *error)
441 : {
442 1 : unsigned long long val = 0;
443 1 : int err = 0;
444 :
445 : TRACE_FLOW_ENTRY();
446 :
447 1 : val = ini_get_ullong_config_value(vo, strict, def, &err);
448 : if (err == 0) {
449 : if (val > ULONG_MAX) {
450 : TRACE_ERROR_NUMBER("Value is out of range", ERANGE);
451 : val = def;
452 : err = ERANGE;
453 : }
454 : }
455 :
456 1 : if (error) *error = err;
457 :
458 : TRACE_FLOW_NUMBER("ini_get_ulong_config_value returning",
459 : (unsigned long)val);
460 1 : return (unsigned long)val;
461 : }
462 :
463 : /* Get int32_t value from config value object */
464 1 : int32_t ini_get_int32_config_value(struct value_obj *vo,
465 : int strict,
466 : int32_t def,
467 : int *error)
468 : {
469 1 : long long val = 0;
470 1 : int err = 0;
471 :
472 : TRACE_FLOW_ENTRY();
473 :
474 1 : val = ini_get_llong_config_value(vo, strict, def, &err);
475 1 : if (err == 0) {
476 1 : if ((val > INT32_MAX) || (val < INT32_MIN)) {
477 : TRACE_ERROR_NUMBER("Value is out of range", ERANGE);
478 0 : val = def;
479 0 : err = ERANGE;
480 : }
481 : }
482 :
483 1 : if (error) *error = err;
484 :
485 : TRACE_FLOW_NUMBER("ini_get_int32_config_value returning",
486 : (int32_t)val);
487 1 : return (int32_t)val;
488 : }
489 :
490 : /* Get uint32_t value from config value object */
491 1 : uint32_t ini_get_uint32_config_value(struct value_obj *vo,
492 : int strict,
493 : uint32_t def,
494 : int *error)
495 : {
496 1 : unsigned long long val = 0;
497 1 : int err = 0;
498 :
499 : TRACE_FLOW_ENTRY();
500 :
501 1 : val = ini_get_ullong_config_value(vo, strict, def, &err);
502 1 : if (err == 0) {
503 1 : if (val > UINT32_MAX) {
504 : TRACE_ERROR_NUMBER("Value is out of range", ERANGE);
505 0 : val = def;
506 0 : err = ERANGE;
507 : }
508 : }
509 :
510 1 : if (error) *error = err;
511 :
512 : TRACE_FLOW_NUMBER("ini_get_uint32_config_value returning",
513 : (uint32_t)val);
514 1 : return (uint32_t)val;
515 : }
516 :
517 : /* Get int64_t value from config value ovject */
518 1 : int64_t ini_get_int64_config_value(struct value_obj *vo,
519 : int strict,
520 : int64_t def,
521 : int *error)
522 : {
523 1 : long long val = 0;
524 1 : int err = 0;
525 :
526 : TRACE_FLOW_ENTRY();
527 :
528 1 : val = ini_get_llong_config_value(vo, strict, def, &err);
529 : if (err == 0) {
530 : if ((val > INT64_MAX) || (val < INT64_MIN)) {
531 : TRACE_ERROR_NUMBER("Value is out of range", ERANGE);
532 : val = def;
533 : err = ERANGE;
534 : }
535 : }
536 :
537 1 : if (error) *error = err;
538 :
539 : TRACE_FLOW_NUMBER("ini_get_int64_config_value returning",
540 : (int64_t)val);
541 1 : return (int64_t)val;
542 : }
543 :
544 : /* Get uint64_t value from config value object */
545 1 : uint64_t ini_get_uint64_config_value(struct value_obj *vo,
546 : int strict,
547 : uint64_t def,
548 : int *error)
549 : {
550 1 : unsigned long long val = 0;
551 1 : int err = 0;
552 :
553 : TRACE_FLOW_ENTRY();
554 :
555 1 : val = ini_get_ullong_config_value(vo, strict, def, &err);
556 : if (err == 0) {
557 : if (val > UINT64_MAX) {
558 : TRACE_ERROR_NUMBER("Value is out of range", ERANGE);
559 : val = def;
560 : err = ERANGE;
561 : }
562 : }
563 :
564 1 : if (error) *error = err;
565 :
566 : TRACE_FLOW_NUMBER("ini_get_uint64_config_value returning",
567 : (uint64_t)val);
568 1 : return (uint64_t)val;
569 : }
570 :
571 : /* Get double value */
572 1 : double ini_get_double_config_value(struct value_obj *vo,
573 : int strict, double def, int *error)
574 : {
575 : const char *str;
576 : char *endptr;
577 1 : double val = 0;
578 :
579 : TRACE_FLOW_ENTRY();
580 :
581 : /* Do we have the vo ? */
582 1 : if (vo == NULL) {
583 : TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
584 0 : if (error) *error = EINVAL;
585 0 : return def;
586 : }
587 :
588 1 : if (error) *error = EOK;
589 :
590 : /* Get value - no error checking as we checked it above
591 : * and there is no other reason the function could fail.
592 : */
593 1 : value_get_concatenated(vo, &str);
594 :
595 1 : errno = 0;
596 1 : val = strtod(str, &endptr);
597 :
598 : /* Check for various possible errors */
599 1 : if ((errno == ERANGE) ||
600 1 : ((errno != 0) && (val == 0)) ||
601 1 : (endptr == str)) {
602 : TRACE_ERROR_NUMBER("Conversion failed", EIO);
603 0 : if (error) *error = EIO;
604 0 : return def;
605 : }
606 :
607 1 : if (strict && (*endptr != '\0')) {
608 : TRACE_ERROR_NUMBER("More characters than expected", EIO);
609 0 : if (error) *error = EIO;
610 0 : val = def;
611 : }
612 :
613 : TRACE_FLOW_DOUBLE("ini_get_double_config_value returning", val);
614 1 : return val;
615 : }
616 :
617 : /* Get boolean value */
618 2 : unsigned char ini_get_bool_config_value(struct value_obj *vo,
619 : unsigned char def, int *error)
620 : {
621 : const char *str;
622 2 : uint32_t len = 0;
623 :
624 : TRACE_FLOW_ENTRY();
625 :
626 : /* Do we have the vo ? */
627 2 : if (vo == NULL) {
628 : TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
629 0 : if (error) *error = EINVAL;
630 0 : return def;
631 : }
632 :
633 2 : if (error) *error = EOK;
634 :
635 : /* Get value - no error checking as we checked it above
636 : * and there is no other reson the function could fail.
637 : */
638 2 : value_get_concatenated(vo, &str);
639 2 : value_get_concatenated_len(vo, &len);
640 :
641 : /* Try to parse the value */
642 4 : if ((strncasecmp(str, "true", len) == 0) ||
643 2 : (strncasecmp(str, "yes", len) == 0)) {
644 : TRACE_FLOW_STRING("Returning", "true");
645 : return '\1';
646 : }
647 3 : else if ((strncasecmp(str, "false", len) == 0) ||
648 1 : (strncasecmp(str, "no", len) == 0)) {
649 : TRACE_FLOW_STRING("Returning", "false");
650 : return '\0';
651 : }
652 :
653 : TRACE_ERROR_STRING("Returning", "error");
654 1 : if (error) *error = EIO;
655 1 : return def;
656 : }
657 :
658 : /* Return a string out of the value */
659 1 : char *ini_get_string_config_value(struct value_obj *vo,
660 : int *error)
661 : {
662 1 : const char *str = NULL;
663 1 : char *ret_str = NULL;
664 :
665 : TRACE_FLOW_ENTRY();
666 :
667 : /* Do we have the vo ? */
668 1 : if (vo == NULL) {
669 : TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
670 0 : if (error) *error = EINVAL;
671 : return NULL;
672 : }
673 :
674 : /* Get value - no error checking as we checked it above
675 : * and there is no other reson the function could fail.
676 : */
677 1 : value_get_concatenated(vo, &str);
678 :
679 1 : ret_str = strdup(str);
680 1 : if (ret_str == NULL) {
681 : TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM);
682 0 : if (error) *error = ENOMEM;
683 : return NULL;
684 : }
685 :
686 1 : if (error) *error = EOK;
687 :
688 : TRACE_FLOW_STRING("ini_get_string_config_value returning", str);
689 1 : return ret_str;
690 : }
691 :
692 : /* Get string from the value object */
693 3 : const char *ini_get_const_string_config_value(struct value_obj *vo,
694 : int *error)
695 : {
696 : const char *str;
697 :
698 : TRACE_FLOW_ENTRY();
699 :
700 : /* Do we have the vo ? */
701 3 : if (vo == NULL) {
702 : TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
703 1 : if (error) *error = EINVAL;
704 : return NULL;
705 : }
706 :
707 : /* Get value - no error checking as we checked it above
708 : * and there is no other reson the function could fail.
709 : */
710 2 : value_get_concatenated(vo, &str);
711 :
712 2 : if (error) *error = EOK;
713 :
714 : TRACE_FLOW_STRING("ini_get_const_string_config_value returning", str);
715 2 : return str;
716 : }
717 :
718 : /* A special hex format is assumed.
719 : * The string should be taken in single quotes
720 : * and consist of hex encoded value two hex digits per byte.
721 : * Example: '0A2BFECC'
722 : * Case does not matter.
723 : */
724 2 : char *ini_get_bin_config_value(struct value_obj *vo,
725 : int *length, int *error)
726 : {
727 : int i;
728 2 : char *value = NULL;
729 : const char *buff;
730 2 : int size = 0;
731 2 : uint32_t len = 0;
732 : const char *str;
733 :
734 : TRACE_FLOW_ENTRY();
735 :
736 : /* Do we have the vo ? */
737 2 : if (vo == NULL) {
738 : TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
739 0 : if (error) *error = EINVAL;
740 : return NULL;
741 : }
742 :
743 2 : if (error) *error = EOK;
744 :
745 : /* Get value - no error checking as we checked it above
746 : * and there is no other reson the function could fail.
747 : */
748 2 : value_get_concatenated(vo, &str);
749 :
750 : /* Check the length */
751 2 : value_get_concatenated_len(vo, &len);
752 2 : if ((len%2) != 0) {
753 : TRACE_ERROR_STRING("Invalid length for binary data", "");
754 0 : if (error) *error = EINVAL;
755 : return NULL;
756 : }
757 :
758 : /* Is the format correct ? */
759 4 : if ((*str != '\'') ||
760 2 : (str[len -1] != '\'')) {
761 : TRACE_ERROR_STRING("String is not escaped","");
762 0 : if (error) *error = EIO;
763 : return NULL;
764 : }
765 :
766 : /* Check that all the symbols are ok */
767 2 : buff = str + 1;
768 2 : len -= 2;
769 14 : for (i = 0; i < len; i++) {
770 12 : if (!isxdigit(buff[i])) {
771 : TRACE_ERROR_STRING("Invalid encoding for binary data", buff);
772 0 : if (error) *error = EIO;
773 : return NULL;
774 : }
775 : }
776 :
777 : /* The value is good so we can allocate memory for it */
778 2 : value = malloc(len / 2);
779 2 : if (value == NULL) {
780 : TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM);
781 0 : if (error) *error = ENOMEM;
782 : return NULL;
783 : }
784 :
785 : /* Convert the value */
786 6 : for (i = 0; i < len; i += 2) {
787 6 : value[size] = (char)(16 * HEXVAL(buff[i]) + HEXVAL(buff[i+1]));
788 6 : size++;
789 : }
790 :
791 2 : if (error) *error = EOK;
792 2 : if (length) *length = size;
793 : TRACE_FLOW_STRING("ini_get_bin_config_value", "Exit");
794 2 : return value;
795 : }
796 :
797 : /* Function to free binary configuration value */
798 2 : void ini_free_bin_config_value(char *value)
799 : {
800 2 : free(value);
801 2 : }
|