3 * dumpscan - routines for scanning and manipulating AFS volume dumps
5 * Copyright (c) 1998 Carnegie Mellon University
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.
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.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes.
29 /* parsetag.c - Parse a tagged data stream */
32 #include "dumpscan_errs.h"
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:
37 * parser(input_file, &tag, &field_rec, value, g_refcon, l_refcon);
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.
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.
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.
56 /* Parse a file containing tagged data and attributes **/
58 ParseTaggedData(XFILE * X, tagged_field * fields, unsigned char *tag,
59 tag_parse_info * pi, void *g_refcon, void *l_refcon)
65 unsigned char *strval;
68 if (i < 0 || (fields[i].kind & DKIND_MASK) != DKIND_SPECIAL) {
69 /* Need to read in a tag */
70 if ((r = ReadByte(X, tag)))
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.
81 if (!*tag && pi->shift_offset && (pi->flags & TPFLAG_RSKIP)) {
82 dt_uint64 where, tmp64a, tmp64b;
83 char buf1[21], buf2[21], buf3[21];
86 if ((r = xftell(X, &tmp64a)))
88 sub64_32(where, tmp64a, pi->shift_offset + 1);
89 if ((r = xfseek(X, &where)))
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,
104 pi->shift_offset = 0;
105 if ((r = ReadByte(X, tag)))
108 if (!*tag && (pi->flags & TPFLAG_SKIP)) {
110 dt_uint64 where, tmp64a;
112 if ((r = xftell(X, &where)))
116 if ((r = ReadByte(X, tag)))
120 pi->shift_offset += count;
121 cp64(pi->shift_start, where);
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));
130 for (i = 0; fields[i].tag && fields[i].tag != *tag; i++);
134 switch (fields[i].kind & DKIND_MASK) {
136 if (fields[i].func) {
137 r = (fields[i].func) (X, 0, fields + i, 0, pi, g_refcon,
145 if ((r = ReadByte(X, &val8)))
147 if (fields[i].func) {
148 r = (fields[i].func) (X, 0, fields + i, val8, pi, g_refcon,
156 if ((r = ReadInt16(X, &val16)))
158 if (fields[i].func) {
159 r = (fields[i].func) (X, 0, fields + i, val16, pi, g_refcon,
167 if ((r = ReadInt32(X, &val)))
169 if (fields[i].func) {
170 r = (fields[i].func) (X, 0, fields + i, val, pi, g_refcon,
178 if ((r = ReadString(X, &strval)))
180 if (fields[i].func) {
181 r = (fields[i].func) (X, strval, fields + i, 0, pi, g_refcon,
185 if (r && r != DSERR_KEEP)
192 if (fields[i].func) {
193 r = (fields[i].func) (X, tag, fields + i, 0, pi, g_refcon,