final merger of cfc and csrg termcaps
[unix-history] / usr / src / sbin / fsck / main.c
CommitLineData
76797561
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1980 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
fa95fc59 13#ifndef lint
e8c2f9ee 14static char sccsid[] = "@(#)main.c 5.5 (Berkeley) %G%";
76797561 15#endif not lint
07670f7d 16
4d308541 17#include <sys/param.h>
4d308541 18#include <sys/inode.h>
f7635e39 19#include <sys/fs.h>
7718c0e6
KM
20#include <sys/stat.h>
21#include <sys/wait.h>
22#include <fstab.h>
23#include <strings.h>
f7635e39 24#include "fsck.h"
6e884967 25
7718c0e6 26char *rawname(), *unrawname(), *blockcheck();
3cfe4689
MK
27int catch(), catchquit(), voidquit();
28int returntosingle;
7718c0e6
KM
29int (*signal())();
30
31main(argc, argv)
32 int argc;
33 char *argv[];
34{
35 struct fstab *fsp;
36 int pid, passno, anygtr, sumstatus;
37 char *name;
38
39 sync();
40 while (--argc > 0 && **++argv == '-') {
41 switch (*++*argv) {
42
43 case 'p':
44 preen++;
45 break;
46
47 case 'b':
48 if (argv[0][1] != '\0') {
49 bflag = atoi(argv[0]+1);
50 } else {
51 bflag = atoi(*++argv);
52 argc--;
53 }
54 printf("Alternate super block location: %d\n", bflag);
55 break;
56
57 case 'd':
58 debug++;
59 break;
60
61 case 'n': /* default no answer flag */
62 case 'N':
63 nflag++;
64 yflag = 0;
65 break;
66
67 case 'y': /* default yes answer flag */
68 case 'Y':
69 yflag++;
70 nflag = 0;
71 break;
72
73 default:
74 errexit("%c option?\n", **argv);
75 }
76 }
77 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
78 (void)signal(SIGINT, catch);
3cfe4689
MK
79 if (preen)
80 (void)signal(SIGQUIT, catchquit);
7718c0e6
KM
81 if (argc) {
82 while (argc-- > 0) {
83 hotroot = 0;
e8c2f9ee
KM
84 name = blockcheck(*argv++);
85 checkfilesys(name);
7718c0e6
KM
86 }
87 exit(0);
88 }
89 sumstatus = 0;
90 passno = 1;
91 do {
92 anygtr = 0;
93 if (setfsent() == 0)
94 errexit("Can't open checklist file: %s\n", FSTAB);
95 while ((fsp = getfsent()) != 0) {
96 if (strcmp(fsp->fs_type, FSTAB_RW) &&
97 strcmp(fsp->fs_type, FSTAB_RO) &&
98 strcmp(fsp->fs_type, FSTAB_RQ))
99 continue;
100 if (preen == 0 ||
101 passno == 1 && fsp->fs_passno == passno) {
102 name = blockcheck(fsp->fs_spec);
103 if (name != NULL)
104 checkfilesys(name);
105 else if (preen)
106 exit(8);
107 } else if (fsp->fs_passno > passno) {
108 anygtr = 1;
109 } else if (fsp->fs_passno == passno) {
110 pid = fork();
111 if (pid < 0) {
112 perror("fork");
113 exit(8);
114 }
115 if (pid == 0) {
3cfe4689 116 (void)signal(SIGQUIT, voidquit);
7718c0e6
KM
117 name = blockcheck(fsp->fs_spec);
118 if (name == NULL)
119 exit(8);
120 checkfilesys(name);
121 exit(0);
122 }
123 }
124 }
125 if (preen) {
126 union wait status;
127 while (wait(&status) != -1)
128 sumstatus |= status.w_retcode;
129 }
130 passno++;
131 } while (anygtr);
132 if (sumstatus)
133 exit(8);
134 (void)endfsent();
3cfe4689
MK
135 if (returntosingle)
136 exit(2);
7718c0e6
KM
137 exit(0);
138}
139
d2c95d76
BJ
140checkfilesys(filesys)
141 char *filesys;
6e884967 142{
993a756c 143 daddr_t n_ffree, n_bfree;
d4233021 144 struct dups *dp;
1a02fd3a 145 struct zlncnt *zlnp;
6e884967 146
d2c95d76
BJ
147 devname = filesys;
148 if (setup(filesys) == 0) {
6e884967 149 if (preen)
d2c95d76 150 pfatal("CAN'T CHECK FILE SYSTEM.");
6e884967
KM
151 return;
152 }
993a756c
KM
153 /*
154 * 1: scan inodes tallying blocks used
155 */
690f77ba
KM
156 if (preen == 0) {
157 printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
6e884967
KM
158 if (hotroot)
159 printf("** Root file system\n");
160 printf("** Phase 1 - Check Blocks and Sizes\n");
161 }
d2c95d76
BJ
162 pass1();
163
993a756c
KM
164 /*
165 * 1b: locate first references to duplicates, if any
166 */
62e6c152 167 if (duplist) {
d2c95d76
BJ
168 if (preen)
169 pfatal("INTERNAL ERROR: dups with -p");
170 printf("** Phase 1b - Rescan For More DUPS\n");
171 pass1b();
172 }
173
993a756c
KM
174 /*
175 * 2: traverse directories from root to mark all connected directories
176 */
d2c95d76
BJ
177 if (preen == 0)
178 printf("** Phase 2 - Check Pathnames\n");
179 pass2();
180
993a756c
KM
181 /*
182 * 3: scan inodes looking for disconnected directories
183 */
d2c95d76
BJ
184 if (preen == 0)
185 printf("** Phase 3 - Check Connectivity\n");
186 pass3();
187
993a756c
KM
188 /*
189 * 4: scan inodes looking for disconnected files; check reference counts
190 */
d2c95d76
BJ
191 if (preen == 0)
192 printf("** Phase 4 - Check Reference Counts\n");
193 pass4();
194
993a756c
KM
195 /*
196 * 5: check and repair resource counts in cylinder groups
197 */
d2c95d76
BJ
198 if (preen == 0)
199 printf("** Phase 5 - Check Cyl groups\n");
200 pass5();
201
993a756c
KM
202 /*
203 * print out summary statistics
204 */
205 n_ffree = sblock.fs_cstotal.cs_nffree;
206 n_bfree = sblock.fs_cstotal.cs_nbfree;
8755a38b
KM
207 pwarn("%d files, %d used, %d free ",
208 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
209 printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
210 n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
993a756c
KM
211 if (debug && (n_files -= imax - ROOTINO - sblock.fs_cstotal.cs_nifree))
212 printf("%d files missing\n", n_files);
213 if (debug) {
214 n_blks += sblock.fs_ncg *
215 (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
216 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
217 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
218 if (n_blks -= fmax - (n_ffree + sblock.fs_frag * n_bfree))
219 printf("%d blocks missing\n", n_blks);
d4233021
KM
220 if (duplist != NULL) {
221 printf("The following duplicate blocks remain:");
222 for (dp = duplist; dp; dp = dp->next)
223 printf(" %d,", dp->dup);
224 printf("\n");
225 }
1a02fd3a
KM
226 if (zlnhead != NULL) {
227 printf("The following zero link count inodes remain:");
228 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
229 printf(" %d,", zlnp->zlncnt);
230 printf("\n");
231 }
d2c95d76 232 }
1a02fd3a
KM
233 zlnhead = (struct zlncnt *)0;
234 duplist = (struct dups *)0;
d2c95d76 235 if (dfile.mod) {
1a724405 236 (void)time(&sblock.fs_time);
d2c95d76
BJ
237 sbdirty();
238 }
239 ckfini();
240 free(blockmap);
d2c95d76 241 free(statemap);
1a724405 242 free((char *)lncntp);
addfa1aa
BJ
243 if (!dfile.mod)
244 return;
245 if (!preen) {
246 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
247 if (hotroot)
248 printf("\n***** REBOOT UNIX *****\n");
249 }
250 if (hotroot) {
251 sync();
252 exit(4);
f5971be7 253 }
f5971be7 254}
7718c0e6
KM
255
256char *
257blockcheck(name)
258 char *name;
259{
260 struct stat stslash, stblock, stchar;
261 char *raw;
262 int looped = 0;
263
264 hotroot = 0;
265 if (stat("/", &stslash) < 0){
266 printf("Can't stat root\n");
267 return (0);
268 }
269retry:
270 if (stat(name, &stblock) < 0){
271 printf("Can't stat %s\n", name);
272 return (0);
273 }
e8c2f9ee 274 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
7718c0e6
KM
275 raw = rawname(name);
276 if (stat(raw, &stchar) < 0){
277 printf("Can't stat %s\n", raw);
278 return (0);
279 }
e8c2f9ee 280 if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
7718c0e6
KM
281 if (stslash.st_dev == stblock.st_rdev) {
282 hotroot++;
283 raw = unrawname(name);
284 }
285 return (raw);
286 } else {
287 printf("%s is not a character device\n", raw);
288 return (0);
289 }
e8c2f9ee 290 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR) {
7718c0e6
KM
291 if (looped) {
292 printf("Can't make sense out of name %s\n", name);
293 return (0);
294 }
295 name = unrawname(name);
296 looped++;
297 goto retry;
298 }
299 printf("Can't make sense out of name %s\n", name);
300 return (0);
301}
302
303char *
304unrawname(cp)
305 char *cp;
306{
307 char *dp = rindex(cp, '/');
308 struct stat stb;
309
310 if (dp == 0)
311 return (cp);
312 if (stat(cp, &stb) < 0)
313 return (cp);
314 if ((stb.st_mode&S_IFMT) != S_IFCHR)
315 return (cp);
316 if (*(dp+1) != 'r')
317 return (cp);
318 (void)strcpy(dp+1, dp+2);
319 return (cp);
320}
321
322char *
323rawname(cp)
324 char *cp;
325{
326 static char rawbuf[32];
327 char *dp = rindex(cp, '/');
328
329 if (dp == 0)
330 return (0);
331 *dp = 0;
332 (void)strcpy(rawbuf, cp);
333 *dp = '/';
334 (void)strcat(rawbuf, "/r");
335 (void)strcat(rawbuf, dp+1);
336 return (rawbuf);
337}