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
));