xref: /original-bsd/sbin/fsck/main.c (revision 7ccea779)
1 /*
2  * Copyright (c) 1980, 1986 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)main.c	5.25 (Berkeley) 06/29/90";
16 #endif /* not lint */
17 
18 #include <sys/param.h>
19 #include <ufs/dinode.h>
20 #include <ufs/fs.h>
21 #include <fstab.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include <stdio.h>
25 #include "fsck.h"
26 
27 void	catch(), catchquit(), voidquit();
28 int	returntosingle;
29 
30 main(argc, argv)
31 	int	argc;
32 	char	*argv[];
33 {
34 	char ch;
35 	int ret, maxrun = 0;
36 	extern int docheck(), checkfilesys();
37 	extern char *optarg;
38 	extern int optind;
39 
40 	sync();
41 	while ((ch = getopt(argc, argv, "cdpnNyYb:l:m:")) != EOF) {
42 		switch (ch) {
43 		case 'p':
44 			preen++;
45 			break;
46 
47 		case 'b':
48 			if (!isdigit(*optarg))
49 				errexit("-b flag requires a number\n");
50 			bflag = atoi(optarg);
51 			printf("Alternate super block location: %d\n", bflag);
52 			break;
53 
54 		case 'c':
55 			cvtflag++;
56 			break;
57 
58 		case 'd':
59 			debug++;
60 			break;
61 
62 		case 'l':
63 			if (!isdigit(*optarg))
64 				errexit("-l flag requires a number\n");
65 			maxrun = atoi(optarg);
66 			break;
67 
68 		case 'm':
69 			if (!isdigit(*optarg))
70 				errexit("-m flag requires a mode\n");
71 			sscanf(optarg, "%o", &lfmode);
72 			if (lfmode &~ 07777)
73 				errexit("bad mode to -m: %o\n", lfmode);
74 			printf("** lost+found creation mode %o\n", lfmode);
75 			break;
76 
77 		case 'n':
78 		case 'N':
79 			nflag++;
80 			yflag = 0;
81 			break;
82 
83 		case 'y':
84 		case 'Y':
85 			yflag++;
86 			nflag = 0;
87 			break;
88 
89 		default:
90 			errexit("%c option?\n", ch);
91 		}
92 	}
93 	argc -= optind;
94 	argv += optind;
95 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
96 		(void)signal(SIGINT, catch);
97 	if (preen)
98 		(void)signal(SIGQUIT, catchquit);
99 	if (argc) {
100 		while (argc-- > 0)
101 			checkfilesys(*argv++, (char *)0, 0);
102 		exit(0);
103 	}
104 	ret = checkfstab(preen, maxrun, docheck, checkfilesys);
105 	if (returntosingle)
106 		exit(2);
107 	exit(ret);
108 }
109 
110 /*
111  * Determine whether a filesystem should be checked.
112  */
113 docheck(fsp)
114 	register struct fstab *fsp;
115 {
116 
117 	if (strcmp(fsp->fs_vfstype, "ufs") ||
118 	    (strcmp(fsp->fs_type, FSTAB_RW) &&
119 	     strcmp(fsp->fs_type, FSTAB_RO)) ||
120 	    fsp->fs_passno == 0)
121 		return (0);
122 	return (1);
123 }
124 
125 /*
126  * Check the specified filesystem.
127  */
128 /* ARGSUSED */
129 checkfilesys(filesys, mntpt, auxdata)
130 	char *filesys, *mntpt;
131 	long auxdata;
132 {
133 	daddr_t n_ffree, n_bfree;
134 	struct dups *dp;
135 	struct zlncnt *zlnp;
136 
137 	(void)signal(SIGQUIT, voidquit);
138 	devname = filesys;
139 	if (debug && preen)
140 		pwarn("starting\n");
141 	if (setup(filesys) == 0) {
142 		if (preen)
143 			pfatal("CAN'T CHECK FILE SYSTEM.");
144 		return (0);
145 	}
146 	/*
147 	 * 1: scan inodes tallying blocks used
148 	 */
149 	if (preen == 0) {
150 		printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
151 		if (hotroot)
152 			printf("** Root file system\n");
153 		printf("** Phase 1 - Check Blocks and Sizes\n");
154 	}
155 	pass1();
156 
157 	/*
158 	 * 1b: locate first references to duplicates, if any
159 	 */
160 	if (duplist) {
161 		if (preen)
162 			pfatal("INTERNAL ERROR: dups with -p");
163 		printf("** Phase 1b - Rescan For More DUPS\n");
164 		pass1b();
165 	}
166 
167 	/*
168 	 * 2: traverse directories from root to mark all connected directories
169 	 */
170 	if (preen == 0)
171 		printf("** Phase 2 - Check Pathnames\n");
172 	pass2();
173 
174 	/*
175 	 * 3: scan inodes looking for disconnected directories
176 	 */
177 	if (preen == 0)
178 		printf("** Phase 3 - Check Connectivity\n");
179 	pass3();
180 
181 	/*
182 	 * 4: scan inodes looking for disconnected files; check reference counts
183 	 */
184 	if (preen == 0)
185 		printf("** Phase 4 - Check Reference Counts\n");
186 	pass4();
187 
188 	/*
189 	 * 5: check and repair resource counts in cylinder groups
190 	 */
191 	if (preen == 0)
192 		printf("** Phase 5 - Check Cyl groups\n");
193 	pass5();
194 
195 	/*
196 	 * print out summary statistics
197 	 */
198 	n_ffree = sblock.fs_cstotal.cs_nffree;
199 	n_bfree = sblock.fs_cstotal.cs_nbfree;
200 	pwarn("%d files, %d used, %d free ",
201 	    n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
202 	printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
203 	    n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
204 	if (debug &&
205 	    (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
206 		printf("%d files missing\n", n_files);
207 	if (debug) {
208 		n_blks += sblock.fs_ncg *
209 			(cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
210 		n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
211 		n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
212 		if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
213 			printf("%d blocks missing\n", n_blks);
214 		if (duplist != NULL) {
215 			printf("The following duplicate blocks remain:");
216 			for (dp = duplist; dp; dp = dp->next)
217 				printf(" %d,", dp->dup);
218 			printf("\n");
219 		}
220 		if (zlnhead != NULL) {
221 			printf("The following zero link count inodes remain:");
222 			for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
223 				printf(" %d,", zlnp->zlncnt);
224 			printf("\n");
225 		}
226 	}
227 	zlnhead = (struct zlncnt *)0;
228 	duplist = (struct dups *)0;
229 	inocleanup();
230 	if (fsmodified) {
231 		(void)time(&sblock.fs_time);
232 		sbdirty();
233 	}
234 	ckfini();
235 	free(blockmap);
236 	free(statemap);
237 	free((char *)lncntp);
238 	if (!fsmodified)
239 		return (0);
240 	if (!preen) {
241 		printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
242 		if (hotroot)
243 			printf("\n***** REBOOT UNIX *****\n");
244 	}
245 	if (hotroot) {
246 		sync();
247 		return (4);
248 	}
249 	return (0);
250 }
251