string.h is ANSI C include file
[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
5f229d0b 19static char sccsid[] = "@(#)preen.c 5.2 (Berkeley) %G%";
5211717f
KM
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
5f229d0b
KM
46int nrun, ndisks;
47char hotroot;
5211717f
KM
48
49checkfstab(preen, maxrun, docheck, chkit)
50 int preen, maxrun;
51 int (*docheck)(), (*chkit)();
52{
53 register struct fstab *fsp;
54 register struct disk *dk, *nextdisk;
55 register struct part *pt;
56 int ret, pid, retcode, passno, sumstatus, status;
57 long auxdata;
58 char *name;
59
60 sumstatus = 0;
61 for (passno = 1; passno <= 2; passno++) {
62 if (setfsent() == 0) {
63 fprintf(stderr, "Can't open checklist file: %s\n",
64 _PATH_FSTAB);
65 return (8);
66 }
67 while ((fsp = getfsent()) != 0) {
68 if ((auxdata = (*docheck)(fsp)) == 0)
69 continue;
70 if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
71 if (name = blockcheck(fsp->fs_spec)) {
72 if (sumstatus = (*chkit)(name,
73 fsp->fs_file, auxdata))
74 return (sumstatus);
75 } else if (preen)
76 return (8);
77 } else if (passno == 2 && fsp->fs_passno > 1) {
78 if ((name = blockcheck(fsp->fs_spec)) == NULL) {
79 fprintf(stderr, "BAD DISK NAME %s\n",
80 fsp->fs_spec);
81 sumstatus |= 8;
82 continue;
83 }
84 addpart(name, fsp->fs_file, auxdata);
85 }
86 }
87 if (preen == 0)
88 return (0);
89 }
90 if (preen) {
91 if (maxrun == 0)
92 maxrun = ndisks;
93 if (maxrun > ndisks)
94 maxrun = ndisks;
95 nextdisk = disks;
96 for (passno = 0; passno < maxrun; ++passno) {
97 while (ret = startdisk(nextdisk, chkit) && nrun > 0)
98 sleep(10);
99 if (ret)
100 return (ret);
101 nextdisk = nextdisk->next;
102 }
103 while ((pid = wait(&status)) != -1) {
104 for (dk = disks; dk; dk = dk->next)
105 if (dk->pid == pid)
106 break;
107 if (dk == 0) {
108 printf("Unknown pid %d\n", pid);
109 continue;
110 }
111 if (WIFEXITED(status))
112 retcode = WEXITSTATUS(status);
113 else
114 retcode = 0;
115 if (WIFSIGNALED(status)) {
116 printf("%s (%s): EXITED WITH SIGNAL %d\n",
117 dk->part->name, dk->part->fsname,
118 WTERMSIG(status));
119 retcode = 8;
120 }
121 if (retcode != 0) {
122 sumstatus |= retcode;
123 *badnext = dk->part;
124 badnext = &dk->part->next;
125 dk->part = dk->part->next;
126 *badnext = NULL;
127 } else
128 dk->part = dk->part->next;
129 dk->pid = 0;
130 nrun--;
131 if (dk->part == NULL)
132 ndisks--;
133
134 if (nextdisk == NULL) {
135 if (dk->part) {
136 while (ret = startdisk(dk, chkit) &&
137 nrun > 0)
138 sleep(10);
139 if (ret)
140 return (ret);
141 }
142 } else if (nrun < maxrun && nrun < ndisks) {
143 for ( ;; ) {
144 if ((nextdisk = nextdisk->next) == NULL)
145 nextdisk = disks;
146 if (nextdisk->part != NULL &&
147 nextdisk->pid == 0)
148 break;
149 }
150 while (ret = startdisk(nextdisk, chkit) &&
151 nrun > 0)
152 sleep(10);
153 if (ret)
154 return (ret);
155 }
156 }
157 }
158 if (sumstatus) {
159 if (badlist == 0)
160 return (sumstatus);
161 fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
162 badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
163 for (pt = badlist; pt; pt = pt->next)
164 fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname,
165 pt->next ? ", " : "\n");
166 return (sumstatus);
167 }
168 (void)endfsent();
169 return (0);
170}
171
172struct disk *
173finddisk(name)
174 char *name;
175{
176 register struct disk *dk, **dkp;
177 register char *p;
178 int len;
179
180 for (p = name + strlen(name) - 1; p >= name; --p)
181 if (isdigit(*p)) {
182 len = p - name + 1;
183 break;
184 }
185 if (p < name)
186 len = strlen(name);
187
188 for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
189 if (strncmp(dk->name, name, len) == 0 &&
190 dk->name[len] == 0)
191 return (dk);
192 }
193 if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) {
194 fprintf(stderr, "out of memory");
195 exit (8);
196 }
197 dk = *dkp;
198 if ((dk->name = malloc((unsigned int)len + 1)) == NULL) {
199 fprintf(stderr, "out of memory");
200 exit (8);
201 }
202 strncpy(dk->name, name, len);
203 dk->name[len] = '\0';
204 dk->part = NULL;
205 dk->next = NULL;
206 dk->pid = 0;
207 ndisks++;
208 return (dk);
209}
210
211addpart(name, fsname, auxdata)
212 char *name, *fsname;
213 long auxdata;
214{
215 struct disk *dk = finddisk(name);
216 register struct part *pt, **ppt = &dk->part;
217
218 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
219 if (strcmp(pt->name, name) == 0) {
220 printf("%s in fstab more than once!\n", name);
221 return;
222 }
223 if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) {
224 fprintf(stderr, "out of memory");
225 exit (8);
226 }
227 pt = *ppt;
228 if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL) {
229 fprintf(stderr, "out of memory");
230 exit (8);
231 }
232 strcpy(pt->name, name);
233 if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL) {
234 fprintf(stderr, "out of memory");
235 exit (8);
236 }
237 strcpy(pt->fsname, fsname);
238 pt->next = NULL;
239 pt->auxdata = auxdata;
240}
241
242startdisk(dk, checkit)
243 register struct disk *dk;
244 int (*checkit)();
245{
246 register struct part *pt = dk->part;
247
248 dk->pid = fork();
249 if (dk->pid < 0) {
250 perror("fork");
251 return (8);
252 }
253 if (dk->pid == 0)
254 exit((*checkit)(pt->name, pt->fsname, pt->auxdata));
255 nrun++;
256 return (0);
257}
258
259char *
260blockcheck(name)
261 char *name;
262{
263 struct stat stslash, stblock, stchar;
264 char *raw;
265 int retried = 0;
266
267 hotroot = 0;
268 if (stat("/", &stslash) < 0) {
269 perror("/");
270 printf("Can't stat root\n");
271 return (0);
272 }
273retry:
274 if (stat(name, &stblock) < 0) {
275 perror(name);
276 printf("Can't stat %s\n", name);
277 return (0);
278 }
279 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
280 if (stslash.st_dev == stblock.st_rdev)
281 hotroot++;
282 raw = rawname(name);
283 if (stat(raw, &stchar) < 0) {
284 perror(raw);
285 printf("Can't stat %s\n", raw);
286 return (name);
287 }
288 if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
289 return (raw);
290 } else {
291 printf("%s is not a character device\n", raw);
292 return (name);
293 }
294 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
295 name = unrawname(name);
296 retried++;
297 goto retry;
298 }
299 printf("Can't make sense out of name %s\n", name);
300 return (0);
301}
302
303char *
304unrawname(name)
305 char *name;
306{
307 char *dp;
308 struct stat stb;
309
310 if ((dp = rindex(name, '/')) == 0)
311 return (name);
312 if (stat(name, &stb) < 0)
313 return (name);
314 if ((stb.st_mode & S_IFMT) != S_IFCHR)
315 return (name);
316 if (*(dp + 1) != 'r')
317 return (name);
318 (void)strcpy(dp + 1, dp + 2);
319 return (name);
320}
321
322char *
323rawname(name)
324 char *name;
325{
326 static char rawbuf[32];
327 char *dp;
328
329 if ((dp = rindex(name, '/')) == 0)
330 return (0);
331 *dp = 0;
332 (void)strcpy(rawbuf, name);
333 *dp = '/';
334 (void)strcat(rawbuf, "/r");
335 (void)strcat(rawbuf, dp + 1);
336 return (rawbuf);
337}