Sun Feb 5 14:14:44 2012 UTC ()
Remove unneeded #include.


(dholland)
diff -r1.47 -r1.48 src/usr.bin/quota/quota.c
diff -r1.41 -r1.42 src/usr.sbin/repquota/repquota.c

cvs diff -r1.47 -r1.48 src/usr.bin/quota/quota.c (switch to unified diff)

--- src/usr.bin/quota/quota.c 2012/02/01 17:48:10 1.47
+++ src/usr.bin/quota/quota.c 2012/02/05 14:14:44 1.48
@@ -1,640 +1,639 @@ @@ -1,640 +1,639 @@
1/* $NetBSD: quota.c,v 1.47 2012/02/01 17:48:10 dholland Exp $ */ 1/* $NetBSD: quota.c,v 1.48 2012/02/05 14:14:44 dholland Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1980, 1990, 1993 4 * Copyright (c) 1980, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Robert Elz at The University of Melbourne. 8 * Robert Elz at The University of Melbourne.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37__COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\ 37__COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\
38 The Regents of the University of California. All rights reserved."); 38 The Regents of the University of California. All rights reserved.");
39#endif /* not lint */ 39#endif /* not lint */
40 40
41#ifndef lint 41#ifndef lint
42#if 0 42#if 0
43static char sccsid[] = "@(#)quota.c 8.4 (Berkeley) 4/28/95"; 43static char sccsid[] = "@(#)quota.c 8.4 (Berkeley) 4/28/95";
44#else 44#else
45__RCSID("$NetBSD: quota.c,v 1.47 2012/02/01 17:48:10 dholland Exp $"); 45__RCSID("$NetBSD: quota.c,v 1.48 2012/02/05 14:14:44 dholland Exp $");
46#endif 46#endif
47#endif /* not lint */ 47#endif /* not lint */
48 48
49/* 49/*
50 * Disk quota reporting program. 50 * Disk quota reporting program.
51 */ 51 */
52#include <sys/param.h> 52#include <sys/param.h>
53#include <sys/types.h> 53#include <sys/types.h>
54#include <sys/file.h> 54#include <sys/file.h>
55#include <sys/stat.h> 55#include <sys/stat.h>
56#include <sys/mount.h> 56#include <sys/mount.h>
57#include <sys/socket.h> 57#include <sys/socket.h>
58 58
59#include <assert.h> 59#include <assert.h>
60#include <ctype.h> 60#include <ctype.h>
61#include <err.h> 61#include <err.h>
62#include <errno.h> 62#include <errno.h>
63#include <fstab.h> 63#include <fstab.h>
64#include <grp.h> 64#include <grp.h>
65#include <netdb.h> 65#include <netdb.h>
66#include <pwd.h> 66#include <pwd.h>
67#include <stdio.h> 67#include <stdio.h>
68#include <stdlib.h> 68#include <stdlib.h>
69#include <string.h> 69#include <string.h>
70#include <time.h> 70#include <time.h>
71#include <unistd.h> 71#include <unistd.h>
72 72
73#include <quota.h> 73#include <quota.h>
74#include <quota/quota.h> 
75 74
76#include "printquota.h" 75#include "printquota.h"
77 76
78struct quotause { 77struct quotause {
79 struct quotause *next; 78 struct quotause *next;
80 uid_t id; 79 uid_t id;
81 struct quotaval *qvs; 80 struct quotaval *qvs;
82 unsigned numqvs; 81 unsigned numqvs;
83 char fsname[MAXPATHLEN + 1]; 82 char fsname[MAXPATHLEN + 1];
84 struct quotahandle *qh; 83 struct quotahandle *qh;
85}; 84};
86 85
87static int anyusage(struct quotaval *, unsigned); 86static int anyusage(struct quotaval *, unsigned);
88static int anyover(struct quotaval *, unsigned, time_t); 87static int anyover(struct quotaval *, unsigned, time_t);
89static const char *getovermsg(struct quotaval *, const char *, time_t); 88static const char *getovermsg(struct quotaval *, const char *, time_t);
90static struct quotause *getprivs(id_t, int); 89static struct quotause *getprivs(id_t, int);
91static void heading(int, const char *, id_t, const char *, const char *); 90static void heading(int, const char *, id_t, const char *, const char *);
92static int isover(struct quotaval *qv, time_t now); 91static int isover(struct quotaval *qv, time_t now);
93static void printqv(struct quotaval *, int, time_t); 92static void printqv(struct quotaval *, int, time_t);
94static void showgid(gid_t); 93static void showgid(gid_t);
95static void showgrpname(const char *); 94static void showgrpname(const char *);
96static void showonequota(int, const char *, id_t, const char *, 95static void showonequota(int, const char *, id_t, const char *,
97 struct quotause *); 96 struct quotause *);
98static void showquotas(int, const char *, id_t, const char *); 97static void showquotas(int, const char *, id_t, const char *);
99static void showuid(uid_t); 98static void showuid(uid_t);
100static void showusrname(const char *); 99static void showusrname(const char *);
101static int unlimited(struct quotaval *qvs, unsigned numqvs); 100static int unlimited(struct quotaval *qvs, unsigned numqvs);
102static void usage(void) __dead; 101static void usage(void) __dead;
103 102
104static int qflag = 0; 103static int qflag = 0;
105static int vflag = 0; 104static int vflag = 0;
106static int hflag = 0; 105static int hflag = 0;
107static int dflag = 0; 106static int dflag = 0;
108static int Dflag = 0; 107static int Dflag = 0;
109static uid_t myuid; 108static uid_t myuid;
110static int needheading; 109static int needheading;
111 110
112int 111int
113main(int argc, char *argv[]) 112main(int argc, char *argv[])
114{ 113{
115 int ngroups;  114 int ngroups;
116 gid_t mygid, gidset[NGROUPS]; 115 gid_t mygid, gidset[NGROUPS];
117 int i, gflag = 0, uflag = 0; 116 int i, gflag = 0, uflag = 0;
118 int ch; 117 int ch;
119 118
120 myuid = getuid(); 119 myuid = getuid();
121 while ((ch = getopt(argc, argv, "Ddhugvq")) != -1) { 120 while ((ch = getopt(argc, argv, "Ddhugvq")) != -1) {
122 switch(ch) { 121 switch(ch) {
123 case 'g': 122 case 'g':
124 gflag++; 123 gflag++;
125 break; 124 break;
126 case 'u': 125 case 'u':
127 uflag++; 126 uflag++;
128 break; 127 break;
129 case 'v': 128 case 'v':
130 vflag++; 129 vflag++;
131 break; 130 break;
132 case 'q': 131 case 'q':
133 qflag++; 132 qflag++;
134 break; 133 break;
135 case 'h': 134 case 'h':
136 hflag++; 135 hflag++;
137 break; 136 break;
138 case 'd': 137 case 'd':
139 dflag++; 138 dflag++;
140 break; 139 break;
141 case 'D': 140 case 'D':
142 Dflag++; 141 Dflag++;
143 break; 142 break;
144 default: 143 default:
145 usage(); 144 usage();
146 } 145 }
147 } 146 }
148 argc -= optind; 147 argc -= optind;
149 argv += optind; 148 argv += optind;
150 if (!uflag && !gflag) 149 if (!uflag && !gflag)
151 uflag++; 150 uflag++;
152 if (dflag) { 151 if (dflag) {
153#if 0 152#if 0
154 if (myuid != 0) 153 if (myuid != 0)
155 errx(1, "-d: permission denied"); 154 errx(1, "-d: permission denied");
156#endif 155#endif
157 if (uflag) 156 if (uflag)
158 showquotas(QUOTA_IDTYPE_USER, "user", 0, ""); 157 showquotas(QUOTA_IDTYPE_USER, "user", 0, "");
159 if (gflag) 158 if (gflag)
160 showquotas(QUOTA_IDTYPE_GROUP, "group", 0, ""); 159 showquotas(QUOTA_IDTYPE_GROUP, "group", 0, "");
161 return 0; 160 return 0;
162 } 161 }
163 if (argc == 0) { 162 if (argc == 0) {
164 if (uflag) 163 if (uflag)
165 showuid(myuid); 164 showuid(myuid);
166 if (gflag) { 165 if (gflag) {
167 if (dflag) 166 if (dflag)
168 showgid(0); 167 showgid(0);
169 else { 168 else {
170 mygid = getgid(); 169 mygid = getgid();
171 ngroups = getgroups(NGROUPS, gidset); 170 ngroups = getgroups(NGROUPS, gidset);
172 if (ngroups < 0) 171 if (ngroups < 0)
173 err(1, "getgroups"); 172 err(1, "getgroups");
174 showgid(mygid); 173 showgid(mygid);
175 for (i = 0; i < ngroups; i++) 174 for (i = 0; i < ngroups; i++)
176 if (gidset[i] != mygid) 175 if (gidset[i] != mygid)
177 showgid(gidset[i]); 176 showgid(gidset[i]);
178 } 177 }
179 } 178 }
180 return 0; 179 return 0;
181 } 180 }
182 if (uflag && gflag) 181 if (uflag && gflag)
183 usage(); 182 usage();
184 if (uflag) { 183 if (uflag) {
185 for (; argc > 0; argc--, argv++) { 184 for (; argc > 0; argc--, argv++) {
186 if (alldigits(*argv)) 185 if (alldigits(*argv))
187 showuid((uid_t)atoi(*argv)); 186 showuid((uid_t)atoi(*argv));
188 else 187 else
189 showusrname(*argv); 188 showusrname(*argv);
190 } 189 }
191 return 0; 190 return 0;
192 } 191 }
193 if (gflag) { 192 if (gflag) {
194 for (; argc > 0; argc--, argv++) { 193 for (; argc > 0; argc--, argv++) {
195 if (alldigits(*argv)) 194 if (alldigits(*argv))
196 showgid((gid_t)atoi(*argv)); 195 showgid((gid_t)atoi(*argv));
197 else 196 else
198 showgrpname(*argv); 197 showgrpname(*argv);
199 } 198 }
200 return 0; 199 return 0;
201 } 200 }
202 /* NOTREACHED */ 201 /* NOTREACHED */
203 return 0; 202 return 0;
204} 203}
205 204
206static void 205static void
207usage(void) 206usage(void)
208{ 207{
209 const char *p = getprogname(); 208 const char *p = getprogname();
210 fprintf(stderr, "Usage: %s [-Dhguqv]\n" 209 fprintf(stderr, "Usage: %s [-Dhguqv]\n"
211 "\t%s [-Dhqv] -u username ...\n" 210 "\t%s [-Dhqv] -u username ...\n"
212 "\t%s [-Dhqv] -g groupname ...\n" 211 "\t%s [-Dhqv] -g groupname ...\n"
213 "\t%s -d [-Dhguqv]\n", p, p, p, p); 212 "\t%s -d [-Dhguqv]\n", p, p, p, p);
214 exit(1); 213 exit(1);
215} 214}
216 215
217/* 216/*
218 * Print out quotas for a specified user identifier. 217 * Print out quotas for a specified user identifier.
219 */ 218 */
220static void 219static void
221showuid(uid_t uid) 220showuid(uid_t uid)
222{ 221{
223 struct passwd *pwd = getpwuid(uid); 222 struct passwd *pwd = getpwuid(uid);
224 const char *name; 223 const char *name;
225 224
226 if (pwd == NULL) 225 if (pwd == NULL)
227 name = "(no account)"; 226 name = "(no account)";
228 else 227 else
229 name = pwd->pw_name; 228 name = pwd->pw_name;
230 if (uid != myuid && myuid != 0) { 229 if (uid != myuid && myuid != 0) {
231 warnx("%s (uid %d): permission denied", name, uid); 230 warnx("%s (uid %d): permission denied", name, uid);
232 return; 231 return;
233 } 232 }
234 showquotas(QUOTA_IDTYPE_USER, "user", uid, name); 233 showquotas(QUOTA_IDTYPE_USER, "user", uid, name);
235} 234}
236 235
237/* 236/*
238 * Print out quotas for a specified user name. 237 * Print out quotas for a specified user name.
239 */ 238 */
240static void 239static void
241showusrname(const char *name) 240showusrname(const char *name)
242{ 241{
243 struct passwd *pwd = getpwnam(name); 242 struct passwd *pwd = getpwnam(name);
244 243
245 if (pwd == NULL) { 244 if (pwd == NULL) {
246 warnx("%s: unknown user", name); 245 warnx("%s: unknown user", name);
247 return; 246 return;
248 } 247 }
249 if (pwd->pw_uid != myuid && myuid != 0) { 248 if (pwd->pw_uid != myuid && myuid != 0) {
250 warnx("%s (uid %d): permission denied", name, pwd->pw_uid); 249 warnx("%s (uid %d): permission denied", name, pwd->pw_uid);
251 return; 250 return;
252 } 251 }
253 showquotas(QUOTA_IDTYPE_USER, "user", pwd->pw_uid, name); 252 showquotas(QUOTA_IDTYPE_USER, "user", pwd->pw_uid, name);
254} 253}
255 254
256/* 255/*
257 * Print out quotas for a specified group identifier. 256 * Print out quotas for a specified group identifier.
258 */ 257 */
259static void 258static void
260showgid(gid_t gid) 259showgid(gid_t gid)
261{ 260{
262 struct group *grp = getgrgid(gid); 261 struct group *grp = getgrgid(gid);
263 int ngroups; 262 int ngroups;
264 gid_t mygid, gidset[NGROUPS]; 263 gid_t mygid, gidset[NGROUPS];
265 int i; 264 int i;
266 const char *name; 265 const char *name;
267 266
268 if (grp == NULL) 267 if (grp == NULL)
269 name = "(no entry)"; 268 name = "(no entry)";
270 else 269 else
271 name = grp->gr_name; 270 name = grp->gr_name;
272 mygid = getgid(); 271 mygid = getgid();
273 ngroups = getgroups(NGROUPS, gidset); 272 ngroups = getgroups(NGROUPS, gidset);
274 if (ngroups < 0) { 273 if (ngroups < 0) {
275 warn("getgroups"); 274 warn("getgroups");
276 return; 275 return;
277 } 276 }
278 if (gid != mygid) { 277 if (gid != mygid) {
279 for (i = 0; i < ngroups; i++) 278 for (i = 0; i < ngroups; i++)
280 if (gid == gidset[i]) 279 if (gid == gidset[i])
281 break; 280 break;
282 if (i >= ngroups && myuid != 0) { 281 if (i >= ngroups && myuid != 0) {
283 warnx("%s (gid %d): permission denied", name, gid); 282 warnx("%s (gid %d): permission denied", name, gid);
284 return; 283 return;
285 } 284 }
286 } 285 }
287 showquotas(QUOTA_IDTYPE_GROUP, "group", gid, name); 286 showquotas(QUOTA_IDTYPE_GROUP, "group", gid, name);
288} 287}
289 288
290/* 289/*
291 * Print out quotas for a specified group name. 290 * Print out quotas for a specified group name.
292 */ 291 */
293static void 292static void
294showgrpname(const char *name) 293showgrpname(const char *name)
295{ 294{
296 struct group *grp = getgrnam(name); 295 struct group *grp = getgrnam(name);
297 int ngroups; 296 int ngroups;
298 gid_t mygid, gidset[NGROUPS]; 297 gid_t mygid, gidset[NGROUPS];
299 int i; 298 int i;
300 299
301 if (grp == NULL) { 300 if (grp == NULL) {
302 warnx("%s: unknown group", name); 301 warnx("%s: unknown group", name);
303 return; 302 return;
304 } 303 }
305 mygid = getgid(); 304 mygid = getgid();
306 ngroups = getgroups(NGROUPS, gidset); 305 ngroups = getgroups(NGROUPS, gidset);
307 if (ngroups < 0) { 306 if (ngroups < 0) {
308 warn("getgroups"); 307 warn("getgroups");
309 return; 308 return;
310 } 309 }
311 if (grp->gr_gid != mygid) { 310 if (grp->gr_gid != mygid) {
312 for (i = 0; i < ngroups; i++) 311 for (i = 0; i < ngroups; i++)
313 if (grp->gr_gid == gidset[i]) 312 if (grp->gr_gid == gidset[i])
314 break; 313 break;
315 if (i >= ngroups && myuid != 0) { 314 if (i >= ngroups && myuid != 0) {
316 warnx("%s (gid %d): permission denied", 315 warnx("%s (gid %d): permission denied",
317 name, grp->gr_gid); 316 name, grp->gr_gid);
318 return; 317 return;
319 } 318 }
320 } 319 }
321 showquotas(QUOTA_IDTYPE_GROUP, "group", grp->gr_gid, name); 320 showquotas(QUOTA_IDTYPE_GROUP, "group", grp->gr_gid, name);
322} 321}
323 322
324static void 323static void
325showquotas(int idtype, const char *idtypename, id_t id, const char *idname) 324showquotas(int idtype, const char *idtypename, id_t id, const char *idname)
326{ 325{
327 struct quotause *qup; 326 struct quotause *qup;
328 struct quotause *quplist; 327 struct quotause *quplist;
329 328
330 needheading = 1; 329 needheading = 1;
331 330
332 quplist = getprivs(id, idtype); 331 quplist = getprivs(id, idtype);
333 for (qup = quplist; qup; qup = qup->next) { 332 for (qup = quplist; qup; qup = qup->next) {
334 showonequota(idtype, idtypename, id, idname, qup); 333 showonequota(idtype, idtypename, id, idname, qup);
335 } 334 }
336 if (!qflag) { 335 if (!qflag) {
337 /* In case nothing printed, issue a header saying "none" */ 336 /* In case nothing printed, issue a header saying "none" */
338 heading(idtype, idtypename, id, idname, "none"); 337 heading(idtype, idtypename, id, idname, "none");
339 } 338 }
340} 339}
341 340
342static void 341static void
343showonequota(int idtype, const char *idtypename, id_t id, const char *idname, 342showonequota(int idtype, const char *idtypename, id_t id, const char *idname,
344 struct quotause *qup) 343 struct quotause *qup)
345{ 344{
346 static time_t now; 345 static time_t now;
347 struct quotaval *qvs; 346 struct quotaval *qvs;
348 unsigned numqvs, i; 347 unsigned numqvs, i;
349 const char *msg; 348 const char *msg;
350 349
351 qvs = qup->qvs; 350 qvs = qup->qvs;
352 numqvs = qup->numqvs; 351 numqvs = qup->numqvs;
353 352
354 if (now == 0) { 353 if (now == 0) {
355 time(&now); 354 time(&now);
356 } 355 }
357 356
358 if (!vflag && unlimited(qvs, numqvs)) { 357 if (!vflag && unlimited(qvs, numqvs)) {
359 return; 358 return;
360 } 359 }
361 360
362 if (qflag) { 361 if (qflag) {
363 for (i=0; i<numqvs; i++) { 362 for (i=0; i<numqvs; i++) {
364 msg = getovermsg(&qvs[i], 363 msg = getovermsg(&qvs[i],
365 quota_idtype_getname(qup->qh, i), 364 quota_idtype_getname(qup->qh, i),
366 now); 365 now);
367 if (msg != NULL) { 366 if (msg != NULL) {
368 heading(idtype, idtypename, id, idname, ""); 367 heading(idtype, idtypename, id, idname, "");
369 printf("\t%s %s\n", msg, qup->fsname); 368 printf("\t%s %s\n", msg, qup->fsname);
370 } 369 }
371 } 370 }
372 return; 371 return;
373 } 372 }
374 373
375 /* 374 /*
376 * XXX this behavior appears to be demanded by the ATF tests, 375 * XXX this behavior appears to be demanded by the ATF tests,
377 * although it seems to be at variance with the preexisting 376 * although it seems to be at variance with the preexisting
378 * logic in quota.c. 377 * logic in quota.c.
379 */ 378 */
380 if (unlimited(qvs, numqvs) && !anyusage(qvs, numqvs)) { 379 if (unlimited(qvs, numqvs) && !anyusage(qvs, numqvs)) {
381 return; 380 return;
382 } 381 }
383 382
384 /* 383 /*
385 * XXX: anyover can in fact be true if anyusage is not true, 384 * XXX: anyover can in fact be true if anyusage is not true,
386 * if there's a quota of zero set on some volume. This is 385 * if there's a quota of zero set on some volume. This is
387 * because the check we do checks if adding one more thing 386 * because the check we do checks if adding one more thing
388 * will go over. That is reasonable, I suppose, but arguably 387 * will go over. That is reasonable, I suppose, but arguably
389 * the resulting behavior with usage 0 is a bug. (Also, what 388 * the resulting behavior with usage 0 is a bug. (Also, what
390 * reason do we have to believe that the reported grace expire 389 * reason do we have to believe that the reported grace expire
391 * time is valid if we aren't in fact over yet?) 390 * time is valid if we aren't in fact over yet?)
392 */ 391 */
393 392
394 if (vflag || dflag || anyover(qvs, numqvs, now) ||  393 if (vflag || dflag || anyover(qvs, numqvs, now) ||
395 anyusage(qvs, numqvs)) { 394 anyusage(qvs, numqvs)) {
396 heading(idtype, idtypename, id, idname, ""); 395 heading(idtype, idtypename, id, idname, "");
397 if (strlen(qup->fsname) > 4) { 396 if (strlen(qup->fsname) > 4) {
398 printf("%s\n", qup->fsname); 397 printf("%s\n", qup->fsname);
399 printf("%12s", ""); 398 printf("%12s", "");
400 } else { 399 } else {
401 printf("%12s", qup->fsname); 400 printf("%12s", qup->fsname);
402 } 401 }
403 402
404 for (i=0; i<numqvs; i++) { 403 for (i=0; i<numqvs; i++) {
405 printqv(&qvs[i], 404 printqv(&qvs[i],
406 quota_objtype_isbytes(qup->qh, i), now); 405 quota_objtype_isbytes(qup->qh, i), now);
407 } 406 }
408 printf("\n"); 407 printf("\n");
409 } 408 }
410} 409}
411 410
412static void 411static void
413heading(int idtype, const char *idtypename, id_t id, const char *idname, 412heading(int idtype, const char *idtypename, id_t id, const char *idname,
414 const char *tag) 413 const char *tag)
415{ 414{
416 if (needheading == 0) 415 if (needheading == 0)
417 return; 416 return;
418 needheading = 0; 417 needheading = 0;
419 418
420 if (dflag) 419 if (dflag)
421 printf("Default %s disk quotas: %s\n", idtypename, tag); 420 printf("Default %s disk quotas: %s\n", idtypename, tag);
422 else 421 else
423 printf("Disk quotas for %s %s (%cid %u): %s\n", 422 printf("Disk quotas for %s %s (%cid %u): %s\n",
424 idtypename, idname, idtypename[0], id, tag); 423 idtypename, idname, idtypename[0], id, tag);
425 424
426 if (!qflag && tag[0] == '\0') { 425 if (!qflag && tag[0] == '\0') {
427 printf("%12s%9s %8s%9s%8s%8s %7s%8s%8s\n" 426 printf("%12s%9s %8s%9s%8s%8s %7s%8s%8s\n"
428 , "Filesystem" 427 , "Filesystem"
429 , "blocks" 428 , "blocks"
430 , "quota" 429 , "quota"
431 , "limit" 430 , "limit"
432 , "grace" 431 , "grace"
433 , "files" 432 , "files"
434 , "quota" 433 , "quota"
435 , "limit" 434 , "limit"
436 , "grace" 435 , "grace"
437 ); 436 );
438 } 437 }
439} 438}
440 439
441static void 440static void
442printqv(struct quotaval *qv, int isbytes, time_t now) 441printqv(struct quotaval *qv, int isbytes, time_t now)
443{ 442{
444 char buf[20]; 443 char buf[20];
445 const char *str; 444 const char *str;
446 int intprtflags, over, width; 445 int intprtflags, over, width;
447 446
448 /* 447 /*
449 * The assorted finagling of width is to match the previous 448 * The assorted finagling of width is to match the previous
450 * open-coded formatting for exactly two quota object types, 449 * open-coded formatting for exactly two quota object types,
451 * which was chosen to make the default report fit in 80 450 * which was chosen to make the default report fit in 80
452 * columns. 451 * columns.
453 */ 452 */
454 453
455 width = isbytes ? 9 : 8; 454 width = isbytes ? 9 : 8;
456 intprtflags = isbytes ? HN_B : 0; 455 intprtflags = isbytes ? HN_B : 0;
457 over = isover(qv, now); 456 over = isover(qv, now);
458 457
459 str = intprt(buf, width, qv->qv_usage, intprtflags, hflag); 458 str = intprt(buf, width, qv->qv_usage, intprtflags, hflag);
460 printf("%*s", width, str); 459 printf("%*s", width, str);
461 460
462 printf("%c", over ? '*' : ' '); 461 printf("%c", over ? '*' : ' ');
463 462
464 str = intprt(buf, width, qv->qv_softlimit, intprtflags, hflag); 463 str = intprt(buf, width, qv->qv_softlimit, intprtflags, hflag);
465 printf("%*s", width-1, str); 464 printf("%*s", width-1, str);
466 465
467 str = intprt(buf, width, qv->qv_hardlimit, intprtflags, hflag); 466 str = intprt(buf, width, qv->qv_hardlimit, intprtflags, hflag);
468 printf("%*s", width, str); 467 printf("%*s", width, str);
469 468
470 if (over) { 469 if (over) {
471 str = timeprt(buf, 9, now, qv->qv_expiretime); 470 str = timeprt(buf, 9, now, qv->qv_expiretime);
472 } else if (vflag && qv->qv_grace != QUOTA_NOTIME) { 471 } else if (vflag && qv->qv_grace != QUOTA_NOTIME) {
473 str = timeprt(buf, 9, 0, qv->qv_grace); 472 str = timeprt(buf, 9, 0, qv->qv_grace);
474 } else { 473 } else {
475 str = ""; 474 str = "";
476 } 475 }
477 printf("%8s", str); 476 printf("%8s", str);
478} 477}
479 478
480/* 479/*
481 * Collect the requested quota information. 480 * Collect the requested quota information.
482 */ 481 */
483static struct quotause * 482static struct quotause *
484getprivs(id_t id, int idtype) 483getprivs(id_t id, int idtype)
485{ 484{
486 struct quotause *qup, *quptail; 485 struct quotause *qup, *quptail;
487 struct quotause *quphead; 486 struct quotause *quphead;
488 struct statvfs *fst; 487 struct statvfs *fst;
489 struct quotakey qk; 488 struct quotakey qk;
490 int nfst, i; 489 int nfst, i;
491 unsigned j; 490 unsigned j;
492 491
493 qup = quphead = quptail = NULL; 492 qup = quphead = quptail = NULL;
494 493
495 nfst = getmntinfo(&fst, MNT_WAIT); 494 nfst = getmntinfo(&fst, MNT_WAIT);
496 if (nfst == 0) 495 if (nfst == 0)
497 errx(2, "no filesystems mounted!"); 496 errx(2, "no filesystems mounted!");
498 for (i = 0; i < nfst; i++) { 497 for (i = 0; i < nfst; i++) {
499 if (qup == NULL) { 498 if (qup == NULL) {
500 if ((qup = malloc(sizeof *qup)) == NULL) 499 if ((qup = malloc(sizeof *qup)) == NULL)
501 err(1, "Out of memory"); 500 err(1, "Out of memory");
502 } 501 }
503 qup->qh = quota_open(fst[i].f_mntonname); 502 qup->qh = quota_open(fst[i].f_mntonname);
504 if (qup->qh == NULL) { 503 if (qup->qh == NULL) {
505 if (errno == EOPNOTSUPP || errno == ENXIO) { 504 if (errno == EOPNOTSUPP || errno == ENXIO) {
506 continue; 505 continue;
507 } 506 }
508 err(1, "%s: quota_open", fst[i].f_mntonname); 507 err(1, "%s: quota_open", fst[i].f_mntonname);
509 } 508 }
510#if 0 509#if 0
511 if (strncmp(fst[i].f_fstypename, "nfs",  510 if (strncmp(fst[i].f_fstypename, "nfs",
512 sizeof(fst[i].f_fstypename)) == 0) { 511 sizeof(fst[i].f_fstypename)) == 0) {
513 version = 0; 512 version = 0;
514 qup->numqvs = QUOTA_NLIMITS; 513 qup->numqvs = QUOTA_NLIMITS;
515 qup->qvs = malloc(qup->numqvs * sizeof(qup->qvs[0])); 514 qup->qvs = malloc(qup->numqvs * sizeof(qup->qvs[0]));
516 if (qup->qvs == NULL) { 515 if (qup->qvs == NULL) {
517 err(1, "Out of memory"); 516 err(1, "Out of memory");
518 } 517 }
519 if (getnfsquota(fst[i].f_mntfromname, 518 if (getnfsquota(fst[i].f_mntfromname,
520 qup->qvs, id, ufs_quota_class_names[idtype]) != 1) 519 qup->qvs, id, ufs_quota_class_names[idtype]) != 1)
521 continue; 520 continue;
522 } else if ((fst[i].f_flag & ST_QUOTA) != 0) { 521 } else if ((fst[i].f_flag & ST_QUOTA) != 0) {
523 qup->numqvs = QUOTA_NLIMITS; 522 qup->numqvs = QUOTA_NLIMITS;
524 qup->qvs = malloc(qup->numqvs * sizeof(qup->qvs[0])); 523 qup->qvs = malloc(qup->numqvs * sizeof(qup->qvs[0]));
525 if (qup->qvs == NULL) { 524 if (qup->qvs == NULL) {
526 err(1, "Out of memory"); 525 err(1, "Out of memory");
527 } 526 }
528 if (getvfsquota(fst[i].f_mntonname, qup->qvs, &version, 527 if (getvfsquota(fst[i].f_mntonname, qup->qvs, &version,
529 id, idtype, dflag, Dflag) != 1) 528 id, idtype, dflag, Dflag) != 1)
530 continue; 529 continue;
531 } else 530 } else
532 continue; 531 continue;
533#else 532#else
534 qup->numqvs = quota_getnumidtypes(qup->qh); 533 qup->numqvs = quota_getnumidtypes(qup->qh);
535 qup->qvs = malloc(qup->numqvs * sizeof(qup->qvs[0])); 534 qup->qvs = malloc(qup->numqvs * sizeof(qup->qvs[0]));
536 if (qup->qvs == NULL) { 535 if (qup->qvs == NULL) {
537 err(1, "Out of memory"); 536 err(1, "Out of memory");
538 } 537 }
539 qk.qk_idtype = idtype; 538 qk.qk_idtype = idtype;
540 if (dflag) { 539 if (dflag) {
541 qk.qk_id = QUOTA_DEFAULTID; 540 qk.qk_id = QUOTA_DEFAULTID;
542 } else { 541 } else {
543 qk.qk_id = id; 542 qk.qk_id = id;
544 } 543 }
545 for (j=0; j<qup->numqvs; j++) { 544 for (j=0; j<qup->numqvs; j++) {
546 qk.qk_objtype = j; 545 qk.qk_objtype = j;
547 if (quota_get(qup->qh, &qk, &qup->qvs[j]) < 0) { 546 if (quota_get(qup->qh, &qk, &qup->qvs[j]) < 0) {
548 if (errno != ENOENT && errno != ENODEV) { 547 if (errno != ENOENT && errno != ENODEV) {
549 warn("%s: quota_get (objtype %u)", 548 warn("%s: quota_get (objtype %u)",
550 fst[i].f_mntonname, j); 549 fst[i].f_mntonname, j);
551 } 550 }
552 quotaval_clear(&qup->qvs[j]); 551 quotaval_clear(&qup->qvs[j]);
553 } 552 }
554 } 553 }
555#endif 554#endif
556 (void)strlcpy(qup->fsname, fst[i].f_mntonname, 555 (void)strlcpy(qup->fsname, fst[i].f_mntonname,
557 sizeof(qup->fsname)); 556 sizeof(qup->fsname));
558 if (quphead == NULL) 557 if (quphead == NULL)
559 quphead = qup; 558 quphead = qup;
560 else 559 else
561 quptail->next = qup; 560 quptail->next = qup;
562 quptail = qup; 561 quptail = qup;
563 quptail->next = 0; 562 quptail->next = 0;
564 qup = NULL; 563 qup = NULL;
565 } 564 }
566 free(qup); 565 free(qup);
567 return quphead; 566 return quphead;
568} 567}
569 568
570static int 569static int
571unlimited(struct quotaval *qvs, unsigned numqvs) 570unlimited(struct quotaval *qvs, unsigned numqvs)
572{ 571{
573 unsigned i; 572 unsigned i;
574 573
575 for (i=0; i<numqvs; i++) { 574 for (i=0; i<numqvs; i++) {
576 if (qvs[i].qv_softlimit != QUOTA_NOLIMIT || 575 if (qvs[i].qv_softlimit != QUOTA_NOLIMIT ||
577 qvs[i].qv_hardlimit != QUOTA_NOLIMIT) { 576 qvs[i].qv_hardlimit != QUOTA_NOLIMIT) {
578 return 0; 577 return 0;
579 } 578 }
580 } 579 }
581 return 1; 580 return 1;
582} 581}
583 582
584static int 583static int
585anyusage(struct quotaval *qvs, unsigned numqvs) 584anyusage(struct quotaval *qvs, unsigned numqvs)
586{ 585{
587 unsigned i; 586 unsigned i;
588 587
589 for (i=0; i<numqvs; i++) { 588 for (i=0; i<numqvs; i++) {
590 if (qvs[i].qv_usage > 0) { 589 if (qvs[i].qv_usage > 0) {
591 return 1; 590 return 1;
592 } 591 }
593 } 592 }
594 return 0; 593 return 0;
595} 594}
596 595
597static int 596static int
598anyover(struct quotaval *qvs, unsigned numqvs, time_t now) 597anyover(struct quotaval *qvs, unsigned numqvs, time_t now)
599{ 598{
600 unsigned i; 599 unsigned i;
601 600
602 for (i=0; i<numqvs; i++) { 601 for (i=0; i<numqvs; i++) {
603 if (isover(&qvs[i], now)) { 602 if (isover(&qvs[i], now)) {
604 return 1; 603 return 1;
605 } 604 }
606 } 605 }
607 return 0; 606 return 0;
608} 607}
609 608
610static int 609static int
611isover(struct quotaval *qv, time_t now) 610isover(struct quotaval *qv, time_t now)
612{ 611{
613 return (qv->qv_usage >= qv->qv_hardlimit || 612 return (qv->qv_usage >= qv->qv_hardlimit ||
614 qv->qv_usage >= qv->qv_softlimit); 613 qv->qv_usage >= qv->qv_softlimit);
615} 614}
616 615
617static const char * 616static const char *
618getovermsg(struct quotaval *qv, const char *what, time_t now) 617getovermsg(struct quotaval *qv, const char *what, time_t now)
619{ 618{
620 static char buf[64]; 619 static char buf[64];
621 620
622 if (qv->qv_usage >= qv->qv_hardlimit) { 621 if (qv->qv_usage >= qv->qv_hardlimit) {
623 snprintf(buf, sizeof(buf), "%c%s limit reached on", 622 snprintf(buf, sizeof(buf), "%c%s limit reached on",
624 toupper((unsigned char)what[0]), what+1); 623 toupper((unsigned char)what[0]), what+1);
625 return buf; 624 return buf;
626 } 625 }
627 626
628 if (qv->qv_usage < qv->qv_softlimit) { 627 if (qv->qv_usage < qv->qv_softlimit) {
629 /* Ok */ 628 /* Ok */
630 return NULL; 629 return NULL;
631 } 630 }
632 631
633 if (now > qv->qv_expiretime) { 632 if (now > qv->qv_expiretime) {
634 snprintf(buf, sizeof(buf), "Over %s quota on", what); 633 snprintf(buf, sizeof(buf), "Over %s quota on", what);
635 return buf; 634 return buf;
636 } 635 }
637 636
638 snprintf(buf, sizeof(buf), "In %s grace period on", what); 637 snprintf(buf, sizeof(buf), "In %s grace period on", what);
639 return buf; 638 return buf;
640} 639}

