OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.24/] [disk/] [tools/] [fs-NetBSD/] [makefs/] [spec.c] - Blame information for rev 211

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 174 hellwig
/*
2
 * spec.c -- specfile parser
3
 */
4
 
5
 
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
#include <stdarg.h>
10
#include <ctype.h>
11
#include <errno.h>
12
#include <assert.h>
13 194 hellwig
#include <sys/time.h>
14 174 hellwig
 
15
#include "mtree.h"
16
#include "pack_dev.h"
17
 
18
 
19
#define BUFSIZE         2000
20
#define REPLACEPTR(x,v) do { if ((x)) free((x)); (x) = (v); } while (0)
21
#define REPLACE(x)      cur->x = new->x
22
#define REPLACESTR(x)   REPLACEPTR(cur->x,new->x)
23
 
24
 
25
static int mtree_lineno = 0;             /* Current spec line number */
26
static int mtree_Mflag = 0;              /* Merge duplicate entries */
27
static int mtree_Wflag = 0;              /* Don't "whack" permissions */
28
static int mtree_Sflag = 0;              /* Sort entries */
29
 
30
 
31
static void addchild(NODE *pathparent, NODE *centry);
32
static void replacenode(NODE *cur, NODE *new);
33
static void set(char *t, NODE *ip);
34
static void unset(char *t, NODE *ip);
35
 
36
 
37
/**************************************************************/
38
 
39
 
40
static void mtree_err(const char *fmt, ...) {
41
  va_list ap;
42
 
43
  va_start(ap, fmt);
44
  vprintf(fmt, ap);
45
  va_end(ap);
46
  if (mtree_lineno) {
47
    printf("\nfailed at line %lu of the specification",
48
           (u_long) mtree_lineno);
49
  }
50
  printf("\n");
51
  exit(1);
52
}
53
 
54
 
55
static const char *nodetype(u_int type) {
56
  return inotype(nodetoino(type));
57
}
58
 
59
 
60
static int strunvis(char *dst, const char *src) {
61
  int i;
62
 
63
  i = 0;
64
  while ((*dst++ = *src++) != '\0') {
65
    i++;
66
  }
67
  return i;
68
}
69
 
70
 
71
/**************************************************************/
72
 
73
 
74
#define TEST(a, b, f) {                                                 \
75
        if (!strcmp(a, b)) {                                            \
76
                if (clear) {                                            \
77
                        if (clrp)                                       \
78
                                *clrp |= (f);                           \
79
                        if (setp)                                       \
80
                                *setp &= ~(f);                          \
81
                } else {                                                \
82
                        if (setp)                                       \
83
                                *setp |= (f);                           \
84
                        if (clrp)                                       \
85
                                *clrp &= ~(f);                          \
86
                }                                                       \
87
                break;                                                  \
88
        }                                                               \
89
}
90
 
91
 
92
/*
93
 * string_to_flags --
94
 *      Take string of arguments and return stat flags.  Return 0 on
95
 *      success, 1 on failure.  On failure, stringp is set to point
96
 *      to the offending token.
97
 */
