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