if attempts to translate name fails, return original
[unix-history] / usr / src / sbin / fsck / preen.c
CommitLineData
5211717f 1/*
21e5ab9a
KB
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5211717f 4 *
70ab3c27 5 * %sccs.include.redist.c%
5211717f
KM
6 */
7
8#ifndef lint
68b09ac6 9static char sccsid[] = "@(#)preen.c 8.3 (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 *
68b09ac6
KM
251blockcheck(origname)
252 char *origname;
5211717f
KM
253{
254 struct stat stslash, stblock, stchar;
68b09ac6 255 char *newname, *raw;
5211717f
KM
256 int retried = 0;
257
258 hotroot = 0;
259 if (stat("/", &stslash) < 0) {
260 perror("/");
261 printf("Can't stat root\n");
68b09ac6 262 return (origname);
5211717f 263 }
68b09ac6 264 newname = origname;
5211717f 265retry:
68b09ac6
KM
266 if (stat(newname, &stblock) < 0) {
267 perror(newname);
268 printf("Can't stat %s\n", newname);
269 return (origname);
5211717f
KM
270 }
271 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
272 if (stslash.st_dev == stblock.st_rdev)
273 hotroot++;
68b09ac6 274 raw = rawname(newname);
5211717f
KM
275 if (stat(raw, &stchar) < 0) {
276 perror(raw);
277 printf("Can't stat %s\n", raw);
68b09ac6 278 return (origname);
5211717f
KM
279 }
280 if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
281 return (raw);
282 } else {
283 printf("%s is not a character device\n", raw);
68b09ac6 284 return (origname);
5211717f
KM
285 }
286 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
68b09ac6 287 newname = unrawname(newname);
5211717f
KM
288 retried++;
289 goto retry;
290 }
48f6b0df
KM
291 /*
292 * Not a block or character device, just return name and
293 * let the user decide whether to use it.
294 */
68b09ac6 295 return (origname);
5211717f
KM
296}
297
298char *
299unrawname(name)
300 char *name;
301{
302 char *dp;
303 struct stat stb;
304
305 if ((dp = rindex(name, '/')) == 0)
306 return (name);
307 if (stat(name, &stb) < 0)
308 return (name);
309 if ((stb.st_mode & S_IFMT) != S_IFCHR)
310 return (name);
a2186afe 311 if (dp[1] != 'r')
5211717f 312 return (name);
a2186afe 313 (void)strcpy(&dp[1], &dp[2]);
5211717f
KM
314 return (name);
315}
316
317char *
318rawname(name)
319 char *name;
320{
321 static char rawbuf[32];
322 char *dp;
323
324 if ((dp = rindex(name, '/')) == 0)
325 return (0);
326 *dp = 0;
327 (void)strcpy(rawbuf, name);
328 *dp = '/';
329 (void)strcat(rawbuf, "/r");
a2186afe 330 (void)strcat(rawbuf, &dp[1]);
5211717f
KM
331 return (rawbuf);
332}