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
,