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