xref: /freebsd/sbin/quotacheck/preen.c (revision 5b31cc94b10d4bb7109c6b27940a0fc76a44a331)
13b9401dbSMike Pritchard /*	$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $	*/
23b9401dbSMike Pritchard 
38a16b7a1SPedro F. Giffuni /*-
48a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
58a16b7a1SPedro F. Giffuni  *
68fae3551SRodney W. Grimes  * Copyright (c) 1990, 1993
78fae3551SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
88fae3551SRodney W. Grimes  *
98fae3551SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
108fae3551SRodney W. Grimes  * modification, are permitted provided that the following conditions
118fae3551SRodney W. Grimes  * are met:
128fae3551SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
138fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
148fae3551SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
158fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
168fae3551SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
17fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
188fae3551SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
198fae3551SRodney W. Grimes  *    without specific prior written permission.
208fae3551SRodney W. Grimes  *
218fae3551SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
228fae3551SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
238fae3551SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
248fae3551SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
258fae3551SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
268fae3551SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
278fae3551SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
288fae3551SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
298fae3551SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
308fae3551SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
318fae3551SRodney W. Grimes  * SUCH DAMAGE.
328fae3551SRodney W. Grimes  */
338fae3551SRodney W. Grimes 
34*5b31cc94SWarner Losh /* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */
358fae3551SRodney W. Grimes 
368fae3551SRodney W. Grimes #include <sys/param.h>
378fae3551SRodney W. Grimes #include <sys/stat.h>
388fae3551SRodney W. Grimes #include <sys/wait.h>
393b9401dbSMike Pritchard #include <sys/queue.h>
40bb19997cSBruce Evans 
413af26d4aSKirk McKusick #include <ufs/ufs/quota.h>
423af26d4aSKirk McKusick 
433b9401dbSMike Pritchard #include <err.h>
44bb19997cSBruce Evans #include <ctype.h>
453af26d4aSKirk McKusick #include <fcntl.h>
468fae3551SRodney W. Grimes #include <fstab.h>
473af26d4aSKirk McKusick #include <libutil.h>
488fae3551SRodney W. Grimes #include <string.h>
49563b79efSPoul-Henning Kamp #include <stdio.h>
50563b79efSPoul-Henning Kamp #include <stdlib.h>
51563b79efSPoul-Henning Kamp #include <unistd.h>
52780a5c1eSPeter Wemm 
533b9401dbSMike Pritchard #include "quotacheck.h"
54563b79efSPoul-Henning Kamp 
553b9401dbSMike Pritchard struct partentry {
563b9401dbSMike Pritchard 	TAILQ_ENTRY(partentry)	 p_entries;
573b9401dbSMike Pritchard 	char			*p_devname;	/* device name */
583af26d4aSKirk McKusick 	const char		*p_mntpt;	/* mount point */
593af26d4aSKirk McKusick 	struct quotafile	*p_qfu;		/* user quota file info ptr */
603af26d4aSKirk McKusick 	struct quotafile	*p_qfg;		/* group quota file info */
613b9401dbSMike Pritchard };
628fae3551SRodney W. Grimes 
633b9401dbSMike Pritchard TAILQ_HEAD(part, partentry) badh;
648fae3551SRodney W. Grimes 
653b9401dbSMike Pritchard struct diskentry {
663b9401dbSMike Pritchard 	TAILQ_ENTRY(diskentry)	    d_entries;
673b9401dbSMike Pritchard 	char			   *d_name;	/* disk base name */
683b9401dbSMike Pritchard 	TAILQ_HEAD(prt, partentry)  d_part;	/* list of partitions on disk */
693b9401dbSMike Pritchard 	int			    d_pid;	/* 0 or pid of fsck proc */
703b9401dbSMike Pritchard };
718fae3551SRodney W. Grimes 
723b9401dbSMike Pritchard TAILQ_HEAD(disk, diskentry) diskh;
738fae3551SRodney W. Grimes 
743b9401dbSMike Pritchard static struct diskentry *finddisk(const char *);
753af26d4aSKirk McKusick static void addpart(struct fstab *, struct quotafile *, struct quotafile *);
763b9401dbSMike Pritchard static int startdisk(struct diskentry *);
773b9401dbSMike Pritchard extern void *emalloc(size_t);
783b9401dbSMike Pritchard extern char *estrdup(const char *);
79780a5c1eSPeter Wemm 
8031f4ab50SBruce Evans int
checkfstab(int uflag,int gflag)813af26d4aSKirk McKusick checkfstab(int uflag, int gflag)
828fae3551SRodney W. Grimes {
833b9401dbSMike Pritchard 	struct fstab *fs;
843b9401dbSMike Pritchard 	struct diskentry *d, *nextdisk;
853b9401dbSMike Pritchard 	struct partentry *p;
863b9401dbSMike Pritchard 	int ret, pid, retcode, passno, sumstatus, status, nextpass;
873af26d4aSKirk McKusick 	struct quotafile *qfu, *qfg;
883b9401dbSMike Pritchard 
893b9401dbSMike Pritchard 	TAILQ_INIT(&badh);
903b9401dbSMike Pritchard 	TAILQ_INIT(&diskh);
918fae3551SRodney W. Grimes 
928fae3551SRodney W. Grimes 	sumstatus = 0;
933b9401dbSMike Pritchard 
943b9401dbSMike Pritchard 	nextpass = 0;
953b9401dbSMike Pritchard 	for (passno = 1; nextpass != INT_MAX; passno = nextpass) {
963b9401dbSMike Pritchard 		nextpass = INT_MAX;
978fae3551SRodney W. Grimes 		if (setfsent() == 0) {
983b9401dbSMike Pritchard 			warnx("Can't open checklist file: %s\n", _PATH_FSTAB);
998fae3551SRodney W. Grimes 			return (8);
1008fae3551SRodney W. Grimes 		}
101deaa3563SMarcelo Araujo 		while ((fs = getfsent()) != NULL) {
1023b9401dbSMike Pritchard 			if (fs->fs_passno > passno && fs->fs_passno < nextpass)
1033b9401dbSMike Pritchard 				nextpass = fs->fs_passno;
1043b9401dbSMike Pritchard 
1053b9401dbSMike Pritchard 			if (passno != fs->fs_passno)
1068fae3551SRodney W. Grimes 				continue;
1073b9401dbSMike Pritchard 
1083af26d4aSKirk McKusick 			qfu = NULL;
1093af26d4aSKirk McKusick 			if (uflag)
1103af26d4aSKirk McKusick 				qfu = quota_open(fs, USRQUOTA, O_CREAT|O_RDWR);
1113af26d4aSKirk McKusick 			qfg = NULL;
1123af26d4aSKirk McKusick 			if (gflag)
1133af26d4aSKirk McKusick 				qfg = quota_open(fs, GRPQUOTA, O_CREAT|O_RDWR);
1143af26d4aSKirk McKusick 			if (qfu == NULL && qfg == NULL)
1153b9401dbSMike Pritchard 				continue;
1163b9401dbSMike Pritchard 
1173b9401dbSMike Pritchard 			if (passno == 1) {
1183af26d4aSKirk McKusick 				sumstatus = chkquota(fs->fs_spec, qfu, qfg);
1193af26d4aSKirk McKusick 				if (qfu)
1203af26d4aSKirk McKusick 					quota_close(qfu);
1213af26d4aSKirk McKusick 				if (qfg)
1223af26d4aSKirk McKusick 					quota_close(qfg);
1233b9401dbSMike Pritchard 				if (sumstatus)
1248fae3551SRodney W. Grimes 					return (sumstatus);
1253b9401dbSMike Pritchard 				continue;
1263b9401dbSMike Pritchard 			}
1273af26d4aSKirk McKusick 			addpart(fs, qfu, qfg);
1288fae3551SRodney W. Grimes 		}
1293b9401dbSMike Pritchard 
1303b9401dbSMike Pritchard 		if (passno == 1)
1313b9401dbSMike Pritchard 			continue;
1323b9401dbSMike Pritchard 
1333b9401dbSMike Pritchard 		TAILQ_FOREACH(nextdisk, &diskh, d_entries) {
1343b9401dbSMike Pritchard 			if ((ret = startdisk(nextdisk)) != 0)
1353b9401dbSMike Pritchard 				return ret;
1368fae3551SRodney W. Grimes 		}
1373b9401dbSMike Pritchard 
1388fae3551SRodney W. Grimes 		while ((pid = wait(&status)) != -1) {
1393b9401dbSMike Pritchard 			TAILQ_FOREACH(d, &diskh, d_entries)
1403b9401dbSMike Pritchard 				if (d->d_pid == pid)
1418fae3551SRodney W. Grimes 					break;
1423b9401dbSMike Pritchard 
1433b9401dbSMike Pritchard 			if (d == NULL) {
1443b9401dbSMike Pritchard 				warnx("Unknown pid %d\n", pid);
1458fae3551SRodney W. Grimes 				continue;
1468fae3551SRodney W. Grimes 			}
1473b9401dbSMike Pritchard 
1488fae3551SRodney W. Grimes 			if (WIFEXITED(status))
1498fae3551SRodney W. Grimes 				retcode = WEXITSTATUS(status);
1508fae3551SRodney W. Grimes 			else
1518fae3551SRodney W. Grimes 				retcode = 0;
1523b9401dbSMike Pritchard 
1533b9401dbSMike Pritchard 			p = TAILQ_FIRST(&d->d_part);
1543b9401dbSMike Pritchard 
1558fae3551SRodney W. Grimes 			if (WIFSIGNALED(status)) {
1563b9401dbSMike Pritchard 				(void) fprintf(stderr,
1573af26d4aSKirk McKusick 				    "%s: (%s): EXITED WITH SIGNAL %d\n",
1583af26d4aSKirk McKusick 				    p->p_devname, p->p_mntpt,
1598fae3551SRodney W. Grimes 				    WTERMSIG(status));
1608fae3551SRodney W. Grimes 				retcode = 8;
1618fae3551SRodney W. Grimes 			}
1628fae3551SRodney W. Grimes 
1633b9401dbSMike Pritchard 			TAILQ_REMOVE(&d->d_part, p, p_entries);
1643b9401dbSMike Pritchard 
1653b9401dbSMike Pritchard 			if (retcode != 0) {
1663b9401dbSMike Pritchard 				TAILQ_INSERT_TAIL(&badh, p, p_entries);
1673b9401dbSMike Pritchard 				sumstatus |= retcode;
1683b9401dbSMike Pritchard 			} else {
1693b9401dbSMike Pritchard 				free(p->p_devname);
1703af26d4aSKirk McKusick 				if (p->p_qfu)
1713af26d4aSKirk McKusick 					quota_close(p->p_qfu);
1723af26d4aSKirk McKusick 				if (p->p_qfg)
1733af26d4aSKirk McKusick 					quota_close(p->p_qfg);
1743b9401dbSMike Pritchard 				free(p);
1758fae3551SRodney W. Grimes 			}
1763b9401dbSMike Pritchard 			d->d_pid = 0;
1773b9401dbSMike Pritchard 
1783b9401dbSMike Pritchard 			if (TAILQ_EMPTY(&d->d_part)) {
1793b9401dbSMike Pritchard 				TAILQ_REMOVE(&diskh, d, d_entries);
1803b9401dbSMike Pritchard 			} else {
1813b9401dbSMike Pritchard 				if ((ret = startdisk(d)) != 0)
1823b9401dbSMike Pritchard 					return ret;
1838fae3551SRodney W. Grimes 			}
1848fae3551SRodney W. Grimes 		}
1858fae3551SRodney W. Grimes 	}
1863b9401dbSMike Pritchard 
1878fae3551SRodney W. Grimes 	if (sumstatus) {
1883b9401dbSMike Pritchard 		p = TAILQ_FIRST(&badh);
1893b9401dbSMike Pritchard 		if (p == NULL)
1908fae3551SRodney W. Grimes 			return (sumstatus);
1913b9401dbSMike Pritchard 
1923b9401dbSMike Pritchard 		(void) fprintf(stderr,
1933b9401dbSMike Pritchard 			"THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
1943b9401dbSMike Pritchard 			TAILQ_NEXT(p, p_entries) ? "S" : "",
1953b9401dbSMike Pritchard 			"UNEXPECTED INCONSISTENCY:");
1963b9401dbSMike Pritchard 
1973b9401dbSMike Pritchard 		for (; p; p = TAILQ_NEXT(p, p_entries))
1983b9401dbSMike Pritchard 			(void) fprintf(stderr,
1993af26d4aSKirk McKusick 			    "%s: (%s)%s", p->p_devname, p->p_mntpt,
2003af26d4aSKirk McKusick 			    TAILQ_NEXT(p, p_entries) ? ", " : "\n");
2013b9401dbSMike Pritchard 
2023b9401dbSMike Pritchard 		return sumstatus;
2038fae3551SRodney W. Grimes 	}
2048fae3551SRodney W. Grimes 	(void) endfsent();
2058fae3551SRodney W. Grimes 	return (0);
2068fae3551SRodney W. Grimes }
2078fae3551SRodney W. Grimes 
2083b9401dbSMike Pritchard 
2093b9401dbSMike Pritchard static struct diskentry *
finddisk(const char * name)2103b9401dbSMike Pritchard finddisk(const char *name)
2118fae3551SRodney W. Grimes {
2123b9401dbSMike Pritchard 	const char *p;
2133b9401dbSMike Pritchard 	size_t len = 0;
2143b9401dbSMike Pritchard 	struct diskentry *d;
2158fae3551SRodney W. Grimes 
21633e60822SBruce Evans 	p = strrchr(name, '/');
2173b9401dbSMike Pritchard 	if (p == NULL)
2183b9401dbSMike Pritchard 		p = name;
2193b9401dbSMike Pritchard 	else
22033e60822SBruce Evans 		p++;
2213b9401dbSMike Pritchard 	for (; *p && !isdigit(*p); p++)
2223b9401dbSMike Pritchard 		continue;
2233b9401dbSMike Pritchard 	for (; *p && isdigit(*p); p++)
2243b9401dbSMike Pritchard 		continue;
2253b9401dbSMike Pritchard 	len = p - name;
2263b9401dbSMike Pritchard 	if (len == 0)
2273b9401dbSMike Pritchard 		len = strlen(name);
2283b9401dbSMike Pritchard 
2293b9401dbSMike Pritchard 	TAILQ_FOREACH(d, &diskh, d_entries)
2303b9401dbSMike Pritchard 		if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0)
2313b9401dbSMike Pritchard 			return d;
2323b9401dbSMike Pritchard 
2333b9401dbSMike Pritchard 	d = emalloc(sizeof(*d));
2343b9401dbSMike Pritchard 	d->d_name = estrdup(name);
2353b9401dbSMike Pritchard 	d->d_name[len] = '\0';
2363b9401dbSMike Pritchard 	TAILQ_INIT(&d->d_part);
2373b9401dbSMike Pritchard 	d->d_pid = 0;
2383b9401dbSMike Pritchard 
2393b9401dbSMike Pritchard 	TAILQ_INSERT_TAIL(&diskh, d, d_entries);
2403b9401dbSMike Pritchard 
2413b9401dbSMike Pritchard 	return d;
2428fae3551SRodney W. Grimes }
2438fae3551SRodney W. Grimes 
244780a5c1eSPeter Wemm static void
addpart(struct fstab * fs,struct quotafile * qfu,struct quotafile * qfg)2453af26d4aSKirk McKusick addpart(struct fstab *fs, struct quotafile *qfu, struct quotafile *qfg)
2468fae3551SRodney W. Grimes {
2473af26d4aSKirk McKusick 	struct diskentry *d = finddisk(fs->fs_spec);
2483b9401dbSMike Pritchard 	struct partentry *p;
2498fae3551SRodney W. Grimes 
2503b9401dbSMike Pritchard 	TAILQ_FOREACH(p, &d->d_part, p_entries)
2513af26d4aSKirk McKusick 		if (strcmp(p->p_devname, fs->fs_spec) == 0) {
2523af26d4aSKirk McKusick 			warnx("%s in fstab more than once!\n", fs->fs_spec);
2538fae3551SRodney W. Grimes 			return;
2548fae3551SRodney W. Grimes 		}
2553b9401dbSMike Pritchard 
2563b9401dbSMike Pritchard 	p = emalloc(sizeof(*p));
2573af26d4aSKirk McKusick 	p->p_devname = estrdup(blockcheck(fs->fs_spec));
2583af26d4aSKirk McKusick 	if (qfu != NULL)
2593af26d4aSKirk McKusick 		p->p_mntpt = quota_fsname(qfu);
2603af26d4aSKirk McKusick 	else
2613af26d4aSKirk McKusick 		p->p_mntpt = quota_fsname(qfg);
2623af26d4aSKirk McKusick 	p->p_qfu = qfu;
2633af26d4aSKirk McKusick 	p->p_qfg = qfg;
2643b9401dbSMike Pritchard 
2653b9401dbSMike Pritchard 	TAILQ_INSERT_TAIL(&d->d_part, p, p_entries);
266d33e92f9SJulian Elischer }
2673b9401dbSMike Pritchard 
2688fae3551SRodney W. Grimes 
269780a5c1eSPeter Wemm static int
startdisk(struct diskentry * d)2703b9401dbSMike Pritchard startdisk(struct diskentry *d)
2718fae3551SRodney W. Grimes {
2723b9401dbSMike Pritchard 	struct partentry *p = TAILQ_FIRST(&d->d_part);
2738fae3551SRodney W. Grimes 
2743b9401dbSMike Pritchard 	d->d_pid = fork();
2753b9401dbSMike Pritchard 	if (d->d_pid < 0) {
276d33e92f9SJulian Elischer 		perror("fork");
2778fae3551SRodney W. Grimes 		return (8);
2788fae3551SRodney W. Grimes 	}
2793b9401dbSMike Pritchard 	if (d->d_pid == 0)
2803af26d4aSKirk McKusick 		exit(chkquota(p->p_devname, p->p_qfu, p->p_qfg));
2818fae3551SRodney W. Grimes 	return (0);
2828fae3551SRodney W. Grimes }
283