]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
hashtable: do not recreate whole hash table if vars are passed to himport_r
authorQuentin Schulz <quentin.schulz@bootlin.com>
Mon, 9 Jul 2018 17:16:28 +0000 (19:16 +0200)
committerTom Rini <trini@konsulko.com>
Fri, 20 Jul 2018 19:55:09 +0000 (15:55 -0400)
When vars are passed to the himport_r function with H_NOCLEAR flag,
those vars will be overridden in the current environment and if one of
those vars is not in the imported environment, it'll be deleted in the
current environment whatever the flag passed to himport_r.

The H_NOCLEAR flag is used to clear the whole environment whether vars
are passed to the function or not.

This leads to incoherent behaviour. If one passes vars to himport_r
with the H_NOCLEAR flag, if a var in vars is not in the imported env,
that var will be removed from the current env.

If one passes vars to himport_r without the H_NOCLEAR flag, the whole
environment will be removed and vars will be imported from the
environment in RAM.

It makes more sense to keep the variable that is in the current
environment but not in the imported environment if the H_NOCLEAR flag is
set and remove only that variable if the H_NOCLEAR flag is not set.

Let's clear the whole environment only if H_NOCLEAR and vars are not
passed to himport_r.

Let's remove variables that are in the current environment but not in
the imported env only if the H_NOCLEAR flag is not passed.

Suggested-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
lib/hashtable.c

index 52aab6df6ebc6f4aca53e8e5350315109b345f33..ffaa5b6e4be782834f0c9842fe8a7f8085cbc153 100644 (file)
@@ -749,8 +749,11 @@ static int drop_var_from_set(const char *name, int nvars, char * vars[])
  *
  * The "flag" argument can be used to control the behaviour: when the
  * H_NOCLEAR bit is set, then an existing hash table will kept, i. e.
- * new data will be added to an existing hash table; otherwise, old
- * data will be discarded and a new hash table will be created.
+ * new data will be added to an existing hash table; otherwise, if no
+ * vars are passed, old data will be discarded and a new hash table
+ * will be created. If vars are passed, passed vars that are not in
+ * the linear list of "name=value" pairs will be removed from the
+ * current hash table.
  *
  * The separator character for the "name=value" pairs can be selected,
  * so we both support importing from externally stored environment
@@ -801,7 +804,7 @@ int himport_r(struct hsearch_data *htab,
        if (nvars)
                memcpy(localvars, vars, sizeof(vars[0]) * nvars);
 
-       if ((flag & H_NOCLEAR) == 0) {
+       if ((flag & H_NOCLEAR) == 0 && !nvars) {
                /* Destroy old hash table if one exists */
                debug("Destroy Hash Table: %p table = %p\n", htab,
                       htab->table);
@@ -933,6 +936,9 @@ int himport_r(struct hsearch_data *htab,
        debug("INSERT: free(data = %p)\n", data);
        free(data);
 
+       if (flag & H_NOCLEAR)
+               goto end;
+
        /* process variables which were not considered */
        for (i = 0; i < nvars; i++) {
                if (localvars[i] == NULL)
@@ -951,6 +957,7 @@ int himport_r(struct hsearch_data *htab,
                        printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
        }
 
+end:
        debug("INSERT: done\n");
        return 1;               /* everything OK */
 }