3 * Copyright (c) 1997 Carnegie Mellon University
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 * Carnegie Mellon requests users of this software to return to
18 * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
27 /* UB - Unified Backups */
28 /* methods/afs/dumpscan/afsdump_scan.c - General-purpose dump scanner */
30 #include <afsconfig.h>
31 #include <afs/param.h>
37 extern int opterr, optind;
40 extern XFILE repair_output;
41 extern afs_uint32 repair_dumphdr_cb(afs_dump_header *, XFILE *, void *);
42 extern afs_uint32 repair_volhdr_cb(afs_vol_header *, XFILE *, void *);
43 extern afs_uint32 repair_vnode_cb(afs_vnode *, XFILE *, void *);
46 static char *input_path, *gendump_path;
47 static afs_uint32 printflags, repairflags, add_admin;
48 static int quiet, verbose, error_count;
50 static path_hashinfo phi;
51 static dump_parser dp;
54 /* Print a usage message and exit */
56 usage(int status, char *msg)
59 fprintf(stderr, "%s: %s\n", argv0, msg);
60 fprintf(stderr, "Usage: %s [options] [file]\n", argv0);
61 fprintf(stderr, " -Pxxx Set print options:\n");
62 fprintf(stderr, " B = Print backup system header (if any)\n");
63 fprintf(stderr, " H = Print AFS dump header\n");
64 fprintf(stderr, " V = Print AFS volume header\n");
65 fprintf(stderr, " v = List vnodes\n");
66 fprintf(stderr, " p = Include path to each vnode\n");
67 fprintf(stderr, " i = Include info for each vnode\n");
68 fprintf(stderr, " d = List directory contents\n");
69 fprintf(stderr, " a = List access control lists\n");
70 fprintf(stderr, " g = Print debugging info\n");
71 fprintf(stderr, " -Rxxx Set repair options:\n");
72 fprintf(stderr, " 0 = Skip null tags\n");
73 fprintf(stderr, " b = Seek backward to find skipped tags\n");
74 fprintf(stderr, " d = Resync after vnode data\n");
75 fprintf(stderr, " v = Resync after corrupted vnodes\n");
77 " -Annn Add all rights for ID nnn to every directory\n");
78 fprintf(stderr, " -h Print this help message\n");
79 fprintf(stderr, " -gxxx Generate a new dump in file xxx\n");
80 fprintf(stderr, " -q Quiet mode (don't print errors)\n");
81 fprintf(stderr, " -v Verbose mode\n");
86 /* Parse the argument given to the -P option.
87 * Returns the resulting * dumpscan print flags (DSPRINT_*).
88 * If an unrecognized flag is used, prints an error message and exits.
91 parse_printflags(char *flags)
93 afs_uint32 result = 0;
96 for (x = flags; *x; x++)
99 result |= DSPRINT_BCKHDR;
102 result |= DSPRINT_DUMPHDR;
105 result |= DSPRINT_VOLHDR;
108 result |= DSPRINT_ITEM;
111 result |= DSPRINT_PATH;
114 result |= DSPRINT_VNODE;
117 result |= DSPRINT_DIR;
120 result |= DSPRINT_ACL;
123 result |= DSPRINT_DEBUG;
126 usage(1, "Invalid print options!");
132 /* Parse the argument given to the -R option.
133 * Returns the resulting * dumpscan repair flags (DSFIX_*).
134 * If an unrecognized flag is used, prints an error message and exits.
137 parse_repairflags(char *flags)
139 afs_uint32 result = 0;
142 for (x = flags; *x; x++)
145 result |= DSFIX_SKIP;
148 result |= DSFIX_RSKIP;
151 result |= DSFIX_VDSYNC;
154 result |= DSFIX_VFSYNC;
157 usage(1, "Invalid repair options!");
163 /* Parse the command-line options */
165 parse_options(int argc, char **argv)
169 /* Set the program name */
170 if (argv0 = strrchr(argv[0], '/'))
175 /* Initialize options */
176 input_path = gendump_path = 0;
177 printflags = repairflags = add_admin = 0;
180 /* Initialize other stuff */
183 /* Parse the options */
184 while ((c = getopt(argc, argv, "A:P:R:g:hv")) != EOF) {
187 add_admin = atoi(optarg);
190 printflags = parse_printflags(optarg);
193 repairflags = parse_repairflags(optarg);
196 gendump_path = optarg;
207 usage(1, "Invalid option!");
211 if (quiet && verbose)
212 usage(1, "Can't specify both -q and -v");
214 /* Parse non-option arguments */
215 if (argc - optind > 1)
216 usage(1, "Too many arguments!");
217 input_path = (argc == optind) ? "-" : argv[optind];
218 if (add_admin && !gendump_path)
223 /* A callback to count and print errors */
225 my_error_cb(afs_uint32 code, int fatal, void *ref, char *msg, ...)
231 va_start(alist, msg);
232 afs_com_err_va(argv0, code, msg, alist);
238 /* A callback to print the path of a vnode. */
240 print_vnode_path(afs_vnode * v, XFILE * X, void *refcon)
245 /* Do repair, but only for known vnode types */
246 if (gendump_path && (!(v->field_mask & F_VNODE_TYPE)
247 || v->type != vFile || v->type != vDirectory
248 || v->type != vSymlink)) {
249 r = repair_vnode_cb(v, X, refcon);
253 r = Path_Build(X, &phi, v->vnode, &name, 0);
255 printf(" Path: %s\n", name);
263 munge_admin_acl(afs_vnode * v, XFILE * X, void *refcon)
265 struct acl_accessList *acl;
266 int add_entry = 1, remove_entry = -1;
269 acl = (struct acl_accessList *)(v->acl);
270 o = n = ntohl(acl->positive);
271 for (i = 0; i < n; i++)
272 if (ntohl(acl->entries[i].id) == add_admin)
274 n = ntohl(acl->negative);
275 for (i = o; i < n + o; i++)
276 if (ntohl(acl->entries[i].id) == add_admin)
280 for (i = (remove_entry < 0) ? o + n : remove_entry; i > o; i--) {
281 acl->entries[i].id = acl->entries[i - 1].id;
282 acl->entries[i].rights = acl->entries[i - 1].rights;
284 acl->entries[o].id = htonl(add_admin);
285 acl->entries[o].rights =
286 htonl((PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
287 PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER));
288 acl->positive = htonl(o + 1);
289 if (remove_entry < 0)
290 acl->total = htonl(o + n + 1);
292 acl->negative = htonl(n - 1);
293 } else if (remove_entry >= 0) {
294 for (i = remove_entry; i < o + n - 1; i++) {
295 acl->entries[i].id = acl->entries[i + 1].id;
296 acl->entries[i].rights = acl->entries[i + 1].rights;
298 acl->negative = htonl(n - 1);
299 acl->total = htonl(o + n - 1);
301 return repair_vnode_cb(v, X, refcon);
305 /* Setup for generating a repaired dump */
311 r = xfopen(&repair_output, gendump_path, O_RDWR, 0644);
315 dp.cb_dumphdr = repair_dumphdr_cb;
316 dp.cb_volhdr = repair_volhdr_cb;
317 dp.cb_vnode_dir = repair_vnode_cb;
318 dp.cb_vnode_file = repair_vnode_cb;
319 dp.cb_vnode_link = repair_vnode_cb;
320 dp.cb_vnode_empty = repair_vnode_cb;
327 main(int argc, char **argv)
332 parse_options(argc, argv);
333 initialize_UB_error_table();
334 initialize_UBsp_error_table();
335 initialize_AVds_error_table();
336 r = xfopen(&X, input_path, O_RDONLY, 0);
338 afs_com_err(argv0, r, "opening %s", input_path);
342 bzero(&dp, sizeof(dp));
343 dp.cb_error = my_error_cb;
344 dp.repair_flags = repairflags;
346 dp.flags |= DSFLAG_SEEK;
350 "Repair modes available only for seekable dumps\n");
351 if (printflags & DSPRINT_PATH)
353 "Path-printing available only for seekable dumps\n");
354 if (repairflags || (printflags & DSPRINT_PATH))
358 if (gendump_path && (r = setup_repair())) {
359 afs_com_err(argv0, r, "setting up repair output");
364 if (printflags & DSPRINT_PATH) {
367 dp.print_flags = printflags & DSPRINT_DEBUG;
368 bzero(&phi, sizeof(phi));
371 if ((r = xftell(X, &where))
372 || (r = Path_PreScan(X, &phi, 0))
373 || (r = xfseek(X, &where))) {
374 afs_com_err(argv0, r, "- path initialization failed");
379 dp.cb_vnode_dir = print_vnode_path;
380 dp.cb_vnode_file = print_vnode_path;
381 dp.cb_vnode_link = print_vnode_path;
382 dp.cb_vnode_empty = print_vnode_path;
383 dp.cb_vnode_wierd = print_vnode_path;
387 dp.cb_vnode_dir = munge_admin_acl;
390 dp.print_flags = printflags;
391 r = ParseDumpFile(X, &dp);
394 r = DumpDumpEnd(&repair_output);
396 r = xfclose(&repair_output);
398 xfclose(&repair_output);
401 if (verbose && error_count)
402 fprintf(stderr, "*** %d errors\n", error_count);
404 fprintf(stderr, "*** FAILED: %s\n", afs_error_message(r));