Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / tools / dumpscan / afsdump_scan.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 /* afsdump_scan.c - General-purpose dump scanner */
30
31 #include <afsconfig.h>
32 #include <afs/param.h>
33
34 #include <roken.h>
35
36 #include <afs/com_err.h>
37 #include <afs/pterror.h>
38 #include <afs/vlserver.h>
39 #include <afs/cellconfig.h>
40 #include <rx/rxkad.h>
41 #include <afs/afsint.h>
42 #include <afs/volser.h>
43 #include <ubik.h>
44
45 #include "dumpscan.h"
46 #include "dumpscan_errs.h"
47 #include "xf_errs.h"
48 extern int optind;
49 extern char *optarg;
50
51 extern XFILE repair_output;
52 extern afs_uint32 repair_dumphdr_cb(afs_dump_header *, XFILE *, void *);
53 extern afs_uint32 repair_volhdr_cb(afs_vol_header *, XFILE *, void *);
54 extern afs_uint32 repair_vnode_cb(afs_vnode *, XFILE *, void *);
55
56 char *argv0;
57 static char *input_path, *gendump_path;
58 static afs_uint32 printflags, repairflags;
59 static int quiet, verbose, error_count;
60
61 static path_hashinfo phi;
62 static dump_parser dp;
63
64
65 /* Print a usage message and exit */
66 static void
67 usage(int status, char *msg)
68 {
69 if (msg)
70 fprintf(stderr, "%s: %s\n", argv0, msg);
71 fprintf(stderr, "Usage: %s [options] [file]\n", argv0);
72 fprintf(stderr, " -Pxxx Set print options:\n");
73 fprintf(stderr, " B = Print backup system header (if any)\n");
74 fprintf(stderr, " H = Print AFS dump header\n");
75 fprintf(stderr, " V = Print AFS volume header\n");
76 fprintf(stderr, " v = List vnodes\n");
77 fprintf(stderr, " p = Include path to each vnode\n");
78 fprintf(stderr, " i = Include info for each vnode\n");
79 fprintf(stderr, " d = List directory contents\n");
80 fprintf(stderr, " a = List access control lists\n");
81 fprintf(stderr, " g = Print debugging info\n");
82 fprintf(stderr, " -Rxxx Set repair options:\n");
83 fprintf(stderr, " 0 = Skip null tags\n");
84 fprintf(stderr, " b = Seek backward to find skipped tags\n");
85 fprintf(stderr, " d = Resync after vnode data\n");
86 fprintf(stderr, " v = Resync after corrupted vnodes\n");
87 fprintf(stderr, " -h Print this help message\n");
88 fprintf(stderr, " -gxxx Generate a new dump in file xxx\n");
89 fprintf(stderr, " -q Quiet mode (don't print errors)\n");
90 fprintf(stderr, " -v Verbose mode\n");
91 exit(status);
92 }
93
94
95 /* Parse the argument given to the -P option.
96 * Returns the resulting * dumpscan print flags (DSPRINT_*).
97 * If an unrecognized flag is used, prints an error message and exits.
98 */
99 static afs_uint32
100 parse_printflags(char *flags)
101 {
102 afs_uint32 result = 0;
103 char *x;
104
105 for (x = flags; *x; x++)
106 switch (*x) {
107 case 'B':
108 result |= DSPRINT_BCKHDR;
109 continue;
110 case 'H':
111 result |= DSPRINT_DUMPHDR;
112 continue;
113 case 'V':
114 result |= DSPRINT_VOLHDR;
115 continue;
116 case 'v':
117 result |= DSPRINT_ITEM;
118 continue;
119 case 'p':
120 result |= DSPRINT_PATH;
121 continue;
122 case 'i':
123 result |= DSPRINT_VNODE;
124 continue;
125 case 'd':
126 result |= DSPRINT_DIR;
127 continue;
128 case 'a':
129 result |= DSPRINT_ACL;
130 continue;
131 case 'g':
132 result |= DSPRINT_DEBUG;
133 continue;
134 default:
135 usage(1, "Invalid print options!");
136 }
137 return result;
138 }
139
140
141 /* Parse the argument given to the -R option.
142 * Returns the resulting * dumpscan repair flags (DSFIX_*).
143 * If an unrecognized flag is used, prints an error message and exits.
144 */
145 static afs_uint32
146 parse_repairflags(char *flags)
147 {
148 afs_uint32 result = 0;
149 char *x;
150
151 for (x = flags; *x; x++)
152 switch (*x) {
153 case '0':
154 result |= DSFIX_SKIP;
155 continue;
156 case 'b':
157 result |= DSFIX_RSKIP;
158 continue;
159 case 'd':
160 result |= DSFIX_VDSYNC;
161 continue;
162 case 'v':
163 result |= DSFIX_VFSYNC;
164 continue;
165 default:
166 usage(1, "Invalid repair options!");
167 }
168 return result;
169 }
170
171
172 /* Parse the command-line options */
173 static void
174 parse_options(int argc, char **argv)
175 {
176 int c;
177
178 /* Set the program name */
179 if ((argv0 = strrchr(argv[0], '/')))
180 argv0++;
181 else
182 argv0 = argv[0];
183
184 /* Initialize options */
185 input_path = gendump_path = 0;
186 printflags = repairflags = 0;
187 quiet = verbose = 0;
188
189 /* Initialize other stuff */
190 error_count = 0;
191
192 /* Parse the options */
193 while ((c = getopt(argc, argv, "P:R:g:hqv")) != EOF) {
194 switch (c) {
195 case 'P':
196 printflags = parse_printflags(optarg);
197 continue;
198 case 'R':
199 repairflags = parse_repairflags(optarg);
200 continue;
201 case 'g':
202 gendump_path = optarg;
203 continue;
204 case 'q':
205 quiet = 1;
206 continue;
207 case 'v':
208 verbose = 1;
209 continue;
210 case 'h':
211 usage(0, 0);
212 default:
213 usage(1, "Invalid option!");
214 }
215 }
216
217 if (quiet && verbose)
218 usage(1, "Can't specify both -q and -v");
219
220 /* Parse non-option arguments */
221 if (argc - optind > 1)
222 usage(1, "Too many arguments!");
223 input_path = (argc == optind) ? "-" : argv[optind];
224 }
225
226
227 /* A callback to count and print errors */
228 static afs_uint32
229 my_error_cb(afs_uint32 code, int fatal, void *ref, char *msg, ...)
230 {
231 va_list alist;
232
233 error_count++;
234 if (!quiet) {
235 va_start(alist, msg);
236 afs_com_err_va(argv0, code, msg, alist);
237 va_end(alist);
238 }
239 return 0;
240 }
241
242
243 /* A callback to print the path of a vnode. */
244 static afs_uint32
245 print_vnode_path(afs_vnode * v, XFILE * X, void *refcon)
246 {
247 afs_uint32 r;
248 char *name = 0;
249
250 /* Do repair, but only for known vnode types */
251 if (gendump_path && (!(v->field_mask & F_VNODE_TYPE)
252 || ((v->type != vFile) && (v->type != vDirectory)
253 && (v->type != vSymlink)))) {
254 r = repair_vnode_cb(v, X, refcon);
255 if (r)
256 return r;
257 }
258 r = Path_Build(X, &phi, v->vnode, &name, 0);
259 if (!r && name)
260 printf(" Path: %s\n", name);
261 if (name)
262 free(name);
263 return r;
264 }
265
266
267 /* Setup for generating a repaired dump */
268 static afs_uint32
269 setup_repair(void)
270 {
271 afs_uint32 r;
272
273 r = xfopen(&repair_output, O_RDWR | O_CREAT | O_TRUNC, gendump_path);
274 if (r)
275 return r;
276
277 dp.cb_dumphdr = repair_dumphdr_cb;
278 dp.cb_volhdr = repair_volhdr_cb;
279 dp.cb_vnode_dir = repair_vnode_cb;
280 dp.cb_vnode_file = repair_vnode_cb;
281 dp.cb_vnode_link = repair_vnode_cb;
282 dp.cb_vnode_empty = repair_vnode_cb;
283 return 0;
284 }
285
286 extern afs_uint32 DumpDumpEnd(XFILE * OX);
287
288 /* Main program */
289 int
290 main(int argc, char **argv)
291 {
292 XFILE input_file;
293 afs_uint32 r;
294
295 parse_options(argc, argv);
296 initialize_acfg_error_table();
297 initialize_AVds_error_table();
298 initialize_rxk_error_table();
299 initialize_u_error_table();
300 initialize_vl_error_table();
301 initialize_vols_error_table();
302 initialize_xFil_error_table();
303 r = xfopen(&input_file, O_RDONLY, input_path);
304 if (r) {
305 afs_com_err(argv0, r, "opening %s", input_path);
306 exit(2);
307 }
308
309 memset(&dp, 0, sizeof(dp));
310 dp.cb_error = my_error_cb;
311 dp.repair_flags = repairflags;
312 if (input_file.is_seekable)
313 dp.flags |= DSFLAG_SEEK;
314 else {
315 if (repairflags)
316 fprintf(stderr,
317 "Repair modes available only for seekable dumps\n");
318 if (printflags & DSPRINT_PATH)
319 fprintf(stderr,
320 "Path-printing available only for seekable dumps\n");
321 if (repairflags || (printflags & DSPRINT_PATH))
322 exit(1);
323 }
324
325 if (gendump_path && (r = setup_repair())) {
326 afs_com_err(argv0, r, "setting up repair output");
327 xfclose(&input_file);
328 exit(2);
329 }
330
331 if (printflags & DSPRINT_PATH) {
332 dt_uint64 where;
333
334 dp.print_flags = printflags & DSPRINT_DEBUG;
335 memset(&phi, 0, sizeof(phi));
336 phi.p = &dp;
337
338 if ((r = xftell(&input_file, &where))
339 || (r = Path_PreScan(&input_file, &phi, 0))
340 || (r = xfseek(&input_file, &where))) {
341 afs_com_err(argv0, r, "- path initialization failed");
342 xfclose(&input_file);
343 exit(2);
344 }
345
346 dp.cb_vnode_dir = print_vnode_path;
347 dp.cb_vnode_file = print_vnode_path;
348 dp.cb_vnode_link = print_vnode_path;
349 dp.cb_vnode_empty = print_vnode_path;
350 dp.cb_vnode_wierd = print_vnode_path;
351 }
352
353 dp.print_flags = printflags;
354 r = ParseDumpFile(&input_file, &dp);
355 xfclose(&input_file);
356 if (gendump_path) {
357 if (!r)
358 r = DumpDumpEnd(&repair_output);
359 if (!r)
360 r = xfclose(&repair_output);
361 else
362 xfclose(&repair_output);
363 }
364
365 if (verbose && error_count)
366 fprintf(stderr, "*** %d errors\n", error_count);
367 if (r && !quiet)
368 fprintf(stderr, "*** FAILED: %s\n", afs_error_message(r));
369 exit(0);
370 }