main.c revision 2153
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1980, 1986, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 351558Srgrimesstatic char copyright[] = 361558Srgrimes"@(#) Copyright (c) 1980, 1986, 1993\n\ 371558Srgrimes The Regents of the University of California. All rights reserved.\n"; 381558Srgrimes#endif /* not lint */ 391558Srgrimes 401558Srgrimes#ifndef lint 411558Srgrimesstatic char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/23/94"; 421558Srgrimes#endif /* not lint */ 431558Srgrimes 441558Srgrimes#include <sys/param.h> 451558Srgrimes#include <sys/time.h> 462153Sdg#include <sys/proc.h> 471558Srgrimes#include <sys/mount.h> 481558Srgrimes#include <ufs/ufs/dinode.h> 491558Srgrimes#include <ufs/ffs/fs.h> 501558Srgrimes#include <fstab.h> 511558Srgrimes#include <stdlib.h> 521558Srgrimes#include <string.h> 531558Srgrimes#include <ctype.h> 541558Srgrimes#include <stdio.h> 551558Srgrimes#include "fsck.h" 561558Srgrimes 571558Srgrimesvoid catch(), catchquit(), voidquit(); 581558Srgrimesint returntosingle; 591558Srgrimes 601558Srgrimesmain(argc, argv) 611558Srgrimes int argc; 621558Srgrimes char *argv[]; 631558Srgrimes{ 641558Srgrimes int ch; 651558Srgrimes int ret, maxrun = 0; 661558Srgrimes extern int docheck(), checkfilesys(); 671558Srgrimes extern char *optarg, *blockcheck(); 681558Srgrimes extern int optind; 691558Srgrimes 701558Srgrimes sync(); 712153Sdg while ((ch = getopt(argc, argv, "dfpnNyYb:c:l:m:")) != EOF) { 721558Srgrimes switch (ch) { 731558Srgrimes case 'p': 741558Srgrimes preen++; 751558Srgrimes break; 761558Srgrimes 771558Srgrimes case 'b': 781558Srgrimes bflag = argtoi('b', "number", optarg, 10); 791558Srgrimes printf("Alternate super block location: %d\n", bflag); 801558Srgrimes break; 811558Srgrimes 821558Srgrimes case 'c': 831558Srgrimes cvtlevel = argtoi('c', "conversion level", optarg, 10); 841558Srgrimes break; 851558Srgrimes 861558Srgrimes case 'd': 871558Srgrimes debug++; 881558Srgrimes break; 891558Srgrimes 902153Sdg case 'f': 912153Sdg fflag++; 922153Sdg break; 932153Sdg 941558Srgrimes case 'l': 951558Srgrimes maxrun = argtoi('l', "number", optarg, 10); 961558Srgrimes break; 971558Srgrimes 981558Srgrimes case 'm': 991558Srgrimes lfmode = argtoi('m', "mode", optarg, 8); 1001558Srgrimes if (lfmode &~ 07777) 1011558Srgrimes errexit("bad mode to -m: %o\n", lfmode); 1021558Srgrimes printf("** lost+found creation mode %o\n", lfmode); 1031558Srgrimes break; 1041558Srgrimes 1051558Srgrimes case 'n': 1061558Srgrimes case 'N': 1071558Srgrimes nflag++; 1081558Srgrimes yflag = 0; 1091558Srgrimes break; 1101558Srgrimes 1111558Srgrimes case 'y': 1121558Srgrimes case 'Y': 1131558Srgrimes yflag++; 1141558Srgrimes nflag = 0; 1151558Srgrimes break; 1161558Srgrimes 1171558Srgrimes default: 1181558Srgrimes errexit("%c option?\n", ch); 1191558Srgrimes } 1201558Srgrimes } 1211558Srgrimes argc -= optind; 1221558Srgrimes argv += optind; 1231558Srgrimes if (signal(SIGINT, SIG_IGN) != SIG_IGN) 1241558Srgrimes (void)signal(SIGINT, catch); 1251558Srgrimes if (preen) 1261558Srgrimes (void)signal(SIGQUIT, catchquit); 1271558Srgrimes if (argc) { 1281558Srgrimes while (argc-- > 0) 1291558Srgrimes (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0); 1301558Srgrimes exit(0); 1311558Srgrimes } 1321558Srgrimes ret = checkfstab(preen, maxrun, docheck, checkfilesys); 1331558Srgrimes if (returntosingle) 1341558Srgrimes exit(2); 1351558Srgrimes exit(ret); 1361558Srgrimes} 1371558Srgrimes 1381558Srgrimesargtoi(flag, req, str, base) 1391558Srgrimes int flag; 1401558Srgrimes char *req, *str; 1411558Srgrimes int base; 1421558Srgrimes{ 1431558Srgrimes char *cp; 1441558Srgrimes int ret; 1451558Srgrimes 1461558Srgrimes ret = (int)strtol(str, &cp, base); 1471558Srgrimes if (cp == str || *cp) 1481558Srgrimes errexit("-%c flag requires a %s\n", flag, req); 1491558Srgrimes return (ret); 1501558Srgrimes} 1511558Srgrimes 1521558Srgrimes/* 1531558Srgrimes * Determine whether a filesystem should be checked. 1541558Srgrimes */ 1551558Srgrimesdocheck(fsp) 1561558Srgrimes register struct fstab *fsp; 1571558Srgrimes{ 1581558Srgrimes 1591558Srgrimes if (strcmp(fsp->fs_vfstype, "ufs") || 1601558Srgrimes (strcmp(fsp->fs_type, FSTAB_RW) && 1611558Srgrimes strcmp(fsp->fs_type, FSTAB_RO)) || 1621558Srgrimes fsp->fs_passno == 0) 1631558Srgrimes return (0); 1641558Srgrimes return (1); 1651558Srgrimes} 1661558Srgrimes 1671558Srgrimes/* 1681558Srgrimes * Check the specified filesystem. 1691558Srgrimes */ 1701558Srgrimes/* ARGSUSED */ 1711558Srgrimescheckfilesys(filesys, mntpt, auxdata, child) 1721558Srgrimes char *filesys, *mntpt; 1731558Srgrimes long auxdata; 1741558Srgrimes{ 1751558Srgrimes daddr_t n_ffree, n_bfree; 1761558Srgrimes struct dups *dp; 1771558Srgrimes struct zlncnt *zlnp; 1781558Srgrimes int cylno; 1791558Srgrimes 1801558Srgrimes if (preen && child) 1811558Srgrimes (void)signal(SIGQUIT, voidquit); 1821558Srgrimes cdevname = filesys; 1831558Srgrimes if (debug && preen) 1841558Srgrimes pwarn("starting\n"); 1851558Srgrimes if (setup(filesys) == 0) { 1861558Srgrimes if (preen) 1871558Srgrimes pfatal("CAN'T CHECK FILE SYSTEM."); 1881558Srgrimes return (0); 1891558Srgrimes } 1902153Sdg 1912153Sdg if (preen && sblock.fs_clean && !fflag) { 1922153Sdg pwarn("clean, %ld free ", sblock.fs_cstotal.cs_nffree + 1932153Sdg sblock.fs_frag * sblock.fs_cstotal.cs_nbfree); 1942153Sdg printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n", 1952153Sdg sblock.fs_cstotal.cs_nffree, 1962153Sdg sblock.fs_cstotal.cs_nbfree, 1972153Sdg (float)(sblock.fs_cstotal.cs_nffree * 100) / 1982153Sdg sblock.fs_dsize); 1992153Sdg return(0); 2002153Sdg } 2012153Sdg 2021558Srgrimes /* 2031558Srgrimes * 1: scan inodes tallying blocks used 2041558Srgrimes */ 2051558Srgrimes if (preen == 0) { 2061558Srgrimes printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 2071558Srgrimes if (hotroot) 2081558Srgrimes printf("** Root file system\n"); 2091558Srgrimes printf("** Phase 1 - Check Blocks and Sizes\n"); 2101558Srgrimes } 2111558Srgrimes pass1(); 2121558Srgrimes 2131558Srgrimes /* 2141558Srgrimes * 1b: locate first references to duplicates, if any 2151558Srgrimes */ 2161558Srgrimes if (duplist) { 2171558Srgrimes if (preen) 2181558Srgrimes pfatal("INTERNAL ERROR: dups with -p"); 2191558Srgrimes printf("** Phase 1b - Rescan For More DUPS\n"); 2201558Srgrimes pass1b(); 2211558Srgrimes } 2221558Srgrimes 2231558Srgrimes /* 2241558Srgrimes * 2: traverse directories from root to mark all connected directories 2251558Srgrimes */ 2261558Srgrimes if (preen == 0) 2271558Srgrimes printf("** Phase 2 - Check Pathnames\n"); 2281558Srgrimes pass2(); 2291558Srgrimes 2301558Srgrimes /* 2311558Srgrimes * 3: scan inodes looking for disconnected directories 2321558Srgrimes */ 2331558Srgrimes if (preen == 0) 2341558Srgrimes printf("** Phase 3 - Check Connectivity\n"); 2351558Srgrimes pass3(); 2361558Srgrimes 2371558Srgrimes /* 2381558Srgrimes * 4: scan inodes looking for disconnected files; check reference counts 2391558Srgrimes */ 2401558Srgrimes if (preen == 0) 2411558Srgrimes printf("** Phase 4 - Check Reference Counts\n"); 2421558Srgrimes pass4(); 2431558Srgrimes 2441558Srgrimes /* 2451558Srgrimes * 5: check and repair resource counts in cylinder groups 2461558Srgrimes */ 2471558Srgrimes if (preen == 0) 2481558Srgrimes printf("** Phase 5 - Check Cyl groups\n"); 2491558Srgrimes pass5(); 2501558Srgrimes 2511558Srgrimes /* 2521558Srgrimes * print out summary statistics 2531558Srgrimes */ 2541558Srgrimes n_ffree = sblock.fs_cstotal.cs_nffree; 2551558Srgrimes n_bfree = sblock.fs_cstotal.cs_nbfree; 2561558Srgrimes pwarn("%ld files, %ld used, %ld free ", 2571558Srgrimes n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); 2581558Srgrimes printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n", 2591558Srgrimes n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize, 2601558Srgrimes ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10); 2611558Srgrimes if (debug && 2621558Srgrimes (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) 2631558Srgrimes printf("%ld files missing\n", n_files); 2641558Srgrimes if (debug) { 2651558Srgrimes n_blks += sblock.fs_ncg * 2661558Srgrimes (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); 2671558Srgrimes n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); 2681558Srgrimes n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 2691558Srgrimes if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) 2701558Srgrimes printf("%ld blocks missing\n", n_blks); 2711558Srgrimes if (duplist != NULL) { 2721558Srgrimes printf("The following duplicate blocks remain:"); 2731558Srgrimes for (dp = duplist; dp; dp = dp->next) 2741558Srgrimes printf(" %ld,", dp->dup); 2751558Srgrimes printf("\n"); 2761558Srgrimes } 2771558Srgrimes if (zlnhead != NULL) { 2781558Srgrimes printf("The following zero link count inodes remain:"); 2791558Srgrimes for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 2801558Srgrimes printf(" %lu,", zlnp->zlncnt); 2811558Srgrimes printf("\n"); 2821558Srgrimes } 2831558Srgrimes } 2841558Srgrimes zlnhead = (struct zlncnt *)0; 2851558Srgrimes duplist = (struct dups *)0; 2861558Srgrimes muldup = (struct dups *)0; 2871558Srgrimes inocleanup(); 2882153Sdg if (fsmodified || (!sblock.fs_clean && preen && !nflag && !hotroot)) { 2892153Sdg sblock.fs_clean = 1; 2901558Srgrimes (void)time(&sblock.fs_time); 2911558Srgrimes sbdirty(); 2921558Srgrimes } 2931558Srgrimes if (cvtlevel && sblk.b_dirty) { 2941558Srgrimes /* 2951558Srgrimes * Write out the duplicate super blocks 2961558Srgrimes */ 2971558Srgrimes for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 2981558Srgrimes bwrite(fswritefd, (char *)&sblock, 2991558Srgrimes fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); 3001558Srgrimes } 3011558Srgrimes ckfini(); 3021558Srgrimes free(blockmap); 3031558Srgrimes free(statemap); 3041558Srgrimes free((char *)lncntp); 3051558Srgrimes if (!fsmodified) 3061558Srgrimes return (0); 3071558Srgrimes if (!preen) 3081558Srgrimes printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 3091558Srgrimes if (hotroot) { 3101558Srgrimes struct statfs stfs_buf; 3111558Srgrimes /* 3121558Srgrimes * We modified the root. Do a mount update on 3131558Srgrimes * it, unless it is read-write, so we can continue. 3141558Srgrimes */ 3151558Srgrimes if (statfs("/", &stfs_buf) == 0) { 3161558Srgrimes long flags = stfs_buf.f_flags; 3171558Srgrimes struct ufs_args args; 3181558Srgrimes int ret; 3191558Srgrimes 3201558Srgrimes if (flags & MNT_RDONLY) { 3211558Srgrimes args.fspec = 0; 3221558Srgrimes args.export.ex_flags = 0; 3231558Srgrimes args.export.ex_root = 0; 3241558Srgrimes flags |= MNT_UPDATE | MNT_RELOAD; 3251558Srgrimes ret = mount(MOUNT_UFS, "/", flags, &args); 3261558Srgrimes if (ret == 0) 3271558Srgrimes return(0); 3281558Srgrimes } 3291558Srgrimes } 3301558Srgrimes if (!preen) 3311558Srgrimes printf("\n***** REBOOT NOW *****\n"); 3321558Srgrimes sync(); 3331558Srgrimes return (4); 3341558Srgrimes } 3351558Srgrimes return (0); 3361558Srgrimes} 337