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, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static char sccsid[] = "@(#)pass1.c 5.16 (Berkeley) 3/19/91"; 36 static char rcsid[] = "$Header: /cvsroot/src/sbin/fsck_ffs/pass1.c,v 1.4 1993/06/13 21:10:50 mycroft Exp $"; 37 #endif /* not lint */ 38 39 #include <sys/param.h> 40 #include <ufs/dinode.h> 41 #include <ufs/fs.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include "fsck.h" 45 46 static daddr_t badblk; 47 static daddr_t dupblk; 48 int pass1check(); 49 struct dinode *getnextinode(); 50 51 pass1() 52 { 53 register int c, i, j; 54 register struct dinode *dp; 55 struct zlncnt *zlnp; 56 int ndb, cgd; 57 struct inodesc idesc; 58 ino_t inumber; 59 60 /* 61 * Set file system reserved blocks in used block map. 62 */ 63 for (c = 0; c < sblock.fs_ncg; c++) { 64 cgd = cgdmin(&sblock, c); 65 if (c == 0) { 66 i = cgbase(&sblock, c); 67 cgd += howmany(sblock.fs_cssize, sblock.fs_fsize); 68 } else 69 i = cgsblock(&sblock, c); 70 for (; i < cgd; i++) 71 setbmap(i); 72 } 73 /* 74 * Find all allocated blocks. 75 */ 76 bzero((char *)&idesc, sizeof(struct inodesc)); 77 idesc.id_type = ADDR; 78 idesc.id_func = pass1check; 79 inumber = 0; 80 n_files = n_blks = 0; 81 resetinodebuf(); 82 for (c = 0; c < sblock.fs_ncg; c++) { 83 for (i = 0; i < sblock.fs_ipg; i++, inumber++) { 84 if (inumber < ROOTINO) 85 continue; 86 dp = getnextinode(inumber); 87 if ((dp->di_mode & IFMT) == 0) { 88 if (bcmp((char *)dp->di_db, (char *)zino.di_db, 89 NDADDR * sizeof(daddr_t)) || 90 bcmp((char *)dp->di_ib, (char *)zino.di_ib, 91 NIADDR * sizeof(daddr_t)) || 92 dp->di_mode || dp->di_size) { 93 pfatal("PARTIALLY ALLOCATED INODE I=%lu", 94 inumber); 95 if (reply("CLEAR") == 1) { 96 dp = ginode(inumber); 97 clearinode(dp); 98 inodirty(); 99 } 100 } 101 statemap[inumber] = USTATE; 102 continue; 103 } 104 lastino = inumber; 105 /* is fast symlink? */ 106 if (DFASTLINK(*dp)) { 107 lncntp[inumber] = dp->di_nlink; 108 statemap[inumber] = FSTATE; 109 n_files++; 110 continue; 111 } 112 if (/* dp->di_size < 0 || */ 113 dp->di_size + sblock.fs_bsize - 1 < dp->di_size) { 114 if (debug) 115 printf("bad size %lu:", dp->di_size); 116 goto unknown; 117 } 118 if (!preen && (dp->di_mode & IFMT) == IFMT && 119 reply("HOLD BAD BLOCK") == 1) { 120 dp = ginode(inumber); 121 dp->di_size = sblock.fs_fsize; 122 dp->di_mode = IFREG|0600; 123 inodirty(); 124 } 125 ndb = howmany(dp->di_size, sblock.fs_bsize); 126 if (ndb < 0) { 127 if (debug) 128 printf("bad size %lu ndb %d:", 129 dp->di_size, ndb); 130 goto unknown; 131 } 132 if ((dp->di_mode & IFMT) == IFBLK || 133 (dp->di_mode & IFMT) == IFCHR) 134 ndb++; 135 for (j = ndb; j < NDADDR; j++) 136 if (dp->di_db[j] != 0) { 137 if (debug) 138 printf("bad direct addr: %ld\n", 139 dp->di_db[j]); 140 goto unknown; 141 } 142 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 143 ndb /= NINDIR(&sblock); 144 for (; j < NIADDR; j++) 145 if (dp->di_ib[j] != 0) { 146 if (debug) 147 printf("bad indirect addr: %ld\n", 148 dp->di_ib[j]); 149 goto unknown; 150 } 151 if (ftypeok(dp) == 0) 152 goto unknown; 153 n_files++; 154 lncntp[inumber] = dp->di_nlink; 155 if (dp->di_nlink <= 0) { 156 zlnp = (struct zlncnt *)malloc(sizeof *zlnp); 157 if (zlnp == NULL) { 158 pfatal("LINK COUNT TABLE OVERFLOW"); 159 if (reply("CONTINUE") == 0) 160 errexit(""); 161 } else { 162 zlnp->zlncnt = inumber; 163 zlnp->next = zlnhead; 164 zlnhead = zlnp; 165 } 166 } 167 if ((dp->di_mode & IFMT) == IFDIR) { 168 if (dp->di_size == 0) 169 statemap[inumber] = DCLEAR; 170 else 171 statemap[inumber] = DSTATE; 172 cacheino(dp, inumber); 173 } else 174 statemap[inumber] = FSTATE; 175 badblk = dupblk = 0; 176 idesc.id_number = inumber; 177 (void)ckinode(dp, &idesc); 178 idesc.id_entryno *= btodb(sblock.fs_fsize); 179 if (dp->di_blocks != idesc.id_entryno) { 180 pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)", 181 inumber, dp->di_blocks, idesc.id_entryno); 182 if (preen) 183 printf(" (CORRECTED)\n"); 184 else if (reply("CORRECT") == 0) 185 continue; 186 dp = ginode(inumber); 187 dp->di_blocks = idesc.id_entryno; 188 inodirty(); 189 } 190 continue; 191 unknown: 192 pfatal("UNKNOWN FILE TYPE I=%lu", inumber); 193 statemap[inumber] = FCLEAR; 194 if (reply("CLEAR") == 1) { 195 statemap[inumber] = USTATE; 196 dp = ginode(inumber); 197 clearinode(dp); 198 inodirty(); 199 } 200 } 201 } 202 freeinodebuf(); 203 } 204 205 pass1check(idesc) 206 register struct inodesc *idesc; 207 { 208 int res = KEEPON; 209 int anyout, nfrags; 210 daddr_t blkno = idesc->id_blkno; 211 register struct dups *dlp; 212 struct dups *new; 213 214 if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 215 blkerror(idesc->id_number, "BAD", blkno); 216 if (badblk++ >= MAXBAD) { 217 pwarn("EXCESSIVE BAD BLKS I=%lu", 218 idesc->id_number); 219 if (preen) 220 printf(" (SKIPPING)\n"); 221 else if (reply("CONTINUE") == 0) 222 errexit(""); 223 return (STOP); 224 } 225 } 226 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 227 if (anyout && chkrange(blkno, 1)) { 228 res = SKIP; 229 } else if (!testbmap(blkno)) { 230 n_blks++; 231 setbmap(blkno); 232 } else { 233 blkerror(idesc->id_number, "DUP", blkno); 234 if (dupblk++ >= MAXDUP) { 235 pwarn("EXCESSIVE DUP BLKS I=%lu", 236 idesc->id_number); 237 if (preen) 238 printf(" (SKIPPING)\n"); 239 else if (reply("CONTINUE") == 0) 240 errexit(""); 241 return (STOP); 242 } 243 new = (struct dups *)malloc(sizeof(struct dups)); 244 if (new == NULL) { 245 pfatal("DUP TABLE OVERFLOW."); 246 if (reply("CONTINUE") == 0) 247 errexit(""); 248 return (STOP); 249 } 250 new->dup = blkno; 251 if (muldup == 0) { 252 duplist = muldup = new; 253 new->next = 0; 254 } else { 255 new->next = muldup->next; 256 muldup->next = new; 257 } 258 for (dlp = duplist; dlp != muldup; dlp = dlp->next) 259 if (dlp->dup == blkno) 260 break; 261 if (dlp == muldup && dlp->dup != blkno) 262 muldup = new; 263 } 264 /* 265 * count the number of blocks found in id_entryno 266 */ 267 idesc->id_entryno++; 268 } 269 return (res); 270 } 271