xref: /original-bsd/sbin/fsck/main.c (revision 860e07fc)
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.32 (Berkeley) 07/02/92";
16 #endif /* not lint */
17 
18 #include <sys/param.h>
19 #include <sys/time.h>
20 #include <ufs/ufs/dinode.h>
21 #include <ufs/ffs/fs.h>
22 #include <fstab.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <stdio.h>
27 #include "fsck.h"
28 
29 void	catch(), catchquit(), voidquit();
30 int	returntosingle;
31 
32 main(argc, argv)
33 	int	argc;
34 	char	*argv[];
35 {
36 	int ch;
37 	int ret, maxrun = 0;
38 	extern int docheck(), checkfilesys();
39 	extern char *optarg;
40 	extern int optind;
41 
42 	sync();
43 	while ((ch = getopt(argc, argv, "dpnNyYb:c:l:m:")) != EOF) {
44 		switch (ch) {
45 		case 'p':
46 			preen++;
47 			break;
48 
49 		case 'b':
50 			bflag = argtoi('b', "number", optarg, 10);
51 			printf("Alternate super block location: %d\n", bflag);
52 			break;
53 
54 		case 'c':
55 			cvtlevel = argtoi('c', "conversion level", optarg, 10);
56 			break;
57 
58 		case 'd':
59 			debug++;
60 			break;
61 
62 		case 'l':
63 			maxrun = argtoi('l', "number", optarg, 10);
64 			break;
65 
66 		case 'm':
67 			lfmode = argtoi('m', "mode", optarg, 8);
68 			if (lfmode &~ 07777)
69 				errexit("bad mode to -m: %o\n", lfmode);
70 			printf("** lost+found creation mode %o\n", lfmode);
71 			break;
72 
73 		case 'n':
74 		case 'N':
75 			nflag++;
76 			yflag = 0;
77 			break;
78 
79 		case 'y':
80 		case 'Y':
81 			yflag++;
82 			nflag = 0;
83 			break;
84 
85 		default:
86 			errexit("%c option?\n", ch);
87 		}
88 	}
89 	argc -= optind;
90 	argv += optind;
91 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
92 		(void)signal(SIGINT, catch);
93 	if (preen)
94 		(void)signal(SIGQUIT, catchquit);
95 	if (argc) {
96 		while (argc-- > 0)
97 			(void)checkfilesys(*argv++, (char *)0, 0L, 0);
98 		exit(0);
99 	}
100 	ret = checkfstab(preen, maxrun, docheck, checkfilesys);
101 	if (returntosingle)
102 		exit(2);
103 	exit(ret);
104 }
105 
106 argtoi(flag, req, str, base)
107 	int flag;
108 	char *req, *str;
109 	int base;
110 {
111 	char *cp;
112 	int ret;
113 
114 	ret = (int)strtol(str, &cp, base);
115 	if (cp == str || *cp)
116 		errexit("-%c flag requires a %s\n", flag, req);
117 	return (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, child)
140 	char *filesys, *mntpt;
141 	long auxdata;
142 {
143 	daddr_t n_ffree, n_bfree;
144 	struct dups *dp;
145 	struct zlncnt *zlnp;
146 	int cylno;
147 
148 	if (preen && child)
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("%ld files, %ld used, %ld free ",
213 	    n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
214 	printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n",
215 	    n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize,
216 	    ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10);
217 	if (debug &&
218 	    (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
219 		printf("%ld files missing\n", n_files);
220 	if (debug) {
221 		n_blks += sblock.fs_ncg *
222 			(cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
223 		n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
224 		n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
225 		if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
226 			printf("%ld blocks missing\n", n_blks);
227 		if (duplist != NULL) {
228 			printf("The following duplicate blocks remain:");
229 			for (dp = duplist; dp; dp = dp->next)
230 				printf(" %ld,", dp->dup);
231 			printf("\n");
232 		}
233 		if (zlnhead != NULL) {
234 			printf("The following zero link count inodes remain:");
235 			for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
236 				printf(" %lu,", zlnp->zlncnt);
237 			printf("\n");
238 		}
239 	}
240 	zlnhead = (struct zlncnt *)0;
241 	duplist = (struct dups *)0;
242 	muldup = (struct dups *)0;
243 	inocleanup();
244 	if (fsmodified) {
245 		(void)time(&sblock.fs_time);
246 		sbdirty();
247 	}
248 	if (cvtlevel && sblk.b_dirty) {
249 		/*
250 		 * Write out the duplicate super blocks
251 		 */
252 		for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
253 			bwrite(fswritefd, (char *)&sblock,
254 			    fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE);
255 	}
256 	ckfini();
257 	free(blockmap);
258 	free(statemap);
259 	free((char *)lncntp);
260 	if (!fsmodified)
261 		return (0);
262 	if (!preen) {
263 		printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
264 		if (hotroot)
265 			printf("\n***** REBOOT UNIX *****\n");
266 	}
267 	if (hotroot) {
268 		sync();
269 		return (4);
270 	}
271 	return (0);
272 }
273