Remove support for Solaris pre-8
[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 <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 #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 <sys/fs/ufs_inode.h>
42 #include <sys/fs/ufs_fs.h>
43 #define _KERNEL
44 #include <sys/fs/ufs_fsdir.h>
45 #undef _KERNEL
46 #include <sys/fs/ufs_mount.h>
47 #else
48 #include <ufs/inode.h>
49 #include <ufs/fs.h>
50 #endif
51 #else /* AFS_VFSINCL_ENV */
52 #include <sys/inode.h>
53 #ifdef  AFS_HPUX_ENV
54 extern int ge_danger;
55 #define DUX
56 #define LONGFILENAMES   1
57 #include <sys/sysmacros.h>
58 #include <sys/ino.h>
59 #endif
60 #include <sys/fs.h>
61 #endif /* AFS_VFSINCL_ENV */
62 #endif /* AFS_OSF_ENV */
63
64 #include <afs/osi_inode.h>
65 #include "fsck.h"
66
67 static daddr_t badblk;
68 static daddr_t dupblk;
69 int pass1check();
70 static int oldreported;
71
72 pass1()
73 {
74     int c, i, j;
75     struct dinode *dp;
76     struct zlncnt *zlnp;
77     int ndb, cgd;
78     struct inodesc idesc;
79     ino_t inumber;
80
81     /*
82      * Set file system reserved blocks in used block map.
83      */
84     for (c = 0; c < sblock.fs_ncg; c++) {
85         cgd = cgdmin(&sblock, c);
86         if (c == 0) {
87             i = cgbase(&sblock, c);
88             cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
89         } else
90             i = cgsblock(&sblock, c);
91         for (; i < cgd; i++)
92             setbmap(i);
93     }
94     /*
95      * Find all allocated blocks.
96      */
97     memset(&idesc, 0, sizeof(struct inodesc));
98     idesc.id_type = ADDR;
99     idesc.id_func = pass1check;
100     inumber = 0;
101     n_files = n_blks = 0;
102 #ifdef VICE
103     nViceFiles = 0;
104 #endif /* VICE */
105     for (c = 0; c < sblock.fs_ncg; c++) {
106         for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
107             if (inumber < ROOTINO)
108                 continue;
109             dp = ginode(inumber);
110             if ((dp->di_mode & IFMT) == 0) {
111                 if (memcmp
112                     ((char *)dp->di_db, (char *)zino.di_db,
113                      NDADDR * sizeof(daddr_t))
114                     || memcmp((char *)dp->di_ib, (char *)zino.di_ib,
115                               NIADDR * sizeof(daddr_t)) ||
116 #if defined(ACLS) && defined(AFS_HPUX_ENV)
117                     dp->di_mode || dp->di_size || dp->di_contin) {
118                     if (dp->di_contin != 0)
119                         pwarn("UNALLOCATED INODE HAS BAD ic_contin VALUE %d",
120                               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_SUN5_ENV)
153             if (dp->di_size < 0 || dp->di_size > (UOFF_T) UFS_MAXOFFSET_T) {
154                 if (debug)
155                     printf("bad size %llu:", dp->di_size);
156                 goto unknown;
157             }
158 #else
159             if (dp->di_size < 0 || dp->di_size + sblock.fs_bsize - 1 < 0) {
160                 if (debug)
161                     printf("bad size %d:", dp->di_size);
162                 goto unknown;
163             }
164 #endif
165 #if defined(AFS_HPUX_ENV)
166             /* initialize all R/W activities of FIFO file */
167             /* make sure FIFO is empty (everything is 0) */
168             if ((dp->di_mode & IFMT) == IFIFO
169                 && (dp->di_frcnt != 0 || dp->di_fwcnt != 0)) {
170                 if (!qflag)
171                     pwarn("NON-ZERO READER/WRITER COUNT(S) ON PIPE I=%u",
172                           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,
207                           dp->di_size);
208                     if (preen)
209                         printf(" (CORRECTED)\n");
210                     else {
211                         printf("\n");
212                         pinode(inumber);
213                         if (reply("CORRECT") == 0)
214                             continue;
215                     }
216                     dp->di_size = len;
217                     inodirty();
218                 }
219                 goto ignore_direct_block_check;
220             }
221 #endif /* IC_FASTLINK */
222 #endif
223           no_reset:
224             if (!preen && (dp->di_mode & IFMT) == IFMT
225                 && reply("HOLD BAD BLOCK") == 1) {
226                 dp->di_size = sblock.fs_fsize;
227                 dp->di_mode = IFREG | 0600;
228                 inodirty();
229             }
230             ndb = howmany(dp->di_size, (UOFF_T) sblock.fs_bsize);
231 #ifdef  AFS_SUN5_ENV
232             if (dp->di_oeftflag == oEFT_MAGIC) {
233                 dp->di_oeftflag = 0;    /* XXX migration aid */
234                 inodirty();
235             }
236 #endif
237
238             if (ndb < 0) {
239                 if (debug)
240 #if     defined(AFS_SUN5_ENV)
241                     printf("bad size %" AFS_INT64_FMT " ndb %d:",
242 #else
243                     printf("bad size %d ndb %d:",
244 #endif
245                            dp->di_size, ndb);
246                 goto unknown;
247             }
248             if ((dp->di_mode & IFMT) == IFBLK
249                 || (dp->di_mode & IFMT) == IFCHR)
250                 ndb++;
251 #ifdef  AFS_OSF_ENV
252             if ((dp->di_flags & IC_FASTLINK) == 0) {
253 #endif /* AFS_OSF_ENV */
254                 for (j = ndb; j < NDADDR; j++) {
255 #if defined(AFS_HPUX_ENV) && (defined(DUX) || defined(CNODE_DEV))
256                     /*
257                      * DUX uses db[2] on cnode-specific
258                      * device files, so skip 'em
259                      */
260                     if (j == 2 && SPECIAL)
261                         continue;
262 #endif
263                     if (dp->di_db[j] != 0) {
264                         if (debug)
265                             printf("bad direct addr: %d\n", 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_SUN5_ENV)
308             if (OLDVICEINODE) {
309                 if (yflag) {
310                     if (!oldreported) {
311                         printf
312                             ("This vicep partition seems to contain pre Sol2.6 AFS inodes\n");
313                         printf
314                             ("You should run the AFS file conversion utility before installing Sol 2.6\n");
315                         printf("Continuing anyway.\n");
316                         oldreported++;
317                     }
318                 } else {
319                     /* This looks like a sol 2.5 AFS inode */
320                     printf
321                         ("This vicep partition seems to contain pre Sol2.6 AFS inodes\n");
322                     printf
323                         ("You should run the AFS file conversion utility before installing Sol 2.6\n");
324                     exit(100);  /* unique return code? */
325                 }
326             }
327 #endif
328             statemap[inumber] =
329 #ifdef VICE
330                 (dp->di_mode & IFMT) ==
331                 IFDIR ? DSTATE : (VICEINODE ? VSTATE : FSTATE);
332 #else /* VICE */
333                 (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
334 #endif /* VICE */
335 #if defined(ACLS) && defined(AFS_HPUX_ENV)
336             /*
337              * keep track of associated contin inodes
338              */
339             if (dp->di_contin != 0)
340                 statemap[inumber] |= HASCINODE;
341 #endif /* ACLS */
342             badblk = dupblk = 0;
343             idesc.id_number = inumber;
344             idesc.id_entryno = 0;
345 #ifdef  AFS_SUN5_ENV
346             idesc.id_fix = DONTKNOW;
347 #endif
348             (void)ckinode(dp, &idesc);
349
350             idesc.id_entryno *= btodb(sblock.fs_fsize);
351
352             if (dp->di_blocks != idesc.id_entryno) {
353                 pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)",
354                       inumber, dp->di_blocks, idesc.id_entryno);
355                 if (preen)
356                     printf(" (CORRECTED)\n");
357                 else if (reply("CORRECT") == 0)
358                     continue;
359 #ifdef  AFS_SUN5_ENV
360                 dp = ginode(inumber);
361 #endif
362                 dp->di_blocks = idesc.id_entryno;
363                 inodirty();
364             }
365 #ifdef  AFS_SUN5_ENV
366             if ((dp->di_mode & IFMT) == IFDIR)
367                 if (dp->di_blocks == 0)
368                     statemap[inumber] = DCLEAR;
369 #endif
370             continue;
371           unknown:
372             pfatal("UNKNOWN FILE TYPE I=%u", inumber);
373 #ifdef  AFS_SUN5_ENV
374             if ((dp->di_mode & IFMT) == IFDIR) {
375                 statemap[inumber] = DCLEAR;
376 #ifdef  notdef
377                 cacheino(dp, inumber);
378 #endif
379             } else
380 #endif
381                 statemap[inumber] = FCLEAR;
382             if (reply("CLEAR") == 1) {
383                 statemap[inumber] = USTATE;
384 #ifdef VICE
385                 zapino(dp);
386 #else /* VICE */
387                 clearinode(dp);
388 #endif /* VICE */
389                 inodirty();
390             }
391         }
392     }
393 }
394
395 pass1check(idesc)
396      struct inodesc *idesc;
397 {
398     int res = KEEPON;
399     int anyout, nfrags;
400     daddr_t blkno = idesc->id_blkno;
401     struct dups *dlp;
402     struct dups *new;
403
404     if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
405         blkerror(idesc->id_number, "BAD", blkno);
406         if (++badblk >= MAXBAD) {
407             pwarn("EXCESSIVE BAD BLKS I=%u", idesc->id_number);
408             if (preen)
409                 printf(" (SKIPPING)\n");
410             else if (reply("CONTINUE") == 0)
411                 errexit("");
412 #ifdef  AFS_HPUX_ENV
413             ge_danger = 1;
414 #endif
415             return (STOP);
416         }
417     }
418     for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
419         if (anyout && chkrange(blkno, 1)) {
420             res = SKIP;
421         } else if (!testbmap(blkno)) {
422             n_blks++;
423             setbmap(blkno);
424         } else {
425             blkerror(idesc->id_number, "DUP", blkno);
426             if (++dupblk >= MAXDUP) {
427                 pwarn("EXCESSIVE DUP BLKS I=%u", idesc->id_number);
428                 if (preen)
429                     printf(" (SKIPPING)\n");
430                 else if (reply("CONTINUE") == 0)
431                     errexit("");
432 #ifdef  AFS_HPUX_ENV
433                 ge_danger = 1;
434 #endif
435                 return (STOP);
436             }
437             new = (struct dups *)malloc(sizeof(struct dups));
438             if (new == NULL) {
439                 pfatal("DUP TABLE OVERFLOW.");
440                 if (reply("CONTINUE") == 0)
441                     errexit("");
442                 return (STOP);
443             }
444             new->dup = blkno;
445             if (muldup == 0) {
446                 duplist = muldup = new;
447                 new->next = 0;
448             } else {
449                 new->next = muldup->next;
450                 muldup->next = new;
451             }
452             for (dlp = duplist; dlp != muldup; dlp = dlp->next)
453                 if (dlp->dup == blkno)
454                     break;
455             if (dlp == muldup && dlp->dup != blkno)
456                 muldup = new;
457         }
458         /*
459          * count the number of blocks found in id_entryno
460          */
461         idesc->id_entryno++;
462     }
463     return (res);
464 }