]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/lib/conf/conf.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / spdk / lib / conf / conf.c
CommitLineData
7c673cae
FG
1/*-
2 * BSD LICENSE
3 *
4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
5 * Copyright (c) Intel Corporation.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
11fdf7f2 35#include "spdk/stdinc.h"
7c673cae 36
11fdf7f2 37#include "spdk/conf.h"
7c673cae 38#include "spdk/string.h"
11fdf7f2 39#include "spdk/log.h"
7c673cae
FG
40
41struct spdk_conf_value {
42 struct spdk_conf_value *next;
43 char *value;
44};
45
46struct spdk_conf_item {
47 struct spdk_conf_item *next;
48 char *key;
49 struct spdk_conf_value *val;
50};
51
52struct spdk_conf_section {
53 struct spdk_conf_section *next;
54 char *name;
55 int num;
56 struct spdk_conf_item *item;
57};
58
59struct spdk_conf {
60 char *file;
61 struct spdk_conf_section *current_section;
62 struct spdk_conf_section *section;
63};
64
65#define CF_DELIM " \t"
66
67#define LIB_MAX_TMPBUF 1024
68
69static struct spdk_conf *default_config = NULL;
70
71struct spdk_conf *
72spdk_conf_allocate(void)
73{
74 return calloc(1, sizeof(struct spdk_conf));
75}
76
77static void
78free_conf_value(struct spdk_conf_value *vp)
79{
80 if (vp == NULL) {
81 return;
82 }
83
84 if (vp->value) {
85 free(vp->value);
86 }
87
88 free(vp);
89}
90
91static void
92free_all_conf_value(struct spdk_conf_value *vp)
93{
94 struct spdk_conf_value *next;
95
96 if (vp == NULL) {
97 return;
98 }
99
100 while (vp != NULL) {
101 next = vp->next;
102 free_conf_value(vp);
103 vp = next;
104 }
105}
106
107static void
108free_conf_item(struct spdk_conf_item *ip)
109{
110 if (ip == NULL) {
111 return;
112 }
113
114 if (ip->val != NULL) {
115 free_all_conf_value(ip->val);
116 }
117
118 if (ip->key != NULL) {
119 free(ip->key);
120 }
121
122 free(ip);
123}
124
125static void
126free_all_conf_item(struct spdk_conf_item *ip)
127{
128 struct spdk_conf_item *next;
129
130 if (ip == NULL) {
131 return;
132 }
133
134 while (ip != NULL) {
135 next = ip->next;
136 free_conf_item(ip);
137 ip = next;
138 }
139}
140
141static void
142free_conf_section(struct spdk_conf_section *sp)
143{
144 if (sp == NULL) {
145 return;
146 }
147
148 if (sp->item) {
149 free_all_conf_item(sp->item);
150 }
151
152 if (sp->name) {
153 free(sp->name);
154 }
155
156 free(sp);
157}
158
159static void
160free_all_conf_section(struct spdk_conf_section *sp)
161{
162 struct spdk_conf_section *next;
163
164 if (sp == NULL) {
165 return;
166 }
167
168 while (sp != NULL) {
169 next = sp->next;
170 free_conf_section(sp);
171 sp = next;
172 }
173}
174
175void
176spdk_conf_free(struct spdk_conf *cp)
177{
178 if (cp == NULL) {
179 return;
180 }
181
182 if (cp->section != NULL) {
183 free_all_conf_section(cp->section);
184 }
185
186 if (cp->file != NULL) {
187 free(cp->file);
188 }
189
190 free(cp);
191}
192
193static struct spdk_conf_section *
194allocate_cf_section(void)
195{
196 return calloc(1, sizeof(struct spdk_conf_section));
197}
198
199static struct spdk_conf_item *
200allocate_cf_item(void)
201{
202 return calloc(1, sizeof(struct spdk_conf_item));
203}
204
205static struct spdk_conf_value *
206allocate_cf_value(void)
207{
208 return calloc(1, sizeof(struct spdk_conf_value));
209}
210
211
212#define CHECK_CP_OR_USE_DEFAULT(cp) (((cp) == NULL) && (default_config != NULL)) ? default_config : (cp)
213
214struct spdk_conf_section *
215spdk_conf_find_section(struct spdk_conf *cp, const char *name)
216{
217 struct spdk_conf_section *sp;
218
219 if (name == NULL || name[0] == '\0') {
220 return NULL;
221 }
222
223 cp = CHECK_CP_OR_USE_DEFAULT(cp);
224 if (cp == NULL) {
225 return NULL;
226 }
227
228 for (sp = cp->section; sp != NULL; sp = sp->next) {
229 if (sp->name != NULL && sp->name[0] == name[0]
230 && strcasecmp(sp->name, name) == 0) {
231 return sp;
232 }
233 }
234
235 return NULL;
236}
237
238struct spdk_conf_section *
239spdk_conf_first_section(struct spdk_conf *cp)
240{
241 cp = CHECK_CP_OR_USE_DEFAULT(cp);
242 if (cp == NULL) {
243 return NULL;
244 }
245
246 return cp->section;
247}
248
249struct spdk_conf_section *
250spdk_conf_next_section(struct spdk_conf_section *sp)
251{
252 if (sp == NULL) {
253 return NULL;
254 }
255
256 return sp->next;
257}
258
259static void
260append_cf_section(struct spdk_conf *cp, struct spdk_conf_section *sp)
261{
262 struct spdk_conf_section *last;
263
264 cp = CHECK_CP_OR_USE_DEFAULT(cp);
265 if (cp == NULL) {
11fdf7f2 266 SPDK_ERRLOG("cp == NULL\n");
7c673cae
FG
267 return;
268 }
269
270 if (cp->section == NULL) {
271 cp->section = sp;
272 return;
273 }
274
275 for (last = cp->section; last->next != NULL; last = last->next)
276 ;
277 last->next = sp;
278}
279
280static struct spdk_conf_item *
281find_cf_nitem(struct spdk_conf_section *sp, const char *key, int idx)
282{
283 struct spdk_conf_item *ip;
284 int i;
285
286 if (key == NULL || key[0] == '\0') {
287 return NULL;
288 }
289
290 i = 0;
291 for (ip = sp->item; ip != NULL; ip = ip->next) {
292 if (ip->key != NULL && ip->key[0] == key[0]
293 && strcasecmp(ip->key, key) == 0) {
294 if (i == idx) {
295 return ip;
296 }
297 i++;
298 }
299 }
300
301 return NULL;
302}
303
304static void
305append_cf_item(struct spdk_conf_section *sp, struct spdk_conf_item *ip)
306{
307 struct spdk_conf_item *last;
308
309 if (sp == NULL) {
310 return;
311 }
312
313 if (sp->item == NULL) {
314 sp->item = ip;
315 return;
316 }
317
318 for (last = sp->item; last->next != NULL; last = last->next)
319 ;
320 last->next = ip;
321}
322
323static void
324append_cf_value(struct spdk_conf_item *ip, struct spdk_conf_value *vp)
325{
326 struct spdk_conf_value *last;
327
328 if (ip == NULL) {
329 return;
330 }
331
332 if (ip->val == NULL) {
333 ip->val = vp;
334 return;
335 }
336
337 for (last = ip->val; last->next != NULL; last = last->next)
338 ;
339 last->next = vp;
340}
341
342bool
343spdk_conf_section_match_prefix(const struct spdk_conf_section *sp, const char *name_prefix)
344{
345 return strncasecmp(sp->name, name_prefix, strlen(name_prefix)) == 0;
346}
347
348const char *
349spdk_conf_section_get_name(const struct spdk_conf_section *sp)
350{
351 return sp->name;
352}
353
354int
355spdk_conf_section_get_num(const struct spdk_conf_section *sp)
356{
357 return sp->num;
358}
359
360char *
361spdk_conf_section_get_nmval(struct spdk_conf_section *sp, const char *key, int idx1, int idx2)
362{
363 struct spdk_conf_item *ip;
364 struct spdk_conf_value *vp;
365 int i;
366
367 ip = find_cf_nitem(sp, key, idx1);
368 if (ip == NULL) {
369 return NULL;
370 }
371
372 vp = ip->val;
373 if (vp == NULL) {
374 return NULL;
375 }
376
377 for (i = 0; vp != NULL; vp = vp->next, i++) {
378 if (i == idx2) {
379 return vp->value;
380 }
381 }
382
383 return NULL;
384}
385
386char *
387spdk_conf_section_get_nval(struct spdk_conf_section *sp, const char *key, int idx)
388{
389 struct spdk_conf_item *ip;
390 struct spdk_conf_value *vp;
391
392 ip = find_cf_nitem(sp, key, idx);
393 if (ip == NULL) {
394 return NULL;
395 }
396
397 vp = ip->val;
398 if (vp == NULL) {
399 return NULL;
400 }
401
402 return vp->value;
403}
404
405char *
406spdk_conf_section_get_val(struct spdk_conf_section *sp, const char *key)
407{
408 return spdk_conf_section_get_nval(sp, key, 0);
409}
410
411int
412spdk_conf_section_get_intval(struct spdk_conf_section *sp, const char *key)
413{
414 const char *v;
415 int value;
416
417 v = spdk_conf_section_get_nval(sp, key, 0);
418 if (v == NULL) {
419 return -1;
420 }
421
422 value = (int)strtol(v, NULL, 10);
423 return value;
424}
425
426bool
427spdk_conf_section_get_boolval(struct spdk_conf_section *sp, const char *key, bool default_val)
428{
429 const char *v;
430
431 v = spdk_conf_section_get_nval(sp, key, 0);
432 if (v == NULL) {
433 return default_val;
434 }
435
436 if (!strcasecmp(v, "Yes") || !strcasecmp(v, "Y") || !strcasecmp(v, "True")) {
437 return true;
438 }
439
440 if (!strcasecmp(v, "No") || !strcasecmp(v, "N") || !strcasecmp(v, "False")) {
441 return false;
442 }
443
444 return default_val;
445}
446
447static int
448parse_line(struct spdk_conf *cp, char *lp)
449{
450 struct spdk_conf_section *sp;
451 struct spdk_conf_item *ip;
452 struct spdk_conf_value *vp;
453 char *arg;
454 char *key;
455 char *val;
456 char *p;
457 int num;
458
459 arg = spdk_str_trim(lp);
460 if (arg == NULL) {
11fdf7f2 461 SPDK_ERRLOG("no section\n");
7c673cae
FG
462 return -1;
463 }
464
465 if (arg[0] == '[') {
466 /* section */
467 arg++;
468 key = spdk_strsepq(&arg, "]");
469 if (key == NULL || arg != NULL) {
11fdf7f2 470 SPDK_ERRLOG("broken section\n");
7c673cae
FG
471 return -1;
472 }
473 /* determine section number */
474 for (p = key; *p != '\0' && !isdigit((int) *p); p++)
475 ;
476 if (*p != '\0') {
477 num = (int)strtol(p, NULL, 10);
478 } else {
479 num = 0;
480 }
481
482 sp = spdk_conf_find_section(cp, key);
483 if (sp == NULL) {
484 sp = allocate_cf_section();
485 append_cf_section(cp, sp);
11fdf7f2
TL
486
487 sp->name = strdup(key);
488 if (sp->name == NULL) {
489 SPDK_ERRLOG("cannot duplicate %s to sp->name\n", key);
490 return -1;
491 }
7c673cae
FG
492 }
493 cp->current_section = sp;
11fdf7f2 494
7c673cae
FG
495
496 sp->num = num;
497 } else {
498 /* parameters */
499 sp = cp->current_section;
500 if (sp == NULL) {
11fdf7f2 501 SPDK_ERRLOG("unknown section\n");
7c673cae
FG
502 return -1;
503 }
504 key = spdk_strsepq(&arg, CF_DELIM);
505 if (key == NULL) {
11fdf7f2 506 SPDK_ERRLOG("broken key\n");
7c673cae
FG
507 return -1;
508 }
509
510 ip = allocate_cf_item();
511 if (ip == NULL) {
11fdf7f2 512 SPDK_ERRLOG("cannot allocate cf item\n");
7c673cae
FG
513 return -1;
514 }
515 append_cf_item(sp, ip);
516 ip->key = strdup(key);
517 if (ip->key == NULL) {
11fdf7f2 518 SPDK_ERRLOG("cannot make duplicate of %s\n", key);
7c673cae
FG
519 return -1;
520 }
521 ip->val = NULL;
522 if (arg != NULL) {
523 /* key has value(s) */
524 while (arg != NULL) {
525 val = spdk_strsepq(&arg, CF_DELIM);
526 vp = allocate_cf_value();
527 if (vp == NULL) {
11fdf7f2 528 SPDK_ERRLOG("cannot allocate cf value\n");
7c673cae
FG
529 return -1;
530 }
531 append_cf_value(ip, vp);
532 vp->value = strdup(val);
533 if (vp->value == NULL) {
11fdf7f2 534 SPDK_ERRLOG("cannot duplicate %s to vp->value\n", val);
7c673cae
FG
535 return -1;
536 }
537 }
538 }
539 }
540
541 return 0;
542}
543
544static char *
545fgets_line(FILE *fp)
546{
547 char *dst, *dst2, *p;
548 size_t total, len;
549
550 dst = p = malloc(LIB_MAX_TMPBUF);
551 if (!dst) {
552 return NULL;
553 }
554
555 dst[0] = '\0';
556 total = 0;
557
558 while (fgets(p, LIB_MAX_TMPBUF, fp) != NULL) {
559 len = strlen(p);
560 total += len;
561 if (len + 1 < LIB_MAX_TMPBUF || dst[total - 1] == '\n') {
562 dst2 = realloc(dst, total + 1);
563 if (!dst2) {
564 free(dst);
565 return NULL;
566 } else {
567 return dst2;
568 }
569 }
570
571 dst2 = realloc(dst, total + LIB_MAX_TMPBUF);
572 if (!dst2) {
573 free(dst);
574 return NULL;
575 } else {
576 dst = dst2;
577 }
578
579 p = dst + total;
580 }
581
582 if (feof(fp) && total != 0) {
583 dst2 = realloc(dst, total + 2);
584 if (!dst2) {
585 free(dst);
586 return NULL;
587 } else {
588 dst = dst2;
589 }
590
591 dst[total] = '\n';
592 dst[total + 1] = '\0';
593 return dst;
594 }
595
596 free(dst);
597
598 return NULL;
599}
600
601int
602spdk_conf_read(struct spdk_conf *cp, const char *file)
603{
604 FILE *fp;
605 char *lp, *p;
606 char *lp2, *q;
607 int line;
608 int n, n2;
609
610 if (file == NULL || file[0] == '\0') {
611 return -1;
612 }
613
614 fp = fopen(file, "r");
615 if (fp == NULL) {
11fdf7f2 616 SPDK_ERRLOG("open error: %s\n", file);
7c673cae
FG
617 return -1;
618 }
619
620 cp->file = strdup(file);
621 if (cp->file == NULL) {
11fdf7f2 622 SPDK_ERRLOG("cannot duplicate %s to cp->file\n", file);
7c673cae
FG
623 fclose(fp);
624 return -1;
625 }
626
627 line = 1;
628 while ((lp = fgets_line(fp)) != NULL) {
629 /* skip spaces */
630 for (p = lp; *p != '\0' && isspace((int) *p); p++)
631 ;
632 /* skip comment, empty line */
633 if (p[0] == '#' || p[0] == '\0') {
634 goto next_line;
635 }
636
637 /* concatenate line end with '\' */
638 n = strlen(p);
639 while (n > 2 && p[n - 1] == '\n' && p[n - 2] == '\\') {
640 n -= 2;
641 lp2 = fgets_line(fp);
642 if (lp2 == NULL) {
643 break;
644 }
645
646 line++;
647 n2 = strlen(lp2);
648
649 q = malloc(n + n2 + 1);
650 if (!q) {
651 free(lp2);
652 free(lp);
11fdf7f2 653 SPDK_ERRLOG("malloc failed at line %d of %s\n", line, cp->file);
7c673cae
FG
654 fclose(fp);
655 return -1;
656 }
657
658 memcpy(q, p, n);
659 memcpy(q + n, lp2, n2);
660 q[n + n2] = '\0';
661 free(lp2);
662 free(lp);
663 p = lp = q;
664 n += n2;
665 }
666
667 /* parse one line */
668 if (parse_line(cp, p) < 0) {
11fdf7f2 669 SPDK_ERRLOG("parse error at line %d of %s\n", line, cp->file);
7c673cae
FG
670 }
671next_line:
672 line++;
673 free(lp);
674 }
675
676 fclose(fp);
677 return 0;
678}
679
680void
681spdk_conf_set_as_default(struct spdk_conf *cp)
682{
683 default_config = cp;
684}