Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/fsck/preen.c
39475 views
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
34
/* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */
35
36
#include <sys/param.h>
37
#include <sys/stat.h>
38
#include <sys/wait.h>
39
#include <sys/queue.h>
40
41
#include <err.h>
42
#include <ctype.h>
43
#include <fstab.h>
44
#include <string.h>
45
#include <stdio.h>
46
#include <stdlib.h>
47
#include <unistd.h>
48
49
#include "fsutil.h"
50
51
struct partentry {
52
TAILQ_ENTRY(partentry) p_entries;
53
char *p_devname; /* device name */
54
char *p_mntpt; /* mount point */
55
char *p_type; /* file system type */
56
int p_failok; /* failok option set */
57
};
58
59
static TAILQ_HEAD(part, partentry) badh;
60
61
struct diskentry {
62
TAILQ_ENTRY(diskentry) d_entries;
63
char *d_name; /* disk base name */
64
TAILQ_HEAD(prt, partentry) d_part; /* list of partitions on disk */
65
int d_pid; /* 0 or pid of fsck proc */
66
};
67
68
static TAILQ_HEAD(disk, diskentry) diskh;
69
70
static int nrun = 0, ndisks = 0;
71
72
static struct diskentry *finddisk(const char *);
73
static void addpart(const char *, const char *, const char *, const int);
74
static int startdisk(struct diskentry *,
75
int (*)(const char *, const char *, const char *, const char *, pid_t *));
76
static void printpart(void);
77
78
int
79
checkfstab(int flags, int (*docheck)(struct fstab *),
80
int (*checkit)(const char *, const char *, const char *, const char *, pid_t *))
81
{
82
struct fstab *fs;
83
struct diskentry *d, *nextdisk;
84
struct partentry *p;
85
int ret, pid, retcode, passno, sumstatus, status, nextpass;
86
const char *name;
87
88
TAILQ_INIT(&badh);
89
TAILQ_INIT(&diskh);
90
91
sumstatus = 0;
92
93
nextpass = 0;
94
for (passno = 1; nextpass != INT_MAX; passno = nextpass) {
95
if (flags & CHECK_DEBUG)
96
printf("pass %d\n", passno);
97
98
nextpass = INT_MAX;
99
if (setfsent() == 0) {
100
warnx("Can't open checklist file: %s\n", _PATH_FSTAB);
101
return (8);
102
}
103
while ((fs = getfsent()) != NULL) {
104
name = fs->fs_spec;
105
if (fs->fs_passno > passno && fs->fs_passno < nextpass)
106
nextpass = fs->fs_passno;
107
108
if (passno != fs->fs_passno)
109
continue;
110
111
if ((*docheck)(fs) == 0)
112
continue;
113
114
if (flags & CHECK_DEBUG)
115
printf("pass %d, name %s\n", passno, name);
116
117
if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
118
(flags & DO_BACKGRD) != 0) {
119
if (name == NULL) {
120
if (flags & CHECK_PREEN)
121
return 8;
122
else
123
continue;
124
}
125
sumstatus = (*checkit)(fs->fs_vfstype,
126
name, fs->fs_file, NULL, NULL);
127
if (sumstatus)
128
return (sumstatus);
129
continue;
130
}
131
if (name == NULL) {
132
(void) fprintf(stderr,
133
"BAD DISK NAME %s\n", fs->fs_spec);
134
sumstatus |= 8;
135
continue;
136
}
137
addpart(fs->fs_vfstype, name, fs->fs_file,
138
getfsopt(fs, "failok"));
139
}
140
141
if ((flags & CHECK_PREEN) == 0 || passno == 1 ||
142
(flags & DO_BACKGRD) != 0)
143
continue;
144
145
if (flags & CHECK_DEBUG) {
146
printf("Parallel start\n");
147
printpart();
148
}
149
150
TAILQ_FOREACH(nextdisk, &diskh, d_entries) {
151
if ((ret = startdisk(nextdisk, checkit)) != 0)
152
return ret;
153
}
154
155
if (flags & CHECK_DEBUG)
156
printf("Parallel wait\n");
157
while ((pid = wait(&status)) != -1) {
158
TAILQ_FOREACH(d, &diskh, d_entries)
159
if (d->d_pid == pid)
160
break;
161
162
if (d == NULL) {
163
warnx("Unknown pid %d\n", pid);
164
continue;
165
}
166
167
p = TAILQ_FIRST(&d->d_part);
168
169
if (WIFEXITED(status) == 0) {
170
retcode = 0;
171
} else if (p->p_failok == 0) {
172
retcode = WEXITSTATUS(status);
173
} else {
174
retcode = 0;
175
fprintf(stderr, "%s: failok SPECIFIED, FSCK "
176
"ERROR(S) IGNORED\n", p->p_devname);
177
}
178
179
if (flags & (CHECK_DEBUG|CHECK_VERBOSE))
180
(void) printf("done %s: %s (%s) = 0x%x\n",
181
p->p_type, p->p_devname, p->p_mntpt,
182
status);
183
184
if (WIFSIGNALED(status)) {
185
(void) fprintf(stderr,
186
"%s: %s (%s): EXITED WITH SIGNAL %d\n",
187
p->p_type, p->p_devname, p->p_mntpt,
188
WTERMSIG(status));
189
retcode = 8;
190
}
191
192
TAILQ_REMOVE(&d->d_part, p, p_entries);
193
194
if (retcode != 0) {
195
TAILQ_INSERT_TAIL(&badh, p, p_entries);
196
sumstatus |= retcode;
197
} else {
198
free(p->p_type);
199
free(p->p_devname);
200
free(p);
201
}
202
d->d_pid = 0;
203
nrun--;
204
205
if (TAILQ_EMPTY(&d->d_part)) {
206
TAILQ_REMOVE(&diskh, d, d_entries);
207
ndisks--;
208
} else {
209
if ((ret = startdisk(d, checkit)) != 0)
210
return ret;
211
}
212
}
213
if (flags & CHECK_DEBUG) {
214
printf("Parallel end\n");
215
printpart();
216
}
217
}
218
219
if (!(flags & CHECK_PREEN))
220
return 0;
221
222
if (sumstatus) {
223
p = TAILQ_FIRST(&badh);
224
if (p == NULL)
225
return (sumstatus);
226
227
(void) fprintf(stderr,
228
"THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
229
TAILQ_NEXT(p, p_entries) ? "S" : "",
230
"UNEXPECTED INCONSISTENCY:");
231
232
for (; p; p = TAILQ_NEXT(p, p_entries))
233
(void) fprintf(stderr,
234
"%s: %s (%s)%s", p->p_type, p->p_devname,
235
p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n");
236
237
return sumstatus;
238
}
239
(void) endfsent();
240
return (0);
241
}
242
243
static struct diskentry *
244
finddisk(const char *name)
245
{
246
const char *p;
247
size_t len = 0;
248
struct diskentry *d;
249
250
p = strrchr(name, '/');
251
if (p == NULL)
252
p = name;
253
else
254
p++;
255
for (; *p && !isdigit(*p); p++)
256
continue;
257
for (; *p && isdigit(*p); p++)
258
continue;
259
len = p - name;
260
if (len == 0)
261
len = strlen(name);
262
263
TAILQ_FOREACH(d, &diskh, d_entries)
264
if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0)
265
return d;
266
267
d = emalloc(sizeof(*d));
268
d->d_name = estrdup(name);
269
d->d_name[len] = '\0';
270
TAILQ_INIT(&d->d_part);
271
d->d_pid = 0;
272
273
TAILQ_INSERT_TAIL(&diskh, d, d_entries);
274
ndisks++;
275
276
return d;
277
}
278
279
280
static void
281
printpart(void)
282
{
283
struct diskentry *d;
284
struct partentry *p;
285
286
TAILQ_FOREACH(d, &diskh, d_entries) {
287
(void) printf("disk %s: ", d->d_name);
288
TAILQ_FOREACH(p, &d->d_part, p_entries)
289
(void) printf("%s ", p->p_devname);
290
(void) printf("\n");
291
}
292
}
293
294
295
static void
296
addpart(const char *type, const char *dev, const char *mntpt, const int failok)
297
{
298
struct diskentry *d = finddisk(dev);
299
struct partentry *p;
300
301
TAILQ_FOREACH(p, &d->d_part, p_entries)
302
if (strcmp(p->p_devname, dev) == 0) {
303
warnx("%s in fstab more than once!\n", dev);
304
return;
305
}
306
307
p = emalloc(sizeof(*p));
308
p->p_devname = estrdup(dev);
309
p->p_mntpt = estrdup(mntpt);
310
p->p_type = estrdup(type);
311
p->p_failok = failok;
312
313
TAILQ_INSERT_TAIL(&d->d_part, p, p_entries);
314
}
315
316
317
static int
318
startdisk(struct diskentry *d, int (*checkit)(const char *, const char *,
319
const char *, const char *, pid_t *))
320
{
321
struct partentry *p = TAILQ_FIRST(&d->d_part);
322
int rv;
323
324
while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt,
325
NULL, &d->d_pid)) != 0 && nrun > 0)
326
sleep(10);
327
328
if (rv == 0)
329
nrun++;
330
331
return rv;
332
}
333
334