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