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