98
int
99
string_to_flags(char **stringp, u_long *setp, u_long *clrp)
100
{
101
#if HAVE_STRUCT_STAT_ST_FLAGS
102
        int clear;
103
        char *string;
104
        char *p;
105
#endif
106
 
107
        if (setp)
108
                *setp = 0;
109
        if (clrp)
110
                *clrp = 0;
111
 
112
#if HAVE_STRUCT_STAT_ST_FLAGS
113
        string = *stringp;
114
        while ((p = strsep(&string, "\t ,")) != NULL) {
115
                clear = 0;
116
                *stringp = p;
117
                if (*p == '\0')
118
                        continue;
119
                if (p[0] == 'n' && p[1] == 'o') {
120
                        clear = 1;
121
                        p += 2;
122
                }
123
                switch (p[0]) {
124
                case 'a':
125
                        TEST(p, "arch", SF_ARCHIVED);
126
                        TEST(p, "archived", SF_ARCHIVED);
127
                        return (1);
128
                case 'd':
129
                        clear = !clear;
130
                        TEST(p, "dump", UF_NODUMP);
131
                        return (1);
132
                case 'n':
133
                                /*
134
                                 * Support `nonodump'. Note that
135
                                 * the state of clear is not changed.
136
                                 */
137
                        TEST(p, "nodump", UF_NODUMP);
138
                        return (1);
139
                case 'o':
140
                        TEST(p, "opaque", UF_OPAQUE);
141
                        return (1);
142
                case 's':
143
                        TEST(p, "sappnd", SF_APPEND);
144
                        TEST(p, "sappend", SF_APPEND);
145
                        TEST(p, "schg", SF_IMMUTABLE);
146
                        TEST(p, "schange", SF_IMMUTABLE);
147
                        TEST(p, "simmutable", SF_IMMUTABLE);
148
                        return (1);
149
                case 'u':
150
                        TEST(p, "uappnd", UF_APPEND);
151
                        TEST(p, "uappend", UF_APPEND);
152
                        TEST(p, "uchg", UF_IMMUTABLE);
153
                        TEST(p, "uchange", UF_IMMUTABLE);
154
                        TEST(p, "uimmutable", UF_IMMUTABLE);
155
                        return (1);
156
                default:
157
                        return (1);
158
                }
159
        }
160
#endif
161
 
162
        return (0);
163
}
164
 
165
 
166
/**************************************************************/
167
 
168
 
169
int uid_from_user(const char *name, uid_t *uid) {
170
  *uid = 0;
171
  return 0;
172
}
173
 
174
 
175
int gid_from_group(const char *name, gid_t *gid) {
176
  *gid = 0;
177
  return 0;
178
}
179
 
180
 
181
/**************************************************************/
182
 
183
 
184
#define NEEDVALUE       0x01
185
 
186
 
187
typedef struct _key {
188
        const char      *name;          /* key name */
189
        u_int           val;            /* value */
190
        u_int           flags;
191
} KEY;
192
 
193
 
194
static KEY keylist[] = {
195
        {"cksum",       F_CKSUM,        NEEDVALUE},
196
        {"device",      F_DEV,          NEEDVALUE},
197
        {"flags",       F_FLAGS,        NEEDVALUE},
198
        {"gid",         F_GID,          NEEDVALUE},
199
        {"gname",       F_GNAME,        NEEDVALUE},
200
        {"ignore",      F_IGN,          0},
201
        {"link",        F_SLINK,        NEEDVALUE},
202
        {"md5",         F_MD5,          NEEDVALUE},
203
        {"md5digest",   F_MD5,          NEEDVALUE},
204
        {"mode",        F_MODE,         NEEDVALUE},
205
        {"nlink",       F_NLINK,        NEEDVALUE},
206
        {"optional",    F_OPT,          0},
207
        {"rmd160",      F_RMD160,       NEEDVALUE},
208
        {"rmd160digest",F_RMD160,       NEEDVALUE},
209
        {"sha1",        F_SHA1,         NEEDVALUE},
210
        {"sha1digest",  F_SHA1,         NEEDVALUE},
211
        {"sha256",      F_SHA256,       NEEDVALUE},
212
        {"sha256digest",F_SHA256,       NEEDVALUE},
213
        {"sha384",      F_SHA384,       NEEDVALUE},
214
        {"sha384digest",F_SHA384,       NEEDVALUE},
215
        {"sha512",      F_SHA512,       NEEDVALUE},
216
        {"sha512digest",F_SHA512,       NEEDVALUE},
217
        {"size",        F_SIZE,         NEEDVALUE},
218
        {"tags",        F_TAGS,         NEEDVALUE},
219
        {"time",        F_TIME,         NEEDVALUE},
220
        {"type",        F_TYPE,         NEEDVALUE},
221
        {"uid",         F_UID,          NEEDVALUE},
222
        {"uname",       F_UNAME,        NEEDVALUE}
223
};
224
 
