+// 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.
*
- * Copyright (C) 2010 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2010-2013 Wolfgang Denk <wd@denx.de>
*
* Original license header:
*
* 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.
- *
- * The GNU C Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * The GNU C Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the GNU C Library; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307 USA.
*/
#include <errno.h>
#endif
#include <env_callback.h>
+#include <env_flags.h>
#include <search.h>
+#include <slre.h>
/*
* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
* example for functions like hdelete().
*/
-/*
- * hstrstr_r - return index to entry whose key and/or data contains match
- */
-int hstrstr_r(const char *match, int last_idx, ENTRY ** retval,
- struct hsearch_data *htab)
-{
- unsigned int idx;
-
- for (idx = last_idx + 1; idx < htab->size; ++idx) {
- if (htab->table[idx].used <= 0)
- continue;
- if (strstr(htab->table[idx].entry.key, match) ||
- strstr(htab->table[idx].entry.data, match)) {
- *retval = &htab->table[idx].entry;
- return idx;
- }
- }
-
- __set_errno(ESRCH);
- *retval = NULL;
- return 0;
-}
-
int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
struct hsearch_data *htab)
{
/* This is a new entry, so look up a possible callback */
env_callback_init(&htab->table[idx].entry);
+ /* Also look for flags */
+ env_flags_init(&htab->table[idx].entry);
/* check for permission */
if (htab->change_ok != NULL && htab->change_ok(
free((void *)ep->key);
free(ep->data);
ep->callback = NULL;
+ ep->flags = 0;
htab->table[idx].used = -1;
--htab->filled;
return 1;
}
+#if !(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SAVEENV))
/*
* hexport()
*/
-#ifndef CONFIG_SPL_BUILD
/*
* Export the data stored in the hash table in linearized form.
*
*
* If the separator character is different from NUL, then any
* separator characters and backslash characters in the values will
- * be escaped by a preceeding backslash in output. This is needed for
+ * be escaped by a preceding backslash in output. This is needed for
* example to enable multi-line values, especially when the output
* shall later be parsed (for example, for re-import).
*
return (strcmp(e1->key, e2->key));
}
+static int match_string(int flag, const char *str, const char *pat, void *priv)
+{
+ switch (flag & H_MATCH_METHOD) {
+ case H_MATCH_IDENT:
+ if (strcmp(str, pat) == 0)
+ return 1;
+ break;
+ case H_MATCH_SUBSTR:
+ if (strstr(str, pat))
+ return 1;
+ break;
+#ifdef CONFIG_REGEX
+ 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))
+ return 1;
+ }
+ break;
+#endif
+ default:
+ printf("## ERROR: unsupported match method: 0x%02x\n",
+ flag & H_MATCH_METHOD);
+ break;
+ }
+ return 0;
+}
+
+static int match_entry(ENTRY *ep, int flag,
+ int argc, char * const argv[])
+{
+ int arg;
+ void *priv = NULL;
+
+ for (arg = 0; arg < argc; ++arg) {
+#ifdef CONFIG_REGEX
+ struct slre slre;
+
+ if (slre_compile(&slre, argv[arg]) == 0) {
+ printf("Error compiling regex: %s\n", slre.err_str);
+ return 0;
+ }
+
+ priv = (void *)&slre;
+#endif
+ if (flag & H_MATCH_KEY) {
+ if (match_string(flag, ep->key, argv[arg], priv))
+ return 1;
+ }
+ if (flag & H_MATCH_DATA) {
+ if (match_string(flag, ep->data, argv[arg], priv))
+ return 1;
+ }
+ }
+ return 0;
+}
+
ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
char **resp, size_t size,
int argc, char * const argv[])
return (-1);
}
- debug("EXPORT table = %p, htab.size = %d, htab.filled = %d, "
- "size = %zu\n", htab, htab->size, htab->filled, size);
+ debug("EXPORT table = %p, htab.size = %d, htab.filled = %d, size = %lu\n",
+ htab, htab->size, htab->filled, (ulong)size);
/*
* Pass 1:
* search used entries,
if (htab->table[i].used > 0) {
ENTRY *ep = &htab->table[i].entry;
- int arg, found = 0;
+ int found = match_entry(ep, flag, argc, argv);
- for (arg = 0; arg < argc; ++arg) {
- if (strcmp(argv[arg], ep->key) == 0) {
- found = 1;
- break;
- }
- }
if ((argc > 0) && (found == 0))
continue;
/* Check if the user supplied buffer size is sufficient */
if (size) {
if (size < totlen + 1) { /* provided buffer too small */
- printf("Env export buffer too small: %zu, "
- "but need %zu\n", size, totlen + 1);
+ printf("Env export buffer too small: %lu, but need %lu\n",
+ (ulong)size, (ulong)totlen + 1);
__set_errno(ENOMEM);
return (-1);
}
int himport_r(struct hsearch_data *htab,
const char *env, size_t size, const char sep, int flag,
- int nvars, char * const vars[])
+ int crlf_is_lf, int nvars, char * const vars[])
{
char *data, *sp, *dp, *name, *value;
char *localvars[nvars];
}
/* we allocate new space to make sure we can write to the array */
- if ((data = malloc(size)) == NULL) {
- debug("himport_r: can't malloc %zu bytes\n", size);
+ if ((data = malloc(size + 1)) == NULL) {
+ debug("himport_r: can't malloc %lu bytes\n", (ulong)size + 1);
__set_errno(ENOMEM);
return 0;
}
memcpy(data, env, size);
+ data[size] = '\0';
dp = data;
/* make a local copy of the list of variables */
* size of 8 per entry (= safety factor of ~5) should provide enough
* safety margin for any existing environment definitions and still
* allow for more than enough dynamic additions. Note that the
- * "size" argument is supposed to give the maximum enviroment size
+ * "size" argument is supposed to give the maximum environment size
* (CONFIG_ENV_SIZE). This heuristics will result in
* unreasonably large numbers (and thus memory footprint) for
* big flash environments (>8,000 entries for 64 KB
- * envrionment size), so we clip it to a reasonable value.
+ * environment size), so we clip it to a reasonable value.
* On the other hand we need to add some more entries for free
* space when importing very small buffers. Both boundaries can
* be overwritten in the board config file if needed.
}
}
+ if (!size) {
+ free(data);
+ return 1; /* everything OK */
+ }
+ if(crlf_is_lf) {
+ /* Remove Carriage Returns in front of Line Feeds */
+ unsigned ignored_crs = 0;
+ for(;dp < data + size && *dp; ++dp) {
+ if(*dp == '\r' &&
+ dp < data + size - 1 && *(dp+1) == '\n')
+ ++ignored_crs;
+ else
+ *(dp-ignored_crs) = *dp;
+ }
+ size -= ignored_crs;
+ dp = data;
+ }
/* Parse environment; allow for '\0' and 'sep' as separators */
do {
ENTRY e, *rv;
*sp++ = '\0'; /* terminate value */
++dp;
+ if (*name == 0) {
+ debug("INSERT: unable to use an empty key\n");
+ __set_errno(EINVAL);
+ free(data);
+ return 0;
+ }
+
/* Skip variables which are not supposed to be processed */
if (!drop_var_from_set(name, nvars, localvars))
continue;