122047Sdist /* 261492Sbostic * Copyright (c) 1980, 1986, 1993 361492Sbostic * The Regents of the University of California. All rights reserved. 439976Smckusick * 542701Sbostic * %sccs.include.redist.c% 622047Sdist */ 722047Sdist 812728Ssam #ifndef lint 961492Sbostic static char copyright[] = 1061492Sbostic "@(#) Copyright (c) 1980, 1986, 1993\n\ 1161492Sbostic The Regents of the University of California. All rights reserved.\n"; 1239976Smckusick #endif /* not lint */ 134428Smckusic 1422047Sdist #ifndef lint 15*69319Smckusick static char sccsid[] = "@(#)main.c 8.5 (Berkeley) 05/09/95"; 1639976Smckusick #endif /* not lint */ 1722047Sdist 186489Smckusick #include <sys/param.h> 1953703Smckusick #include <sys/time.h> 2057046Smckusick #include <sys/mount.h> 2168908Smckusick 2251532Sbostic #include <ufs/ufs/dinode.h> 2368908Smckusick #include <ufs/ufs/ufsmount.h> 2451532Sbostic #include <ufs/ffs/fs.h> 2568908Smckusick 2668908Smckusick #include <ctype.h> 2768908Smckusick #include <err.h> 2817930Smckusick #include <fstab.h> 2942041Sbostic #include <string.h> 3068908Smckusick 3116257Smckusick #include "fsck.h" 324236Smckusick 3324679Skarels int returntosingle; 3417930Smckusick 3568908Smckusick static int argtoi __P((int flag, char *req, char *str, int base)); 3668908Smckusick static int docheck __P((struct fstab *fsp)); 3768908Smckusick static int checkfilesys __P((char *filesys, char *mntpt, long auxdata, 3868908Smckusick int child)); 3968908Smckusick void main __P((int argc, char *argv[])); 4068908Smckusick 4168908Smckusick void 4217930Smckusick main(argc, argv) 4317930Smckusick int argc; 4417930Smckusick char *argv[]; 4517930Smckusick { 4644933Smckusick int ch; 4741099Smckusick int ret, maxrun = 0; 4868908Smckusick extern char *optarg; 4941417Smckusick extern int optind; 5017930Smckusick 5117930Smckusick sync(); 5254602Smckusick while ((ch = getopt(argc, argv, "dpnNyYb:c:l:m:")) != EOF) { 5341417Smckusick switch (ch) { 5417930Smckusick case 'p': 5517930Smckusick preen++; 5617930Smckusick break; 5717930Smckusick 5817930Smckusick case 'b': 5944933Smckusick bflag = argtoi('b', "number", optarg, 10); 6017930Smckusick printf("Alternate super block location: %d\n", bflag); 6117930Smckusick break; 6217930Smckusick 6334139Smckusick case 'c': 6454602Smckusick cvtlevel = argtoi('c', "conversion level", optarg, 10); 6534139Smckusick break; 6654602Smckusick 6717930Smckusick case 'd': 6817930Smckusick debug++; 6917930Smckusick break; 7017930Smckusick 7137216Skarels case 'l': 7244933Smckusick maxrun = argtoi('l', "number", optarg, 10); 7337216Skarels break; 7437216Skarels 7536827Smckusick case 'm': 7644933Smckusick lfmode = argtoi('m', "mode", optarg, 8); 7736827Smckusick if (lfmode &~ 07777) 7868908Smckusick errx(EEXIT, "bad mode to -m: %o", lfmode); 7936827Smckusick printf("** lost+found creation mode %o\n", lfmode); 8036827Smckusick break; 8136827Smckusick 8239972Smckusick case 'n': 8317930Smckusick case 'N': 8417930Smckusick nflag++; 8517930Smckusick yflag = 0; 8617930Smckusick break; 8717930Smckusick 8839972Smckusick case 'y': 8917930Smckusick case 'Y': 9017930Smckusick yflag++; 9117930Smckusick nflag = 0; 9217930Smckusick break; 9317930Smckusick 9417930Smckusick default: 9568908Smckusick errx(EEXIT, "%c option?", ch); 9617930Smckusick } 9717930Smckusick } 9841417Smckusick argc -= optind; 9941417Smckusick argv += optind; 10017930Smckusick if (signal(SIGINT, SIG_IGN) != SIG_IGN) 10117930Smckusick (void)signal(SIGINT, catch); 10224679Skarels if (preen) 10324679Skarels (void)signal(SIGQUIT, catchquit); 10417930Smckusick if (argc) { 10541417Smckusick while (argc-- > 0) 10657046Smckusick (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0); 10717930Smckusick exit(0); 10817930Smckusick } 10941099Smckusick ret = checkfstab(preen, maxrun, docheck, checkfilesys); 11024679Skarels if (returntosingle) 11124679Skarels exit(2); 11241099Smckusick exit(ret); 11317930Smckusick } 11417930Smckusick 11568908Smckusick static int 11644933Smckusick argtoi(flag, req, str, base) 11744933Smckusick int flag; 11844933Smckusick char *req, *str; 11944933Smckusick int base; 12044933Smckusick { 12144933Smckusick char *cp; 12244933Smckusick int ret; 12344933Smckusick 12444933Smckusick ret = (int)strtol(str, &cp, base); 12544933Smckusick if (cp == str || *cp) 12668908Smckusick errx(EEXIT, "-%c flag requires a %s", flag, req); 12744933Smckusick return (ret); 12844933Smckusick } 12944933Smckusick 13041099Smckusick /* 13141099Smckusick * Determine whether a filesystem should be checked. 13241099Smckusick */ 13368908Smckusick static int 13441099Smckusick docheck(fsp) 13541099Smckusick register struct fstab *fsp; 13637216Skarels { 13737216Skarels 13841099Smckusick if (strcmp(fsp->fs_vfstype, "ufs") || 13941099Smckusick (strcmp(fsp->fs_type, FSTAB_RW) && 14041099Smckusick strcmp(fsp->fs_type, FSTAB_RO)) || 14141099Smckusick fsp->fs_passno == 0) 14241099Smckusick return (0); 14341099Smckusick return (1); 14437216Skarels } 14537216Skarels 14641099Smckusick /* 14741099Smckusick * Check the specified filesystem. 14841099Smckusick */ 14941099Smckusick /* ARGSUSED */ 15068908Smckusick static int 15145027Skarels checkfilesys(filesys, mntpt, auxdata, child) 15241099Smckusick char *filesys, *mntpt; 15341099Smckusick long auxdata; 15468908Smckusick int child; 15537216Skarels { 15668548Smckusick ufs_daddr_t n_ffree, n_bfree; 15721760Smckusick struct dups *dp; 15826479Smckusick struct zlncnt *zlnp; 15954602Smckusick int cylno; 1604236Smckusick 16145027Skarels if (preen && child) 16245027Skarels (void)signal(SIGQUIT, voidquit); 16361110Sbostic cdevname = filesys; 16437216Skarels if (debug && preen) 16537216Skarels pwarn("starting\n"); 166*69319Smckusick switch (setup(filesys)) { 167*69319Smckusick case 0: 1684236Smckusick if (preen) 1699255Smckusick pfatal("CAN'T CHECK FILE SYSTEM."); 170*69319Smckusick /* fall through */ 171*69319Smckusick case -1: 17241099Smckusick return (0); 1734236Smckusick } 17417936Smckusick /* 17517936Smckusick * 1: scan inodes tallying blocks used 17617936Smckusick */ 1776837Smckusick if (preen == 0) { 1786837Smckusick printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 1794236Smckusick if (hotroot) 1804236Smckusick printf("** Root file system\n"); 1814236Smckusick printf("** Phase 1 - Check Blocks and Sizes\n"); 1824236Smckusick } 1839255Smckusick pass1(); 1849255Smckusick 18517936Smckusick /* 18617936Smckusick * 1b: locate first references to duplicates, if any 18717936Smckusick */ 18821743Smckusick if (duplist) { 1899255Smckusick if (preen) 1909255Smckusick pfatal("INTERNAL ERROR: dups with -p"); 1919255Smckusick printf("** Phase 1b - Rescan For More DUPS\n"); 1929255Smckusick pass1b(); 1939255Smckusick } 1949255Smckusick 19517936Smckusick /* 19617936Smckusick * 2: traverse directories from root to mark all connected directories 19717936Smckusick */ 1989255Smckusick if (preen == 0) 1999255Smckusick printf("** Phase 2 - Check Pathnames\n"); 2009255Smckusick pass2(); 2019255Smckusick 20217936Smckusick /* 20317936Smckusick * 3: scan inodes looking for disconnected directories 20417936Smckusick */ 2059255Smckusick if (preen == 0) 2069255Smckusick printf("** Phase 3 - Check Connectivity\n"); 2079255Smckusick pass3(); 2089255Smckusick 20917936Smckusick /* 21017936Smckusick * 4: scan inodes looking for disconnected files; check reference counts 21117936Smckusick */ 2129255Smckusick if (preen == 0) 2139255Smckusick printf("** Phase 4 - Check Reference Counts\n"); 2149255Smckusick pass4(); 2159255Smckusick 21617936Smckusick /* 21717936Smckusick * 5: check and repair resource counts in cylinder groups 21817936Smckusick */ 2199255Smckusick if (preen == 0) 2209255Smckusick printf("** Phase 5 - Check Cyl groups\n"); 2219255Smckusick pass5(); 2229255Smckusick 22317936Smckusick /* 22417936Smckusick * print out summary statistics 22517936Smckusick */ 22617936Smckusick n_ffree = sblock.fs_cstotal.cs_nffree; 22717936Smckusick n_bfree = sblock.fs_cstotal.cs_nbfree; 22844933Smckusick pwarn("%ld files, %ld used, %ld free ", 22925288Smckusick n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); 23053055Smckusick printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n", 23153055Smckusick n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize, 23253055Smckusick ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10); 23339972Smckusick if (debug && 23439972Smckusick (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) 23544933Smckusick printf("%ld files missing\n", n_files); 23617936Smckusick if (debug) { 23717936Smckusick n_blks += sblock.fs_ncg * 23817936Smckusick (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); 23917936Smckusick n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); 24017936Smckusick n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 24139972Smckusick if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) 24244933Smckusick printf("%ld blocks missing\n", n_blks); 24321760Smckusick if (duplist != NULL) { 24421760Smckusick printf("The following duplicate blocks remain:"); 24521760Smckusick for (dp = duplist; dp; dp = dp->next) 24644933Smckusick printf(" %ld,", dp->dup); 24721760Smckusick printf("\n"); 24821760Smckusick } 24926479Smckusick if (zlnhead != NULL) { 25026479Smckusick printf("The following zero link count inodes remain:"); 25126479Smckusick for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 25244933Smckusick printf(" %lu,", zlnp->zlncnt); 25326479Smckusick printf("\n"); 25426479Smckusick } 2559255Smckusick } 25626479Smckusick zlnhead = (struct zlncnt *)0; 25726479Smckusick duplist = (struct dups *)0; 25851354Smckusick muldup = (struct dups *)0; 25939980Smckusick inocleanup(); 26039972Smckusick if (fsmodified) { 26114952Smckusick (void)time(&sblock.fs_time); 2629255Smckusick sbdirty(); 2639255Smckusick } 26454602Smckusick if (cvtlevel && sblk.b_dirty) { 26554602Smckusick /* 26654602Smckusick * Write out the duplicate super blocks 26754602Smckusick */ 26854602Smckusick for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 26954602Smckusick bwrite(fswritefd, (char *)&sblock, 27054602Smckusick fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); 27154602Smckusick } 272*69319Smckusick ckfini(1); 2739255Smckusick free(blockmap); 2749255Smckusick free(statemap); 27514952Smckusick free((char *)lncntp); 27639972Smckusick if (!fsmodified) 27741099Smckusick return (0); 27857046Smckusick if (!preen) 27913729Sroot printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 28013729Sroot if (hotroot) { 28157046Smckusick struct statfs stfs_buf; 28257046Smckusick /* 28357046Smckusick * We modified the root. Do a mount update on 28457046Smckusick * it, unless it is read-write, so we can continue. 28557046Smckusick */ 28657046Smckusick if (statfs("/", &stfs_buf) == 0) { 28757046Smckusick long flags = stfs_buf.f_flags; 28857046Smckusick struct ufs_args args; 28957046Smckusick int ret; 29057046Smckusick 29157046Smckusick if (flags & MNT_RDONLY) { 29257046Smckusick args.fspec = 0; 29365842Sbostic args.export.ex_flags = 0; 29465842Sbostic args.export.ex_root = 0; 29557046Smckusick flags |= MNT_UPDATE | MNT_RELOAD; 29668908Smckusick ret = mount("ufs", "/", flags, &args); 29757046Smckusick if (ret == 0) 29857046Smckusick return(0); 29957046Smckusick } 30057046Smckusick } 30157046Smckusick if (!preen) 30257046Smckusick printf("\n***** REBOOT NOW *****\n"); 30313729Sroot sync(); 30441099Smckusick return (4); 30513729Sroot } 30617930Smckusick return (0); 30717930Smckusick } 308