225
 
226
static KEY typelist[] = {
227
        {"block",       F_BLOCK,        0},
228
        {"char",        F_CHAR,         0},
229
        {"dir",         F_DIR,          0},
230
#ifdef S_IFDOOR
231
        {"door",        F_DOOR,         0},
232
#endif
233
        {"fifo",        F_FIFO,         0},
234
        {"file",        F_FILE,         0},
235
        {"link",        F_LINK,         0},
236
        {"socket",      F_SOCK,         0},
237
};
238
 
239
 
240
int keycompare(const void *a, const void *b) {
241
  return strcmp(((const KEY *)a)->name, ((const KEY *)b)->name);
242
}
243
 
244
 
245
u_int parsekey(const char *name, int *needvaluep) {
246
        static int allbits;
247
        KEY *k, tmp;
248
 
249
        if (allbits == 0) {
250
                size_t i;
251
 
252
                for (i = 0; i < sizeof(keylist) / sizeof(KEY); i++)
253
                        allbits |= keylist[i].val;
254
        }
255
        tmp.name = name;
256
        if (strcmp(name, "all") == 0)
257
                return (allbits);
258
        k = (KEY *)bsearch(&tmp, keylist, sizeof(keylist) / sizeof(KEY),
259
            sizeof(KEY), keycompare);
260
        if (k == NULL)
261
                mtree_err("unknown keyword `%s'", name);
262
 
263
        if (needvaluep)
264
                *needvaluep = k->flags & NEEDVALUE ? 1 : 0;
265
 
266
        return k->val;
267
}
268
 
269
 
270
u_int parsetype(const char *name) {
271
  KEY *k, tmp;
272
 
273
  tmp.name = name;
274
  k = (KEY *) bsearch(&tmp, typelist, sizeof(typelist) / sizeof(KEY),
275
                      sizeof(KEY), keycompare);
276
  if (k == NULL) {
277
    mtree_err("unknown file type `%s'", name);
278
  }
279
  return k->val;
280
}
281
 
282
 
283
/**************************************************************/
284
 
285
 
286
#define MAX_PACK_ARGS   3
287
 
288
 
289
static dev_t parsedev(char *arg) {
290
        u_long  numbers[MAX_PACK_ARGS];
291
        char    *p, *ep, *dev;
292
        int     argc;
293
        pack_t  *pack;
294
        dev_t   result;
295
        const char *error = NULL;
296
 
297
        if ((dev = strchr(arg, ',')) != NULL) {
298
                *dev++='\0';
299
                if ((pack = pack_find(arg)) == NULL)
300
                        mtree_err("unknown format `%s'", arg);
301
                argc = 0;
302
                while ((p = strsep(&dev, ",")) != NULL) {
303
                        if (*p == '\0')
304
                                mtree_err("missing number");
305
                        numbers[argc++] = strtoul(p, &ep, 0);
306
                        if (*ep != '\0')
307
                                mtree_err("invalid number `%s'",
308
                                    p);
309
                        if (argc > MAX_PACK_ARGS)
310
                                mtree_err("too many arguments");
311
                }
312
                if (argc < 2)
313
                        mtree_err("not enough arguments");
314
                result = (*pack)(argc, numbers, &error);
315
                if (error != NULL)
316
                        mtree_err("%s", error);
317
        } else {
318
                result = (dev_t)strtoul(arg, &ep, 0);
319
                if (*ep != '\0')
320
                        mtree_err("invalid device `%s'", arg);
321
        }
322
        return result;
323
}
324
 
325
 
326
/**************************************************************/
327
 
328
 
