Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #include <assert.h>
6 : : #include <stdio.h>
7 : : #include <stdlib.h>
8 : : #include <string.h>
9 : : #include <ctype.h>
10 : : #include <errno.h>
11 : : #include <limits.h>
12 : :
13 : : #ifndef LINE_MAX
14 : : #define LINE_MAX 2048
15 : : #endif
16 : :
17 : : #include <eal_export.h>
18 : : #include <rte_string_fns.h>
19 : : #include <rte_common.h>
20 : : #include <rte_log.h>
21 : :
22 : : #include "rte_cfgfile.h"
23 : :
24 : : struct rte_cfgfile_section {
25 : : char name[CFG_NAME_LEN];
26 : : int num_entries;
27 : : int allocated_entries;
28 : : struct rte_cfgfile_entry *entries;
29 : : };
30 : :
31 : : struct rte_cfgfile {
32 : : int flags;
33 : : int num_sections;
34 : : int allocated_sections;
35 : : struct rte_cfgfile_section *sections;
36 : : };
37 : :
38 : : /* Setting up dynamic logging 8< */
39 [ - + ]: 276 : RTE_LOG_REGISTER_DEFAULT(cfgfile_logtype, INFO);
40 : : #define RTE_LOGTYPE_CFGFILE cfgfile_logtype
41 : :
42 : : #define CFG_LOG(level, ...) \
43 : : RTE_LOG_LINE_PREFIX(level, CFGFILE, "%s(): ", __func__, __VA_ARGS__)
44 : : /* >8 End of setting up dynamic logging */
45 : :
46 : : /** when we resize a file structure, how many extra entries
47 : : * for new sections do we add in */
48 : : #define CFG_ALLOC_SECTION_BATCH 8
49 : : /** when we resize a section structure, how many extra entries
50 : : * for new entries do we add in */
51 : : #define CFG_ALLOC_ENTRY_BATCH 16
52 : :
53 : : /**
54 : : * Default cfgfile load parameters.
55 : : */
56 : : static const struct rte_cfgfile_parameters default_cfgfile_params = {
57 : : .comment_character = CFG_DEFAULT_COMMENT_CHARACTER,
58 : : };
59 : :
60 : : /**
61 : : * Defines the list of acceptable comment characters supported by this
62 : : * library.
63 : : */
64 : : static const char valid_comment_chars[] = {
65 : : '!',
66 : : '#',
67 : : '%',
68 : : ';',
69 : : '@'
70 : : };
71 : :
72 : : static unsigned
73 : 420 : _strip(char *str, unsigned len)
74 : : {
75 : 420 : int newlen = len;
76 [ + + ]: 420 : if (len == 0)
77 : : return 0;
78 : :
79 [ + + ]: 406 : if (isspace(str[len-1])) {
80 : : /* strip trailing whitespace */
81 [ + + + + ]: 302 : while (newlen > 0 && isspace(str[newlen - 1]))
82 : 151 : str[--newlen] = '\0';
83 : : }
84 : :
85 [ - + ]: 406 : if (isspace(str[0])) {
86 : : /* strip leading whitespace */
87 : : int i, start = 1;
88 [ # # # # ]: 0 : while (isspace(str[start]) && start < newlen)
89 : 0 : start++
90 : : ; /* do nothing */
91 : 0 : newlen -= start;
92 [ # # ]: 0 : for (i = 0; i < newlen; i++)
93 : 0 : str[i] = str[i+start];
94 : 0 : str[i] = '\0';
95 : : }
96 : 406 : return newlen;
97 : : }
98 : :
99 : : static struct rte_cfgfile_section *
100 : 24 : _get_section(struct rte_cfgfile *cfg, const char *sectionname)
101 : : {
102 : : int i;
103 : :
104 [ + - ]: 58 : for (i = 0; i < cfg->num_sections; i++) {
105 [ + + ]: 58 : if (strncmp(cfg->sections[i].name, sectionname,
106 : : sizeof(cfg->sections[0].name)) == 0)
107 : 24 : return &cfg->sections[i];
108 : : }
109 : : return NULL;
110 : : }
111 : :
112 : : static int
113 : 119 : _add_entry(struct rte_cfgfile_section *section, const char *entryname,
114 : : const char *entryvalue)
115 : : {
116 [ + - + - ]: 119 : if (strlen(entryname) >= CFG_NAME_LEN || strlen(entryvalue) >= CFG_VALUE_LEN)
117 : : return -ENAMETOOLONG;
118 : :
119 : : /* resize entry structure if we don't have room for more entries */
120 [ + + ]: 119 : if (section->num_entries == section->allocated_entries) {
121 : 4 : struct rte_cfgfile_entry *n_entries = realloc(
122 : 4 : section->entries,
123 : : sizeof(struct rte_cfgfile_entry) *
124 : 4 : ((section->allocated_entries) +
125 : : CFG_ALLOC_ENTRY_BATCH));
126 : :
127 [ + - ]: 4 : if (n_entries == NULL)
128 : : return -ENOMEM;
129 : :
130 : 4 : section->entries = n_entries;
131 : 4 : section->allocated_entries += CFG_ALLOC_ENTRY_BATCH;
132 : : }
133 : : /* fill up entry fields with key name and value */
134 : 119 : struct rte_cfgfile_entry *curr_entry =
135 : 119 : §ion->entries[section->num_entries];
136 : :
137 : 119 : strlcpy(curr_entry->name, entryname, sizeof(curr_entry->name));
138 : 119 : strlcpy(curr_entry->value, entryvalue, sizeof(curr_entry->value));
139 : 119 : section->num_entries++;
140 : :
141 : 119 : return 0;
142 : : }
143 : :
144 : : static int
145 : 10 : rte_cfgfile_check_params(const struct rte_cfgfile_parameters *params)
146 : : {
147 : : unsigned int valid_comment;
148 : : unsigned int i;
149 : :
150 [ - + ]: 10 : if (!params) {
151 : 0 : CFG_LOG(ERR, "missing cfgfile parameters");
152 : 0 : return -EINVAL;
153 : : }
154 : :
155 : : valid_comment = 0;
156 [ + + ]: 40 : for (i = 0; i < RTE_DIM(valid_comment_chars); i++) {
157 [ + + ]: 39 : if (params->comment_character == valid_comment_chars[i]) {
158 : : valid_comment = 1;
159 : : break;
160 : : }
161 : : }
162 : :
163 [ + + ]: 10 : if (valid_comment == 0) {
164 : 1 : CFG_LOG(ERR, "invalid comment characters %c",
165 : : params->comment_character);
166 : 1 : return -ENOTSUP;
167 : : }
168 : :
169 : : return 0;
170 : : }
171 : :
172 : : RTE_EXPORT_SYMBOL(rte_cfgfile_load)
173 : : struct rte_cfgfile *
174 : 8 : rte_cfgfile_load(const char *filename, int flags)
175 : : {
176 : 8 : return rte_cfgfile_load_with_params(filename, flags,
177 : : &default_cfgfile_params);
178 : : }
179 : :
180 : : /* Need enough space for largest name and value */
181 : : static_assert(CFG_NAME_LEN + CFG_VALUE_LEN + 4 < LINE_MAX,
182 : : "not enough space for cfgfile name/value");
183 : :
184 : : RTE_EXPORT_SYMBOL(rte_cfgfile_load_with_params)
185 : : struct rte_cfgfile *
186 : 10 : rte_cfgfile_load_with_params(const char *filename, int flags,
187 : : const struct rte_cfgfile_parameters *params)
188 : : {
189 : : char buffer[LINE_MAX];
190 : : int lineno = 0;
191 : : struct rte_cfgfile *cfg;
192 : :
193 [ + + ]: 10 : if (rte_cfgfile_check_params(params))
194 : : return NULL;
195 : :
196 : 9 : FILE *f = fopen(filename, "r");
197 [ + - ]: 9 : if (f == NULL)
198 : : return NULL;
199 : :
200 : 9 : cfg = rte_cfgfile_create(flags);
201 : :
202 [ + + ]: 178 : while (fgets(buffer, sizeof(buffer), f) != NULL) {
203 : : char *pos;
204 : 163 : size_t len = strnlen(buffer, sizeof(buffer));
205 : 163 : lineno++;
206 [ - + - - ]: 163 : if ((len >= sizeof(buffer) - 1) && (buffer[len-1] != '\n')) {
207 : 0 : CFG_LOG(ERR, " line %d - no \\n found on string. "
208 : : "Check if line too long", lineno);
209 : 0 : goto error1;
210 : : }
211 : : /* skip parsing if comment character found */
212 : 163 : pos = memchr(buffer, params->comment_character, len);
213 [ + + + + ]: 163 : if (pos != NULL &&
214 [ + - ]: 2 : (pos == buffer || *(pos-1) != '\\')) {
215 : 14 : *pos = '\0';
216 : 14 : len = pos - buffer;
217 : : }
218 : :
219 : 163 : len = _strip(buffer, len);
220 : : /* skip lines without useful content */
221 [ + + + + ]: 163 : if (buffer[0] != '[' && memchr(buffer, '=', len) == NULL)
222 : 26 : continue;
223 : :
224 [ + + ]: 137 : if (buffer[0] == '[') {
225 : : /* section heading line */
226 : 16 : char *end = memchr(buffer, ']', len);
227 [ + + ]: 16 : if (end == NULL) {
228 : 1 : CFG_LOG(ERR,
229 : : "line %d - no terminating ']' character found",
230 : : lineno);
231 : 1 : goto error1;
232 : : }
233 : 15 : *end = '\0';
234 : 15 : _strip(&buffer[1], end - &buffer[1]);
235 : :
236 : 15 : int ret = rte_cfgfile_add_section(cfg, &buffer[1]);
237 [ - + ]: 15 : if (ret != 0) {
238 : 0 : CFG_LOG(ERR,
239 : : "line %d - add section failed: %s",
240 : : lineno, strerror(-ret));
241 : 0 : goto error1;
242 : : }
243 : : } else {
244 : : /* key and value line */
245 : : char *split[2] = {NULL};
246 : :
247 : : split[0] = buffer;
248 : 121 : split[1] = memchr(buffer, '=', len);
249 [ - + ]: 121 : if (split[1] == NULL) {
250 : 0 : CFG_LOG(ERR,
251 : : "line %d - no '=' character found",
252 : : lineno);
253 : 0 : goto error1;
254 : : }
255 : 121 : *split[1] = '\0';
256 : 121 : split[1]++;
257 : :
258 : 121 : _strip(split[0], strlen(split[0]));
259 : 121 : _strip(split[1], strlen(split[1]));
260 : 121 : char *end = memchr(split[1], '\\', strlen(split[1]));
261 : :
262 : 121 : size_t split_len = strlen(split[1]) + 1;
263 [ - + ]: 121 : while (end != NULL) {
264 [ # # ]: 0 : if (*(end+1) == params->comment_character) {
265 : 0 : *end = '\0';
266 : 0 : strlcat(split[1], end+1, split_len);
267 : : } else
268 : 0 : end++;
269 : 0 : end = memchr(end, '\\', strlen(end));
270 : : }
271 : :
272 [ + + ]: 121 : if (!(flags & CFG_FLAG_EMPTY_VALUES) &&
273 [ + + ]: 120 : (*split[1] == '\0')) {
274 : 1 : CFG_LOG(ERR,
275 : : "line %d - cannot use empty values",
276 : : lineno);
277 : 1 : goto error1;
278 : : }
279 : :
280 [ + + ]: 120 : if (cfg->num_sections == 0)
281 : 1 : goto error1;
282 : :
283 : 119 : int ret = _add_entry(&cfg->sections[cfg->num_sections - 1],
284 : : split[0], split[1]);
285 [ - + ]: 119 : if (ret != 0) {
286 : 0 : CFG_LOG(ERR,
287 : : "line %d - add entry failed: %s", lineno, strerror(-ret));
288 : 0 : goto error1;
289 : : }
290 : : }
291 : : }
292 : 6 : fclose(f);
293 : 6 : return cfg;
294 : 3 : error1:
295 : 3 : rte_cfgfile_close(cfg);
296 : 3 : fclose(f);
297 : 3 : return NULL;
298 : : }
299 : :
300 : : RTE_EXPORT_SYMBOL(rte_cfgfile_create)
301 : : struct rte_cfgfile *
302 : 9 : rte_cfgfile_create(int flags)
303 : : {
304 : : int i;
305 : : struct rte_cfgfile *cfg;
306 : :
307 : : /* future proof flags usage */
308 [ + - ]: 9 : if (flags & ~(CFG_FLAG_GLOBAL_SECTION | CFG_FLAG_EMPTY_VALUES))
309 : : return NULL;
310 : :
311 : 9 : cfg = malloc(sizeof(*cfg));
312 : :
313 [ + - ]: 9 : if (cfg == NULL)
314 : : return NULL;
315 : :
316 : 9 : cfg->flags = flags;
317 : 9 : cfg->num_sections = 0;
318 : :
319 : : /* allocate first batch of sections and entries */
320 : 9 : cfg->sections = calloc(CFG_ALLOC_SECTION_BATCH,
321 : : sizeof(struct rte_cfgfile_section));
322 [ - + ]: 9 : if (cfg->sections == NULL)
323 : 0 : goto error1;
324 : :
325 : 9 : cfg->allocated_sections = CFG_ALLOC_SECTION_BATCH;
326 : :
327 [ + + ]: 81 : for (i = 0; i < CFG_ALLOC_SECTION_BATCH; i++) {
328 : 72 : cfg->sections[i].entries = calloc(CFG_ALLOC_ENTRY_BATCH,
329 : : sizeof(struct rte_cfgfile_entry));
330 : :
331 [ - + ]: 72 : if (cfg->sections[i].entries == NULL)
332 : 0 : goto error1;
333 : :
334 : 72 : cfg->sections[i].num_entries = 0;
335 : 72 : cfg->sections[i].allocated_entries = CFG_ALLOC_ENTRY_BATCH;
336 : : }
337 : :
338 [ + + ]: 9 : if (flags & CFG_FLAG_GLOBAL_SECTION)
339 : 1 : rte_cfgfile_add_section(cfg, "GLOBAL");
340 : :
341 : : return cfg;
342 : 0 : error1:
343 [ # # ]: 0 : if (cfg->sections != NULL) {
344 [ # # ]: 0 : for (i = 0; i < cfg->allocated_sections; i++) {
345 [ # # ]: 0 : if (cfg->sections[i].entries != NULL) {
346 : 0 : free(cfg->sections[i].entries);
347 : 0 : cfg->sections[i].entries = NULL;
348 : : }
349 : : }
350 : 0 : free(cfg->sections);
351 : : cfg->sections = NULL;
352 : : }
353 : 0 : free(cfg);
354 : 0 : return NULL;
355 : : }
356 : :
357 : : RTE_EXPORT_SYMBOL(rte_cfgfile_add_section)
358 : : int
359 : 16 : rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname)
360 : : {
361 : : int i;
362 : :
363 [ + - ]: 16 : if (cfg == NULL)
364 : : return -EINVAL;
365 : :
366 [ + - ]: 16 : if (sectionname == NULL)
367 : : return -EINVAL;
368 : :
369 [ + - ]: 16 : if (strlen(sectionname) >= CFG_NAME_LEN)
370 : : return -ENAMETOOLONG;
371 : :
372 : : /* resize overall struct if we don't have room for more sections */
373 [ + + ]: 16 : if (cfg->num_sections == cfg->allocated_sections) {
374 : :
375 : : struct rte_cfgfile_section *n_sections =
376 : 1 : realloc(cfg->sections,
377 : : sizeof(struct rte_cfgfile_section) *
378 : 1 : ((cfg->allocated_sections) +
379 : : CFG_ALLOC_SECTION_BATCH));
380 : :
381 [ + - ]: 1 : if (n_sections == NULL)
382 : : return -ENOMEM;
383 : :
384 [ + + ]: 9 : for (i = 0; i < CFG_ALLOC_SECTION_BATCH; i++) {
385 : 8 : n_sections[i + cfg->allocated_sections].num_entries = 0;
386 : : n_sections[i +
387 : 8 : cfg->allocated_sections].allocated_entries = 0;
388 : 8 : n_sections[i + cfg->allocated_sections].entries = NULL;
389 : : }
390 : 1 : cfg->sections = n_sections;
391 : 1 : cfg->allocated_sections += CFG_ALLOC_SECTION_BATCH;
392 : : }
393 : :
394 : 16 : strlcpy(cfg->sections[cfg->num_sections].name, sectionname,
395 : : sizeof(cfg->sections[0].name));
396 : 16 : cfg->sections[cfg->num_sections].num_entries = 0;
397 : 16 : cfg->num_sections++;
398 : :
399 : 16 : return 0;
400 : : }
401 : :
402 : : RTE_EXPORT_SYMBOL(rte_cfgfile_add_entry)
403 : 0 : int rte_cfgfile_add_entry(struct rte_cfgfile *cfg,
404 : : const char *sectionname, const char *entryname,
405 : : const char *entryvalue)
406 : : {
407 [ # # ]: 0 : if ((cfg == NULL) || (sectionname == NULL) || (entryname == NULL)
408 [ # # ]: 0 : || (entryvalue == NULL))
409 : : return -EINVAL;
410 : :
411 [ # # ]: 0 : if (rte_cfgfile_has_entry(cfg, sectionname, entryname) != 0)
412 : : return -EEXIST;
413 : :
414 : : /* search for section pointer by sectionname */
415 : 0 : struct rte_cfgfile_section *curr_section = _get_section(cfg,
416 : : sectionname);
417 [ # # ]: 0 : if (curr_section == NULL)
418 : : return -EINVAL;
419 : :
420 : 0 : return _add_entry(curr_section, entryname, entryvalue);
421 : : }
422 : :
423 : : RTE_EXPORT_SYMBOL(rte_cfgfile_set_entry)
424 : 0 : int rte_cfgfile_set_entry(struct rte_cfgfile *cfg, const char *sectionname,
425 : : const char *entryname, const char *entryvalue)
426 : : {
427 : : int i;
428 : :
429 [ # # # # ]: 0 : if ((cfg == NULL) || (sectionname == NULL) || (entryname == NULL))
430 : : return -EINVAL;
431 : :
432 : : /* search for section pointer by sectionname */
433 : 0 : struct rte_cfgfile_section *curr_section = _get_section(cfg,
434 : : sectionname);
435 [ # # ]: 0 : if (curr_section == NULL)
436 : : return -EINVAL;
437 : :
438 [ # # ]: 0 : if (entryvalue == NULL)
439 : : entryvalue = "";
440 : :
441 [ # # ]: 0 : for (i = 0; i < curr_section->num_entries; i++)
442 [ # # ]: 0 : if (!strcmp(curr_section->entries[i].name, entryname)) {
443 : 0 : strlcpy(curr_section->entries[i].value, entryvalue,
444 : : sizeof(curr_section->entries[i].value));
445 : 0 : return 0;
446 : : }
447 : :
448 : 0 : CFG_LOG(ERR, "entry name doesn't exist");
449 : 0 : return -EINVAL;
450 : : }
451 : :
452 : : RTE_EXPORT_SYMBOL(rte_cfgfile_save)
453 : 1 : int rte_cfgfile_save(struct rte_cfgfile *cfg, const char *filename)
454 : : {
455 : : int i, j;
456 : :
457 [ + - ]: 1 : if ((cfg == NULL) || (filename == NULL))
458 : : return -EINVAL;
459 : :
460 : 1 : FILE *f = fopen(filename, "w");
461 : :
462 [ + - ]: 1 : if (f == NULL)
463 : : return -EINVAL;
464 : :
465 [ + + ]: 10 : for (i = 0; i < cfg->num_sections; i++) {
466 : 9 : fprintf(f, "[%s]\n", cfg->sections[i].name);
467 : :
468 [ + + ]: 120 : for (j = 0; j < cfg->sections[i].num_entries; j++) {
469 : : fprintf(f, "%s=%s\n",
470 : 111 : cfg->sections[i].entries[j].name,
471 : 111 : cfg->sections[i].entries[j].value);
472 : : }
473 : : }
474 : 1 : return fclose(f);
475 : : }
476 : :
477 : : RTE_EXPORT_SYMBOL(rte_cfgfile_close)
478 : 9 : int rte_cfgfile_close(struct rte_cfgfile *cfg)
479 : : {
480 : : int i;
481 : :
482 [ + - ]: 9 : if (cfg == NULL)
483 : : return -1;
484 : :
485 [ + - ]: 9 : if (cfg->sections != NULL) {
486 [ + + ]: 89 : for (i = 0; i < cfg->allocated_sections; i++) {
487 [ + + ]: 80 : if (cfg->sections[i].entries != NULL) {
488 : 73 : free(cfg->sections[i].entries);
489 : 73 : cfg->sections[i].entries = NULL;
490 : : }
491 : : }
492 : 9 : free(cfg->sections);
493 : : cfg->sections = NULL;
494 : : }
495 : 9 : free(cfg);
496 : : cfg = NULL;
497 : :
498 : 9 : return 0;
499 : : }
500 : :
501 : : RTE_EXPORT_SYMBOL(rte_cfgfile_num_sections)
502 : : int
503 : 6 : rte_cfgfile_num_sections(struct rte_cfgfile *cfg, const char *sectionname,
504 : : size_t length)
505 : : {
506 : : int num_sections = 0;
507 : : int i;
508 : :
509 [ + - ]: 6 : if (sectionname == NULL)
510 : 6 : return cfg->num_sections;
511 : :
512 [ # # ]: 0 : for (i = 0; i < cfg->num_sections; i++) {
513 [ # # ]: 0 : if (strncmp(cfg->sections[i].name, sectionname, length) == 0)
514 : 0 : num_sections++;
515 : : }
516 : : return num_sections;
517 : : }
518 : :
519 : : RTE_EXPORT_SYMBOL(rte_cfgfile_sections)
520 : : int
521 : 0 : rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[],
522 : : int max_sections)
523 : : {
524 : : int i;
525 : :
526 [ # # # # ]: 0 : for (i = 0; i < cfg->num_sections && i < max_sections; i++)
527 : 0 : strlcpy(sections[i], cfg->sections[i].name, CFG_NAME_LEN);
528 : :
529 : 0 : return i;
530 : : }
531 : :
532 : : RTE_EXPORT_SYMBOL(rte_cfgfile_has_section)
533 : : int
534 : 7 : rte_cfgfile_has_section(struct rte_cfgfile *cfg, const char *sectionname)
535 : : {
536 : 7 : return _get_section(cfg, sectionname) != NULL;
537 : : }
538 : :
539 : : RTE_EXPORT_SYMBOL(rte_cfgfile_section_num_entries)
540 : : int
541 : 8 : rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg,
542 : : const char *sectionname)
543 : : {
544 : 8 : const struct rte_cfgfile_section *s = _get_section(cfg, sectionname);
545 [ + - ]: 8 : if (s == NULL)
546 : : return -1;
547 : 8 : return s->num_entries;
548 : : }
549 : :
550 : : RTE_EXPORT_SYMBOL(rte_cfgfile_section_num_entries_by_index)
551 : : int
552 : 0 : rte_cfgfile_section_num_entries_by_index(struct rte_cfgfile *cfg,
553 : : char *sectionname, int index)
554 : : {
555 [ # # # # ]: 0 : if (index < 0 || index >= cfg->num_sections)
556 : : return -1;
557 : :
558 : 0 : const struct rte_cfgfile_section *sect = &(cfg->sections[index]);
559 : :
560 : 0 : strlcpy(sectionname, sect->name, CFG_NAME_LEN);
561 : 0 : return sect->num_entries;
562 : : }
563 : : RTE_EXPORT_SYMBOL(rte_cfgfile_section_entries)
564 : : int
565 : 0 : rte_cfgfile_section_entries(struct rte_cfgfile *cfg, const char *sectionname,
566 : : struct rte_cfgfile_entry *entries, int max_entries)
567 : : {
568 : : int i;
569 : 0 : const struct rte_cfgfile_section *sect = _get_section(cfg, sectionname);
570 [ # # ]: 0 : if (sect == NULL)
571 : : return -1;
572 [ # # # # ]: 0 : for (i = 0; i < max_entries && i < sect->num_entries; i++)
573 : 0 : entries[i] = sect->entries[i];
574 : : return i;
575 : : }
576 : :
577 : : RTE_EXPORT_SYMBOL(rte_cfgfile_section_entries_by_index)
578 : : int
579 : 0 : rte_cfgfile_section_entries_by_index(struct rte_cfgfile *cfg, int index,
580 : : char *sectionname,
581 : : struct rte_cfgfile_entry *entries, int max_entries)
582 : : {
583 : : int i;
584 : : const struct rte_cfgfile_section *sect;
585 : :
586 [ # # # # ]: 0 : if (index < 0 || index >= cfg->num_sections)
587 : : return -1;
588 : 0 : sect = &cfg->sections[index];
589 : 0 : strlcpy(sectionname, sect->name, CFG_NAME_LEN);
590 [ # # # # ]: 0 : for (i = 0; i < max_entries && i < sect->num_entries; i++)
591 : 0 : entries[i] = sect->entries[i];
592 : : return i;
593 : : }
594 : :
595 : : RTE_EXPORT_SYMBOL(rte_cfgfile_get_entry)
596 : : const char *
597 : 9 : rte_cfgfile_get_entry(struct rte_cfgfile *cfg, const char *sectionname,
598 : : const char *entryname)
599 : : {
600 : : int i;
601 : 9 : const struct rte_cfgfile_section *sect = _get_section(cfg, sectionname);
602 [ + - ]: 9 : if (sect == NULL)
603 : : return NULL;
604 [ + - ]: 18 : for (i = 0; i < sect->num_entries; i++)
605 [ + + ]: 18 : if (strncmp(sect->entries[i].name, entryname, CFG_NAME_LEN)
606 : : == 0)
607 : 9 : return sect->entries[i].value;
608 : : return NULL;
609 : : }
610 : :
611 : : RTE_EXPORT_SYMBOL(rte_cfgfile_has_entry)
612 : : int
613 : 0 : rte_cfgfile_has_entry(struct rte_cfgfile *cfg, const char *sectionname,
614 : : const char *entryname)
615 : : {
616 : 0 : return rte_cfgfile_get_entry(cfg, sectionname, entryname) != NULL;
617 : : }
|