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