122047Sdist /* 239976Smckusick * Copyright (c) 1980, 1986 The Regents of the University of California. 339976Smckusick * All rights reserved. 439976Smckusick * 542701Sbostic * %sccs.include.redist.c% 622047Sdist */ 722047Sdist 812728Ssam #ifndef lint 922047Sdist char copyright[] = 1039976Smckusick "@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\ 1122047Sdist All rights reserved.\n"; 1239976Smckusick #endif /* not lint */ 134428Smckusic 1422047Sdist #ifndef lint 15*51532Sbostic static char sccsid[] = "@(#)main.c 5.29 (Berkeley) 11/04/91"; 1639976Smckusick #endif /* not lint */ 1722047Sdist 186489Smckusick #include <sys/param.h> 19*51532Sbostic #include <ufs/ufs/dinode.h> 20*51532Sbostic #include <ufs/ffs/fs.h> 2117930Smckusick #include <fstab.h> 2244933Smckusick #include <stdlib.h> 2342041Sbostic #include <string.h> 2436827Smckusick #include <ctype.h> 2541417Smckusick #include <stdio.h> 2616257Smckusick #include "fsck.h" 274236Smckusick 2839165Sbostic void catch(), catchquit(), voidquit(); 2924679Skarels int returntosingle; 3017930Smckusick 3117930Smckusick main(argc, argv) 3217930Smckusick int argc; 3317930Smckusick char *argv[]; 3417930Smckusick { 3544933Smckusick int ch; 3641099Smckusick int ret, maxrun = 0; 3741417Smckusick extern int docheck(), checkfilesys(); 3841417Smckusick extern char *optarg; 3941417Smckusick extern int optind; 4017930Smckusick 4117930Smckusick sync(); 4241417Smckusick while ((ch = getopt(argc, argv, "cdpnNyYb:l:m:")) != EOF) { 4341417Smckusick switch (ch) { 4417930Smckusick case 'p': 4517930Smckusick preen++; 4617930Smckusick break; 4717930Smckusick 4817930Smckusick case 'b': 4944933Smckusick bflag = argtoi('b', "number", optarg, 10); 5017930Smckusick printf("Alternate super block location: %d\n", bflag); 5117930Smckusick break; 5217930Smckusick 5334139Smckusick case 'c': 5434139Smckusick cvtflag++; 5534139Smckusick break; 5634139Smckusick 5717930Smckusick case 'd': 5817930Smckusick debug++; 5917930Smckusick break; 6017930Smckusick 6137216Skarels case 'l': 6244933Smckusick maxrun = argtoi('l', "number", optarg, 10); 6337216Skarels break; 6437216Skarels 6536827Smckusick case 'm': 6644933Smckusick lfmode = argtoi('m', "mode", optarg, 8); 6736827Smckusick if (lfmode &~ 07777) 6836827Smckusick errexit("bad mode to -m: %o\n", lfmode); 6936827Smckusick printf("** lost+found creation mode %o\n", lfmode); 7036827Smckusick break; 7136827Smckusick 7239972Smckusick case 'n': 7317930Smckusick case 'N': 7417930Smckusick nflag++; 7517930Smckusick yflag = 0; 7617930Smckusick break; 7717930Smckusick 7839972Smckusick case 'y': 7917930Smckusick case 'Y': 8017930Smckusick yflag++; 8117930Smckusick nflag = 0; 8217930Smckusick break; 8317930Smckusick 8417930Smckusick default: 8541417Smckusick errexit("%c option?\n", ch); 8617930Smckusick } 8717930Smckusick } 8841417Smckusick argc -= optind; 8941417Smckusick argv += optind; 9017930Smckusick if (signal(SIGINT, SIG_IGN) != SIG_IGN) 9117930Smckusick (void)signal(SIGINT, catch); 9224679Skarels if (preen) 9324679Skarels (void)signal(SIGQUIT, catchquit); 9417930Smckusick if (argc) { 9541417Smckusick while (argc-- > 0) 9645027Skarels (void)checkfilesys(*argv++, (char *)0, 0L, 0); 9717930Smckusick exit(0); 9817930Smckusick } 9941099Smckusick ret = checkfstab(preen, maxrun, docheck, checkfilesys); 10024679Skarels if (returntosingle) 10124679Skarels exit(2); 10241099Smckusick exit(ret); 10317930Smckusick } 10417930Smckusick 10544933Smckusick argtoi(flag, req, str, base) 10644933Smckusick int flag; 10744933Smckusick char *req, *str; 10844933Smckusick int base; 10944933Smckusick { 11044933Smckusick char *cp; 11144933Smckusick int ret; 11244933Smckusick 11344933Smckusick ret = (int)strtol(str, &cp, base); 11444933Smckusick if (cp == str || *cp) 11544933Smckusick errexit("-%c flag requires a %s\n", flag, req); 11644933Smckusick return (ret); 11744933Smckusick } 11844933Smckusick 11941099Smckusick /* 12041099Smckusick * Determine whether a filesystem should be checked. 12141099Smckusick */ 12241099Smckusick docheck(fsp) 12341099Smckusick register struct fstab *fsp; 12437216Skarels { 12537216Skarels 12641099Smckusick if (strcmp(fsp->fs_vfstype, "ufs") || 12741099Smckusick (strcmp(fsp->fs_type, FSTAB_RW) && 12841099Smckusick strcmp(fsp->fs_type, FSTAB_RO)) || 12941099Smckusick fsp->fs_passno == 0) 13041099Smckusick return (0); 13141099Smckusick return (1); 13237216Skarels } 13337216Skarels 13441099Smckusick /* 13541099Smckusick * Check the specified filesystem. 13641099Smckusick */ 13741099Smckusick /* ARGSUSED */ 13845027Skarels checkfilesys(filesys, mntpt, auxdata, child) 13941099Smckusick char *filesys, *mntpt; 14041099Smckusick long auxdata; 14137216Skarels { 14217936Smckusick daddr_t n_ffree, n_bfree; 14321760Smckusick struct dups *dp; 14426479Smckusick struct zlncnt *zlnp; 1454236Smckusick 14645027Skarels if (preen && child) 14745027Skarels (void)signal(SIGQUIT, voidquit); 1489255Smckusick devname = filesys; 14937216Skarels if (debug && preen) 15037216Skarels pwarn("starting\n"); 1519255Smckusick if (setup(filesys) == 0) { 1524236Smckusick if (preen) 1539255Smckusick pfatal("CAN'T CHECK FILE SYSTEM."); 15441099Smckusick return (0); 1554236Smckusick } 15617936Smckusick /* 15717936Smckusick * 1: scan inodes tallying blocks used 15817936Smckusick */ 1596837Smckusick if (preen == 0) { 1606837Smckusick printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 1614236Smckusick if (hotroot) 1624236Smckusick printf("** Root file system\n"); 1634236Smckusick printf("** Phase 1 - Check Blocks and Sizes\n"); 1644236Smckusick } 1659255Smckusick pass1(); 1669255Smckusick 16717936Smckusick /* 16817936Smckusick * 1b: locate first references to duplicates, if any 16917936Smckusick */ 17021743Smckusick if (duplist) { 1719255Smckusick if (preen) 1729255Smckusick pfatal("INTERNAL ERROR: dups with -p"); 1739255Smckusick printf("** Phase 1b - Rescan For More DUPS\n"); 1749255Smckusick pass1b(); 1759255Smckusick } 1769255Smckusick 17717936Smckusick /* 17817936Smckusick * 2: traverse directories from root to mark all connected directories 17917936Smckusick */ 1809255Smckusick if (preen == 0) 1819255Smckusick printf("** Phase 2 - Check Pathnames\n"); 1829255Smckusick pass2(); 1839255Smckusick 18417936Smckusick /* 18517936Smckusick * 3: scan inodes looking for disconnected directories 18617936Smckusick */ 1879255Smckusick if (preen == 0) 1889255Smckusick printf("** Phase 3 - Check Connectivity\n"); 1899255Smckusick pass3(); 1909255Smckusick 19117936Smckusick /* 19217936Smckusick * 4: scan inodes looking for disconnected files; check reference counts 19317936Smckusick */ 1949255Smckusick if (preen == 0) 1959255Smckusick printf("** Phase 4 - Check Reference Counts\n"); 1969255Smckusick pass4(); 1979255Smckusick 19817936Smckusick /* 19917936Smckusick * 5: check and repair resource counts in cylinder groups 20017936Smckusick */ 2019255Smckusick if (preen == 0) 2029255Smckusick printf("** Phase 5 - Check Cyl groups\n"); 2039255Smckusick pass5(); 2049255Smckusick 20517936Smckusick /* 20617936Smckusick * print out summary statistics 20717936Smckusick */ 20817936Smckusick n_ffree = sblock.fs_cstotal.cs_nffree; 20917936Smckusick n_bfree = sblock.fs_cstotal.cs_nbfree; 21044933Smckusick pwarn("%ld files, %ld used, %ld free ", 21125288Smckusick n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); 21244933Smckusick printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n", 21325288Smckusick n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize); 21439972Smckusick if (debug && 21539972Smckusick (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) 21644933Smckusick printf("%ld files missing\n", n_files); 21717936Smckusick if (debug) { 21817936Smckusick n_blks += sblock.fs_ncg * 21917936Smckusick (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); 22017936Smckusick n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); 22117936Smckusick n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 22239972Smckusick if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) 22344933Smckusick printf("%ld blocks missing\n", n_blks); 22421760Smckusick if (duplist != NULL) { 22521760Smckusick printf("The following duplicate blocks remain:"); 22621760Smckusick for (dp = duplist; dp; dp = dp->next) 22744933Smckusick printf(" %ld,", dp->dup); 22821760Smckusick printf("\n"); 22921760Smckusick } 23026479Smckusick if (zlnhead != NULL) { 23126479Smckusick printf("The following zero link count inodes remain:"); 23226479Smckusick for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 23344933Smckusick printf(" %lu,", zlnp->zlncnt); 23426479Smckusick printf("\n"); 23526479Smckusick } 2369255Smckusick } 23726479Smckusick zlnhead = (struct zlncnt *)0; 23826479Smckusick duplist = (struct dups *)0; 23951354Smckusick muldup = (struct dups *)0; 24039980Smckusick inocleanup(); 24139972Smckusick if (fsmodified) { 24214952Smckusick (void)time(&sblock.fs_time); 2439255Smckusick sbdirty(); 2449255Smckusick } 2459255Smckusick ckfini(); 2469255Smckusick free(blockmap); 2479255Smckusick free(statemap); 24814952Smckusick free((char *)lncntp); 24939972Smckusick if (!fsmodified) 25041099Smckusick return (0); 25113729Sroot if (!preen) { 25213729Sroot printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 25313729Sroot if (hotroot) 25413729Sroot printf("\n***** REBOOT UNIX *****\n"); 2559255Smckusick } 25613729Sroot if (hotroot) { 25713729Sroot sync(); 25841099Smckusick return (4); 25913729Sroot } 26017930Smckusick return (0); 26117930Smckusick } 262