329
/*
330
 * nodecmp --
331
 *      used as a comparison function by addchild() to control the order
332
 *      in which entries appear within a list of sibling nodes.  We make
333
 *      directories sort after non-directories, but otherwise sort in
334
 *      strcmp() order.
335
 *
336
 * Keep this in sync with dcmp() in create.c.
337
 */
338
static int nodecmp(const NODE *a, const NODE *b) {
339
        if ((a->type & F_DIR) != 0) {
340
                if ((b->type & F_DIR) == 0)
341
                        return 1;
342
        } else if ((b->type & F_DIR) != 0)
343
                return -1;
344
        return strcmp(a->name, b->name);
345
}
346
 
347
 
348
/**************************************************************/
349
 
350
 
351
NODE *spec(FILE *fp) {
352
        NODE *centry, *last, *pathparent, *cur;
353
        char *p, *e, *next;
354
        NODE ginfo, *root;
355
        char *tname, *ntname;
356
        size_t tnamelen, plen;
357
        char buf[BUFSIZE];
358
        int ll;
359
 
360
        root = NULL;
361
        centry = last = NULL;
362
        tname = NULL;
363
        tnamelen = 0;
364
        memset(&ginfo, 0, sizeof(ginfo));
365
        mtree_lineno = 0;
366
        while (fgets(buf, BUFSIZE, fp) != NULL) {
367
                mtree_lineno++;
368
                /* Delete trailing newline. */
369
                ll = strlen(buf);
370
                if (ll > 0 && buf[ll - 1] == '\n') {
371
                  buf[ll - 1] = '\0';
372
                }
373
                /* Skip leading whitespace. */
374
                for (p = buf; *p && isspace((unsigned char)*p); ++p)
375
                        continue;
376
 
377
                /* If nothing but whitespace (or comment), continue. */
378
                if (*p == '\0' || *p == '#')
379
                        continue;
380
 
381
#ifdef DEBUG
382
                fprintf(stderr, "line %lu: {%s}\n",
383
                    (u_long)mtree_lineno, p);
384
#endif
385
                /* Grab file name, "$", "set", or "unset". */
386
                next = buf;
387
                while ((p = strsep(&next, " \t")) != NULL && *p == '\0')
388
                        continue;
389
                if (p == NULL)
390
                        mtree_err("missing field");
391
 
392
                if (p[0] == '/') {
393
                        if (strcmp(p + 1, "set") == 0)
394
                                set(next, &ginfo);
395
                        else if (strcmp(p + 1, "unset") == 0)
396
                                unset(next, &ginfo);
397
                        else
398
                                mtree_err("invalid specification `%s'", p);
399
                        continue;
400
                }
401
 
402
                if (strcmp(p, "..") == 0) {
403
                        /* Don't go up, if haven't gone down. */
404
                        if (root == NULL)
405
                                goto noparent;
406
                        if (last->type != F_DIR || last->flags & F_DONE) {
407
                                if (last == root)
408
                                        goto noparent;
409
                                last = last->parent;
410
                        }
411
                        last->flags |= F_DONE;
412
                        continue;
413
 
414
noparent:               mtree_err("no parent node");
415
                }
416
 
417
                plen = strlen(p) + 1;
418
                if (plen > tnamelen) {
419
                        if ((ntname = realloc(tname, plen)) == NULL)
420
                                mtree_err("realloc: %s", strerror(errno));
421
                        tname = ntname;
422
                        tnamelen = plen;
423
                }
424
                if (strunvis(tname, p) == -1)
425
                        mtree_err("strunvis failed on `%s'", p);
426
                p = tname;
427
 
428
                pathparent = NULL;
429
                if (strchr(p, '/') != NULL) {
430
                        cur = root;
431
                        for (; (e = strchr(p, '/')) != NULL; p = e+1) {
432
                                if (p == e)
433
                                        continue;       /* handle // */
434
                                *e = '\0';
435
                                if (strcmp(p, ".") != 0) {
436
                                        while (cur &&
437
                                            strcmp(cur->name, p) != 0) {
438
                                                cur = cur->next;
439
                                        }
440
                                }
441
                                if (cur == NULL || cur->type != F_DIR) {
442
                                        mtree_err("%s: %s", tname,
443
                                        "missing directory in specification");
444
                                }
445
                                *e = '/';
446
                                pathparent = cur;
447
                                cur = cur->child;
448
                        }
449
                        if (*p == '\0')
450
                                mtree_err("%s: empty leaf element", tname);
451
                }
452
 
453
                if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL)
454
                        mtree_err("%s", strerror(errno));
455
                *centry = ginfo;
456
                centry->lineno = mtree_lineno;
457
                strcpy(centry->name, p);
458
#define MAGIC   "?*["
459
                if (strpbrk(p, MAGIC))
460
                        centry->flags |= F_MAGIC;
461
                set(next, centry);
462
 
463
                if (root == NULL) {
464
                                /*
465
                                 * empty tree
466
                                 */
467
                        if (strcmp(centry->name, ".") != 0 ||
468
                            centry->type != F_DIR)
469
                                mtree_err(
470
                                    "root node must be the directory `.'");
471
                        last = root = centry;
472
                        root->parent = root;
473
                } else if (pathparent != NULL) {
474
                                /*
475
                                 * full path entry; add or replace
476
                                 */
477
                        centry->parent = pathparent;
478
                        addchild(pathparent, centry);
479
                        last = centry;
480
                } else if (strcmp(centry->name, ".") == 0) {
481
                                /*
482
                                 * duplicate "." entry; always replace
483
                                 */
484
                        replacenode(root, centry);
485
                } else if (last->type == F_DIR && !(last->flags & F_DONE)) {
486
                                /*
487
                                 * new relative child in current dir;
488
                                 * add or replace
489
                                 */
490
                        centry->parent = last;
491
                        addchild(last, centry);
492
                        last = centry;
493
                } else {
494
                                /*
495
                                 * new relative child in parent dir
496
                                 * (after encountering ".." entry);
497
                                 * add or replace
498
                                 */
499
                        centry->parent = last->parent;
500
                        addchild(last->parent, centry);
501
                        last = centry;
502
                }
503
        }
