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 **/
57 afs_uint32 ParseTaggedData(XFILE *X, tagged_field *fields, unsigned char *tag,
58 tag_parse_info *pi, void *g_refcon, void *l_refcon)
64 unsigned char *strval;
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;
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.
79 if (!*tag && pi->shift_offset && (pi->flags & TPFLAG_RSKIP)) {
80 u_int64 where, tmp64a, tmp64b;
81 char buf1[21], buf2[21], buf3[21];
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;
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",
100 pi->shift_offset = 0;
101 if (r = ReadByte(X, tag)) return r;
103 if (!*tag && (pi->flags & TPFLAG_SKIP)) {
105 u_int64 where, tmp64a;
107 if (r = xftell(X, &where)) return r;
110 if (r = ReadByte(X, tag)) return r;
113 pi->shift_offset += count;
114 cp64(pi->shift_start, where);
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));
123 for (i = 0; fields[i].tag && fields[i].tag != *tag; i++);
124 if (!fields[i].tag) return 0;
126 switch (fields[i].kind & DKIND_MASK) {
128 if (fields[i].func) {
129 r = (fields[i].func)(X, 0, fields+i, 0, pi, g_refcon, l_refcon);
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);
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);
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);
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;
168 if (fields[i].func) {
169 r = (fields[i].func)(X, tag, fields+i, 0, pi, g_refcon, l_refcon);