|
|
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.4 (Berkeley) 3/5/86";
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:
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);
79: if (preen)
80: (void)signal(SIGQUIT, catchquit);
81: if (argc) {
82: while (argc-- > 0) {
83: hotroot = 0;
84: checkfilesys(*argv++);
85: }
86: exit(0);
87: }
88: sumstatus = 0;
89: passno = 1;
90: do {
91: anygtr = 0;
92: if (setfsent() == 0)
93: errexit("Can't open checklist file: %s\n", FSTAB);
94: while ((fsp = getfsent()) != 0) {
95: if (strcmp(fsp->fs_type, FSTAB_RW) &&
96: strcmp(fsp->fs_type, FSTAB_RO) &&
97: strcmp(fsp->fs_type, FSTAB_RQ))
98: continue;
99: if (preen == 0 ||
100: passno == 1 && fsp->fs_passno == passno) {
101: name = blockcheck(fsp->fs_spec);
102: if (name != NULL)
103: checkfilesys(name);
104: else if (preen)
105: exit(8);
106: } else if (fsp->fs_passno > passno) {
107: anygtr = 1;
108: } else if (fsp->fs_passno == passno) {
109: pid = fork();
110: if (pid < 0) {
111: perror("fork");
112: exit(8);
113: }
114: if (pid == 0) {
115: (void)signal(SIGQUIT, voidquit);
116: name = blockcheck(fsp->fs_spec);
117: if (name == NULL)
118: exit(8);
119: checkfilesys(name);
120: exit(0);
121: }
122: }
123: }
124: if (preen) {
125: union wait status;
126: while (wait(&status) != -1)
127: sumstatus |= status.w_retcode;
128: }
129: passno++;
130: } while (anygtr);
131: if (sumstatus)
132: exit(8);
133: (void)endfsent();
134: if (returntosingle)
135: exit(2);
136: exit(0);
137: }
138:
139: checkfilesys(filesys)
140: char *filesys;
141: {
142: daddr_t n_ffree, n_bfree;
143: struct dups *dp;
144: struct zlncnt *zlnp;
145:
146: devname = filesys;
147: if (setup(filesys) == 0) {
148: if (preen)
149: pfatal("CAN'T CHECK FILE SYSTEM.");
150: return;
151: }
152: /*
153: * 1: scan inodes tallying blocks used
154: */
155: if (preen == 0) {
156: printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
157: if (hotroot)
158: printf("** Root file system\n");
159: printf("** Phase 1 - Check Blocks and Sizes\n");
160: }
161: pass1();
162:
163: /*
164: * 1b: locate first references to duplicates, if any
165: */
166: if (duplist) {
167: if (preen)
168: pfatal("INTERNAL ERROR: dups with -p");
169: printf("** Phase 1b - Rescan For More DUPS\n");
170: pass1b();
171: }
172:
173: /*
174: * 2: traverse directories from root to mark all connected directories
175: */
176: if (preen == 0)
177: printf("** Phase 2 - Check Pathnames\n");
178: pass2();
179:
180: /*
181: * 3: scan inodes looking for disconnected directories
182: */
183: if (preen == 0)
184: printf("** Phase 3 - Check Connectivity\n");
185: pass3();
186:
187: /*
188: * 4: scan inodes looking for disconnected files; check reference counts
189: */
190: if (preen == 0)
191: printf("** Phase 4 - Check Reference Counts\n");
192: pass4();
193:
194: /*
195: * 5: check and repair resource counts in cylinder groups
196: */
197: if (preen == 0)
198: printf("** Phase 5 - Check Cyl groups\n");
199: pass5();
200:
201: /*
202: * print out summary statistics
203: */
204: n_ffree = sblock.fs_cstotal.cs_nffree;
205: n_bfree = sblock.fs_cstotal.cs_nbfree;
206: pwarn("%d files, %d used, %d free ",
207: n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
208: printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
209: n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
210: if (debug && (n_files -= imax - ROOTINO - sblock.fs_cstotal.cs_nifree))
211: printf("%d files missing\n", n_files);
212: if (debug) {
213: n_blks += sblock.fs_ncg *
214: (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
215: n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
216: n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
217: if (n_blks -= fmax - (n_ffree + sblock.fs_frag * n_bfree))
218: printf("%d blocks missing\n", n_blks);
219: if (duplist != NULL) {
220: printf("The following duplicate blocks remain:");
221: for (dp = duplist; dp; dp = dp->next)
222: printf(" %d,", dp->dup);
223: printf("\n");
224: }
225: if (zlnhead != NULL) {
226: printf("The following zero link count inodes remain:");
227: for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
228: printf(" %d,", zlnp->zlncnt);
229: printf("\n");
230: }
231: }
232: zlnhead = (struct zlncnt *)0;
233: duplist = (struct dups *)0;
234: if (dfile.mod) {
235: (void)time(&sblock.fs_time);
236: sbdirty();
237: }
238: ckfini();
239: free(blockmap);
240: free(statemap);
241: free((char *)lncntp);
242: if (!dfile.mod)
243: return;
244: if (!preen) {
245: printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
246: if (hotroot)
247: printf("\n***** REBOOT UNIX *****\n");
248: }
249: if (hotroot) {
250: sync();
251: exit(4);
252: }
253: }
254:
255: char *
256: blockcheck(name)
257: char *name;
258: {
259: struct stat stslash, stblock, stchar;
260: char *raw;
261: int looped = 0;
262:
263: hotroot = 0;
264: if (stat("/", &stslash) < 0){
265: printf("Can't stat root\n");
266: return (0);
267: }
268: retry:
269: if (stat(name, &stblock) < 0){
270: printf("Can't stat %s\n", name);
271: return (0);
272: }
273: if (stblock.st_mode & S_IFBLK) {
274: raw = rawname(name);
275: if (stat(raw, &stchar) < 0){
276: printf("Can't stat %s\n", raw);
277: return (0);
278: }
279: if (stchar.st_mode & S_IFCHR) {
280: if (stslash.st_dev == stblock.st_rdev) {
281: hotroot++;
282: raw = unrawname(name);
283: }
284: return (raw);
285: } else {
286: printf("%s is not a character device\n", raw);
287: return (0);
288: }
289: } else if (stblock.st_mode & S_IFCHR) {
290: if (looped) {
291: printf("Can't make sense out of name %s\n", name);
292: return (0);
293: }
294: name = unrawname(name);
295: looped++;
296: goto retry;
297: }
298: printf("Can't make sense out of name %s\n", name);
299: return (0);
300: }
301:
302: char *
303: unrawname(cp)
304: char *cp;
305: {
306: char *dp = rindex(cp, '/');
307: struct stat stb;
308:
309: if (dp == 0)
310: return (cp);
311: if (stat(cp, &stb) < 0)
312: return (cp);
313: if ((stb.st_mode&S_IFMT) != S_IFCHR)
314: return (cp);
315: if (*(dp+1) != 'r')
316: return (cp);
317: (void)strcpy(dp+1, dp+2);
318: return (cp);
319: }
320:
321: char *
322: rawname(cp)
323: char *cp;
324: {
325: static char rawbuf[32];
326: char *dp = rindex(cp, '/');
327:
328: if (dp == 0)
329: return (0);
330: *dp = 0;
331: (void)strcpy(rawbuf, cp);
332: *dp = '/';
333: (void)strcat(rawbuf, "/r");
334: (void)strcat(rawbuf, dp+1);
335: return (rawbuf);
336: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.