504
        return root;
505
}
506
 
507
 
508
/*
509
 * addchild --
510
 *      Add the centry node as a child of the pathparent node.  If
511
 *      centry is a duplicate, call replacenode().  If centry is not
512
 *      a duplicate, insert it into the linked list referenced by
513
 *      pathparent->child.  Keep the list sorted if Sflag is set.
514
 */
515
static void addchild(NODE *pathparent, NODE *centry) {
516
        NODE *samename;      /* node with the same name as centry */
517
        NODE *replacepos;    /* if non-NULL, centry should replace this node */
518
        NODE *insertpos;     /* if non-NULL, centry should be inserted
519
                              * after this node */
520
        NODE *cur;           /* for stepping through the list */
521
        NODE *last;          /* the last node in the list */
522
        int cmp;
523
 
524
        samename = NULL;
525
        replacepos = NULL;
526
        insertpos = NULL;
527
        last = NULL;
528
        cur = pathparent->child;
529
        if (cur == NULL) {
530
                /* centry is pathparent's first and only child node so far */
531
                pathparent->child = centry;
532
                return;
533
        }
534
 
535
        /*
536
         * pathparent already has at least one other child, so add the
537
         * centry node to the list.
538
         *
539
         * We first scan through the list looking for an existing node
540
         * with the same name (setting samename), and also looking
541
         * for the correct position to replace or insert the new node
542
         * (setting replacepos and/or insertpos).
543
         */
544
        for (; cur != NULL; last = cur, cur = cur->next) {
545
                if (strcmp(centry->name, cur->name) == 0) {
546
                        samename = cur;
547
                }
548
                if (mtree_Sflag) {
549
                        cmp = nodecmp(centry, cur);
550
                        if (cmp == 0) {
551
                                replacepos = cur;
552
                        } else if (cmp > 0) {
553
                                insertpos = cur;
554
                        }
555
                }
556
        }
557
        if (! mtree_Sflag) {
558
                if (samename != NULL) {
559
                        /* replace node with same name */
560
                        replacepos = samename;
561
                } else {
562
                        /* add new node at end of list */
563
                        insertpos = last;
564
                }
565
        }
566
 
567
        if (samename != NULL) {
568
                /*
569
                 * We found a node with the same name above.  Call
570
                 * replacenode(), which will either exit with an error,
571
                 * or replace the information in the samename node and
572
                 * free the information in the centry node.
573
                 */
574
                replacenode(samename, centry);
575
                if (samename == replacepos) {
576
                        /* The just-replaced node was in the correct position */
577
                        return;
578
                }
579
                if (samename == insertpos || samename->prev == insertpos) {
580
                        /*
581
                         * We thought the new node should be just before
582
                         * or just after the replaced node, but that would
583
                         * be equivalent to just retaining the replaced node.
584
                         */
585
                        return;
586
                }
587
 
588
                /*
589
                 * The just-replaced node is in the wrong position in
590
                 * the list.  This can happen if sort order depends on
591
                 * criteria other than the node name.
592
                 *
593
                 * Make centry point to the just-replaced node.  Unlink
594
                 * the just-replaced node from the list, and allow it to
595
                 * be insterted in the correct position later.
596
                 */
597
                centry = samename;
598
                if (centry->prev)
599
                        centry->prev->next = centry->next;
600
                else {
601
                        /* centry->next is the new head of the list */
602
                        pathparent->child = centry->next;
603
                        assert(centry->next != NULL);
604
                }
605
                if (centry->next)
606
                        centry->next->prev = centry->prev;
607
                centry->prev = NULL;
608
                centry->next = NULL;
609
        }
610
 
611
        if (insertpos == NULL) {
612
                /* insert centry at the beginning of the list */
613
                pathparent->child->prev = centry;
614
                centry->next = pathparent->child;
615
                centry->prev = NULL;
616
                pathparent->child = centry;
617
        } else {
618
                /* insert centry into the list just after insertpos */
619
                centry->next = insertpos->next;
620
                insertpos->next = centry;
621
                centry->prev = insertpos;
622
                if (centry->next)
623
                        centry->next->prev = centry;
624
        }
625
        return;
626
}
627
 
