Print this page
6659 nvlist_free(NULL) is a no-op
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/common/fsreparse/fs_reparse.c
+++ new/usr/src/common/fsreparse/fs_reparse.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/param.h>
28 28 #include <sys/errno.h>
29 29
30 30 #ifdef _KERNEL
31 31 #include <sys/sunddi.h>
32 32 #include <fs/fs_reparse.h>
33 33 #else
34 34 #include <string.h>
35 35 #include <limits.h>
36 36 #include <sys/fs_reparse.h>
37 37
38 38 #define strfree(str) free((str))
39 39 #endif
40 40
41 41 static char *reparse_skipspace(char *cp);
42 42 static int reparse_create_nvlist(const char *string, nvlist_t *nvl);
43 43 static int reparse_add_nvpair(char *token, nvlist_t *nvl);
44 44 static boolean_t reparse_validate_svctype(char *svc_str);
45 45 static int reparse_validate_create_nvlist(const char *string, nvlist_t *nvl);
46 46
47 47 /* array of characters not allowed in service type string */
48 48 static char svctype_invalid_chars[] = { '{', '}', 0 };
49 49
50 50 /*
51 51 * reparse_init()
52 52 *
53 53 * Function to allocate a new name-value pair list.
54 54 * Caller needs to call reparse_free() to free memory
55 55 * used by the list when done.
56 56 *
57 57 * Return pointer to new list else return NULL.
58 58 */
59 59 nvlist_t *
60 60 reparse_init(void)
61 61 {
62 62 nvlist_t *nvl;
63 63
64 64 /*
65 65 * Service type is unique, only one entry
66 66 * of each service type is allowed
67 67 */
68 68 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0))
69 69 return (NULL);
70 70
71 71 return (nvl);
72 72 }
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
73 73
74 74 /*
75 75 * reparse_free()
76 76 *
77 77 * Function to free memory of a nvlist allocated previously
78 78 * by reparse_init().
79 79 */
80 80 void
81 81 reparse_free(nvlist_t *nvl)
82 82 {
83 - if (nvl)
84 - nvlist_free(nvl);
83 + nvlist_free(nvl);
85 84 }
86 85
87 86 /*
88 87 * reparse_parse()
89 88 *
90 89 * Parse the specified string and populate the nvlist with the svc_types
91 90 * and data from the 'string'. The string could be read from the reparse
92 91 * point symlink body. This routine will allocate memory that must be
93 92 * freed by reparse_free().
94 93 *
95 94 * If ok return 0 and the nvlist is populated, otherwise return error code.
96 95 */
97 96 int
98 97 reparse_parse(const char *string, nvlist_t *nvl)
99 98 {
100 99 int err;
101 100
102 101 if (string == NULL || nvl == NULL)
103 102 return (EINVAL);
104 103
105 104 if ((err = reparse_validate(string)) != 0)
106 105 return (err);
107 106
108 107 if ((err = reparse_create_nvlist(string, nvl)) != 0)
109 108 return (err);
110 109
111 110 return (0);
112 111 }
113 112
114 113 static char *
115 114 reparse_skipspace(char *cp)
116 115 {
117 116 while ((*cp) && (*cp == ' ' || *cp == '\t'))
118 117 cp++;
119 118 return (cp);
120 119 }
121 120
122 121 static boolean_t
123 122 reparse_validate_svctype(char *svc_str)
124 123 {
125 124 int nx, ix, len;
126 125
127 126 if (svc_str == NULL)
128 127 return (B_FALSE);
129 128
130 129 len = strlen(svc_str);
131 130 for (ix = 0; ix < len; ix++) {
132 131 for (nx = 0; nx < sizeof (svctype_invalid_chars); nx++) {
133 132 if (svc_str[ix] == svctype_invalid_chars[nx])
134 133 return (B_FALSE);
135 134 }
136 135 }
137 136 return (B_TRUE);
138 137 }
139 138
140 139 static boolean_t
141 140 reparse_validate_svc_token(char *svc_token)
142 141 {
143 142 char save_c, *cp;
144 143
145 144 if (svc_token == NULL)
146 145 return (B_FALSE);
147 146 if ((cp = strchr(svc_token, ':')) == NULL)
148 147 return (B_FALSE);
149 148
150 149 save_c = *cp;
151 150 *cp = '\0';
152 151
153 152 /*
154 153 * make sure service type and service data are non-empty string.
155 154 */
156 155 if (strlen(svc_token) == 0 || strlen(cp + 1) == 0) {
157 156 *cp = save_c;
158 157 return (B_FALSE);
159 158 }
160 159
161 160 *cp = save_c;
162 161 return (B_TRUE);
163 162 }
164 163
165 164 /*
166 165 * Format of reparse data:
167 166 * @{REPARSE@{servicetype:data} [@{servicetype:data}] ...}
168 167 * REPARSE_TAG_STR@{REPARSE_TOKEN} [@{REPARSE_TOKEN}] ... REPARSE_TAG_END
169 168 *
170 169 * Validating reparse data:
171 170 * . check for valid length of reparse data
172 171 * . check for valid reparse data format
173 172 * Return 0 if OK else return error code.
174 173 */
175 174 int
176 175 reparse_validate(const char *string)
177 176 {
178 177 return (reparse_validate_create_nvlist(string, NULL));
179 178 }
180 179
181 180 /*
182 181 * reparse_validate_create_nvlist
183 182 *
184 183 * dual-purpose function:
185 184 * . Validate a reparse data string.
186 185 * . Validate a reparse data string and parse the data
187 186 * into a nvlist.
188 187 */
189 188 static int
190 189 reparse_validate_create_nvlist(const char *string, nvlist_t *nvl)
191 190 {
192 191 int err, tcnt;
193 192 char *reparse_data, save_c, save_e, *save_e_ptr, *cp, *s_str, *e_str;
194 193
195 194 if (string == NULL)
196 195 return (EINVAL);
197 196
198 197 if (strlen(string) >= MAXREPARSELEN)
199 198 return (ENAMETOOLONG);
200 199
201 200 if ((reparse_data = strdup(string)) == NULL)
202 201 return (ENOMEM);
203 202
204 203 /* check FS_REPARSE_TAG_STR */
205 204 if (strncmp(reparse_data, FS_REPARSE_TAG_STR,
206 205 strlen(FS_REPARSE_TAG_STR))) {
207 206 strfree(reparse_data);
208 207 return (EINVAL);
209 208 }
210 209
211 210 /* locate FS_REPARSE_TAG_END_CHAR */
212 211 if ((cp = strrchr(reparse_data, FS_REPARSE_TAG_END_CHAR)) == NULL) {
213 212 strfree(reparse_data);
214 213 return (EINVAL);
215 214 }
216 215 save_e = *cp;
217 216 save_e_ptr = cp;
218 217 *cp = '\0';
219 218
220 219 e_str = cp;
221 220 cp++; /* should point to NULL, or spaces */
222 221
223 222 cp = reparse_skipspace(cp);
224 223 if (*cp) {
225 224 *save_e_ptr = save_e;
226 225 strfree(reparse_data);
227 226 return (EINVAL);
228 227 }
229 228
230 229 /* skip FS_REPARSE_TAG_STR */
231 230 s_str = reparse_data + strlen(FS_REPARSE_TAG_STR);
232 231
233 232 /* skip spaces after FS_REPARSE_TAG_STR */
234 233 s_str = reparse_skipspace(s_str);
235 234
236 235 tcnt = 0;
237 236 while (s_str < e_str) {
238 237 /* check FS_TOKEN_START_STR */
239 238 if (strncmp(s_str, FS_TOKEN_START_STR,
240 239 strlen(FS_TOKEN_START_STR))) {
241 240 *save_e_ptr = save_e;
242 241 strfree(reparse_data);
243 242 return (EINVAL);
244 243 }
245 244
246 245 /* skip over FS_TOKEN_START_STR */
247 246 s_str += strlen(FS_TOKEN_START_STR);
248 247
249 248 /* locate FS_TOKEN_END_STR */
250 249 if ((cp = strstr(s_str, FS_TOKEN_END_STR)) == NULL) {
251 250 *save_e_ptr = save_e;
252 251 strfree(reparse_data);
253 252 return (EINVAL);
254 253 }
255 254
256 255 tcnt++;
257 256 save_c = *cp;
258 257 *cp = '\0';
259 258
260 259 /* check for valid characters in service type */
261 260 if (reparse_validate_svctype(s_str) == B_FALSE) {
262 261 *cp = save_c;
263 262 *save_e_ptr = save_e;
264 263 strfree(reparse_data);
265 264 return (EINVAL);
266 265 }
267 266
268 267 if (strlen(s_str) == 0) {
269 268 *cp = save_c;
270 269 *save_e_ptr = save_e;
271 270 strfree(reparse_data);
272 271 return (EINVAL);
273 272 }
274 273
275 274 if (reparse_validate_svc_token(s_str) == B_FALSE) {
276 275 *cp = save_c;
277 276 *save_e_ptr = save_e;
278 277 strfree(reparse_data);
279 278 return (EINVAL);
280 279 }
281 280
282 281 /* create a nvpair entry */
283 282 if (nvl != NULL &&
284 283 (err = reparse_add_nvpair(s_str, nvl)) != 0) {
285 284 *cp = save_c;
286 285 *save_e_ptr = save_e;
287 286 strfree(reparse_data);
288 287 return (err);
289 288 }
290 289
291 290 *cp = save_c;
292 291
293 292 /* skip over FS_TOKEN_END_STR */
294 293 cp += strlen(FS_TOKEN_END_STR);
295 294 cp = reparse_skipspace(cp);
296 295 s_str = cp;
297 296 }
298 297 *save_e_ptr = save_e;
299 298 strfree(reparse_data);
300 299
301 300 return (tcnt ? 0 : EINVAL);
302 301 }
303 302
304 303 static int
305 304 reparse_add_nvpair(char *token, nvlist_t *nvl)
306 305 {
307 306 int err;
308 307 char save_c, *cp;
309 308
310 309 if ((cp = strchr(token, ':')) == NULL)
311 310 return (EINVAL);
312 311
313 312 save_c = *cp;
314 313 *cp = '\0';
315 314 err = nvlist_add_string(nvl, token, cp + 1);
316 315 *cp = save_c;
317 316
318 317 return (err);
319 318 }
320 319
321 320 static int
322 321 reparse_create_nvlist(const char *string, nvlist_t *nvl)
323 322 {
324 323 if (nvl == NULL)
325 324 return (EINVAL);
326 325
327 326 return (reparse_validate_create_nvlist(string, nvl));
328 327 }
↓ open down ↓ |
234 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX