Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / vfsck / pass1.c
CommitLineData
805e021f
CE
1/*
2 * Copyright (c) 1980, 1986 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18#include <afsconfig.h>
19#include <afs/param.h>
20
21#include <roken.h>
22
23#include <ctype.h>
24
25#define VICE
26#ifdef AFS_OSF_ENV
27#include <sys/vnode.h>
28#include <sys/mount.h>
29#include <ufs/inode.h>
30#include <ufs/fs.h>
31#define _BSD
32#define _KERNEL
33#include <ufs/dir.h>
34#undef _KERNEL
35#undef _BSD
36#else /* AFS_OSF_ENV */
37#ifdef AFS_VFSINCL_ENV
38#include <sys/vnode.h>
39#ifdef AFS_SUN5_ENV
40#include <sys/fs/ufs_inode.h>
41#include <sys/fs/ufs_fs.h>
42#define _KERNEL
43#include <sys/fs/ufs_fsdir.h>
44#undef _KERNEL
45#include <sys/fs/ufs_mount.h>
46#else
47#include <ufs/inode.h>
48#include <ufs/fs.h>
49#endif
50#else /* AFS_VFSINCL_ENV */
51#include <sys/inode.h>
52#ifdef AFS_HPUX_ENV
53extern int ge_danger;
54#define DUX
55#define LONGFILENAMES 1
56#include <sys/sysmacros.h>
57#include <sys/ino.h>
58#endif
59#include <sys/fs.h>
60#endif /* AFS_VFSINCL_ENV */
61#endif /* AFS_OSF_ENV */
62
63#include <afs/osi_inode.h>
64#include "fsck.h"
65
66static daddr_t badblk;
67static daddr_t dupblk;
68int pass1check();
69static int oldreported;
70
71pass1()
72{
73 int c, i, j;
74 struct dinode *dp;
75 struct zlncnt *zlnp;
76 int ndb, cgd;
77 struct inodesc idesc;
78 ino_t inumber;
79
80 /*
81 * Set file system reserved blocks in used block map.
82 */
83 for (c = 0; c < sblock.fs_ncg; c++) {
84 cgd = cgdmin(&sblock, c);
85 if (c == 0) {
86 i = cgbase(&sblock, c);
87 cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
88 } else
89 i = cgsblock(&sblock, c);
90 for (; i < cgd; i++)
91 setbmap(i);
92 }
93 /*
94 * Find all allocated blocks.
95 */
96 memset(&idesc, 0, sizeof(struct inodesc));
97 idesc.id_type = ADDR;
98 idesc.id_func = pass1check;
99 inumber = 0;
100 n_files = n_blks = 0;
101#ifdef VICE
102 nViceFiles = 0;
103#endif /* VICE */
104 for (c = 0; c < sblock.fs_ncg; c++) {
105 for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
106 if (inumber < ROOTINO)
107 continue;
108 dp = ginode(inumber);
109 if ((dp->di_mode & IFMT) == 0) {
110 if (memcmp
111 ((char *)dp->di_db, (char *)zino.di_db,
112 NDADDR * sizeof(daddr_t))
113 || memcmp((char *)dp->di_ib, (char *)zino.di_ib,
114 NIADDR * sizeof(daddr_t)) ||
115#if defined(ACLS) && defined(AFS_HPUX_ENV)
116 dp->di_mode || dp->di_size || dp->di_contin) {
117 if (dp->di_contin != 0)
118 pwarn("UNALLOCATED INODE HAS BAD ic_contin VALUE %d",
119 dp->di_contin);
120 else
121#else
122 dp->di_mode || dp->di_size) {
123#endif
124
125 pfatal("PARTIALLY ALLOCATED INODE I=%u", inumber);
126 if (reply("CLEAR") == 1) {
127#ifdef VICE
128 zapino(dp);
129#else /* VICE */
130 clearinode(dp);
131#endif /* VICE */
132 inodirty();
133 }
134 }
135 statemap[inumber] = USTATE;
136 continue;
137 }
138 lastino = inumber;
139#if defined(ACLS) && defined(AFS_HPUX_ENV)
140 /*
141 * Don't check blocks and sizes of
142 * continuation inodes
143 */
144 if (CONT) {
145 statemap[inumber] = CSTATE;
146 lncntp[inumber] = dp->di_nlink;
147 n_cont++;
148 continue;
149 }
150#endif /* ACLS */
151#if defined(AFS_SUN5_ENV)
152 if (dp->di_size < 0 || dp->di_size > (UOFF_T) UFS_MAXOFFSET_T) {
153 if (debug)
154 printf("bad size %llu:", dp->di_size);
155 goto unknown;
156 }
157#else
158 if (dp->di_size < 0 || dp->di_size + sblock.fs_bsize - 1 < 0) {
159 if (debug)
160 printf("bad size %d:", dp->di_size);
161 goto unknown;
162 }
163#endif
164#if defined(AFS_HPUX_ENV)
165 /* initialize all R/W activities of FIFO file */
166 /* make sure FIFO is empty (everything is 0) */
167 if ((dp->di_mode & IFMT) == IFIFO
168 && (dp->di_frcnt != 0 || dp->di_fwcnt != 0)) {
169 if (!qflag)
170 pwarn("NON-ZERO READER/WRITER COUNT(S) ON PIPE I=%u",
171 inumber);
172 if (preen && !qflag)
173 printf(" (CORRECTED)\n");
174 else if (!qflag) {
175 if (reply("CORRECT") == 0)
176 goto no_reset;
177 }
178 dp->di_size = 0;
179 dp->di_frptr = 0;
180 dp->di_fwptr = 0;
181 dp->di_frcnt = 0;
182 dp->di_fwcnt = 0;
183 dp->di_fflag = 0;
184 dp->di_fifosize = 0;
185 inodirty();
186 ndb = 0;
187 for (j = ndb; j < NDADDR; j++)
188 dp->di_db[j] = 0;
189 }
190#ifdef IC_FASTLINK
191 else if (FASTLNK) {
192 /*
193 * Fast symlink -- verify that the size is valid and that the length
194 * of the path is correct.
195 */
196
197 if (dp->di_size >= MAX_FASTLINK_SIZE) {
198 if (debug)
199 printf("bad fastlink size %d:", dp->di_size);
200 goto unknown;
201 }
202 dp->di_symlink[MAX_FASTLINK_SIZE - 1] = '\0';
203 if (strlen(dp->di_symlink) != dp->di_size) {
204 int len = strlen(dp->di_symlink);
205 pwarn("BAD SYMLINK SIZE, SHOULD BE %d: size = %d", len,
206 dp->di_size);
207 if (preen)
208 printf(" (CORRECTED)\n");
209 else {
210 printf("\n");
211 pinode(inumber);
212 if (reply("CORRECT") == 0)
213 continue;
214 }
215 dp->di_size = len;
216 inodirty();
217 }
218 goto ignore_direct_block_check;
219 }
220#endif /* IC_FASTLINK */
221#endif
222 no_reset:
223 if (!preen && (dp->di_mode & IFMT) == IFMT
224 && reply("HOLD BAD BLOCK") == 1) {
225 dp->di_size = sblock.fs_fsize;
226 dp->di_mode = IFREG | 0600;
227 inodirty();
228 }
229 ndb = howmany(dp->di_size, (UOFF_T) sblock.fs_bsize);
230#ifdef AFS_SUN5_ENV
231 if (dp->di_oeftflag == oEFT_MAGIC) {
232 dp->di_oeftflag = 0; /* XXX migration aid */
233 inodirty();
234 }
235#endif
236
237 if (ndb < 0) {
238 if (debug)
239#if defined(AFS_SUN5_ENV)
240 printf("bad size %" AFS_INT64_FMT " ndb %d:",
241#else
242 printf("bad size %d ndb %d:",
243#endif
244 dp->di_size, ndb);
245 goto unknown;
246 }
247 if ((dp->di_mode & IFMT) == IFBLK
248 || (dp->di_mode & IFMT) == IFCHR)
249 ndb++;
250#ifdef AFS_OSF_ENV
251 if ((dp->di_flags & IC_FASTLINK) == 0) {
252#endif /* AFS_OSF_ENV */
253 for (j = ndb; j < NDADDR; j++) {
254#if defined(AFS_HPUX_ENV) && (defined(DUX) || defined(CNODE_DEV))
255 /*
256 * DUX uses db[2] on cnode-specific
257 * device files, so skip 'em
258 */
259 if (j == 2 && SPECIAL)
260 continue;
261#endif
262 if (dp->di_db[j] != 0) {
263 if (debug)
264 printf("bad direct addr: %d\n", dp->di_db[j]);
265 goto unknown;
266 }
267 }
268 for (j = 0, ndb -= NDADDR; ndb > 0; j++)
269 ndb /= NINDIR(&sblock);
270 for (; j < NIADDR; j++)
271 if (dp->di_ib[j] != 0) {
272#ifdef AFS_HPUX_ENV
273 if ((dp->di_mode & IFMT) != IFIFO) {
274#endif
275 if (debug)
276 printf("bad indirect addr: %d\n",
277 dp->di_ib[j]);
278 goto unknown;
279#ifdef AFS_HPUX_ENV
280 }
281#endif
282
283 }
284#if defined(AFS_HPUX_ENV)
285 ignore_direct_block_check:
286#endif
287#ifdef AFS_OSF_ENV
288 }
289#endif /* AFS_OSF_ENV */
290 if (ftypeok(dp) == 0)
291 goto unknown;
292 n_files++;
293 lncntp[inumber] = dp->di_nlink;
294 if (dp->di_nlink <= 0) {
295 zlnp = malloc(sizeof *zlnp);
296 if (zlnp == NULL) {
297 pfatal("LINK COUNT TABLE OVERFLOW");
298 if (reply("CONTINUE") == 0)
299 errexit("");
300 } else {
301 zlnp->zlncnt = inumber;
302 zlnp->next = zlnhead;
303 zlnhead = zlnp;
304 }
305 }
306#if defined(AFS_SUN5_ENV)
307 if (OLDVICEINODE) {
308 if (yflag) {
309 if (!oldreported) {
310 printf
311 ("This vicep partition seems to contain pre Sol2.6 AFS inodes\n");
312 printf
313 ("You should run the AFS file conversion utility before installing Sol 2.6\n");
314 printf("Continuing anyway.\n");
315 oldreported++;
316 }
317 } else {
318 /* This looks like a sol 2.5 AFS inode */
319 printf
320 ("This vicep partition seems to contain pre Sol2.6 AFS inodes\n");
321 printf
322 ("You should run the AFS file conversion utility before installing Sol 2.6\n");
323 exit(100); /* unique return code? */
324 }
325 }
326#endif
327 statemap[inumber] =
328#ifdef VICE
329 (dp->di_mode & IFMT) ==
330 IFDIR ? DSTATE : (VICEINODE ? VSTATE : FSTATE);
331#else /* VICE */
332 (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
333#endif /* VICE */
334#if defined(ACLS) && defined(AFS_HPUX_ENV)
335 /*
336 * keep track of associated contin inodes
337 */
338 if (dp->di_contin != 0)
339 statemap[inumber] |= HASCINODE;
340#endif /* ACLS */
341 badblk = dupblk = 0;
342 idesc.id_number = inumber;
343 idesc.id_entryno = 0;
344#ifdef AFS_SUN5_ENV
345 idesc.id_fix = DONTKNOW;
346#endif
347 (void)ckinode(dp, &idesc);
348
349 idesc.id_entryno *= btodb(sblock.fs_fsize);
350
351 if (dp->di_blocks != idesc.id_entryno) {
352 pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)",
353 inumber, dp->di_blocks, idesc.id_entryno);
354 if (preen)
355 printf(" (CORRECTED)\n");
356 else if (reply("CORRECT") == 0)
357 continue;
358#ifdef AFS_SUN5_ENV
359 dp = ginode(inumber);
360#endif
361 dp->di_blocks = idesc.id_entryno;
362 inodirty();
363 }
364#ifdef AFS_SUN5_ENV
365 if ((dp->di_mode & IFMT) == IFDIR)
366 if (dp->di_blocks == 0)
367 statemap[inumber] = DCLEAR;
368#endif
369 continue;
370 unknown:
371 pfatal("UNKNOWN FILE TYPE I=%u", inumber);
372#ifdef AFS_SUN5_ENV
373 if ((dp->di_mode & IFMT) == IFDIR) {
374 statemap[inumber] = DCLEAR;
375#ifdef notdef
376 cacheino(dp, inumber);
377#endif
378 } else
379#endif
380 statemap[inumber] = FCLEAR;
381 if (reply("CLEAR") == 1) {
382 statemap[inumber] = USTATE;
383#ifdef VICE
384 zapino(dp);
385#else /* VICE */
386 clearinode(dp);
387#endif /* VICE */
388 inodirty();
389 }
390 }
391 }
392}
393
394pass1check(idesc)
395 struct inodesc *idesc;
396{
397 int res = KEEPON;
398 int anyout, nfrags;
399 daddr_t blkno = idesc->id_blkno;
400 struct dups *dlp;
401 struct dups *new;
402
403 if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
404 blkerror(idesc->id_number, "BAD", blkno);
405 if (++badblk >= MAXBAD) {
406 pwarn("EXCESSIVE BAD BLKS I=%u", idesc->id_number);
407 if (preen)
408 printf(" (SKIPPING)\n");
409 else if (reply("CONTINUE") == 0)
410 errexit("");
411#ifdef AFS_HPUX_ENV
412 ge_danger = 1;
413#endif
414 return (STOP);
415 }
416 }
417 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
418 if (anyout && chkrange(blkno, 1)) {
419 res = SKIP;
420 } else if (!testbmap(blkno)) {
421 n_blks++;
422 setbmap(blkno);
423 } else {
424 blkerror(idesc->id_number, "DUP", blkno);
425 if (++dupblk >= MAXDUP) {
426 pwarn("EXCESSIVE DUP BLKS I=%u", idesc->id_number);
427 if (preen)
428 printf(" (SKIPPING)\n");
429 else if (reply("CONTINUE") == 0)
430 errexit("");
431#ifdef AFS_HPUX_ENV
432 ge_danger = 1;
433#endif
434 return (STOP);
435 }
436 new = malloc(sizeof(struct dups));
437 if (new == NULL) {
438 pfatal("DUP TABLE OVERFLOW.");
439 if (reply("CONTINUE") == 0)
440 errexit("");
441 return (STOP);
442 }
443 new->dup = blkno;
444 if (muldup == 0) {
445 duplist = muldup = new;
446 new->next = 0;
447 } else {
448 new->next = muldup->next;
449 muldup->next = new;
450 }
451 for (dlp = duplist; dlp != muldup; dlp = dlp->next)
452 if (dlp->dup == blkno)
453 break;
454 if (dlp == muldup && dlp->dup != blkno)
455 muldup = new;
456 }
457 /*
458 * count the number of blocks found in id_entryno
459 */
460 idesc->id_entryno++;
461 }
462 return (res);
463}