preen.c revision 8871
1139804Simp/*
2131903Smarcel * Copyright (c) 1990, 1993
3131903Smarcel *	The Regents of the University of California.  All rights reserved.
4131903Smarcel *
5131903Smarcel * Redistribution and use in source and binary forms, with or without
6131903Smarcel * modification, are permitted provided that the following conditions
7131903Smarcel * are met:
8131903Smarcel * 1. Redistributions of source code must retain the above copyright
9131903Smarcel *    notice, this list of conditions and the following disclaimer.
10131903Smarcel * 2. Redistributions in binary form must reproduce the above copyright
11131903Smarcel *    notice, this list of conditions and the following disclaimer in the
12131903Smarcel *    documentation and/or other materials provided with the distribution.
13131903Smarcel * 3. All advertising materials mentioning features or use of this software
14131903Smarcel *    must display the following acknowledgement:
15131903Smarcel *	This product includes software developed by the University of
16131903Smarcel *	California, Berkeley and its contributors.
17131903Smarcel * 4. Neither the name of the University nor the names of its contributors
18131903Smarcel *    may be used to endorse or promote products derived from this software
19131903Smarcel *    without specific prior written permission.
20131903Smarcel *
21131903Smarcel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22131903Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23131903Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24131903Smarcel * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25131903Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26131903Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27131903Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28131903Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29131903Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30147674Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31212964Savg * SUCH DAMAGE.
32147674Speter */
33131903Smarcel
34131903Smarcel#ifndef lint
35228632Savgstatic const char sccsid[] = "@(#)preen.c	8.1 (Berkeley) 6/5/93";
36131903Smarcel#endif /* not lint */
37131903Smarcel
38131903Smarcel#include <sys/param.h>
39131903Smarcel#include <sys/stat.h>
40131903Smarcel#include <sys/wait.h>
41218825Smdf#include <ufs/ufs/dinode.h>
42131903Smarcel#include <fstab.h>
43212964Savg#include <string.h>
44131903Smarcel#include <stdio.h>
45131903Smarcel#include <unistd.h>
46131903Smarcel#include <stdlib.h>
47131903Smarcel#include <ctype.h>
48131903Smarcel#include "fsck.h"
49151634Sjhb
50145727Sdwhitestruct part {
51145727Sdwhite	struct	part *next;		/* forward link of partitions on disk */
52145727Sdwhite	char	*name;			/* device name */
53131903Smarcel	char	*fsname;		/* mounted filesystem name */
54191948Simp	long	auxdata;		/* auxillary data for application */
55131903Smarcel} *badlist, **badnext = &badlist;
56191948Simp
57131903Smarcelstruct disk {
58131903Smarcel	char	*name;			/* disk base name */
59131903Smarcel	struct	disk *next;		/* forward link for list of disks */
60131903Smarcel	struct	part *part;		/* head of list of partitions on disk */
61225203Srwatson	int	pid;			/* If != 0, pid of proc working on */
62225203Srwatson} *disks;
63225203Srwatson
64225203Srwatsonstatic void	addpart __P((char *name, char *fsname, long auxdata));
65225203Srwatsonstatic int	startdisk __P((struct disk *dk, int (*checkit)()));
66225203Srwatsonstatic struct disk 	*finddisk __P((char *name));
67225203Srwatsonstatic char 	*unrawname __P((char *name));
68225203Srwatsonstatic char 	*rawname __P((char *name));
69225203Srwatson
70225203Srwatsonint	nrun, ndisks;
71225203Srwatsonchar	hotroot;
72225203Srwatson
73225203Srwatsonint
74225203Srwatsoncheckfstab(preen, maxrun, docheck, chkit)
75225203Srwatson	int preen, maxrun;
76234190Sjhb	int (*docheck)(), (*chkit)();
77131903Smarcel{
78131903Smarcel	register struct fstab *fsp;
79131903Smarcel	register struct disk *dk, *nextdisk;
80131903Smarcel	register struct part *pt;
81131903Smarcel	int ret, pid, retcode, passno, sumstatus, status;
82151725Speter	long auxdata;
83151725Speter	char *name;
84159726Syar
85131903Smarcel	sumstatus = 0;
86227309Sed	for (passno = 1; passno <= 2; passno++) {
87131903Smarcel		if (setfsent() == 0) {
88191948Simp			fprintf(stderr, "Can't open checklist file: %s\n",
89191948Simp			    _PATH_FSTAB);
90131903Smarcel			return (8);
91191948Simp		}
92191948Simp		while ((fsp = getfsent()) != 0) {
93131903Smarcel			if ((auxdata = (*docheck)(fsp)) == 0)
94226089Sobrien				continue;
95226089Sobrien			if (!preen || (passno == 1 && fsp->fs_passno == 1)) {
96131903Smarcel				name = blockcheck(fsp->fs_spec);
97131903Smarcel				if (name) {
98226089Sobrien					sumstatus = (*chkit)(name,
99226089Sobrien					    fsp->fs_file, auxdata, 0);
100151725Speter					if (sumstatus)
101151725Speter						return (sumstatus);
102226089Sobrien				} else if (preen)
103226089Sobrien					return (8);
104159726Syar			} else if (passno == 2 && fsp->fs_passno > 1) {
105151725Speter				if ((name = blockcheck(fsp->fs_spec)) == NULL) {
106226089Sobrien					fprintf(stderr, "BAD DISK NAME %s\n",
107226089Sobrien						fsp->fs_spec);
108159726Syar					sumstatus |= 8;
109159726Syar					continue;
110226089Sobrien				}
111273736Shselasky				addpart(name, fsp->fs_file, auxdata);
112226089Sobrien			}
113225203Srwatson		}
114225203Srwatson		if (preen == 0)
115226089Sobrien			return (0);
116273736Shselasky	}
117226089Sobrien	if (preen) {
118225203Srwatson		if (maxrun == 0)
119225203Srwatson			maxrun = ndisks;
120133737Srwatson		if (maxrun > ndisks)
121174898Srwatson			maxrun = ndisks;
122174898Srwatson		nextdisk = disks;
123174898Srwatson		for (passno = 0; passno < maxrun; ++passno) {
124174898Srwatson			while ((ret = startdisk(nextdisk, chkit)) != 0 &&
125131903Smarcel			    nrun > 0)
126131903Smarcel				sleep(10);
127131903Smarcel			if (ret)
128218825Smdf				return (ret);
129218825Smdf			nextdisk = nextdisk->next;
130131903Smarcel		}
131131903Smarcel		while ((pid = wait(&status)) != -1) {
132218825Smdf			for (dk = disks; dk; dk = dk->next)
133131903Smarcel				if (dk->pid == pid)
134218825Smdf					break;
135218825Smdf			if (dk == 0) {
136131903Smarcel				printf("Unknown pid %d\n", pid);
137218825Smdf				continue;
138218825Smdf			}
139131903Smarcel			if (WIFEXITED(status))
140131903Smarcel				retcode = WEXITSTATUS(status);
141131903Smarcel			else
142131903Smarcel				retcode = 0;
143131903Smarcel			if (WIFSIGNALED(status)) {
144131903Smarcel				printf("%s (%s): EXITED WITH SIGNAL %d\n",
145131903Smarcel					dk->part->name, dk->part->fsname,
146131903Smarcel					WTERMSIG(status));
147131903Smarcel				retcode = 8;
148218825Smdf			}
149218825Smdf			if (retcode != 0) {
150218825Smdf				sumstatus |= retcode;
151131982Smarcel				*badnext = dk->part;
152131903Smarcel				badnext = &dk->part->next;
153131903Smarcel				dk->part = dk->part->next;
154131903Smarcel				*badnext = NULL;
155131903Smarcel			} else
156131903Smarcel				dk->part = dk->part->next;
157132001Smarcel			dk->pid = 0;
158131903Smarcel			nrun--;
159131903Smarcel			if (dk->part == NULL)
160131903Smarcel				ndisks--;
161131903Smarcel
162131903Smarcel			if (nextdisk == NULL) {
163131903Smarcel				if (dk->part) {
164131903Smarcel					while ((ret = startdisk(dk, chkit)) != 0
165131903Smarcel					    && nrun > 0)
166131903Smarcel						sleep(10);
167131903Smarcel					if (ret)
168131903Smarcel						return (ret);
169131903Smarcel				}
170131903Smarcel			} else if (nrun < maxrun && nrun < ndisks) {
171131903Smarcel				for ( ;; ) {
172131903Smarcel					if ((nextdisk = nextdisk->next) == NULL)
173131903Smarcel						nextdisk = disks;
174174898Srwatson					if (nextdisk->part != NULL &&
175131903Smarcel					    nextdisk->pid == 0)
176131903Smarcel						break;
177131903Smarcel				}
178151725Speter				while ((ret = startdisk(nextdisk, chkit)) != 0
179151725Speter				    && nrun > 0)
180151725Speter					sleep(10);
181151725Speter				if (ret)
182151725Speter					return (ret);
183151725Speter			}
184151725Speter		}
185151725Speter	}
186151725Speter	if (sumstatus) {
187151725Speter		if (badlist == 0)
188151725Speter			return (sumstatus);
189151725Speter		fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
190151725Speter			badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
191151725Speter		for (pt = badlist; pt; pt = pt->next)
192151725Speter			fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname,
193151725Speter			    pt->next ? ", " : "\n");
194151725Speter		return (sumstatus);
195151725Speter	}
196151725Speter	(void)endfsent();
197151725Speter	return (0);
198151725Speter}
199151725Speter
200151725Speterstruct disk *
201151725Speterfinddisk(name)
202151725Speter	char *name;
203151725Speter{
204151725Speter	register struct disk *dk, **dkp;
205151725Speter	register char *p;
206151725Speter	size_t len = 0;
207151725Speter
208151725Speter	for (p = name + strlen(name) - 1; p >= name; --p)
209151725Speter		if (isdigit(*p)) {
210159726Syar			len = p - name + 1;
211159726Syar			break;
212159726Syar		}
213159726Syar	if (p < name)
214159726Syar		len = strlen(name);
215159726Syar
216159726Syar	for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
217159726Syar		if (strncmp(dk->name, name, len) == 0 &&
218159726Syar		    dk->name[len] == 0)
219159726Syar			return (dk);
220159726Syar	}
221159726Syar	if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) {
222159726Syar		fprintf(stderr, "out of memory");
223159726Syar		exit (8);
224159726Syar	}
225159726Syar	dk = *dkp;
226159726Syar	if ((dk->name = malloc(len + 1)) == NULL) {
227178766Speter		fprintf(stderr, "out of memory");
228178766Speter		exit (8);
229178766Speter	}
230223758Sattilio	(void)strncpy(dk->name, name, len);
231178766Speter	dk->name[len] = '\0';
232209062Savg	dk->part = NULL;
233178766Speter	dk->next = NULL;
234178766Speter	dk->pid = 0;
235178766Speter	ndisks++;
236178766Speter	return (dk);
237178766Speter}
238178766Speter
239178766Spetervoid
240178766Speteraddpart(name, fsname, auxdata)
241178766Speter	char *name, *fsname;
242178766Speter	long auxdata;
243131903Smarcel{
244131903Smarcel	struct disk *dk = finddisk(name);
245131903Smarcel	register struct part *pt, **ppt = &dk->part;
246131903Smarcel
247131903Smarcel	for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
248131903Smarcel		if (strcmp(pt->name, name) == 0) {
249131903Smarcel			printf("%s in fstab more than once!\n", name);
250131903Smarcel			return;
251131903Smarcel		}
252131903Smarcel	if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) {
253131903Smarcel		fprintf(stderr, "out of memory");
254131903Smarcel		exit (8);
255131903Smarcel	}
256131903Smarcel	pt = *ppt;
257178766Speter	if ((pt->name = malloc(strlen(name) + 1)) == NULL) {
258178766Speter		fprintf(stderr, "out of memory");
259131903Smarcel		exit (8);
260223099Sgibbs	}
261223099Sgibbs	(void)strcpy(pt->name, name);
262223099Sgibbs	if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) {
263223099Sgibbs		fprintf(stderr, "out of memory");
264223099Sgibbs		exit (8);
265223099Sgibbs	}
266223099Sgibbs	(void)strcpy(pt->fsname, fsname);
267131903Smarcel	pt->next = NULL;
268225203Srwatson	pt->auxdata = auxdata;
269131903Smarcel}
270225203Srwatson
271225203Srwatsonint
272225203Srwatsonstartdisk(dk, checkit)
273225203Srwatson	register struct disk *dk;
274225203Srwatson	int (*checkit)();
275225203Srwatson{
276225203Srwatson	register struct part *pt = dk->part;
277225203Srwatson
278225203Srwatson	dk->pid = fork();
279225203Srwatson	if (dk->pid < 0) {
280131903Smarcel		perror("fork");
281131903Smarcel		return (8);
282223099Sgibbs	}
283223099Sgibbs	if (dk->pid == 0)
284223099Sgibbs		exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1));
285223099Sgibbs	nrun++;
286223099Sgibbs	return (0);
287223099Sgibbs}
288131903Smarcel
289178766Speterchar *
290223099Sgibbsblockcheck(name)
291223099Sgibbs	char *name;
292178766Speter{
293223099Sgibbs	struct stat stslash, stblock, stchar;
294131903Smarcel	char *raw;
295223099Sgibbs	int retried = 0;
296223099Sgibbs
297178766Speter	hotroot = 0;
298178766Speter	if (stat("/", &stslash) < 0) {
299178766Speter		perror("/");
300178766Speter		printf("Can't stat root\n");
301178766Speter		return (0);
302178766Speter	}
303223099Sgibbsretry:
304223099Sgibbs	if (stat(name, &stblock) < 0) {
305223099Sgibbs		perror(name);
306223099Sgibbs		printf("Can't stat %s\n", name);
307223099Sgibbs		return (0);
308131903Smarcel	}
309131903Smarcel	if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
310131903Smarcel		if (stslash.st_dev == stblock.st_rdev)
311131903Smarcel			hotroot++;
312225203Srwatson		raw = rawname(name);
313225203Srwatson		if (stat(raw, &stchar) < 0) {
314225203Srwatson			perror(raw);
315225203Srwatson			printf("Can't stat %s\n", raw);
316225203Srwatson			return (name);
317225203Srwatson		}
318225203Srwatson		if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
319225203Srwatson			return (raw);
320225203Srwatson		} else {
321225203Srwatson			printf("%s is not a character device\n", raw);
322225203Srwatson			return (name);
323225203Srwatson		}
324225203Srwatson	} else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
325225203Srwatson		name = unrawname(name);
326225203Srwatson		retried++;
327225203Srwatson		goto retry;
328225203Srwatson	}
329225203Srwatson	printf("Can't make sense out of name %s\n", name);
330225203Srwatson	return (0);
331225203Srwatson}
332225203Srwatson
333225203Srwatsonchar *
334225203Srwatsonunrawname(name)
335225203Srwatson	char *name;
336225203Srwatson{
337225203Srwatson	char *dp;
338225203Srwatson	struct stat stb;
339225203Srwatson
340225203Srwatson	if ((dp = rindex(name, '/')) == 0)
341225203Srwatson		return (name);
342225203Srwatson	if (stat(name, &stb) < 0)
343225203Srwatson		return (name);
344225203Srwatson	if ((stb.st_mode & S_IFMT) != S_IFCHR)
345225203Srwatson		return (name);
346225203Srwatson	if (dp[1] != 'r')
347131903Smarcel		return (name);
348225203Srwatson	(void)strcpy(&dp[1], &dp[2]);
349225203Srwatson	return (name);
350225203Srwatson}
351225203Srwatson
352225203Srwatsonchar *
353225203Srwatsonrawname(name)
354225203Srwatson	char *name;
355225203Srwatson{
356225203Srwatson	static char rawbuf[32];
357225203Srwatson	char *dp;
358225203Srwatson
359225203Srwatson	if ((dp = rindex(name, '/')) == 0)
360131903Smarcel		return (0);
361131903Smarcel	*dp = 0;
362131903Smarcel	(void)strcpy(rawbuf, name);
363131903Smarcel	*dp = '/';
364131903Smarcel	(void)strcat(rawbuf, "/r");
365131903Smarcel	(void)strcat(rawbuf, &dp[1]);
366131903Smarcel	return (rawbuf);
367191948Simp}
368131903Smarcel