]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/fsck/preen.c
sys/{x86,amd64}: remove one of doubled ;s
[FreeBSD/FreeBSD.git] / sbin / fsck / preen.c
1 /*      $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $       */
2
3 /*-
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  * Copyright (c) 1990, 1993
7  *      The Regents of the University of California.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * $FreeBSD$
34  */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)preen.c     8.5 (Berkeley) 4/28/95";
40 #else
41 __RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $");
42 #endif
43 #endif /* not lint */
44
45 #include <sys/param.h>
46 #include <sys/stat.h>
47 #include <sys/wait.h>
48 #include <sys/queue.h>
49
50 #include <err.h>
51 #include <ctype.h>
52 #include <fstab.h>
53 #include <string.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57
58 #include "fsutil.h"
59
60 struct partentry {
61         TAILQ_ENTRY(partentry)   p_entries;
62         char                    *p_devname;     /* device name */
63         char                    *p_mntpt;       /* mount point */
64         char                    *p_type;        /* file system type */
65 };
66
67 static TAILQ_HEAD(part, partentry) badh;
68
69 struct diskentry {
70         TAILQ_ENTRY(diskentry)      d_entries;
71         char                       *d_name;     /* disk base name */
72         TAILQ_HEAD(prt, partentry)  d_part;     /* list of partitions on disk */
73         int                         d_pid;      /* 0 or pid of fsck proc */
74 };
75
76 static TAILQ_HEAD(disk, diskentry) diskh;
77
78 static int nrun = 0, ndisks = 0;
79
80 static struct diskentry *finddisk(const char *);
81 static void addpart(const char *, const char *, const char *);
82 static int startdisk(struct diskentry *, 
83     int (*)(const char *, const char *, const char *, const char *, pid_t *));
84 static void printpart(void);
85
86 int
87 checkfstab(int flags, int (*docheck)(struct fstab *), 
88     int (*checkit)(const char *, const char *, const char *, const char *, pid_t *))
89 {
90         struct fstab *fs;
91         struct diskentry *d, *nextdisk;
92         struct partentry *p;
93         int ret, pid, retcode, passno, sumstatus, status, nextpass;
94         const char *name;
95
96         TAILQ_INIT(&badh);
97         TAILQ_INIT(&diskh);
98
99         sumstatus = 0;
100
101         nextpass = 0;
102         for (passno = 1; nextpass != INT_MAX; passno = nextpass) {
103                 if (flags & CHECK_DEBUG)
104                         printf("pass %d\n", passno);
105                 
106                 nextpass = INT_MAX;
107                 if (setfsent() == 0) {
108                         warnx("Can't open checklist file: %s\n", _PATH_FSTAB);
109                         return (8);
110                 }
111                 while ((fs = getfsent()) != NULL) {
112                         name = fs->fs_spec;
113                         if (fs->fs_passno > passno && fs->fs_passno < nextpass)
114                                 nextpass = fs->fs_passno;
115
116                         if (passno != fs->fs_passno)
117                                 continue;
118
119                         if ((*docheck)(fs) == 0)
120                                 continue;
121
122                         if (flags & CHECK_DEBUG)
123                                 printf("pass %d, name %s\n", passno, name);
124
125                         if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
126                             (flags & DO_BACKGRD) != 0) {
127                                 if (name == NULL) {
128                                         if (flags & CHECK_PREEN)
129                                                 return 8;
130                                         else
131                                                 continue;
132                                 }
133                                 sumstatus = (*checkit)(fs->fs_vfstype,
134                                     name, fs->fs_file, NULL, NULL);
135
136                                 if (sumstatus)
137                                         return (sumstatus);
138                                 continue;
139                         } 
140                         if (name == NULL) {
141                                 (void) fprintf(stderr,
142                                     "BAD DISK NAME %s\n", fs->fs_spec);
143                                 sumstatus |= 8;
144                                 continue;
145                         }
146                         addpart(fs->fs_vfstype, name, fs->fs_file);
147                 }
148
149                 if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
150                     (flags & DO_BACKGRD) != 0)
151                         continue;
152
153                 if (flags & CHECK_DEBUG) {
154                         printf("Parallel start\n");
155                         printpart();
156                 }
157                 
158                 TAILQ_FOREACH(nextdisk, &diskh, d_entries) {
159                         if ((ret = startdisk(nextdisk, checkit)) != 0)
160                                 return ret;
161                 }
162
163                 if (flags & CHECK_DEBUG) 
164                         printf("Parallel wait\n");
165                 while ((pid = wait(&status)) != -1) {
166                         TAILQ_FOREACH(d, &diskh, d_entries) 
167                                 if (d->d_pid == pid)
168                                         break;
169
170                         if (d == NULL) {
171                                 warnx("Unknown pid %d\n", pid);
172                                 continue;
173                         }
174
175                         if (WIFEXITED(status))
176                                 retcode = WEXITSTATUS(status);
177                         else
178                                 retcode = 0;
179
180                         p = TAILQ_FIRST(&d->d_part);
181
182                         if (flags & (CHECK_DEBUG|CHECK_VERBOSE))
183                                 (void) printf("done %s: %s (%s) = 0x%x\n",
184                                     p->p_type, p->p_devname, p->p_mntpt,
185                                     status);
186
187                         if (WIFSIGNALED(status)) {
188                                 (void) fprintf(stderr,
189                                     "%s: %s (%s): EXITED WITH SIGNAL %d\n",
190                                     p->p_type, p->p_devname, p->p_mntpt,
191                                     WTERMSIG(status));
192                                 retcode = 8;
193                         }
194
195                         TAILQ_REMOVE(&d->d_part, p, p_entries);
196
197                         if (retcode != 0) {
198                                 TAILQ_INSERT_TAIL(&badh, p, p_entries);
199                                 sumstatus |= retcode;
200                         } else {
201                                 free(p->p_type);
202                                 free(p->p_devname);
203                                 free(p);
204                         }
205                         d->d_pid = 0;
206                         nrun--;
207
208                         if (TAILQ_EMPTY(&d->d_part)) {
209                                 TAILQ_REMOVE(&diskh, d, d_entries);
210                                 ndisks--;
211                         } else {
212                                 if ((ret = startdisk(d, checkit)) != 0)
213                                         return ret;
214                         }
215                 }
216                 if (flags & CHECK_DEBUG) {
217                         printf("Parallel end\n");
218                         printpart();
219                 }
220         }
221
222         if (!(flags & CHECK_PREEN))
223                         return 0;
224
225         if (sumstatus) {
226                 p = TAILQ_FIRST(&badh);
227                 if (p == NULL)
228                         return (sumstatus);
229
230                 (void) fprintf(stderr,
231                         "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
232                         TAILQ_NEXT(p, p_entries) ? "S" : "",
233                         "UNEXPECTED INCONSISTENCY:");
234
235                 for (; p; p = TAILQ_NEXT(p, p_entries))
236                         (void) fprintf(stderr,
237                             "%s: %s (%s)%s", p->p_type, p->p_devname,
238                             p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n");
239
240                 return sumstatus;
241         }
242         (void) endfsent();
243         return (0);
244 }
245
246
247 static struct diskentry *
248 finddisk(const char *name)
249 {
250         const char *p;
251         size_t len = 0;
252         struct diskentry *d;
253
254         p = strrchr(name, '/');
255         if (p == NULL)
256                 p = name;
257         else
258                 p++;
259         for (; *p && !isdigit(*p); p++)
260                 continue;
261         for (; *p && isdigit(*p); p++)
262                 continue;
263         len = p - name;
264         if (len == 0)
265                 len = strlen(name);
266
267         TAILQ_FOREACH(d, &diskh, d_entries) 
268                 if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0)
269                         return d;
270
271         d = emalloc(sizeof(*d));
272         d->d_name = estrdup(name);
273         d->d_name[len] = '\0';
274         TAILQ_INIT(&d->d_part);
275         d->d_pid = 0;
276
277         TAILQ_INSERT_TAIL(&diskh, d, d_entries);
278         ndisks++;
279
280         return d;
281 }
282
283
284 static void
285 printpart(void)
286 {
287         struct diskentry *d;
288         struct partentry *p;
289
290         TAILQ_FOREACH(d, &diskh, d_entries) {
291                 (void) printf("disk %s: ", d->d_name);
292                 TAILQ_FOREACH(p, &d->d_part, p_entries)
293                         (void) printf("%s ", p->p_devname);
294                 (void) printf("\n");
295         }
296 }
297
298
299 static void
300 addpart(const char *type, const char *dev, const char *mntpt)
301 {
302         struct diskentry *d = finddisk(dev);
303         struct partentry *p;
304
305         TAILQ_FOREACH(p, &d->d_part, p_entries)
306                 if (strcmp(p->p_devname, dev) == 0) {
307                         warnx("%s in fstab more than once!\n", dev);
308                         return;
309                 }
310
311         p = emalloc(sizeof(*p));
312         p->p_devname = estrdup(dev);
313         p->p_mntpt = estrdup(mntpt);
314         p->p_type = estrdup(type);
315
316         TAILQ_INSERT_TAIL(&d->d_part, p, p_entries);
317 }
318
319
320 static int
321 startdisk(struct diskentry *d, int (*checkit)(const char *, const char *,
322     const char *, const char *, pid_t *))
323 {
324         struct partentry *p = TAILQ_FIRST(&d->d_part);
325         int rv;
326
327         while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt,
328             NULL, &d->d_pid)) != 0 && nrun > 0)
329                 sleep(10);
330
331         if (rv == 0)
332                 nrun++;
333
334         return rv;
335 }