~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/common/env_attr.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (C) Copyright 2012
 
3
 * Joe Hershberger, National Instruments, joe.hershberger@ni.com
 
4
 *
 
5
 * SPDX-License-Identifier:     GPL-2.0+
 
6
 */
 
7
 
 
8
#ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */
 
9
#include <stdint.h>
 
10
#include <stdio.h>
 
11
#include <linux/linux_string.h>
 
12
#else
 
13
#include <common.h>
 
14
#endif
 
15
 
 
16
#include <env_attr.h>
 
17
#include <errno.h>
 
18
#include <linux/string.h>
 
19
#include <malloc.h>
 
20
 
 
21
/*
 
22
 * Iterate through the whole list calling the callback for each found element.
 
23
 * "attr_list" takes the form:
 
24
 *      attributes = [^,:\s]*
 
25
 *      entry = name[:attributes]
 
26
 *      list = entry[,list]
 
27
 */
 
28
int env_attr_walk(const char *attr_list,
 
29
        int (*callback)(const char *name, const char *attributes))
 
30
{
 
31
        const char *entry, *entry_end;
 
32
        char *name, *attributes;
 
33
 
 
34
        if (!attr_list)
 
35
                /* list not found */
 
36
                return 1;
 
37
 
 
38
        entry = attr_list;
 
39
        do {
 
40
                char *entry_cpy = NULL;
 
41
 
 
42
                entry_end = strchr(entry, ENV_ATTR_LIST_DELIM);
 
43
                /* check if this is the last entry in the list */
 
44
                if (entry_end == NULL) {
 
45
                        int entry_len = strlen(entry);
 
46
 
 
47
                        if (entry_len) {
 
48
                                /*
 
49
                                 * allocate memory to copy the entry into since
 
50
                                 * we will need to inject '\0' chars and squash
 
51
                                 * white-space before calling the callback
 
52
                                 */
 
53
                                entry_cpy = malloc(entry_len + 1);
 
54
                                if (entry_cpy)
 
55
                                        /* copy the rest of the list */
 
56
                                        strcpy(entry_cpy, entry);
 
57
                                else
 
58
                                        return -ENOMEM;
 
59
                        }
 
60
                } else {
 
61
                        int entry_len = entry_end - entry;
 
62
 
 
63
                        if (entry_len) {
 
64
                                /*
 
65
                                 * allocate memory to copy the entry into since
 
66
                                 * we will need to inject '\0' chars and squash
 
67
                                 * white-space before calling the callback
 
68
                                 */
 
69
                                entry_cpy = malloc(entry_len + 1);
 
70
                                if (entry_cpy) {
 
71
                                        /* copy just this entry and null term */
 
72
                                        strncpy(entry_cpy, entry, entry_len);
 
73
                                        entry_cpy[entry_len] = '\0';
 
74
                                } else
 
75
                                        return -ENOMEM;
 
76
                        }
 
77
                }
 
78
 
 
79
                /* check if there is anything to process (e.g. not ",,,") */
 
80
                if (entry_cpy != NULL) {
 
81
                        attributes = strchr(entry_cpy, ENV_ATTR_SEP);
 
82
                        /* check if there is a ':' */
 
83
                        if (attributes != NULL) {
 
84
                                /* replace the ':' with '\0' to term name */
 
85
                                *attributes++ = '\0';
 
86
                                /* remove white-space from attributes */
 
87
                                attributes = strim(attributes);
 
88
                        }
 
89
                        /* remove white-space from name */
 
90
                        name = strim(entry_cpy);
 
91
 
 
92
                        /* only call the callback if there is a name */
 
93
                        if (strlen(name) != 0) {
 
94
                                int retval = 0;
 
95
 
 
96
                                retval = callback(name, attributes);
 
97
                                if (retval) {
 
98
                                        free(entry_cpy);
 
99
                                        return retval;
 
100
                                }
 
101
                        }
 
102
                }
 
103
 
 
104
                free(entry_cpy);
 
105
                entry = entry_end + 1;
 
106
        } while (entry_end != NULL);
 
107
 
 
108
        return 0;
 
109
}
 
110
 
 
111
/*
 
112
 * Search for the last matching string in another string with the option to
 
113
 * start looking at a certain point (i.e. ignore anything beyond that point).
 
114
 */
 
115
static char *reverse_strstr(const char *searched, const char *search_for,
 
116
        const char *searched_start)
 
117
{
 
118
        char *result = NULL;
 
119
 
 
120
        if (*search_for == '\0')
 
121
                return (char *)searched;
 
122
 
 
123
        for (;;) {
 
124
                char *match = strstr(searched, search_for);
 
125
 
 
126
                /*
 
127
                 * Stop looking if no new match is found or looking past the
 
128
                 * searched_start pointer
 
129
                 */
 
130
                if (match == NULL || (searched_start != NULL &&
 
131
                    match + strlen(search_for) > searched_start))
 
132
                        break;
 
133
 
 
134
                result = match;
 
135
                searched = match + 1;
 
136
        }
 
137
 
 
138
        return result;
 
139
}
 
140
 
 
141
/*
 
142
 * Retrieve the attributes string associated with a single name in the list
 
143
 * There is no protection on attributes being too small for the value
 
144
 */
 
145
int env_attr_lookup(const char *attr_list, const char *name, char *attributes)
 
146
{
 
147
        const char *entry = NULL;
 
148
 
 
149
        if (!attributes)
 
150
                /* bad parameter */
 
151
                return -1;
 
152
        if (!attr_list)
 
153
                /* list not found */
 
154
                return 1;
 
155
 
 
156
        entry = reverse_strstr(attr_list, name, NULL);
 
157
        while (entry != NULL) {
 
158
                const char *prevch = entry - 1;
 
159
                const char *nextch = entry + strlen(name);
 
160
 
 
161
                /* Skip spaces */
 
162
                while (*prevch == ' ')
 
163
                        prevch--;
 
164
                while (*nextch == ' ')
 
165
                        nextch++;
 
166
 
 
167
                /* check for an exact match */
 
168
                if ((entry == attr_list ||
 
169
                     *prevch == ENV_ATTR_LIST_DELIM) &&
 
170
                    (*nextch == ENV_ATTR_SEP ||
 
171
                     *nextch == ENV_ATTR_LIST_DELIM ||
 
172
                     *nextch == '\0'))
 
173
                        break;
 
174
 
 
175
                entry = reverse_strstr(attr_list, name, entry);
 
176
        }
 
177
        if (entry != NULL) {
 
178
                int len;
 
179
 
 
180
                /* skip the name */
 
181
                entry += strlen(name);
 
182
                /* skip spaces */
 
183
                while (*entry == ' ')
 
184
                        entry++;
 
185
                if (*entry != ENV_ATTR_SEP)
 
186
                        len = 0;
 
187
                else {
 
188
                        const char *delim;
 
189
                        static const char delims[] = {
 
190
                                ENV_ATTR_LIST_DELIM, ' ', '\0'};
 
191
 
 
192
                        /* skip the attr sep */
 
193
                        entry += 1;
 
194
                        /* skip spaces */
 
195
                        while (*entry == ' ')
 
196
                                entry++;
 
197
 
 
198
                        delim = strpbrk(entry, delims);
 
199
                        if (delim == NULL)
 
200
                                len = strlen(entry);
 
201
                        else
 
202
                                len = delim - entry;
 
203
                        memcpy(attributes, entry, len);
 
204
                }
 
205
                attributes[len] = '\0';
 
206
 
 
207
                /* success */
 
208
                return 0;
 
209
        }
 
210
 
 
211
        /* not found in list */
 
212
        return 2;
 
213
}