main.c revision 1.11 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
35 char 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
41 /*static char sccsid[] = "from: @(#)main.c 5.27 (Berkeley) 8/7/90";*/
42 static char rcsid[] = "$Id: main.c,v 1.11 1994/04/06 00:08:58 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
55 void catch(), catchquit(), voidquit();
56 int returntosingle;
57
58 main(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
132 argtoi(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 */
149 docheck(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 */
165 checkfilesys(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 int clean;
173
174 if (preen && child)
175 (void)signal(SIGQUIT, voidquit);
176 devname = filesys;
177 if (debug && preen)
178 pwarn("starting\n");
179 if (setup(filesys) == 0) {
180 if (preen)
181 pfatal("CAN'T CHECK FILE SYSTEM.");
182 return (0);
183 }
184
185 /*
186 * 0: check whether file system is already clean
187 */
188 clean = preen && (sblock.fs_state == FSOKAY) && sblock.fs_clean;
189
190 #ifdef notyet
191 if (clean) {
192 #else
193 if (0) {
194 #endif
195 printf("** filesystem clean -- skipping checks\n");
196 } else {
197 /*
198 * 1: scan inodes tallying blocks used
199 */
200 if (preen == 0) {
201 printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
202 if (hotroot)
203 printf("** Root file system\n");
204 printf("** Phase 1 - Check Blocks and Sizes\n");
205 }
206 pass1();
207
208 /*
209 * 1b: locate first references to duplicates, if any
210 */
211 if (duplist) {
212 if (preen)
213 pfatal("INTERNAL ERROR: dups with -p");
214 printf("** Phase 1b - Rescan For More DUPS\n");
215 pass1b();
216 }
217
218 /*
219 * 2: traverse directories from root to mark all connected
220 * directories
221 */
222 if (preen == 0)
223 printf("** Phase 2 - Check Pathnames\n");
224 pass2();
225
226 /*
227 * 3: scan inodes looking for disconnected directories
228 */
229 if (preen == 0)
230 printf("** Phase 3 - Check Connectivity\n");
231 pass3();
232
233 /*
234 * 4: scan inodes looking for disconnected files; check
235 * reference counts
236 */
237 if (preen == 0)
238 printf("** Phase 4 - Check Reference Counts\n");
239 pass4();
240
241 /*
242 * 5: check and repair resource counts in cylinder groups
243 */
244 if (preen == 0)
245 printf("** Phase 5 - Check Cyl groups\n");
246 pass5();
247 }
248
249 /*
250 * print out summary statistics
251 */
252 n_ffree = sblock.fs_cstotal.cs_nffree;
253 n_bfree = sblock.fs_cstotal.cs_nbfree;
254 pwarn("%ld files, %ld used, %ld free ",
255 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
256 printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n",
257 n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
258 if (debug &&
259 (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
260 printf("%ld files missing\n", n_files);
261 if (debug) {
262 n_blks += sblock.fs_ncg *
263 (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
264 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
265 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
266 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
267 printf("%ld blocks missing\n", n_blks);
268 if (duplist != NULL) {
269 printf("The following duplicate blocks remain:");
270 for (dp = duplist; dp; dp = dp->next)
271 printf(" %ld,", dp->dup);
272 printf("\n");
273 }
274 if (zlnhead != NULL) {
275 printf("The following zero link count inodes remain:");
276 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
277 printf(" %lu,", zlnp->zlncnt);
278 printf("\n");
279 }
280 }
281 zlnhead = (struct zlncnt *)0;
282 duplist = (struct dups *)0;
283 inocleanup();
284 #ifdef notyet
285 if (!clean && !nflag && fswritefd != -1) {
286 sblock.fs_state = FSOKAY;
287 sblock.fs_clean = FS_CLEANFREQ;
288 fsmodified = 1;
289 }
290 #endif
291 if (fsmodified) {
292 (void)time(&sblock.fs_time);
293 sbdirty();
294 }
295 ckfini();
296 free(blockmap);
297 free(statemap);
298 free((char *)lncntp);
299 if (!fsmodified)
300 return (0);
301 if (!preen) {
302 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
303 if (hotroot)
304 printf("\n***** REBOOT NETBSD *****\n");
305 }
306 if (hotroot) {
307 sync();
308 return (4);
309 }
310 return (0);
311 }
312