3 * dumpscan - routines for scanning and manipulating AFS volume dumps
5 * Copyright (c) 1998 Carnegie Mellon University
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.
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.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes.
29 /* repair.c - Routines to generate a repaired dump */
31 #include <sys/types.h>
32 #include <netinet/in.h>
38 #include "dumpscan_errs.h"
43 #include <afs/prs_fs.h>
47 #define RV repair_verbose
49 extern afs_uint32
CopyVNodeData(XFILE
* OX
, XFILE
* X
, afs_uint32 size
);
50 extern afs_uint32
DumpVNodeData(XFILE
* OX
, char *buf
, afs_uint32 size
);
52 /* Try to dump a dump header. Generate missing fields, if neccessary */
54 repair_dumphdr_cb(afs_dump_header
* hdr
, XFILE
* X
, void *refcon
)
56 afs_uint32 field_mask
= hdr
->field_mask
;
59 if (!(field_mask
& F_DUMPHDR_VOLID
)) {
61 fprintf(stderr
, ">>> DUMP HEADER missing volume ID\n");
64 if (!(field_mask
& F_DUMPHDR_VOLNAME
)) {
66 fprintf(stderr
, ">>> DUMP HEADER missing volume name\n");
67 fprintf(stderr
, ">>> Will use RESTORED.%d\n", hdr
->volid
);
69 sprintf(volname
, "RESTORED.%d", hdr
->volid
);
70 hdr
->volname
= (unsigned char *) strdup(volname
);
73 hdr
->field_mask
|= F_DUMPHDR_VOLNAME
;
75 if (!(field_mask
& F_DUMPHDR_FROM
)) {
77 fprintf(stderr
, ">>> DUMP HEADER missing from time (using 0)\n");
79 hdr
->field_mask
|= F_DUMPHDR_FROM
;
81 if (!(field_mask
& F_DUMPHDR_TO
)) {
82 hdr
->to_date
= time(0);
84 fprintf(stderr
, ">>> DUMP HEADER missing from time (using %d)\n",
86 hdr
->field_mask
|= F_DUMPHDR_TO
;
89 return DumpDumpHeader(&repair_output
, hdr
);
93 /* Try to dump a volume header. Generate missing fields, if necessary */
95 repair_volhdr_cb(afs_vol_header
* hdr
, XFILE
* X
, void *refcon
)
97 afs_uint32 field_mask
= hdr
->field_mask
;
100 if (!(field_mask
& F_VOLHDR_VOLID
)) {
102 fprintf(stderr
, ">>> VOL HEADER missing volume ID\n");
105 if (!(field_mask
& F_VOLHDR_VOLVERS
)) {
107 fprintf(stderr
, ">>> VOL HEADER missing version (using 1)\n");
109 hdr
->field_mask
|= F_VOLHDR_VOLVERS
;
110 } else if (hdr
->volvers
!= 1) {
112 fprintf(stderr
, ">>> VOL HEADER bogus version %d (using 1)\n",
116 if (!(field_mask
& F_VOLHDR_VOLNAME
)) {
118 fprintf(stderr
, ">>> VOL HEADER missing volume name\n");
119 fprintf(stderr
, ">>> Will use RESTORED.%d\n", hdr
->volid
);
121 sprintf(volname
, "RESTORED.%d", hdr
->volid
);
122 hdr
->volname
= (unsigned char *)strdup(volname
);
125 hdr
->field_mask
|= F_VOLHDR_VOLNAME
;
127 if (!(field_mask
& F_VOLHDR_INSERV
)) {
130 ">>> VOL HEADER missing in-service flag (using 1)\n");
131 hdr
->flag_inservice
= 1;
132 hdr
->field_mask
|= F_VOLHDR_INSERV
;
134 if (!(field_mask
& F_VOLHDR_BLESSED
)) {
137 ">>> VOL HEADER missing blessed flag (using 1)\n");
138 hdr
->flag_blessed
= 1;
139 hdr
->field_mask
|= F_VOLHDR_BLESSED
;
141 if (!(field_mask
& F_VOLHDR_VOLUNIQ
)) {
143 fprintf(stderr
, ">>> VOL HEADER missing uniquifier (using 1)\n");
145 hdr
->field_mask
|= F_VOLHDR_VOLUNIQ
;
147 if (!(field_mask
& F_VOLHDR_VOLTYPE
)) {
149 fprintf(stderr
, ">>> VOL HEADER missing type (using 0: RW)\n");
151 hdr
->field_mask
|= F_VOLHDR_VOLTYPE
;
152 } else if (hdr
->voltype
< 0 || hdr
->voltype
> 2) {
154 fprintf(stderr
, ">>> VOL HEADER bogus type %d (using 0: RW)\n",
158 if (!(field_mask
& F_VOLHDR_PARENT
)) {
160 fprintf(stderr
, ">>> VOL HEADER parent (using %d)\n", hdr
->volid
);
161 hdr
->parent_volid
= hdr
->volid
;
162 hdr
->field_mask
|= F_VOLHDR_PARENT
;
164 if (!(field_mask
& F_VOLHDR_MAXQ
)) {
165 if (field_mask
& F_VOLHDR_DISKUSED
)
166 hdr
->maxquota
= hdr
->diskused
;
170 fprintf(stderr
, ">>> VOL HEADER missing max quota (using %d)\n",
172 hdr
->field_mask
|= F_VOLHDR_MAXQ
;
174 if (!(field_mask
& F_VOLHDR_DISKUSED
)) {
177 ">>> VOL HEADER missing disk used (using 2048)\n");
178 hdr
->diskused
= 2048;
179 hdr
->field_mask
|= F_VOLHDR_DISKUSED
;
181 if (!(field_mask
& F_VOLHDR_NFILES
)) {
183 fprintf(stderr
, ">>> VOL HEADER missing file count (using 1)\n");
185 hdr
->field_mask
|= F_VOLHDR_NFILES
;
187 if (!(field_mask
& F_VOLHDR_CREATE_DATE
)) {
188 hdr
->create_date
= 0;
189 if ((field_mask
& F_VOLHDR_ACCESS_DATE
)
190 && (!hdr
->create_date
|| hdr
->access_date
< hdr
->create_date
))
191 hdr
->create_date
= hdr
->access_date
;
192 if ((field_mask
& F_VOLHDR_UPDATE_DATE
)
193 && (!hdr
->create_date
|| hdr
->update_date
< hdr
->create_date
))
194 hdr
->create_date
= hdr
->update_date
;
195 if ((field_mask
& F_VOLHDR_BACKUP_DATE
)
196 && (!hdr
->create_date
|| hdr
->backup_date
< hdr
->create_date
))
197 hdr
->create_date
= hdr
->backup_date
;
200 fprintf(stderr
, ">>> VOL HEADER missing create date (using %d)\n",
202 hdr
->field_mask
|= F_VOLHDR_CREATE_DATE
;
204 if (!(field_mask
& F_VOLHDR_ACCESS_DATE
)) {
205 hdr
->access_date
= 0;
206 if ((field_mask
& F_VOLHDR_CREATE_DATE
)
207 && (!hdr
->access_date
|| hdr
->create_date
> hdr
->access_date
))
208 hdr
->access_date
= hdr
->create_date
;
209 if ((field_mask
& F_VOLHDR_UPDATE_DATE
)
210 && (!hdr
->access_date
|| hdr
->update_date
> hdr
->access_date
))
211 hdr
->access_date
= hdr
->update_date
;
212 if ((field_mask
& F_VOLHDR_BACKUP_DATE
)
213 && (!hdr
->access_date
|| hdr
->backup_date
> hdr
->access_date
))
214 hdr
->access_date
= hdr
->backup_date
;
217 fprintf(stderr
, ">>> VOL HEADER missing access date (using %d)\n",
219 hdr
->field_mask
|= F_VOLHDR_ACCESS_DATE
;
221 if (!(field_mask
& F_VOLHDR_UPDATE_DATE
)) {
222 hdr
->update_date
= 0;
223 if ((field_mask
& F_VOLHDR_CREATE_DATE
)
224 && (!hdr
->update_date
|| hdr
->create_date
> hdr
->update_date
))
225 hdr
->update_date
= hdr
->create_date
;
226 if ((field_mask
& F_VOLHDR_ACCESS_DATE
) && !hdr
->update_date
)
227 hdr
->update_date
= hdr
->access_date
;
228 if ((field_mask
& F_VOLHDR_BACKUP_DATE
) && !hdr
->update_date
)
229 hdr
->update_date
= hdr
->backup_date
;
232 fprintf(stderr
, ">>> VOL HEADER missing update date (using %d)\n",
234 hdr
->field_mask
|= F_VOLHDR_UPDATE_DATE
;
237 return DumpVolumeHeader(&repair_output
, hdr
);
241 /* Try to dump a vnode. Generate missing fields, if necessary */
243 repair_vnode_cb(afs_vnode
* v
, XFILE
* X
, void *refcon
)
245 afs_uint32 r
, field_mask
= v
->field_mask
;
247 if ((v
->vnode
& 1) && !field_mask
) {
249 fprintf(stderr
, ">>> VNODE %d is directory but has no fields?\n", v
->vnode
);
250 v
->type
= vDirectory
;
251 v
->field_mask
|= F_VNODE_TYPE
;
252 field_mask
= F_VNODE_TYPE
; /* Messy! */
254 if (field_mask
&& !(field_mask
& F_VNODE_TYPE
)) {
255 v
->type
= (v
->vnode
& 1) ? vDirectory
: vFile
;
257 fprintf(stderr
, ">>> VNODE %d missing type (using %d)\n",
259 v
->field_mask
|= F_VNODE_TYPE
;
261 if (field_mask
&& !(field_mask
& F_VNODE_NLINKS
)) {
263 fprintf(stderr
, ">>> VNODE %d missing link count (using 1)\n",
266 v
->field_mask
|= F_VNODE_NLINKS
;
268 if (field_mask
&& !(field_mask
& F_VNODE_PARENT
)) {
270 fprintf(stderr
, ">>> VNODE %d missing parent (using 1)\n",
273 v
->field_mask
|= F_VNODE_PARENT
;
275 if (field_mask
&& !(field_mask
& F_VNODE_DVERS
)) {
277 fprintf(stderr
, ">>> VNODE %d missing data version (using 1)\n",
280 v
->field_mask
|= F_VNODE_DVERS
;
282 if (field_mask
&& !(field_mask
& F_VNODE_AUTHOR
)) {
283 if (field_mask
& F_VNODE_OWNER
)
284 v
->author
= v
->owner
;
288 fprintf(stderr
, ">>> VNODE %d missing author (using %d)\n",
289 v
->vnode
, v
->author
);
290 v
->field_mask
|= F_VNODE_AUTHOR
;
292 if (field_mask
&& !(field_mask
& F_VNODE_OWNER
)) {
293 if (field_mask
& F_VNODE_AUTHOR
)
294 v
->owner
= v
->author
;
298 fprintf(stderr
, ">>> VNODE %d missing owner (using %d)\n",
300 v
->field_mask
|= F_VNODE_OWNER
;
302 if (field_mask
&& !(field_mask
& F_VNODE_MODE
)) {
303 v
->mode
= (v
->vnode
& 1) ? 0755 : 0644;
305 fprintf(stderr
, ">>> VNODE missing mode (using %d)\n", v
->mode
);
306 v
->field_mask
|= F_VNODE_MODE
;
308 if (field_mask
&& !(field_mask
& F_VNODE_CDATE
)) {
309 if (field_mask
& F_VNODE_SDATE
)
310 v
->client_date
= v
->server_date
;
315 fprintf(stderr
, ">>> VNODE %d missing client date (using %d)\n",
316 v
->vnode
, v
->client_date
);
317 v
->field_mask
|= F_VNODE_CDATE
;
319 if (field_mask
&& !(field_mask
& F_VNODE_SDATE
)) {
320 if (field_mask
& F_VNODE_CDATE
)
321 v
->server_date
= v
->client_date
;
326 fprintf(stderr
, ">>> VNODE %d missing server date (using %d)\n",
327 v
->vnode
, v
->server_date
);
328 v
->field_mask
|= F_VNODE_SDATE
;
330 if (field_mask
&& !(field_mask
& F_VNODE_SIZE
)) {
332 fprintf(stderr
, ">>> VNODE %d has no data size (using 0)\n", v
->vnode
);
334 v
->field_mask
|= F_VNODE_SIZE
;
336 if ((field_mask
& F_VNODE_DATA
) && !v
->size
) {
339 ">>> VNODE %d has data, but size == 0 (ignoring)\n",
341 v
->field_mask
&= ~F_VNODE_DATA
;
343 if (field_mask
&& v
->type
== vDirectory
&& !(field_mask
& F_VNODE_ACL
)) {
344 struct acl_accessList
*acl
= (struct acl_accessList
*)v
->acl
;
346 fprintf(stderr
, ">>> VNODE %d is directory but has no ACL\n", v
->vnode
);
347 fprintf(stderr
, ">>> Will generate default ACL\n");
349 memset(v
->acl
, 0, SIZEOF_LARGEDISKVNODE
- SIZEOF_SMALLDISKVNODE
);
350 acl
->size
= htonl(SIZEOF_LARGEDISKVNODE
- SIZEOF_SMALLDISKVNODE
);
351 acl
->version
= htonl(ACL_ACLVERSION
);
352 acl
->total
= htonl(v
->owner
? 0 : 1);
353 acl
->positive
= acl
->total
;
356 acl
->entries
[0].id
= htonl(v
->owner
);
357 acl
->entries
[0].rights
=
358 htonl((PRSFS_READ
| PRSFS_WRITE
| PRSFS_INSERT
| PRSFS_LOOKUP
359 | PRSFS_DELETE
| PRSFS_LOCK
| PRSFS_ADMINISTER
));
361 v
->field_mask
|= F_VNODE_ACL
;
364 r
= DumpVNode(&repair_output
, v
);
369 if ((r
= xfseek(X
, &v
->d_offset
)))
371 r
= CopyVNodeData(&repair_output
, X
, v
->size
);
372 } else if (v
->type
== vDirectory
) {
374 struct DirHeader
*dhp
= (struct DirHeader
*)&page
;
379 ">>> VNODE %d is directory but has no contents\n", v
->vnode
);
380 fprintf(stderr
, ">>> Will generate deafult directory entries\n");
382 memset(&page
, 0, sizeof(page
));
384 /* Page and Directory Headers */
385 page
.header
.tag
= htons(1234);
386 page
.header
.freecount
= (EPP
- DHE
- 3);
387 page
.header
.freebitmap
[0] = 0xff;
388 page
.header
.freebitmap
[1] = 0x7f;
389 dhp
->alloMap
[0] = EPP
- DHE
- 3;
390 for (i
= 1; i
< MAXPAGES
; i
++)
391 dhp
->alloMap
[i
] = EPP
;
394 page
.entry
[DHE
+ 1].flag
= FFIRST
;
395 page
.entry
[DHE
+ 1].length
= 1;
396 page
.entry
[DHE
+ 1].vnode
= v
->vnode
;
397 page
.entry
[DHE
+ 1].vunique
= v
->vuniq
;
398 strcpy(page
.entry
[DHE
+ 1].name
, ".");
399 dhp
->hashTable
[0x2e] = DHE
+ 1;
402 page
.entry
[DHE
+ 2].flag
= FFIRST
;
403 page
.entry
[DHE
+ 2].length
= 1;
404 page
.entry
[DHE
+ 2].vnode
= v
->parent
;
405 page
.entry
[DHE
+ 2].vunique
= 1; /* Can't have everything! */
406 strcpy(page
.entry
[DHE
+ 2].name
, "..");
407 dhp
->hashTable
[0x44] = DHE
+ 2;
409 r
= DumpVNodeData(&repair_output
, (char *)&page
, 2048);
410 } else if (field_mask
) {
411 /* We wrote out attributes, so we should also write the 0-length data */
412 r
= DumpVNodeData(&repair_output
, "", 0);