Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / tools / dumpscan / 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
58 ParseTaggedData(XFILE * X, tagged_field * fields, unsigned char *tag,
59 tag_parse_info * pi, void *g_refcon, void *l_refcon)
60 {
61 int i = -1;
62 afs_uint32 r, val;
63 afs_uint16 val16;
64 unsigned char val8;
65 unsigned char *strval;
66
67 for (;;) {
68 if (i < 0 || (fields[i].kind & DKIND_MASK) != DKIND_SPECIAL) {
69 /* Need to read in a tag */
70 if ((r = ReadByte(X, tag)))
71 return r;
72 }
73
74 /* Simple error recovery - if we encounter a 0, it can never be
75 * a valid tag. If TPFLAG_SKIP is set, we can skip over any
76 * such null bytes, and process whatever tag we find beyond.
77 * In addition, if TPFLAG_RSKIP is set, then the next time
78 * we encounter a 0, try skipping backwards. That seems to
79 * work much of the time.
80 */
81 if (!*tag && pi->shift_offset && (pi->flags & TPFLAG_RSKIP)) {
82 dt_uint64 where, tmp64a, tmp64b;
83 char buf1[21], buf2[21], buf3[21];
84 char *p1, *p2, *p3;
85
86 if ((r = xftell(X, &tmp64a)))
87 return r;
88 sub64_32(where, tmp64a, pi->shift_offset + 1);
89 if ((r = xfseek(X, &where)))
90 return r;
91 if (pi->cb_error) {
92 (pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
93 "Inserted %d bytes before offset %d",
94 pi->shift_offset, decimate_int64(&where, 0));
95 add64_32(tmp64a, pi->shift_start, pi->shift_offset);
96 p1 = decimate_int64(&tmp64a, buf1);
97 sub64_64(tmp64b, where, tmp64a);
98 p2 = decimate_int64(&tmp64b, buf2);
99 p3 = decimate_int64(&pi->shift_start, buf3);
100 (pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
101 ">>> SHIFT start=%s length=%s target=%s", p1,
102 p2, p3);
103 }
104 pi->shift_offset = 0;
105 if ((r = ReadByte(X, tag)))
106 return r;
107 }
108 if (!*tag && (pi->flags & TPFLAG_SKIP)) {
109 int count = 0;
110 dt_uint64 where, tmp64a;
111
112 if ((r = xftell(X, &where)))
113 return r;
114
115 while (!*tag) {
116 if ((r = ReadByte(X, tag)))
117 return r;
118 count++;
119 }
120 pi->shift_offset += count;
121 cp64(pi->shift_start, where);
122 if (pi->cb_error) {
123 sub64_32(tmp64a, where, 1);
124 (pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
125 "Skipped %d bytes at offset %s", count,
126 decimate_int64(&tmp64a, 0));
127 }
128 }
129
130 for (i = 0; fields[i].tag && fields[i].tag != *tag; i++);
131 if (!fields[i].tag)
132 return 0;
133
134 switch (fields[i].kind & DKIND_MASK) {
135 case DKIND_NOOP:
136 if (fields[i].func) {
137 r = (fields[i].func) (X, 0, fields + i, 0, pi, g_refcon,
138 l_refcon);
139 if (r)
140 return r;
141 }
142 break;
143
144 case DKIND_BYTE:
145 if ((r = ReadByte(X, &val8)))
146 return r;
147 if (fields[i].func) {
148 r = (fields[i].func) (X, 0, fields + i, val8, pi, g_refcon,
149 l_refcon);
150 if (r)
151 return r;
152 }
153 break;
154
155 case DKIND_INT16:
156 if ((r = ReadInt16(X, &val16)))
157 return r;
158 if (fields[i].func) {
159 r = (fields[i].func) (X, 0, fields + i, val16, pi, g_refcon,
160 l_refcon);
161 if (r)
162 return r;
163 }
164 break;
165
166 case DKIND_INT32:
167 if ((r = ReadInt32(X, &val)))
168 return r;
169 if (fields[i].func) {
170 r = (fields[i].func) (X, 0, fields + i, val, pi, g_refcon,
171 l_refcon);
172 if (r)
173 return r;
174 }
175 break;
176
177 case DKIND_STRING:
178 if ((r = ReadString(X, &strval)))
179 return r;
180 if (fields[i].func) {
181 r = (fields[i].func) (X, strval, fields + i, 0, pi, g_refcon,
182 l_refcon);
183 if (r != DSERR_KEEP)
184 free(strval);
185 if (r && r != DSERR_KEEP)
186 return r;
187 } else
188 free(strval);
189 break;
190
191 case DKIND_SPECIAL:
192 if (fields[i].func) {
193 r = (fields[i].func) (X, tag, fields + i, 0, pi, g_refcon,
194 l_refcon);
195 if (r)
196 return r;
197 } else
198 i = -1;
199 }
200 }
201 }