main.c revision 1.11
1/*
2 * Copyright (c) 1980, 1986 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35char copyright[] =
36"@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\
37 All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41/*static char sccsid[] = "from: @(#)main.c	5.27 (Berkeley) 8/7/90";*/
42static char rcsid[] = "$Id: main.c,v 1.11 1994/04/06 00:08:58 cgd Exp $";
43#endif /* not lint */
44
45#include <sys/param.h>
46#include <ufs/dinode.h>
47#include <ufs/fs.h>
48#include <fstab.h>
49#include <stdlib.h>
50#include <string.h>
51#include <ctype.h>
52#include <stdio.h>
53#include "fsck.h"
54
55void	catch(), catchquit(), voidquit();
56int	returntosingle;
57
58main(argc, argv)
59	int	argc;
60	char	*argv[];
61{
62	int ch;
63	int ret, maxrun = 0;
64	extern int docheck(), checkfilesys();
65	extern char *optarg;
66	extern int optind;
67
68	sync();
69	while ((ch = getopt(argc, argv, "cdpnNyYb:l:m:")) != EOF) {
70		switch (ch) {
71		case 'p':
72			preen++;
73			break;
74
75		case 'b':
76			bflag = argtoi('b', "number", optarg, 10);
77			printf("Alternate super block location: %d\n", bflag);
78			break;
79
80		case 'c':
81			cvtflag++;
82			break;
83
84		case 'd':
85			debug++;
86			break;
87
88		case 'l':
89			maxrun = argtoi('l', "number", optarg, 10);
90			break;
91
92		case 'm':
93			lfmode = argtoi('m', "mode", optarg, 8);
94			if (lfmode &~ 07777)
95				errexit("bad mode to -m: %o\n", lfmode);
96			printf("** lost+found creation mode %o\n", lfmode);
97			break;
98
99		case 'n':
100		case 'N':
101			nflag++;
102			yflag = 0;
103			break;
104
105		case 'y':
106		case 'Y':
107			yflag++;
108			nflag = 0;
109			break;
110
111		default:
112			errexit("%c option?\n", ch);
113		}
114	}
115	argc -= optind;
116	argv += optind;
117	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
118		(void)signal(SIGINT, catch);
119	if (preen)
120		(void)signal(SIGQUIT, catchquit);
121	if (argc) {
122		while (argc-- > 0)
123			(void)checkfilesys(*argv++, (char *)0, 0L, 0);
124		exit(0);
125	}
126	ret = checkfstab(preen, maxrun, docheck, checkfilesys);
127	if (returntosingle)
128		exit(2);
129	exit(ret);
130}
131
132argtoi(flag, req, str, base)
133	int flag;
134	char *req, *str;
135	int base;
136{
137	char *cp;
138	int ret;
139
140	ret = (int)strtol(str, &cp, base);
141	if (cp == str || *cp)
142		errexit("-%c flag requires a %s\n", flag, req);
143	return (ret);
144}
145
146/*
147 * Determine whether a filesystem should be checked.
148 */
149docheck(fsp)
150	register struct fstab *fsp;
151{
152
153	if (strcmp(fsp->fs_vfstype, "ufs") ||
154	    (strcmp(fsp->fs_type, FSTAB_RW) &&
155	     strcmp(fsp->fs_type, FSTAB_RO)) ||
156	    fsp->fs_passno == 0)
157		return (0);
158	return (1);
159}
160
161/*
162 * Check the specified filesystem.
163 */
164/* ARGSUSED */
165checkfilesys(filesys, mntpt, auxdata, child)
166	char *filesys, *mntpt;
167	long auxdata;
168{
169	daddr_t n_ffree, n_bfree;
170	struct dups *dp;
171	struct zlncnt *zlnp;
172	int clean;
173
174	if (preen && child)
175		(void)signal(SIGQUIT, voidquit);
176	devname = filesys;
177	if (debug && preen)
178		pwarn("starting\n");
179	if (setup(filesys) == 0) {
180		if (preen)
181			pfatal("CAN'T CHECK FILE SYSTEM.");
182		return (0);
183	}
184
185	/*
186	 * 0: check whether file system is already clean
187	 */
188	clean = preen && (sblock.fs_state == FSOKAY) && sblock.fs_clean;
189
190#ifdef notyet
191	if (clean) {
192#else
193	if (0) {
194#endif
195		printf("** filesystem clean -- skipping checks\n");
196	} else {
197		/*
198		 * 1: scan inodes tallying blocks used
199		 */
200		if (preen == 0) {
201			printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
202			if (hotroot)
203				printf("** Root file system\n");
204			printf("** Phase 1 - Check Blocks and Sizes\n");
205		}
206		pass1();
207
208		/*
209		 * 1b: locate first references to duplicates, if any
210		 */
211		if (duplist) {
212			if (preen)
213				pfatal("INTERNAL ERROR: dups with -p");
214			printf("** Phase 1b - Rescan For More DUPS\n");
215			pass1b();
216		}
217
218		/*
219		 * 2: traverse directories from root to mark all connected
220		 * directories
221		 */
222		if (preen == 0)
223			printf("** Phase 2 - Check Pathnames\n");
224		pass2();
225
226		/*
227		 * 3: scan inodes looking for disconnected directories
228		 */
229		if (preen == 0)
230			printf("** Phase 3 - Check Connectivity\n");
231		pass3();
232
233		/*
234		 * 4: scan inodes looking for disconnected files; check
235		 * reference counts
236		 */
237		if (preen == 0)
238			printf("** Phase 4 - Check Reference Counts\n");
239		pass4();
240
241		/*
242		 * 5: check and repair resource counts in cylinder groups
243		 */
244		if (preen == 0)
245			printf("** Phase 5 - Check Cyl groups\n");
246		pass5();
247	}
248
249	/*
250	 * print out summary statistics
251	 */
252	n_ffree = sblock.fs_cstotal.cs_nffree;
253	n_bfree = sblock.fs_cstotal.cs_nbfree;
254	pwarn("%ld files, %ld used, %ld free ",
255	    n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
256	printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n",
257	    n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
258	if (debug &&
259	    (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
260		printf("%ld files missing\n", n_files);
261	if (debug) {
262		n_blks += sblock.fs_ncg *
263			(cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
264		n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
265		n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
266		if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
267			printf("%ld blocks missing\n", n_blks);
268		if (duplist != NULL) {
269			printf("The following duplicate blocks remain:");
270			for (dp = duplist; dp; dp = dp->next)
271				printf(" %ld,", dp->dup);
272			printf("\n");
273		}
274		if (zlnhead != NULL) {
275			printf("The following zero link count inodes remain:");
276			for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
277				printf(" %lu,", zlnp->zlncnt);
278			printf("\n");
279		}
280	}
281	zlnhead = (struct zlncnt *)0;
282	duplist = (struct dups *)0;
283	inocleanup();
284#ifdef notyet
285	if (!clean && !nflag && fswritefd != -1) {
286		sblock.fs_state = FSOKAY;
287		sblock.fs_clean = FS_CLEANFREQ;
288		fsmodified = 1;
289	}
290#endif
291	if (fsmodified) {
292		(void)time(&sblock.fs_time);
293		sbdirty();
294	}
295	ckfini();
296	free(blockmap);
297	free(statemap);
298	free((char *)lncntp);
299	if (!fsmodified)
300		return (0);
301	if (!preen) {
302		printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
303		if (hotroot)
304			printf("\n***** REBOOT NETBSD *****\n");
305	}
306	if (hotroot) {
307		sync();
308		return (4);
309	}
310	return (0);
311}
312