1 /* $NetBSD: preen.c,v 1.30 2008/02/23 21:41:47 christos 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.30 2008/02/23 21:41:47 christos Exp $");
41 #include <sys/param.h>
44 #include <sys/queue.h>
46 #include <sys/ioctl.h>
59 #include "exitvalues.h"
62 TAILQ_ENTRY(partentry
) p_entries
;
63 char *p_devname
; /* device name */
64 char *p_mntpt
; /* mount point */
65 char *p_type
; /* file system type */
66 void *p_auxarg
; /* auxiliary argument */
69 TAILQ_HEAD(part
, partentry
) badh
;
72 TAILQ_ENTRY(diskentry
) d_entries
;
73 char *d_name
; /* disk base name */
74 TAILQ_HEAD(prt
, partentry
) d_part
; /* list of partitions on disk */
75 int d_pid
; /* 0 or pid of fsck proc */
78 TAILQ_HEAD(diskinfo
, diskentry
) diskh
;
80 static int nrun
= 0, ndisks
= 0;
82 static struct diskentry
*finddisk(const char *);
83 static void addpart(const char *, const char *, const char *, void *);
84 static int startdisk(struct diskentry
*,
85 int (*)(const char *, const char *, const char *, void *, pid_t
*));
86 static void printpart(void);
89 checkfstab(int flags
, int maxrun
, void *(*docheck
)(struct fstab
*),
90 int (*checkit
)(const char *, const char *, const char *, void *, pid_t
*))
93 struct diskentry
*d
, *nextdisk
;
95 int ret
, pid
, retcode
, passno
, sumstatus
, status
;
98 int error
= FSCK_EXIT_OK
;
103 sumstatus
= FSCK_EXIT_OK
;
105 for (passno
= 1; passno
<= 2; passno
++) {
106 if (setfsent() == 0) {
107 warnx("Can't open checklist file: %s", _PATH_FSTAB
);
108 return FSCK_EXIT_CHECK_FAILED
;
110 while ((fs
= getfsent()) != 0) {
111 if ((auxarg
= (*docheck
)(fs
)) == NULL
)
114 name
= blockcheck(fs
->fs_spec
);
115 if (flags
& CHECK_DEBUG
)
116 printf("pass %d, name %s\n", passno
, name
);
118 if ((flags
& CHECK_PREEN
) == 0 ||
119 (passno
== 1 && fs
->fs_passno
== 1)) {
121 if (flags
& CHECK_PREEN
)
122 return FSCK_EXIT_CHECK_FAILED
;
126 sumstatus
= (*checkit
)(fs
->fs_vfstype
,
127 name
, fs
->fs_file
, auxarg
, NULL
);
130 if ((flags
& CHECK_NOFIX
) == 0)
132 else if (error
< sumstatus
)
135 } else if (passno
== 2 && fs
->fs_passno
> 1) {
137 (void) fprintf(stderr
,
138 "BAD DISK NAME %s\n", fs
->fs_spec
);
139 sumstatus
= FSCK_EXIT_CHECK_FAILED
;
142 addpart(fs
->fs_vfstype
, name
, fs
->fs_file
,
146 if ((flags
& CHECK_PREEN
) == 0)
150 if (flags
& CHECK_DEBUG
)
153 if (flags
& CHECK_PREEN
) {
158 nextdisk
= TAILQ_FIRST(&diskh
);
159 for (passno
= 0; passno
< maxrun
; ++passno
) {
160 if ((ret
= startdisk(nextdisk
, checkit
)) != 0) {
161 if ((flags
& CHECK_NOFIX
) == 0)
163 else if (error
< ret
)
166 nextdisk
= TAILQ_NEXT(nextdisk
, d_entries
);
169 while ((pid
= wait(&status
)) != -1) {
170 TAILQ_FOREACH(d
, &diskh
, d_entries
)
175 warnx("Unknown pid %d", pid
);
180 if (WIFEXITED(status
))
181 retcode
= WEXITSTATUS(status
);
185 p
= TAILQ_FIRST(&d
->d_part
);
187 if (flags
& (CHECK_DEBUG
|CHECK_VERBOSE
))
188 (void) printf("done %s: %s (%s) = 0x%x\n",
189 p
->p_type
, p
->p_devname
, p
->p_mntpt
,
192 if (WIFSIGNALED(status
)) {
193 (void) fprintf(stderr
,
194 "%s: %s (%s): EXITED WITH SIGNAL %d\n",
195 p
->p_type
, p
->p_devname
, p
->p_mntpt
,
197 retcode
= FSCK_EXIT_SIGNALLED
;
200 TAILQ_REMOVE(&d
->d_part
, p
, p_entries
);
203 TAILQ_INSERT_TAIL(&badh
, p
, p_entries
);
204 sumstatus
|= retcode
;
213 if (TAILQ_FIRST(&d
->d_part
) == NULL
)
216 if (nextdisk
== NULL
) {
217 if (TAILQ_FIRST(&d
->d_part
) != NULL
) {
218 if ((ret
= startdisk(d
, checkit
)) != 0)
220 if ((flags
& CHECK_NOFIX
) == 0)
222 else if (error
< ret
)
226 } else if (nrun
< maxrun
&& nrun
< ndisks
) {
228 nextdisk
= TAILQ_NEXT(nextdisk
,
230 if (nextdisk
== NULL
)
231 nextdisk
= TAILQ_FIRST(&diskh
);
232 if (TAILQ_FIRST(&nextdisk
->d_part
)
233 != NULL
&& nextdisk
->d_pid
== 0)
236 if ((ret
= startdisk(nextdisk
, checkit
)) != 0)
238 if ((flags
& CHECK_NOFIX
) == 0)
240 else if (error
< ret
)
247 p
= TAILQ_FIRST(&badh
);
251 (void) fprintf(stderr
,
252 "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
253 TAILQ_NEXT(p
, p_entries
) ? "S" : "",
254 "UNEXPECTED INCONSISTENCY:");
256 TAILQ_FOREACH(p
, &badh
, p_entries
)
257 (void) fprintf(stderr
,
258 "%s: %s (%s)%s", p
->p_type
, p
->p_devname
,
259 p
->p_mntpt
, TAILQ_NEXT(p
, p_entries
) ? ", " : "\n");
268 static struct diskentry
*
269 finddisk(const char *name
)
274 char buf
[MAXPATHLEN
];
275 struct dkwedge_info dkw
;
279 if ((fd
= opendisk(name
, O_RDONLY
, buf
, sizeof(buf
), 0)) != -1) {
280 if (ioctl(fd
, DIOCGWEDGEINFO
, &dkw
) != -1)
281 name
= dkw
.dkw_parent
;
286 for (dlen
= len
= strlen(name
), p
= name
+ len
- 1; p
>= name
; --p
)
287 if (isdigit((unsigned char)*p
)) {
294 TAILQ_FOREACH(d
, &diskh
, d_entries
)
295 if (strncmp(d
->d_name
, name
, len
) == 0 && d
->d_name
[len
] == 0)
298 d
= emalloc(sizeof(*d
));
299 d
->d_name
= estrdup(name
);
300 d
->d_name
[len
] = '\0';
301 TAILQ_INIT(&d
->d_part
);
304 TAILQ_INSERT_TAIL(&diskh
, d
, d_entries
);
317 TAILQ_FOREACH(d
, &diskh
, d_entries
) {
318 (void) printf("disk %s:", d
->d_name
);
319 TAILQ_FOREACH(p
, &d
->d_part
, p_entries
)
320 (void) printf(" %s", p
->p_devname
);
327 addpart(const char *type
, const char *dev
, const char *mntpt
, void *auxarg
)
329 struct diskentry
*d
= finddisk(dev
);
332 TAILQ_FOREACH(p
, &d
->d_part
, p_entries
)
333 if (strcmp(p
->p_devname
, dev
) == 0) {
334 warnx("%s in fstab more than once!", dev
);
338 p
= emalloc(sizeof(*p
));
339 p
->p_devname
= estrdup(dev
);
340 p
->p_mntpt
= estrdup(mntpt
);
341 p
->p_type
= estrdup(type
);
342 p
->p_auxarg
= auxarg
;
344 TAILQ_INSERT_TAIL(&d
->d_part
, p
, p_entries
);
349 startdisk(struct diskentry
*d
,
350 int (*checkit
)(const char *, const char *, const char *, void *, pid_t
*))
352 struct partentry
*p
= TAILQ_FIRST(&d
->d_part
);
355 while ((rv
= (*checkit
)(p
->p_type
, p
->p_devname
, p
->p_mntpt
,
356 p
->p_auxarg
, &d
->d_pid
)) != 0 && nrun
> 0)