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