From patchwork Wed Dec 12 04:16:21 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joe Hershberger X-Patchwork-Id: 205375 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 6BBA12C0094 for ; Wed, 12 Dec 2012 15:20:37 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 604664A279; Wed, 12 Dec 2012 05:20:19 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 81ClGxq1YJ7W; Wed, 12 Dec 2012 05:20:19 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4513B4A01E; Wed, 12 Dec 2012 05:18:29 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id A7D784A160 for ; Wed, 12 Dec 2012 05:17:32 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 0cvaBH3PlSkD for ; Wed, 12 Dec 2012 05:17:30 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from spamkiller06.natinst.com (mailserver6.natinst.com [130.164.80.6]) by theia.denx.de (Postfix) with ESMTP id 103194A15D for ; Wed, 12 Dec 2012 05:17:22 +0100 (CET) Received: from mailserv58-us.natinst.com (nb-hsrp-1338.natinst.com [130.164.19.133]) by spamkiller06.natinst.com (8.14.5/8.14.5) with ESMTP id qBC4HFsi022809; Tue, 11 Dec 2012 22:17:15 -0600 Received: from linux-xvxi.natinst.com ([130.164.14.197]) by mailserv58-us.natinst.com (Lotus Domino Release 8.5.3FP2 HF169) with ESMTP id 2012121122171588-310419 ; Tue, 11 Dec 2012 22:17:15 -0600 From: Joe Hershberger To: u-boot@lists.denx.de Date: Tue, 11 Dec 2012 22:16:21 -0600 Message-Id: <1355285797-27051-5-git-send-email-joe.hershberger@ni.com> X-Mailer: git-send-email 1.7.11.5 In-Reply-To: <1355285797-27051-1-git-send-email-joe.hershberger@ni.com> References: <1354672367-23747-1-git-send-email-joe.hershberger@ni.com> <1355285797-27051-1-git-send-email-joe.hershberger@ni.com> X-MIMETrack: Itemize by SMTP Server on MailServ58-US/AUS/H/NIC(Release 8.5.3FP2 HF169|September 14, 2012) at 12/11/2012 10:17:15 PM, Serialize by Router on MailServ58-US/AUS/H/NIC(Release 8.5.3FP2 HF169|September 14, 2012) at 12/11/2012 10:17:16 PM, Serialize complete at 12/11/2012 10:17:16 PM X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.9.8327, 1.0.431, 0.0.0000 definitions=2012-12-12_01:2012-12-12, 2012-12-12, 1970-01-01 signatures=0 Cc: Tom Rini , Joe Hershberger , Gerlando Falauto Subject: [U-Boot] [PATCH v5 04/20] env: Refactor apply into change_ok X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de 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 --- Changes in v5: - Manually relocate change_ok() pointer Changes in v4: None Changes in v3: - Split hdelete_r() into the core delete and the validation before delete - Delete vars on failed insertion Changes in v2: None common/cmd_nvedit.c | 34 +++++++++++-------------- common/env_common.c | 3 ++- include/environment.h | 7 +++--- include/search.h | 13 +++++++--- lib/hashtable.c | 70 +++++++++++++++++++++++++++++++-------------------- 5 files changed, 72 insertions(+), 55 deletions(-) diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index a8dc9a6..da5689c 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -208,10 +208,20 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag, * 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 ? : ""; @@ -242,12 +252,12 @@ int env_check_apply(const char *name, const char *oldval, #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 @@ -265,7 +275,7 @@ int env_check_apply(const char *name, const char *oldval, * (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 @@ -339,20 +349,6 @@ static int _do_env_set(int flag, int argc, char * const argv[]) } 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) { diff --git a/common/env_common.c b/common/env_common.c index f22f5b9..a960aa8 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -40,7 +40,7 @@ DECLARE_GLOBAL_DATA_PTR; #include struct hsearch_data env_htab = { - .apply = env_check_apply, + .change_ok = env_change_ok, }; static uchar __env_get_char_spec(int index) @@ -162,6 +162,7 @@ void env_relocate(void) { #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) diff --git a/include/environment.h b/include/environment.h index e8ab703..4b19f32 100644 --- a/include/environment.h +++ b/include/environment.h @@ -188,13 +188,12 @@ int set_default_vars(int nvars, char * const vars[]); 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 */ diff --git a/include/search.h b/include/search.h index f5165b0..fa00ea1 100644 --- a/include/search.h +++ b/include/search.h @@ -32,6 +32,12 @@ #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, @@ -59,14 +65,13 @@ struct hsearch_data { 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. */ diff --git a/lib/hashtable.c b/lib/hashtable.c index f4d5795..6861a42 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",