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 *)malloc(strlen(volname) + 1);
73 strcpy((char *)hdr->volname, volname);
74 hdr->field_mask |= F_DUMPHDR_VOLNAME;
76 if (!(field_mask & F_DUMPHDR_FROM)) {
78 fprintf(stderr, ">>> DUMP HEADER missing from time (using 0)\n");
80 hdr->field_mask |= F_DUMPHDR_FROM;
82 if (!(field_mask & F_DUMPHDR_TO)) {
83 hdr->to_date = time(0);
85 fprintf(stderr, ">>> DUMP HEADER missing from time (using %d)\n",
87 hdr->field_mask |= F_DUMPHDR_TO;
90 return DumpDumpHeader(&repair_output, hdr);
94 /* Try to dump a volume header. Generate missing fields, if necessary */
96 repair_volhdr_cb(afs_vol_header * hdr, XFILE * X, void *refcon)
98 afs_uint32 field_mask = hdr->field_mask;
101 if (!(field_mask & F_VOLHDR_VOLID)) {
103 fprintf(stderr, ">>> VOL HEADER missing volume ID\n");
106 if (!(field_mask & F_VOLHDR_VOLVERS)) {
108 fprintf(stderr, ">>> VOL HEADER missing version (using 1)\n");
110 hdr->field_mask |= F_VOLHDR_VOLVERS;
111 } else if (hdr->volvers != 1) {
113 fprintf(stderr, ">>> VOL HEADER bogus version %d (using 1)\n",
117 if (!(field_mask & F_VOLHDR_VOLNAME)) {
119 fprintf(stderr, ">>> VOL HEADER missing volume name\n");
120 fprintf(stderr, ">>> Will use RESTORED.%d\n", hdr->volid);
122 sprintf(volname, "RESTORED.%d", hdr->volid);
123 hdr->volname = (unsigned char *)malloc(strlen(volname) + 1);
126 strcpy((char *)hdr->volname, volname);
127 hdr->field_mask |= F_VOLHDR_VOLNAME;
129 if (!(field_mask & F_VOLHDR_INSERV)) {
132 ">>> VOL HEADER missing in-service flag (using 1)\n");
133 hdr->flag_inservice = 1;
134 hdr->field_mask |= F_VOLHDR_INSERV;
136 if (!(field_mask & F_VOLHDR_BLESSED)) {
139 ">>> VOL HEADER missing blessed flag (using 1)\n");
140 hdr->flag_blessed = 1;
141 hdr->field_mask |= F_VOLHDR_BLESSED;
143 if (!(field_mask & F_VOLHDR_VOLUNIQ)) {
145 fprintf(stderr, ">>> VOL HEADER missing uniquifier (using 1)\n");
147 hdr->field_mask |= F_VOLHDR_VOLUNIQ;
149 if (!(field_mask & F_VOLHDR_VOLTYPE)) {
151 fprintf(stderr, ">>> VOL HEADER missing type (using 0: RW)\n");
153 hdr->field_mask |= F_VOLHDR_VOLTYPE;
154 } else if (hdr->voltype < 0 || hdr->voltype > 2) {
156 fprintf(stderr, ">>> VOL HEADER bogus type %d (using 0: RW)\n",
160 if (!(field_mask & F_VOLHDR_PARENT)) {
162 fprintf(stderr, ">>> VOL HEADER parent (using %d)\n", hdr->volid);
163 hdr->parent_volid = hdr->volid;
164 hdr->field_mask |= F_VOLHDR_PARENT;
166 if (!(field_mask & F_VOLHDR_MAXQ)) {
167 if (field_mask & F_VOLHDR_DISKUSED)
168 hdr->maxquota = hdr->diskused;
172 fprintf(stderr, ">>> VOL HEADER missing max quota (using %d)\n",
174 hdr->field_mask |= F_VOLHDR_MAXQ;
176 if (!(field_mask & F_VOLHDR_DISKUSED)) {
179 ">>> VOL HEADER missing disk used (using 2048)\n");
180 hdr->diskused = 2048;
181 hdr->field_mask |= F_VOLHDR_DISKUSED;
183 if (!(field_mask & F_VOLHDR_NFILES)) {
185 fprintf(stderr, ">>> VOL HEADER missing file count (using 1)\n");
187 hdr->field_mask |= F_VOLHDR_NFILES;
189 if (!(field_mask & F_VOLHDR_CREATE_DATE)) {
190 hdr->create_date = 0;
191 if ((field_mask & F_VOLHDR_ACCESS_DATE)
192 && (!hdr->create_date || hdr->access_date < hdr->create_date))
193 hdr->create_date = hdr->access_date;
194 if ((field_mask & F_VOLHDR_UPDATE_DATE)
195 && (!hdr->create_date || hdr->update_date < hdr->create_date))
196 hdr->create_date = hdr->update_date;
197 if ((field_mask & F_VOLHDR_BACKUP_DATE)
198 && (!hdr->create_date || hdr->backup_date < hdr->create_date))
199 hdr->create_date = hdr->backup_date;
202 fprintf(stderr, ">>> VOL HEADER missing create date (using %d)\n",
204 hdr->field_mask |= F_VOLHDR_CREATE_DATE;
206 if (!(field_mask & F_VOLHDR_ACCESS_DATE)) {
207 hdr->access_date = 0;
208 if ((field_mask & F_VOLHDR_CREATE_DATE)
209 && (!hdr->access_date || hdr->create_date > hdr->access_date))
210 hdr->access_date = hdr->create_date;
211 if ((field_mask & F_VOLHDR_UPDATE_DATE)
212 && (!hdr->access_date || hdr->update_date > hdr->access_date))
213 hdr->access_date = hdr->update_date;
214 if ((field_mask & F_VOLHDR_BACKUP_DATE)
215 && (!hdr->access_date || hdr->backup_date > hdr->access_date))
216 hdr->access_date = hdr->backup_date;
219 fprintf(stderr, ">>> VOL HEADER missing access date (using %d)\n",
221 hdr->field_mask |= F_VOLHDR_ACCESS_DATE;
223 if (!(field_mask & F_VOLHDR_UPDATE_DATE)) {
224 hdr->update_date = 0;
225 if ((field_mask & F_VOLHDR_CREATE_DATE)
226 && (!hdr->update_date || hdr->create_date > hdr->update_date))
227 hdr->update_date = hdr->create_date;
228 if ((field_mask & F_VOLHDR_ACCESS_DATE) && !hdr->update_date)
229 hdr->update_date = hdr->access_date;
230 if ((field_mask & F_VOLHDR_BACKUP_DATE) && !hdr->update_date)
231 hdr->update_date = hdr->backup_date;
234 fprintf(stderr, ">>> VOL HEADER missing update date (using %d)\n",
236 hdr->field_mask |= F_VOLHDR_UPDATE_DATE;
239 return DumpVolumeHeader(&repair_output, hdr);
243 /* Try to dump a vnode. Generate missing fields, if necessary */
245 repair_vnode_cb(afs_vnode * v, XFILE * X, void *refcon)
247 afs_uint32 r, field_mask = v->field_mask;
249 if ((v->vnode & 1) && !field_mask) {
251 fprintf(stderr, ">>> VNODE %d is directory but has no fields?\n", v->vnode);
252 v->type = vDirectory;
253 v->field_mask |= F_VNODE_TYPE;
254 field_mask = F_VNODE_TYPE; /* Messy! */
256 if (field_mask && !(field_mask & F_VNODE_TYPE)) {
257 v->type = (v->vnode & 1) ? vDirectory : vFile;
259 fprintf(stderr, ">>> VNODE %d missing type (using %d)\n",
261 v->field_mask |= F_VNODE_TYPE;
263 if (field_mask && !(field_mask & F_VNODE_NLINKS)) {
265 fprintf(stderr, ">>> VNODE %d missing link count (using 1)\n",
268 v->field_mask |= F_VNODE_NLINKS;
270 if (field_mask && !(field_mask & F_VNODE_PARENT)) {
272 fprintf(stderr, ">>> VNODE %d missing parent (using 1)\n",
275 v->field_mask |= F_VNODE_PARENT;
277 if (field_mask && !(field_mask & F_VNODE_DVERS)) {
279 fprintf(stderr, ">>> VNODE %d missing data version (using 1)\n",
282 v->field_mask |= F_VNODE_DVERS;
284 if (field_mask && !(field_mask & F_VNODE_AUTHOR)) {
285 if (field_mask & F_VNODE_OWNER)
286 v->author = v->owner;
290 fprintf(stderr, ">>> VNODE %d missing author (using %d)\n",
291 v->vnode, v->author);
292 v->field_mask |= F_VNODE_AUTHOR;
294 if (field_mask && !(field_mask & F_VNODE_OWNER)) {
295 if (field_mask & F_VNODE_AUTHOR)
296 v->owner = v->author;
300 fprintf(stderr, ">>> VNODE %d missing owner (using %d)\n",
302 v->field_mask |= F_VNODE_OWNER;
304 if (field_mask && !(field_mask & F_VNODE_MODE)) {
305 v->mode = (v->vnode & 1) ? 0755 : 0644;
307 fprintf(stderr, ">>> VNODE missing mode (using %d)\n", v->mode);
308 v->field_mask |= F_VNODE_MODE;
310 if (field_mask && !(field_mask & F_VNODE_CDATE)) {
311 if (field_mask & F_VNODE_SDATE)
312 v->client_date = v->server_date;
317 fprintf(stderr, ">>> VNODE %d missing client date (using %d)\n",
318 v->vnode, v->client_date);
319 v->field_mask |= F_VNODE_CDATE;
321 if (field_mask && !(field_mask & F_VNODE_SDATE)) {
322 if (field_mask & F_VNODE_CDATE)
323 v->server_date = v->client_date;
328 fprintf(stderr, ">>> VNODE %d missing server date (using %d)\n",
329 v->vnode, v->server_date);
330 v->field_mask |= F_VNODE_SDATE;
332 if (field_mask && !(field_mask & F_VNODE_SIZE)) {
334 fprintf(stderr, ">>> VNODE %d has no data size (using 0)\n", v->vnode);
336 v->field_mask |= F_VNODE_SIZE;
338 if ((field_mask & F_VNODE_DATA) && !v->size) {
341 ">>> VNODE %d has data, but size == 0 (ignoring)\n",
343 v->field_mask &= ~F_VNODE_DATA;
345 if (field_mask && v->type == vDirectory && !(field_mask & F_VNODE_ACL)) {
346 struct acl_accessList *acl = (struct acl_accessList *)v->acl;
348 fprintf(stderr, ">>> VNODE %d is directory but has no ACL\n", v->vnode);
349 fprintf(stderr, ">>> Will generate default ACL\n");
351 memset(v->acl, 0, SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE);
352 acl->size = htonl(SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE);
353 acl->version = htonl(ACL_ACLVERSION);
354 acl->total = htonl(v->owner ? 0 : 1);
355 acl->positive = acl->total;
358 acl->entries[0].id = htonl(v->owner);
359 acl->entries[0].rights =
360 htonl((PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP
361 | PRSFS_DELETE | PRSFS_LOCK | PRSFS_ADMINISTER));
363 v->field_mask |= F_VNODE_ACL;
366 r = DumpVNode(&repair_output, v);
371 if ((r = xfseek(X, &v->d_offset)))
373 r = CopyVNodeData(&repair_output, X, v->size);
374 } else if (v->type == vDirectory) {
376 struct DirHeader *dhp = (struct DirHeader *)&page;
381 ">>> VNODE %d is directory but has no contents\n", v->vnode);
382 fprintf(stderr, ">>> Will generate deafult directory entries\n");
384 memset(&page, 0, sizeof(page));
386 /* Page and Directory Headers */
387 page.header.tag = htons(1234);
388 page.header.freecount = (EPP - DHE - 3);
389 page.header.freebitmap[0] = 0xff;
390 page.header.freebitmap[1] = 0x7f;
391 dhp->alloMap[0] = EPP - DHE - 3;
392 for (i = 1; i < MAXPAGES; i++)
393 dhp->alloMap[i] = EPP;
396 page.entry[DHE + 1].flag = FFIRST;
397 page.entry[DHE + 1].length = 1;
398 page.entry[DHE + 1].vnode = v->vnode;
399 page.entry[DHE + 1].vunique = v->vuniq;
400 strcpy(page.entry[DHE + 1].name, ".");
401 dhp->hashTable[0x2e] = DHE + 1;
404 page.entry[DHE + 2].flag = FFIRST;
405 page.entry[DHE + 2].length = 1;
406 page.entry[DHE + 2].vnode = v->parent;
407 page.entry[DHE + 2].vunique = 1; /* Can't have everything! */
408 strcpy(page.entry[DHE + 2].name, "..");
409 dhp->hashTable[0x44] = DHE + 2;
411 r = DumpVNodeData(&repair_output, (char *)&page, 2048);
412 } else if (field_mask) {
413 /* We wrote out attributes, so we should also write the 0-length data */
414 r = DumpVNodeData(&repair_output, "", 0);