preen.c revision 7585
11558Srgrimes/*
21558Srgrimes * Copyright (c) 1990, 1993
31558Srgrimes *	The Regents of the University of California.  All rights reserved.
41558Srgrimes *
51558Srgrimes * Redistribution and use in source and binary forms, with or without
61558Srgrimes * modification, are permitted provided that the following conditions
71558Srgrimes * are met:
81558Srgrimes * 1. Redistributions of source code must retain the above copyright
91558Srgrimes *    notice, this list of conditions and the following disclaimer.
101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer in the
121558Srgrimes *    documentation and/or other materials provided with the distribution.
131558Srgrimes * 3. All advertising materials mentioning features or use of this software
141558Srgrimes *    must display the following acknowledgement:
151558Srgrimes *	This product includes software developed by the University of
161558Srgrimes *	California, Berkeley and its contributors.
171558Srgrimes * 4. Neither the name of the University nor the names of its contributors
181558Srgrimes *    may be used to endorse or promote products derived from this software
191558Srgrimes *    without specific prior written permission.
201558Srgrimes *
211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311558Srgrimes * SUCH DAMAGE.
321558Srgrimes */
331558Srgrimes
341558Srgrimes#ifndef lint
357585Sbdestatic const char sccsid[] = "@(#)preen.c	8.1 (Berkeley) 6/5/93";
361558Srgrimes#endif /* not lint */
371558Srgrimes
381558Srgrimes#include <sys/param.h>
391558Srgrimes#include <sys/stat.h>
401558Srgrimes#include <sys/wait.h>
417585Sbde#include <ufs/ufs/dinode.h>
421558Srgrimes#include <fstab.h>
431558Srgrimes#include <string.h>
441558Srgrimes#include <stdio.h>
457585Sbde#include <unistd.h>
461558Srgrimes#include <stdlib.h>
471558Srgrimes#include <ctype.h>
487585Sbde#include "fsck.h"
491558Srgrimes
501558Srgrimesstruct part {
511558Srgrimes	struct	part *next;		/* forward link of partitions on disk */
521558Srgrimes	char	*name;			/* device name */
531558Srgrimes	char	*fsname;		/* mounted filesystem name */
541558Srgrimes	long	auxdata;		/* auxillary data for application */
551558Srgrimes} *badlist, **badnext = &badlist;
561558Srgrimes
571558Srgrimesstruct disk {
581558Srgrimes	char	*name;			/* disk base name */
591558Srgrimes	struct	disk *next;		/* forward link for list of disks */
601558Srgrimes	struct	part *part;		/* head of list of partitions on disk */
611558Srgrimes	int	pid;			/* If != 0, pid of proc working on */
621558Srgrimes} *disks;
631558Srgrimes
647585Sbdestatic void	addpart __P((char *name, char *fsname, long auxdata));
657585Sbdestatic int	startdisk __P((struct disk *dk, int (*checkit)()));
667585Sbdestatic struct disk 	*finddisk __P((char *name));
677585Sbdestatic char 	*unrawname __P((char *name));
687585Sbdestatic char 	*rawname __P((char *name));
697585Sbde
701558Srgrimesint	nrun, ndisks;
711558Srgrimeschar	hotroot;
721558Srgrimes
737585Sbdeint
741558Srgrimescheckfstab(preen, maxrun, docheck, chkit)
751558Srgrimes	int preen, maxrun;
761558Srgrimes	int (*docheck)(), (*chkit)();
771558Srgrimes{
781558Srgrimes	register struct fstab *fsp;
791558Srgrimes	register struct disk *dk, *nextdisk;
801558Srgrimes	register struct part *pt;
811558Srgrimes	int ret, pid, retcode, passno, sumstatus, status;
821558Srgrimes	long auxdata;
831558Srgrimes	char *name;
841558Srgrimes
851558Srgrimes	sumstatus = 0;
861558Srgrimes	for (passno = 1; passno <= 2; passno++) {
871558Srgrimes		if (setfsent() == 0) {
881558Srgrimes			fprintf(stderr, "Can't open checklist file: %s\n",
891558Srgrimes			    _PATH_FSTAB);
901558Srgrimes			return (8);
911558Srgrimes		}
921558Srgrimes		while ((fsp = getfsent()) != 0) {
931558Srgrimes			if ((auxdata = (*docheck)(fsp)) == 0)
941558Srgrimes				continue;
957585Sbde			if (!preen || (passno == 1 && fsp->fs_passno == 1)) {
967585Sbde				name = blockcheck(fsp->fs_spec);
977585Sbde				if (name) {
987585Sbde					sumstatus = (*chkit)(name,
997585Sbde					    fsp->fs_file, auxdata, 0);
1007585Sbde					if (sumstatus)
1011558Srgrimes						return (sumstatus);
1021558Srgrimes				} else if (preen)
1031558Srgrimes					return (8);
1041558Srgrimes			} else if (passno == 2 && fsp->fs_passno > 1) {
1051558Srgrimes				if ((name = blockcheck(fsp->fs_spec)) == NULL) {
1061558Srgrimes					fprintf(stderr, "BAD DISK NAME %s\n",
1071558Srgrimes						fsp->fs_spec);
1081558Srgrimes					sumstatus |= 8;
1091558Srgrimes					continue;
1101558Srgrimes				}
1111558Srgrimes				addpart(name, fsp->fs_file, auxdata);
1121558Srgrimes			}
1131558Srgrimes		}
1141558Srgrimes		if (preen == 0)
1151558Srgrimes			return (0);
1161558Srgrimes	}
1171558Srgrimes	if (preen) {
1181558Srgrimes		if (maxrun == 0)
1191558Srgrimes			maxrun = ndisks;
1201558Srgrimes		if (maxrun > ndisks)
1211558Srgrimes			maxrun = ndisks;
1221558Srgrimes		nextdisk = disks;
1231558Srgrimes		for (passno = 0; passno < maxrun; ++passno) {
1247585Sbde			while ((ret = startdisk(nextdisk, chkit)) != 0 &&
1257585Sbde			    nrun > 0)
1261558Srgrimes				sleep(10);
1271558Srgrimes			if (ret)
1281558Srgrimes				return (ret);
1291558Srgrimes			nextdisk = nextdisk->next;
1301558Srgrimes		}
1311558Srgrimes		while ((pid = wait(&status)) != -1) {
1321558Srgrimes			for (dk = disks; dk; dk = dk->next)
1331558Srgrimes				if (dk->pid == pid)
1341558Srgrimes					break;
1351558Srgrimes			if (dk == 0) {
1361558Srgrimes				printf("Unknown pid %d\n", pid);
1371558Srgrimes				continue;
1381558Srgrimes			}
1391558Srgrimes			if (WIFEXITED(status))
1401558Srgrimes				retcode = WEXITSTATUS(status);
1411558Srgrimes			else
1421558Srgrimes				retcode = 0;
1431558Srgrimes			if (WIFSIGNALED(status)) {
1441558Srgrimes				printf("%s (%s): EXITED WITH SIGNAL %d\n",
1451558Srgrimes					dk->part->name, dk->part->fsname,
1461558Srgrimes					WTERMSIG(status));
1471558Srgrimes				retcode = 8;
1481558Srgrimes			}
1491558Srgrimes			if (retcode != 0) {
1501558Srgrimes				sumstatus |= retcode;
1511558Srgrimes				*badnext = dk->part;
1521558Srgrimes				badnext = &dk->part->next;
1531558Srgrimes				dk->part = dk->part->next;
1541558Srgrimes				*badnext = NULL;
1551558Srgrimes			} else
1561558Srgrimes				dk->part = dk->part->next;
1571558Srgrimes			dk->pid = 0;
1581558Srgrimes			nrun--;
1591558Srgrimes			if (dk->part == NULL)
1601558Srgrimes				ndisks--;
1611558Srgrimes
1621558Srgrimes			if (nextdisk == NULL) {
1631558Srgrimes				if (dk->part) {
1647585Sbde					while ((ret = startdisk(dk, chkit)) != 0
1657585Sbde					    && nrun > 0)
1661558Srgrimes						sleep(10);
1671558Srgrimes					if (ret)
1681558Srgrimes						return (ret);
1691558Srgrimes				}
1701558Srgrimes			} else if (nrun < maxrun && nrun < ndisks) {
1711558Srgrimes				for ( ;; ) {
1721558Srgrimes					if ((nextdisk = nextdisk->next) == NULL)
1731558Srgrimes						nextdisk = disks;
1741558Srgrimes					if (nextdisk->part != NULL &&
1751558Srgrimes					    nextdisk->pid == 0)
1761558Srgrimes						break;
1771558Srgrimes				}
1787585Sbde				while ((ret = startdisk(nextdisk, chkit)) != 0
1797585Sbde				    && nrun > 0)
1801558Srgrimes					sleep(10);
1811558Srgrimes				if (ret)
1821558Srgrimes					return (ret);
1831558Srgrimes			}
1841558Srgrimes		}
1851558Srgrimes	}
1861558Srgrimes	if (sumstatus) {
1871558Srgrimes		if (badlist == 0)
1881558Srgrimes			return (sumstatus);
1891558Srgrimes		fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
1901558Srgrimes			badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
1911558Srgrimes		for (pt = badlist; pt; pt = pt->next)
1921558Srgrimes			fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname,
1931558Srgrimes			    pt->next ? ", " : "\n");
1941558Srgrimes		return (sumstatus);
1951558Srgrimes	}
1961558Srgrimes	(void)endfsent();
1971558Srgrimes	return (0);
1981558Srgrimes}
1991558Srgrimes
2001558Srgrimesstruct disk *
2011558Srgrimesfinddisk(name)
2021558Srgrimes	char *name;
2031558Srgrimes{
2041558Srgrimes	register struct disk *dk, **dkp;
2051558Srgrimes	register char *p;
2067585Sbde	size_t len = 0;
2071558Srgrimes
2081558Srgrimes	for (p = name + strlen(name) - 1; p >= name; --p)
2091558Srgrimes		if (isdigit(*p)) {
2101558Srgrimes			len = p - name + 1;
2111558Srgrimes			break;
2121558Srgrimes		}
2131558Srgrimes	if (p < name)
2141558Srgrimes		len = strlen(name);
2151558Srgrimes
2161558Srgrimes	for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
2171558Srgrimes		if (strncmp(dk->name, name, len) == 0 &&
2181558Srgrimes		    dk->name[len] == 0)
2191558Srgrimes			return (dk);
2201558Srgrimes	}
2211558Srgrimes	if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) {
2221558Srgrimes		fprintf(stderr, "out of memory");
2231558Srgrimes		exit (8);
2241558Srgrimes	}
2251558Srgrimes	dk = *dkp;
2261558Srgrimes	if ((dk->name = malloc(len + 1)) == NULL) {
2271558Srgrimes		fprintf(stderr, "out of memory");
2281558Srgrimes		exit (8);
2291558Srgrimes	}
2301558Srgrimes	(void)strncpy(dk->name, name, len);
2311558Srgrimes	dk->name[len] = '\0';
2321558Srgrimes	dk->part = NULL;
2331558Srgrimes	dk->next = NULL;
2341558Srgrimes	dk->pid = 0;
2351558Srgrimes	ndisks++;
2361558Srgrimes	return (dk);
2371558Srgrimes}
2381558Srgrimes
2397585Sbdevoid
2401558Srgrimesaddpart(name, fsname, auxdata)
2411558Srgrimes	char *name, *fsname;
2421558Srgrimes	long auxdata;
2431558Srgrimes{
2441558Srgrimes	struct disk *dk = finddisk(name);
2451558Srgrimes	register struct part *pt, **ppt = &dk->part;
2461558Srgrimes
2471558Srgrimes	for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
2481558Srgrimes		if (strcmp(pt->name, name) == 0) {
2491558Srgrimes			printf("%s in fstab more than once!\n", name);
2501558Srgrimes			return;
2511558Srgrimes		}
2521558Srgrimes	if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) {
2531558Srgrimes		fprintf(stderr, "out of memory");
2541558Srgrimes		exit (8);
2551558Srgrimes	}
2561558Srgrimes	pt = *ppt;
2571558Srgrimes	if ((pt->name = malloc(strlen(name) + 1)) == NULL) {
2581558Srgrimes		fprintf(stderr, "out of memory");
2591558Srgrimes		exit (8);
2601558Srgrimes	}
2611558Srgrimes	(void)strcpy(pt->name, name);
2621558Srgrimes	if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) {
2631558Srgrimes		fprintf(stderr, "out of memory");
2641558Srgrimes		exit (8);
2651558Srgrimes	}
2661558Srgrimes	(void)strcpy(pt->fsname, fsname);
2671558Srgrimes	pt->next = NULL;
2681558Srgrimes	pt->auxdata = auxdata;
2691558Srgrimes}
2701558Srgrimes
2717585Sbdeint
2721558Srgrimesstartdisk(dk, checkit)
2731558Srgrimes	register struct disk *dk;
2741558Srgrimes	int (*checkit)();
2751558Srgrimes{
2761558Srgrimes	register struct part *pt = dk->part;
2771558Srgrimes
2781558Srgrimes	dk->pid = fork();
2791558Srgrimes	if (dk->pid < 0) {
2801558Srgrimes		perror("fork");
2811558Srgrimes		return (8);
2821558Srgrimes	}
2831558Srgrimes	if (dk->pid == 0)
2841558Srgrimes		exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1));
2851558Srgrimes	nrun++;
2861558Srgrimes	return (0);
2871558Srgrimes}
2881558Srgrimes
2891558Srgrimeschar *
2901558Srgrimesblockcheck(name)
2911558Srgrimes	char *name;
2921558Srgrimes{
2931558Srgrimes	struct stat stslash, stblock, stchar;
2941558Srgrimes	char *raw;
2951558Srgrimes	int retried = 0;
2961558Srgrimes
2971558Srgrimes	hotroot = 0;
2981558Srgrimes	if (stat("/", &stslash) < 0) {
2991558Srgrimes		perror("/");
3001558Srgrimes		printf("Can't stat root\n");
3011558Srgrimes		return (0);
3021558Srgrimes	}
3031558Srgrimesretry:
3041558Srgrimes	if (stat(name, &stblock) < 0) {
3051558Srgrimes		perror(name);
3061558Srgrimes		printf("Can't stat %s\n", name);
3071558Srgrimes		return (0);
3081558Srgrimes	}
3091558Srgrimes	if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
3101558Srgrimes		if (stslash.st_dev == stblock.st_rdev)
3111558Srgrimes			hotroot++;
3121558Srgrimes		raw = rawname(name);
3131558Srgrimes		if (stat(raw, &stchar) < 0) {
3141558Srgrimes			perror(raw);
3151558Srgrimes			printf("Can't stat %s\n", raw);
3161558Srgrimes			return (name);
3171558Srgrimes		}
3181558Srgrimes		if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
3191558Srgrimes			return (raw);
3201558Srgrimes		} else {
3211558Srgrimes			printf("%s is not a character device\n", raw);
3221558Srgrimes			return (name);
3231558Srgrimes		}
3241558Srgrimes	} else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
3251558Srgrimes		name = unrawname(name);
3261558Srgrimes		retried++;
3271558Srgrimes		goto retry;
3281558Srgrimes	}
3291558Srgrimes	printf("Can't make sense out of name %s\n", name);
3301558Srgrimes	return (0);
3311558Srgrimes}
3321558Srgrimes
3331558Srgrimeschar *
3341558Srgrimesunrawname(name)
3351558Srgrimes	char *name;
3361558Srgrimes{
3371558Srgrimes	char *dp;
3381558Srgrimes	struct stat stb;
3391558Srgrimes
3401558Srgrimes	if ((dp = rindex(name, '/')) == 0)
3411558Srgrimes		return (name);
3421558Srgrimes	if (stat(name, &stb) < 0)
3431558Srgrimes		return (name);
3441558Srgrimes	if ((stb.st_mode & S_IFMT) != S_IFCHR)
3451558Srgrimes		return (name);
3461558Srgrimes	if (dp[1] != 'r')
3471558Srgrimes		return (name);
3481558Srgrimes	(void)strcpy(&dp[1], &dp[2]);
3491558Srgrimes	return (name);
3501558Srgrimes}
3511558Srgrimes
3521558Srgrimeschar *
3531558Srgrimesrawname(name)
3541558Srgrimes	char *name;
3551558Srgrimes{
3561558Srgrimes	static char rawbuf[32];
3571558Srgrimes	char *dp;
3581558Srgrimes
3591558Srgrimes	if ((dp = rindex(name, '/')) == 0)
3601558Srgrimes		return (0);
3611558Srgrimes	*dp = 0;
3621558Srgrimes	(void)strcpy(rawbuf, name);
3631558Srgrimes	*dp = '/';
3641558Srgrimes	(void)strcat(rawbuf, "/r");
3651558Srgrimes	(void)strcat(rawbuf, &dp[1]);
3661558Srgrimes	return (rawbuf);
3671558Srgrimes}
368