]> git.proxmox.com Git - mirror_corosync.git/blame - exec/icmap.c
icmap: Fix value len checking for strings
[mirror_corosync.git] / exec / icmap.c
CommitLineData
525e6a6e
JF
1/*
2 * Copyright (c) 2011 Red Hat, Inc.
3 *
4 * All rights reserved.
5 *
6 * Author: Jan Friesse (jfriesse@redhat.com)
7 *
8 * This software licensed under BSD license, the text of which follows:
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the Red Hat, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <config.h>
36
37#include <string.h>
38#include <stdio.h>
39
40#include <corosync/corotypes.h>
41
42#include <qb/qbdefs.h>
43#include <corosync/list.h>
7e1c9771 44#include <corosync/icmap.h>
525e6a6e
JF
45
46#define ICMAP_MAX_VALUE_LEN (16*1024)
47
48struct icmap_item {
49 char *key_name;
50 icmap_value_types_t type;
51 size_t value_len;
52 char value[];
53};
54
e5a528c5
JF
55struct icmap_map {
56 qb_map_t *qb_map;
57};
58
59static icmap_map_t icmap_global_map;
525e6a6e
JF
60
61struct icmap_track {
62 char *key_name;
63 int32_t track_type;
64 icmap_notify_fn_t notify_fn;
65 void *user_data;
1dcb2d43 66 struct list_head list;
525e6a6e
JF
67};
68
69struct icmap_ro_access_item {
70 char *key_name;
71 int prefix;
72 struct list_head list;
73};
74
75DECLARE_LIST_INIT(icmap_ro_access_item_list_head);
1dcb2d43 76DECLARE_LIST_INIT(icmap_track_list_head);
525e6a6e
JF
77
78/*
79 * Static functions declarations
80 */
81
82/*
83 * Check if key_name is valid icmap key name. Returns 0 on success, and -1 on fail
84 */
85static int icmap_check_key_name(const char *key_name);
86
87/*
88 * Check that value with given type has correct length value_len. Returns 0 on success,
89 * and -1 on fail
90 */
91static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type);
92
93/*
94 * Returns length of value of given type, or 0 for string and binary data type
95 */
96static size_t icmap_get_valuetype_len(icmap_value_types_t type);
97
98/*
99 * Converts track type of icmap to qb
100 */
101static int32_t icmap_tt_to_qbtt(int32_t track_type);
102
103/*
104 * Convert track type of qb to icmap
105 */
106static int32_t icmap_qbtt_to_tt(int32_t track_type);
107
108/*
109 * Checks if item has same value as value with value_len and given type. Returns 0 if not, otherwise !0.
110 */
111static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type);
112
113/*
114 * Checks if given character is valid in key name. Returns 0 if not, otherwise !0.
115 */
116static int icmap_is_valid_name_char(char c);
117
118/*
119 * Helper for getting integer and float value with given type for key key_name and store it in value.
120 */
e5a528c5
JF
121static cs_error_t icmap_get_int_r(
122 const icmap_map_t map,
525e6a6e
JF
123 const char *key_name,
124 void *value,
125 icmap_value_types_t type);
126
127/*
128 * Function implementation
129 */
130static int32_t icmap_tt_to_qbtt(int32_t track_type)
131{
132 int32_t res = 0;
133
134 if (track_type & ICMAP_TRACK_DELETE) {
135 res |= QB_MAP_NOTIFY_DELETED;
136 }
137
138 if (track_type & ICMAP_TRACK_MODIFY) {
139 res |= QB_MAP_NOTIFY_REPLACED;
140 }
141
142 if (track_type & ICMAP_TRACK_ADD) {
143 res |= QB_MAP_NOTIFY_INSERTED;
144 }
145
146 if (track_type & ICMAP_TRACK_PREFIX) {
147 res |= QB_MAP_NOTIFY_RECURSIVE;
148 }
149
8a2e9363 150 return (res);
525e6a6e
JF
151}
152
153static int32_t icmap_qbtt_to_tt(int32_t track_type)
154{
155 int32_t res = 0;
156
157 if (track_type & QB_MAP_NOTIFY_DELETED) {
158 res |= ICMAP_TRACK_DELETE;
159 }
160
161 if (track_type & QB_MAP_NOTIFY_REPLACED) {
162 res |= ICMAP_TRACK_MODIFY;
163 }
164
165 if (track_type & QB_MAP_NOTIFY_INSERTED) {
166 res |= ICMAP_TRACK_ADD;
167 }
168
169 if (track_type & QB_MAP_NOTIFY_RECURSIVE) {
170 res |= ICMAP_TRACK_PREFIX;
171 }
172
8a2e9363 173 return (res);
525e6a6e
JF
174}
175
176static void icmap_map_free_cb(uint32_t event,
177 char* key, void* old_value,
178 void* value, void* user_data)
179{
180 struct icmap_item *item = (struct icmap_item *)old_value;
181
a1df899d
JF
182 /*
183 * value == old_value -> fast_adjust_int was used, don't free data
184 */
185 if (item != NULL && value != old_value) {
525e6a6e
JF
186 free(item->key_name);
187 free(item);
188 }
189}
190
e5a528c5 191cs_error_t icmap_init_r(icmap_map_t *result)
525e6a6e
JF
192{
193 int32_t err;
194
e5a528c5
JF
195 *result = malloc(sizeof(struct icmap_map));
196 if (*result == NULL) {
197 return (CS_ERR_NO_MEMORY);
198 }
199
200 (*result)->qb_map = qb_trie_create();
201 if ((*result)->qb_map == NULL)
525e6a6e
JF
202 return (CS_ERR_INIT);
203
e5a528c5 204 err = qb_map_notify_add((*result)->qb_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
525e6a6e
JF
205
206 return (qb_to_cs_error(err));
207}
208
e5a528c5
JF
209cs_error_t icmap_init(void)
210{
211 return (icmap_init_r(&icmap_global_map));
212}
213
1dcb2d43
FDN
214static void icmap_set_ro_access_free(void)
215{
216 struct list_head *iter = icmap_ro_access_item_list_head.next;
217 struct icmap_ro_access_item *icmap_ro_ai;
218
219 while (iter != &icmap_ro_access_item_list_head) {
220 icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
221 list_del(&icmap_ro_ai->list);
222 free(icmap_ro_ai->key_name);
223 free(icmap_ro_ai);
224 iter = icmap_ro_access_item_list_head.next;
225 }
226}
227
228static void icmap_del_all_track(void)
229{
230 struct list_head *iter = icmap_track_list_head.next;
231 struct icmap_track *icmap_track;
232
233 while (iter != &icmap_track_list_head) {
234 icmap_track = list_entry(iter, struct icmap_track, list);
235 icmap_track_delete(icmap_track);
236 iter = icmap_track_list_head.next;
237 }
238}
239
e5a528c5
JF
240void icmap_fini_r(const icmap_map_t map)
241{
242
243 qb_map_destroy(map->qb_map);
244 free(map);
245
246 return;
247}
248
1dcb2d43
FDN
249void icmap_fini(void)
250{
e5a528c5 251
1dcb2d43
FDN
252 icmap_del_all_track();
253 /*
254 * catch 22 warning:
255 * We need to drop this notify but we can't because it calls icmap_map_free_cb
256 * while destroying the tree to free icmap_item(s).
257 * -> qb_map_notify_del_2(icmap_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
258 * and we cannot call it after map_destroy. joy! :)
259 */
e5a528c5 260 icmap_fini_r(icmap_global_map);
1dcb2d43 261 icmap_set_ro_access_free();
e5a528c5
JF
262
263 return ;
1dcb2d43
FDN
264}
265
04ddddd6
JF
266icmap_map_t icmap_get_global_map(void)
267{
268
269 return (icmap_global_map);
270}
271
525e6a6e
JF
272static int icmap_is_valid_name_char(char c)
273{
274 return ((c >= 'a' && c <= 'z') ||
275 (c >= 'A' && c <= 'Z') ||
276 (c >= '0' && c <= '9') ||
277 c == '.' || c == '_' || c == '-' || c == '/' || c == ':');
278}
279
280void icmap_convert_name_to_valid_name(char *key_name)
281{
282 int i;
283
284 for (i = 0; i < strlen(key_name); i++) {
285 if (!icmap_is_valid_name_char(key_name[i])) {
286 key_name[i] = '_';
287 }
288 }
289}
290
291static int icmap_check_key_name(const char *key_name)
292{
293 int i;
294
295 if ((strlen(key_name) < ICMAP_KEYNAME_MINLEN) || strlen(key_name) > ICMAP_KEYNAME_MAXLEN) {
296 return (-1);
297 }
298
299 for (i = 0; i < strlen(key_name); i++) {
300 if (!icmap_is_valid_name_char(key_name[i])) {
301 return (-1);
302 }
303 }
304
305 return (0);
306}
307
308static size_t icmap_get_valuetype_len(icmap_value_types_t type)
309{
841a7a82 310 size_t res = 0;
525e6a6e
JF
311
312 switch (type) {
313 case ICMAP_VALUETYPE_INT8: res = sizeof(int8_t); break;
314 case ICMAP_VALUETYPE_UINT8: res = sizeof(uint8_t); break;
315 case ICMAP_VALUETYPE_INT16: res = sizeof(int16_t); break;
316 case ICMAP_VALUETYPE_UINT16: res = sizeof(uint16_t); break;
317 case ICMAP_VALUETYPE_INT32: res = sizeof(int32_t); break;
318 case ICMAP_VALUETYPE_UINT32: res = sizeof(uint32_t); break;
319 case ICMAP_VALUETYPE_INT64: res = sizeof(int64_t); break;
320 case ICMAP_VALUETYPE_UINT64: res = sizeof(uint64_t); break;
321 case ICMAP_VALUETYPE_FLOAT: res = sizeof(float); break;
322 case ICMAP_VALUETYPE_DOUBLE: res = sizeof(double); break;
323 case ICMAP_VALUETYPE_STRING:
324 case ICMAP_VALUETYPE_BINARY:
325 res = 0;
326 break;
327 }
328
329 return (res);
330}
331
332static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type)
333{
334
335 if (value_len > ICMAP_MAX_VALUE_LEN) {
336 return (-1);
337 }
338
339 if (type != ICMAP_VALUETYPE_STRING && type != ICMAP_VALUETYPE_BINARY) {
340 if (icmap_get_valuetype_len(type) == value_len) {
341 return (0);
342 } else {
343 return (-1);
344 }
345 }
346
347 if (type == ICMAP_VALUETYPE_STRING) {
624cd439
JF
348 /*
349 * value_len can be shorter then real string length, but never
350 * longer (+ 1 is because of 0 at the end of string)
351 */
352 if (value_len > strlen((const char *)value) + 1) {
525e6a6e
JF
353 return (-1);
354 } else {
355 return (0);
356 }
357 }
358
359 return (0);
360}
361
362static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type)
363{
364 size_t ptr_len;
365
366 if (item->type != type) {
367 return (0);
368 }
369
370 if (item->type == ICMAP_VALUETYPE_STRING) {
371 ptr_len = strlen((const char *)value);
372 if (ptr_len > value_len) {
373 ptr_len = value_len;
374 }
375 ptr_len++;
376 } else {
377 ptr_len = value_len;
378 }
379
380 if (item->value_len == ptr_len) {
381 return (memcmp(item->value, value, value_len) == 0);
382 };
383
384 return (0);
385}
386
e5a528c5
JF
387cs_error_t icmap_set_r(
388 const icmap_map_t map,
525e6a6e
JF
389 const char *key_name,
390 const void *value,
391 size_t value_len,
392 icmap_value_types_t type)
393{
394 struct icmap_item *item;
395 struct icmap_item *new_item;
396 size_t new_value_len;
397 size_t new_item_size;
398
399 if (value == NULL || key_name == NULL) {
400 return (CS_ERR_INVALID_PARAM);
401 }
402
403 if (icmap_check_value_len(value, value_len, type) != 0) {
404 return (CS_ERR_INVALID_PARAM);
405 }
406
e5a528c5 407 item = qb_map_get(map->qb_map, key_name);
525e6a6e
JF
408 if (item != NULL) {
409 /*
410 * Check that key is really changed
411 */
412 if (icmap_item_eq(item, value, value_len, type)) {
413 return (CS_OK);
414 }
415 } else {
416 if (icmap_check_key_name(key_name) != 0) {
417 return (CS_ERR_NAME_TOO_LONG);
418 }
419 }
420
421 if (type == ICMAP_VALUETYPE_BINARY || type == ICMAP_VALUETYPE_STRING) {
422 if (type == ICMAP_VALUETYPE_STRING) {
423 new_value_len = strlen((const char *)value);
424 if (new_value_len > value_len) {
425 new_value_len = value_len;
426 }
427 new_value_len++;
428 } else {
429 new_value_len = value_len;
430 }
431 } else {
432 new_value_len = icmap_get_valuetype_len(type);
433 }
434
435 new_item_size = sizeof(struct icmap_item) + new_value_len;
436 new_item = malloc(new_item_size);
437 if (new_item == NULL) {
438 return (CS_ERR_NO_MEMORY);
439 }
440 memset(new_item, 0, new_item_size);
441
442 if (item == NULL) {
443 new_item->key_name = strdup(key_name);
444 if (new_item->key_name == NULL) {
445 free(new_item);
446 return (CS_ERR_NO_MEMORY);
447 }
448 } else {
449 new_item->key_name = item->key_name;
450 item->key_name = NULL;
451 }
452
453 new_item->type = type;
454 new_item->value_len = new_value_len;
455
456 memcpy(new_item->value, value, new_value_len);
457
458 if (new_item->type == ICMAP_VALUETYPE_STRING) {
459 ((char *)new_item->value)[new_value_len - 1] = 0;
460 }
461
e5a528c5 462 qb_map_put(map->qb_map, new_item->key_name, new_item);
525e6a6e
JF
463
464 return (CS_OK);
465}
466
e5a528c5
JF
467cs_error_t icmap_set(
468 const char *key_name,
469 const void *value,
470 size_t value_len,
471 icmap_value_types_t type)
472{
473
474 return (icmap_set_r(icmap_global_map, key_name, value, value_len, type));
475}
476
477cs_error_t icmap_set_int8_r(const icmap_map_t map, const char *key_name, int8_t value)
478{
479
480 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT8));
481}
482
483cs_error_t icmap_set_uint8_r(const icmap_map_t map, const char *key_name, uint8_t value)
484{
485
486 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT8));
487}
488
489cs_error_t icmap_set_int16_r(const icmap_map_t map, const char *key_name, int16_t value)
490{
491
492 return (icmap_set_r(map,key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT16));
493}
494
495cs_error_t icmap_set_uint16_r(const icmap_map_t map, const char *key_name, uint16_t value)
496{
497
498 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT16));
499}
500
501cs_error_t icmap_set_int32_r(const icmap_map_t map, const char *key_name, int32_t value)
502{
503
504 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT32));
505}
506
507cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value)
508{
509
510 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT32));
511}
512
513cs_error_t icmap_set_int64_r(const icmap_map_t map, const char *key_name, int64_t value)
514{
515
516 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT64));
517}
518
519cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value)
520{
521
522 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT64));
523}
524
525cs_error_t icmap_set_float_r(const icmap_map_t map, const char *key_name, float value)
526{
527
528 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_FLOAT));
529}
530
531cs_error_t icmap_set_double_r(const icmap_map_t map, const char *key_name, double value)
532{
533
534 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_DOUBLE));
535}
536
537cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value)
538{
539
540 if (value == NULL) {
541 return (CS_ERR_INVALID_PARAM);
542 }
543
544 return (icmap_set_r(map, key_name, value, strlen(value), ICMAP_VALUETYPE_STRING));
545}
546
525e6a6e
JF
547cs_error_t icmap_set_int8(const char *key_name, int8_t value)
548{
549
e5a528c5 550 return (icmap_set_int8_r(icmap_global_map, key_name, value));
525e6a6e
JF
551}
552
553cs_error_t icmap_set_uint8(const char *key_name, uint8_t value)
554{
555
e5a528c5 556 return (icmap_set_uint8_r(icmap_global_map, key_name, value));
525e6a6e
JF
557}
558
559cs_error_t icmap_set_int16(const char *key_name, int16_t value)
560{
561
e5a528c5 562 return (icmap_set_int16_r(icmap_global_map, key_name, value));
525e6a6e
JF
563}
564
565cs_error_t icmap_set_uint16(const char *key_name, uint16_t value)
566{
567
e5a528c5 568 return (icmap_set_uint16_r(icmap_global_map, key_name, value));
525e6a6e
JF
569}
570
571cs_error_t icmap_set_int32(const char *key_name, int32_t value)
572{
573
e5a528c5 574 return (icmap_set_int32_r(icmap_global_map, key_name, value));
525e6a6e
JF
575}
576
577cs_error_t icmap_set_uint32(const char *key_name, uint32_t value)
578{
579
e5a528c5 580 return (icmap_set_uint32_r(icmap_global_map, key_name, value));
525e6a6e
JF
581}
582
583cs_error_t icmap_set_int64(const char *key_name, int64_t value)
584{
585
e5a528c5 586 return (icmap_set_int64_r(icmap_global_map, key_name, value));
525e6a6e
JF
587}
588
589cs_error_t icmap_set_uint64(const char *key_name, uint64_t value)
590{
591
e5a528c5 592 return (icmap_set_uint64_r(icmap_global_map, key_name, value));
525e6a6e
JF
593}
594
595cs_error_t icmap_set_float(const char *key_name, float value)
596{
597
e5a528c5 598 return (icmap_set_float_r(icmap_global_map, key_name, value));
525e6a6e
JF
599}
600
601cs_error_t icmap_set_double(const char *key_name, double value)
602{
603
e5a528c5 604 return (icmap_set_double_r(icmap_global_map, key_name, value));
525e6a6e
JF
605}
606
607cs_error_t icmap_set_string(const char *key_name, const char *value)
608{
609
e5a528c5 610 return (icmap_set_string_r(icmap_global_map, key_name, value));
525e6a6e
JF
611}
612
e5a528c5 613cs_error_t icmap_delete_r(const icmap_map_t map, const char *key_name)
525e6a6e
JF
614{
615 struct icmap_item *item;
616
617 if (key_name == NULL) {
618 return (CS_ERR_INVALID_PARAM);
619 }
620
e5a528c5 621 item = qb_map_get(map->qb_map, key_name);
525e6a6e
JF
622 if (item == NULL) {
623 return (CS_ERR_NOT_EXIST);
624 }
625
e5a528c5 626 if (qb_map_rm(map->qb_map, item->key_name) != QB_TRUE) {
525e6a6e
JF
627 return (CS_ERR_NOT_EXIST);
628 }
629
630 return (CS_OK);
631}
632
e5a528c5
JF
633cs_error_t icmap_delete(const char *key_name)
634{
635
636 return (icmap_delete_r(icmap_global_map, key_name));
637}
638
639cs_error_t icmap_get_r(
640 const icmap_map_t map,
525e6a6e
JF
641 const char *key_name,
642 void *value,
643 size_t *value_len,
644 icmap_value_types_t *type)
645{
646 struct icmap_item *item;
647
648 if (key_name == NULL) {
649 return (CS_ERR_INVALID_PARAM);
650 }
651
e5a528c5 652 item = qb_map_get(map->qb_map, key_name);
525e6a6e
JF
653 if (item == NULL) {
654 return (CS_ERR_NOT_EXIST);
655 }
656
657 if (type != NULL) {
658 *type = item->type;
659 }
660
661 if (value == NULL) {
662 if (value_len != NULL) {
663 *value_len = item->value_len;
664 }
665 } else {
666 if (value_len == NULL || *value_len < item->value_len) {
667 return (CS_ERR_INVALID_PARAM);
668 }
669
670 *value_len = item->value_len;
671
672 memcpy(value, item->value, item->value_len);
673 }
674
675 return (CS_OK);
676}
677
e5a528c5
JF
678cs_error_t icmap_get(
679 const char *key_name,
680 void *value,
681 size_t *value_len,
682 icmap_value_types_t *type)
683{
684
685 return (icmap_get_r(icmap_global_map, key_name, value, value_len, type));
686}
687
688static cs_error_t icmap_get_int_r(
689 const icmap_map_t map,
525e6a6e
JF
690 const char *key_name,
691 void *value,
692 icmap_value_types_t type)
693{
694 char key_value[16];
695 size_t key_size;
696 cs_error_t err;
697 icmap_value_types_t key_type;
698
699 key_size = sizeof(key_value);
700 memset(key_value, 0, key_size);
701
702 err = icmap_get(key_name, key_value, &key_size, &key_type);
703 if (err != CS_OK)
704 return (err);
705
706 if (key_type != type) {
707 return (CS_ERR_INVALID_PARAM);
708 }
709
710 memcpy(value, key_value, icmap_get_valuetype_len(key_type));
711
712 return (CS_OK);
713}
714
e5a528c5
JF
715cs_error_t icmap_get_int8_r(const icmap_map_t map, const char *key_name, int8_t *i8)
716{
717
718 return (icmap_get_int_r(map, key_name, i8, ICMAP_VALUETYPE_INT8));
719}
720
721cs_error_t icmap_get_uint8_r(const icmap_map_t map, const char *key_name, uint8_t *u8)
722{
723
724 return (icmap_get_int_r(map, key_name, u8, ICMAP_VALUETYPE_UINT8));
725}
726
727cs_error_t icmap_get_int16_r(const icmap_map_t map, const char *key_name, int16_t *i16)
728{
729
730 return (icmap_get_int_r(map, key_name, i16, ICMAP_VALUETYPE_INT16));
731}
732
733cs_error_t icmap_get_uint16_r(const icmap_map_t map, const char *key_name, uint16_t *u16)
734{
735
736 return (icmap_get_int_r(map, key_name, u16, ICMAP_VALUETYPE_UINT16));
737}
738
739cs_error_t icmap_get_int32_r(const icmap_map_t map, const char *key_name, int32_t *i32)
740{
741
742 return (icmap_get_int_r(map, key_name, i32, ICMAP_VALUETYPE_INT32));
743}
744
745cs_error_t icmap_get_uint32_r(const icmap_map_t map, const char *key_name, uint32_t *u32)
746{
747
748 return (icmap_get_int_r(map, key_name, u32, ICMAP_VALUETYPE_UINT32));
749}
750
751cs_error_t icmap_get_int64_r(const icmap_map_t map, const char *key_name, int64_t *i64)
752{
753
754 return(icmap_get_int_r(map, key_name, i64, ICMAP_VALUETYPE_INT64));
755}
756
757cs_error_t icmap_get_uint64_r(const icmap_map_t map, const char *key_name, uint64_t *u64)
758{
759
760 return (icmap_get_int_r(map, key_name, u64, ICMAP_VALUETYPE_UINT64));
761}
762
763cs_error_t icmap_get_float_r(const icmap_map_t map, const char *key_name, float *flt)
764{
765
766 return (icmap_get_int_r(map, key_name, flt, ICMAP_VALUETYPE_FLOAT));
767}
768
769cs_error_t icmap_get_double_r(const icmap_map_t map, const char *key_name, double *dbl)
770{
771
772 return (icmap_get_int_r(map, key_name, dbl, ICMAP_VALUETYPE_DOUBLE));
773}
774
525e6a6e
JF
775cs_error_t icmap_get_int8(const char *key_name, int8_t *i8)
776{
777
e5a528c5 778 return (icmap_get_int8_r(icmap_global_map, key_name, i8));
525e6a6e
JF
779}
780
781cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8)
782{
783
e5a528c5 784 return (icmap_get_uint8_r(icmap_global_map, key_name, u8));
525e6a6e
JF
785}
786
787cs_error_t icmap_get_int16(const char *key_name, int16_t *i16)
788{
789
e5a528c5 790 return (icmap_get_int16_r(icmap_global_map, key_name, i16));
525e6a6e
JF
791}
792
793cs_error_t icmap_get_uint16(const char *key_name, uint16_t *u16)
794{
795
e5a528c5 796 return (icmap_get_uint16_r(icmap_global_map, key_name, u16));
525e6a6e
JF
797}
798
799cs_error_t icmap_get_int32(const char *key_name, int32_t *i32)
800{
801
e5a528c5 802 return (icmap_get_int32_r(icmap_global_map, key_name, i32));
525e6a6e
JF
803}
804
805cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32)
806{
807
e5a528c5 808 return (icmap_get_uint32_r(icmap_global_map, key_name, u32));
525e6a6e
JF
809}
810
811cs_error_t icmap_get_int64(const char *key_name, int64_t *i64)
812{
813
e5a528c5 814 return(icmap_get_int64_r(icmap_global_map, key_name, i64));
525e6a6e
JF
815}
816
817cs_error_t icmap_get_uint64(const char *key_name, uint64_t *u64)
818{
819
e5a528c5 820 return (icmap_get_uint64_r(icmap_global_map, key_name, u64));
525e6a6e
JF
821}
822
823cs_error_t icmap_get_float(const char *key_name, float *flt)
824{
825
e5a528c5 826 return (icmap_get_float_r(icmap_global_map, key_name, flt));
525e6a6e
JF
827}
828
829cs_error_t icmap_get_double(const char *key_name, double *dbl)
830{
831
e5a528c5 832 return (icmap_get_double_r(icmap_global_map, key_name, dbl));
525e6a6e
JF
833}
834
835cs_error_t icmap_get_string(const char *key_name, char **str)
836{
837 cs_error_t res;
838 size_t str_len;
839 icmap_value_types_t type;
840
841 res = icmap_get(key_name, NULL, &str_len, &type);
842 if (res != CS_OK || type != ICMAP_VALUETYPE_STRING) {
843 if (res == CS_OK) {
844 res = CS_ERR_INVALID_PARAM;
845 }
846
847 goto return_error;
848 }
849
850 *str = malloc(str_len);
851 if (*str == NULL) {
852 res = CS_ERR_NO_MEMORY;
853
854 goto return_error;
855 }
856
857 res = icmap_get(key_name, *str, &str_len, &type);
858 if (res != CS_OK) {
859 free(*str);
860 goto return_error;
861 }
862
863 return (CS_OK);
864
865return_error:
866 return (res);
867}
868
e5a528c5
JF
869cs_error_t icmap_adjust_int_r(
870 const icmap_map_t map,
525e6a6e
JF
871 const char *key_name,
872 int32_t step)
873{
874 struct icmap_item *item;
875 uint8_t u8;
876 uint16_t u16;
877 uint32_t u32;
878 uint64_t u64;
879 cs_error_t err = CS_OK;
880
881 if (key_name == NULL) {
882 return (CS_ERR_INVALID_PARAM);
883 }
884
e5a528c5 885 item = qb_map_get(map->qb_map, key_name);
525e6a6e
JF
886 if (item == NULL) {
887 return (CS_ERR_NOT_EXIST);
888 }
889
890 switch (item->type) {
891 case ICMAP_VALUETYPE_INT8:
892 case ICMAP_VALUETYPE_UINT8:
893 memcpy(&u8, item->value, sizeof(u8));
894 u8 += step;
895 err = icmap_set(key_name, &u8, sizeof(u8), item->type);
896 break;
897 case ICMAP_VALUETYPE_INT16:
898 case ICMAP_VALUETYPE_UINT16:
899 memcpy(&u16, item->value, sizeof(u16));
900 u16 += step;
901 err = icmap_set(key_name, &u16, sizeof(u16), item->type);
902 break;
903 case ICMAP_VALUETYPE_INT32:
904 case ICMAP_VALUETYPE_UINT32:
905 memcpy(&u32, item->value, sizeof(u32));
906 u32 += step;
907 err = icmap_set(key_name, &u32, sizeof(u32), item->type);
908 break;
909 case ICMAP_VALUETYPE_INT64:
910 case ICMAP_VALUETYPE_UINT64:
911 memcpy(&u64, item->value, sizeof(u64));
912 u64 += step;
913 err = icmap_set(key_name, &u64, sizeof(u64), item->type);
914 break;
915 case ICMAP_VALUETYPE_FLOAT:
916 case ICMAP_VALUETYPE_DOUBLE:
917 case ICMAP_VALUETYPE_STRING:
918 case ICMAP_VALUETYPE_BINARY:
919 err = CS_ERR_INVALID_PARAM;
920 break;
921 }
922
923 return (err);
924}
925
e5a528c5
JF
926cs_error_t icmap_adjust_int(
927 const char *key_name,
928 int32_t step)
929{
930
931 return (icmap_adjust_int_r(icmap_global_map, key_name, step));
932}
933
934cs_error_t icmap_fast_adjust_int_r(
935 const icmap_map_t map,
a1df899d
JF
936 const char *key_name,
937 int32_t step)
938{
939 struct icmap_item *item;
940 cs_error_t err = CS_OK;
941
942 if (key_name == NULL) {
943 return (CS_ERR_INVALID_PARAM);
944 }
945
e5a528c5 946 item = qb_map_get(map->qb_map, key_name);
a1df899d
JF
947 if (item == NULL) {
948 return (CS_ERR_NOT_EXIST);
949 }
950
951 switch (item->type) {
952 case ICMAP_VALUETYPE_INT8:
953 case ICMAP_VALUETYPE_UINT8:
954 *(uint8_t *)item->value += step;
955 break;
956 case ICMAP_VALUETYPE_INT16:
957 case ICMAP_VALUETYPE_UINT16:
958 *(uint16_t *)item->value += step;
959 break;
960 case ICMAP_VALUETYPE_INT32:
961 case ICMAP_VALUETYPE_UINT32:
962 *(uint32_t *)item->value += step;
963 break;
964 case ICMAP_VALUETYPE_INT64:
965 case ICMAP_VALUETYPE_UINT64:
966 *(uint64_t *)item->value += step;
967 break;
968 case ICMAP_VALUETYPE_FLOAT:
969 case ICMAP_VALUETYPE_DOUBLE:
970 case ICMAP_VALUETYPE_STRING:
971 case ICMAP_VALUETYPE_BINARY:
972 err = CS_ERR_INVALID_PARAM;
973 break;
974 }
975
976 if (err == CS_OK) {
e5a528c5 977 qb_map_put(map->qb_map, item->key_name, item);
a1df899d
JF
978 }
979
980 return (err);
981}
982
e5a528c5
JF
983cs_error_t icmap_fast_adjust_int(
984 const char *key_name,
985 int32_t step)
986{
987
988 return (icmap_fast_adjust_int_r(icmap_global_map, key_name, step));
989}
990
991cs_error_t icmap_inc_r(const icmap_map_t map, const char *key_name)
992{
993 return (icmap_adjust_int_r(map, key_name, 1));
994}
995
525e6a6e
JF
996cs_error_t icmap_inc(const char *key_name)
997{
e5a528c5
JF
998 return (icmap_inc_r(icmap_global_map, key_name));
999}
1000
1001cs_error_t icmap_dec_r(const icmap_map_t map, const char *key_name)
1002{
1003 return (icmap_adjust_int_r(map, key_name, -1));
525e6a6e
JF
1004}
1005
1006cs_error_t icmap_dec(const char *key_name)
1007{
e5a528c5
JF
1008 return (icmap_dec_r(icmap_global_map, key_name));
1009}
1010
1011cs_error_t icmap_fast_inc_r(const icmap_map_t map, const char *key_name)
1012{
1013 return (icmap_fast_adjust_int_r(map, key_name, 1));
525e6a6e
JF
1014}
1015
a1df899d
JF
1016cs_error_t icmap_fast_inc(const char *key_name)
1017{
e5a528c5
JF
1018 return (icmap_fast_inc_r(icmap_global_map, key_name));
1019}
1020
1021cs_error_t icmap_fast_dec_r(const icmap_map_t map, const char *key_name)
1022{
1023 return (icmap_fast_adjust_int_r(map, key_name, -1));
a1df899d
JF
1024}
1025
1026cs_error_t icmap_fast_dec(const char *key_name)
1027{
e5a528c5
JF
1028 return (icmap_fast_dec_r(icmap_global_map, key_name));
1029}
1030
1031icmap_iter_t icmap_iter_init_r(const icmap_map_t map, const char *prefix)
1032{
1033 return (qb_map_pref_iter_create(map->qb_map, prefix));
a1df899d
JF
1034}
1035
525e6a6e
JF
1036icmap_iter_t icmap_iter_init(const char *prefix)
1037{
e5a528c5 1038 return (icmap_iter_init_r(icmap_global_map, prefix));
525e6a6e
JF
1039}
1040
e5a528c5 1041
525e6a6e
JF
1042const char *icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
1043{
1044 struct icmap_item *item;
1045 const char *res;
1046
1047 res = qb_map_iter_next(iter, (void **)&item);
1048 if (res == NULL) {
1049 return (res);
1050 }
1051
1052 if (value_len != NULL) {
1053 *value_len = item->value_len;
1054 }
1055
1056 if (type != NULL) {
1057 *type = item->type;
1058 }
1059
1060 return (res);
1061}
1062
1063void icmap_iter_finalize(icmap_iter_t iter)
1064{
1065 qb_map_iter_free(iter);
1066}
1067
1068static void icmap_notify_fn(uint32_t event, char *key, void *old_value, void *value, void *user_data)
1069{
1070 icmap_track_t icmap_track = (icmap_track_t)user_data;
1071 struct icmap_item *new_item = (struct icmap_item *)value;
1072 struct icmap_item *old_item = (struct icmap_item *)old_value;
1073 struct icmap_notify_value new_val;
1074 struct icmap_notify_value old_val;
1075
1076 if (value == NULL && old_value == NULL) {
1077 return ;
1078 }
1079
1080 if (new_item != NULL) {
1081 new_val.type = new_item->type;
1082 new_val.len = new_item->value_len;
1083 new_val.data = new_item->value;
1084 } else {
1085 memset(&new_val, 0, sizeof(new_val));
1086 }
1087
a1df899d
JF
1088 /*
1089 * old_item == new_item if fast functions are used -> don't fill old value
1090 */
1091 if (old_item != NULL && old_item != new_item) {
525e6a6e
JF
1092 old_val.type = old_item->type;
1093 old_val.len = old_item->value_len;
1094 old_val.data = old_item->value;
1095 } else {
1096 memset(&old_val, 0, sizeof(old_val));
1097 }
1098
1099 icmap_track->notify_fn(icmap_qbtt_to_tt(event),
1100 key,
1101 new_val,
1102 old_val,
1103 icmap_track->user_data);
1104}
1105
1106cs_error_t icmap_track_add(
1107 const char *key_name,
1108 int32_t track_type,
1109 icmap_notify_fn_t notify_fn,
1110 void *user_data,
1111 icmap_track_t *icmap_track)
1112{
1113 int32_t err;
1114
1115 if (notify_fn == NULL || icmap_track == NULL) {
1116 return (CS_ERR_INVALID_PARAM);
1117 }
1118
1119 if ((track_type & ~(ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX)) != 0) {
1120 return (CS_ERR_INVALID_PARAM);
1121 }
1122
1123 *icmap_track = malloc(sizeof(**icmap_track));
1124 if (*icmap_track == NULL) {
1125 return (CS_ERR_NO_MEMORY);
1126 }
1127 memset(*icmap_track, 0, sizeof(**icmap_track));
1128
1129 if (key_name != NULL) {
1130 (*icmap_track)->key_name = strdup(key_name);
1131 };
1132
1133 (*icmap_track)->track_type = track_type;
1134 (*icmap_track)->notify_fn = notify_fn;
1135 (*icmap_track)->user_data = user_data;
1136
e5a528c5 1137 if ((err = qb_map_notify_add(icmap_global_map->qb_map, (*icmap_track)->key_name, icmap_notify_fn,
525e6a6e
JF
1138 icmap_tt_to_qbtt(track_type), *icmap_track)) != 0) {
1139 free((*icmap_track)->key_name);
1140 free(*icmap_track);
1141
1142 return (qb_to_cs_error(err));
1143 }
1144
1dcb2d43
FDN
1145 list_init(&(*icmap_track)->list);
1146 list_add (&(*icmap_track)->list, &icmap_track_list_head);
1147
525e6a6e
JF
1148 return (CS_OK);
1149}
1150
1151cs_error_t icmap_track_delete(icmap_track_t icmap_track)
1152{
1153 int32_t err;
1154
e5a528c5 1155 if ((err = qb_map_notify_del_2(icmap_global_map->qb_map, icmap_track->key_name,
525e6a6e
JF
1156 icmap_notify_fn, icmap_tt_to_qbtt(icmap_track->track_type), icmap_track)) != 0) {
1157 return (qb_to_cs_error(err));
1158 }
1159
1dcb2d43 1160 list_del(&icmap_track->list);
525e6a6e
JF
1161 free(icmap_track->key_name);
1162 free(icmap_track);
1163
1164 return (CS_OK);
1165}
1166
1167void *icmap_track_get_user_data(icmap_track_t icmap_track)
1168{
1169 return (icmap_track->user_data);
1170}
1171
1172cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access)
1173{
1174 struct list_head *iter;
1175 struct icmap_ro_access_item *icmap_ro_ai;
1176
1177 for (iter = icmap_ro_access_item_list_head.next; iter != &icmap_ro_access_item_list_head; iter = iter->next) {
1178 icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
1179
1180 if (icmap_ro_ai->prefix == prefix && strcmp(key_name, icmap_ro_ai->key_name) == 0) {
1181 /*
1182 * We found item
1183 */
1184 if (ro_access) {
1185 return (CS_ERR_EXIST);
1186 } else {
1187 list_del(&icmap_ro_ai->list);
f2444eff 1188 free(icmap_ro_ai->key_name);
525e6a6e
JF
1189 free(icmap_ro_ai);
1190
1191 return (CS_OK);
1192 }
1193 }
1194 }
1195
1196 if (!ro_access) {
1197 return (CS_ERR_NOT_EXIST);
1198 }
1199
1200 icmap_ro_ai = malloc(sizeof(*icmap_ro_ai));
1201 if (icmap_ro_ai == NULL) {
1202 return (CS_ERR_NO_MEMORY);
1203 }
1204
1205 memset(icmap_ro_ai, 0, sizeof(*icmap_ro_ai));
1206 icmap_ro_ai->key_name = strdup(key_name);
1207 if (icmap_ro_ai->key_name == NULL) {
1208 free(icmap_ro_ai);
1209 return (CS_ERR_NO_MEMORY);
1210 }
1211
1212 icmap_ro_ai->prefix = prefix;
1213 list_init(&icmap_ro_ai->list);
1214 list_add (&icmap_ro_ai->list, &icmap_ro_access_item_list_head);
1215
1216 return (CS_OK);
1217}
1218
1219int icmap_is_key_ro(const char *key_name)
1220{
1221 struct list_head *iter;
1222 struct icmap_ro_access_item *icmap_ro_ai;
1223
1224 for (iter = icmap_ro_access_item_list_head.next; iter != &icmap_ro_access_item_list_head; iter = iter->next) {
1225 icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
1226
1227 if (icmap_ro_ai->prefix) {
1228 if (strlen(icmap_ro_ai->key_name) > strlen(key_name))
1229 continue;
1230
1231 if (strncmp(icmap_ro_ai->key_name, key_name, strlen(icmap_ro_ai->key_name)) == 0) {
1232 return (CS_TRUE);
1233 }
1234 } else {
1235 if (strcmp(icmap_ro_ai->key_name, key_name) == 0) {
1236 return (CS_TRUE);
1237 }
1238 }
1239 }
1240
1241 return (CS_FALSE);
1242
1243}