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