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