]> git.ipfire.org Git - people/ms/u-boot.git/blame - lib/hashtable.c
build: Pull -DBUILD_TAG into separate ifdef
[people/ms/u-boot.git] / lib / hashtable.c
CommitLineData
a6826fbc
WD
1/*
2 * This implementation is based on code from uClibc-0.9.30.3 but was
3 * modified and extended for use within U-Boot.
4 *
ea009d47 5 * Copyright (C) 2010-2013 Wolfgang Denk <wd@denx.de>
a6826fbc
WD
6 *
7 * Original license header:
8 *
9 * Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
10 * This file is part of the GNU C Library.
11 * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1993.
12 *
13 * The GNU C Library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
17 *
18 * The GNU C Library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with the GNU C Library; if not, write to the Free
25 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 * 02111-1307 USA.
27 */
28
29#include <errno.h>
30#include <malloc.h>
31
32#ifdef USE_HOSTCC /* HOST build */
33# include <string.h>
34# include <assert.h>
4d91a6ec 35# include <ctype.h>
a6826fbc
WD
36
37# ifndef debug
38# ifdef DEBUG
39# define debug(fmt,args...) printf(fmt ,##args)
40# else
41# define debug(fmt,args...)
42# endif
43# endif
44#else /* U-Boot build */
45# include <common.h>
46# include <linux/string.h>
4d91a6ec 47# include <linux/ctype.h>
a6826fbc
WD
48#endif
49
fc5fc76b
AB
50#ifndef CONFIG_ENV_MIN_ENTRIES /* minimum number of entries */
51#define CONFIG_ENV_MIN_ENTRIES 64
52#endif
ea882baf
WD
53#ifndef CONFIG_ENV_MAX_ENTRIES /* maximum number of entries */
54#define CONFIG_ENV_MAX_ENTRIES 512
55#endif
56
170ab110 57#include <env_callback.h>
2598090b 58#include <env_flags.h>
170ab110 59#include <search.h>
be29df6a 60#include <slre.h>
a6826fbc
WD
61
62/*
63 * [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
071bc923 64 * [Knuth] The Art of Computer Programming, part 3 (6.4)
a6826fbc
WD
65 */
66
a6826fbc
WD
67/*
68 * The reentrant version has no static variables to maintain the state.
69 * Instead the interface of all functions is extended to take an argument
70 * which describes the current status.
71 */
7afcf3a5 72
a6826fbc 73typedef struct _ENTRY {
c81c1222 74 int used;
a6826fbc
WD
75 ENTRY entry;
76} _ENTRY;
77
78
7afcf3a5
JH
79static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
80 int idx);
81
a6826fbc
WD
82/*
83 * hcreate()
84 */
85
86/*
87 * For the used double hash method the table size has to be a prime. To
88 * correct the user given table size we need a prime test. This trivial
89 * algorithm is adequate because
90 * a) the code is (most probably) called a few times per program run and
91 * b) the number is small because the table must fit in the core
92 * */
93static int isprime(unsigned int number)
94{
95 /* no even number will be passed */
96 unsigned int div = 3;
97
98 while (div * div < number && number % div != 0)
99 div += 2;
100
101 return number % div != 0;
102}
103
a6826fbc
WD
104/*
105 * Before using the hash table we must allocate memory for it.
106 * Test for an existing table are done. We allocate one element
107 * more as the found prime number says. This is done for more effective
108 * indexing as explained in the comment for the hsearch function.
109 * The contents of the table is zeroed, especially the field used
110 * becomes zero.
111 */
2eb1573f 112
a6826fbc
WD
113int hcreate_r(size_t nel, struct hsearch_data *htab)
114{
115 /* Test for correct arguments. */
116 if (htab == NULL) {
117 __set_errno(EINVAL);
118 return 0;
119 }
120
121 /* There is still another table active. Return with error. */
122 if (htab->table != NULL)
123 return 0;
124
125 /* Change nel to the first prime number not smaller as nel. */
126 nel |= 1; /* make odd */
127 while (!isprime(nel))
128 nel += 2;
129
130 htab->size = nel;
131 htab->filled = 0;
132
133 /* allocate memory and zero out */
134 htab->table = (_ENTRY *) calloc(htab->size + 1, sizeof(_ENTRY));
135 if (htab->table == NULL)
136 return 0;
137
138 /* everything went alright */
139 return 1;
140}
141
142
143/*
144 * hdestroy()
145 */
a6826fbc
WD
146
147/*
148 * After using the hash table it has to be destroyed. The used memory can
149 * be freed and the local static variable can be marked as not used.
150 */
2eb1573f 151
c4e0057f 152void hdestroy_r(struct hsearch_data *htab)
a6826fbc
WD
153{
154 int i;
155
156 /* Test for correct arguments. */
157 if (htab == NULL) {
158 __set_errno(EINVAL);
159 return;
160 }
161
162 /* free used memory */
163 for (i = 1; i <= htab->size; ++i) {
c81c1222 164 if (htab->table[i].used > 0) {
a6826fbc 165 ENTRY *ep = &htab->table[i].entry;
c4e0057f 166
84b5e802 167 free((void *)ep->key);
a6826fbc
WD
168 free(ep->data);
169 }
170 }
171 free(htab->table);
172
173 /* the sign for an existing table is an value != NULL in htable */
174 htab->table = NULL;
175}
176
177/*
178 * hsearch()
179 */
180
181/*
182 * This is the search function. It uses double hashing with open addressing.
183 * The argument item.key has to be a pointer to an zero terminated, most
184 * probably strings of chars. The function for generating a number of the
185 * strings is simple but fast. It can be replaced by a more complex function
186 * like ajw (see [Aho,Sethi,Ullman]) if the needs are shown.
187 *
188 * We use an trick to speed up the lookup. The table is created by hcreate
189 * with one more element available. This enables us to use the index zero
190 * special. This index will never be used because we store the first hash
191 * index in the field used where zero means not used. Every other value
192 * means used. The used field can be used as a first fast comparison for
193 * equality of the stored and the parameter value. This helps to prevent
194 * unnecessary expensive calls of strcmp.
195 *
196 * This implementation differs from the standard library version of
197 * this function in a number of ways:
198 *
199 * - While the standard version does not make any assumptions about
200 * the type of the stored data objects at all, this implementation
201 * works with NUL terminated strings only.
202 * - Instead of storing just pointers to the original objects, we
203 * create local copies so the caller does not need to care about the
204 * data any more.
205 * - The standard implementation does not provide a way to update an
206 * existing entry. This version will create a new entry or update an
207 * existing one when both "action == ENTER" and "item.data != NULL".
208 * - Instead of returning 1 on success, we return the index into the
209 * internal hash table, which is also guaranteed to be positive.
210 * This allows us direct access to the found hash table slot for
211 * example for functions like hdelete().
212 */
213
560d424b
MF
214int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
215 struct hsearch_data *htab)
216{
217 unsigned int idx;
218 size_t key_len = strlen(match);
219
220 for (idx = last_idx + 1; idx < htab->size; ++idx) {
af4d9074 221 if (htab->table[idx].used <= 0)
560d424b
MF
222 continue;
223 if (!strncmp(match, htab->table[idx].entry.key, key_len)) {
224 *retval = &htab->table[idx].entry;
225 return idx;
226 }
227 }
228
229 __set_errno(ESRCH);
230 *retval = NULL;
231 return 0;
232}
233
3d3b52f2
JH
234/*
235 * Compare an existing entry with the desired key, and overwrite if the action
236 * is ENTER. This is simply a helper function for hsearch_r().
237 */
238static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
239 ENTRY **retval, struct hsearch_data *htab, int flag,
240 unsigned int hval, unsigned int idx)
241{
242 if (htab->table[idx].used == hval
243 && strcmp(item.key, htab->table[idx].entry.key) == 0) {
244 /* Overwrite existing value? */
245 if ((action == ENTER) && (item.data != NULL)) {
7afcf3a5
JH
246 /* check for permission */
247 if (htab->change_ok != NULL && htab->change_ok(
248 &htab->table[idx].entry, item.data,
249 env_op_overwrite, flag)) {
250 debug("change_ok() rejected setting variable "
251 "%s, skipping it!\n", item.key);
252 __set_errno(EPERM);
253 *retval = NULL;
254 return 0;
255 }
256
170ab110
JH
257 /* If there is a callback, call it */
258 if (htab->table[idx].entry.callback &&
259 htab->table[idx].entry.callback(item.key,
260 item.data, env_op_overwrite, flag)) {
261 debug("callback() rejected setting variable "
262 "%s, skipping it!\n", item.key);
263 __set_errno(EINVAL);
264 *retval = NULL;
265 return 0;
266 }
267
3d3b52f2
JH
268 free(htab->table[idx].entry.data);
269 htab->table[idx].entry.data = strdup(item.data);
270 if (!htab->table[idx].entry.data) {
271 __set_errno(ENOMEM);
272 *retval = NULL;
273 return 0;
274 }
275 }
276 /* return found entry */
277 *retval = &htab->table[idx].entry;
278 return idx;
279 }
280 /* keep searching */
281 return -1;
282}
283
a6826fbc 284int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
c4e0057f 285 struct hsearch_data *htab, int flag)
a6826fbc
WD
286{
287 unsigned int hval;
288 unsigned int count;
289 unsigned int len = strlen(item.key);
290 unsigned int idx;
c81c1222 291 unsigned int first_deleted = 0;
3d3b52f2 292 int ret;
a6826fbc
WD
293
294 /* Compute an value for the given string. Perhaps use a better method. */
295 hval = len;
296 count = len;
297 while (count-- > 0) {
298 hval <<= 4;
299 hval += item.key[count];
300 }
301
302 /*
303 * First hash function:
304 * simply take the modul but prevent zero.
305 */
306 hval %= htab->size;
307 if (hval == 0)
308 ++hval;
309
310 /* The first index tried. */
311 idx = hval;
312
313 if (htab->table[idx].used) {
314 /*
071bc923 315 * Further action might be required according to the
a6826fbc
WD
316 * action value.
317 */
318 unsigned hval2;
319
c81c1222
PB
320 if (htab->table[idx].used == -1
321 && !first_deleted)
322 first_deleted = idx;
323
3d3b52f2
JH
324 ret = _compare_and_overwrite_entry(item, action, retval, htab,
325 flag, hval, idx);
326 if (ret != -1)
327 return ret;
a6826fbc
WD
328
329 /*
330 * Second hash function:
331 * as suggested in [Knuth]
332 */
333 hval2 = 1 + hval % (htab->size - 2);
334
335 do {
336 /*
071bc923
WD
337 * Because SIZE is prime this guarantees to
338 * step through all available indices.
a6826fbc
WD
339 */
340 if (idx <= hval2)
341 idx = htab->size + idx - hval2;
342 else
343 idx -= hval2;
344
345 /*
346 * If we visited all entries leave the loop
347 * unsuccessfully.
348 */
349 if (idx == hval)
350 break;
351
352 /* If entry is found use it. */
3d3b52f2
JH
353 ret = _compare_and_overwrite_entry(item, action, retval,
354 htab, flag, hval, idx);
355 if (ret != -1)
356 return ret;
a6826fbc
WD
357 }
358 while (htab->table[idx].used);
359 }
360
361 /* An empty bucket has been found. */
362 if (action == ENTER) {
363 /*
071bc923
WD
364 * If table is full and another entry should be
365 * entered return with error.
a6826fbc
WD
366 */
367 if (htab->filled == htab->size) {
368 __set_errno(ENOMEM);
369 *retval = NULL;
370 return 0;
371 }
372
373 /*
374 * Create new entry;
375 * create copies of item.key and item.data
376 */
c81c1222
PB
377 if (first_deleted)
378 idx = first_deleted;
379
a6826fbc
WD
380 htab->table[idx].used = hval;
381 htab->table[idx].entry.key = strdup(item.key);
382 htab->table[idx].entry.data = strdup(item.data);
383 if (!htab->table[idx].entry.key ||
384 !htab->table[idx].entry.data) {
385 __set_errno(ENOMEM);
386 *retval = NULL;
387 return 0;
388 }
389
390 ++htab->filled;
391
170ab110
JH
392 /* This is a new entry, so look up a possible callback */
393 env_callback_init(&htab->table[idx].entry);
2598090b
JH
394 /* Also look for flags */
395 env_flags_init(&htab->table[idx].entry);
170ab110 396
7afcf3a5
JH
397 /* check for permission */
398 if (htab->change_ok != NULL && htab->change_ok(
399 &htab->table[idx].entry, item.data, env_op_create, flag)) {
400 debug("change_ok() rejected setting variable "
401 "%s, skipping it!\n", item.key);
402 _hdelete(item.key, htab, &htab->table[idx].entry, idx);
403 __set_errno(EPERM);
404 *retval = NULL;
405 return 0;
406 }
407
170ab110
JH
408 /* If there is a callback, call it */
409 if (htab->table[idx].entry.callback &&
410 htab->table[idx].entry.callback(item.key, item.data,
411 env_op_create, flag)) {
412 debug("callback() rejected setting variable "
413 "%s, skipping it!\n", item.key);
414 _hdelete(item.key, htab, &htab->table[idx].entry, idx);
415 __set_errno(EINVAL);
416 *retval = NULL;
417 return 0;
418 }
419
a6826fbc
WD
420 /* return new entry */
421 *retval = &htab->table[idx].entry;
422 return 1;
423 }
424
425 __set_errno(ESRCH);
426 *retval = NULL;
427 return 0;
428}
429
430
431/*
432 * hdelete()
433 */
434
435/*
436 * The standard implementation of hsearch(3) does not provide any way
437 * to delete any entries from the hash table. We extend the code to
438 * do that.
439 */
440
7afcf3a5
JH
441static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
442 int idx)
443{
444 /* free used ENTRY */
445 debug("hdelete: DELETING key \"%s\"\n", key);
446 free((void *)ep->key);
447 free(ep->data);
170ab110 448 ep->callback = NULL;
2598090b 449 ep->flags = 0;
7afcf3a5
JH
450 htab->table[idx].used = -1;
451
452 --htab->filled;
453}
454
c4e0057f 455int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
a6826fbc
WD
456{
457 ENTRY e, *ep;
458 int idx;
459
460 debug("hdelete: DELETE key \"%s\"\n", key);
461
462 e.key = (char *)key;
463
c4e0057f
JH
464 idx = hsearch_r(e, FIND, &ep, htab, 0);
465 if (idx == 0) {
a6826fbc
WD
466 __set_errno(ESRCH);
467 return 0; /* not found */
468 }
469
c4e0057f 470 /* Check for permission */
7afcf3a5
JH
471 if (htab->change_ok != NULL &&
472 htab->change_ok(ep, NULL, env_op_delete, flag)) {
473 debug("change_ok() rejected deleting variable "
474 "%s, skipping it!\n", key);
c4e0057f
JH
475 __set_errno(EPERM);
476 return 0;
477 }
478
170ab110
JH
479 /* If there is a callback, call it */
480 if (htab->table[idx].entry.callback &&
481 htab->table[idx].entry.callback(key, NULL, env_op_delete, flag)) {
482 debug("callback() rejected deleting variable "
483 "%s, skipping it!\n", key);
484 __set_errno(EINVAL);
485 return 0;
486 }
487
7afcf3a5 488 _hdelete(key, htab, ep, idx);
a6826fbc
WD
489
490 return 1;
491}
492
493/*
494 * hexport()
495 */
496
7ac2fe2d 497#ifndef CONFIG_SPL_BUILD
a6826fbc
WD
498/*
499 * Export the data stored in the hash table in linearized form.
500 *
501 * Entries are exported as "name=value" strings, separated by an
502 * arbitrary (non-NUL, of course) separator character. This allows to
503 * use this function both when formatting the U-Boot environment for
504 * external storage (using '\0' as separator), but also when using it
505 * for the "printenv" command to print all variables, simply by using
506 * as '\n" as separator. This can also be used for new features like
507 * exporting the environment data as text file, including the option
508 * for later re-import.
509 *
510 * The entries in the result list will be sorted by ascending key
511 * values.
512 *
513 * If the separator character is different from NUL, then any
514 * separator characters and backslash characters in the values will
515 * be escaped by a preceeding backslash in output. This is needed for
516 * example to enable multi-line values, especially when the output
517 * shall later be parsed (for example, for re-import).
518 *
519 * There are several options how the result buffer is handled:
520 *
521 * *resp size
522 * -----------
523 * NULL 0 A string of sufficient length will be allocated.
524 * NULL >0 A string of the size given will be
525 * allocated. An error will be returned if the size is
526 * not sufficient. Any unused bytes in the string will
527 * be '\0'-padded.
528 * !NULL 0 The user-supplied buffer will be used. No length
529 * checking will be performed, i. e. it is assumed that
530 * the buffer size will always be big enough. DANGEROUS.
531 * !NULL >0 The user-supplied buffer will be used. An error will
532 * be returned if the size is not sufficient. Any unused
533 * bytes in the string will be '\0'-padded.
534 */
535
a6826fbc
WD
536static int cmpkey(const void *p1, const void *p2)
537{
538 ENTRY *e1 = *(ENTRY **) p1;
539 ENTRY *e2 = *(ENTRY **) p2;
540
541 return (strcmp(e1->key, e2->key));
542}
543
be29df6a 544static int match_string(int flag, const char *str, const char *pat, void *priv)
5a31ea04
WD
545{
546 switch (flag & H_MATCH_METHOD) {
547 case H_MATCH_IDENT:
548 if (strcmp(str, pat) == 0)
549 return 1;
550 break;
551 case H_MATCH_SUBSTR:
552 if (strstr(str, pat))
553 return 1;
554 break;
be29df6a
WD
555#ifdef CONFIG_REGEX
556 case H_MATCH_REGEX:
557 {
558 struct slre *slrep = (struct slre *)priv;
559 struct cap caps[slrep->num_caps + 2];
560
561 if (slre_match(slrep, str, strlen(str), caps))
562 return 1;
563 }
564 break;
565#endif
5a31ea04
WD
566 default:
567 printf("## ERROR: unsupported match method: 0x%02x\n",
568 flag & H_MATCH_METHOD);
569 break;
570 }
571 return 0;
572}
573
574static int match_entry(ENTRY *ep, int flag,
ea009d47
WD
575 int argc, char * const argv[])
576{
577 int arg;
be29df6a 578 void *priv = NULL;
ea009d47 579
5a31ea04 580 for (arg = 1; arg < argc; ++arg) {
be29df6a
WD
581#ifdef CONFIG_REGEX
582 struct slre slre;
583
584 if (slre_compile(&slre, argv[arg]) == 0) {
585 printf("Error compiling regex: %s\n", slre.err_str);
586 return 0;
587 }
588
589 priv = (void *)&slre;
590#endif
ea009d47 591 if (flag & H_MATCH_KEY) {
be29df6a 592 if (match_string(flag, ep->key, argv[arg], priv))
5a31ea04
WD
593 return 1;
594 }
595 if (flag & H_MATCH_DATA) {
be29df6a 596 if (match_string(flag, ep->data, argv[arg], priv))
5a31ea04 597 return 1;
ea009d47
WD
598 }
599 }
600 return 0;
601}
602
be11235a 603ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
37f2fe74
WD
604 char **resp, size_t size,
605 int argc, char * const argv[])
a6826fbc
WD
606{
607 ENTRY *list[htab->size];
608 char *res, *p;
609 size_t totlen;
610 int i, n;
611
612 /* Test for correct arguments. */
613 if ((resp == NULL) || (htab == NULL)) {
614 __set_errno(EINVAL);
615 return (-1);
616 }
617
ff856286
SG
618 debug("EXPORT table = %p, htab.size = %d, htab.filled = %d, "
619 "size = %zu\n", htab, htab->size, htab->filled, size);
a6826fbc
WD
620 /*
621 * Pass 1:
622 * search used entries,
623 * save addresses and compute total length
624 */
625 for (i = 1, n = 0, totlen = 0; i <= htab->size; ++i) {
626
c81c1222 627 if (htab->table[i].used > 0) {
a6826fbc 628 ENTRY *ep = &htab->table[i].entry;
5a31ea04 629 int found = match_entry(ep, flag, argc, argv);
37f2fe74 630
37f2fe74
WD
631 if ((argc > 0) && (found == 0))
632 continue;
a6826fbc 633
be11235a
JH
634 if ((flag & H_HIDE_DOT) && ep->key[0] == '.')
635 continue;
636
a6826fbc
WD
637 list[n++] = ep;
638
639 totlen += strlen(ep->key) + 2;
640
641 if (sep == '\0') {
642 totlen += strlen(ep->data);
643 } else { /* check if escapes are needed */
644 char *s = ep->data;
645
646 while (*s) {
647 ++totlen;
648 /* add room for needed escape chars */
649 if ((*s == sep) || (*s == '\\'))
650 ++totlen;
651 ++s;
652 }
653 }
654 totlen += 2; /* for '=' and 'sep' char */
655 }
656 }
657
658#ifdef DEBUG
659 /* Pass 1a: print unsorted list */
660 printf("Unsorted: n=%d\n", n);
661 for (i = 0; i < n; ++i) {
662 printf("\t%3d: %p ==> %-10s => %s\n",
663 i, list[i], list[i]->key, list[i]->data);
664 }
665#endif
666
667 /* Sort list by keys */
668 qsort(list, n, sizeof(ENTRY *), cmpkey);
669
670 /* Check if the user supplied buffer size is sufficient */
671 if (size) {
672 if (size < totlen + 1) { /* provided buffer too small */
ff856286
SG
673 printf("Env export buffer too small: %zu, "
674 "but need %zu\n", size, totlen + 1);
a6826fbc
WD
675 __set_errno(ENOMEM);
676 return (-1);
677 }
678 } else {
679 size = totlen + 1;
680 }
681
682 /* Check if the user provided a buffer */
683 if (*resp) {
684 /* yes; clear it */
685 res = *resp;
686 memset(res, '\0', size);
687 } else {
688 /* no, allocate and clear one */
689 *resp = res = calloc(1, size);
690 if (res == NULL) {
691 __set_errno(ENOMEM);
692 return (-1);
693 }
694 }
695 /*
696 * Pass 2:
697 * export sorted list of result data
698 */
699 for (i = 0, p = res; i < n; ++i) {
84b5e802 700 const char *s;
a6826fbc
WD
701
702 s = list[i]->key;
703 while (*s)
704 *p++ = *s++;
705 *p++ = '=';
706
707 s = list[i]->data;
708
709 while (*s) {
710 if ((*s == sep) || (*s == '\\'))
711 *p++ = '\\'; /* escape */
712 *p++ = *s++;
713 }
714 *p++ = sep;
715 }
716 *p = '\0'; /* terminate result */
717
718 return size;
719}
7ac2fe2d 720#endif
a6826fbc
WD
721
722
723/*
724 * himport()
725 */
726
d5370feb
GF
727/*
728 * Check whether variable 'name' is amongst vars[],
729 * and remove all instances by setting the pointer to NULL
730 */
731static int drop_var_from_set(const char *name, int nvars, char * vars[])
348b1f1c
GF
732{
733 int i = 0;
d5370feb 734 int res = 0;
348b1f1c
GF
735
736 /* No variables specified means process all of them */
737 if (nvars == 0)
738 return 1;
739
740 for (i = 0; i < nvars; i++) {
d5370feb
GF
741 if (vars[i] == NULL)
742 continue;
743 /* If we found it, delete all of them */
744 if (!strcmp(name, vars[i])) {
745 vars[i] = NULL;
746 res = 1;
747 }
348b1f1c 748 }
d5370feb
GF
749 if (!res)
750 debug("Skipping non-listed variable %s\n", name);
348b1f1c 751
d5370feb 752 return res;
348b1f1c
GF
753}
754
a6826fbc
WD
755/*
756 * Import linearized data into hash table.
757 *
758 * This is the inverse function to hexport(): it takes a linear list
759 * of "name=value" pairs and creates hash table entries from it.
760 *
761 * Entries without "value", i. e. consisting of only "name" or
762 * "name=", will cause this entry to be deleted from the hash table.
763 *
764 * The "flag" argument can be used to control the behaviour: when the
765 * H_NOCLEAR bit is set, then an existing hash table will kept, i. e.
766 * new data will be added to an existing hash table; otherwise, old
767 * data will be discarded and a new hash table will be created.
768 *
769 * The separator character for the "name=value" pairs can be selected,
770 * so we both support importing from externally stored environment
771 * data (separated by NUL characters) and from plain text files
772 * (entries separated by newline characters).
773 *
774 * To allow for nicely formatted text input, leading white space
775 * (sequences of SPACE and TAB chars) is ignored, and entries starting
776 * (after removal of any leading white space) with a '#' character are
777 * considered comments and ignored.
778 *
779 * [NOTE: this means that a variable name cannot start with a '#'
780 * character.]
781 *
782 * When using a non-NUL separator character, backslash is used as
783 * escape character in the value part, allowing for example for
784 * multi-line values.
785 *
786 * In theory, arbitrary separator characters can be used, but only
787 * '\0' and '\n' have really been tested.
788 */
789
a6826fbc 790int himport_r(struct hsearch_data *htab,
348b1f1c 791 const char *env, size_t size, const char sep, int flag,
c4e0057f 792 int nvars, char * const vars[])
a6826fbc
WD
793{
794 char *data, *sp, *dp, *name, *value;
d5370feb
GF
795 char *localvars[nvars];
796 int i;
a6826fbc
WD
797
798 /* Test for correct arguments. */
799 if (htab == NULL) {
800 __set_errno(EINVAL);
801 return 0;
802 }
803
804 /* we allocate new space to make sure we can write to the array */
805 if ((data = malloc(size)) == NULL) {
ff856286 806 debug("himport_r: can't malloc %zu bytes\n", size);
a6826fbc
WD
807 __set_errno(ENOMEM);
808 return 0;
809 }
810 memcpy(data, env, size);
811 dp = data;
812
d5370feb
GF
813 /* make a local copy of the list of variables */
814 if (nvars)
815 memcpy(localvars, vars, sizeof(vars[0]) * nvars);
816
a6826fbc
WD
817 if ((flag & H_NOCLEAR) == 0) {
818 /* Destroy old hash table if one exists */
819 debug("Destroy Hash Table: %p table = %p\n", htab,
820 htab->table);
821 if (htab->table)
c4e0057f 822 hdestroy_r(htab);
a6826fbc
WD
823 }
824
825 /*
826 * Create new hash table (if needed). The computation of the hash
827 * table size is based on heuristics: in a sample of some 70+
828 * existing systems we found an average size of 39+ bytes per entry
829 * in the environment (for the whole key=value pair). Assuming a
ea882baf
WD
830 * size of 8 per entry (= safety factor of ~5) should provide enough
831 * safety margin for any existing environment definitions and still
a6826fbc
WD
832 * allow for more than enough dynamic additions. Note that the
833 * "size" argument is supposed to give the maximum enviroment size
ea882baf
WD
834 * (CONFIG_ENV_SIZE). This heuristics will result in
835 * unreasonably large numbers (and thus memory footprint) for
836 * big flash environments (>8,000 entries for 64 KB
fc5fc76b
AB
837 * envrionment size), so we clip it to a reasonable value.
838 * On the other hand we need to add some more entries for free
839 * space when importing very small buffers. Both boundaries can
840 * be overwritten in the board config file if needed.
a6826fbc
WD
841 */
842
843 if (!htab->table) {
fc5fc76b 844 int nent = CONFIG_ENV_MIN_ENTRIES + size / 8;
ea882baf
WD
845
846 if (nent > CONFIG_ENV_MAX_ENTRIES)
847 nent = CONFIG_ENV_MAX_ENTRIES;
a6826fbc
WD
848
849 debug("Create Hash Table: N=%d\n", nent);
850
851 if (hcreate_r(nent, htab) == 0) {
852 free(data);
853 return 0;
854 }
855 }
856
857 /* Parse environment; allow for '\0' and 'sep' as separators */
858 do {
859 ENTRY e, *rv;
860
861 /* skip leading white space */
4d91a6ec 862 while (isblank(*dp))
a6826fbc
WD
863 ++dp;
864
865 /* skip comment lines */
866 if (*dp == '#') {
867 while (*dp && (*dp != sep))
868 ++dp;
869 ++dp;
870 continue;
871 }
872
873 /* parse name */
874 for (name = dp; *dp != '=' && *dp && *dp != sep; ++dp)
875 ;
876
877 /* deal with "name" and "name=" entries (delete var) */
878 if (*dp == '\0' || *(dp + 1) == '\0' ||
879 *dp == sep || *(dp + 1) == sep) {
880 if (*dp == '=')
881 *dp++ = '\0';
882 *dp++ = '\0'; /* terminate name */
883
884 debug("DELETE CANDIDATE: \"%s\"\n", name);
d5370feb 885 if (!drop_var_from_set(name, nvars, localvars))
348b1f1c 886 continue;
a6826fbc 887
c4e0057f 888 if (hdelete_r(name, htab, flag) == 0)
a6826fbc
WD
889 debug("DELETE ERROR ##############################\n");
890
891 continue;
892 }
893 *dp++ = '\0'; /* terminate name */
894
895 /* parse value; deal with escapes */
896 for (value = sp = dp; *dp && (*dp != sep); ++dp) {
897 if ((*dp == '\\') && *(dp + 1))
898 ++dp;
899 *sp++ = *dp;
900 }
901 *sp++ = '\0'; /* terminate value */
902 ++dp;
903
348b1f1c 904 /* Skip variables which are not supposed to be processed */
d5370feb 905 if (!drop_var_from_set(name, nvars, localvars))
348b1f1c
GF
906 continue;
907
a6826fbc
WD
908 /* enter into hash table */
909 e.key = name;
910 e.data = value;
911
c4e0057f 912 hsearch_r(e, ENTER, &rv, htab, flag);
170ab110 913 if (rv == NULL)
ea882baf
WD
914 printf("himport_r: can't insert \"%s=%s\" into hash table\n",
915 name, value);
a6826fbc 916
ea882baf
WD
917 debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" value=\"%s\"\n",
918 htab, htab->filled, htab->size,
919 rv, name, value);
a6826fbc
WD
920 } while ((dp < data + size) && *dp); /* size check needed for text */
921 /* without '\0' termination */
ea882baf 922 debug("INSERT: free(data = %p)\n", data);
a6826fbc
WD
923 free(data);
924
d5370feb
GF
925 /* process variables which were not considered */
926 for (i = 0; i < nvars; i++) {
927 if (localvars[i] == NULL)
928 continue;
929 /*
930 * All variables which were not deleted from the variable list
931 * were not present in the imported env
932 * This could mean two things:
933 * a) if the variable was present in current env, we delete it
934 * b) if the variable was not present in current env, we notify
935 * it might be a typo
936 */
c4e0057f 937 if (hdelete_r(localvars[i], htab, flag) == 0)
d5370feb
GF
938 printf("WARNING: '%s' neither in running nor in imported env!\n", localvars[i]);
939 else
940 printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
941 }
942
ea882baf 943 debug("INSERT: done\n");
a6826fbc
WD
944 return 1; /* everything OK */
945}
170ab110
JH
946
947/*
948 * hwalk_r()
949 */
950
951/*
952 * Walk all of the entries in the hash, calling the callback for each one.
953 * this allows some generic operation to be performed on each element.
954 */
955int hwalk_r(struct hsearch_data *htab, int (*callback)(ENTRY *))
956{
957 int i;
958 int retval;
959
960 for (i = 1; i <= htab->size; ++i) {
961 if (htab->table[i].used > 0) {
962 retval = callback(&htab->table[i].entry);
963 if (retval)
964 return retval;
965 }
966 }
967
968 return 0;
969}