test-suite-pull-tools-directly-in-20020114
[openafs.git] / src / tests / parsetag.c
1 /*
2  * CMUCS AFStools
3  * dumpscan - routines for scanning and manipulating AFS volume dumps
4  *
5  * Copyright (c) 1998 Carnegie Mellon University
6  * All Rights Reserved.
7  * 
8  * Permission to use, copy, modify and distribute this software and its
9  * documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  *
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  *
18  * Carnegie Mellon requests users of this software to return to
19  *
20  *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  *
25  * any improvements or extensions that they make and grant Carnegie Mellon
26  * the rights to redistribute these changes.
27  */
28
29 /* parsetag.c - Parse a tagged data stream */
30
31 #include "dumpscan.h"
32 #include "dumpscan_errs.h"
33
34 /* If a parser function is defined, it will be called after the data value
35  * (if any) is read.  The parser is called as follows:
36  *
37  *   parser(input_file, &tag, &field_rec, value, g_refcon, l_refcon);
38  *
39  * - input_file is the FILE * for the input stream
40  * - field_rec is a pointer to the field record for the field just read
41  * - g_refcon and l_refcon are as passed in to ParseTaggedData
42  * - For integer types, value is the integer value
43  * - For DKIND_STRING, tag is a pointer to the string just read
44  * - For DKIND_SPEACH, tag is a pointer to the place to put the next tag.
45  *
46  * If the field type is DKIND_SPECIAL, the parser is expected to read its
47  * own data from the input stream, and return when ParseTaggedData is supposed
48  * to take over, with the next tag to process in *tag.  At no other time
49  * should the parser read, write, or reposition the input stream.
50  *
51  * The parser routine should return 0 on success, non-0 on failure.  If the
52  * data type is DKIND_STRING, the parser may return DSERR_KEEP to indicate
53  * that the memory allocated for the value should not be freed.
54  */
55
56 /* Parse a file containing tagged data and attributes **/
57 afs_uint32 ParseTaggedData(XFILE *X, tagged_field *fields, unsigned char *tag,
58                     tag_parse_info *pi, void *g_refcon, void *l_refcon)
59 {
60   int i = -1;
61   afs_uint32 r, val;
62   afs_uint16 val16;
63   unsigned char val8;
64   unsigned char *strval;
65
66   for (;;) {
67     if (i < 0 || (fields[i].kind & DKIND_MASK) != DKIND_SPECIAL) {
68       /* Need to read in a tag */
69       if (r = ReadByte(X, tag)) return r;
70     }
71
72     /* Simple error recovery - if we encounter a 0, it can never be
73      * a valid tag.  If TPFLAG_SKIP is set, we can skip over any
74      * such null bytes, and process whatever tag we find beyond.
75      * In addition, if TPFLAG_RSKIP is set, then the next time
76      * we encounter a 0, try skipping backwards.  That seems to
77      * work much of the time.
78      */
79     if (!*tag && pi->shift_offset && (pi->flags & TPFLAG_RSKIP)) {
80       u_int64 where, tmp64a, tmp64b;
81       char buf1[21], buf2[21], buf3[21];
82       char *p1, *p2, *p3;
83
84       if (r = xftell(X, &tmp64a)) return r;
85       sub64_32(where, tmp64a, pi->shift_offset + 1);
86       if (r = xfseek(X, &where)) return r;
87       if (pi->cb_error){
88         (pi->cb_error)(DSERR_FMT, 0, pi->err_refcon,
89                        "Inserted %d bytes before offset %d",
90                        pi->shift_offset, decimate_int64(&where, 0));
91         add64_32(tmp64a, pi->shift_start, pi->shift_offset);
92         p1 = decimate_int64(&tmp64a, buf1);
93         sub64_64(tmp64b, where, tmp64a);
94         p2 = decimate_int64(&tmp64b, buf2);
95         p3 = decimate_int64(&pi->shift_start, buf3);
96         (pi->cb_error)(DSERR_FMT, 0, pi->err_refcon,
97                        ">>> SHIFT start=%s length=%s target=%s",
98                        p1, p2, p3);
99       }
100       pi->shift_offset = 0;
101       if (r = ReadByte(X, tag)) return r;
102     }
103     if (!*tag && (pi->flags & TPFLAG_SKIP)) {
104       int count = 0;
105       u_int64 where, tmp64a;
106
107       if (r = xftell(X, &where)) return r;
108       
109       while (!*tag) {
110         if (r = ReadByte(X, tag)) return r;
111         count++;
112       }
113       pi->shift_offset += count;
114       cp64(pi->shift_start, where);
115       if (pi->cb_error) {
116         sub64_32(tmp64a, where, 1);
117         (pi->cb_error)(DSERR_FMT, 0, pi->err_refcon,
118                        "Skipped %d bytes at offset %s",
119                        count, decimate_int64(&tmp64a, 0));
120       }
121     }
122
123     for (i = 0; fields[i].tag && fields[i].tag != *tag; i++);
124     if (!fields[i].tag) return 0;
125
126     switch (fields[i].kind & DKIND_MASK) {
127     case DKIND_NOOP:
128       if (fields[i].func) {
129         r = (fields[i].func)(X, 0, fields+i, 0, pi, g_refcon, l_refcon);
130         if (r) return r;
131       }
132       break;
133
134     case DKIND_BYTE:
135       if (r = ReadByte(X, &val8)) return r;
136       if (fields[i].func) {
137         r = (fields[i].func)(X, 0, fields+i, val8, pi, g_refcon, l_refcon);
138         if (r) return r;
139       }
140       break;
141
142     case DKIND_INT16:
143       if (r = ReadInt16(X, &val16)) return r;
144       if (fields[i].func) {
145         r = (fields[i].func)(X, 0, fields+i, val16, pi, g_refcon, l_refcon);
146         if (r) return r;
147       }
148       break;
149
150     case DKIND_INT32:
151       if (r = ReadInt32(X, &val)) return r;
152       if (fields[i].func) {
153         r = (fields[i].func)(X, 0, fields+i, val, pi, g_refcon, l_refcon);
154         if (r) return r;
155       }
156       break;
157
158     case DKIND_STRING: 
159       if (r = ReadString(X, &strval)) return r;
160       if (fields[i].func) {
161         r = (fields[i].func)(X, strval, fields+i, 0, pi, g_refcon, l_refcon);
162         if (r != DSERR_KEEP) free(strval);
163         if (r && r != DSERR_KEEP) return r;
164       } else free(strval);
165       break;
166
167     case DKIND_SPECIAL:
168       if (fields[i].func) {
169         r = (fields[i].func)(X, tag, fields+i, 0, pi, g_refcon, l_refcon);
170         if (r) return r;
171       } else i = -1;
172     }
173   }
174 }