628
 
629
static void replacenode(NODE *cur, NODE *new) {
630
        if (cur->type != new->type) {
631
                if (mtree_Mflag) {
632
                                /*
633
                                 * merge entries with different types; we
634
                                 * don't want children retained in this case.
635
                                 */
636
                        REPLACE(type);
637
                        free_nodes(cur->child);
638
                        cur->child = NULL;
639
                } else {
640
                        mtree_err(
641
                            "existing entry for `%s', type `%s'"
642
                            " does not match type `%s'",
643
                            cur->name, nodetype(cur->type),
644
                            nodetype(new->type));
645
                }
646
        }
647
 
648
        REPLACE(st_size);
649
        REPLACE(st_mtimespec);
650
        REPLACESTR(slink);
651
        if (cur->slink != NULL) {
652
                if ((cur->slink = strdup(new->slink)) == NULL)
653
                        mtree_err("memory allocation error");
654
                if (strunvis(cur->slink, new->slink) == -1)
655
                        mtree_err("strunvis failed on `%s'", new->slink);
656
                free(new->slink);
657
        }
658
        REPLACE(st_uid);
659
        REPLACE(st_gid);
660
        REPLACE(st_mode);
661
        REPLACE(st_rdev);
662
        REPLACE(st_flags);
663
        REPLACE(st_nlink);
664
        REPLACE(cksum);
665
        REPLACESTR(md5digest);
666
        REPLACESTR(rmd160digest);
667
        REPLACESTR(sha1digest);
668
        REPLACESTR(sha256digest);
669
        REPLACESTR(sha384digest);
670
        REPLACESTR(sha512digest);
671
        REPLACESTR(tags);
672
        REPLACE(lineno);
673
        REPLACE(flags);
674
        free(new);
675
}
676
 
