* overwriting of write-once variables.
*/
-int env_check_apply(const char *name, const char *oldval,
- const char *newval, int flag)
+int env_change_ok(const ENTRY *item, const char *newval, enum env_op op,
+ int flag)
{
int console = -1;
+ const char *name;
+#if !defined(CONFIG_ENV_OVERWRITE) && defined(CONFIG_OVERWRITE_ETHADDR_ONCE) \
+&& defined(CONFIG_ETHADDR)
+ const char *oldval = NULL;
+
+ if (op != env_op_create)
+ oldval = item->data;
+#endif
+
+ name = item->key;
/* Default value for NULL to protect string-manipulating functions */
newval = newval ? : "";
#endif /* CONFIG_CONSOLE_MUX */
}
+#ifndef CONFIG_ENV_OVERWRITE
/*
* Some variables like "ethaddr" and "serial#" can be set only once and
* cannot be deleted, unless CONFIG_ENV_OVERWRITE is defined.
*/
-#ifndef CONFIG_ENV_OVERWRITE
- if (oldval != NULL && /* variable exists */
+ if (op != env_op_create && /* variable exists */
(flag & H_FORCE) == 0) { /* and we are not forced */
if (strcmp(name, "serial#") == 0 ||
(strcmp(name, "ethaddr") == 0
* (which will erase all variables prior to calling this),
* we want the baudrate to actually change - for real.
*/
- if (oldval != NULL || /* variable exists */
+ if (op != env_op_create || /* variable exists */
(flag & H_NOCLEAR) == 0) { /* or env is clear */
/*
* Switch to new baudrate if new baudrate is supported
}
env_id++;
- /*
- * search if variable with this name already exists
- */
- e.key = name;
- e.data = NULL;
- hsearch_r(e, FIND, &ep, &env_htab, 0);
-
- /*
- * Perform requested checks.
- */
- if (env_check_apply(name, ep ? ep->data : NULL, value, 0)) {
- debug("check function did not approve, refusing\n");
- return 1;
- }
/* Delete only ? */
if (argc < 3 || argv[2] == NULL) {
#include <env_default.h>
struct hsearch_data env_htab = {
- .apply = env_check_apply,
+ .change_ok = env_change_ok,
};
static uchar __env_get_char_spec(int index)
{
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
env_reloc();
+ env_htab.change_ok += gd->reloc_off;
#endif
if (gd->env_valid == 0) {
#if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
int env_import(const char *buf, int check);
/*
- * Check if variable "name" can be changed from oldval to newval,
- * and if so, apply the changes (e.g. baudrate).
+ * Check if variable "item" can be changed to newval
* When (flag & H_FORCE) is set, it does not print out any error
* message and forces overwriting of write-once variables.
*/
-int env_check_apply(const char *name, const char *oldval,
- const char *newval, int flag);
+int env_change_ok(const ENTRY *item, const char *newval, enum env_op op,
+ int flag);
#endif /* DO_DEPS_ONLY */
#define __set_errno(val) do { errno = val; } while (0)
+enum env_op {
+ env_op_create,
+ env_op_delete,
+ env_op_overwrite,
+};
+
/* Action which shall be performed in the call the hsearch. */
typedef enum {
FIND,
unsigned int filled;
/*
* Callback function which will check whether the given change for variable
- * "name" from "oldval" to "newval" may be applied or not, and possibly apply
- * such change.
+ * "item" to "newval" may be applied or not, and possibly apply such change.
* When (flag & H_FORCE) is set, it shall not print out any error message and
* shall force overwriting of write-once variables.
.* Must return 0 for approval, 1 for denial.
*/
- int (*apply)(const char *name, const char *oldval,
- const char *newval, int flag);
+ int (*change_ok)(const ENTRY *__item, const char *newval, enum env_op,
+ int flag);
};
/* Create a new hashing table which will at most contain NEL elements. */
* Instead the interface of all functions is extended to take an argument
* which describes the current status.
*/
+
typedef struct _ENTRY {
int used;
ENTRY entry;
} _ENTRY;
+static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
+ int idx);
+
/*
* hcreate()
*/
&& strcmp(item.key, htab->table[idx].entry.key) == 0) {
/* Overwrite existing value? */
if ((action == ENTER) && (item.data != NULL)) {
+ /* check for permission */
+ if (htab->change_ok != NULL && htab->change_ok(
+ &htab->table[idx].entry, item.data,
+ env_op_overwrite, flag)) {
+ debug("change_ok() rejected setting variable "
+ "%s, skipping it!\n", item.key);
+ __set_errno(EPERM);
+ *retval = NULL;
+ return 0;
+ }
+
free(htab->table[idx].entry.data);
htab->table[idx].entry.data = strdup(item.data);
if (!htab->table[idx].entry.data) {
++htab->filled;
+ /* check for permission */
+ if (htab->change_ok != NULL && htab->change_ok(
+ &htab->table[idx].entry, item.data, env_op_create, flag)) {
+ debug("change_ok() rejected setting variable "
+ "%s, skipping it!\n", item.key);
+ _hdelete(item.key, htab, &htab->table[idx].entry, idx);
+ __set_errno(EPERM);
+ *retval = NULL;
+ return 0;
+ }
+
/* return new entry */
*retval = &htab->table[idx].entry;
return 1;
* do that.
*/
+static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
+ int idx)
+{
+ /* free used ENTRY */
+ debug("hdelete: DELETING key \"%s\"\n", key);
+ free((void *)ep->key);
+ free(ep->data);
+ htab->table[idx].used = -1;
+
+ --htab->filled;
+}
+
int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
{
ENTRY e, *ep;
}
/* Check for permission */
- if (htab->apply != NULL &&
- htab->apply(ep->key, ep->data, NULL, flag)) {
+ if (htab->change_ok != NULL &&
+ htab->change_ok(ep, NULL, env_op_delete, flag)) {
+ debug("change_ok() rejected deleting variable "
+ "%s, skipping it!\n", key);
__set_errno(EPERM);
return 0;
}
- /* free used ENTRY */
- debug("hdelete: DELETING key \"%s\"\n", key);
- free((void *)ep->key);
- free(ep->data);
- htab->table[idx].used = -1;
-
- --htab->filled;
+ _hdelete(key, htab, ep, idx);
return 1;
}
e.key = name;
e.data = value;
- /* if there is an apply function, check what it has to say */
- if (htab->apply != NULL) {
- debug("searching before calling cb function"
- " for %s\n", name);
- /*
- * Search for variable in existing env, so to pass
- * its previous value to the apply callback
- */
- hsearch_r(e, FIND, &rv, htab, 0);
- debug("previous value was %s\n", rv ? rv->data : "");
- if (htab->apply(name, rv ? rv->data : NULL,
- value, flag)) {
- debug("callback function refused to set"
- " variable %s, skipping it!\n", name);
- continue;
- }
- }
-
hsearch_r(e, ENTER, &rv, htab, flag);
if (rv == NULL) {
printf("himport_r: can't insert \"%s=%s\" into hash table\n",