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