]> git.proxmox.com Git - mirror_corosync.git/blob - exec/icmap.c
Add icmap
[mirror_corosync.git] / exec / icmap.c
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>
44 #include <corosync/engine/icmap.h>
45
46 #define ICMAP_MAX_VALUE_LEN (16*1024)
47
48 struct icmap_item {
49 char *key_name;
50 icmap_value_types_t type;
51 size_t value_len;
52 char value[];
53 };
54
55 static qb_map_t *icmap_map;
56
57 struct icmap_track {
58 char *key_name;
59 int32_t track_type;
60 icmap_notify_fn_t notify_fn;
61 void *user_data;
62 };
63
64 struct icmap_ro_access_item {
65 char *key_name;
66 int prefix;
67 struct list_head list;
68 };
69
70 DECLARE_LIST_INIT(icmap_ro_access_item_list_head);
71
72 /*
73 * Static functions declarations
74 */
75
76 /*
77 * Check if key_name is valid icmap key name. Returns 0 on success, and -1 on fail
78 */
79 static int icmap_check_key_name(const char *key_name);
80
81 /*
82 * Check that value with given type has correct length value_len. Returns 0 on success,
83 * and -1 on fail
84 */
85 static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type);
86
87 /*
88 * Returns length of value of given type, or 0 for string and binary data type
89 */
90 static size_t icmap_get_valuetype_len(icmap_value_types_t type);
91
92 /*
93 * Converts track type of icmap to qb
94 */
95 static int32_t icmap_tt_to_qbtt(int32_t track_type);
96
97 /*
98 * Convert track type of qb to icmap
99 */
100 static int32_t icmap_qbtt_to_tt(int32_t track_type);
101
102 /*
103 * Checks if item has same value as value with value_len and given type. Returns 0 if not, otherwise !0.
104 */
105 static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type);
106
107 /*
108 * Checks if given character is valid in key name. Returns 0 if not, otherwise !0.
109 */
110 static int icmap_is_valid_name_char(char c);
111
112 /*
113 * Helper for getting integer and float value with given type for key key_name and store it in value.
114 */
115 static cs_error_t icmap_get_int(
116 const char *key_name,
117 void *value,
118 icmap_value_types_t type);
119
120 /*
121 * Function implementation
122 */
123 static int32_t icmap_tt_to_qbtt(int32_t track_type)
124 {
125 int32_t res = 0;
126
127 if (track_type & ICMAP_TRACK_DELETE) {
128 res |= QB_MAP_NOTIFY_DELETED;
129 }
130
131 if (track_type & ICMAP_TRACK_MODIFY) {
132 res |= QB_MAP_NOTIFY_REPLACED;
133 }
134
135 if (track_type & ICMAP_TRACK_ADD) {
136 res |= QB_MAP_NOTIFY_INSERTED;
137 }
138
139 if (track_type & ICMAP_TRACK_PREFIX) {
140 res |= QB_MAP_NOTIFY_RECURSIVE;
141 }
142
143 return (track_type);
144 }
145
146 static int32_t icmap_qbtt_to_tt(int32_t track_type)
147 {
148 int32_t res = 0;
149
150 if (track_type & QB_MAP_NOTIFY_DELETED) {
151 res |= ICMAP_TRACK_DELETE;
152 }
153
154 if (track_type & QB_MAP_NOTIFY_REPLACED) {
155 res |= ICMAP_TRACK_MODIFY;
156 }
157
158 if (track_type & QB_MAP_NOTIFY_INSERTED) {
159 res |= ICMAP_TRACK_ADD;
160 }
161
162 if (track_type & QB_MAP_NOTIFY_RECURSIVE) {
163 res |= ICMAP_TRACK_PREFIX;
164 }
165
166 return (track_type);
167 }
168
169 static void icmap_map_free_cb(uint32_t event,
170 char* key, void* old_value,
171 void* value, void* user_data)
172 {
173 struct icmap_item *item = (struct icmap_item *)old_value;
174
175 if (item != NULL) {
176 free(item->key_name);
177 free(item);
178 }
179 }
180
181 cs_error_t icmap_init(void)
182 {
183 int32_t err;
184
185 icmap_map = qb_trie_create();
186 if (icmap_map == NULL)
187 return (CS_ERR_INIT);
188
189 err = qb_map_notify_add(icmap_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
190
191 return (qb_to_cs_error(err));
192 }
193
194 static int icmap_is_valid_name_char(char c)
195 {
196 return ((c >= 'a' && c <= 'z') ||
197 (c >= 'A' && c <= 'Z') ||
198 (c >= '0' && c <= '9') ||
199 c == '.' || c == '_' || c == '-' || c == '/' || c == ':');
200 }
201
202 void icmap_convert_name_to_valid_name(char *key_name)
203 {
204 int i;
205
206 for (i = 0; i < strlen(key_name); i++) {
207 if (!icmap_is_valid_name_char(key_name[i])) {
208 key_name[i] = '_';
209 }
210 }
211 }
212
213 static int icmap_check_key_name(const char *key_name)
214 {
215 int i;
216
217 if ((strlen(key_name) < ICMAP_KEYNAME_MINLEN) || strlen(key_name) > ICMAP_KEYNAME_MAXLEN) {
218 return (-1);
219 }
220
221 for (i = 0; i < strlen(key_name); i++) {
222 if (!icmap_is_valid_name_char(key_name[i])) {
223 return (-1);
224 }
225 }
226
227 return (0);
228 }
229
230 static size_t icmap_get_valuetype_len(icmap_value_types_t type)
231 {
232 size_t res;
233
234 switch (type) {
235 case ICMAP_VALUETYPE_INT8: res = sizeof(int8_t); break;
236 case ICMAP_VALUETYPE_UINT8: res = sizeof(uint8_t); break;
237 case ICMAP_VALUETYPE_INT16: res = sizeof(int16_t); break;
238 case ICMAP_VALUETYPE_UINT16: res = sizeof(uint16_t); break;
239 case ICMAP_VALUETYPE_INT32: res = sizeof(int32_t); break;
240 case ICMAP_VALUETYPE_UINT32: res = sizeof(uint32_t); break;
241 case ICMAP_VALUETYPE_INT64: res = sizeof(int64_t); break;
242 case ICMAP_VALUETYPE_UINT64: res = sizeof(uint64_t); break;
243 case ICMAP_VALUETYPE_FLOAT: res = sizeof(float); break;
244 case ICMAP_VALUETYPE_DOUBLE: res = sizeof(double); break;
245 case ICMAP_VALUETYPE_STRING:
246 case ICMAP_VALUETYPE_BINARY:
247 res = 0;
248 break;
249 }
250
251 return (res);
252 }
253
254 static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type)
255 {
256
257 if (value_len > ICMAP_MAX_VALUE_LEN) {
258 return (-1);
259 }
260
261 if (type != ICMAP_VALUETYPE_STRING && type != ICMAP_VALUETYPE_BINARY) {
262 if (icmap_get_valuetype_len(type) == value_len) {
263 return (0);
264 } else {
265 return (-1);
266 }
267 }
268
269 if (type == ICMAP_VALUETYPE_STRING) {
270 if (value_len > strlen((const char *)value)) {
271 return (-1);
272 } else {
273 return (0);
274 }
275 }
276
277 return (0);
278 }
279
280 static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type)
281 {
282 size_t ptr_len;
283
284 if (item->type != type) {
285 return (0);
286 }
287
288 if (item->type == ICMAP_VALUETYPE_STRING) {
289 ptr_len = strlen((const char *)value);
290 if (ptr_len > value_len) {
291 ptr_len = value_len;
292 }
293 ptr_len++;
294 } else {
295 ptr_len = value_len;
296 }
297
298 if (item->value_len == ptr_len) {
299 return (memcmp(item->value, value, value_len) == 0);
300 };
301
302 return (0);
303 }
304
305 cs_error_t icmap_set(
306 const char *key_name,
307 const void *value,
308 size_t value_len,
309 icmap_value_types_t type)
310 {
311 struct icmap_item *item;
312 struct icmap_item *new_item;
313 size_t new_value_len;
314 size_t new_item_size;
315
316 if (value == NULL || key_name == NULL) {
317 return (CS_ERR_INVALID_PARAM);
318 }
319
320 if (icmap_check_value_len(value, value_len, type) != 0) {
321 return (CS_ERR_INVALID_PARAM);
322 }
323
324 item = qb_map_get(icmap_map, key_name);
325 if (item != NULL) {
326 /*
327 * Check that key is really changed
328 */
329 if (icmap_item_eq(item, value, value_len, type)) {
330 return (CS_OK);
331 }
332 } else {
333 if (icmap_check_key_name(key_name) != 0) {
334 return (CS_ERR_NAME_TOO_LONG);
335 }
336 }
337
338 if (type == ICMAP_VALUETYPE_BINARY || type == ICMAP_VALUETYPE_STRING) {
339 if (type == ICMAP_VALUETYPE_STRING) {
340 new_value_len = strlen((const char *)value);
341 if (new_value_len > value_len) {
342 new_value_len = value_len;
343 }
344 new_value_len++;
345 } else {
346 new_value_len = value_len;
347 }
348 } else {
349 new_value_len = icmap_get_valuetype_len(type);
350 }
351
352 new_item_size = sizeof(struct icmap_item) + new_value_len;
353 new_item = malloc(new_item_size);
354 if (new_item == NULL) {
355 return (CS_ERR_NO_MEMORY);
356 }
357 memset(new_item, 0, new_item_size);
358
359 if (item == NULL) {
360 new_item->key_name = strdup(key_name);
361 if (new_item->key_name == NULL) {
362 free(new_item);
363 return (CS_ERR_NO_MEMORY);
364 }
365 } else {
366 new_item->key_name = item->key_name;
367 item->key_name = NULL;
368 }
369
370 new_item->type = type;
371 new_item->value_len = new_value_len;
372
373 memcpy(new_item->value, value, new_value_len);
374
375 if (new_item->type == ICMAP_VALUETYPE_STRING) {
376 ((char *)new_item->value)[new_value_len - 1] = 0;
377 }
378
379 qb_map_put(icmap_map, new_item->key_name, new_item);
380
381 return (CS_OK);
382 }
383
384 cs_error_t icmap_set_int8(const char *key_name, int8_t value)
385 {
386
387 return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT8));
388 }
389
390 cs_error_t icmap_set_uint8(const char *key_name, uint8_t value)
391 {
392
393 return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT8));
394 }
395
396 cs_error_t icmap_set_int16(const char *key_name, int16_t value)
397 {
398
399 return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT16));
400 }
401
402 cs_error_t icmap_set_uint16(const char *key_name, uint16_t value)
403 {
404
405 return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT16));
406 }
407
408 cs_error_t icmap_set_int32(const char *key_name, int32_t value)
409 {
410
411 return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT32));
412 }
413
414 cs_error_t icmap_set_uint32(const char *key_name, uint32_t value)
415 {
416
417 return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT32));
418 }
419
420 cs_error_t icmap_set_int64(const char *key_name, int64_t value)
421 {
422
423 return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT64));
424 }
425
426 cs_error_t icmap_set_uint64(const char *key_name, uint64_t value)
427 {
428
429 return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT64));
430 }
431
432 cs_error_t icmap_set_float(const char *key_name, float value)
433 {
434
435 return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_FLOAT));
436 }
437
438 cs_error_t icmap_set_double(const char *key_name, double value)
439 {
440
441 return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_DOUBLE));
442 }
443
444 cs_error_t icmap_set_string(const char *key_name, const char *value)
445 {
446
447 return (icmap_set(key_name, value, strlen(value), ICMAP_VALUETYPE_STRING));
448 }
449
450 cs_error_t icmap_delete(const char *key_name)
451 {
452 struct icmap_item *item;
453
454 if (key_name == NULL) {
455 return (CS_ERR_INVALID_PARAM);
456 }
457
458 item = qb_map_get(icmap_map, key_name);
459 if (item == NULL) {
460 return (CS_ERR_NOT_EXIST);
461 }
462
463 if (qb_map_rm(icmap_map, item->key_name) != QB_TRUE) {
464 return (CS_ERR_NOT_EXIST);
465 }
466
467 return (CS_OK);
468 }
469
470 cs_error_t icmap_get(
471 const char *key_name,
472 void *value,
473 size_t *value_len,
474 icmap_value_types_t *type)
475 {
476 struct icmap_item *item;
477
478 if (key_name == NULL) {
479 return (CS_ERR_INVALID_PARAM);
480 }
481
482 item = qb_map_get(icmap_map, key_name);
483 if (item == NULL) {
484 return (CS_ERR_NOT_EXIST);
485 }
486
487 if (type != NULL) {
488 *type = item->type;
489 }
490
491 if (value == NULL) {
492 if (value_len != NULL) {
493 *value_len = item->value_len;
494 }
495 } else {
496 if (value_len == NULL || *value_len < item->value_len) {
497 return (CS_ERR_INVALID_PARAM);
498 }
499
500 *value_len = item->value_len;
501
502 memcpy(value, item->value, item->value_len);
503 }
504
505 return (CS_OK);
506 }
507
508 static cs_error_t icmap_get_int(
509 const char *key_name,
510 void *value,
511 icmap_value_types_t type)
512 {
513 char key_value[16];
514 size_t key_size;
515 cs_error_t err;
516 icmap_value_types_t key_type;
517
518 key_size = sizeof(key_value);
519 memset(key_value, 0, key_size);
520
521 err = icmap_get(key_name, key_value, &key_size, &key_type);
522 if (err != CS_OK)
523 return (err);
524
525 if (key_type != type) {
526 return (CS_ERR_INVALID_PARAM);
527 }
528
529 memcpy(value, key_value, icmap_get_valuetype_len(key_type));
530
531 return (CS_OK);
532 }
533
534 cs_error_t icmap_get_int8(const char *key_name, int8_t *i8)
535 {
536
537 return (icmap_get_int(key_name, i8, ICMAP_VALUETYPE_INT8));
538 }
539
540 cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8)
541 {
542
543 return (icmap_get_int(key_name, u8, ICMAP_VALUETYPE_UINT8));
544 }
545
546 cs_error_t icmap_get_int16(const char *key_name, int16_t *i16)
547 {
548
549 return (icmap_get_int(key_name, i16, ICMAP_VALUETYPE_INT16));
550 }
551
552 cs_error_t icmap_get_uint16(const char *key_name, uint16_t *u16)
553 {
554
555 return (icmap_get_int(key_name, u16, ICMAP_VALUETYPE_UINT16));
556 }
557
558 cs_error_t icmap_get_int32(const char *key_name, int32_t *i32)
559 {
560
561 return (icmap_get_int(key_name, i32, ICMAP_VALUETYPE_INT32));
562 }
563
564 cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32)
565 {
566
567 return (icmap_get_int(key_name, u32, ICMAP_VALUETYPE_UINT32));
568 }
569
570 cs_error_t icmap_get_int64(const char *key_name, int64_t *i64)
571 {
572
573 return(icmap_get_int(key_name, i64, ICMAP_VALUETYPE_INT64));
574 }
575
576 cs_error_t icmap_get_uint64(const char *key_name, uint64_t *u64)
577 {
578
579 return (icmap_get_int(key_name, u64, ICMAP_VALUETYPE_UINT64));
580 }
581
582 cs_error_t icmap_get_float(const char *key_name, float *flt)
583 {
584
585 return (icmap_get_int(key_name, flt, ICMAP_VALUETYPE_FLOAT));
586 }
587
588 cs_error_t icmap_get_double(const char *key_name, double *dbl)
589 {
590
591 return (icmap_get_int(key_name, dbl, ICMAP_VALUETYPE_DOUBLE));
592 }
593
594 cs_error_t icmap_get_string(const char *key_name, char **str)
595 {
596 cs_error_t res;
597 size_t str_len;
598 icmap_value_types_t type;
599
600 res = icmap_get(key_name, NULL, &str_len, &type);
601 if (res != CS_OK || type != ICMAP_VALUETYPE_STRING) {
602 if (res == CS_OK) {
603 res = CS_ERR_INVALID_PARAM;
604 }
605
606 goto return_error;
607 }
608
609 *str = malloc(str_len);
610 if (*str == NULL) {
611 res = CS_ERR_NO_MEMORY;
612
613 goto return_error;
614 }
615
616 res = icmap_get(key_name, *str, &str_len, &type);
617 if (res != CS_OK) {
618 free(*str);
619 goto return_error;
620 }
621
622 return (CS_OK);
623
624 return_error:
625 return (res);
626 }
627
628 cs_error_t icmap_adjust_int(
629 const char *key_name,
630 int32_t step)
631 {
632 struct icmap_item *item;
633 uint8_t u8;
634 uint16_t u16;
635 uint32_t u32;
636 uint64_t u64;
637 cs_error_t err = CS_OK;
638
639 if (key_name == NULL) {
640 return (CS_ERR_INVALID_PARAM);
641 }
642
643 item = qb_map_get(icmap_map, key_name);
644 if (item == NULL) {
645 return (CS_ERR_NOT_EXIST);
646 }
647
648 switch (item->type) {
649 case ICMAP_VALUETYPE_INT8:
650 case ICMAP_VALUETYPE_UINT8:
651 memcpy(&u8, item->value, sizeof(u8));
652 u8 += step;
653 err = icmap_set(key_name, &u8, sizeof(u8), item->type);
654 break;
655 case ICMAP_VALUETYPE_INT16:
656 case ICMAP_VALUETYPE_UINT16:
657 memcpy(&u16, item->value, sizeof(u16));
658 u16 += step;
659 err = icmap_set(key_name, &u16, sizeof(u16), item->type);
660 break;
661 case ICMAP_VALUETYPE_INT32:
662 case ICMAP_VALUETYPE_UINT32:
663 memcpy(&u32, item->value, sizeof(u32));
664 u32 += step;
665 err = icmap_set(key_name, &u32, sizeof(u32), item->type);
666 break;
667 case ICMAP_VALUETYPE_INT64:
668 case ICMAP_VALUETYPE_UINT64:
669 memcpy(&u64, item->value, sizeof(u64));
670 u64 += step;
671 err = icmap_set(key_name, &u64, sizeof(u64), item->type);
672 break;
673 case ICMAP_VALUETYPE_FLOAT:
674 case ICMAP_VALUETYPE_DOUBLE:
675 case ICMAP_VALUETYPE_STRING:
676 case ICMAP_VALUETYPE_BINARY:
677 err = CS_ERR_INVALID_PARAM;
678 break;
679 }
680
681 return (err);
682 }
683
684 cs_error_t icmap_inc(const char *key_name)
685 {
686 return (icmap_adjust_int(key_name, 1));
687 }
688
689 cs_error_t icmap_dec(const char *key_name)
690 {
691 return (icmap_adjust_int(key_name, -1));
692 }
693
694 icmap_iter_t icmap_iter_init(const char *prefix)
695 {
696 return (qb_map_pref_iter_create(icmap_map, prefix));
697 }
698
699 const char *icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
700 {
701 struct icmap_item *item;
702 const char *res;
703
704 res = qb_map_iter_next(iter, (void **)&item);
705 if (res == NULL) {
706 return (res);
707 }
708
709 if (value_len != NULL) {
710 *value_len = item->value_len;
711 }
712
713 if (type != NULL) {
714 *type = item->type;
715 }
716
717 return (res);
718 }
719
720 void icmap_iter_finalize(icmap_iter_t iter)
721 {
722 qb_map_iter_free(iter);
723 }
724
725 static void icmap_notify_fn(uint32_t event, char *key, void *old_value, void *value, void *user_data)
726 {
727 icmap_track_t icmap_track = (icmap_track_t)user_data;
728 struct icmap_item *new_item = (struct icmap_item *)value;
729 struct icmap_item *old_item = (struct icmap_item *)old_value;
730 struct icmap_notify_value new_val;
731 struct icmap_notify_value old_val;
732
733 if (value == NULL && old_value == NULL) {
734 return ;
735 }
736
737 if (new_item != NULL) {
738 new_val.type = new_item->type;
739 new_val.len = new_item->value_len;
740 new_val.data = new_item->value;
741 } else {
742 memset(&new_val, 0, sizeof(new_val));
743 }
744
745 if (old_item != NULL) {
746 old_val.type = old_item->type;
747 old_val.len = old_item->value_len;
748 old_val.data = old_item->value;
749 } else {
750 memset(&old_val, 0, sizeof(old_val));
751 }
752
753 icmap_track->notify_fn(icmap_qbtt_to_tt(event),
754 key,
755 new_val,
756 old_val,
757 icmap_track->user_data);
758 }
759
760 cs_error_t icmap_track_add(
761 const char *key_name,
762 int32_t track_type,
763 icmap_notify_fn_t notify_fn,
764 void *user_data,
765 icmap_track_t *icmap_track)
766 {
767 int32_t err;
768
769 if (notify_fn == NULL || icmap_track == NULL) {
770 return (CS_ERR_INVALID_PARAM);
771 }
772
773 if ((track_type & ~(ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX)) != 0) {
774 return (CS_ERR_INVALID_PARAM);
775 }
776
777 *icmap_track = malloc(sizeof(**icmap_track));
778 if (*icmap_track == NULL) {
779 return (CS_ERR_NO_MEMORY);
780 }
781 memset(*icmap_track, 0, sizeof(**icmap_track));
782
783 if (key_name != NULL) {
784 (*icmap_track)->key_name = strdup(key_name);
785 };
786
787 (*icmap_track)->track_type = track_type;
788 (*icmap_track)->notify_fn = notify_fn;
789 (*icmap_track)->user_data = user_data;
790
791 if ((err = qb_map_notify_add(icmap_map, (*icmap_track)->key_name, icmap_notify_fn,
792 icmap_tt_to_qbtt(track_type), *icmap_track)) != 0) {
793 free((*icmap_track)->key_name);
794 free(*icmap_track);
795
796 return (qb_to_cs_error(err));
797 }
798
799 return (CS_OK);
800 }
801
802 cs_error_t icmap_track_delete(icmap_track_t icmap_track)
803 {
804 int32_t err;
805
806 if ((err = qb_map_notify_del_2(icmap_map, icmap_track->key_name,
807 icmap_notify_fn, icmap_tt_to_qbtt(icmap_track->track_type), icmap_track)) != 0) {
808 return (qb_to_cs_error(err));
809 }
810
811 free(icmap_track->key_name);
812 free(icmap_track);
813
814 return (CS_OK);
815 }
816
817 void *icmap_track_get_user_data(icmap_track_t icmap_track)
818 {
819 return (icmap_track->user_data);
820 }
821
822 cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access)
823 {
824 struct list_head *iter;
825 struct icmap_ro_access_item *icmap_ro_ai;
826
827 for (iter = icmap_ro_access_item_list_head.next; iter != &icmap_ro_access_item_list_head; iter = iter->next) {
828 icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
829
830 if (icmap_ro_ai->prefix == prefix && strcmp(key_name, icmap_ro_ai->key_name) == 0) {
831 /*
832 * We found item
833 */
834 if (ro_access) {
835 return (CS_ERR_EXIST);
836 } else {
837 list_del(&icmap_ro_ai->list);
838 free(icmap_ro_ai);
839
840 return (CS_OK);
841 }
842 }
843 }
844
845 if (!ro_access) {
846 return (CS_ERR_NOT_EXIST);
847 }
848
849 icmap_ro_ai = malloc(sizeof(*icmap_ro_ai));
850 if (icmap_ro_ai == NULL) {
851 return (CS_ERR_NO_MEMORY);
852 }
853
854 memset(icmap_ro_ai, 0, sizeof(*icmap_ro_ai));
855 icmap_ro_ai->key_name = strdup(key_name);
856 if (icmap_ro_ai->key_name == NULL) {
857 free(icmap_ro_ai);
858 return (CS_ERR_NO_MEMORY);
859 }
860
861 icmap_ro_ai->prefix = prefix;
862 list_init(&icmap_ro_ai->list);
863 list_add (&icmap_ro_ai->list, &icmap_ro_access_item_list_head);
864
865 return (CS_OK);
866 }
867
868 int icmap_is_key_ro(const char *key_name)
869 {
870 struct list_head *iter;
871 struct icmap_ro_access_item *icmap_ro_ai;
872
873 for (iter = icmap_ro_access_item_list_head.next; iter != &icmap_ro_access_item_list_head; iter = iter->next) {
874 icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
875
876 if (icmap_ro_ai->prefix) {
877 if (strlen(icmap_ro_ai->key_name) > strlen(key_name))
878 continue;
879
880 if (strncmp(icmap_ro_ai->key_name, key_name, strlen(icmap_ro_ai->key_name)) == 0) {
881 return (CS_TRUE);
882 }
883 } else {
884 if (strcmp(icmap_ro_ai->key_name, key_name) == 0) {
885 return (CS_TRUE);
886 }
887 }
888 }
889
890 return (CS_FALSE);
891
892 }