1 /* $NetBSD: preen.c,v 1.31 2012/04/07 04:52:20 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.31 2012/04/07 04:52:20 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 char buf
[MAXPATHLEN
];
113 if ((auxarg
= (*docheck
)(fs
)) == NULL
)
115 fsspec
= getfsspecname(buf
, sizeof(buf
), fs
->fs_spec
);
116 if (fsspec
== NULL
) {
118 return FSCK_EXIT_CHECK_FAILED
;
120 name
= blockcheck(fsspec
);
121 if (flags
& CHECK_DEBUG
)
122 printf("pass %d, name %s\n", passno
, name
);
124 if ((flags
& CHECK_PREEN
) == 0 ||
125 (passno
== 1 && fs
->fs_passno
== 1)) {
127 if (flags
& CHECK_PREEN
)
128 return FSCK_EXIT_CHECK_FAILED
;
132 sumstatus
= (*checkit
)(fs
->fs_vfstype
,
133 name
, fs
->fs_file
, auxarg
, NULL
);
136 if ((flags
& CHECK_NOFIX
) == 0)
138 else if (error
< sumstatus
)
141 } else if (passno
== 2 && fs
->fs_passno
> 1) {
143 (void) fprintf(stderr
,
144 "BAD DISK NAME %s\n", fsspec
);
145 sumstatus
= FSCK_EXIT_CHECK_FAILED
;
148 addpart(fs
->fs_vfstype
, name
, fs
->fs_file
,
152 if ((flags
& CHECK_PREEN
) == 0)
156 if (flags
& CHECK_DEBUG
)
159 if (flags
& CHECK_PREEN
) {
164 nextdisk
= TAILQ_FIRST(&diskh
);
165 for (passno
= 0; passno
< maxrun
; ++passno
) {
166 if ((ret
= startdisk(nextdisk
, checkit
)) != 0) {
167 if ((flags
& CHECK_NOFIX
) == 0)
169 else if (error
< ret
)
172 nextdisk
= TAILQ_NEXT(nextdisk
, d_entries
);
175 while ((pid
= wait(&status
)) != -1) {
176 TAILQ_FOREACH(d
, &diskh
, d_entries
)
181 warnx("Unknown pid %d", pid
);
186 if (WIFEXITED(status
))
187 retcode
= WEXITSTATUS(status
);
191 p
= TAILQ_FIRST(&d
->d_part
);
193 if (flags
& (CHECK_DEBUG
|CHECK_VERBOSE
))
194 (void) printf("done %s: %s (%s) = 0x%x\n",
195 p
->p_type
, p
->p_devname
, p
->p_mntpt
,
198 if (WIFSIGNALED(status
)) {
199 (void) fprintf(stderr
,
200 "%s: %s (%s): EXITED WITH SIGNAL %d\n",
201 p
->p_type
, p
->p_devname
, p
->p_mntpt
,
203 retcode
= FSCK_EXIT_SIGNALLED
;
206 TAILQ_REMOVE(&d
->d_part
, p
, p_entries
);
209 TAILQ_INSERT_TAIL(&badh
, p
, p_entries
);
210 sumstatus
|= retcode
;
219 if (TAILQ_FIRST(&d
->d_part
) == NULL
)
222 if (nextdisk
== NULL
) {
223 if (TAILQ_FIRST(&d
->d_part
) != NULL
) {
224 if ((ret
= startdisk(d
, checkit
)) != 0)
226 if ((flags
& CHECK_NOFIX
) == 0)
228 else if (error
< ret
)
232 } else if (nrun
< maxrun
&& nrun
< ndisks
) {
234 nextdisk
= TAILQ_NEXT(nextdisk
,
236 if (nextdisk
== NULL
)
237 nextdisk
= TAILQ_FIRST(&diskh
);
238 if (TAILQ_FIRST(&nextdisk
->d_part
)
239 != NULL
&& nextdisk
->d_pid
== 0)
242 if ((ret
= startdisk(nextdisk
, checkit
)) != 0)
244 if ((flags
& CHECK_NOFIX
) == 0)
246 else if (error
< ret
)
253 p
= TAILQ_FIRST(&badh
);
257 (void) fprintf(stderr
,
258 "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
259 TAILQ_NEXT(p
, p_entries
) ? "S" : "",
260 "UNEXPECTED INCONSISTENCY:");
262 TAILQ_FOREACH(p
, &badh
, p_entries
)
263 (void) fprintf(stderr
,
264 "%s: %s (%s)%s", p
->p_type
, p
->p_devname
,
265 p
->p_mntpt
, TAILQ_NEXT(p
, p_entries
) ? ", " : "\n");
274 static struct diskentry
*
275 finddisk(const char *name
)
280 #if !defined(__minix)
281 char buf
[MAXPATHLEN
];
282 struct dkwedge_info dkw
;
285 if ((fd
= opendisk(name
, O_RDONLY
, buf
, sizeof(buf
), 0)) != -1) {
286 if (ioctl(fd
, DIOCGWEDGEINFO
, &dkw
) != -1)
287 name
= dkw
.dkw_parent
;
290 #endif /* !defined(__minix) */
292 for (dlen
= len
= strlen(name
), p
= name
+ len
- 1; p
>= name
; --p
)
293 if (isdigit((unsigned char)*p
)) {
300 TAILQ_FOREACH(d
, &diskh
, d_entries
)
301 if (strncmp(d
->d_name
, name
, len
) == 0 && d
->d_name
[len
] == 0)
304 d
= emalloc(sizeof(*d
));
305 d
->d_name
= estrdup(name
);
306 d
->d_name
[len
] = '\0';
307 TAILQ_INIT(&d
->d_part
);
310 TAILQ_INSERT_TAIL(&diskh
, d
, d_entries
);
323 TAILQ_FOREACH(d
, &diskh
, d_entries
) {
324 (void) printf("disk %s:", d
->d_name
);
325 TAILQ_FOREACH(p
, &d
->d_part
, p_entries
)
326 (void) printf(" %s", p
->p_devname
);
333 addpart(const char *type
, const char *dev
, const char *mntpt
, void *auxarg
)
335 struct diskentry
*d
= finddisk(dev
);
338 TAILQ_FOREACH(p
, &d
->d_part
, p_entries
)
339 if (strcmp(p
->p_devname
, dev
) == 0) {
340 warnx("%s in fstab more than once!", dev
);
344 p
= emalloc(sizeof(*p
));
345 p
->p_devname
= estrdup(dev
);
346 p
->p_mntpt
= estrdup(mntpt
);
347 p
->p_type
= estrdup(type
);
348 p
->p_auxarg
= auxarg
;
350 TAILQ_INSERT_TAIL(&d
->d_part
, p
, p_entries
);
355 startdisk(struct diskentry
*d
,
356 int (*checkit
)(const char *, const char *, const char *, void *, pid_t
*))
358 struct partentry
*p
= TAILQ_FIRST(&d
->d_part
);
361 while ((rv
= (*checkit
)(p
->p_type
, p
->p_devname
, p
->p_mntpt
,
362 p
->p_auxarg
, &d
->d_pid
)) != 0 && nrun
> 0)