
With this patch, variable's context is always honored in all operations, FIND/ENTER (including delete).
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/search.h | 6 +++++- lib/hashtable.c | 14 +++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/include/search.h b/include/search.h index 0469a852e07c..202cf652de5f 100644 --- a/include/search.h +++ b/include/search.h @@ -25,13 +25,16 @@ enum env_action { ENV_ENTER, };
+struct env_context; + /** struct env_entry - An entry in the environment hashtable */ struct env_entry { const char *key; char *data; int (*callback)(const char *name, const char *value, enum env_op op, - int flags); + int flags); int flags; + struct env_context *ctx; };
/* @@ -45,6 +48,7 @@ struct hsearch_data { struct env_entry_node *table; unsigned int size; unsigned int filled; + struct env_context *ctx; /* * Callback function which will check whether the given change for variable * "item" to "newval" may be applied or not, and possibly apply such change. diff --git a/lib/hashtable.c b/lib/hashtable.c index 2caab0a4c6d3..8fe017470256 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -231,6 +231,7 @@ static inline int _compare_and_overwrite_entry(struct env_entry item, unsigned int idx) { if (htab->table[idx].used == hval + && (item.ctx && (item.ctx == htab->table[idx].entry.ctx)) && strcmp(item.key, htab->table[idx].entry.key) == 0) { /* Overwrite existing value? */ if (action == ENV_ENTER && item.data) { @@ -247,8 +248,9 @@ static inline int _compare_and_overwrite_entry(struct env_entry item,
/* If there is a callback, call it */ if (htab->table[idx].entry.callback && - htab->table[idx].entry.callback(item.key, - item.data, env_op_overwrite, flag)) { + htab->table[idx].entry.callback(item.key, item.data, + env_op_overwrite, + flag)) { debug("callback() rejected setting variable " "%s, skipping it!\n", item.key); __set_errno(EINVAL); @@ -340,6 +342,9 @@ int hsearch_r(struct env_entry item, enum env_action action, if (idx == hval) break;
+ if (htab->table[idx].used == USED_FREE) + break; + if (htab->table[idx].used == USED_DELETED && !first_deleted) first_deleted = idx; @@ -381,6 +386,7 @@ int hsearch_r(struct env_entry item, enum env_action action, *retval = NULL; return 0; } + htab->table[idx].entry.ctx = item.ctx;
++htab->filled;
@@ -403,7 +409,7 @@ int hsearch_r(struct env_entry item, enum env_action action, /* If there is a callback, call it */ if (htab->table[idx].entry.callback && htab->table[idx].entry.callback(item.key, item.data, - env_op_create, flag)) { + env_op_create, flag)) { debug("callback() rejected setting variable " "%s, skipping it!\n", item.key); _hdelete(item.key, htab, &htab->table[idx].entry, idx); @@ -454,6 +460,7 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
debug("hdelete: DELETE key "%s"\n", key);
+ e.ctx = htab->ctx; e.key = (char *)key;
idx = hsearch_r(e, ENV_FIND, &ep, htab, 0); @@ -928,6 +935,7 @@ int himport_r(struct hsearch_data *htab, continue;
/* enter into hash table */ + e.ctx = htab->ctx; e.key = name; e.data = value;