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 <ufs/ufs/quota.h>
42
43 #include <err.h>
44 #include <ctype.h>
45 #include <fcntl.h>
46 #include <fstab.h>
47 #include <libutil.h>
48 #include <string.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <unistd.h>
52
53 #include "quotacheck.h"
54
55 struct partentry {
56 TAILQ_ENTRY(partentry) p_entries;
57 char *p_devname; /* device name */
58 const char *p_mntpt; /* mount point */
59 struct quotafile *p_qfu; /* user quota file info ptr */
60 struct quotafile *p_qfg; /* group quota file info */
61 };
62
63 TAILQ_HEAD(part, partentry) badh;
64
65 struct diskentry {
66 TAILQ_ENTRY(diskentry) d_entries;
67 char *d_name; /* disk base name */
68 TAILQ_HEAD(prt, partentry) d_part; /* list of partitions on disk */
69 int d_pid; /* 0 or pid of fsck proc */
70 };
71
72 TAILQ_HEAD(disk, diskentry) diskh;
73
74 static struct diskentry *finddisk(const char *);
75 static void addpart(struct fstab *, struct quotafile *, struct quotafile *);
76 static int startdisk(struct diskentry *);
77 extern void *emalloc(size_t);
78 extern char *estrdup(const char *);
79
80 int
checkfstab(int uflag,int gflag)81 checkfstab(int uflag, int gflag)
82 {
83 struct fstab *fs;
84 struct diskentry *d, *nextdisk;
85 struct partentry *p;
86 int ret, pid, retcode, passno, sumstatus, status, nextpass;
87 struct quotafile *qfu, *qfg;
88
89 TAILQ_INIT(&badh);
90 TAILQ_INIT(&diskh);
91
92 sumstatus = 0;
93
94 nextpass = 0;
95 for (passno = 1; nextpass != INT_MAX; passno = nextpass) {
96 nextpass = INT_MAX;
97 if (setfsent() == 0) {
98 warnx("Can't open checklist file: %s\n", _PATH_FSTAB);
99 return (8);
100 }
101 while ((fs = getfsent()) != NULL) {
102 if (fs->fs_passno > passno && fs->fs_passno < nextpass)
103 nextpass = fs->fs_passno;
104
105 if (passno != fs->fs_passno)
106 continue;
107
108 qfu = NULL;
109 if (uflag)
110 qfu = quota_open(fs, USRQUOTA, O_CREAT|O_RDWR);
111 qfg = NULL;
112 if (gflag)
113 qfg = quota_open(fs, GRPQUOTA, O_CREAT|O_RDWR);
114 if (qfu == NULL && qfg == NULL)
115 continue;
116
117 if (passno == 1) {
118 sumstatus = chkquota(fs->fs_spec, qfu, qfg);
119 if (qfu)
120 quota_close(qfu);
121 if (qfg)
122 quota_close(qfg);
123 if (sumstatus)
124 return (sumstatus);
125 continue;
126 }
127 addpart(fs, qfu, qfg);
128 }
129
130 if (passno == 1)
131 continue;
132
133 TAILQ_FOREACH(nextdisk, &diskh, d_entries) {
134 if ((ret = startdisk(nextdisk)) != 0)
135 return ret;
136 }
137
138 while ((pid = wait(&status)) != -1) {
139 TAILQ_FOREACH(d, &diskh, d_entries)
140 if (d->d_pid == pid)
141 break;
142
143 if (d == NULL) {
144 warnx("Unknown pid %d\n", pid);
145 continue;
146 }
147
148 if (WIFEXITED(status))
149 retcode = WEXITSTATUS(status);
150 else
151 retcode = 0;
152
153 p = TAILQ_FIRST(&d->d_part);
154
155 if (WIFSIGNALED(status)) {
156 (void) fprintf(stderr,
157 "%s: (%s): EXITED WITH SIGNAL %d\n",
158 p->p_devname, p->p_mntpt,
159 WTERMSIG(status));
160 retcode = 8;
161 }
162
163 TAILQ_REMOVE(&d->d_part, p, p_entries);
164
165 if (retcode != 0) {
166 TAILQ_INSERT_TAIL(&badh, p, p_entries);
167 sumstatus |= retcode;
168 } else {
169 free(p->p_devname);
170 if (p->p_qfu)
171 quota_close(p->p_qfu);
172 if (p->p_qfg)
173 quota_close(p->p_qfg);
174 free(p);
175 }
176 d->d_pid = 0;
177
178 if (TAILQ_EMPTY(&d->d_part)) {
179 TAILQ_REMOVE(&diskh, d, d_entries);
180 } else {
181 if ((ret = startdisk(d)) != 0)
182 return ret;
183 }
184 }
185 }
186
187 if (sumstatus) {
188 p = TAILQ_FIRST(&badh);
189 if (p == NULL)
190 return (sumstatus);
191
192 (void) fprintf(stderr,
193 "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
194 TAILQ_NEXT(p, p_entries) ? "S" : "",
195 "UNEXPECTED INCONSISTENCY:");
196
197 for (; p; p = TAILQ_NEXT(p, p_entries))
198 (void) fprintf(stderr,
199 "%s: (%s)%s", p->p_devname, p->p_mntpt,
200 TAILQ_NEXT(p, p_entries) ? ", " : "\n");
201
202 return sumstatus;
203 }
204 (void) endfsent();
205 return (0);
206 }
207
208
209 static struct diskentry *
finddisk(const char * name)210 finddisk(const char *name)
211 {
212 const char *p;
213 size_t len = 0;
214 struct diskentry *d;
215
216 p = strrchr(name, '/');
217 if (p == NULL)
218 p = name;
219 else
220 p++;
221 for (; *p && !isdigit(*p); p++)
222 continue;
223 for (; *p && isdigit(*p); p++)
224 continue;
225 len = p - name;
226 if (len == 0)
227 len = strlen(name);
228
229 TAILQ_FOREACH(d, &diskh, d_entries)
230 if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0)
231 return d;
232
233 d = emalloc(sizeof(*d));
234 d->d_name = estrdup(name);
235 d->d_name[len] = '\0';
236 TAILQ_INIT(&d->d_part);
237 d->d_pid = 0;
238
239 TAILQ_INSERT_TAIL(&diskh, d, d_entries);
240
241 return d;
242 }
243
244 static void
addpart(struct fstab * fs,struct quotafile * qfu,struct quotafile * qfg)245 addpart(struct fstab *fs, struct quotafile *qfu, struct quotafile *qfg)
246 {
247 struct diskentry *d = finddisk(fs->fs_spec);
248 struct partentry *p;
249
250 TAILQ_FOREACH(p, &d->d_part, p_entries)
251 if (strcmp(p->p_devname, fs->fs_spec) == 0) {
252 warnx("%s in fstab more than once!\n", fs->fs_spec);
253 return;
254 }
255
256 p = emalloc(sizeof(*p));
257 p->p_devname = estrdup(blockcheck(fs->fs_spec));
258 if (qfu != NULL)
259 p->p_mntpt = quota_fsname(qfu);
260 else
261 p->p_mntpt = quota_fsname(qfg);
262 p->p_qfu = qfu;
263 p->p_qfg = qfg;
264
265 TAILQ_INSERT_TAIL(&d->d_part, p, p_entries);
266 }
267
268
269 static int
startdisk(struct diskentry * d)270 startdisk(struct diskentry *d)
271 {
272 struct partentry *p = TAILQ_FIRST(&d->d_part);
273
274 d->d_pid = fork();
275 if (d->d_pid < 0) {
276 perror("fork");
277 return (8);
278 }
279 if (d->d_pid == 0)
280 exit(chkquota(p->p_devname, p->p_qfu, p->p_qfg));
281 return (0);
282 }
283