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