main.c revision 1.3
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
41static char sccsid[] = "@(#)main.c	5.27 (Berkeley) 8/7/90";
42static char rcsid[] = "$Header: /usr/local/opengrok/home/cvs-mirror/mirrors/netbsd/src/sbin/fsck_ffs/main.c,v 1.3 1993/03/23 00:27:55 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
173	if (preen && child)
174		(void)signal(SIGQUIT, voidquit);
175	devname = filesys;
176	if (debug && preen)
177		pwarn("starting\n");
178	if (setup(filesys) == 0) {
179		if (preen)
180			pfatal("CAN'T CHECK FILE SYSTEM.");
181		return (0);
182	}
183	/*
184	 * 1: scan inodes tallying blocks used
185	 */
186	if (preen == 0) {
187		printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
188		if (hotroot)
189			printf("** Root file system\n");
190		printf("** Phase 1 - Check Blocks and Sizes\n");
191	}
192	pass1();
193
194	/*
195	 * 1b: locate first references to duplicates, if any
196	 */
197	if (duplist) {
198		if (preen)
199			pfatal("INTERNAL ERROR: dups with -p");
200		printf("** Phase 1b - Rescan For More DUPS\n");
201		pass1b();
202	}
203
204	/*
205	 * 2: traverse directories from root to mark all connected directories
206	 */
207	if (preen == 0)
208		printf("** Phase 2 - Check Pathnames\n");
209	pass2();
210
211	/*
212	 * 3: scan inodes looking for disconnected directories
213	 */
214	if (preen == 0)
215		printf("** Phase 3 - Check Connectivity\n");
216	pass3();
217
218	/*
219	 * 4: scan inodes looking for disconnected files; check reference counts
220	 */
221	if (preen == 0)
222		printf("** Phase 4 - Check Reference Counts\n");
223	pass4();
224
225	/*
226	 * 5: check and repair resource counts in cylinder groups
227	 */
228	if (preen == 0)
229		printf("** Phase 5 - Check Cyl groups\n");
230	pass5();
231
232	/*
233	 * print out summary statistics
234	 */
235	n_ffree = sblock.fs_cstotal.cs_nffree;
236	n_bfree = sblock.fs_cstotal.cs_nbfree;
237	pwarn("%ld files, %ld used, %ld free ",
238	    n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
239	printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n",
240	    n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
241	if (debug &&
242	    (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
243		printf("%ld files missing\n", n_files);
244	if (debug) {
245		n_blks += sblock.fs_ncg *
246			(cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
247		n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
248		n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
249		if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
250			printf("%ld blocks missing\n", n_blks);
251		if (duplist != NULL) {
252			printf("The following duplicate blocks remain:");
253			for (dp = duplist; dp; dp = dp->next)
254				printf(" %ld,", dp->dup);
255			printf("\n");
256		}
257		if (zlnhead != NULL) {
258			printf("The following zero link count inodes remain:");
259			for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
260				printf(" %lu,", zlnp->zlncnt);
261			printf("\n");
262		}
263	}
264	zlnhead = (struct zlncnt *)0;
265	duplist = (struct dups *)0;
266	inocleanup();
267	if (fsmodified) {
268		(void)time(&sblock.fs_time);
269		sbdirty();
270	}
271	ckfini();
272	free(blockmap);
273	free(statemap);
274	free((char *)lncntp);
275	if (!fsmodified)
276		return (0);
277	if (!preen) {
278		printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
279		if (hotroot)
280			printf("\n***** REBOOT UNIX *****\n");
281	}
282	if (hotroot) {
283		sync();
284		return (4);
285	}
286	return (0);
287}
288