projects
/
oweals
/
u-boot.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge tag 'u-boot-imx-20200623' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
[oweals/u-boot.git]
/
lib
/
hashtable.c
diff --git
a/lib/hashtable.c
b/lib/hashtable.c
index f08847758a091da8d9960ff94ec830fbcfa502ce..b96dbe19be4dd52e0233e9d452f3201f6c57ad69 100644
(file)
--- a/
lib/hashtable.c
+++ b/
lib/hashtable.c
@@
-1,3
+1,4
@@
+// SPDX-License-Identifier: LGPL-2.1+
/*
* This implementation is based on code from uClibc-0.9.30.3 but was
* modified and extended for use within U-Boot.
/*
* This implementation is based on code from uClibc-0.9.30.3 but was
* modified and extended for use within U-Boot.
@@
-9,12
+10,12
@@
* Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
* This file is part of the GNU C Library.
* Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1993.
* Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
* This file is part of the GNU C Library.
* Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1993.
- *
- * SPDX-License-Identifier: LGPL-2.1+
*/
#include <errno.h>
*/
#include <errno.h>
+#include <log.h>
#include <malloc.h>
#include <malloc.h>
+#include <sort.h>
#ifdef USE_HOSTCC /* HOST build */
# include <string.h>
#ifdef USE_HOSTCC /* HOST build */
# include <string.h>
@@
-41,6
+42,9
@@
#define CONFIG_ENV_MAX_ENTRIES 512
#endif
#define CONFIG_ENV_MAX_ENTRIES 512
#endif
+#define USED_FREE 0
+#define USED_DELETED -1
+
#include <env_callback.h>
#include <env_flags.h>
#include <search.h>
#include <env_callback.h>
#include <env_flags.h>
#include <search.h>
@@
-57,14
+61,14
@@
* which describes the current status.
*/
* which describes the current status.
*/
-
typedef struct _ENTRY
{
+
struct env_entry_node
{
int used;
int used;
-
ENTRY
entry;
-}
_ENTRY
;
+
struct env_entry
entry;
+};
-static void _hdelete(const char *key, struct hsearch_data *htab,
ENTRY *ep,
- int idx);
+static void _hdelete(const char *key, struct hsearch_data *htab,
+
struct env_entry *ep,
int idx);
/*
* hcreate()
/*
* hcreate()
@@
-118,7
+122,8
@@
int hcreate_r(size_t nel, struct hsearch_data *htab)
htab->filled = 0;
/* allocate memory and zero out */
htab->filled = 0;
/* allocate memory and zero out */
- htab->table = (_ENTRY *) calloc(htab->size + 1, sizeof(_ENTRY));
+ htab->table = (struct env_entry_node *)calloc(htab->size + 1,
+ sizeof(struct env_entry_node));
if (htab->table == NULL)
return 0;
if (htab->table == NULL)
return 0;
@@
-149,7
+154,7
@@
void hdestroy_r(struct hsearch_data *htab)
/* free used memory */
for (i = 1; i <= htab->size; ++i) {
if (htab->table[i].used > 0) {
/* free used memory */
for (i = 1; i <= htab->size; ++i) {
if (htab->table[i].used > 0) {
-
ENTRY
*ep = &htab->table[i].entry;
+
struct env_entry
*ep = &htab->table[i].entry;
free((void *)ep->key);
free(ep->data);
free((void *)ep->key);
free(ep->data);
@@
-191,14
+196,14
@@
void hdestroy_r(struct hsearch_data *htab)
* data any more.
* - The standard implementation does not provide a way to update an
* existing entry. This version will create a new entry or update an
* data any more.
* - The standard implementation does not provide a way to update an
* existing entry. This version will create a new entry or update an
- * existing one when both "action == ENTER" and "item.data != NULL".
+ * existing one when both "action == EN
V_EN
TER" and "item.data != NULL".
* - Instead of returning 1 on success, we return the index into the
* internal hash table, which is also guaranteed to be positive.
* This allows us direct access to the found hash table slot for
* example for functions like hdelete().
*/
* - Instead of returning 1 on success, we return the index into the
* internal hash table, which is also guaranteed to be positive.
* This allows us direct access to the found hash table slot for
* example for functions like hdelete().
*/
-int hmatch_r(const char *match, int last_idx,
ENTRY **
retval,
+int hmatch_r(const char *match, int last_idx,
struct env_entry **
retval,
struct hsearch_data *htab)
{
unsigned int idx;
struct hsearch_data *htab)
{
unsigned int idx;
@@
-218,18
+223,30
@@
int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
return 0;
}
return 0;
}
+static int
+do_callback(const struct env_entry *e, const char *name, const char *value,
+ enum env_op op, int flags)
+{
+#ifndef CONFIG_SPL_BUILD
+ if (e->callback)
+ return e->callback(name, value, op, flags);
+#endif
+ return 0;
+}
+
/*
* Compare an existing entry with the desired key, and overwrite if the action
/*
* Compare an existing entry with the desired key, and overwrite if the action
- * is ENTER. This is simply a helper function for hsearch_r().
+ * is EN
V_EN
TER. This is simply a helper function for hsearch_r().
*/
*/
-static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
- ENTRY **retval, struct hsearch_data *htab, int flag,
- unsigned int hval, unsigned int idx)
+static inline int _compare_and_overwrite_entry(struct env_entry item,
+ enum env_action action, struct env_entry **retval,
+ struct hsearch_data *htab, int flag, unsigned int hval,
+ unsigned int idx)
{
if (htab->table[idx].used == hval
&& strcmp(item.key, htab->table[idx].entry.key) == 0) {
/* Overwrite existing value? */
{
if (htab->table[idx].used == hval
&& strcmp(item.key, htab->table[idx].entry.key) == 0) {
/* Overwrite existing value? */
- if (
(action == ENTER) && (item.data != NULL)
) {
+ if (
action == ENV_ENTER && item.data
) {
/* check for permission */
if (htab->change_ok != NULL && htab->change_ok(
&htab->table[idx].entry, item.data,
/* check for permission */
if (htab->change_ok != NULL && htab->change_ok(
&htab->table[idx].entry, item.data,
@@
-242,9
+259,8
@@
static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
}
/* If there is a callback, call it */
}
/* 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)) {
+ if (do_callback(&htab->table[idx].entry, item.key,
+ item.data, env_op_overwrite, flag)) {
debug("callback() rejected setting variable "
"%s, skipping it!\n", item.key);
__set_errno(EINVAL);
debug("callback() rejected setting variable "
"%s, skipping it!\n", item.key);
__set_errno(EINVAL);
@@
-268,8
+284,8
@@
static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
return -1;
}
return -1;
}
-int hsearch_r(
ENTRY item, ACTION action, ENTRY ** retval
,
- struct hsearch_data *htab, int flag)
+int hsearch_r(
struct env_entry item, enum env_action action
,
+ struct
env_entry **retval, struct
hsearch_data *htab, int flag)
{
unsigned int hval;
unsigned int count;
{
unsigned int hval;
unsigned int count;
@@
-304,7
+320,7
@@
int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
*/
unsigned hval2;
*/
unsigned hval2;
- if (htab->table[idx].used ==
-1
+ if (htab->table[idx].used ==
USED_DELETED
&& !first_deleted)
first_deleted = idx;
&& !first_deleted)
first_deleted = idx;
@@
-336,17
+352,21
@@
int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
if (idx == hval)
break;
if (idx == hval)
break;
+ if (htab->table[idx].used == USED_DELETED
+ && !first_deleted)
+ first_deleted = idx;
+
/* If entry is found use it. */
ret = _compare_and_overwrite_entry(item, action, retval,
htab, flag, hval, idx);
if (ret != -1)
return ret;
}
/* If entry is found use it. */
ret = _compare_and_overwrite_entry(item, action, retval,
htab, flag, hval, idx);
if (ret != -1)
return ret;
}
- while (htab->table[idx].used);
+ while (htab->table[idx].used
!= USED_FREE
);
}
/* An empty bucket has been found. */
}
/* An empty bucket has been found. */
- if (action == ENTER) {
+ if (action == EN
V_EN
TER) {
/*
* If table is full and another entry should be
* entered return with error.
/*
* If table is full and another entry should be
* entered return with error.
@@
-393,9
+413,8
@@
int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
}
/* If there is a callback, call it */
}
/* 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)) {
+ if (do_callback(&htab->table[idx].entry, item.key, item.data,
+ env_op_create, flag)) {
debug("callback() rejected setting variable "
"%s, skipping it!\n", item.key);
_hdelete(item.key, htab, &htab->table[idx].entry, idx);
debug("callback() rejected setting variable "
"%s, skipping it!\n", item.key);
_hdelete(item.key, htab, &htab->table[idx].entry, idx);
@@
-425,30
+444,29
@@
int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
* do that.
*/
* do that.
*/
-static void _hdelete(const char *key, struct hsearch_data *htab,
ENTRY *ep,
- int idx)
+static void _hdelete(const char *key, struct hsearch_data *htab,
+
struct env_entry *ep,
int idx)
{
{
- /* free used
ENTRY
*/
+ /* free used
entry
*/
debug("hdelete: DELETING key \"%s\"\n", key);
free((void *)ep->key);
free(ep->data);
debug("hdelete: DELETING key \"%s\"\n", key);
free((void *)ep->key);
free(ep->data);
- ep->callback = NULL;
ep->flags = 0;
ep->flags = 0;
- htab->table[idx].used =
-1
;
+ htab->table[idx].used =
USED_DELETED
;
--htab->filled;
}
int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
{
--htab->filled;
}
int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
{
-
ENTRY
e, *ep;
+
struct env_entry
e, *ep;
int idx;
debug("hdelete: DELETE key \"%s\"\n", key);
e.key = (char *)key;
int idx;
debug("hdelete: DELETE key \"%s\"\n", key);
e.key = (char *)key;
- idx = hsearch_r(e, FIND, &ep, htab, 0);
+ idx = hsearch_r(e,
ENV_
FIND, &ep, htab, 0);
if (idx == 0) {
__set_errno(ESRCH);
return 0; /* not found */
if (idx == 0) {
__set_errno(ESRCH);
return 0; /* not found */
@@
-464,8
+482,8
@@
int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
}
/* If there is a callback, call it */
}
/* If there is a callback, call it */
- if (
htab->table[idx].entry.callback &&
-
htab->table[idx].entry.callback(key, NULL,
env_op_delete, flag)) {
+ if (
do_callback(&htab->table[idx].entry, key, NULL,
+
env_op_delete, flag)) {
debug("callback() rejected deleting variable "
"%s, skipping it!\n", key);
__set_errno(EINVAL);
debug("callback() rejected deleting variable "
"%s, skipping it!\n", key);
__set_errno(EINVAL);
@@
-522,8
+540,8
@@
int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
static int cmpkey(const void *p1, const void *p2)
{
static int cmpkey(const void *p1, const void *p2)
{
-
ENTRY *e1 = *(ENTRY **)
p1;
-
ENTRY *e2 = *(ENTRY **)
p2;
+
struct env_entry *e1 = *(struct env_entry **)
p1;
+
struct env_entry *e2 = *(struct env_entry **)
p2;
return (strcmp(e1->key, e2->key));
}
return (strcmp(e1->key, e2->key));
}
@@
-543,9
+561,8
@@
static int match_string(int flag, const char *str, const char *pat, void *priv)
case H_MATCH_REGEX:
{
struct slre *slrep = (struct slre *)priv;
case H_MATCH_REGEX:
{
struct slre *slrep = (struct slre *)priv;
- struct cap caps[slrep->num_caps + 2];
- if (slre_match(slrep, str, strlen(str),
caps
))
+ if (slre_match(slrep, str, strlen(str),
NULL
))
return 1;
}
break;
return 1;
}
break;
@@
-558,8
+575,8
@@
static int match_string(int flag, const char *str, const char *pat, void *priv)
return 0;
}
return 0;
}
-static int match_entry(
ENTRY *ep, int flag
,
-
int argc, char *
const argv[])
+static int match_entry(
struct env_entry *ep, int flag, int argc
,
+
char *
const argv[])
{
int arg;
void *priv = NULL;
{
int arg;
void *priv = NULL;
@@
-589,9
+606,9
@@
static int match_entry(ENTRY *ep, int flag,
ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
char **resp, size_t size,
ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
char **resp, size_t size,
- int argc, char *
const argv[])
+ int argc, char *const argv[])
{
{
-
ENTRY
*list[htab->size];
+
struct env_entry
*list[htab->size];
char *res, *p;
size_t totlen;
int i, n;
char *res, *p;
size_t totlen;
int i, n;
@@
-612,7
+629,7
@@
ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
for (i = 1, n = 0, totlen = 0; i <= htab->size; ++i) {
if (htab->table[i].used > 0) {
for (i = 1, n = 0, totlen = 0; i <= htab->size; ++i) {
if (htab->table[i].used > 0) {
-
ENTRY
*ep = &htab->table[i].entry;
+
struct env_entry
*ep = &htab->table[i].entry;
int found = match_entry(ep, flag, argc, argv);
if ((argc > 0) && (found == 0))
int found = match_entry(ep, flag, argc, argv);
if ((argc > 0) && (found == 0))
@@
-623,7
+640,7
@@
ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
list[n++] = ep;
list[n++] = ep;
- totlen += strlen(ep->key)
+ 2
;
+ totlen += strlen(ep->key);
if (sep == '\0') {
totlen += strlen(ep->data);
if (sep == '\0') {
totlen += strlen(ep->data);
@@
-652,7
+669,7
@@
ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
#endif
/* Sort list by keys */
#endif
/* Sort list by keys */
- qsort(list, n, sizeof(
ENTRY
*), cmpkey);
+ qsort(list, n, sizeof(
struct env_entry
*), cmpkey);
/* Check if the user supplied buffer size is sufficient */
if (size) {
/* Check if the user supplied buffer size is sufficient */
if (size) {
@@
-750,8
+767,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.
*
* 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
*
* The separator character for the "name=value" pairs can be selected,
* so we both support importing from externally stored environment
@@
-802,7
+822,7
@@
int himport_r(struct hsearch_data *htab,
if (nvars)
memcpy(localvars, vars, sizeof(vars[0]) * nvars);
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);
/* Destroy old hash table if one exists */
debug("Destroy Hash Table: %p table = %p\n", htab,
htab->table);
@@
-861,7
+881,7
@@
int himport_r(struct hsearch_data *htab,
}
/* Parse environment; allow for '\0' and 'sep' as separators */
do {
}
/* Parse environment; allow for '\0' and 'sep' as separators */
do {
-
ENTRY
e, *rv;
+
struct env_entry
e, *rv;
/* skip leading white space */
while (isblank(*dp))
/* skip leading white space */
while (isblank(*dp))
@@
-921,7
+941,7
@@
int himport_r(struct hsearch_data *htab,
e.key = name;
e.data = value;
e.key = name;
e.data = value;
- hsearch_r(e, ENTER, &rv, htab, flag);
+ hsearch_r(e, EN
V_EN
TER, &rv, htab, flag);
if (rv == NULL)
printf("himport_r: can't insert \"%s=%s\" into hash table\n",
name, value);
if (rv == NULL)
printf("himport_r: can't insert \"%s=%s\" into hash table\n",
name, value);
@@
-934,6
+954,9
@@
int himport_r(struct hsearch_data *htab,
debug("INSERT: free(data = %p)\n", data);
free(data);
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)
/* process variables which were not considered */
for (i = 0; i < nvars; i++) {
if (localvars[i] == NULL)
@@
-952,6
+975,7
@@
int himport_r(struct hsearch_data *htab,
printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
}
printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
}
+end:
debug("INSERT: done\n");
return 1; /* everything OK */
}
debug("INSERT: done\n");
return 1; /* everything OK */
}
@@
-964,7
+988,7
@@
int himport_r(struct hsearch_data *htab,
* Walk all of the entries in the hash, calling the callback for each one.
* this allows some generic operation to be performed on each element.
*/
* Walk all of the entries in the hash, calling the callback for each one.
* this allows some generic operation to be performed on each element.
*/
-int hwalk_r(struct hsearch_data *htab, int (*callback)(
ENTRY *
))
+int hwalk_r(struct hsearch_data *htab, int (*callback)(
struct env_entry *entry
))
{
int i;
int retval;
{
int i;
int retval;