19a317438SAdrian Chadd /* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */
29a317438SAdrian Chadd
38a16b7a1SPedro F. Giffuni /*-
48a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
58a16b7a1SPedro F. Giffuni *
69a317438SAdrian Chadd * Copyright (c) 1990, 1993
79a317438SAdrian Chadd * The Regents of the University of California. All rights reserved.
89a317438SAdrian Chadd *
99a317438SAdrian Chadd * Redistribution and use in source and binary forms, with or without
109a317438SAdrian Chadd * modification, are permitted provided that the following conditions
119a317438SAdrian Chadd * are met:
129a317438SAdrian Chadd * 1. Redistributions of source code must retain the above copyright
139a317438SAdrian Chadd * notice, this list of conditions and the following disclaimer.
149a317438SAdrian Chadd * 2. Redistributions in binary form must reproduce the above copyright
159a317438SAdrian Chadd * notice, this list of conditions and the following disclaimer in the
169a317438SAdrian Chadd * documentation and/or other materials provided with the distribution.
17fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
189a317438SAdrian Chadd * may be used to endorse or promote products derived from this software
199a317438SAdrian Chadd * without specific prior written permission.
209a317438SAdrian Chadd *
219a317438SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
229a317438SAdrian Chadd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
239a317438SAdrian Chadd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
249a317438SAdrian Chadd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
259a317438SAdrian Chadd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
269a317438SAdrian Chadd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
279a317438SAdrian Chadd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
289a317438SAdrian Chadd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
299a317438SAdrian Chadd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
309a317438SAdrian Chadd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
319a317438SAdrian Chadd * SUCH DAMAGE.
329a317438SAdrian Chadd */
339a317438SAdrian Chadd
34*5b31cc94SWarner Losh /* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */
359a317438SAdrian Chadd
369a317438SAdrian Chadd #include <sys/param.h>
379a317438SAdrian Chadd #include <sys/stat.h>
389a317438SAdrian Chadd #include <sys/wait.h>
399a317438SAdrian Chadd #include <sys/queue.h>
409a317438SAdrian Chadd
419a317438SAdrian Chadd #include <err.h>
429a317438SAdrian Chadd #include <ctype.h>
439a317438SAdrian Chadd #include <fstab.h>
449a317438SAdrian Chadd #include <string.h>
459a317438SAdrian Chadd #include <stdio.h>
469a317438SAdrian Chadd #include <stdlib.h>
479a317438SAdrian Chadd #include <unistd.h>
489a317438SAdrian Chadd
499a317438SAdrian Chadd #include "fsutil.h"
509a317438SAdrian Chadd
519a317438SAdrian Chadd struct partentry {
529a317438SAdrian Chadd TAILQ_ENTRY(partentry) p_entries;
539a317438SAdrian Chadd char *p_devname; /* device name */
549a317438SAdrian Chadd char *p_mntpt; /* mount point */
559a317438SAdrian Chadd char *p_type; /* file system type */
56c72372c6SKirk McKusick int p_failok; /* failok option set */
579a317438SAdrian Chadd };
589a317438SAdrian Chadd
591efe3c6bSEd Schouten static TAILQ_HEAD(part, partentry) badh;
609a317438SAdrian Chadd
619a317438SAdrian Chadd struct diskentry {
629a317438SAdrian Chadd TAILQ_ENTRY(diskentry) d_entries;
639a317438SAdrian Chadd char *d_name; /* disk base name */
649a317438SAdrian Chadd TAILQ_HEAD(prt, partentry) d_part; /* list of partitions on disk */
659a317438SAdrian Chadd int d_pid; /* 0 or pid of fsck proc */
669a317438SAdrian Chadd };
679a317438SAdrian Chadd
681efe3c6bSEd Schouten static TAILQ_HEAD(disk, diskentry) diskh;
699a317438SAdrian Chadd
709a317438SAdrian Chadd static int nrun = 0, ndisks = 0;
719a317438SAdrian Chadd
72b70cd7eeSWarner Losh static struct diskentry *finddisk(const char *);
73c72372c6SKirk McKusick static void addpart(const char *, const char *, const char *, const int);
74b70cd7eeSWarner Losh static int startdisk(struct diskentry *,
753bbc4438SUlrich Spörlein int (*)(const char *, const char *, const char *, const char *, pid_t *));
76b70cd7eeSWarner Losh static void printpart(void);
779a317438SAdrian Chadd
789a317438SAdrian Chadd int
checkfstab(int flags,int (* docheck)(struct fstab *),int (* checkit)(const char *,const char *,const char *,const char *,pid_t *))79b70cd7eeSWarner Losh checkfstab(int flags, int (*docheck)(struct fstab *),
803bbc4438SUlrich Spörlein int (*checkit)(const char *, const char *, const char *, const char *, pid_t *))
819a317438SAdrian Chadd {
829a317438SAdrian Chadd struct fstab *fs;
839a317438SAdrian Chadd struct diskentry *d, *nextdisk;
849a317438SAdrian Chadd struct partentry *p;
850af7bca2SPoul-Henning Kamp int ret, pid, retcode, passno, sumstatus, status, nextpass;
869a317438SAdrian Chadd const char *name;
879a317438SAdrian Chadd
889a317438SAdrian Chadd TAILQ_INIT(&badh);
899a317438SAdrian Chadd TAILQ_INIT(&diskh);
909a317438SAdrian Chadd
919a317438SAdrian Chadd sumstatus = 0;
929a317438SAdrian Chadd
930af7bca2SPoul-Henning Kamp nextpass = 0;
940af7bca2SPoul-Henning Kamp for (passno = 1; nextpass != INT_MAX; passno = nextpass) {
950af7bca2SPoul-Henning Kamp if (flags & CHECK_DEBUG)
960af7bca2SPoul-Henning Kamp printf("pass %d\n", passno);
970af7bca2SPoul-Henning Kamp
980af7bca2SPoul-Henning Kamp nextpass = INT_MAX;
999a317438SAdrian Chadd if (setfsent() == 0) {
1009a317438SAdrian Chadd warnx("Can't open checklist file: %s\n", _PATH_FSTAB);
1019a317438SAdrian Chadd return (8);
1029a317438SAdrian Chadd }
103cd5f6a0cSMarcelo Araujo while ((fs = getfsent()) != NULL) {
1049a317438SAdrian Chadd name = fs->fs_spec;
1050af7bca2SPoul-Henning Kamp if (fs->fs_passno > passno && fs->fs_passno < nextpass)
1060af7bca2SPoul-Henning Kamp nextpass = fs->fs_passno;
1070af7bca2SPoul-Henning Kamp
1085cb6703eSPoul-Henning Kamp if (passno != fs->fs_passno)
1095cb6703eSPoul-Henning Kamp continue;
1105cb6703eSPoul-Henning Kamp
1115cb6703eSPoul-Henning Kamp if ((*docheck)(fs) == 0)
1120af7bca2SPoul-Henning Kamp continue;
1130af7bca2SPoul-Henning Kamp
1149a317438SAdrian Chadd if (flags & CHECK_DEBUG)
1159a317438SAdrian Chadd printf("pass %d, name %s\n", passno, name);
1169a317438SAdrian Chadd
117a02a0079SKirk McKusick if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
118a02a0079SKirk McKusick (flags & DO_BACKGRD) != 0) {
1199a317438SAdrian Chadd if (name == NULL) {
1209a317438SAdrian Chadd if (flags & CHECK_PREEN)
1219a317438SAdrian Chadd return 8;
1229a317438SAdrian Chadd else
1239a317438SAdrian Chadd continue;
1249a317438SAdrian Chadd }
1259a317438SAdrian Chadd sumstatus = (*checkit)(fs->fs_vfstype,
126a02a0079SKirk McKusick name, fs->fs_file, NULL, NULL);
1279a317438SAdrian Chadd if (sumstatus)
1289a317438SAdrian Chadd return (sumstatus);
1290af7bca2SPoul-Henning Kamp continue;
1300af7bca2SPoul-Henning Kamp }
1319a317438SAdrian Chadd if (name == NULL) {
1329a317438SAdrian Chadd (void) fprintf(stderr,
1339a317438SAdrian Chadd "BAD DISK NAME %s\n", fs->fs_spec);
1349a317438SAdrian Chadd sumstatus |= 8;
1359a317438SAdrian Chadd continue;
1369a317438SAdrian Chadd }
137c72372c6SKirk McKusick addpart(fs->fs_vfstype, name, fs->fs_file,
138c72372c6SKirk McKusick getfsopt(fs, "failok"));
1399a317438SAdrian Chadd }
1400af7bca2SPoul-Henning Kamp
141a02a0079SKirk McKusick if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
142a02a0079SKirk McKusick (flags & DO_BACKGRD) != 0)
1430af7bca2SPoul-Henning Kamp continue;
1440af7bca2SPoul-Henning Kamp
1450af7bca2SPoul-Henning Kamp if (flags & CHECK_DEBUG) {
1460af7bca2SPoul-Henning Kamp printf("Parallel start\n");
1470af7bca2SPoul-Henning Kamp printpart();
1489a317438SAdrian Chadd }
1490af7bca2SPoul-Henning Kamp
1500af7bca2SPoul-Henning Kamp TAILQ_FOREACH(nextdisk, &diskh, d_entries) {
1510af7bca2SPoul-Henning Kamp if ((ret = startdisk(nextdisk, checkit)) != 0)
1520af7bca2SPoul-Henning Kamp return ret;
1539a317438SAdrian Chadd }
1549a317438SAdrian Chadd
1559a317438SAdrian Chadd if (flags & CHECK_DEBUG)
1560af7bca2SPoul-Henning Kamp printf("Parallel wait\n");
1579a317438SAdrian Chadd while ((pid = wait(&status)) != -1) {
158dab777beSPoul-Henning Kamp TAILQ_FOREACH(d, &diskh, d_entries)
1599a317438SAdrian Chadd if (d->d_pid == pid)
1609a317438SAdrian Chadd break;
1619a317438SAdrian Chadd
1629a317438SAdrian Chadd if (d == NULL) {
1639a317438SAdrian Chadd warnx("Unknown pid %d\n", pid);
1649a317438SAdrian Chadd continue;
1659a317438SAdrian Chadd }
1669a317438SAdrian Chadd
167dab777beSPoul-Henning Kamp p = TAILQ_FIRST(&d->d_part);
1689a317438SAdrian Chadd
169c72372c6SKirk McKusick if (WIFEXITED(status) == 0) {
170c72372c6SKirk McKusick retcode = 0;
171c72372c6SKirk McKusick } else if (p->p_failok == 0) {
172c72372c6SKirk McKusick retcode = WEXITSTATUS(status);
173c72372c6SKirk McKusick } else {
174c72372c6SKirk McKusick retcode = 0;
175c72372c6SKirk McKusick fprintf(stderr, "%s: failok SPECIFIED, FSCK "
176c72372c6SKirk McKusick "ERROR(S) IGNORED\n", p->p_devname);
177c72372c6SKirk McKusick }
178c72372c6SKirk McKusick
1799a317438SAdrian Chadd if (flags & (CHECK_DEBUG|CHECK_VERBOSE))
1809a317438SAdrian Chadd (void) printf("done %s: %s (%s) = 0x%x\n",
1819a317438SAdrian Chadd p->p_type, p->p_devname, p->p_mntpt,
1829a317438SAdrian Chadd status);
1839a317438SAdrian Chadd
1849a317438SAdrian Chadd if (WIFSIGNALED(status)) {
1859a317438SAdrian Chadd (void) fprintf(stderr,
1869a317438SAdrian Chadd "%s: %s (%s): EXITED WITH SIGNAL %d\n",
1879a317438SAdrian Chadd p->p_type, p->p_devname, p->p_mntpt,
1889a317438SAdrian Chadd WTERMSIG(status));
1899a317438SAdrian Chadd retcode = 8;
1909a317438SAdrian Chadd }
1919a317438SAdrian Chadd
1929a317438SAdrian Chadd TAILQ_REMOVE(&d->d_part, p, p_entries);
1939a317438SAdrian Chadd
1949a317438SAdrian Chadd if (retcode != 0) {
1959a317438SAdrian Chadd TAILQ_INSERT_TAIL(&badh, p, p_entries);
1969a317438SAdrian Chadd sumstatus |= retcode;
1979a317438SAdrian Chadd } else {
1989a317438SAdrian Chadd free(p->p_type);
1999a317438SAdrian Chadd free(p->p_devname);
2009a317438SAdrian Chadd free(p);
2019a317438SAdrian Chadd }
2029a317438SAdrian Chadd d->d_pid = 0;
2039a317438SAdrian Chadd nrun--;
2049a317438SAdrian Chadd
2050af7bca2SPoul-Henning Kamp if (TAILQ_EMPTY(&d->d_part)) {
2060af7bca2SPoul-Henning Kamp TAILQ_REMOVE(&diskh, d, d_entries);
2079a317438SAdrian Chadd ndisks--;
20846e78a1fSPoul-Henning Kamp } else {
20946e78a1fSPoul-Henning Kamp if ((ret = startdisk(d, checkit)) != 0)
21046e78a1fSPoul-Henning Kamp return ret;
2110af7bca2SPoul-Henning Kamp }
2120af7bca2SPoul-Henning Kamp }
2130af7bca2SPoul-Henning Kamp if (flags & CHECK_DEBUG) {
2140af7bca2SPoul-Henning Kamp printf("Parallel end\n");
2150af7bca2SPoul-Henning Kamp printpart();
2160af7bca2SPoul-Henning Kamp }
2170af7bca2SPoul-Henning Kamp }
2189a317438SAdrian Chadd
2190af7bca2SPoul-Henning Kamp if (!(flags & CHECK_PREEN))
2200af7bca2SPoul-Henning Kamp return 0;
2210af7bca2SPoul-Henning Kamp
2229a317438SAdrian Chadd if (sumstatus) {
22332ff2662SPoul-Henning Kamp p = TAILQ_FIRST(&badh);
2249a317438SAdrian Chadd if (p == NULL)
2259a317438SAdrian Chadd return (sumstatus);
2269a317438SAdrian Chadd
2279a317438SAdrian Chadd (void) fprintf(stderr,
2289a317438SAdrian Chadd "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
229dab777beSPoul-Henning Kamp TAILQ_NEXT(p, p_entries) ? "S" : "",
2309a317438SAdrian Chadd "UNEXPECTED INCONSISTENCY:");
2319a317438SAdrian Chadd
232dab777beSPoul-Henning Kamp for (; p; p = TAILQ_NEXT(p, p_entries))
2339a317438SAdrian Chadd (void) fprintf(stderr,
2349a317438SAdrian Chadd "%s: %s (%s)%s", p->p_type, p->p_devname,
235dab777beSPoul-Henning Kamp p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n");
2369a317438SAdrian Chadd
2379a317438SAdrian Chadd return sumstatus;
2389a317438SAdrian Chadd }
2399a317438SAdrian Chadd (void) endfsent();
2409a317438SAdrian Chadd return (0);
2419a317438SAdrian Chadd }
2429a317438SAdrian Chadd
2439a317438SAdrian Chadd static struct diskentry *
finddisk(const char * name)244b70cd7eeSWarner Losh finddisk(const char *name)
2459a317438SAdrian Chadd {
2469a317438SAdrian Chadd const char *p;
2479a317438SAdrian Chadd size_t len = 0;
2489a317438SAdrian Chadd struct diskentry *d;
2499a317438SAdrian Chadd
25028b66787SPoul-Henning Kamp p = strrchr(name, '/');
25128b66787SPoul-Henning Kamp if (p == NULL)
25228b66787SPoul-Henning Kamp p = name;
25328b66787SPoul-Henning Kamp else
25428b66787SPoul-Henning Kamp p++;
25528b66787SPoul-Henning Kamp for (; *p && !isdigit(*p); p++)
25628b66787SPoul-Henning Kamp continue;
25728b66787SPoul-Henning Kamp for (; *p && isdigit(*p); p++)
25828b66787SPoul-Henning Kamp continue;
25928b66787SPoul-Henning Kamp len = p - name;
26028b66787SPoul-Henning Kamp if (len == 0)
2619a317438SAdrian Chadd len = strlen(name);
2629a317438SAdrian Chadd
263dab777beSPoul-Henning Kamp TAILQ_FOREACH(d, &diskh, d_entries)
2649a317438SAdrian Chadd if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0)
2659a317438SAdrian Chadd return d;
2669a317438SAdrian Chadd
2679a317438SAdrian Chadd d = emalloc(sizeof(*d));
2689a317438SAdrian Chadd d->d_name = estrdup(name);
2699a317438SAdrian Chadd d->d_name[len] = '\0';
2709a317438SAdrian Chadd TAILQ_INIT(&d->d_part);
2719a317438SAdrian Chadd d->d_pid = 0;
2729a317438SAdrian Chadd
2739a317438SAdrian Chadd TAILQ_INSERT_TAIL(&diskh, d, d_entries);
2749a317438SAdrian Chadd ndisks++;
2759a317438SAdrian Chadd
2769a317438SAdrian Chadd return d;
2779a317438SAdrian Chadd }
2789a317438SAdrian Chadd
2799a317438SAdrian Chadd
2809a317438SAdrian Chadd static void
printpart(void)281b70cd7eeSWarner Losh printpart(void)
2829a317438SAdrian Chadd {
2839a317438SAdrian Chadd struct diskentry *d;
2849a317438SAdrian Chadd struct partentry *p;
2859a317438SAdrian Chadd
286dab777beSPoul-Henning Kamp TAILQ_FOREACH(d, &diskh, d_entries) {
2879a317438SAdrian Chadd (void) printf("disk %s: ", d->d_name);
288dab777beSPoul-Henning Kamp TAILQ_FOREACH(p, &d->d_part, p_entries)
2899a317438SAdrian Chadd (void) printf("%s ", p->p_devname);
2909a317438SAdrian Chadd (void) printf("\n");
2919a317438SAdrian Chadd }
2929a317438SAdrian Chadd }
2939a317438SAdrian Chadd
2949a317438SAdrian Chadd
2959a317438SAdrian Chadd static void
addpart(const char * type,const char * dev,const char * mntpt,const int failok)296c72372c6SKirk McKusick addpart(const char *type, const char *dev, const char *mntpt, const int failok)
2979a317438SAdrian Chadd {
2986cf357bcSUlrich Spörlein struct diskentry *d = finddisk(dev);
2999a317438SAdrian Chadd struct partentry *p;
3009a317438SAdrian Chadd
301dab777beSPoul-Henning Kamp TAILQ_FOREACH(p, &d->d_part, p_entries)
3026cf357bcSUlrich Spörlein if (strcmp(p->p_devname, dev) == 0) {
3036cf357bcSUlrich Spörlein warnx("%s in fstab more than once!\n", dev);
3049a317438SAdrian Chadd return;
3059a317438SAdrian Chadd }
3069a317438SAdrian Chadd
3079a317438SAdrian Chadd p = emalloc(sizeof(*p));
3086cf357bcSUlrich Spörlein p->p_devname = estrdup(dev);
3099a317438SAdrian Chadd p->p_mntpt = estrdup(mntpt);
3109a317438SAdrian Chadd p->p_type = estrdup(type);
311c72372c6SKirk McKusick p->p_failok = failok;
3129a317438SAdrian Chadd
3139a317438SAdrian Chadd TAILQ_INSERT_TAIL(&d->d_part, p, p_entries);
3149a317438SAdrian Chadd }
3159a317438SAdrian Chadd
3169a317438SAdrian Chadd
3179a317438SAdrian Chadd static int
startdisk(struct diskentry * d,int (* checkit)(const char *,const char *,const char *,const char *,pid_t *))318b70cd7eeSWarner Losh startdisk(struct diskentry *d, int (*checkit)(const char *, const char *,
3193bbc4438SUlrich Spörlein const char *, const char *, pid_t *))
3209a317438SAdrian Chadd {
32132ff2662SPoul-Henning Kamp struct partentry *p = TAILQ_FIRST(&d->d_part);
3229a317438SAdrian Chadd int rv;
3239a317438SAdrian Chadd
3249a317438SAdrian Chadd while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt,
325a02a0079SKirk McKusick NULL, &d->d_pid)) != 0 && nrun > 0)
3269a317438SAdrian Chadd sleep(10);
3279a317438SAdrian Chadd
3289a317438SAdrian Chadd if (rv == 0)
3299a317438SAdrian Chadd nrun++;
3309a317438SAdrian Chadd
3319a317438SAdrian Chadd return rv;
3329a317438SAdrian Chadd }
333