afsconfig-and-rcsid-all-around-20010705
[openafs.git] / src / vfsck / pass1.c
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 <afs/param.h>
19 #include <afsconfig.h>
20
21 RCSID("$Header$");
22
23 #define VICE
24 #include <sys/param.h>
25 #include <sys/time.h>
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 #include <stdio.h>
37 #else   /* AFS_OSF_ENV */
38 #ifdef AFS_VFSINCL_ENV
39 #include <sys/vnode.h>
40 #ifdef    AFS_SUN5_ENV
41 #include <stdio.h>
42 #include <unistd.h>
43 #include <sys/fs/ufs_inode.h>
44 #include <sys/fs/ufs_fs.h>
45 #define _KERNEL
46 #include <sys/fs/ufs_fsdir.h>
47 #undef _KERNEL
48 #include <sys/fs/ufs_mount.h>
49 #else
50 #include <ufs/inode.h>
51 #include <ufs/fs.h>
52 #endif
53 #else /* AFS_VFSINCL_ENV */
54 #include <sys/inode.h>
55 #ifdef  AFS_HPUX_ENV
56 extern int ge_danger;
57 #define DUX
58 #include <ctype.h>
59 #define LONGFILENAMES   1
60 #include <sys/sysmacros.h>
61 #include <sys/ino.h>
62 #endif
63 #include <sys/fs.h>
64 #endif /* AFS_VFSINCL_ENV */
65 #endif  /* AFS_OSF_ENV */
66
67 #include <afs/osi_inode.h>
68 #include "fsck.h"
69
70 static daddr_t badblk;
71 static daddr_t dupblk;
72 int pass1check();
73
74 pass1()
75 {
76         register int c, i, j;
77         register struct dinode *dp;
78         struct zlncnt *zlnp;
79         int ndb, cgd;
80         struct inodesc idesc;
81         ino_t inumber;
82
83         /*
84          * Set file system reserved blocks in used block map.
85          */
86         for (c = 0; c < sblock.fs_ncg; c++) {
87                 cgd = cgdmin(&sblock, c);
88                 if (c == 0) {
89                         i = cgbase(&sblock, c);
90                         cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
91                 } else
92                         i = cgsblock(&sblock, c);
93                 for (; i < cgd; i++)
94                         setbmap(i);
95         }
96         /*
97          * Find all allocated blocks.
98          */
99         bzero((char *)&idesc, sizeof(struct inodesc));
100         idesc.id_type = ADDR;
101         idesc.id_func = pass1check;
102         inumber = 0;
103         n_files = n_blks = 0;
104 #ifdef VICE
105         nViceFiles = 0;
106 #endif /* VICE */
107         for (c = 0; c < sblock.fs_ncg; c++) {
108                 for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
109                         if (inumber < ROOTINO)
110                                 continue;
111                         dp = ginode(inumber);
112                         if ((dp->di_mode & IFMT) == 0) {
113                                 if (bcmp((char *)dp->di_db, (char *)zino.di_db,
114                                         NDADDR * sizeof(daddr_t)) ||
115                                     bcmp((char *)dp->di_ib, (char *)zino.di_ib,
116                                         NIADDR * sizeof(daddr_t)) ||
117 #if defined(ACLS) && defined(AFS_HPUX_ENV)
118                                     dp->di_mode || dp->di_size || dp->di_contin) {
119                                             if (dp->di_contin != 0) 
120                                                 pwarn("UNALLOCATED INODE HAS BAD ic_contin VALUE %d", dp->di_contin);
121                                             else
122 #else
123                                     dp->di_mode || dp->di_size) {
124 #endif
125
126                                         pfatal("PARTIALLY ALLOCATED INODE I=%u", inumber);
127                                         if (reply("CLEAR") == 1) {
128 #ifdef VICE
129                                                 zapino(dp);
130 #else /* VICE */
131                                                 clearinode(dp);
132 #endif /* VICE */
133                                                 inodirty();
134                                         }
135                                 }
136                                 statemap[inumber] = USTATE;
137                                 continue;
138                             }
139                         lastino = inumber;
140 #if defined(ACLS) && defined(AFS_HPUX_ENV)
141                         /* 
142                          * Don't check blocks and sizes of  
143                          * continuation inodes 
144                          */
145                         if (CONT) {
146                             statemap[inumber] = CSTATE;
147                             lncntp[inumber] = dp->di_nlink;
148                             n_cont++;
149                             continue;
150                         } 
151 #endif /* ACLS */
152 #if     defined(AFS_SUN56_ENV)
153                         if (dp->di_size < 0 || 
154                             dp->di_size > (UOFF_T)UFS_MAXOFFSET_T) {
155                                 if (debug)
156                                         printf("bad size %llu:", dp->di_size);
157                                 goto unknown;
158                         }
159 #else
160                         if (dp->di_size < 0 ||
161                             dp->di_size + sblock.fs_bsize - 1 < 0) {
162                                 if (debug)
163                                         printf("bad size %d:", dp->di_size);
164                                 goto unknown;
165                         }
166 #endif
167 #if defined(AFS_HPUX_ENV)
168                         /* initialize all R/W activities of FIFO file */
169                         /* make sure FIFO is empty (everything is 0) */
170                         if ((dp->di_mode & IFMT) == IFIFO && (dp->di_frcnt!=0 || dp->di_fwcnt!=0)) {
171                             if (!qflag)
172                                 pwarn("NON-ZERO READER/WRITER COUNT(S) ON PIPE I=%u",inumber);
173                             if (preen && !qflag)
174                                 printf(" (CORRECTED)\n");
175                             else if (!qflag) {
176                                 if (reply("CORRECT") == 0)
177                                     goto no_reset;
178                             }
179                             dp->di_size = 0;
180                             dp->di_frptr = 0;
181                             dp->di_fwptr = 0;
182                             dp->di_frcnt = 0;
183                             dp->di_fwcnt = 0;
184                             dp->di_fflag = 0;
185                             dp->di_fifosize = 0;
186                             inodirty();
187                             ndb = 0;
188                             for (j = ndb; j < NDADDR; j++)
189                                 dp->di_db[j] = 0;
190                         } 
191 #ifdef IC_FASTLINK
192                         else if (FASTLNK) {
193                             /*
194                              * Fast symlink -- verify that the size is valid and that the length
195                              * of the path is correct.
196                              */
197
198                             if (dp->di_size >= MAX_FASTLINK_SIZE) {
199                                 if (debug)
200                                     printf("bad fastlink size %d:", dp->di_size);
201                                 goto unknown;
202                             }
203                             dp->di_symlink[MAX_FASTLINK_SIZE-1] = '\0';
204                             if (strlen(dp->di_symlink) != dp->di_size) {
205                                 int len = strlen(dp->di_symlink);
206                                 pwarn("BAD SYMLINK SIZE, SHOULD BE %d: size = %d", len, 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_SUN56_ENV)
240                                         printf("bad size %lld 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",
265                                                         dp->di_db[j]);
266                                         goto unknown;
267                                 }
268                             }
269                         for (j = 0, ndb -= NDADDR; ndb > 0; j++)
270                                 ndb /= NINDIR(&sblock);
271                         for (; j < NIADDR; j++)
272                                 if (dp->di_ib[j] != 0) {
273 #ifdef  AFS_HPUX_ENV
274                                         if ((dp->di_mode & IFMT) != IFIFO) {
275 #endif
276                                         if (debug)
277                                                 printf("bad indirect addr: %d\n",
278                                                         dp->di_ib[j]);
279                                         goto unknown;
280 #ifdef  AFS_HPUX_ENV
281                                         }
282 #endif
283
284                                 }
285 #if     defined(AFS_HPUX_ENV)
286 ignore_direct_block_check:
287 #endif
288 #ifdef  AFS_OSF_ENV
289                     }
290 #endif  /* AFS_OSF_ENV */
291                         if (ftypeok(dp) == 0)
292                                 goto unknown;
293                         n_files++;
294                         lncntp[inumber] = dp->di_nlink;
295                         if (dp->di_nlink <= 0) {
296                                 zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
297                                 if (zlnp == NULL) {
298                                         pfatal("LINK COUNT TABLE OVERFLOW");
299                                         if (reply("CONTINUE") == 0)
300                                                 errexit("");
301                                 } else {
302                                         zlnp->zlncnt = inumber;
303                                         zlnp->next = zlnhead;
304                                         zlnhead = zlnp;
305                                 }
306                         }
307 #if     defined(AFS_SUN56_ENV) 
308                         if ( OLDVICEINODE )
309                         {
310                             /* This looks like a sol 2.5 AFS inode */
311                             printf("This vicep partition seems to contain pre Sol2.6 AFS inodes\n");
312                             printf("You should run the AFS file conversion utility before installing Sol 2.6\n");
313                             exit(100); /* unique return code? */
314                         }
315 #endif
316                         statemap[inumber] =
317 #ifdef VICE
318                             (dp->di_mode & IFMT) == IFDIR ? DSTATE : (VICEINODE? VSTATE : FSTATE);
319 #else /* VICE */
320                             (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
321 #endif /* VICE */
322 #if defined(ACLS) && defined(AFS_HPUX_ENV)
323                         /* 
324                          * keep track of associated contin inodes 
325                          */
326                         if (dp->di_contin != 0)
327                             statemap[inumber] |= HASCINODE;
328 #endif /* ACLS */
329                         badblk = dupblk = 0;
330                         idesc.id_number = inumber;
331                         idesc.id_entryno = 0;
332 #ifdef  AFS_SUN5_ENV
333                         idesc.id_fix = DONTKNOW;
334 #endif
335                         (void)ckinode(dp, &idesc);
336
337                         idesc.id_entryno *= btodb(sblock.fs_fsize);
338
339                         if (dp->di_blocks != idesc.id_entryno) {
340                                 pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)",
341                                     inumber, dp->di_blocks, idesc.id_entryno);
342                                 if (preen)
343                                         printf(" (CORRECTED)\n");
344                                 else if (reply("CORRECT") == 0)
345                                         continue;
346 #ifdef  AFS_SUN5_ENV
347                                 dp = ginode(inumber);
348 #endif
349                                 dp->di_blocks = idesc.id_entryno;
350                                 inodirty();
351                         }
352 #ifdef  AFS_SUN5_ENV
353                         if ((dp->di_mode & IFMT) == IFDIR)
354                                 if (dp->di_blocks == 0)
355                                         statemap[inumber] = DCLEAR;
356 #endif
357                         continue;
358         unknown:
359                         pfatal("UNKNOWN FILE TYPE I=%u", inumber);
360 #ifdef  AFS_SUN5_ENV
361                         if ((dp->di_mode & IFMT) == IFDIR) {
362                                 statemap[inumber] = DCLEAR;
363 #ifdef  notdef
364                                 cacheino(dp, inumber);
365 #endif
366                         } else
367 #endif
368                         statemap[inumber] = FCLEAR;
369                         if (reply("CLEAR") == 1) {
370                                 statemap[inumber] = USTATE;
371 #ifdef VICE
372                                 zapino(dp);
373 #else /* VICE */
374                                 clearinode(dp);
375 #endif /* VICE */
376                                 inodirty();
377                         }
378                 }
379         }
380 }
381
382 pass1check(idesc)
383         register struct inodesc *idesc;
384 {
385         int res = KEEPON;
386         int anyout, nfrags;
387         daddr_t blkno = idesc->id_blkno;
388         register struct dups *dlp;
389         struct dups *new;
390
391         if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
392                 blkerror(idesc->id_number, "BAD", blkno);
393                 if (++badblk >= MAXBAD) {
394                         pwarn("EXCESSIVE BAD BLKS I=%u",
395                                 idesc->id_number);
396                         if (preen)
397                                 printf(" (SKIPPING)\n");
398                         else if (reply("CONTINUE") == 0)
399                                 errexit("");
400 #ifdef  AFS_HPUX_ENV
401                         ge_danger = 1;
402 #endif
403                         return (STOP);
404                 }
405         }
406         for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
407                 if (anyout && chkrange(blkno, 1)) {
408                         res = SKIP;
409                 } else if (!testbmap(blkno)) {
410                         n_blks++;
411                         setbmap(blkno);
412                 } else {
413                         blkerror(idesc->id_number, "DUP", blkno);
414                         if (++dupblk >= MAXDUP) {
415                                 pwarn("EXCESSIVE DUP BLKS I=%u",
416                                         idesc->id_number);
417                                 if (preen)
418                                         printf(" (SKIPPING)\n");
419                                 else if (reply("CONTINUE") == 0)
420                                         errexit("");
421 #ifdef  AFS_HPUX_ENV
422                                 ge_danger = 1;
423 #endif
424                                 return (STOP);
425                         }
426                         new = (struct dups *)malloc(sizeof(struct dups));
427                         if (new == NULL) {
428                                 pfatal("DUP TABLE OVERFLOW.");
429                                 if (reply("CONTINUE") == 0)
430                                         errexit("");
431                                 return (STOP);
432                         }
433                         new->dup = blkno;
434                         if (muldup == 0) {
435                                 duplist = muldup = new;
436                                 new->next = 0;
437                         } else {
438                                 new->next = muldup->next;
439                                 muldup->next = new;
440                         }
441                         for (dlp = duplist; dlp != muldup; dlp = dlp->next)
442                                 if (dlp->dup == blkno)
443                                         break;
444                         if (dlp == muldup && dlp->dup != blkno)
445                                 muldup = new;
446                 }
447                 /*
448                  * count the number of blocks found in id_entryno
449                  */
450                 idesc->id_entryno++;
451         }
452         return (res);
453 }