pass1.c revision 8871
125839Speter/* 225839Speter * Copyright (c) 1980, 1986, 1993 325839Speter * The Regents of the University of California. All rights reserved. 425839Speter * 525839Speter * Redistribution and use in source and binary forms, with or without 625839Speter * modification, are permitted provided that the following conditions 725839Speter * are met: 817721Speter * 1. Redistributions of source code must retain the above copyright 917721Speter * notice, this list of conditions and the following disclaimer. 1017721Speter * 2. Redistributions in binary form must reproduce the above copyright 1117721Speter * notice, this list of conditions and the following disclaimer in the 1217721Speter * documentation and/or other materials provided with the distribution. 1317721Speter * 3. All advertising materials mentioning features or use of this software 1417721Speter * must display the following acknowledgement: 1517721Speter * This product includes software developed by the University of 1617721Speter * California, Berkeley and its contributors. 1717721Speter * 4. Neither the name of the University nor the names of its contributors 1817721Speter * may be used to endorse or promote products derived from this software 1917721Speter * without specific prior written permission. 2017721Speter * 2117721Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2217721Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2317721Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2417721Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2517721Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2617721Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2717721Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2817721Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2917721Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3017721Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3117721Speter * SUCH DAMAGE. 3217721Speter */ 3317721Speter 3417721Speter#ifndef lint 3517721Speterstatic const char sccsid[] = "@(#)pass1.c 8.1 (Berkeley) 6/5/93"; 3617721Speter#endif /* not lint */ 3717721Speter 3817721Speter#include <sys/param.h> 3917721Speter#include <sys/time.h> 4017721Speter#include <ufs/ufs/dinode.h> 4117721Speter#include <ufs/ufs/dir.h> 4217721Speter#include <ufs/ffs/fs.h> 4317721Speter#include <stdio.h> 4417721Speter#include <stdlib.h> 4517721Speter#include <string.h> 4617721Speter#include "fsck.h" 4717721Speter 4817721Speterstatic daddr_t badblk; 4917721Speterstatic daddr_t dupblk; 5017721Speter 5117721Speterstatic void checkinode __P((ino_t inumber, struct inodesc *idesc)); 5217721Speter 5317721Spetervoid 5417721Speterpass1() 5517721Speter{ 5617721Speter ino_t inumber; 5717721Speter int c, i, cgd; 5817721Speter struct inodesc idesc; 5917721Speter 6017721Speter /* 6117721Speter * Set file system reserved blocks in used block map. 6217721Speter */ 6317721Speter for (c = 0; c < sblock.fs_ncg; c++) { 6417721Speter cgd = cgdmin(&sblock, c); 6517721Speter if (c == 0) { 6617721Speter i = cgbase(&sblock, c); 6717721Speter cgd += howmany(sblock.fs_cssize, sblock.fs_fsize); 6817721Speter } else 6917721Speter i = cgsblock(&sblock, c); 7017721Speter for (; i < cgd; i++) 7117721Speter setbmap(i); 7217721Speter } 7317721Speter /* 7417721Speter * Find all allocated blocks. 7517721Speter */ 7617721Speter bzero((char *)&idesc, sizeof(struct inodesc)); 7717721Speter idesc.id_type = ADDR; 7817721Speter idesc.id_func = pass1check; 7917721Speter inumber = 0; 8017721Speter n_files = n_blks = 0; 8117721Speter resetinodebuf(); 8217721Speter for (c = 0; c < sblock.fs_ncg; c++) { 8317721Speter for (i = 0; i < sblock.fs_ipg; i++, inumber++) { 8417721Speter if (inumber < ROOTINO) 8517721Speter continue; 8617721Speter checkinode(inumber, &idesc); 8717721Speter } 8817721Speter } 8917721Speter freeinodebuf(); 9017721Speter} 9117721Speter 9217721Spetervoid 9317721Spetercheckinode(inumber, idesc) 9417721Speter ino_t inumber; 9517721Speter register struct inodesc *idesc; 9617721Speter{ 9717721Speter register struct dinode *dp; 9817721Speter struct zlncnt *zlnp; 9917721Speter int ndb, j; 10017721Speter mode_t mode; 10125839Speter char *symbuf; 10225839Speter 10325839Speter dp = getnextinode(inumber); 10425839Speter mode = dp->di_mode & IFMT; 10517721Speter if (mode == 0) { 10617721Speter if (bcmp((char *)dp->di_db, (char *)zino.di_db, 10717721Speter NDADDR * sizeof(daddr_t)) || 10817721Speter bcmp((char *)dp->di_ib, (char *)zino.di_ib, 10917721Speter NIADDR * sizeof(daddr_t)) || 11017721Speter dp->di_mode || dp->di_size) { 11117721Speter pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber); 11217721Speter if (reply("CLEAR") == 1) { 11325839Speter dp = ginode(inumber); 11425839Speter clearinode(dp); 11517721Speter inodirty(); 11617721Speter } 11717721Speter } 11817721Speter statemap[inumber] = USTATE; 11917721Speter return; 12017721Speter } 12117721Speter lastino = inumber; 12217721Speter if (/* dp->di_size < 0 || */ 12317721Speter dp->di_size + sblock.fs_bsize - 1 < dp->di_size) { 12417721Speter if (debug) 12517721Speter printf("bad size %qu:", dp->di_size); 12617721Speter goto unknown; 12717721Speter } 12817721Speter if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { 12917721Speter dp = ginode(inumber); 13032788Speter dp->di_size = sblock.fs_fsize; 13132788Speter dp->di_mode = IFREG|0600; 13217721Speter inodirty(); 13317721Speter } 13417721Speter ndb = howmany(dp->di_size, sblock.fs_bsize); 13517721Speter if (ndb < 0) { 13617721Speter if (debug) 13717721Speter printf("bad size %qu ndb %d:", 13817721Speter dp->di_size, ndb); 13917721Speter goto unknown; 14017721Speter } 14117721Speter if (mode == IFBLK || mode == IFCHR) 14217721Speter ndb++; 14317721Speter if (mode == IFLNK) { 14417721Speter if (doinglevel2 && 14517721Speter dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN && 14617721Speter dp->di_blocks != 0) { 14717721Speter symbuf = alloca(secsize); 14817721Speter if (bread(fsreadfd, symbuf, 14932788Speter fsbtodb(&sblock, dp->di_db[0]), 15032788Speter (long)secsize) != 0) 15117721Speter errexit("cannot read symlink"); 15217721Speter if (debug) { 15317721Speter symbuf[dp->di_size] = 0; 15417721Speter printf("convert symlink %ld(%s) of size %ld\n", 15517721Speter inumber, symbuf, (long)dp->di_size); 15617721Speter } 15717721Speter dp = ginode(inumber); 15817721Speter bcopy(symbuf, (caddr_t)dp->di_shortlink, 15917721Speter (long)dp->di_size); 16017721Speter dp->di_blocks = 0; 16117721Speter inodirty(); 16217721Speter } 16317721Speter /* 16417721Speter * Fake ndb value so direct/indirect block checks below 16517721Speter * will detect any garbage after symlink string. 16617721Speter */ 16717721Speter if ((dp->di_size < sblock.fs_maxsymlinklen) || dp->di_blocks == 0) { 16817721Speter ndb = howmany(dp->di_size, sizeof(daddr_t)); 16917721Speter if (ndb > NDADDR) { 17017721Speter j = ndb - NDADDR; 17117721Speter for (ndb = 1; j > 1; j--) 17217721Speter ndb *= NINDIR(&sblock); 17317721Speter ndb += NDADDR; 17417721Speter } 17517721Speter } 17617721Speter } 17717721Speter for (j = ndb; j < NDADDR; j++) 17825839Speter if (dp->di_db[j] != 0) { 17917721Speter if (debug) 18017721Speter printf("bad direct addr: %ld\n", dp->di_db[j]); 18117721Speter goto unknown; 18217721Speter } 18317721Speter for (j = 0, ndb -= NDADDR; ndb > 0; j++) 18417721Speter ndb /= NINDIR(&sblock); 18517721Speter for (; j < NIADDR; j++) 18625839Speter if (dp->di_ib[j] != 0) { 18725839Speter if (debug) 18825839Speter printf("bad indirect addr: %ld\n", 18932788Speter dp->di_ib[j]); 19025847Speter goto unknown; 19117721Speter } 19217721Speter if (ftypeok(dp) == 0) 19317721Speter goto unknown; 19417721Speter n_files++; 19517721Speter lncntp[inumber] = dp->di_nlink; 19617721Speter if (dp->di_nlink <= 0) { 19717721Speter zlnp = (struct zlncnt *)malloc(sizeof *zlnp); 19817721Speter if (zlnp == NULL) { 19917721Speter pfatal("LINK COUNT TABLE OVERFLOW"); 20017721Speter if (reply("CONTINUE") == 0) 20117721Speter errexit(""); 20217721Speter } else { 20317721Speter zlnp->zlncnt = inumber; 20417721Speter zlnp->next = zlnhead; 20517721Speter zlnhead = zlnp; 20617721Speter } 20717721Speter } 20817721Speter if (mode == IFDIR) { 20917721Speter if (dp->di_size == 0) 21017721Speter statemap[inumber] = DCLEAR; 21117721Speter else 21225839Speter statemap[inumber] = DSTATE; 21325839Speter cacheino(dp, inumber); 21425839Speter } else 21532788Speter statemap[inumber] = FSTATE; 21632788Speter typemap[inumber] = IFTODT(mode); 21732788Speter if (doinglevel2 && 21832788Speter (dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) { 21925839Speter dp = ginode(inumber); 22025839Speter dp->di_uid = dp->di_ouid; 22125839Speter dp->di_ouid = -1; 22225839Speter dp->di_gid = dp->di_ogid; 22325839Speter dp->di_ogid = -1; 22417721Speter inodirty(); 22525839Speter } 22625839Speter badblk = dupblk = 0; 22725839Speter idesc->id_number = inumber; 22817721Speter (void)ckinode(dp, idesc); 22925839Speter idesc->id_entryno *= btodb(sblock.fs_fsize); 23025839Speter if (dp->di_blocks != idesc->id_entryno) { 23125839Speter pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)", 23225839Speter inumber, dp->di_blocks, idesc->id_entryno); 23325839Speter if (preen) 23417721Speter printf(" (CORRECTED)\n"); 23517721Speter else if (reply("CORRECT") == 0) 23617721Speter return; 23717721Speter dp = ginode(inumber); 23817721Speter dp->di_blocks = idesc->id_entryno; 23917721Speter inodirty(); 24017721Speter } 24117721Speter return; 24217721Speterunknown: 24317721Speter pfatal("UNKNOWN FILE TYPE I=%lu", inumber); 24417721Speter statemap[inumber] = FCLEAR; 24517721Speter if (reply("CLEAR") == 1) { 24617721Speter statemap[inumber] = USTATE; 24717721Speter dp = ginode(inumber); 24817721Speter clearinode(dp); 24917721Speter inodirty(); 25017721Speter } 25117721Speter} 25217721Speter 25317721Speterint 25417721Speterpass1check(idesc) 25517721Speter register struct inodesc *idesc; 25617721Speter{ 25717721Speter int res = KEEPON; 25832788Speter int anyout, nfrags; 25917721Speter daddr_t blkno = idesc->id_blkno; 26025866Speter register struct dups *dlp; 26125866Speter struct dups *new; 26225839Speter 26325839Speter if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 26425839Speter blkerror(idesc->id_number, "BAD", blkno); 26517721Speter if (badblk++ >= MAXBAD) { 26617721Speter pwarn("EXCESSIVE BAD BLKS I=%lu", 26717721Speter idesc->id_number); 26825839Speter if (preen) 26917721Speter printf(" (SKIPPING)\n"); 27017721Speter else if (reply("CONTINUE") == 0) 27117721Speter errexit(""); 27217721Speter return (STOP); 27317721Speter } 27417721Speter } 27517721Speter for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 27617721Speter if (anyout && chkrange(blkno, 1)) { 27725839Speter res = SKIP; 27817721Speter } else if (!testbmap(blkno)) { 27917721Speter n_blks++; 28017721Speter setbmap(blkno); 28117721Speter } else { 28217721Speter blkerror(idesc->id_number, "DUP", blkno); 28317721Speter if (dupblk++ >= MAXDUP) { 28417721Speter pwarn("EXCESSIVE DUP BLKS I=%lu", 28517721Speter idesc->id_number); 28617721Speter if (preen) 28725839Speter printf(" (SKIPPING)\n"); 28825839Speter else if (reply("CONTINUE") == 0) 28925839Speter errexit(""); 29025839Speter return (STOP); 29117721Speter } 29225839Speter new = (struct dups *)malloc(sizeof(struct dups)); 29325839Speter if (new == NULL) { 29425839Speter pfatal("DUP TABLE OVERFLOW."); 29525839Speter if (reply("CONTINUE") == 0) 29625839Speter errexit(""); 29725839Speter return (STOP); 29817721Speter } 29917721Speter new->dup = blkno; 30017721Speter if (muldup == 0) { 30125839Speter duplist = muldup = new; 30217721Speter new->next = 0; 30317721Speter } else { 30432788Speter new->next = muldup->next; 30532788Speter muldup->next = new; 30617721Speter } 30732788Speter for (dlp = duplist; dlp != muldup; dlp = dlp->next) 30832788Speter if (dlp->dup == blkno) 30917721Speter break; 31032788Speter if (dlp == muldup && dlp->dup != blkno) 31117721Speter muldup = new; 31217721Speter } 31317721Speter /* 31417721Speter * count the number of blocks found in id_entryno 31517721Speter */ 31617721Speter idesc->id_entryno++; 31717721Speter } 31817721Speter return (res); 31917721Speter} 32017721Speter