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