1b3171b01bcbd76b1c625e2ef9292a41c352bb13
[openafs.git] / src / tools / parsedump.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 /* parsedump.c - Parse a volume dump file */
30
31 #include "dumpscan.h"
32 #include "dumpscan_errs.h"
33 #include "dumpfmt.h"
34 #include "internal.h"
35 #include "stagehdr.h"
36
37 static afs_uint32 parse_dumphdr(XFILE *, unsigned char *, tagged_field *,
38                                 afs_uint32, tag_parse_info *, void *, void *);
39 static afs_uint32 parse_dumpend(XFILE *, unsigned char *, tagged_field *,
40                                 afs_uint32, tag_parse_info *, void *, void *);
41 static afs_uint32 store_dumphdr(XFILE *, unsigned char *, tagged_field *,
42                                 afs_uint32, tag_parse_info *, void *, void *);
43 static afs_uint32 parse_dumptimes(XFILE *, unsigned char *, tagged_field *,
44                                   afs_uint32, tag_parse_info *, void *,
45                                   void *);
46
47 /** Field list for top-level objects **/
48 static tagged_field top_fields[] = {
49     {TAG_DUMPHEADER, DKIND_SPECIAL, "* DUMP HEADER", parse_dumphdr, 0, 0},
50     {TAG_VOLHEADER, DKIND_SPECIAL, "* VOLUME HEADER", parse_volhdr, 0, 0},
51     {TAG_VNODE, DKIND_SPECIAL, "* VNODE ", parse_vnode, 0, 0},
52     {TAG_DUMPEND, DKIND_INT32, "* DUMP END", parse_dumpend, 0, 0},
53     {STAGE_VERSMIN, DKIND_SPECIAL, "* STAGE HEADER", try_backuphdr, 0, 0},
54     {0, 0, 0, 0, 0, 0}
55 };
56
57
58 /** Field list for dump headers **/
59 static tagged_field dumphdr_fields[] = {
60     {DHTAG_VOLNAME, DKIND_STRING, " Volume name:  ", store_dumphdr, 0, 0},
61     {DHTAG_VOLID, DKIND_INT32, " Volume ID:    ", store_dumphdr, 0, 0},
62     {DHTAG_DUMPTIMES, DKIND_SPECIAL, " Dump Range:   ", parse_dumptimes, 0,
63      0},
64     {0, 0, 0, 0, 0, 0}
65 };
66
67
68 /* Parse a dump header, including its tagged attributes, and call the
69  * dump-header callback, if one is defined.
70  */
71 static afs_uint32
72 parse_dumphdr(XFILE * X, unsigned char *tag, tagged_field * field,
73               afs_uint32 value, tag_parse_info * pi, void *g_refcon,
74               void *l_refcon)
75 {
76     dump_parser *p = (dump_parser *) g_refcon;
77     afs_dump_header hdr;
78     dt_uint64 where;
79     afs_uint32 r;
80
81     memset(&hdr, 0, sizeof(hdr));
82     if ((r = xftell(X, &where)))
83         return r;
84     sub64_32(hdr.offset, where, 1);
85
86     if ((r = ReadInt32(X, &hdr.magic)))
87         return r;
88     if ((r = ReadInt32(X, &hdr.version)))
89         return r;
90
91     if (hdr.magic != DUMPBEGINMAGIC) {
92         if (p->cb_error)
93             (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
94                            "Invalid magic number (0x%08x) in dump header",
95                            hdr.magic);
96         return DSERR_MAGIC;
97     }
98     if (hdr.version != DUMPVERSION) {
99         if (p->cb_error)
100             (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
101                            "Unknown dump format version (%d) in dump header",
102                            hdr.version);
103         return DSERR_MAGIC;
104     }
105
106     if (p->print_flags & DSPRINT_DUMPHDR)
107         printf("%s [%s = 0x%s]\n", field->label,
108                decimate_int64(&hdr.offset, 0), hexify_int64(&hdr.offset, 0));
109     if (p->print_flags & DSPRINT_DUMPHDR) {
110         printf(" Magic number: 0x%08x\n", hdr.magic);
111         printf(" Version:      %d\n", hdr.version);
112     }
113     r = ParseTaggedData(X, dumphdr_fields, tag, pi, g_refcon, (void *)&hdr);
114
115     if (!r && p->cb_dumphdr) {
116         r = xftell(X, &where);
117         if (!r)
118             r = (p->cb_dumphdr) (&hdr, X, p->refcon);
119         if (p->flags & DSFLAG_SEEK) {
120             if (!r)
121                 r = xfseek(X, &where);
122             else
123                 xfseek(X, &where);
124         }
125     }
126     if (hdr.field_mask & F_DUMPHDR_VOLNAME)
127         free(hdr.volname);
128     return r;
129 }
130
131
132 /* Store tagged attributes into a dump header */
133 static afs_uint32
134 store_dumphdr(XFILE * X, unsigned char *tag, tagged_field * field,
135               afs_uint32 value, tag_parse_info * pi, void *g_refcon,
136               void *l_refcon)
137 {
138     dump_parser *p = (dump_parser *) g_refcon;
139     afs_dump_header *hdr = (afs_dump_header *) l_refcon;
140
141     switch (field->tag) {
142     case DHTAG_VOLID:
143         hdr->field_mask |= F_DUMPHDR_VOLID;
144         hdr->volid = value;
145         if (p->print_flags & DSPRINT_DUMPHDR)
146             printf("%s%d\n", field->label, hdr->volid);
147         return 0;
148
149     case DHTAG_VOLNAME:
150         if (tag && tag[0]) {
151             hdr->field_mask |= F_DUMPHDR_VOLNAME;
152             hdr->volname = tag;
153             if (p->print_flags & DSPRINT_DUMPHDR)
154                 printf("%s%s\n", field->label, hdr->volname);
155             return DSERR_KEEP;
156         } else
157             return 0;
158
159     default:
160         if (p->print_flags & DSPRINT_DUMPHDR)
161             printf("%s<<< UNKNOWN FIELD >>>\n", field->label);
162         return 0;
163     }
164 }
165
166
167 /* Parse and store the dump time range from a dump header */
168 static afs_uint32
169 parse_dumptimes(XFILE * X, unsigned char *tag, tagged_field * field,
170                 afs_uint32 value, tag_parse_info * pi, void *g_refcon,
171                 void *l_refcon)
172 {
173     dump_parser *p = (dump_parser *) g_refcon;
174     afs_dump_header *hdr = (afs_dump_header *) l_refcon;
175     afs_uint16 count;
176     afs_uint32 r;
177
178     if ((r = ReadInt16(X, &count)))
179         return r;
180     if (count != 2) {
181         if (p->cb_error)
182             (p->cb_error) (DSERR_FMT, 1, p->err_refcon,
183                            "Incorrect array count (%d) in dump times", count);
184         return DSERR_FMT;
185     }
186     if ((r = ReadInt32(X, &hdr->from_date)))
187         return r;
188     if ((r = ReadInt32(X, &hdr->to_date)))
189         return r;
190     hdr->field_mask |= (F_DUMPHDR_FROM | F_DUMPHDR_TO);
191     if (p->print_flags & DSPRINT_DUMPHDR)
192         printf("%s%d => %d\n", field->label, hdr->from_date, hdr->to_date);
193
194     return ReadByte(X, tag);
195 }
196
197
198 /* Parse a dump_end record */
199 static afs_uint32
200 parse_dumpend(XFILE * X, unsigned char *tag, tagged_field * field,
201               afs_uint32 value, tag_parse_info * pi, void *g_refcon,
202               void *l_refcon)
203 {
204     dump_parser *p = (dump_parser *) g_refcon;
205
206     if (value != DUMPENDMAGIC) {
207         if (p->cb_error)
208             (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
209                            "Invalid magic number (0x%08x) in dump trailer",
210                            value);
211         return DSERR_MAGIC;
212     }
213     if (p->print_flags & (DSPRINT_DUMPHDR | DSPRINT_ITEM))
214         printf("%s\n", field->label);
215     return DSERR_DONE;
216 }
217
218
219
220 afs_uint32
221 ParseDumpFile(XFILE * X, dump_parser * p)
222 {
223     tag_parse_info pi;
224     unsigned char tag;
225     afs_uint32 r;
226
227     prep_pi(p, &pi);
228     r = ParseTaggedData(X, top_fields, &tag, &pi, (void *)p, 0);
229     return handle_return(r, X, tag, p);
230 }
231
232
233 afs_uint32
234 ParseDumpHeader(XFILE * X, dump_parser * p)
235 {
236     tag_parse_info pi;
237     unsigned char tag;
238     afs_uint32 r;
239
240     prep_pi(p, &pi);
241     if ((r = ReadByte(X, &tag)))
242         return handle_return(r, X, tag, p);
243     if (tag != TAG_DUMPHEADER)
244         return handle_return(0, X, tag, p);
245     r = parse_dumphdr(X, &tag, &top_fields[0], 0, &pi, (void *)p, 0);
246     if (!r && tag >= 1 && tag <= 4)
247         r = DSERR_DONE;
248     return handle_return(r, X, tag, p);
249 }
250
251
252 afs_uint32
253 ParseVolumeHeader(XFILE * X, dump_parser * p)
254 {
255     tag_parse_info pi;
256     unsigned char tag;
257     afs_uint32 r;
258
259     prep_pi(p, &pi);
260     if ((r = ReadByte(X, &tag)))
261         return handle_return(r, X, tag, p);
262     if (tag != TAG_VOLHEADER)
263         return handle_return(0, X, tag, p);
264     r = parse_volhdr(X, &tag, &top_fields[1], 0, &pi, (void *)p, 0);
265     if (!r && tag >= 1 && tag <= 4)
266         r = DSERR_DONE;
267     return handle_return(r, X, tag, p);
268 }
269
270
271 afs_uint32
272 ParseVNode(XFILE * X, dump_parser * p)
273 {
274     tag_parse_info pi;
275     unsigned char tag;
276     afs_uint32 r;
277
278     prep_pi(p, &pi);
279     if ((r = ReadByte(X, &tag)))
280         return handle_return(r, X, tag, p);
281     if (tag != TAG_VNODE)
282         return handle_return(0, X, tag, p);
283     r = parse_vnode(X, &tag, &top_fields[2], 0, &pi, (void *)p, 0);
284     if (!r && tag >= 1 && tag <= 4)
285         r = DSERR_DONE;
286     return handle_return(r, X, tag, p);
287 }