cvs diff -r1.41 -r1.42 src/usr.sbin/repquota/repquota.c (switch to unified diff)

--- src/usr.sbin/repquota/repquota.c 2012/02/01 17:48:10 1.41
+++ src/usr.sbin/repquota/repquota.c 2012/02/05 14:14:44 1.42
@@ -1,574 +1,573 @@ @@ -1,574 +1,573 @@
1/* $NetBSD: repquota.c,v 1.41 2012/02/01 17:48:10 dholland Exp $ */ 1/* $NetBSD: repquota.c,v 1.42 2012/02/05 14:14:44 dholland Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1980, 1990, 1993 4 * Copyright (c) 1980, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Robert Elz at The University of Melbourne. 8 * Robert Elz at The University of Melbourne.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37__COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\ 37__COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\
38 The Regents of the University of California. All rights reserved."); 38 The Regents of the University of California. All rights reserved.");
39#endif /* not lint */ 39#endif /* not lint */
40 40
41#ifndef lint 41#ifndef lint
42#if 0 42#if 0
43static char sccsid[] = "@(#)repquota.c 8.2 (Berkeley) 11/22/94"; 43static char sccsid[] = "@(#)repquota.c 8.2 (Berkeley) 11/22/94";
44#else 44#else
45__RCSID("$NetBSD: repquota.c,v 1.41 2012/02/01 17:48:10 dholland Exp $"); 45__RCSID("$NetBSD: repquota.c,v 1.42 2012/02/05 14:14:44 dholland Exp $");
46#endif 46#endif
47#endif /* not lint */ 47#endif /* not lint */
48 48
49/* 49/*
50 * Quota report 50 * Quota report
51 */ 51 */
52#include <sys/param.h> 52#include <sys/param.h>
53#include <sys/stat.h> 53#include <sys/stat.h>
54#include <sys/types.h> 54#include <sys/types.h>
55#include <sys/statvfs.h> 55#include <sys/statvfs.h>
56 56
57#include <errno.h> 57#include <errno.h>
58#include <err.h> 58#include <err.h>
59#include <fstab.h> 59#include <fstab.h>
60#include <grp.h> 60#include <grp.h>
61#include <pwd.h> 61#include <pwd.h>
62#include <stdio.h> 62#include <stdio.h>
63#include <stdlib.h> 63#include <stdlib.h>
64#include <string.h> 64#include <string.h>
65#include <unistd.h> 65#include <unistd.h>
66 66
67#include <quota/quota.h> 
68#include <quota.h> 67#include <quota.h>
69 68
70#include "printquota.h" 69#include "printquota.h"
71 70
72/* 71/*
73 * XXX. Ideally we shouldn't compile either of these in, but it's a 72 * XXX. Ideally we shouldn't compile either of these in, but it's a
74 * nontrivial rework to avoid it and it'll work ok for now. 73 * nontrivial rework to avoid it and it'll work ok for now.
75 */ 74 */
76#define REPQUOTA_NUMIDTYPES 2 75#define REPQUOTA_NUMIDTYPES 2
77#define REPQUOTA_NUMOBJTYPES 2 76#define REPQUOTA_NUMOBJTYPES 2
78 77
79struct fileusage { 78struct fileusage {
80 struct fileusage *fu_next; 79 struct fileusage *fu_next;
81 struct quotaval fu_qv[REPQUOTA_NUMOBJTYPES]; 80 struct quotaval fu_qv[REPQUOTA_NUMOBJTYPES];
82 uint32_t fu_id; 81 uint32_t fu_id;
83 char fu_name[1]; 82 char fu_name[1];
84 /* actually bigger */ 83 /* actually bigger */
85}; 84};
86 85
87#define FUHASH 1024 /* must be power of two */ 86#define FUHASH 1024 /* must be power of two */
88static struct fileusage *fuhead[REPQUOTA_NUMIDTYPES][FUHASH]; 87static struct fileusage *fuhead[REPQUOTA_NUMIDTYPES][FUHASH];
89 88
90/* highest addid()'ed identifier per idtype */ 89/* highest addid()'ed identifier per idtype */
91static uint32_t highid[REPQUOTA_NUMIDTYPES]; 90static uint32_t highid[REPQUOTA_NUMIDTYPES];
92 91
93int valid[REPQUOTA_NUMIDTYPES]; 92int valid[REPQUOTA_NUMIDTYPES];
94 93
95static struct quotaval defaultqv[REPQUOTA_NUMIDTYPES][REPQUOTA_NUMOBJTYPES]; 94static struct quotaval defaultqv[REPQUOTA_NUMIDTYPES][REPQUOTA_NUMOBJTYPES];
96 95
97static int vflag = 0; /* verbose */ 96static int vflag = 0; /* verbose */
98static int aflag = 0; /* all file systems */ 97static int aflag = 0; /* all file systems */
99static int Dflag = 0; /* debug */ 98static int Dflag = 0; /* debug */
100static int hflag = 0; /* humanize */ 99static int hflag = 0; /* humanize */
101static int xflag = 0; /* export */ 100static int xflag = 0; /* export */
102 101
103/* 102/*
104 * XXX this should go away and be replaced with a call to 103 * XXX this should go away and be replaced with a call to
105 * quota_idtype_getname(), but that needs a quotahandle and requires 104 * quota_idtype_getname(), but that needs a quotahandle and requires
106 * the same nontrivial rework as getting rid of REPQUOTA_NUMIDTYPES. 105 * the same nontrivial rework as getting rid of REPQUOTA_NUMIDTYPES.
107 */ 106 */
108static const char *const repquota_idtype_names[REPQUOTA_NUMIDTYPES] = { 107static const char *const repquota_idtype_names[REPQUOTA_NUMIDTYPES] = {
109 "user", 108 "user",
110 "group", 109 "group",
111}; 110};
112 111
113static struct fileusage *addid(uint32_t, int, const char *); 112static struct fileusage *addid(uint32_t, int, const char *);
114static struct fileusage *lookup(uint32_t, int); 113static struct fileusage *lookup(uint32_t, int);
115static struct fileusage *qremove(uint32_t, int); 114static struct fileusage *qremove(uint32_t, int);
116static int repquota(struct quotahandle *, int); 115static int repquota(struct quotahandle *, int);
117static void usage(void) __attribute__((__noreturn__)); 116static void usage(void) __attribute__((__noreturn__));
118static void printquotas(int, struct quotahandle *); 117static void printquotas(int, struct quotahandle *);
119static void exportquotas(void); 118static void exportquotas(void);
120static int oneof(const char *, char *[], int cnt); 119static int oneof(const char *, char *[], int cnt);
121static int isover(struct quotaval *qv, time_t now); 120static int isover(struct quotaval *qv, time_t now);
122 121
123int 122int
124main(int argc, char **argv) 123main(int argc, char **argv)
125{ 124{
126 int gflag = 0, uflag = 0, errs = 0; 125 int gflag = 0, uflag = 0, errs = 0;
127 long i, argnum, done = 0; 126 long i, argnum, done = 0;
128 int ch; 127 int ch;
129 struct statvfs *fst; 128 struct statvfs *fst;
130 int nfst; 129 int nfst;
131 struct quotahandle *qh; 130 struct quotahandle *qh;
132 131
133 while ((ch = getopt(argc, argv, "Daguhvx")) != -1) { 132 while ((ch = getopt(argc, argv, "Daguhvx")) != -1) {
134 switch(ch) { 133 switch(ch) {
135 case 'a': 134 case 'a':
136 aflag++; 135 aflag++;
137 break; 136 break;
138 case 'g': 137 case 'g':
139 gflag++; 138 gflag++;
140 break; 139 break;
141 case 'u': 140 case 'u':
142 uflag++; 141 uflag++;
143 break; 142 break;
144 case 'h': 143 case 'h':
145 hflag++; 144 hflag++;
146 break; 145 break;
147 case 'v': 146 case 'v':
148 vflag++; 147 vflag++;
149 break; 148 break;
150 case 'D': 149 case 'D':
151 Dflag++; 150 Dflag++;
152 break; 151 break;
153 case 'x': 152 case 'x':
154 xflag++; 153 xflag++;
155 break; 154 break;
156 default: 155 default:
157 usage(); 156 usage();
158 } 157 }
159 } 158 }
160 argc -= optind; 159 argc -= optind;
161 argv += optind; 160 argv += optind;
162 if (xflag && (argc != 1 || aflag)) 161 if (xflag && (argc != 1 || aflag))
163 usage(); 162 usage();
164 if (argc == 0 && !aflag) 163 if (argc == 0 && !aflag)
165 usage(); 164 usage();
166 if (!gflag && !uflag) { 165 if (!gflag && !uflag) {
167 if (aflag) 166 if (aflag)
168 gflag++; 167 gflag++;
169 uflag++; 168 uflag++;
170 } 169 }
171 170
172 nfst = getmntinfo(&fst, MNT_WAIT); 171 nfst = getmntinfo(&fst, MNT_WAIT);
173 if (nfst == 0) 172 if (nfst == 0)
174 errx(1, "no filesystems mounted!"); 173 errx(1, "no filesystems mounted!");
175 for (i = 0; i < nfst; i++) { 174 for (i = 0; i < nfst; i++) {
176 if ((fst[i].f_flag & ST_QUOTA) == 0) 175 if ((fst[i].f_flag & ST_QUOTA) == 0)
177 continue; 176 continue;
178 /* check if we want this volume */ 177 /* check if we want this volume */
179 if (!aflag) { 178 if (!aflag) {
180 argnum = oneof(fst[i].f_mntonname, argv, argc); 179 argnum = oneof(fst[i].f_mntonname, argv, argc);
181 if (argnum < 0) { 180 if (argnum < 0) {
182 argnum = oneof(fst[i].f_mntfromname, 181 argnum = oneof(fst[i].f_mntfromname,
183 argv, argc); 182 argv, argc);
184 } 183 }
185 if (argnum < 0) { 184 if (argnum < 0) {
186 continue; 185 continue;
187 } 186 }
188 done |= 1U << argnum; 187 done |= 1U << argnum;
189 } 188 }
190 189
191 qh = quota_open(fst[i].f_mntonname); 190 qh = quota_open(fst[i].f_mntonname);
192 if (qh == NULL) { 191 if (qh == NULL) {
193 /* XXX: check this errno */ 192 /* XXX: check this errno */
194 if (errno == EOPNOTSUPP || errno == ENXIO) { 193 if (errno == EOPNOTSUPP || errno == ENXIO) {
195 continue; 194 continue;
196 } 195 }
197 warn("%s: quota_open", fst[i].f_mntonname); 196 warn("%s: quota_open", fst[i].f_mntonname);
198 continue; 197 continue;
199 } 198 }
200 199
201 if (gflag) 200 if (gflag)
202 errs += repquota(qh, QUOTA_IDTYPE_GROUP); 201 errs += repquota(qh, QUOTA_IDTYPE_GROUP);
203 if (uflag) 202 if (uflag)
204 errs += repquota(qh, QUOTA_IDTYPE_USER); 203 errs += repquota(qh, QUOTA_IDTYPE_USER);
205 204
206 quota_close(qh); 205 quota_close(qh);
207 } 206 }
208 if (xflag) 207 if (xflag)
209 exportquotas(); 208 exportquotas();
210 for (i = 0; i < argc; i++) 209 for (i = 0; i < argc; i++)
211 if ((done & (1U << i)) == 0) 210 if ((done & (1U << i)) == 0)
212 warnx("%s not mounted", argv[i]); 211 warnx("%s not mounted", argv[i]);
213 return errs; 212 return errs;
214} 213}
215 214
216static void 215static void
217usage(void) 216usage(void)
218{ 217{
219 const char *p = getprogname(); 218 const char *p = getprogname();
220 fprintf(stderr, "usage: %s [-D] [-v] [-g] [-u] -a\n" 219 fprintf(stderr, "usage: %s [-D] [-v] [-g] [-u] -a\n"
221 "\t%s [-D] [-v] [-g] [-u] filesys ...\n" 220 "\t%s [-D] [-v] [-g] [-u] filesys ...\n"
222 "\t%s -x [-D] [-g] [-u] filesys\n", p, p, p); 221 "\t%s -x [-D] [-g] [-u] filesys\n", p, p, p);
223 exit(1); 222 exit(1);
224} 223}
225 224
226static int 225static int
227repquota(struct quotahandle *qh, int idtype) 226repquota(struct quotahandle *qh, int idtype)
228{ 227{
229 struct quotacursor *qc; 228 struct quotacursor *qc;
230 struct quotakey qk; 229 struct quotakey qk;
231 struct quotaval qv; 230 struct quotaval qv;
232 struct quotaval *qvp; 231 struct quotaval *qvp;
233 struct fileusage *fup; 232 struct fileusage *fup;
234 233
235 qc = quota_opencursor(qh); 234 qc = quota_opencursor(qh);
236 if (qc == NULL) { 235 if (qc == NULL) {
237 return 1; 236 return 1;
238 } 237 }
239 238
240 if (idtype == QUOTA_IDTYPE_USER) { 239 if (idtype == QUOTA_IDTYPE_USER) {
241 quotacursor_skipidtype(qc, QUOTA_IDTYPE_GROUP); 240 quotacursor_skipidtype(qc, QUOTA_IDTYPE_GROUP);
242 } 241 }
243 if (idtype == QUOTA_IDTYPE_GROUP) { 242 if (idtype == QUOTA_IDTYPE_GROUP) {
244 quotacursor_skipidtype(qc, QUOTA_IDTYPE_USER); 243 quotacursor_skipidtype(qc, QUOTA_IDTYPE_USER);
245 } 244 }
246 245
247 valid[idtype] = 0; 246 valid[idtype] = 0;
248 while (!quotacursor_atend(qc)) { 247 while (!quotacursor_atend(qc)) {
249 if (quotacursor_get(qc, &qk, &qv)) { 248 if (quotacursor_get(qc, &qk, &qv)) {
250 err(1, "%s: quotacursor_get", quota_getmountpoint(qh)); 249 err(1, "%s: quotacursor_get", quota_getmountpoint(qh));
251 } 250 }
252 if (qk.qk_idtype != idtype) { 251 if (qk.qk_idtype != idtype) {
253 continue; 252 continue;
254 } 253 }
255 254
256 valid[idtype] = 1; 255 valid[idtype] = 1;
257 if (qk.qk_id == QUOTA_DEFAULTID) { 256 if (qk.qk_id == QUOTA_DEFAULTID) {
258 qvp = defaultqv[idtype]; 257 qvp = defaultqv[idtype];
259 } else { 258 } else {
260 if ((fup = lookup(qk.qk_id, idtype)) == 0) 259 if ((fup = lookup(qk.qk_id, idtype)) == 0)
261 fup = addid(qk.qk_id, idtype, (char *)0); 260 fup = addid(qk.qk_id, idtype, (char *)0);
262 qvp = fup->fu_qv; 261 qvp = fup->fu_qv;
263 } 262 }
264 if (qk.qk_objtype == QUOTA_OBJTYPE_BLOCKS) { 263 if (qk.qk_objtype == QUOTA_OBJTYPE_BLOCKS) {
265 qvp[QUOTA_OBJTYPE_BLOCKS] = qv; 264 qvp[QUOTA_OBJTYPE_BLOCKS] = qv;
266 } else if (qk.qk_objtype == QUOTA_OBJTYPE_FILES) { 265 } else if (qk.qk_objtype == QUOTA_OBJTYPE_FILES) {
267 qvp[QUOTA_OBJTYPE_FILES] = qv; 266 qvp[QUOTA_OBJTYPE_FILES] = qv;
268 } 267 }
269 } 268 }
270 269
271 if (xflag == 0 && valid[idtype]) 270 if (xflag == 0 && valid[idtype])
272 printquotas(idtype, qh); 271 printquotas(idtype, qh);
273 272
274 return 0; 273 return 0;
275} 274}
276 275
277static void 276static void
278printquotas(int idtype, struct quotahandle *qh) 277printquotas(int idtype, struct quotahandle *qh)
279{ 278{
280 static int multiple = 0; 279 static int multiple = 0;
281 uint32_t id; 280 uint32_t id;
282 int i; 281 int i;
283 struct fileusage *fup; 282 struct fileusage *fup;
284 struct quotaval *q; 283 struct quotaval *q;
285 const char *timemsg[REPQUOTA_NUMOBJTYPES]; 284 const char *timemsg[REPQUOTA_NUMOBJTYPES];
286 char overchar[REPQUOTA_NUMOBJTYPES]; 285 char overchar[REPQUOTA_NUMOBJTYPES];
287 time_t now; 286 time_t now;
288 char b0[2][20], b1[20], b2[20], b3[20]; 287 char b0[2][20], b1[20], b2[20], b3[20];
289 int ok, objtype; 288 int ok, objtype;
290 int isbytes, width; 289 int isbytes, width;
291 290
292 switch (idtype) { 291 switch (idtype) {
293 case QUOTA_IDTYPE_GROUP: 292 case QUOTA_IDTYPE_GROUP:
294 { 293 {
295 struct group *gr; 294 struct group *gr;
296 setgrent(); 295 setgrent();
297 while ((gr = getgrent()) != 0) 296 while ((gr = getgrent()) != 0)
298 (void)addid(gr->gr_gid, idtype, gr->gr_name); 297 (void)addid(gr->gr_gid, idtype, gr->gr_name);
299 endgrent(); 298 endgrent();
300 break; 299 break;
301 } 300 }
302 case QUOTA_IDTYPE_USER: 301 case QUOTA_IDTYPE_USER:
303 { 302 {
304 struct passwd *pw; 303 struct passwd *pw;
305 setpwent(); 304 setpwent();
306 while ((pw = getpwent()) != 0) 305 while ((pw = getpwent()) != 0)
307 (void)addid(pw->pw_uid, idtype, pw->pw_name); 306 (void)addid(pw->pw_uid, idtype, pw->pw_name);
308 endpwent(); 307 endpwent();
309 break; 308 break;
310 } 309 }
311 default: 310 default:
312 errx(1, "Unknown quota ID type %d", idtype); 311 errx(1, "Unknown quota ID type %d", idtype);
313 } 312 }
314 313
315 time(&now); 314 time(&now);
316 315
317 if (multiple++) 316 if (multiple++)
318 printf("\n"); 317 printf("\n");
319 if (vflag) 318 if (vflag)
320 printf("*** Report for %s quotas on %s (%s: %s)\n", 319 printf("*** Report for %s quotas on %s (%s: %s)\n",
321 repquota_idtype_names[idtype], quota_getmountpoint(qh), 320 repquota_idtype_names[idtype], quota_getmountpoint(qh),
322 quota_getmountdevice(qh), quota_getimplname(qh)); 321 quota_getmountdevice(qh), quota_getimplname(qh));
323 printf(" Block limits " 322 printf(" Block limits "
324 "File limits\n"); 323 "File limits\n");
325 printf(idtype == QUOTA_IDTYPE_USER ? "User " : "Group"); 324 printf(idtype == QUOTA_IDTYPE_USER ? "User " : "Group");
326 printf(" used soft hard grace used" 325 printf(" used soft hard grace used"
327 " soft hard grace\n"); 326 " soft hard grace\n");
328 for (id = 0; id <= highid[idtype]; id++) { 327 for (id = 0; id <= highid[idtype]; id++) {
329 fup = qremove(id, idtype); 328 fup = qremove(id, idtype);
330 q = fup->fu_qv; 329 q = fup->fu_qv;
331 if (fup == 0) 330 if (fup == 0)
332 continue; 331 continue;
333 for (i = 0; i < REPQUOTA_NUMOBJTYPES; i++) { 332 for (i = 0; i < REPQUOTA_NUMOBJTYPES; i++) {
334 if (isover(&q[i], now)) { 333 if (isover(&q[i], now)) {
335 timemsg[i] = timeprt(b0[i], 8, now, 334 timemsg[i] = timeprt(b0[i], 8, now,
336 q[i].qv_expiretime); 335 q[i].qv_expiretime);
337 overchar[i] = '+'; 336 overchar[i] = '+';
338 } else { 337 } else {
339 if (vflag && q[i].qv_grace != QUOTA_NOTIME) { 338 if (vflag && q[i].qv_grace != QUOTA_NOTIME) {
340 timemsg[i] = timeprt(b0[i], 8, 0, 339 timemsg[i] = timeprt(b0[i], 8, 0,
341 q[i].qv_grace); 340 q[i].qv_grace);
342 } else { 341 } else {
343 timemsg[i] = ""; 342 timemsg[i] = "";
344 } 343 }
345 overchar[i] = '-'; 344 overchar[i] = '-';
346 } 345 }
347 } 346 }
348 347
349 ok = 1; 348 ok = 1;
350 for (objtype = 0; objtype < REPQUOTA_NUMOBJTYPES; objtype++) { 349 for (objtype = 0; objtype < REPQUOTA_NUMOBJTYPES; objtype++) {
351 if (q[objtype].qv_usage != 0 || 350 if (q[objtype].qv_usage != 0 ||
352 overchar[objtype] != '-') { 351 overchar[objtype] != '-') {
353 ok = 0; 352 ok = 0;
354 } 353 }
355 } 354 }
356 if (ok && vflag == 0) 355 if (ok && vflag == 0)
357 continue; 356 continue;
358 if (strlen(fup->fu_name) > 9) 357 if (strlen(fup->fu_name) > 9)
359 printf("%s ", fup->fu_name); 358 printf("%s ", fup->fu_name);
360 else 359 else
361 printf("%-10s", fup->fu_name); 360 printf("%-10s", fup->fu_name);
362 for (objtype = 0; objtype < REPQUOTA_NUMOBJTYPES; objtype++) { 361 for (objtype = 0; objtype < REPQUOTA_NUMOBJTYPES; objtype++) {
363 printf("%c", overchar[objtype]); 362 printf("%c", overchar[objtype]);
364 } 363 }
365 for (objtype = 0; objtype < REPQUOTA_NUMOBJTYPES; objtype++) { 364 for (objtype = 0; objtype < REPQUOTA_NUMOBJTYPES; objtype++) {
366 isbytes = quota_objtype_isbytes(qh, objtype); 365 isbytes = quota_objtype_isbytes(qh, objtype);
367 width = isbytes ? 9 : 8; 366 width = isbytes ? 9 : 8;
368 printf("%*s%*s%*s%7s", 367 printf("%*s%*s%*s%7s",
369 width, 368 width,
370 intprt(b1, width+1, q[objtype].qv_usage, 369 intprt(b1, width+1, q[objtype].qv_usage,
371 isbytes ? HN_B : 0, hflag), 370 isbytes ? HN_B : 0, hflag),
372 width, 371 width,
373 intprt(b2, width+1, q[objtype].qv_softlimit, 372 intprt(b2, width+1, q[objtype].qv_softlimit,
374 isbytes ? HN_B : 0, hflag), 373 isbytes ? HN_B : 0, hflag),
375 width, 374 width,
376 intprt(b3, width+1, q[objtype].qv_hardlimit, 375 intprt(b3, width+1, q[objtype].qv_hardlimit,
377 isbytes ? HN_B : 0, hflag), 376 isbytes ? HN_B : 0, hflag),
378 timemsg[objtype]); 377 timemsg[objtype]);
379 378
380 if (objtype + 1 < REPQUOTA_NUMOBJTYPES) { 379 if (objtype + 1 < REPQUOTA_NUMOBJTYPES) {
381 printf(" "); 380 printf(" ");
382 } else { 381 } else {
383 printf("\n"); 382 printf("\n");
384 } 383 }
385 } 384 }
386 free(fup); 385 free(fup);
387 } 386 }
388} 387}
389 388
390static void 389static void
391exportquotaval(const struct quotaval *qv) 390exportquotaval(const struct quotaval *qv)
392{ 391{
393 if (qv->qv_hardlimit == QUOTA_NOLIMIT) { 392 if (qv->qv_hardlimit == QUOTA_NOLIMIT) {
394 printf(" -"); 393 printf(" -");
395 } else { 394 } else {
396 printf(" %llu", (unsigned long long)qv->qv_hardlimit); 395 printf(" %llu", (unsigned long long)qv->qv_hardlimit);
397 } 396 }
398 397
399 if (qv->qv_softlimit == QUOTA_NOLIMIT) { 398 if (qv->qv_softlimit == QUOTA_NOLIMIT) {
400 printf(" -"); 399 printf(" -");
401 } else { 400 } else {
402 printf(" %llu", (unsigned long long)qv->qv_softlimit); 401 printf(" %llu", (unsigned long long)qv->qv_softlimit);
403 } 402 }
404 403
405 printf(" %llu", (unsigned long long)qv->qv_usage); 404 printf(" %llu", (unsigned long long)qv->qv_usage);
406 405
407 if (qv->qv_expiretime == QUOTA_NOTIME) { 406 if (qv->qv_expiretime == QUOTA_NOTIME) {
408 printf(" -"); 407 printf(" -");
409 } else { 408 } else {
410 printf(" %lld", (long long)qv->qv_expiretime); 409 printf(" %lld", (long long)qv->qv_expiretime);
411 } 410 }
412 411
413 if (qv->qv_grace == QUOTA_NOTIME) { 412 if (qv->qv_grace == QUOTA_NOTIME) {
414 printf(" -"); 413 printf(" -");
415 } else { 414 } else {
416 printf(" %lld", (long long)qv->qv_grace); 415 printf(" %lld", (long long)qv->qv_grace);
417 } 416 }
418} 417}
419 418
420static void 419static void
421exportquotas(void) 420exportquotas(void)
422{ 421{
423 int idtype; 422 int idtype;
424 id_t id; 423 id_t id;
425 struct fileusage *fup; 424 struct fileusage *fup;
426 425
427 /* header */ 426 /* header */
428 printf("@format netbsd-quota-dump v1\n"); 427 printf("@format netbsd-quota-dump v1\n");
429 printf("# idtype id objtype hard soft usage expire grace\n"); 428 printf("# idtype id objtype hard soft usage expire grace\n");
430 429
431 for (idtype = 0; idtype < REPQUOTA_NUMIDTYPES; idtype++) { 430 for (idtype = 0; idtype < REPQUOTA_NUMIDTYPES; idtype++) {
432 if (valid[idtype] == 0) 431 if (valid[idtype] == 0)
433 continue; 432 continue;
434 433
435 printf("%s default blocks ", repquota_idtype_names[idtype]); 434 printf("%s default blocks ", repquota_idtype_names[idtype]);
436 exportquotaval(&defaultqv[idtype][QUOTA_OBJTYPE_BLOCKS]); 435 exportquotaval(&defaultqv[idtype][QUOTA_OBJTYPE_BLOCKS]);
437 printf("\n"); 436 printf("\n");
438  437
439 printf("%s default files ", repquota_idtype_names[idtype]); 438 printf("%s default files ", repquota_idtype_names[idtype]);
440 exportquotaval(&defaultqv[idtype][QUOTA_OBJTYPE_FILES]); 439 exportquotaval(&defaultqv[idtype][QUOTA_OBJTYPE_FILES]);
441 printf("\n"); 440 printf("\n");
442 441
443 for (id = 0; id <= highid[idtype]; id++) { 442 for (id = 0; id <= highid[idtype]; id++) {
444 fup = qremove(id, idtype); 443 fup = qremove(id, idtype);
445 if (fup == 0) 444 if (fup == 0)
446 continue; 445 continue;
447 446
448 printf("%s %u blocks ", repquota_idtype_names[idtype], 447 printf("%s %u blocks ", repquota_idtype_names[idtype],
449 id); 448 id);
450 exportquotaval(&fup->fu_qv[QUOTA_OBJTYPE_BLOCKS]); 449 exportquotaval(&fup->fu_qv[QUOTA_OBJTYPE_BLOCKS]);
451 printf("\n"); 450 printf("\n");
452 451
453 printf("%s %u files ", repquota_idtype_names[idtype], 452 printf("%s %u files ", repquota_idtype_names[idtype],
454 id); 453 id);
455 exportquotaval(&fup->fu_qv[QUOTA_OBJTYPE_FILES]); 454 exportquotaval(&fup->fu_qv[QUOTA_OBJTYPE_FILES]);
456 printf("\n"); 455 printf("\n");
457 456
458 free(fup); 457 free(fup);
459 } 458 }
460 } 459 }
461 printf("@end\n"); 460 printf("@end\n");
462} 461}
463 462
464/* 463/*
465 * Routines to manage the file usage table. 464 * Routines to manage the file usage table.
466 * 465 *
467 * Lookup an id of a specific id type. 466 * Lookup an id of a specific id type.
468 */ 467 */
469struct fileusage * 468struct fileusage *
470lookup(uint32_t id, int idtype) 469lookup(uint32_t id, int idtype)
471{ 470{
472 struct fileusage *fup; 471 struct fileusage *fup;
473 472
474 for (fup = fuhead[idtype][id & (FUHASH-1)]; fup != 0; fup = fup->fu_next) 473 for (fup = fuhead[idtype][id & (FUHASH-1)]; fup != 0; fup = fup->fu_next)
475 if (fup->fu_id == id) 474 if (fup->fu_id == id)
476 return fup; 475 return fup;
477 return NULL; 476 return NULL;
478} 477}
479/* 478/*
480 * Lookup and remove an id of a specific id type. 479 * Lookup and remove an id of a specific id type.
481 */ 480 */
482static struct fileusage * 481static struct fileusage *
483qremove(uint32_t id, int idtype) 482qremove(uint32_t id, int idtype)
484{ 483{
485 struct fileusage *fup, **fupp; 484 struct fileusage *fup, **fupp;
486 485
487 for (fupp = &fuhead[idtype][id & (FUHASH-1)]; *fupp != 0;) { 486 for (fupp = &fuhead[idtype][id & (FUHASH-1)]; *fupp != 0;) {
488 fup = *fupp; 487 fup = *fupp;
489 if (fup->fu_id == id) { 488 if (fup->fu_id == id) {
490 *fupp = fup->fu_next; 489 *fupp = fup->fu_next;
491 return fup; 490 return fup;
492 } 491 }
493 fupp = &fup->fu_next; 492 fupp = &fup->fu_next;
494 } 493 }
495 return NULL; 494 return NULL;
496} 495}
497 496
498/* 497/*
499 * Add a new file usage id if it does not already exist. 498 * Add a new file usage id if it does not already exist.
500 */ 499 */
501static struct fileusage * 500static struct fileusage *
502addid(uint32_t id, int idtype, const char *name) 501addid(uint32_t id, int idtype, const char *name)
503{ 502{
504 struct fileusage *fup, **fhp; 503 struct fileusage *fup, **fhp;
505 struct group *gr = NULL; 504 struct group *gr = NULL;
506 struct passwd *pw = NULL; 505 struct passwd *pw = NULL;
507 size_t len; 506 size_t len;
508 507
509 if ((fup = lookup(id, idtype)) != NULL) { 508 if ((fup = lookup(id, idtype)) != NULL) {
510 return fup; 509 return fup;
511 } 510 }
512 if (name == NULL) { 511 if (name == NULL) {
513 switch(idtype) { 512 switch(idtype) {
514 case QUOTA_IDTYPE_GROUP: 513 case QUOTA_IDTYPE_GROUP:
515 gr = getgrgid(id); 514 gr = getgrgid(id);
516  515
517 if (gr != NULL) 516 if (gr != NULL)
518 name = gr->gr_name; 517 name = gr->gr_name;
519 break; 518 break;
520 case QUOTA_IDTYPE_USER: 519 case QUOTA_IDTYPE_USER:
521 pw = getpwuid(id); 520 pw = getpwuid(id);
522 if (pw) 521 if (pw)
523 name = pw->pw_name; 522 name = pw->pw_name;
524 break; 523 break;
525 default: 524 default:
526 errx(1, "Unknown quota ID type %d\n", idtype); 525 errx(1, "Unknown quota ID type %d\n", idtype);
527 } 526 }
528 } 527 }
529 528
530 if (name) 529 if (name)
531 len = strlen(name); 530 len = strlen(name);
532 else 531 else
533 len = 10; 532 len = 10;
534 if ((fup = calloc(1, sizeof(*fup) + len)) == NULL) 533 if ((fup = calloc(1, sizeof(*fup) + len)) == NULL)
535 err(1, "out of memory for fileusage structures"); 534 err(1, "out of memory for fileusage structures");
536 fhp = &fuhead[idtype][id & (FUHASH - 1)]; 535 fhp = &fuhead[idtype][id & (FUHASH - 1)];
537 fup->fu_next = *fhp; 536 fup->fu_next = *fhp;
538 *fhp = fup; 537 *fhp = fup;
539 fup->fu_id = id; 538 fup->fu_id = id;
540 if (id > highid[idtype]) 539 if (id > highid[idtype])
541 highid[idtype] = id; 540 highid[idtype] = id;
542 if (name) { 541 if (name) {
543 memmove(fup->fu_name, name, len + 1); 542 memmove(fup->fu_name, name, len + 1);
544 } else { 543 } else {
545 snprintf(fup->fu_name, len + 1, "%u", id); 544 snprintf(fup->fu_name, len + 1, "%u", id);
546 } 545 }
547 /* 546 /*
548 * XXX nothing guarantees the default limits have been loaded yet 547 * XXX nothing guarantees the default limits have been loaded yet
549 */ 548 */
550 fup->fu_qv[QUOTA_OBJTYPE_BLOCKS] = defaultqv[idtype][QUOTA_OBJTYPE_BLOCKS]; 549 fup->fu_qv[QUOTA_OBJTYPE_BLOCKS] = defaultqv[idtype][QUOTA_OBJTYPE_BLOCKS];
551 fup->fu_qv[QUOTA_OBJTYPE_FILES] = defaultqv[idtype][QUOTA_OBJTYPE_FILES]; 550 fup->fu_qv[QUOTA_OBJTYPE_FILES] = defaultqv[idtype][QUOTA_OBJTYPE_FILES];
552 return fup; 551 return fup;
553} 552}
554 553
555/* 554/*
556 * Check to see if target appears in list of size cnt. 555 * Check to see if target appears in list of size cnt.
557 */ 556 */
558static int 557static int
559oneof(const char *target, char *list[], int cnt) 558oneof(const char *target, char *list[], int cnt)
560{ 559{
561 int i; 560 int i;
562 561
563 for (i = 0; i < cnt; i++) 562 for (i = 0; i < cnt; i++)
564 if (strcmp(target, list[i]) == 0) 563 if (strcmp(target, list[i]) == 0)
565 return i; 564 return i;
566 return -1; 565 return -1;
567} 566}
568 567
569static int 568static int
570isover(struct quotaval *qv, time_t now) 569isover(struct quotaval *qv, time_t now)
571{  570{
572 return (qv->qv_usage >= qv->qv_hardlimit || 571 return (qv->qv_usage >= qv->qv_hardlimit ||
573 qv->qv_usage >= qv->qv_softlimit); 572 qv->qv_usage >= qv->qv_softlimit);
574}  573}