]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - db/flist.c
xfs: zero length symlinks are not valid
[thirdparty/xfsprogs-dev.git] / db / flist.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
da23017d
NS
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
2bd0ea18
NS
5 */
6
6b803e5a 7#include "libxfs.h"
2bd0ea18
NS
8#include "type.h"
9#include "faddr.h"
10#include "fprint.h"
11#include "field.h"
12#include "flist.h"
13#include "debug.h"
14#include "output.h"
15#include "malloc.h"
16
17static void flist_expand_arrays(flist_t *fl);
18static void flist_expand_structs(flist_t *fl, void *obj);
19static flist_t *flist_replicate(flist_t *fl);
20static ftok_t *flist_split(char *s);
21static void ftok_free(ftok_t *ft);
22
23static void
24flist_expand_arrays(
25 flist_t *fl)
26{
27 const field_t *f;
28#ifdef DEBUG
29 const ftattr_t *fa;
30#endif
31 int high;
32 int idx;
33 int low;
34 flist_t *new;
35 flist_t *prev;
36 flist_t *sib;
37
38 f = fl->fld;
39#ifdef DEBUG
40 fa = &ftattrtab[f->ftyp];
41#endif
42 ASSERT(fa->ftyp == f->ftyp);
43 ASSERT(f->flags & FLD_ARRAY);
44 low = fl->low;
45 high = fl->high;
46 fl->high = fl->low;
47 sib = fl->sibling;
48 for (idx = low + 1, prev = fl; idx <= high; idx++) {
49 new = flist_make(f->name);
50 new->fld = f;
51 new->low = new->high = idx;
52 new->flags |= FL_OKLOW | FL_OKHIGH;
53 new->child = flist_replicate(fl->child);
54 prev->sibling = new;
55 prev = new;
56 }
57 prev->sibling = sib;
58}
59
60static void
61flist_expand_structs(
62 flist_t *fl,
63 void *obj)
64{
65 const field_t *cf;
66 const field_t *f;
67 const ftattr_t *fa;
68 flist_t *new;
69 flist_t *prev;
70
71 f = fl->fld;
72 fa = &ftattrtab[f->ftyp];
73 ASSERT(fa->ftyp == f->ftyp);
74 ASSERT(fa->subfld != NULL);
75 ASSERT(fl->child == NULL);
76 for (cf = fa->subfld, prev = NULL; cf->name != NULL; cf++) {
77 if (fcount(cf, obj, fl->offset) == 0)
78 continue;
79 if (cf->flags & FLD_SKIPALL)
80 continue;
81 new = flist_make(cf->name);
82 new->fld = cf;
83 if (prev)
84 prev->sibling = new;
85 else
86 fl->child = new;
87 prev = new;
88 }
89}
90
91void
92flist_free(
93 flist_t *fl)
94{
95 if (fl->child)
96 flist_free(fl->child);
97 if (fl->sibling)
98 flist_free(fl->sibling);
99 if (fl->name)
100 xfree(fl->name);
101 xfree(fl);
102}
103
104flist_t *
105flist_make(
106 char *name)
107{
108 flist_t *fl;
109
110 fl = xmalloc(sizeof(*fl));
111 fl->name = xstrdup(name);
112 fl->fld = NULL;
113 fl->child = NULL;
114 fl->sibling = NULL;
115 fl->low = 0;
116 fl->high = 0;
117 fl->flags = 0;
118 fl->offset = 0;
119 return fl;
120}
121
122int
123flist_parse(
124 const field_t *fields,
125 flist_t *fl,
126 void *obj,
127 int startoff)
128{
129 const field_t *f;
130 const ftattr_t *fa;
131 int high;
132 int low;
133
134 while (fl) {
135 f = findfield(fl->name, fields, obj, startoff);
136 if (f == NULL) {
9ee7055c 137 dbprintf(_("field %s not found\n"), fl->name);
2bd0ea18
NS
138 return 0;
139 }
140 fl->fld = f;
141 fa = &ftattrtab[f->ftyp];
142 ASSERT(fa->ftyp == f->ftyp);
143 if (f->flags & FLD_ARRAY) {
144 low = (f->flags & FLD_ABASE1) != 0;
145 high = fcount(f, obj, startoff) + low - 1;
146 if (low > high) {
9ee7055c 147 dbprintf(_("no elements in %s\n"), fl->name);
2bd0ea18
NS
148 return 0;
149 }
150 if (fl->flags & FL_OKHIGH) {
151 if (fl->low < low || fl->low > high ||
152 fl->high < low || fl->high > high) {
9ee7055c
AM
153 dbprintf(_("indices %d-%d for field %s "
154 "out of range %d-%d\n"),
2bd0ea18
NS
155 fl->low, fl->high, fl->name,
156 low, high);
157 return 0;
158 }
159 } else if (fl->flags & FL_OKLOW) {
160 if (fl->low < low || fl->low > high) {
9ee7055c
AM
161 dbprintf(_("index %d for field %s out of "
162 "range %d-%d\n"),
2bd0ea18
NS
163 fl->low, fl->name, low, high);
164 return 0;
165 }
166 fl->high = fl->low;
167 fl->flags |= FL_OKHIGH;
168 } else {
169 fl->low = low;
170 fl->high = high;
171 fl->flags |= FL_OKLOW | FL_OKHIGH;
172 }
173 } else {
174 if (fl->flags & FL_OKLOW) {
9ee7055c 175 dbprintf(_("field %s is not an array\n"),
2bd0ea18
NS
176 fl->name);
177 return 0;
178 }
179 }
180 fl->offset = startoff + bitoffset(f, obj, startoff, fl->low);
181 if ((fl->child != NULL || fa->prfunc == NULL) &&
182 (f->flags & FLD_ARRAY) && fl->low != fl->high)
183 flist_expand_arrays(fl);
184 if (fa->prfunc == NULL && fl->child == NULL)
185 flist_expand_structs(fl, obj);
186 if (fl->child) {
187 if (fa->subfld == NULL) {
9ee7055c 188 dbprintf(_("field %s has no subfields\n"),
2bd0ea18
NS
189 fl->name);
190 return 0;
191 }
192 if (!flist_parse(fa->subfld, fl->child, obj,
193 fl->offset))
194 return 0;
195 }
196 fl = fl->sibling;
197 }
198 return 1;
199}
200
201void
202flist_print(
203 flist_t *fl)
204{
205 if (!(debug_state & DEBUG_FLIST))
206 return;
207 while (fl) {
9ee7055c
AM
208 dbprintf(_("fl@%p:\n"), fl);
209 dbprintf(_("\tname=%s, fld=%p, child=%p, sibling=%p\n"),
2bd0ea18 210 fl->name, fl->fld, fl->child, fl->sibling);
9ee7055c 211 dbprintf(_("\tlow=%d, high=%d, flags=%d (%s%s), offset=%d\n"),
2bd0ea18 212 fl->low, fl->high, fl->flags,
9ee7055c
AM
213 fl->flags & FL_OKLOW ? _("oklow ") : "",
214 fl->flags & FL_OKHIGH ? _("okhigh") : "", fl->offset);
215 dbprintf(_("\tfld->name=%s, fld->ftyp=%d (%s)\n"),
2bd0ea18
NS
216 fl->fld->name, fl->fld->ftyp,
217 ftattrtab[fl->fld->ftyp].name);
9ee7055c 218 dbprintf(_("\tfld->flags=%d (%s%s%s%s%s)\n"), fl->fld->flags,
2bd0ea18
NS
219 fl->fld->flags & FLD_ABASE1 ? "abase1 " : "",
220 fl->fld->flags & FLD_SKIPALL ? "skipall " : "",
221 fl->fld->flags & FLD_ARRAY ? "array " : "",
222 fl->fld->flags & FLD_OFFSET ? "offset " : "",
223 fl->fld->flags & FLD_COUNT ? "count " : "");
224 if (fl->child)
225 flist_print(fl->child);
226 fl = fl->sibling;
227 }
228}
229
230static flist_t *
231flist_replicate(
232 flist_t *f)
233{
234 flist_t *new;
235
236 if (f == NULL)
237 return NULL;
238 new = flist_make(f->name);
239 new->fld = f->fld;
240 new->child = flist_replicate(f->child);
241 new->sibling = flist_replicate(f->sibling);
242 new->low = f->low;
243 new->high = f->high;
244 new->flags = f->flags;
245 new->offset = f->offset;
246 return new;
247}
248
249flist_t *
250flist_scan(
251 char *name)
252{
253 flist_t *fl;
254 flist_t *lfl;
255 flist_t *nfl;
256 int num;
257 ftok_t *p;
258 ftok_t *v;
259 char *x;
260
261 v = flist_split(name);
262 if (!v)
263 return NULL;
264 p = v;
265 fl = lfl = NULL;
266 while (p->tokty != TT_END) {
267 if (p->tokty != TT_NAME)
268 goto bad;
269 nfl = flist_make(p->tok);
270 if (lfl)
271 lfl->child = nfl;
272 else
273 fl = nfl;
274 lfl = nfl;
275 p++;
276 if (p->tokty == TT_LB) {
277 p++;
278 if (p->tokty != TT_NUM)
279 goto bad;
280 num = (int)strtoul(p->tok, &x, 0);
281 if (*x != '\0')
282 goto bad;
283 nfl->flags |= FL_OKLOW;
284 nfl->low = num;
285 p++;
286 if (p->tokty == TT_DASH) {
287 p++;
288 if (p->tokty != TT_NUM)
289 goto bad;
290 num = (int)strtoul(p->tok, &x, 0);
291 if (*x != '\0')
292 goto bad;
293 nfl->flags |= FL_OKHIGH;
294 nfl->high = num;
295 p++;
296 }
297 if (p->tokty != TT_RB)
298 goto bad;
299 p++;
300 }
301 if (p->tokty == TT_DOT) {
302 p++;
303 if (p->tokty == TT_END)
304 goto bad;
305 }
306 }
307 ftok_free(v);
308 return fl;
309bad:
9ee7055c 310 dbprintf(_("bad syntax in field name %s\n"), name);
2bd0ea18
NS
311 ftok_free(v);
312 if (fl)
313 flist_free(fl);
314 return NULL;
315}
316
317static ftok_t *
318flist_split(
319 char *s)
320{
321 char *a;
322 int i;
323 static char *idchars;
324 static char *initidchar;
325 int l;
326 int tailskip = 0;
327 static char *numchars;
328 static char *xnumchars; /* extended for hex conversion */
329 int nv;
330 static char punctchars[] = "[-].";
331 static tokty_t puncttypes[] = { TT_LB, TT_DASH, TT_RB, TT_DOT };
332 tokty_t t;
333 ftok_t *v;
334
335 if (idchars == NULL) {
336 idchars = xmalloc(26 + 10 + 1 + 1);
337 initidchar = xmalloc(26 + 1);
338 numchars = xmalloc(10 + 1);
339 xnumchars = xmalloc(12 + 1);
340 for (i = 'a'; i <= 'z'; i++) {
341 idchars[i - 'a'] = i;
342 initidchar[i - 'a'] = i;
343 }
344
345 for (i = '0'; i <= '9'; i++) {
346 idchars[26 + (i - '0')] = i;
347 numchars[i - '0'] = i;
348 xnumchars[i - '0'] = i;
349 }
350 idchars[26 + 10] = '_';
351 idchars[26 + 10 + 1] = '\0';
352 initidchar[26] = '\0';
353 numchars[10] = '\0';
354 xnumchars[10] = 'x';
355 xnumchars[11] = 'X';
356 xnumchars[12] = '\0';
357 }
358 nv = 0;
359 v = xmalloc(sizeof(*v));
360 v->tok = NULL;
361 while (*s) {
362 /* need to add string handling */
363 if (*s == '\"') {
364 s++; /* skip first quote */
365 if ((a = strrchr(s, '\"')) == NULL) {
9ee7055c 366 dbprintf(_("missing closing quote %s\n"), s);
2bd0ea18
NS
367 ftok_free(v);
368 return NULL;
369 }
370 tailskip = 1; /* skip remaing quote */
371 l = (int)(a - s);
372 t = TT_STRING;
373 } else if (strchr(initidchar, *s)) {
374 l = (int)strspn(s, idchars);
375 t = TT_NAME;
376 } else if (strchr(numchars, *s)) {
377 l = (int)strspn(s, xnumchars);
378 t = TT_NUM;
27527004 379 } else if ((a = strchr(punctchars, *s))) {
2bd0ea18
NS
380 l = 1;
381 t = puncttypes[a - punctchars];
382 } else {
9ee7055c 383 dbprintf(_("bad character in field %s\n"), s);
2bd0ea18
NS
384 ftok_free(v);
385 return NULL;
386 }
387 a = xmalloc(l + 1);
388 strncpy(a, s, l);
389 a[l] = '\0';
390 v = xrealloc(v, (nv + 2) * sizeof(*v));
945e47e2 391 v[nv + 1].tok = NULL;
2bd0ea18
NS
392 v[nv].tok = a;
393 v[nv].tokty = t;
394 nv++;
395 s += l + tailskip;
396 tailskip = 0;
397 }
398 v[nv].tok = NULL;
399 v[nv].tokty = TT_END;
400 return v;
401}
402
b64af2c4
ES
403/*
404 * Given a set of fields, scan for a field of the given type.
405 * Return an flist leading to the first found field
406 * of that type.
407 * Return NULL if no field of the given type is found.
408 */
409flist_t *
410flist_find_ftyp(
411 const field_t *fields,
412 fldt_t type)
413{
414 flist_t *fl;
415 const field_t *f;
416 const ftattr_t *fa;
417
418 for (f = fields; f->name; f++) {
419 fl = flist_make(f->name);
420 fl->fld = f;
421 if (f->ftyp == type)
422 return fl;
423 fa = &ftattrtab[f->ftyp];
424 if (fa->subfld) {
425 flist_t *nfl;
426
427 nfl = flist_find_ftyp(fa->subfld, type);
428 if (nfl) {
429 fl->child = nfl;
430 return fl;
431 }
432 }
433 flist_free(fl);
434 }
435 return NULL;
436}
437
2bd0ea18
NS
438static void
439ftok_free(
440 ftok_t *ft)
441{
442 ftok_t *p;
443
444 for (p = ft; p->tok; p++)
445 xfree(p->tok);
446 xfree(ft);
447}