From d9fc9077eb7eb5b793e5cbfb3364f15754fbb562 Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Mon, 9 Jul 2018 19:16:28 +0200 Subject: [PATCH] hashtable: do not recreate whole hash table if vars are passed to himport_r 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 Signed-off-by: Quentin Schulz --- lib/hashtable.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/hashtable.c b/lib/hashtable.c index 52aab6d..ffaa5b6 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -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 */ }