'flags' value of all the entries in hashtable should be preserved across
save/load of U-Boot environment context.
To hold such information in an exported file, its text format is now
expanded as follows:
name:attr=value<sp>
   ...
\0

where "attr" must be a fixed-length(ENV_FLAGS_ATTR_MAX_LEN) string which
complies with a existing format of ".flags" variable and used by
env_attr_lookup().

Signed-off-by: AKASHI Takahiro <takahiro.aka...@linaro.org>
---
 include/search.h |  1 +
 lib/hashtable.c  | 61 ++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/include/search.h b/include/search.h
index 9cece695d726..ab0d7ccb5f8c 100644
--- a/include/search.h
+++ b/include/search.h
@@ -133,6 +133,7 @@ extern int hwalk_r(struct hsearch_data *__htab, int 
(*callback)(ENTRY *));
 #define H_MATCH_REGEX  (1 << 8) /* search for regular expression matches    */
 #define H_MATCH_METHOD (H_MATCH_IDENT | H_MATCH_SUBSTR | H_MATCH_REGEX)
 #define H_PROGRAMMATIC (1 << 9) /* indicate that an import is from env_set() */
+#define H_MATCH_FLAGS  (1 << 10) /* search/grep key  = variable flags       */
 #define H_ORIGIN_FLAGS (H_INTERACTIVE | H_PROGRAMMATIC)
 
 #endif /* _SEARCH_H_ */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index d6975d9cafc6..3fe1d38c827e 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -248,6 +248,15 @@ static inline int _compare_and_overwrite_entry(ENTRY item, 
ACTION action,
 
                /* Overwrite existing value? */
                if ((action == ENTER) && (item.data != NULL)) {
+                       /* attributes cannot be changed */
+                       if (item.flags != htab->table[idx].entry.flags) {
+                               debug("attributes cannot be changed %s\n",
+                                     item.key);
+                               __set_errno(EINVAL);
+                               *retval = NULL;
+                               return 0;
+                       }
+
                        /* check for permission */
                        if (htab->change_ok != NULL && htab->change_ok(
                            &htab->table[idx].entry, item.data,
@@ -389,6 +398,8 @@ int hsearch_ext(ENTRY item, ACTION action, ENTRY ** retval,
                htab->table[idx].used = hval;
                htab->table[idx].entry.context = item.context;
                htab->table[idx].entry.key = strdup(item.key);
+               /* TODO: can be overwritten by env_flags_init() */
+               htab->table[idx].entry.flags = item.flags;
                htab->table[idx].entry.data = strdup(item.data);
                if (!htab->table[idx].entry.key ||
                    !htab->table[idx].entry.data) {
@@ -402,7 +413,9 @@ int hsearch_ext(ENTRY item, ACTION action, ENTRY ** retval,
                /* 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);
+               /* TODO: or we may want to add another argument? */
+               if (!item.flags)
+                       env_flags_init(&htab->table[idx].entry);
 
                /* check for permission */
                if (htab->change_ok != NULL && htab->change_ok(
@@ -596,6 +609,21 @@ static int match_string(int flag, const char *str, const 
char *pat, void *priv)
        return 0;
 }
 
+/* TODO: we always need some kind of regex matching */
+static int match_attr(int flag, const char *attr, const char *pat, void *priv)
+{
+       int found, i;
+
+       for (found = 1, i = 0; i < ENV_FLAGS_ATTR_MAX_LEN; i++) {
+               if (pat[i] != '.' && attr[i] != pat[i]) {
+                       found = 0;
+                       break;
+               }
+       }
+
+       return found;
+}
+
 static int match_entry(ENTRY *ep, int flag,
                 int argc, char * const argv[])
 {
@@ -617,6 +645,14 @@ static int match_entry(ENTRY *ep, int flag,
                        if (match_string(flag, ep->key, argv[arg], priv))
                                return 1;
                }
+               if (flag & H_MATCH_FLAGS) {
+                       char attr[ENV_FLAGS_ATTR_MAX_LEN + 1];
+
+                       env_flags_encode_attr_from_binflags(attr, ep->flags);
+                       attr[ENV_FLAGS_ATTR_MAX_LEN] = '\0';
+                       if (match_attr(flag, attr, argv[arg], priv))
+                               return 1;
+               }
                if (flag & H_MATCH_DATA) {
                        if (match_string(flag, ep->data, argv[arg], priv))
                                return 1;
@@ -680,6 +716,7 @@ ssize_t hexport_ext(struct hsearch_data *htab, unsigned int 
ctx,
                                        ++s;
                                }
                        }
+                       totlen += ENV_FLAGS_ATTR_MAX_LEN + 1; /* for :xxx */
                        totlen += 2;    /* for '=' and 'sep' char */
                }
        }
@@ -731,6 +768,9 @@ ssize_t hexport_ext(struct hsearch_data *htab, unsigned int 
ctx,
                s = list[i]->key;
                while (*s)
                        *p++ = *s++;
+               *p++ = ':';
+               env_flags_encode_attr_from_binflags(p, list[i]->flags);
+               p += ENV_FLAGS_ATTR_MAX_LEN;
                *p++ = '=';
 
                s = list[i]->data;
@@ -829,9 +869,9 @@ int himport_ext(struct hsearch_data *htab, unsigned int ctx,
                const char *env, size_t size, const char sep, int flag,
                int crlf_is_lf, int nvars, char * const vars[])
 {
-       char *data, *sp, *dp, *name, *value;
+       char *data, *sp, *dp, *name, *value, *attr;
        char *localvars[nvars];
-       int i;
+       int flags, i;
 
        /* Test for correct arguments.  */
        if (htab == NULL) {
@@ -927,8 +967,10 @@ int himport_ext(struct hsearch_data *htab, unsigned int 
ctx,
                }
 
                /* parse name */
-               for (name = dp; *dp != '=' && *dp && *dp != sep; ++dp)
-                       ;
+               for (name = dp, attr = NULL; *dp != '=' && *dp && *dp != sep;
+                    ++dp)
+                       if (*dp == ':')
+                               attr = dp;
 
                /* deal with "name" and "name=" entries (delete var) */
                if (*dp == '\0' || *(dp + 1) == '\0' ||
@@ -936,6 +978,8 @@ int himport_ext(struct hsearch_data *htab, unsigned int ctx,
                        if (*dp == '=')
                                *dp++ = '\0';
                        *dp++ = '\0';   /* terminate name */
+                       if (attr)
+                               *attr = '\0';
 
                        debug("DELETE CANDIDATE: \"%s\"\n", name);
                        if (!drop_var_from_set(name, nvars, localvars))
@@ -947,6 +991,12 @@ int himport_ext(struct hsearch_data *htab, unsigned int 
ctx,
                        continue;
                }
                *dp++ = '\0';   /* terminate name */
+               if (attr) {
+                       *attr = '\0';
+                       flags = env_parse_flags_to_bin(++attr);
+               } else {
+                       flags = 0; /* TODO: default? */
+               }
 
                /* parse value; deal with escapes */
                for (value = sp = dp; *dp && (*dp != sep); ++dp) {
@@ -971,6 +1021,7 @@ int himport_ext(struct hsearch_data *htab, unsigned int 
ctx,
                /* enter into hash table */
                e.context = ctx;
                e.key = name;
+               e.flags = flags;
                e.data = value;
 
                hsearch_ext(e, ENTER, &rv, htab, flag);
-- 
2.21.0

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to