summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJoe Hershberger <joe.hershberger@ni.com>2012-12-11 22:16:21 -0600
committerTom Rini <trini@ti.com>2012-12-13 11:46:55 -0700
commit7afcf3a55b5f484b3d3442053fae8186a3fb92d7 (patch)
tree1aa2c5143a1bbef6570b03652107a09832a2f2ad /lib
parent3d3b52f2586a8bf1c53496547062594fd4386454 (diff)
env: Refactor apply into change_ok
Move the read of the old value to inside the check function. In some cases it can be avoided all together and at the least the code is only called from one place. Also name the function and the callback to more clearly describe what it does. Pass the ENTRY instead of just the name for direct access to the whole data structure. Pass an enum to the callback that specifies the operation being approved. Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/hashtable.c70
1 files changed, 43 insertions, 27 deletions
diff --git a/lib/hashtable.c b/lib/hashtable.c
index f4d5795059..6861a42029 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -66,12 +66,16 @@
* 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()
*/
@@ -259,6 +263,17 @@ static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
&& 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) {
@@ -383,6 +398,17 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
++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;
@@ -404,6 +430,18 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
* 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;
@@ -420,19 +458,15 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
}
/* 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;
}
@@ -800,24 +834,6 @@ int himport_r(struct hsearch_data *htab,
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",