main.c revision 11750
198943Sluigi/* 2117328Sluigi * Copyright (c) 1980, 1986, 1993 398943Sluigi * The Regents of the University of California. All rights reserved. 498943Sluigi * 598943Sluigi * Redistribution and use in source and binary forms, with or without 698943Sluigi * modification, are permitted provided that the following conditions 798943Sluigi * are met: 898943Sluigi * 1. Redistributions of source code must retain the above copyright 998943Sluigi * notice, this list of conditions and the following disclaimer. 1098943Sluigi * 2. Redistributions in binary form must reproduce the above copyright 1198943Sluigi * notice, this list of conditions and the following disclaimer in the 1298943Sluigi * documentation and/or other materials provided with the distribution. 1398943Sluigi * 3. All advertising materials mentioning features or use of this software 1498943Sluigi * must display the following acknowledgement: 1598943Sluigi * This product includes software developed by the University of 1698943Sluigi * California, Berkeley and its contributors. 1798943Sluigi * 4. Neither the name of the University nor the names of its contributors 1898943Sluigi * may be used to endorse or promote products derived from this software 1998943Sluigi * without specific prior written permission. 2098943Sluigi * 2198943Sluigi * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2298943Sluigi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2398943Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2498943Sluigi * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2598943Sluigi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2698943Sluigi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2798943Sluigi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2898943Sluigi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2998943Sluigi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30136071Sgreen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3198943Sluigi * SUCH DAMAGE. 3298943Sluigi */ 3398943Sluigi 3498943Sluigi#ifndef lint 3598943Sluigistatic const char copyright[] = 3698943Sluigi"@(#) Copyright (c) 1980, 1986, 1993\n\ 3798943Sluigi The Regents of the University of California. All rights reserved.\n"; 3898943Sluigi#endif /* not lint */ 3998943Sluigi 4098943Sluigi#ifndef lint 4198943Sluigistatic const char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/23/94"; 4298943Sluigi#endif /* not lint */ 4398943Sluigi 44117469Sluigi#include <sys/param.h> 4598943Sluigi#include <sys/time.h> 4698943Sluigi#include <sys/proc.h> 47136071Sgreen#include <sys/mount.h> 48136071Sgreen#include <ufs/ufs/dinode.h> 4998943Sluigi#include <ufs/ffs/fs.h> 50175659Srwatson#include <fstab.h> 51175659Srwatson#include <stdlib.h> 52169424Smaxim#include <unistd.h> 5398943Sluigi#include <string.h> 54165648Spiso#include <stdio.h> 55136071Sgreen#include "fsck.h" 56145246Sbrooksstatic int argtoi __P((int flag, char *req, char *str, int base)); 5798943Sluigistatic int docheck __P((struct fstab *fsp)); 5898943Sluigistatic int checkfilesys __P((char *filesys, char *mntpt, long auxdata, 5998943Sluigi int child)); 6098943Sluigi 61145246Sbrooksint 6298943Sluigimain(argc, argv) 6398943Sluigi int argc; 6498943Sluigi char *argv[]; 6598943Sluigi{ 66165648Spiso int ch; 6798943Sluigi int ret, maxrun = 0; 68117328Sluigi extern char *optarg; 69176391Sjulian extern int optind; 7098943Sluigi 7198943Sluigi sync(); 7298943Sluigi while ((ch = getopt(argc, argv, "dfpnNyYb:c:l:m:")) != EOF) { 7398943Sluigi switch (ch) { 74165648Spiso case 'p': 7598943Sluigi preen++; 7698943Sluigi break; 7798943Sluigi 78102098Sluigi case 'b': 79123804Smaxim bflag = argtoi('b', "number", optarg, 10); 80170923Smaxim printf("Alternate super block location: %d\n", bflag); 81101628Sluigi break; 82117328Sluigi 83123495Sluigi case 'c': 8498943Sluigi cvtlevel = argtoi('c', "conversion level", optarg, 10); 8598943Sluigi break; 8698943Sluigi 87130013Scsjp case 'd': 88130013Scsjp debug++; 89130013Scsjp break; 90130013Scsjp 91130013Scsjp case 'f': 9298943Sluigi fflag++; 93159636Soleg break; 94159636Soleg 95159636Soleg case 'l': 96159636Soleg maxrun = argtoi('l', "number", optarg, 10); 97159636Soleg break; 98159636Soleg 99159636Soleg case 'm': 100159636Soleg lfmode = argtoi('m', "mode", optarg, 8); 101159636Soleg if (lfmode &~ 07777) 102159636Soleg errexit("bad mode to -m: %o\n", lfmode); 103159636Soleg printf("** lost+found creation mode %o\n", lfmode); 104159636Soleg break; 105159636Soleg 106159636Soleg case 'n': 107159636Soleg case 'N': 108159636Soleg nflag++; 109159636Soleg yflag = 0; 110159636Soleg break; 111159636Soleg 112159636Soleg case 'y': 113159636Soleg case 'Y': 114159636Soleg yflag++; 115159636Soleg nflag = 0; 116159636Soleg break; 117159636Soleg 118159636Soleg default: 119159636Soleg errexit("%c option?\n", ch); 120158879Soleg } 121158879Soleg } 122159636Soleg argc -= optind; 123159636Soleg argv += optind; 124159636Soleg if (signal(SIGINT, SIG_IGN) != SIG_IGN) 125159636Soleg (void)signal(SIGINT, catch); 126159636Soleg if (preen) 127159636Soleg (void)signal(SIGQUIT, catchquit); 128159636Soleg if (argc) { 129159636Soleg while (argc-- > 0) 130159636Soleg (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0); 13198943Sluigi exit(0); 132117328Sluigi } 133117328Sluigi ret = checkfstab(preen, maxrun, docheck, checkfilesys); 134117328Sluigi if (returntosingle) 135117328Sluigi exit(2); 136117328Sluigi exit(ret); 13798943Sluigi} 13898943Sluigi 13998943Sluigiint 140117469Sluigiargtoi(flag, req, str, base) 14198943Sluigi int flag; 14298943Sluigi char *req, *str; 14398943Sluigi int base; 14498943Sluigi{ 14598943Sluigi char *cp; 14698943Sluigi int ret; 14798943Sluigi 14898943Sluigi ret = (int)strtol(str, &cp, base); 14998943Sluigi if (cp == str || *cp) 15098943Sluigi errexit("-%c flag requires a %s\n", flag, req); 15198943Sluigi return (ret); 15298943Sluigi} 15398943Sluigi 15498943Sluigi/* 15598943Sluigi * Determine whether a filesystem should be checked. 15698943Sluigi */ 15798943Sluigiint 15898943Sluigidocheck(fsp) 15998943Sluigi register struct fstab *fsp; 16098943Sluigi{ 16198943Sluigi 16298943Sluigi if (strcmp(fsp->fs_vfstype, "ufs") || 16398943Sluigi (strcmp(fsp->fs_type, FSTAB_RW) && 16498943Sluigi strcmp(fsp->fs_type, FSTAB_RO)) || 16598943Sluigi fsp->fs_passno == 0) 16698943Sluigi return (0); 16798943Sluigi return (1); 16898943Sluigi} 16998943Sluigi 17098943Sluigi/* 17198943Sluigi * Check the specified filesystem. 17298943Sluigi */ 17398943Sluigi/* ARGSUSED */ 17498943Sluigiint 17598943Sluigicheckfilesys(filesys, mntpt, auxdata, child) 17698943Sluigi char *filesys, *mntpt; 17798943Sluigi long auxdata; 17898943Sluigi int child; 17998943Sluigi{ 18098943Sluigi daddr_t n_ffree, n_bfree; 18198943Sluigi struct dups *dp; 18298943Sluigi struct zlncnt *zlnp; 18398943Sluigi int cylno; 18498943Sluigi 185172801Srpaulo if (preen && child) 186172801Srpaulo (void)signal(SIGQUIT, voidquit); 18798943Sluigi cdevname = filesys; 18898943Sluigi if (debug && preen) 18998943Sluigi pwarn("starting\n"); 19098943Sluigi if (setup(filesys) == 0) { 19198943Sluigi if (preen) 19298943Sluigi pfatal("CAN'T CHECK FILE SYSTEM."); 19398943Sluigi return (0); 19498943Sluigi } 19598943Sluigi 19698943Sluigi if (preen && sblock.fs_clean && !fflag) { 19798943Sluigi pwarn("clean, %ld free ", sblock.fs_cstotal.cs_nffree + 19898943Sluigi sblock.fs_frag * sblock.fs_cstotal.cs_nbfree); 19998943Sluigi printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n", 20098943Sluigi sblock.fs_cstotal.cs_nffree, 20198943Sluigi sblock.fs_cstotal.cs_nbfree, 20298943Sluigi (float)(sblock.fs_cstotal.cs_nffree * 100) / 20398943Sluigi sblock.fs_dsize); 20498943Sluigi return(0); 20598943Sluigi } 20698943Sluigi 20798943Sluigi /* 20898943Sluigi * 1: scan inodes tallying blocks used 20998943Sluigi */ 21098943Sluigi if (preen == 0) { 21198943Sluigi printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 21298943Sluigi if (hotroot) 21398943Sluigi printf("** Root file system\n"); 21498943Sluigi printf("** Phase 1 - Check Blocks and Sizes\n"); 21598943Sluigi } 21698943Sluigi pass1(); 21798943Sluigi 21898943Sluigi /* 21998943Sluigi * 1b: locate first references to duplicates, if any 22098943Sluigi */ 22198943Sluigi if (duplist) { 22298943Sluigi if (preen) 22398943Sluigi pfatal("INTERNAL ERROR: dups with -p"); 22498943Sluigi printf("** Phase 1b - Rescan For More DUPS\n"); 22598943Sluigi pass1b(); 22698943Sluigi } 22798943Sluigi 22898943Sluigi /* 22998943Sluigi * 2: traverse directories from root to mark all connected directories 23098943Sluigi */ 23198943Sluigi if (preen == 0) 23298943Sluigi printf("** Phase 2 - Check Pathnames\n"); 23398943Sluigi pass2(); 23498943Sluigi 23598943Sluigi /* 23698943Sluigi * 3: scan inodes looking for disconnected directories 23798943Sluigi */ 23898943Sluigi if (preen == 0) 23998943Sluigi printf("** Phase 3 - Check Connectivity\n"); 240101641Sluigi pass3(); 241101641Sluigi 24298943Sluigi /* 24398943Sluigi * 4: scan inodes looking for disconnected files; check reference counts 24498943Sluigi */ 24598943Sluigi if (preen == 0) 24698943Sluigi printf("** Phase 4 - Check Reference Counts\n"); 24798943Sluigi pass4(); 24898943Sluigi 249141351Sglebius /* 250141351Sglebius * 5: check and repair resource counts in cylinder groups 25198943Sluigi */ 25298943Sluigi if (preen == 0) 25398943Sluigi printf("** Phase 5 - Check Cyl groups\n"); 25498943Sluigi pass5(); 25598943Sluigi 25698943Sluigi /* 25798943Sluigi * print out summary statistics 258165648Spiso */ 25998943Sluigi n_ffree = sblock.fs_cstotal.cs_nffree; 260136071Sgreen n_bfree = sblock.fs_cstotal.cs_nbfree; 261136071Sgreen pwarn("%ld files, %ld used, %ld free ", 262158879Soleg n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); 263158879Soleg printf("(%ld frags, %ld blocks, %ld.%ld%% fragmentation)\n", 264136071Sgreen n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize, 265158879Soleg ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10); 26698943Sluigi if (debug && 26798943Sluigi (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) 268133600Scsjp printf("%ld files missing\n", n_files); 26998943Sluigi if (debug) { 27098943Sluigi n_blks += sblock.fs_ncg * 27198943Sluigi (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); 27298943Sluigi n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); 27398943Sluigi n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 274136073Sgreen if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) 275136073Sgreen printf("%ld blocks missing\n", n_blks); 276136073Sgreen if (duplist != NULL) { 27798943Sluigi printf("The following duplicate blocks remain:"); 27898943Sluigi for (dp = duplist; dp; dp = dp->next) 27998943Sluigi printf(" %ld,", dp->dup); 28098943Sluigi printf("\n"); 28198943Sluigi } 28298943Sluigi if (zlnhead != NULL) { 28398943Sluigi printf("The following zero link count inodes remain:"); 28498943Sluigi for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 28598943Sluigi printf(" %lu,", zlnp->zlncnt); 28698943Sluigi printf("\n"); 28798943Sluigi } 28898943Sluigi } 28998943Sluigi zlnhead = (struct zlncnt *)0; 290136075Sgreen duplist = (struct dups *)0; 29198943Sluigi muldup = (struct dups *)0; 29298943Sluigi inocleanup(); 29398943Sluigi if (fsmodified) { 29498943Sluigi (void)time(&sblock.fs_time); 29598943Sluigi sbdirty(); 29698943Sluigi } 297102087Sluigi if (cvtlevel && sblk.b_dirty) { 298102087Sluigi /* 299112250Scjc * Write out the duplicate super blocks 300128575Sandre */ 301133387Sandre for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 302117241Sluigi bwrite(fswritefd, (char *)&sblock, 303117469Sluigi fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); 30498943Sluigi } 30598943Sluigi ckfini(); 306101978Sluigi free(blockmap); 30798943Sluigi free(statemap); 30898943Sluigi free((char *)lncntp); 30998943Sluigi if (!fsmodified) 31098943Sluigi return (0); 31198943Sluigi if (!preen) 31298943Sluigi printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 31398943Sluigi if (hotroot) { 31498943Sluigi struct statfs stfs_buf; 31598943Sluigi /* 31698943Sluigi * We modified the root. Do a mount update on 31798943Sluigi * it, unless it is read-write, so we can continue. 31898943Sluigi */ 31998943Sluigi if (statfs("/", &stfs_buf) == 0) { 32098943Sluigi long flags = stfs_buf.f_flags; 321165648Spiso struct ufs_args args; 322165648Spiso int ret; 323165648Spiso 324165648Spiso if (flags & MNT_RDONLY) { 325165648Spiso args.fspec = 0; 326165648Spiso args.export.ex_flags = 0; 327165648Spiso args.export.ex_root = 0; 328165648Spiso flags |= MNT_UPDATE | MNT_RELOAD; 329165648Spiso ret = mount(MOUNT_UFS, "/", flags, &args); 330165648Spiso if (ret == 0) 331165648Spiso return(0); 332165648Spiso } 333145246Sbrooks } 334145246Sbrooks if (!preen) 335145246Sbrooks printf("\n***** REBOOT NOW *****\n"); 336145246Sbrooks sync(); 337145246Sbrooks return (4); 338145246Sbrooks } 339145246Sbrooks return (0); 340146894Smlaier} 341146894Smlaier