1 /* $NetBSD: preen.c,v 1.32 2015/06/21 04:01:40 dholland Exp $ */
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95";
37 __RCSID("$NetBSD: preen.c,v 1.32 2015/06/21 04:01:40 dholland Exp $");
43 * used by usr.sbin/quotacheck
46 #include <sys/param.h>
49 #include <sys/queue.h>
51 #include <sys/ioctl.h>
64 #include "exitvalues.h"
67 TAILQ_ENTRY(partentry
) p_entries
;
68 char *p_devname
; /* device name */
69 char *p_mntpt
; /* mount point */
70 char *p_type
; /* file system type */
71 void *p_auxarg
; /* auxiliary argument */
74 TAILQ_HEAD(part
, partentry
) badh
;
77 TAILQ_ENTRY(diskentry
) d_entries
;
78 char *d_name
; /* disk base name */
79 TAILQ_HEAD(prt
, partentry
) d_part
; /* list of partitions on disk */
80 int d_pid
; /* 0 or pid of fsck proc */
83 TAILQ_HEAD(diskinfo
, diskentry
) diskh
;
85 static int nrun
= 0, ndisks
= 0;
87 static struct diskentry
*finddisk(const char *);
88 static void addpart(const char *, const char *, const char *, void *);
89 static int startdisk(struct diskentry
*,
90 int (*)(const char *, const char *, const char *, void *, pid_t
*));
91 static void printpart(void);
94 checkfstab(int flags
, int maxrun
, void *(*docheck
)(struct fstab
*),
95 int (*checkit
)(const char *, const char *, const char *, void *, pid_t
*))
98 struct diskentry
*d
, *nextdisk
;
100 int ret
, pid
, retcode
, passno
, sumstatus
, status
;
103 int error
= FSCK_EXIT_OK
;
108 sumstatus
= FSCK_EXIT_OK
;
110 for (passno
= 1; passno
<= 2; passno
++) {
111 if (setfsent() == 0) {
112 warnx("Can't open checklist file: %s", _PATH_FSTAB
);
113 return FSCK_EXIT_CHECK_FAILED
;
115 while ((fs
= getfsent()) != 0) {
116 char buf
[MAXPATHLEN
];
118 if ((auxarg
= (*docheck
)(fs
)) == NULL
)
120 fsspec
= getfsspecname(buf
, sizeof(buf
), fs
->fs_spec
);
121 if (fsspec
== NULL
) {
123 return FSCK_EXIT_CHECK_FAILED
;
125 name
= blockcheck(fsspec
);
126 if (flags
& CHECK_DEBUG
)
127 printf("pass %d, name %s\n", passno
, name
);
129 if ((flags
& CHECK_PREEN
) == 0 ||
130 (passno
== 1 && fs
->fs_passno
== 1)) {
132 if (flags
& CHECK_PREEN
)
133 return FSCK_EXIT_CHECK_FAILED
;
137 sumstatus
= (*checkit
)(fs
->fs_vfstype
,
138 name
, fs
->fs_file
, auxarg
, NULL
);
141 if ((flags
& CHECK_NOFIX
) == 0)
143 else if (error
< sumstatus
)
146 } else if (passno
== 2 && fs
->fs_passno
> 1) {
148 (void) fprintf(stderr
,
149 "BAD DISK NAME %s\n", fsspec
);
150 sumstatus
= FSCK_EXIT_CHECK_FAILED
;
153 addpart(fs
->fs_vfstype
, name
, fs
->fs_file
,
157 if ((flags
& CHECK_PREEN
) == 0)
161 if (flags
& CHECK_DEBUG
)
164 if (flags
& CHECK_PREEN
) {
169 nextdisk
= TAILQ_FIRST(&diskh
);
170 for (passno
= 0; passno
< maxrun
; ++passno
) {
171 if ((ret
= startdisk(nextdisk
, checkit
)) != 0) {
172 if ((flags
& CHECK_NOFIX
) == 0)
174 else if (error
< ret
)
177 nextdisk
= TAILQ_NEXT(nextdisk
, d_entries
);
180 while ((pid
= wait(&status
)) != -1) {
181 TAILQ_FOREACH(d
, &diskh
, d_entries
)
186 warnx("Unknown pid %d", pid
);
191 if (WIFEXITED(status
))
192 retcode
= WEXITSTATUS(status
);
196 p
= TAILQ_FIRST(&d
->d_part
);
198 if (flags
& (CHECK_DEBUG
|CHECK_VERBOSE
))
199 (void) printf("done %s: %s (%s) = 0x%x\n",
200 p
->p_type
, p
->p_devname
, p
->p_mntpt
,
203 if (WIFSIGNALED(status
)) {
204 (void) fprintf(stderr
,
205 "%s: %s (%s): EXITED WITH SIGNAL %d\n",
206 p
->p_type
, p
->p_devname
, p
->p_mntpt
,
208 retcode
= FSCK_EXIT_SIGNALLED
;
211 TAILQ_REMOVE(&d
->d_part
, p
, p_entries
);
214 TAILQ_INSERT_TAIL(&badh
, p
, p_entries
);
215 sumstatus
|= retcode
;
224 if (TAILQ_FIRST(&d
->d_part
) == NULL
)
227 if (nextdisk
== NULL
) {
228 if (TAILQ_FIRST(&d
->d_part
) != NULL
) {
229 if ((ret
= startdisk(d
, checkit
)) != 0)
231 if ((flags
& CHECK_NOFIX
) == 0)
233 else if (error
< ret
)
237 } else if (nrun
< maxrun
&& nrun
< ndisks
) {
239 nextdisk
= TAILQ_NEXT(nextdisk
,
241 if (nextdisk
== NULL
)
242 nextdisk
= TAILQ_FIRST(&diskh
);
243 if (TAILQ_FIRST(&nextdisk
->d_part
)
244 != NULL
&& nextdisk
->d_pid
== 0)
247 if ((ret
= startdisk(nextdisk
, checkit
)) != 0)
249 if ((flags
& CHECK_NOFIX
) == 0)
251 else if (error
< ret
)
258 p
= TAILQ_FIRST(&badh
);
262 (void) fprintf(stderr
,
263 "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
264 TAILQ_NEXT(p
, p_entries
) ? "S" : "",
265 "UNEXPECTED INCONSISTENCY:");
267 TAILQ_FOREACH(p
, &badh
, p_entries
)
268 (void) fprintf(stderr
,
269 "%s: %s (%s)%s", p
->p_type
, p
->p_devname
,
270 p
->p_mntpt
, TAILQ_NEXT(p
, p_entries
) ? ", " : "\n");
279 static struct diskentry
*
280 finddisk(const char *name
)
285 #if !defined(__minix)
286 char buf
[MAXPATHLEN
];
287 struct dkwedge_info dkw
;
290 if ((fd
= opendisk(name
, O_RDONLY
, buf
, sizeof(buf
), 0)) != -1) {
291 if (ioctl(fd
, DIOCGWEDGEINFO
, &dkw
) != -1)
292 name
= dkw
.dkw_parent
;
295 #endif /* !defined(__minix) */
297 for (dlen
= len
= strlen(name
), p
= name
+ len
- 1; p
>= name
; --p
)
298 if (isdigit((unsigned char)*p
)) {
305 TAILQ_FOREACH(d
, &diskh
, d_entries
)
306 if (strncmp(d
->d_name
, name
, len
) == 0 && d
->d_name
[len
] == 0)
309 d
= emalloc(sizeof(*d
));
310 d
->d_name
= estrdup(name
);
311 d
->d_name
[len
] = '\0';
312 TAILQ_INIT(&d
->d_part
);
315 TAILQ_INSERT_TAIL(&diskh
, d
, d_entries
);
328 TAILQ_FOREACH(d
, &diskh
, d_entries
) {
329 (void) printf("disk %s:", d
->d_name
);
330 TAILQ_FOREACH(p
, &d
->d_part
, p_entries
)
331 (void) printf(" %s", p
->p_devname
);
338 addpart(const char *type
, const char *dev
, const char *mntpt
, void *auxarg
)
340 struct diskentry
*d
= finddisk(dev
);
343 TAILQ_FOREACH(p
, &d
->d_part
, p_entries
)
344 if (strcmp(p
->p_devname
, dev
) == 0) {
345 warnx("%s in fstab more than once!", dev
);
349 p
= emalloc(sizeof(*p
));
350 p
->p_devname
= estrdup(dev
);
351 p
->p_mntpt
= estrdup(mntpt
);
352 p
->p_type
= estrdup(type
);
353 p
->p_auxarg
= auxarg
;
355 TAILQ_INSERT_TAIL(&d
->d_part
, p
, p_entries
);
360 startdisk(struct diskentry
*d
,
361 int (*checkit
)(const char *, const char *, const char *, void *, pid_t
*))
363 struct partentry
*p
= TAILQ_FIRST(&d
->d_part
);
366 while ((rv
= (*checkit
)(p
->p_type
, p
->p_devname
, p
->p_mntpt
,
367 p
->p_auxarg
, &d
->d_pid
)) != 0 && nrun
> 0)