|
|
1.1 root 1: /*
2: * Copyright (c) 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)preen.c 5.5 (Berkeley) 7/20/90";
22: #endif /* not lint */
23:
24: #include <sys/param.h>
25: #include <sys/stat.h>
26: #include <sys/wait.h>
27: #include <fstab.h>
28: #include <string.h>
29: #include <stdio.h>
30: #include <stdlib.h>
31: #include <ctype.h>
32:
33: char *rawname(), *unrawname(), *blockcheck();
34:
35: struct part {
36: struct part *next; /* forward link of partitions on disk */
37: char *name; /* device name */
38: char *fsname; /* mounted filesystem name */
39: long auxdata; /* auxillary data for application */
40: } *badlist, **badnext = &badlist;
41:
42: struct disk {
43: char *name; /* disk base name */
44: struct disk *next; /* forward link for list of disks */
45: struct part *part; /* head of list of partitions on disk */
46: int pid; /* If != 0, pid of proc working on */
47: } *disks;
48:
49: int nrun, ndisks;
50: char hotroot;
51:
52: checkfstab(preen, maxrun, docheck, chkit)
53: int preen, maxrun;
54: int (*docheck)(), (*chkit)();
55: {
56: register struct fstab *fsp;
57: register struct disk *dk, *nextdisk;
58: register struct part *pt;
59: int ret, pid, retcode, passno, sumstatus, status;
60: long auxdata;
61: char *name;
62:
63: sumstatus = 0;
64: for (passno = 1; passno <= 2; passno++) {
65: if (setfsent() == 0) {
66: fprintf(stderr, "Can't open checklist file: %s\n",
67: _PATH_FSTAB);
68: return (8);
69: }
70: while ((fsp = getfsent()) != 0) {
71: if ((auxdata = (*docheck)(fsp)) == 0)
72: continue;
73: if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
74: if (name = blockcheck(fsp->fs_spec)) {
75: if (sumstatus = (*chkit)(name,
76: fsp->fs_file, auxdata))
77: return (sumstatus);
78: } else if (preen)
79: return (8);
80: } else if (passno == 2 && fsp->fs_passno > 1) {
81: if ((name = blockcheck(fsp->fs_spec)) == NULL) {
82: fprintf(stderr, "BAD DISK NAME %s\n",
83: fsp->fs_spec);
84: sumstatus |= 8;
85: continue;
86: }
87: addpart(name, fsp->fs_file, auxdata);
88: }
89: }
90: if (preen == 0)
91: return (0);
92: }
93: if (preen) {
94: if (maxrun == 0)
95: maxrun = ndisks;
96: if (maxrun > ndisks)
97: maxrun = ndisks;
98: nextdisk = disks;
99: for (passno = 0; passno < maxrun; ++passno) {
100: while (ret = startdisk(nextdisk, chkit) && nrun > 0)
101: sleep(10);
102: if (ret)
103: return (ret);
104: nextdisk = nextdisk->next;
105: }
106: while ((pid = wait(&status)) != -1) {
107: for (dk = disks; dk; dk = dk->next)
108: if (dk->pid == pid)
109: break;
110: if (dk == 0) {
111: printf("Unknown pid %d\n", pid);
112: continue;
113: }
114: if (WIFEXITED(status))
115: retcode = WEXITSTATUS(status);
116: else
117: retcode = 0;
118: if (WIFSIGNALED(status)) {
119: printf("%s (%s): EXITED WITH SIGNAL %d\n",
120: dk->part->name, dk->part->fsname,
121: WTERMSIG(status));
122: retcode = 8;
123: }
124: if (retcode != 0) {
125: sumstatus |= retcode;
126: *badnext = dk->part;
127: badnext = &dk->part->next;
128: dk->part = dk->part->next;
129: *badnext = NULL;
130: } else
131: dk->part = dk->part->next;
132: dk->pid = 0;
133: nrun--;
134: if (dk->part == NULL)
135: ndisks--;
136:
137: if (nextdisk == NULL) {
138: if (dk->part) {
139: while (ret = startdisk(dk, chkit) &&
140: nrun > 0)
141: sleep(10);
142: if (ret)
143: return (ret);
144: }
145: } else if (nrun < maxrun && nrun < ndisks) {
146: for ( ;; ) {
147: if ((nextdisk = nextdisk->next) == NULL)
148: nextdisk = disks;
149: if (nextdisk->part != NULL &&
150: nextdisk->pid == 0)
151: break;
152: }
153: while (ret = startdisk(nextdisk, chkit) &&
154: nrun > 0)
155: sleep(10);
156: if (ret)
157: return (ret);
158: }
159: }
160: }
161: if (sumstatus) {
162: if (badlist == 0)
163: return (sumstatus);
164: fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
165: badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
166: for (pt = badlist; pt; pt = pt->next)
167: fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname,
168: pt->next ? ", " : "\n");
169: return (sumstatus);
170: }
171: (void)endfsent();
172: return (0);
173: }
174:
175: struct disk *
176: finddisk(name)
177: char *name;
178: {
179: register struct disk *dk, **dkp;
180: register char *p;
181: size_t len;
182:
183: for (p = name + strlen(name) - 1; p >= name; --p)
184: if (isdigit(*p)) {
185: len = p - name + 1;
186: break;
187: }
188: if (p < name)
189: len = strlen(name);
190:
191: for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
192: if (strncmp(dk->name, name, len) == 0 &&
193: dk->name[len] == 0)
194: return (dk);
195: }
196: if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) {
197: fprintf(stderr, "out of memory");
198: exit (8);
199: }
200: dk = *dkp;
201: if ((dk->name = malloc(len + 1)) == NULL) {
202: fprintf(stderr, "out of memory");
203: exit (8);
204: }
205: (void)strncpy(dk->name, name, len);
206: dk->name[len] = '\0';
207: dk->part = NULL;
208: dk->next = NULL;
209: dk->pid = 0;
210: ndisks++;
211: return (dk);
212: }
213:
214: addpart(name, fsname, auxdata)
215: char *name, *fsname;
216: long auxdata;
217: {
218: struct disk *dk = finddisk(name);
219: register struct part *pt, **ppt = &dk->part;
220:
221: for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
222: if (strcmp(pt->name, name) == 0) {
223: printf("%s in fstab more than once!\n", name);
224: return;
225: }
226: if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) {
227: fprintf(stderr, "out of memory");
228: exit (8);
229: }
230: pt = *ppt;
231: if ((pt->name = malloc(strlen(name) + 1)) == NULL) {
232: fprintf(stderr, "out of memory");
233: exit (8);
234: }
235: (void)strcpy(pt->name, name);
236: if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) {
237: fprintf(stderr, "out of memory");
238: exit (8);
239: }
240: (void)strcpy(pt->fsname, fsname);
241: pt->next = NULL;
242: pt->auxdata = auxdata;
243: }
244:
245: startdisk(dk, checkit)
246: register struct disk *dk;
247: int (*checkit)();
248: {
249: register struct part *pt = dk->part;
250:
251: dk->pid = fork();
252: if (dk->pid < 0) {
253: perror("fork");
254: return (8);
255: }
256: if (dk->pid == 0)
257: exit((*checkit)(pt->name, pt->fsname, pt->auxdata));
258: nrun++;
259: return (0);
260: }
261:
262: char *
263: blockcheck(name)
264: char *name;
265: {
266: struct stat stslash, stblock, stchar;
267: char *raw;
268: int retried = 0;
269:
270: hotroot = 0;
271: if (stat("/", &stslash) < 0) {
272: perror("/");
273: printf("Can't stat root\n");
274: return (0);
275: }
276: retry:
277: if (stat(name, &stblock) < 0) {
278: perror(name);
279: printf("Can't stat %s\n", name);
280: return (0);
281: }
282: if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
283: if (stslash.st_dev == stblock.st_rdev)
284: hotroot++;
285: raw = rawname(name);
286: if (stat(raw, &stchar) < 0) {
287: perror(raw);
288: printf("Can't stat %s\n", raw);
289: return (name);
290: }
291: if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
292: return (raw);
293: } else {
294: printf("%s is not a character device\n", raw);
295: return (name);
296: }
297: } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
298: name = unrawname(name);
299: retried++;
300: goto retry;
301: }
302: printf("Can't make sense out of name %s\n", name);
303: return (0);
304: }
305:
306: char *
307: unrawname(name)
308: char *name;
309: {
310: char *dp;
311: struct stat stb;
312:
313: if ((dp = rindex(name, '/')) == 0)
314: return (name);
315: if (stat(name, &stb) < 0)
316: return (name);
317: if ((stb.st_mode & S_IFMT) != S_IFCHR)
318: return (name);
319: if (*(dp + 1) != 'r')
320: return (name);
321: (void)strcpy(dp + 1, dp + 2);
322: return (name);
323: }
324:
325: char *
326: rawname(name)
327: char *name;
328: {
329: static char rawbuf[32];
330: char *dp;
331:
332: if ((dp = rindex(name, '/')) == 0)
333: return (0);
334: *dp = 0;
335: (void)strcpy(rawbuf, name);
336: *dp = '/';
337: (void)strcat(rawbuf, "/r");
338: (void)strcat(rawbuf, dp + 1);
339: return (rawbuf);
340: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.