677
 
678
static void set(char *t, NODE *ip) {
679
        int     type, value, len;
680
        gid_t   gid;
681
        uid_t   uid;
682
        char    *kw, *val, *md, *ep;
683
        void    *m;
684
 
685
        while ((kw = strsep(&t, "= \t")) != NULL) {
686
                if (*kw == '\0')
687
                        continue;
688
                if (strcmp(kw, "all") == 0)
689
                        mtree_err("invalid keyword `all'");
690
                ip->flags |= type = parsekey(kw, &value);
691
                if (!value)
692
                        /* Just set flag bit (F_IGN and F_OPT) */
693
                        continue;
694
                while ((val = strsep(&t, " \t")) != NULL && *val == '\0')
695
                        continue;
696
                if (val == NULL)
697
                        mtree_err("missing value");
698
                switch (type) {
699
                case F_CKSUM:
700
                        ip->cksum = strtoul(val, &ep, 10);
701
                        if (*ep)
702
                                mtree_err("invalid checksum `%s'", val);
703
                        break;
704
                case F_DEV:
705
                        ip->st_rdev = parsedev(val);
706
                        break;
707
                case F_FLAGS:
708
                        if (strcmp("none", val) == 0)
709
                                ip->st_flags = 0;
710
                        else if (string_to_flags(&val, &ip->st_flags, NULL)
711
                            != 0)
712
                                mtree_err("invalid flag `%s'", val);
713
                        break;
714
                case F_GID:
715
                        ip->st_gid = (gid_t)strtoul(val, &ep, 10);
716
                        if (*ep)
717
                                mtree_err("invalid gid `%s'", val);
718
                        break;
719
                case F_GNAME:
720
                        if (mtree_Wflag)        /* don't parse if whacking */
721
                                break;
722
                        if (gid_from_group(val, &gid) == -1)
723
                                mtree_err("unknown group `%s'", val);
724
                        ip->st_gid = gid;
725
                        break;
726
                case F_MD5:
727
                        if (val[0]=='0' && val[1]=='x')
728
                                md=&val[2];
729
                        else
730
                                md=val;
731
                        if ((ip->md5digest = strdup(md)) == NULL)
732
                                mtree_err("memory allocation error");
733
                        break;
734
                case F_MODE:
735
                        if ((m = setmode(val)) == NULL)
736
                                mtree_err("cannot set file mode `%s' (%s)",
737
                                    val, strerror(errno));
738
                        ip->st_mode = getmode(m, 0);
739
                        free(m);
740
                        break;
741
                case F_NLINK:
742
                        ip->st_nlink = (nlink_t)strtoul(val, &ep, 10);
743
                        if (*ep)
744
                                mtree_err("invalid link count `%s'", val);
745
                        break;
746
                case F_RMD160:
747
                        if (val[0]=='0' && val[1]=='x')
748
                                md=&val[2];
749
                        else
750
                                md=val;
751
                        if ((ip->rmd160digest = strdup(md)) == NULL)
752
                                mtree_err("memory allocation error");
753
                        break;
754
                case F_SHA1:
755
                        if (val[0]=='0' && val[1]=='x')
756
                                md=&val[2];
757
                        else
758
                                md=val;
759
                        if ((ip->sha1digest = strdup(md)) == NULL)
760
                                mtree_err("memory allocation error");
761
                        break;
762
                case F_SIZE:
763
                        ip->st_size = (off_t)strtoll(val, &ep, 10);
764
                        if (*ep)
765
                                mtree_err("invalid size `%s'", val);
766
                        break;
767
                case F_SLINK:
768
                        if ((ip->slink = strdup(val)) == NULL)
769
                                mtree_err("memory allocation error");
770
                        if (strunvis(ip->slink, val) == -1)
771
                                mtree_err("strunvis failed on `%s'", val);
772
                        break;
773
                case F_TAGS:
774
                        len = strlen(val) + 3;  /* "," + str + ",\0" */
775
                        if ((ip->tags = malloc(len)) == NULL)
776
                                mtree_err("memory allocation error");
777
                        snprintf(ip->tags, len, ",%s,", val);
778
                        break;
779
                case F_TIME:
780
                        ip->st_mtimespec.tv_sec =
781
                            (time_t)strtoll(val, &ep, 10);
782
                        if (*ep != '.')
783
                                mtree_err("invalid time `%s'", val);
784
                        val = ep + 1;
785
                        ip->st_mtimespec.tv_nsec = strtol(val, &ep, 10);
786
                        if (*ep)
787
                                mtree_err("invalid time `%s'", val);
788
                        break;
789
                case F_TYPE:
790
                        ip->type = parsetype(val);
791
                        break;
792
                case F_UID:
793
                        ip->st_uid = (uid_t)strtoul(val, &ep, 10);
794
                        if (*ep)
795
                                mtree_err("invalid uid `%s'", val);
796
                        break;
797
                case F_UNAME:
798
                        if (mtree_Wflag)        /* don't parse if whacking */
799
                                break;
800
                        if (uid_from_user(val, &uid) == -1)
801
                                mtree_err("unknown user `%s'", val);
802
                        ip->st_uid = uid;
803
                        break;
804
                case F_SHA256:
805
                        if (val[0]=='0' && val[1]=='x')
806
                                md=&val[2];
807
                        else
808
                                md=val;
809
                        if ((ip->sha256digest = strdup(md)) == NULL)
810
                                mtree_err("memory allocation error");
811
                        break;
812
                case F_SHA384:
813
                        if (val[0]=='0' && val[1]=='x')
814
                                md=&val[2];
815
                        else
816
                                md=val;
817
                        if ((ip->sha384digest = strdup(md)) == NULL)
818
                                mtree_err("memory allocation error");
819
                        break;
820
                case F_SHA512:
821
                        if (val[0]=='0' && val[1]=='x')
822
                                md=&val[2];
823
                        else
824
                                md=val;
825
                        if ((ip->sha512digest = strdup(md)) == NULL)
826
                                mtree_err("memory allocation error");
827
                        break;
828
                default:
829
                        mtree_err(
830
                            "set(): unsupported key type 0x%x (INTERNAL ERROR)",
831
                            type);
832
                        /* NOTREACHED */
833
                }
834
        }
835
}
836
 
837
 
838
static void unset(char *t, NODE *ip) {
839
  char *p;
840
 
841
  while ((p = strsep(&t, " \t")) != NULL) {
842
    if (*p == '\0') {
843
      continue;
844
    }
845
    ip->flags &= ~parsekey(p, NULL);
846
  }
847
}
848
 
849
 
850
void free_nodes(NODE *root) {
851
  NODE *cur, *next;
852
 
853
  if (root == NULL) {
854
    return;
855
  }
856
  next = NULL;
857
  for (cur = root; cur != NULL; cur = next) {
858
    next = cur->next;
859
    free_nodes(cur->child);
860
    REPLACEPTR(cur->slink, NULL);
861
    REPLACEPTR(cur->md5digest, NULL);
862
    REPLACEPTR(cur->rmd160digest, NULL);
863
    REPLACEPTR(cur->sha1digest, NULL);
864
    REPLACEPTR(cur->sha256digest, NULL);
865
    REPLACEPTR(cur->sha384digest, NULL);
866
    REPLACEPTR(cur->sha512digest, NULL);
867
    REPLACEPTR(cur->tags, NULL);
868
    REPLACEPTR(cur, NULL);
869
  }
870
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.