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*68908Smckusick static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 04/27/95"; 1639976Smckusick #endif /* not lint */ 1722047Sdist 186489Smckusick #include <sys/param.h> 1953703Smckusick #include <sys/time.h> 2057046Smckusick #include <sys/mount.h> 21*68908Smckusick 2251532Sbostic #include <ufs/ufs/dinode.h> 23*68908Smckusick #include <ufs/ufs/ufsmount.h> 2451532Sbostic #include <ufs/ffs/fs.h> 25*68908Smckusick 26*68908Smckusick #include <ctype.h> 27*68908Smckusick #include <err.h> 2817930Smckusick #include <fstab.h> 2942041Sbostic #include <string.h> 30*68908Smckusick 3116257Smckusick #include "fsck.h" 324236Smckusick 3324679Skarels int returntosingle; 3417930Smckusick 35*68908Smckusick static int argtoi __P((int flag, char *req, char *str, int base)); 36*68908Smckusick static int docheck __P((struct fstab *fsp)); 37*68908Smckusick static int checkfilesys __P((char *filesys, char *mntpt, long auxdata, 38*68908Smckusick int child)); 39*68908Smckusick void main __P((int argc, char *argv[])); 40*68908Smckusick 41*68908Smckusick void 4217930Smckusick main(argc, argv) 4317930Smckusick int argc; 4417930Smckusick char *argv[]; 4517930Smckusick { 4644933Smckusick int ch; 4741099Smckusick int ret, maxrun = 0; 48*68908Smckusick 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) 78*68908Smckusick 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: 95*68908Smckusick 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 115*68908Smckusick 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) 126*68908Smckusick errx(EEXIT, "-%c flag requires a %s", flag, req); 12744933Smckusick return (ret); 12844933Smckusick } 12944933Smckusick 13041099Smckusick /* 13141099Smckusick * Determine whether a filesystem should be checked. 13241099Smckusick */ 133*68908Smckusick 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 */ 150*68908Smckusick static int 15145027Skarels checkfilesys(filesys, mntpt, auxdata, child) 15241099Smckusick char *filesys, *mntpt; 15341099Smckusick long auxdata; 154*68908Smckusick 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"); 1669255Smckusick if (setup(filesys) == 0) { 1674236Smckusick if (preen) 1689255Smckusick pfatal("CAN'T CHECK FILE SYSTEM."); 16941099Smckusick return (0); 1704236Smckusick } 17117936Smckusick /* 17217936Smckusick * 1: scan inodes tallying blocks used 17317936Smckusick */ 1746837Smckusick if (preen == 0) { 1756837Smckusick printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 1764236Smckusick if (hotroot) 1774236Smckusick printf("** Root file system\n"); 1784236Smckusick printf("** Phase 1 - Check Blocks and Sizes\n"); 1794236Smckusick } 1809255Smckusick pass1(); 1819255Smckusick 18217936Smckusick /* 18317936Smckusick * 1b: locate first references to duplicates, if any 18417936Smckusick */ 18521743Smckusick if (duplist) { 1869255Smckusick if (preen) 1879255Smckusick pfatal("INTERNAL ERROR: dups with -p"); 1889255Smckusick printf("** Phase 1b - Rescan For More DUPS\n"); 1899255Smckusick pass1b(); 1909255Smckusick } 1919255Smckusick 19217936Smckusick /* 19317936Smckusick * 2: traverse directories from root to mark all connected directories 19417936Smckusick */ 1959255Smckusick if (preen == 0) 1969255Smckusick printf("** Phase 2 - Check Pathnames\n"); 1979255Smckusick pass2(); 1989255Smckusick 19917936Smckusick /* 20017936Smckusick * 3: scan inodes looking for disconnected directories 20117936Smckusick */ 2029255Smckusick if (preen == 0) 2039255Smckusick printf("** Phase 3 - Check Connectivity\n"); 2049255Smckusick pass3(); 2059255Smckusick 20617936Smckusick /* 20717936Smckusick * 4: scan inodes looking for disconnected files; check reference counts 20817936Smckusick */ 2099255Smckusick if (preen == 0) 2109255Smckusick printf("** Phase 4 - Check Reference Counts\n"); 2119255Smckusick pass4(); 2129255Smckusick 21317936Smckusick /* 21417936Smckusick * 5: check and repair resource counts in cylinder groups 21517936Smckusick */ 2169255Smckusick if (preen == 0) 2179255Smckusick printf("** Phase 5 - Check Cyl groups\n"); 2189255Smckusick pass5(); 2199255Smckusick 22017936Smckusick /* 22117936Smckusick * print out summary statistics 22217936Smckusick */ 22317936Smckusick n_ffree = sblock.fs_cstotal.cs_nffree; 22417936Smckusick n_bfree = sblock.fs_cstotal.cs_nbfree; 22544933Smckusick pwarn("%ld files, %ld used, %ld free ", 22625288Smckusick n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); 22753055Smckusick printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n", 22853055Smckusick n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize, 22953055Smckusick ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10); 23039972Smckusick if (debug && 23139972Smckusick (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) 23244933Smckusick printf("%ld files missing\n", n_files); 23317936Smckusick if (debug) { 23417936Smckusick n_blks += sblock.fs_ncg * 23517936Smckusick (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); 23617936Smckusick n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); 23717936Smckusick n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 23839972Smckusick if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) 23944933Smckusick printf("%ld blocks missing\n", n_blks); 24021760Smckusick if (duplist != NULL) { 24121760Smckusick printf("The following duplicate blocks remain:"); 24221760Smckusick for (dp = duplist; dp; dp = dp->next) 24344933Smckusick printf(" %ld,", dp->dup); 24421760Smckusick printf("\n"); 24521760Smckusick } 24626479Smckusick if (zlnhead != NULL) { 24726479Smckusick printf("The following zero link count inodes remain:"); 24826479Smckusick for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 24944933Smckusick printf(" %lu,", zlnp->zlncnt); 25026479Smckusick printf("\n"); 25126479Smckusick } 2529255Smckusick } 25326479Smckusick zlnhead = (struct zlncnt *)0; 25426479Smckusick duplist = (struct dups *)0; 25551354Smckusick muldup = (struct dups *)0; 25639980Smckusick inocleanup(); 25739972Smckusick if (fsmodified) { 25814952Smckusick (void)time(&sblock.fs_time); 2599255Smckusick sbdirty(); 2609255Smckusick } 26154602Smckusick if (cvtlevel && sblk.b_dirty) { 26254602Smckusick /* 26354602Smckusick * Write out the duplicate super blocks 26454602Smckusick */ 26554602Smckusick for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 26654602Smckusick bwrite(fswritefd, (char *)&sblock, 26754602Smckusick fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); 26854602Smckusick } 2699255Smckusick ckfini(); 2709255Smckusick free(blockmap); 2719255Smckusick free(statemap); 27214952Smckusick free((char *)lncntp); 27339972Smckusick if (!fsmodified) 27441099Smckusick return (0); 27557046Smckusick if (!preen) 27613729Sroot printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 27713729Sroot if (hotroot) { 27857046Smckusick struct statfs stfs_buf; 27957046Smckusick /* 28057046Smckusick * We modified the root. Do a mount update on 28157046Smckusick * it, unless it is read-write, so we can continue. 28257046Smckusick */ 28357046Smckusick if (statfs("/", &stfs_buf) == 0) { 28457046Smckusick long flags = stfs_buf.f_flags; 28557046Smckusick struct ufs_args args; 28657046Smckusick int ret; 28757046Smckusick 28857046Smckusick if (flags & MNT_RDONLY) { 28957046Smckusick args.fspec = 0; 29065842Sbostic args.export.ex_flags = 0; 29165842Sbostic args.export.ex_root = 0; 29257046Smckusick flags |= MNT_UPDATE | MNT_RELOAD; 293*68908Smckusick ret = mount("ufs", "/", flags, &args); 29457046Smckusick if (ret == 0) 29557046Smckusick return(0); 29657046Smckusick } 29757046Smckusick } 29857046Smckusick if (!preen) 29957046Smckusick printf("\n***** REBOOT NOW *****\n"); 30013729Sroot sync(); 30141099Smckusick return (4); 30213729Sroot } 30317930Smckusick return (0); 30417930Smckusick } 305