Fri Jan 21 16:58:07 2011 UTC ()
Add support for quotactl("getall") command, and convert repquota to new
world.


(bouyer)
diff -r1.1.2.1 -r1.1.2.2 src/sys/ufs/ufs/quota2.h
diff -r1.1.2.1 -r1.1.2.2 src/sys/ufs/ufs/quota2_prop.c
diff -r1.1.2.1 -r1.1.2.2 src/sys/ufs/ufs/quota2_prop.h
diff -r1.1.2.1 -r1.1.2.2 src/sys/ufs/ufs/ufs_quota.h
diff -r1.1.2.1 -r1.1.2.2 src/sys/ufs/ufs/ufs_quota2.c
diff -r1.68.4.1 -r1.68.4.2 src/sys/ufs/ufs/ufs_quota.c
diff -r1.6.64.1 -r1.6.64.2 src/usr.bin/quota/Makefile
diff -r0 -r1.1.2.1 src/usr.bin/quota/printquota.c
diff -r0 -r1.1.2.1 src/usr.bin/quota/printquota.h
diff -r1.14.52.2 -r1.14.52.3 src/usr.bin/quota/quota.1
diff -r1.33.2.1 -r1.33.2.2 src/usr.bin/quota/quota.c
diff -r1.5 -r1.5.64.1 src/usr.sbin/repquota/Makefile
diff -r1.9 -r1.9.50.1 src/usr.sbin/repquota/repquota.8
diff -r1.25 -r1.25.2.1 src/usr.sbin/repquota/repquota.c

cvs diff -r1.1.2.1 -r1.1.2.2 src/sys/ufs/ufs/quota2.h (expand / switch to unified diff)

--- src/sys/ufs/ufs/quota2.h 2011/01/20 14:25:03 1.1.2.1
+++ src/sys/ufs/ufs/quota2.h 2011/01/21 16:58:06 1.1.2.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: quota2.h,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $ */ 1/* $NetBSD: quota2.h,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */
2/*- 2/*-
3 * Copyright (c) 2010 Manuel Bouyer 3 * Copyright (c) 2010 Manuel Bouyer
4 * All rights reserved. 4 * All rights reserved.
5 * This software is distributed under the following condiions 5 * This software is distributed under the following condiions
6 * compliant with the NetBSD foundation policy. 6 * compliant with the NetBSD foundation policy.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -87,15 +87,14 @@ struct quota2_header { @@ -87,15 +87,14 @@ struct quota2_header {
87 87
88#define Q2_HEAD_MAGIC 0xb746915e 88#define Q2_HEAD_MAGIC 0xb746915e
89 89
90/* superblock flags */ 90/* superblock flags */
91#define FS_Q2_DO_TYPE(type) (0x01 << (type)) 91#define FS_Q2_DO_TYPE(type) (0x01 << (type))
92 92
93#define off2qindex(hsize, off) (((off) - (hsize)) / sizeof(struct quota2_entry)) 93#define off2qindex(hsize, off) (((off) - (hsize)) / sizeof(struct quota2_entry))
94#define qindex2off(hsize, idx) \ 94#define qindex2off(hsize, idx) \
95 ((daddr_t)(idx) * sizeof(struct quota2_entry) + (hsize)) 95 ((daddr_t)(idx) * sizeof(struct quota2_entry) + (hsize))
96 96
97/* quota2_subr.c */ 97/* quota2_subr.c */
98void quota2_addfreeq2e(struct quota2_header *, void *, uint64_t, uint64_t, int); 98void quota2_addfreeq2e(struct quota2_header *, void *, uint64_t, uint64_t, int);
99void quota2_create_blk0(uint64_t, void *bp, int, int, int); 99void quota2_create_blk0(uint64_t, void *bp, int, int, int);
100 
101#endif /* _UFS_UFS_QUOTA2_H_ */ 100#endif /* _UFS_UFS_QUOTA2_H_ */

cvs diff -r1.1.2.1 -r1.1.2.2 src/sys/ufs/ufs/Attic/quota2_prop.c (expand / switch to unified diff)

--- src/sys/ufs/ufs/Attic/quota2_prop.c 2011/01/20 14:25:03 1.1.2.1
+++ src/sys/ufs/ufs/Attic/quota2_prop.c 2011/01/21 16:58:06 1.1.2.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: quota2_prop.c,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $ */ 1/* $NetBSD: quota2_prop.c,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */
2/*- 2/*-
3 * Copyright (c) 2010 Manuel Bouyer 3 * Copyright (c) 2010 Manuel Bouyer
4 * All rights reserved. 4 * All rights reserved.
5 * This software is distributed under the following condiions 5 * This software is distributed under the following condiions
6 * compliant with the NetBSD foundation policy. 6 * compliant with the NetBSD foundation policy.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -85,28 +85,26 @@ quota2_dict_get_q2v_usage(prop_dictionar @@ -85,28 +85,26 @@ quota2_dict_get_q2v_usage(prop_dictionar
85 return EINVAL; 85 return EINVAL;
86 q2v->q2v_cur = vu; 86 q2v->q2v_cur = vu;
87 if (!prop_dictionary_get_int64(dict, "expire time", &v)) 87 if (!prop_dictionary_get_int64(dict, "expire time", &v))
88 return EINVAL; 88 return EINVAL;
89 q2v->q2v_time = v; 89 q2v->q2v_time = v;
90 return 0; 90 return 0;
91} 91}
92 92
93int 93int
94quota2_dict_get_q2e_usage(prop_dictionary_t data, struct quota2_entry *q2e) 94quota2_dict_get_q2e_usage(prop_dictionary_t data, struct quota2_entry *q2e)
95{ 95{
96 int i, error; 96 int i, error;
97 prop_dictionary_t val; 97 prop_dictionary_t val;
98 if (!prop_dictionary_get_uint32(data, "id", &q2e->q2e_uid)) 
99 return EINVAL; 
100 for (i = 0; i < NQ2V; i++) { 98 for (i = 0; i < NQ2V; i++) {
101 val = prop_dictionary_get_dict(data, quota2_valnames[i]); 99 val = prop_dictionary_get_dict(data, quota2_valnames[i]);
102 if (val == NULL) 100 if (val == NULL)
103 return EINVAL; 101 return EINVAL;
104 error = quota2_dict_get_q2v_usage(val, &q2e->q2e_val[i]); 102 error = quota2_dict_get_q2v_usage(val, &q2e->q2e_val[i]);
105 if (error) 103 if (error)
106 return error; 104 return error;
107 } 105 }
108 return 0; 106 return 0;
109} 107}
110 108
111int 109int
112quota2_get_cmds(prop_dictionary_t qdict, prop_array_t *cmds) 110quota2_get_cmds(prop_dictionary_t qdict, prop_array_t *cmds)
@@ -125,26 +123,36 @@ quota2_get_cmds(prop_dictionary_t qdict, @@ -125,26 +123,36 @@ quota2_get_cmds(prop_dictionary_t qdict,
125 return EINVAL; 123 return EINVAL;
126 if (prop_number_integer_value(pn) != 2) 124 if (prop_number_integer_value(pn) != 2)
127 return EINVAL; 125 return EINVAL;
128 126
129 o = prop_dictionary_get(qdict, "commands"); 127 o = prop_dictionary_get(qdict, "commands");
130 if (o == NULL) 128 if (o == NULL)
131 return ENOMEM; 129 return ENOMEM;
132 if(prop_object_type(o) != PROP_TYPE_ARRAY) 130 if(prop_object_type(o) != PROP_TYPE_ARRAY)
133 return EINVAL; 131 return EINVAL;
134 *cmds = o; 132 *cmds = o;
135 return 0; 133 return 0;
136} 134}
137 135
 136bool
 137prop_array_add_and_rel(prop_array_t array, prop_object_t po)
 138{
 139 bool ret;
 140 if (po == NULL)
 141 return false;
 142 ret = prop_array_add(array, po);
 143 prop_object_release(po);
 144 return ret;
 145}
138 146
139bool 147bool
140prop_dictionary_set_and_rel(prop_dictionary_t dict, const char *key, 148prop_dictionary_set_and_rel(prop_dictionary_t dict, const char *key,
141 prop_object_t po) 149 prop_object_t po)
142{ 150{
143 bool ret; 151 bool ret;
144 if (po == NULL) 152 if (po == NULL)
145 return false; 153 return false;
146 ret = prop_dictionary_set(dict, key, po); 154 ret = prop_dictionary_set(dict, key, po);
147 prop_object_release(po); 155 prop_object_release(po);
148 return ret; 156 return ret;
149} 157}
150 158

cvs diff -r1.1.2.1 -r1.1.2.2 src/sys/ufs/ufs/Attic/quota2_prop.h (expand / switch to unified diff)

--- src/sys/ufs/ufs/Attic/quota2_prop.h 2011/01/20 14:25:03 1.1.2.1
+++ src/sys/ufs/ufs/Attic/quota2_prop.h 2011/01/21 16:58:06 1.1.2.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: quota2_prop.h,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $ */ 1/* $NetBSD: quota2_prop.h,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */
2/*- 2/*-
3 * Copyright (c) 2010 Manuel Bouyer 3 * Copyright (c) 2010 Manuel Bouyer
4 * All rights reserved. 4 * All rights reserved.
5 * This software is distributed under the following condiions 5 * This software is distributed under the following condiions
6 * compliant with the NetBSD foundation policy. 6 * compliant with the NetBSD foundation policy.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -26,20 +26,21 @@ @@ -26,20 +26,21 @@
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE. 27 * POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#include <prop/proplib.h> 30#include <prop/proplib.h>
31#include <ufs/ufs/quota2.h> 31#include <ufs/ufs/quota2.h>
32 32
33prop_dictionary_t prop_dictionary_get_dict(prop_dictionary_t, const char *); 33prop_dictionary_t prop_dictionary_get_dict(prop_dictionary_t, const char *);
34int quota2_dict_get_q2v_limits(prop_dictionary_t, struct quota2_val *, bool); 34int quota2_dict_get_q2v_limits(prop_dictionary_t, struct quota2_val *, bool);
35int quota2_dict_get_q2v_usage(prop_dictionary_t, struct quota2_val *); 35int quota2_dict_get_q2v_usage(prop_dictionary_t, struct quota2_val *);
36int quota2_dict_get_q2e_usage(prop_dictionary_t, struct quota2_entry *); 36int quota2_dict_get_q2e_usage(prop_dictionary_t, struct quota2_entry *);
37int quota2_get_cmds(prop_dictionary_t, prop_array_t *); 37int quota2_get_cmds(prop_dictionary_t, prop_array_t *);
38 38
 39bool prop_array_add_and_rel(prop_array_t, prop_object_t);
39bool prop_dictionary_set_and_rel(prop_dictionary_t, const char *, 40bool prop_dictionary_set_and_rel(prop_dictionary_t, const char *,
40 prop_object_t); 41 prop_object_t);
41prop_dictionary_t quota2_prop_create(void); 42prop_dictionary_t quota2_prop_create(void);
42bool quota2_prop_add_command(prop_array_t, const char *, const char *, 43bool quota2_prop_add_command(prop_array_t, const char *, const char *,
43 prop_array_t); 44 prop_array_t);
44prop_dictionary_t q2vtoprop(struct quota2_val *); 45prop_dictionary_t q2vtoprop(struct quota2_val *);
45prop_dictionary_t q2etoprop(struct quota2_entry *, int); 46prop_dictionary_t q2etoprop(struct quota2_entry *, int);

cvs diff -r1.1.2.1 -r1.1.2.2 src/sys/ufs/ufs/ufs_quota.h (expand / switch to unified diff)

--- src/sys/ufs/ufs/ufs_quota.h 2011/01/20 14:25:03 1.1.2.1
+++ src/sys/ufs/ufs/ufs_quota.h 2011/01/21 16:58:06 1.1.2.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ufs_quota.h,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $ */ 1/* $NetBSD: ufs_quota.h,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1990, 1993, 1995 4 * Copyright (c) 1982, 1986, 1990, 1993, 1995
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.
@@ -86,28 +86,28 @@ struct dquot { @@ -86,28 +86,28 @@ struct dquot {
86#define dq_curinodes dq_un.dq1_dqb.dqb_curinodes 86#define dq_curinodes dq_un.dq1_dqb.dqb_curinodes
87#define dq_btime dq_un.dq_dqb.dqb_btime 87#define dq_btime dq_un.dq_dqb.dqb_btime
88#define dq_itime dq_un.dq_dqb.dqb_itime 88#define dq_itime dq_un.dq_dqb.dqb_itime
89 89
90#define dq2_lblkno dq_un.dq2_desc.dq2_lblkno 90#define dq2_lblkno dq_un.dq2_desc.dq2_lblkno
91#define dq2_blkoff dq_un.dq2_desc.dq2_blkoff 91#define dq2_blkoff dq_un.dq2_desc.dq2_blkoff
92/* 92/*
93 * If the system has never checked for a quota for this file, then it is 93 * If the system has never checked for a quota for this file, then it is
94 * set to NODQUOT. Once a write attempt is made the inode pointer is set 94 * set to NODQUOT. Once a write attempt is made the inode pointer is set
95 * to reference a dquot structure. 95 * to reference a dquot structure.
96 */ 96 */
97#define NODQUOT NULL 97#define NODQUOT NULL
98 98
99static kmutex_t dqlock; 99extern kmutex_t dqlock;
100static kcondvar_t dqcv; 100extern kcondvar_t dqcv;
101/* 101/*
102 * Quota name to error message mapping. 102 * Quota name to error message mapping.
103 */ 103 */
104static const char *quotatypes[] = INITQFNAMES; 104static const char *quotatypes[] = INITQFNAMES;
105 105
106/*  106/*
107 * Code pertaining to management of the in-core dquot data structures. 107 * Code pertaining to management of the in-core dquot data structures.
108 */  108 */
109#define DQHASH(dqvp, id) \ 109#define DQHASH(dqvp, id) \
110 (((((long)(dqvp)) >> 8) + id) & dqhash)  110 (((((long)(dqvp)) >> 8) + id) & dqhash)
111static LIST_HEAD(dqhashhead, dquot) *dqhashtbl; 111static LIST_HEAD(dqhashhead, dquot) *dqhashtbl;
112static u_long dqhash; 112static u_long dqhash;
113static pool_cache_t dquot_cache; 113static pool_cache_t dquot_cache;
@@ -118,18 +118,19 @@ void dqref(struct dquot *); @@ -118,18 +118,19 @@ void dqref(struct dquot *);
118void dqrele(struct vnode *, struct dquot *); 118void dqrele(struct vnode *, struct dquot *);
119void dqflush(struct vnode *); 119void dqflush(struct vnode *);
120 120
121int chkdq1(struct inode *, int64_t, kauth_cred_t, int); 121int chkdq1(struct inode *, int64_t, kauth_cred_t, int);
122int chkiq1(struct inode *, int32_t, kauth_cred_t, int); 122int chkiq1(struct inode *, int32_t, kauth_cred_t, int);
123int getquota1(struct mount *, u_long, int, struct dqblk *); 123int getquota1(struct mount *, u_long, int, struct dqblk *);
124int setquota1(struct mount *, u_long, int, struct dqblk *); 124int setquota1(struct mount *, u_long, int, struct dqblk *);
125int q1sync(struct mount *); 125int q1sync(struct mount *);
126int dq1get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *); 126int dq1get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *);
127int dq1sync(struct vnode *, struct dquot *); 127int dq1sync(struct vnode *, struct dquot *);
128 128
129int chkdq2(struct inode *, int64_t, kauth_cred_t, int); 129int chkdq2(struct inode *, int64_t, kauth_cred_t, int);
130int chkiq2(struct inode *, int32_t, kauth_cred_t, int); 130int chkiq2(struct inode *, int32_t, kauth_cred_t, int);
131int quota2_handle_cmd_get(struct ufsmount *, const char *, int, int, 131int quota2_handle_cmd_get(struct ufsmount *, int, int, int,
132 prop_array_t); 132 prop_array_t);
 133int quota2_handle_cmd_getall(struct ufsmount *, int, prop_array_t);
133int q2sync(struct mount *); 134int q2sync(struct mount *);
134int dq2get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *); 135int dq2get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *);
135int dq2sync(struct vnode *, struct dquot *); 136int dq2sync(struct vnode *, struct dquot *);

cvs diff -r1.1.2.1 -r1.1.2.2 src/sys/ufs/ufs/ufs_quota2.c (expand / switch to unified diff)

--- src/sys/ufs/ufs/ufs_quota2.c 2011/01/20 14:25:03 1.1.2.1
+++ src/sys/ufs/ufs/ufs_quota2.c 2011/01/21 16:58:06 1.1.2.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ufs_quota2.c,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $ */ 1/* $NetBSD: ufs_quota2.c,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */
2/*- 2/*-
3 * Copyright (c) 2010 Manuel Bouyer 3 * Copyright (c) 2010 Manuel Bouyer
4 * All rights reserved. 4 * All rights reserved.
5 * This software is distributed under the following condiions 5 * This software is distributed under the following condiions
6 * compliant with the NetBSD foundation policy. 6 * compliant with the NetBSD foundation policy.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -18,27 +18,27 @@ @@ -18,27 +18,27 @@
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE. 27 * POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $"); 31__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $");
32 32
33#include <sys/buf.h> 33#include <sys/buf.h>
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/kernel.h> 35#include <sys/kernel.h>
36#include <sys/systm.h> 36#include <sys/systm.h>
37#include <sys/namei.h> 37#include <sys/namei.h>
38#include <sys/file.h> 38#include <sys/file.h>
39#include <sys/proc.h> 39#include <sys/proc.h>
40#include <sys/vnode.h> 40#include <sys/vnode.h>
41#include <sys/mount.h> 41#include <sys/mount.h>
42#include <sys/fstrans.h> 42#include <sys/fstrans.h>
43#include <sys/kauth.h> 43#include <sys/kauth.h>
44#include <sys/wapbl.h> 44#include <sys/wapbl.h>
@@ -48,26 +48,29 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c @@ -48,26 +48,29 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c
48#include <ufs/ufs/ufsmount.h> 48#include <ufs/ufs/ufsmount.h>
49#include <ufs/ufs/ufs_bswap.h> 49#include <ufs/ufs/ufs_bswap.h>
50#include <ufs/ufs/ufs_extern.h> 50#include <ufs/ufs/ufs_extern.h>
51#include <ufs/ufs/ufs_quota.h> 51#include <ufs/ufs/ufs_quota.h>
52#include <ufs/ufs/ufs_wapbl.h> 52#include <ufs/ufs/ufs_wapbl.h>
53#include <ufs/ufs/quota2_prop.h> 53#include <ufs/ufs/quota2_prop.h>
54 54
55static int getinoquota2(struct inode *, int, struct buf **, 55static int getinoquota2(struct inode *, int, struct buf **,
56 struct quota2_entry **); 56 struct quota2_entry **);
57static int getq2h(struct ufsmount *, int, struct buf **, 57static int getq2h(struct ufsmount *, int, struct buf **,
58 struct quota2_header **, int); 58 struct quota2_header **, int);
59static int getq2e(struct ufsmount *, int, daddr_t, int, struct buf **, 59static int getq2e(struct ufsmount *, int, daddr_t, int, struct buf **,
60 struct quota2_entry **, int); 60 struct quota2_entry **, int);
 61static int quota2_walk_list(struct ufsmount *, struct buf *, int,
 62 uint64_t *, int, void *,
 63 int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, uint64_t, void *));
61 64
62static int 65static int
63getq2h(struct ufsmount *ump, int type, 66getq2h(struct ufsmount *ump, int type,
64 struct buf **bpp, struct quota2_header **q2hp, int flags) 67 struct buf **bpp, struct quota2_header **q2hp, int flags)
65{ 68{
66 const int needswap = UFS_MPNEEDSWAP(ump); 69 const int needswap = UFS_MPNEEDSWAP(ump);
67 int error; 70 int error;
68 struct buf *bp; 71 struct buf *bp;
69 struct quota2_header *q2h; 72 struct quota2_header *q2h;
70 73
71 error = bread(ump->um_quotas[type], 0, ump->umq2_bsize, 74 error = bread(ump->um_quotas[type], 0, ump->umq2_bsize,
72 ump->um_cred[type], flags, &bp); 75 ump->um_cred[type], flags, &bp);
73 if (error) 76 if (error)
@@ -97,26 +100,100 @@ getq2e(struct ufsmount *ump, int type, d @@ -97,26 +100,100 @@ getq2e(struct ufsmount *ump, int type, d
97 } 100 }
98 error = bread(ump->um_quotas[type], lblkno, ump->umq2_bsize, 101 error = bread(ump->um_quotas[type], lblkno, ump->umq2_bsize,
99 ump->um_cred[type], flags, &bp); 102 ump->um_cred[type], flags, &bp);
100 if (error) 103 if (error)
101 return error; 104 return error;
102 if (bp->b_resid != 0) { 105 if (bp->b_resid != 0) {
103 panic("dq2get: %s quota file corrupted", 106 panic("dq2get: %s quota file corrupted",
104 quotatypes[type]); 107 quotatypes[type]);
105 } 108 }
106 *q2ep = (void *)((char *)bp->b_data + blkoffset); 109 *q2ep = (void *)((char *)bp->b_data + blkoffset);
107 *bpp = bp; 110 *bpp = bp;
108 return 0; 111 return 0;
109} 112}
 113
 114/* walk a quota entry list, calling the callback for each entry */
 115#define Q2WL_ABORT 0x10000000
 116
 117static int
 118quota2_walk_list(struct ufsmount *ump, struct buf *hbp, int type,
 119 uint64_t *offp, int flags, void *a,
 120 int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, uint64_t, void *))
 121{
 122 const int needswap = UFS_MPNEEDSWAP(ump);
 123 daddr_t off = ufs_rw64(*offp, needswap);
 124 struct buf *bp, *obp = hbp;
 125 int ret = 0, ret2 = 0;
 126 struct quota2_entry *q2e;
 127 daddr_t lblkno, blkoff;
 128
 129 KASSERT(mutex_owner(&dqlock));
 130
 131 while (off != 0) {
 132 lblkno = (off >> ump->um_mountp->mnt_fs_bshift);
 133 blkoff = (off & ump->umq2_bmask);
 134 if (lblkno == 0) {
 135 /* in the header block */
 136 bp = hbp;
 137 } else {
 138 ret = bread(ump->um_quotas[type], lblkno,
 139 ump->umq2_bsize,
 140 ump->um_cred[type], flags, &bp);
 141 if (ret)
 142 return ret;
 143 if (bp->b_resid != 0) {
 144 panic("quota2_walk_list: %s quota file corrupted",
 145 quotatypes[type]);
 146 }
 147 }
 148 q2e = (void *)((char *)(bp->b_data) + blkoff);
 149 ret = (*func)(ump, offp, q2e, off, a);
 150 if (off != ufs_rw64(*offp, needswap)) {
 151 /* callback changed parent's pointer, redo */
 152 off = ufs_rw64(*offp, needswap);
 153 if (bp != hbp && bp != obp)
 154 ret2 = VOP_BWRITE(bp);
 155 } else {
 156 /* parent if now current */
 157 if (obp != bp && obp != hbp) {
 158 if (flags & B_MODIFY)
 159 ret2 = VOP_BWRITE(obp);
 160 else
 161 brelse(obp, 0);
 162 }
 163 obp = bp;
 164 offp = &(q2e->q2e_next);
 165 off = ufs_rw64(*offp, needswap);
 166 }
 167 if (ret)
 168 break;
 169 if (ret2) {
 170 ret = ret2;
 171 break;
 172 }
 173 }
 174 if (obp != hbp) {
 175 if (flags & B_MODIFY)
 176 ret2 = VOP_BWRITE(obp);
 177 else
 178 brelse(obp, 0);
 179 }
 180 if (ret & Q2WL_ABORT)
 181 return 0;
 182 if (ret == 0)
 183 return ret2;
 184 return ret;
 185}
 186
110void 187void
111quota2_umount(struct mount *mp) 188quota2_umount(struct mount *mp)
112{ 189{
113 int i, error; 190 int i, error;
114 struct ufsmount *ump = VFSTOUFS(mp); 191 struct ufsmount *ump = VFSTOUFS(mp);
115 192
116 for (i = 0; i < MAXQUOTAS; i++) { 193 for (i = 0; i < MAXQUOTAS; i++) {
117 if (ump->um_quotas[i]) { 194 if (ump->um_quotas[i]) {
118 error = vn_close(ump->um_quotas[i], FREAD|FWRITE, 195 error = vn_close(ump->um_quotas[i], FREAD|FWRITE,
119 ump->um_cred[i]); 196 ump->um_cred[i]);
120 if (error) { 197 if (error) {
121 printf("quota2_umount failed: close(%p) %d\n", 198 printf("quota2_umount failed: close(%p) %d\n",
122 ump->um_quotas[i], error); 199 ump->um_quotas[i], error);
@@ -308,116 +385,177 @@ quota2_check(struct inode *ip, int vtype @@ -308,116 +385,177 @@ quota2_check(struct inode *ip, int vtype
308int 385int
309chkdq2(struct inode *ip, int64_t change, kauth_cred_t cred, int flags) 386chkdq2(struct inode *ip, int64_t change, kauth_cred_t cred, int flags)
310{ 387{
311 return quota2_check(ip, Q2V_BLOCK, change, cred, flags); 388 return quota2_check(ip, Q2V_BLOCK, change, cred, flags);
312} 389}
313 390
314int 391int
315chkiq2(struct inode *ip, int32_t change, kauth_cred_t cred, int flags) 392chkiq2(struct inode *ip, int32_t change, kauth_cred_t cred, int flags)
316{ 393{
317 return quota2_check(ip, Q2V_FILE, change, cred, flags); 394 return quota2_check(ip, Q2V_FILE, change, cred, flags);
318} 395}
319 396
320int 397int
321quota2_handle_cmd_get(struct ufsmount *ump, const char *type, int id, 398quota2_handle_cmd_get(struct ufsmount *ump, int type, int id,
322 int defaultq, prop_array_t replies) 399 int defaultq, prop_array_t replies)
323{ 400{
324 struct dquot *dq; 401 struct dquot *dq;
325 int error; 402 int error;
326 struct quota2_header *q2h; 403 struct quota2_header *q2h;
327 struct quota2_entry *q2e; 404 struct quota2_entry *q2e;
328 struct buf *bp; 405 struct buf *bp;
329 prop_dictionary_t dict; 406 prop_dictionary_t dict;
330 int q2type; 
331 407
332 if (!strcmp(type, "user")) { 408 if (ump->um_quotas[type] == NULLVP)
333 q2type = USRQUOTA; 
334 } else if (!strcmp(type, "group")) { 
335 q2type = GRPQUOTA; 
336 } else 
337 return EOPNOTSUPP; 
338 
339 if (ump->um_quotas[q2type] == NULLVP) 
340 return ENODEV; 409 return ENODEV;
341 if (defaultq) { 410 if (defaultq) {
342 error = getq2h(ump, q2type, &bp, &q2h, 0); 411 mutex_enter(&dqlock);
343 if (error) 412 error = getq2h(ump, type, &bp, &q2h, 0);
 413 if (error) {
 414 mutex_exit(&dqlock);
344 return error; 415 return error;
 416 }
345 q2e = &q2h->q2h_defentry; 417 q2e = &q2h->q2h_defentry;
346 } else { 418 } else {
347 error = dqget(NULLVP, id, ump, q2type, &dq); 419 error = dqget(NULLVP, id, ump, type, &dq);
348 420
349 if (error) 421 if (error)
350 return error; 422 return error;
351 423
352 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { 424 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) {
353 dqrele(NULLVP, dq); 425 dqrele(NULLVP, dq);
354 return ENOENT; 426 return ENOENT;
355 } 427 }
356 error = getq2e(ump, q2type, dq->dq2_lblkno, dq->dq2_blkoff, 428 error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff,
357 &bp, &q2e, 0); 429 &bp, &q2e, 0);
358 dqrele(NULLVP, dq); 
359 if (error) 430 if (error)
360 return error; 431 return error;
361 } 432 }
362 dict = q2etoprop(q2e, 0); 433 dict = q2etoprop(q2e, defaultq);
 434 if (defaultq)
 435 mutex_exit(&dqlock);
 436 else
 437 dqrele(NULLVP, dq);
363 brelse(bp, 0); 438 brelse(bp, 0);
364 if (dict == NULL) 439 if (dict == NULL)
365 return ENOMEM; 440 return ENOMEM;
366  441
367 if (!prop_array_add(replies, dict)) { 442 if (!prop_array_add_and_rel(replies, dict)) {
368 error = ENOMEM; 443 error = ENOMEM;
369 } 444 }
370 prop_object_release(dict); 445 return error;
 446}
 447
 448
 449static int
 450quota2_getall_callback(struct ufsmount *ump, uint64_t *offp,
 451 struct quota2_entry *q2e, uint64_t off, void *v)
 452{
 453 prop_array_t replies = v;
 454 prop_dictionary_t dict;
 455
 456 dict = q2etoprop(q2e, 0);
 457 if (!prop_array_add_and_rel(replies, dict)) {
 458 return ENOMEM;
 459 }
 460 return 0;
 461}
 462
 463int
 464quota2_handle_cmd_getall(struct ufsmount *ump, int type, prop_array_t replies)
 465{
 466 int error;
 467 struct quota2_header *q2h;
 468 struct buf *hbp;
 469 prop_dictionary_t dict;
 470 uint64_t offset;
 471 int i;
 472 int quota2_hash_size;
 473 const int needswap = UFS_MPNEEDSWAP(ump);
 474
 475 if (ump->um_quotas[type] == NULLVP)
 476 return ENODEV;
 477 error = getq2h(ump, type, &hbp, &q2h, 0);
 478 if (error)
 479 return error;
 480 dict = q2etoprop(&q2h->q2h_defentry, 1);
 481 if (!prop_array_add_and_rel(replies, dict)) {
 482 brelse(hbp, 0);
 483 return ENOMEM;
 484 }
 485 quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap);
 486 for (i = 0; i < quota2_hash_size ; i++) {
 487 offset = ufs_rw64(q2h->q2h_entries[i], needswap);
 488 error = quota2_walk_list(ump, hbp, type, &offset, 0, replies,
 489 quota2_getall_callback);
 490 if (error)
 491 break;
 492 }
 493 brelse(hbp, 0);
371 return error; 494 return error;
372} 495}
373 496
374int 497int
375q2sync(struct mount *mp) 498q2sync(struct mount *mp)
376{ 499{
377 return 0; 500 return 0;
378} 501}
379 502
 503struct dq2get_callback {
 504 uid_t id;
 505 struct dquot *dq;
 506};
 507
 508static int
 509dq2get_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e,
 510 uint64_t off, void *v)
 511{
 512 struct dq2get_callback *c = v;
 513 daddr_t lblkno;
 514 int blkoff;
 515 const int needswap = UFS_MPNEEDSWAP(ump);
 516
 517 if (ufs_rw32(q2e->q2e_uid, needswap) == c->id) {
 518 lblkno = (off >> ump->um_mountp->mnt_fs_bshift);
 519 blkoff = (off & ump->umq2_bmask);
 520 c->dq->dq2_lblkno = lblkno;
 521 c->dq->dq2_blkoff = blkoff;
 522 return Q2WL_ABORT;
 523 }
 524 return 0;
 525}
 526
380int 527int
381dq2get(struct vnode *dqvp, u_long id, struct ufsmount *ump, int type, 528dq2get(struct vnode *dqvp, u_long id, struct ufsmount *ump, int type,
382 struct dquot *dq) 529 struct dquot *dq)
383{ 530{
384 struct buf *bp; 531 struct buf *bp;
385 struct quota2_header *q2h; 532 struct quota2_header *q2h;
386 struct quota2_entry *q2e; 
387 int error; 533 int error;
388 daddr_t offset, lblkno; 534 daddr_t offset;
389 int blkoffset; 
390 u_long hash_mask; 535 u_long hash_mask;
391 const int needswap = UFS_MPNEEDSWAP(ump); 536 const int needswap = UFS_MPNEEDSWAP(ump);
 537 struct dq2get_callback c = {
 538 .id = id,
 539 .dq = dq
 540 };
392 541
 542 mutex_enter(&dqlock);
393 error = getq2h(ump, type, &bp, &q2h, 0); 543 error = getq2h(ump, type, &bp, &q2h, 0);
394 if (error) 544 if (error)
395 return error; 545 goto out_mutex;
396 /* look for our entry */ 546 /* look for our entry */
397 hash_mask = ((1 << q2h->q2h_hash_shift) - 1); 547 hash_mask = ((1 << q2h->q2h_hash_shift) - 1);
398 offset = ufs_rw64(q2h->q2h_entries[id & hash_mask], needswap); 548 offset = ufs_rw64(q2h->q2h_entries[id & hash_mask], needswap);
399 dq->dq2_lblkno = 0; 549 error = quota2_walk_list(ump, bp, type, &offset, 0, (void *)&c,
400 dq->dq2_blkoff = 0; 550 dq2get_callback);
401 while (offset != 0) { 
402 lblkno = (offset >> ump->um_mountp->mnt_fs_bshift); 
403 blkoffset = (offset & ump->umq2_bmask); 
404 brelse(bp, 0); 
405 error = getq2e(ump, type, lblkno, blkoffset, &bp, &q2e, 0); 
406 if (error) 
407 return error; 
408 if (ufs_rw32(q2e->q2e_uid, needswap) == id) { 
409 dq->dq2_lblkno = lblkno; 
410 dq->dq2_blkoff = blkoffset; 
411 break; 
412 } 
413 offset = ufs_rw64(q2e->q2e_next, needswap); 
414 } 
415 brelse(bp, 0); 551 brelse(bp, 0);
 552out_mutex:
 553 mutex_exit(&dqlock);
416 return error; 554 return error;
417} 555}
418 556
419int 557int
420dq2sync(struct vnode *vp, struct dquot *dq) 558dq2sync(struct vnode *vp, struct dquot *dq)
421{ 559{
422 return 0; 560 return 0;
423} 561}

cvs diff -r1.68.4.1 -r1.68.4.2 src/sys/ufs/ufs/ufs_quota.c (expand / switch to unified diff)

--- src/sys/ufs/ufs/ufs_quota.c 2011/01/20 14:25:03 1.68.4.1
+++ src/sys/ufs/ufs/ufs_quota.c 2011/01/21 16:58:06 1.68.4.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ufs_quota.c,v 1.68.4.1 2011/01/20 14:25:03 bouyer Exp $ */ 1/* $NetBSD: ufs_quota.c,v 1.68.4.2 2011/01/21 16:58:06 bouyer Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1990, 1993, 1995 4 * Copyright (c) 1982, 1986, 1990, 1993, 1995
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.
@@ -25,51 +25,55 @@ @@ -25,51 +25,55 @@
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 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 34 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.68.4.1 2011/01/20 14:25:03 bouyer Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.68.4.2 2011/01/21 16:58:06 bouyer Exp $");
39 39
40#if defined(_KERNEL_OPT) 40#if defined(_KERNEL_OPT)
41#include "opt_quota.h" 41#include "opt_quota.h"
42#endif  42#endif
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/kernel.h> 44#include <sys/kernel.h>
45#include <sys/systm.h> 45#include <sys/systm.h>
46#include <sys/namei.h> 46#include <sys/namei.h>
47#include <sys/file.h> 47#include <sys/file.h>
48#include <sys/proc.h> 48#include <sys/proc.h>
49#include <sys/vnode.h> 49#include <sys/vnode.h>
50#include <sys/mount.h> 50#include <sys/mount.h>
51#include <sys/kauth.h> 51#include <sys/kauth.h>
52 52
53#include <ufs/ufs/quota.h> 53#include <ufs/ufs/quota.h>
54#include <ufs/ufs/inode.h> 54#include <ufs/ufs/inode.h>
55#include <ufs/ufs/ufsmount.h> 55#include <ufs/ufs/ufsmount.h>
56#include <ufs/ufs/ufs_extern.h> 56#include <ufs/ufs/ufs_extern.h>
57#include <ufs/ufs/ufs_quota.h> 57#include <ufs/ufs/ufs_quota.h>
58#include <ufs/ufs/quota2_prop.h> 58#include <ufs/ufs/quota2_prop.h>
59 59
 60kmutex_t dqlock;
 61kcondvar_t dqcv;
60 62
61static int quota_handle_cmd_get(struct mount *, struct lwp *, 63static int quota_handle_cmd_get(struct mount *, struct lwp *,
62 prop_dictionary_t, const char *, prop_array_t); 64 prop_dictionary_t, int, prop_array_t);
 65static int quota_handle_cmd_getall(struct mount *, struct lwp *,
 66 prop_dictionary_t, int, prop_array_t);
63/* 67/*
64 * Initialize the quota fields of an inode. 68 * Initialize the quota fields of an inode.
65 */ 69 */
66void 70void
67ufsquota_init(struct inode *ip) 71ufsquota_init(struct inode *ip)
68{ 72{
69 int i; 73 int i;
70 74
71 for (i = 0; i < MAXQUOTAS; i++) 75 for (i = 0; i < MAXQUOTAS; i++)
72 ip->i_dquot[i] = NODQUOT; 76 ip->i_dquot[i] = NODQUOT;
73} 77}
74 78
75/* 79/*
@@ -116,131 +120,170 @@ chkiq(struct inode *ip, int32_t change,  @@ -116,131 +120,170 @@ chkiq(struct inode *ip, int32_t change,
116#ifdef QUOTA2 120#ifdef QUOTA2
117 if (ip->i_ump->um_flags & UFS_QUOTA2) 121 if (ip->i_ump->um_flags & UFS_QUOTA2)
118 return chkiq2(ip, change, cred, flags); 122 return chkiq2(ip, change, cred, flags);
119#endif 123#endif
120 return 0; 124 return 0;
121} 125}
122 126
123int 127int
124quota_handle_cmd(struct mount *mp, struct lwp *l, prop_dictionary_t cmddict) 128quota_handle_cmd(struct mount *mp, struct lwp *l, prop_dictionary_t cmddict)
125{ 129{
126 int error = 0; 130 int error = 0;
127 const char *cmd, *type; 131 const char *cmd, *type;
128 prop_array_t datas; 132 prop_array_t datas;
 133 int q2type;
129 134
130 if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd)) 135 if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd))
131 return EINVAL; 136 return EINVAL;
132 if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type)) 137 if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type))
133 return EINVAL; 138 return EINVAL;
 139 if (!strcmp(type, "user")) {
 140 q2type = USRQUOTA;
 141 } else if (!strcmp(type, "group")) {
 142 q2type = GRPQUOTA;
 143 } else
 144 return EOPNOTSUPP;
134 datas = prop_dictionary_get(cmddict, "data"); 145 datas = prop_dictionary_get(cmddict, "data");
135 if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY) 146 if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY)
136 return EINVAL; 147 return EINVAL;
137 148
138 prop_object_retain(datas); 149 prop_object_retain(datas);
139 prop_dictionary_remove(cmddict, "data"); /* prepare for return */ 150 prop_dictionary_remove(cmddict, "data"); /* prepare for return */
140 151
141 if (strcmp(cmd, "get") == 0) { 152 if (strcmp(cmd, "get") == 0) {
142 error = quota_handle_cmd_get(mp, l, cmddict, type, datas); 153 error = quota_handle_cmd_get(mp, l, cmddict, q2type, datas);
143 goto end; 154 goto end;
144 } 155 }
145 if (!prop_dictionary_set_int8(cmddict, "return", EOPNOTSUPP)) 156 if (strcmp(cmd, "getall") == 0) {
146 error = ENOMEM; 157 error = quota_handle_cmd_getall(mp, l, cmddict, q2type, datas);
 158 goto end;
 159 }
 160 error = EOPNOTSUPP;
147end: 161end:
 162 error = (prop_dictionary_set_int8(cmddict, "return",
 163 error) ? 0 : ENOMEM);
148 prop_object_release(datas); 164 prop_object_release(datas);
149 return error; 165 return error;
150} 166}
151 167
152/* XXX shouldn't all this be in kauth ? */ 168/* XXX shouldn't all this be in kauth ? */
153static int 169static int
154quota_get_auth(struct mount *mp, struct lwp *l, uid_t id) { 170quota_get_auth(struct mount *mp, struct lwp *l, uid_t id) {
155 /* The user can always query about his own quota. */ 171 /* The user can always query about his own quota. */
156 if (id == kauth_cred_getuid(l->l_cred)) 172 if (id == kauth_cred_getuid(l->l_cred))
157 return 0; 173 return 0;
158 return kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 174 return kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
159 KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, KAUTH_ARG(id), NULL); 175 KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, KAUTH_ARG(id), NULL);
160} 176}
161 177
162static int  178static int
163quota_handle_cmd_get(struct mount *mp, struct lwp *l,  179quota_handle_cmd_get(struct mount *mp, struct lwp *l,
164 prop_dictionary_t cmddict, const char *type, prop_array_t datas) 180 prop_dictionary_t cmddict, int type, prop_array_t datas)
165{ 181{
166 prop_array_t replies; 182 prop_array_t replies;
167 prop_object_iterator_t iter; 183 prop_object_iterator_t iter;
168 prop_dictionary_t data; 184 prop_dictionary_t data;
169 uint32_t id; 185 uint32_t id;
170 struct ufsmount *ump = VFSTOUFS(mp); 186 struct ufsmount *ump = VFSTOUFS(mp);
171 int error, defaultq = 0; 187 int error, defaultq = 0;
172 const char *idstr; 188 const char *idstr;
173 189
174 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) 190 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0)
175 return (prop_dictionary_set_int8(cmddict, "return", 191 return EOPNOTSUPP;
176 EOPNOTSUPP) ? 0 : ENOMEM); 
177  192
178 replies = prop_array_create(); 193 replies = prop_array_create();
179 if (replies == NULL) 194 if (replies == NULL)
180 return (prop_dictionary_set_int8(cmddict, "return", ENOMEM) ? 195 return ENOMEM;
181 0 : ENOMEM); 
182 196
183 iter = prop_array_iterator(datas); 197 iter = prop_array_iterator(datas);
184 if (iter == NULL) { 198 if (iter == NULL) {
185 prop_object_release(replies); 199 prop_object_release(replies);
186 return (prop_dictionary_set_int8(cmddict, "return", ENOMEM) ? 200 return ENOMEM;
187 0 : ENOMEM); 
188 } 201 }
189 while ((data = prop_object_iterator_next(iter)) != NULL) { 202 while ((data = prop_object_iterator_next(iter)) != NULL) {
190 if (!prop_dictionary_get_uint32(data, "id", &id)) { 203 if (!prop_dictionary_get_uint32(data, "id", &id)) {
191 if (!prop_dictionary_get_cstring_nocopy(data, "id", 204 if (!prop_dictionary_get_cstring_nocopy(data, "id",
192 &idstr)) 205 &idstr))
193 continue; 206 continue;
194 if (strcmp(idstr, "default")) 207 if (strcmp(idstr, "default"))
195 continue; 208 continue;
196 id = 0; 209 id = 0;
197 defaultq = 1; 210 defaultq = 1;
198 } 211 }
199 error = quota_get_auth(mp, l, id); 212 error = quota_get_auth(mp, l, id);
200 if (error == EPERM) 213 if (error == EPERM)
201 continue; 214 continue;
202 if (error != 0) { 215 if (error != 0) {
203 error = (prop_dictionary_set_int8(cmddict, "return", 
204 error) ? 0 : ENOMEM); 
205 prop_object_release(replies); 216 prop_object_release(replies);
206 return error; 217 return error;
207 } 218 }
208#ifdef QUOTA 219#ifdef QUOTA
209 if (ump->um_flags & UFS_QUOTA) 220 if (ump->um_flags & UFS_QUOTA)
210 error = quota1_handle_cmd_get(ump, type, id, replies) 221 error = quota1_handle_cmd_get(ump, type, id, replies)
211 else 222 else
212#endif 223#endif
213#ifdef QUOTA2 224#ifdef QUOTA2
214 if (ump->um_flags & UFS_QUOTA2) { 225 if (ump->um_flags & UFS_QUOTA2) {
215 error = quota2_handle_cmd_get(ump, type, id, defaultq, 226 error = quota2_handle_cmd_get(ump, type, id, defaultq,
216 replies); 227 replies);
217 } else 228 } else
218#endif 229#endif
219 panic("quota_handle_cmd_get: no support ?"); 230 panic("quota_handle_cmd_get: no support ?");
220  231
221 if (error && error != ENOENT) { 232 if (error && error != ENOENT) {
222 error = (prop_dictionary_set_int8(cmddict, "return", 
223 error) ? 0 : ENOMEM); 
224 prop_object_release(replies); 233 prop_object_release(replies);
225 return error; 234 return error;
226 } 235 }
227 } 236 }
228 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { 237 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
229 error = (prop_dictionary_set_int8(cmddict, "return", 238 error = ENOMEM;
230 ENOMEM) ? 0 : ENOMEM); 239 } else {
 240 error = 0;
 241 }
 242 return error;
 243}
 244
 245static int
 246quota_handle_cmd_getall(struct mount *mp, struct lwp *l,
 247 prop_dictionary_t cmddict, int type, prop_array_t datas)
 248{
 249 prop_array_t replies;
 250 struct ufsmount *ump = VFSTOUFS(mp);
 251 int error;
 252
 253 if ((ump->um_flags & UFS_QUOTA2) == 0)
 254 return EOPNOTSUPP;
 255
 256 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
 257 KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL);
 258 if (error)
 259 return error;
 260
 261 replies = prop_array_create();
 262 if (replies == NULL)
 263 return ENOMEM;
 264
 265#ifdef QUOTA2
 266 if (ump->um_flags & UFS_QUOTA2) {
 267 mutex_enter(&dqlock);
 268 error = quota2_handle_cmd_getall(ump, type, replies);
 269 mutex_exit(&dqlock);
 270 } else
 271#endif
 272 panic("quota_handle_cmd_getall: no support ?");
 273 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
 274 error = ENOMEM;
231 } else { 275 } else {
232 error = (prop_dictionary_set_int8(cmddict, "return", 0) ? 276 error = 0;
233 0 : ENOMEM); 
234 } 277 }
235 return error; 278 return error;
236} 279}
237 280
238/* 281/*
239 * Initialize the quota system. 282 * Initialize the quota system.
240 */ 283 */
241void 284void
242dqinit(void) 285dqinit(void)
243{ 286{
244 287
245 mutex_init(&dqlock, MUTEX_DEFAULT, IPL_NONE); 288 mutex_init(&dqlock, MUTEX_DEFAULT, IPL_NONE);
246 cv_init(&dqcv, "quota"); 289 cv_init(&dqcv, "quota");

cvs diff -r1.6.64.1 -r1.6.64.2 src/usr.bin/quota/Makefile (expand / switch to unified diff)

--- src/usr.bin/quota/Makefile 2011/01/20 14:25:05 1.6.64.1
+++ src/usr.bin/quota/Makefile 2011/01/21 16:58:06 1.6.64.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: Makefile,v 1.6.64.1 2011/01/20 14:25:05 bouyer Exp $  1# $NetBSD: Makefile,v 1.6.64.2 2011/01/21 16:58:06 bouyer Exp $
2# from: @(#)Makefile 8.1 (Berkeley) 6/6/93 2# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
3 3
4.include <bsd.own.mk> 4.include <bsd.own.mk>
5PROG= quota 5PROG= quota
6SRCS= quota.c 6SRCS= quota.c printquota.c
7 7
8CPPFLAGS+=-I${NETBSDSRCDIR}/sys 8CPPFLAGS+=-I${NETBSDSRCDIR}/sys -I${NETBSDSRCDIR}/usr.bin/quota
9DPADD= ${LIBRPCSVC} 9DPADD= ${LIBRPCSVC} ${LIBPROP}
10LDADD= -lrpcsvc -lprop 10LDADD= -lrpcsvc -lprop
11 11
12.PATH: ${NETBSDSRCDIR}/sys/ufs/ufs  12.PATH: ${NETBSDSRCDIR}/sys/ufs/ufs
13SRCS+= quota2_prop.c 13SRCS+= quota2_prop.c
14.include <bsd.prog.mk> 14.include <bsd.prog.mk>

File Added: src/usr.bin/quota/printquota.c
/*	$NetBSD: printquota.c,v 1.1.2.1 2011/01/21 16:58:06 bouyer Exp $	*/

/*
 * Copyright (c) 1980, 1990, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Robert Elz at The University of Melbourne.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\
 The Regents of the University of California.  All rights reserved.");
#endif /* not lint */

#ifndef lint
#if 0
static char sccsid[] = "@(#)quota.c	8.4 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: printquota.c,v 1.1.2.1 2011/01/21 16:58:06 bouyer Exp $");
#endif
#endif /* not lint */

#include <sys/param.h>
#include <sys/types.h>

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <printquota.h>

/*
 * convert 64bit value to a printable string
 */
const char *
intprt(uint64_t val, int flags, int hflag)
{
	static char buf[21];

	if (val == UQUAD_MAX)
		return("-");

	if (flags & HN_B)
		val = dbtob(val);
	
	if (hflag) {
		humanize_number(buf, 6, val, "", HN_AUTOSCALE, flags);
		return buf;
	}
	if (flags & HN_B) {
		/* traditionnal display: blocks are in kilobytes */
		val = val / 1024;
	}
	snprintf(buf, sizeof(buf), "%" PRIu64, val);
	return buf;
}

/*
 * Calculate the grace period and return a printable string for it.
 */
const char *
timeprt(time_t seconds)
{
	time_t hours, minutes;
	static char buf[20];
	static time_t now;

	if (now == 0)
		time(&now);
	if (now > seconds)
		return ("none");
	seconds -= now;
	minutes = (seconds + 30) / 60;
	hours = (minutes + 30) / 60;
	if (hours >= 36) {
		(void)snprintf(buf, sizeof buf, "%ddays",
		    (int)((hours + 12) / 24));
		return (buf);
	}
	if (minutes >= 60) {
		(void)snprintf(buf, sizeof buf, "%2d:%d",
		    (int)(minutes / 60), (int)(minutes % 60));
		return (buf);
	}
	(void)snprintf(buf, sizeof buf, "%2d", (int)minutes);
	return (buf);
}

File Added: src/usr.bin/quota/printquota.h
/*	$NetBSD: printquota.h,v 1.1.2.1 2011/01/21 16:58:06 bouyer Exp $	*/

const char *intprt(uint64_t, int, int);
const char *timeprt(time_t);

cvs diff -r1.14.52.2 -r1.14.52.3 src/usr.bin/quota/quota.1 (expand / switch to unified diff)

--- src/usr.bin/quota/quota.1 2011/01/21 16:36:57 1.14.52.2
+++ src/usr.bin/quota/quota.1 2011/01/21 16:58:06 1.14.52.3
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1.\" $NetBSD: quota.1,v 1.14.52.2 2011/01/21 16:36:57 bouyer Exp $ 1.\" $NetBSD: quota.1,v 1.14.52.3 2011/01/21 16:58:06 bouyer Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1990, 1993 3.\" Copyright (c) 1983, 1990, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
5.\" 5.\"
6.\" This code is derived from software contributed to Berkeley by 6.\" This code is derived from software contributed to Berkeley by
7.\" Robert Elz at The University of Melbourne. 7.\" Robert Elz at The University of Melbourne.
8.\" 8.\"
9.\" Redistribution and use in source and binary forms, with or without 9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions 10.\" modification, are permitted provided that the following conditions
11.\" are met: 11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright 12.\" 1. Redistributions of source code must retain the above copyright
13.\" notice, this list of conditions and the following disclaimer. 13.\" notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright 14.\" 2. Redistributions in binary form must reproduce the above copyright
@@ -125,27 +125,26 @@ flag. @@ -125,27 +125,26 @@ flag.
125.Nm 125.Nm
126tries to report the quotas of all mounted filesystems. 126tries to report the quotas of all mounted filesystems.
127If the filesystem is mounted via 127If the filesystem is mounted via
128.Em NFS 128.Em NFS
129it will attempt to contact the 129it will attempt to contact the
130.Xr rpc.rquotad 8 130.Xr rpc.rquotad 8
131daemon on the 131daemon on the
132.Em NFS 132.Em NFS
133server. 133server.
134If 134If
135.Nm 135.Nm
136exits with a non-zero status, one or more filesystems 136exits with a non-zero status, one or more filesystems
137are over quota. 137are over quota.
138.El 
139.Sh SEE ALSO 138.Sh SEE ALSO
140.Xr quotactl 2 , 139.Xr quotactl 2 ,
141.Xr fstab 5 , 140.Xr fstab 5 ,
142.Xr edquota 8 , 141.Xr edquota 8 ,
143.Xr quotacheck 8 , 142.Xr quotacheck 8 ,
144.Xr quotaon 8 , 143.Xr quotaon 8 ,
145.Xr repquota 8 , 144.Xr repquota 8 ,
146.Xr rpc.rquotad 8 145.Xr rpc.rquotad 8
147.Sh HISTORY 146.Sh HISTORY
148The 147The
149.Nm 148.Nm
150command appeared in 149command appeared in
151.Bx 4.2 . 150.Bx 4.2 .

cvs diff -r1.33.2.1 -r1.33.2.2 src/usr.bin/quota/quota.c (expand / switch to unified diff)

--- src/usr.bin/quota/quota.c 2011/01/20 14:25:05 1.33.2.1
+++ src/usr.bin/quota/quota.c 2011/01/21 16:58:06 1.33.2.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: quota.c,v 1.33.2.1 2011/01/20 14:25:05 bouyer Exp $ */ 1/* $NetBSD: quota.c,v 1.33.2.2 2011/01/21 16:58:06 bouyer 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.
@@ -32,88 +32,88 @@ @@ -32,88 +32,88 @@
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.33.2.1 2011/01/20 14:25:05 bouyer Exp $"); 45__RCSID("$NetBSD: quota.c,v 1.33.2.2 2011/01/21 16:58:06 bouyer 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#include <sys/queue.h> 
59#include <prop/proplib.h> 
60#include <sys/quota.h> 
61 58
62#include <ufs/ufs/quota2_prop.h> 59#include <ufs/ufs/quota2_prop.h>
 60#include <sys/quota.h>
 61
63#include <ctype.h> 62#include <ctype.h>
64#include <err.h> 63#include <err.h>
65#include <errno.h> 64#include <errno.h>
66#include <fstab.h> 65#include <fstab.h>
67#include <grp.h> 66#include <grp.h>
68#include <netdb.h> 67#include <netdb.h>
69#include <pwd.h> 68#include <pwd.h>
70#include <stdio.h> 69#include <stdio.h>
71#include <stdlib.h> 70#include <stdlib.h>
72#include <string.h> 71#include <string.h>
73#include <time.h> 72#include <time.h>
74#include <unistd.h> 73#include <unistd.h>
75 74
76#include <rpc/rpc.h> 75#include <rpc/rpc.h>
77#include <rpc/pmap_prot.h> 76#include <rpc/pmap_prot.h>
78#include <rpcsvc/rquota.h> 77#include <rpcsvc/rquota.h>
79 78
80const char *qfextension[] = INITQFNAMES; 79#include <printquota.h>
81 80
82struct quotause { 81struct quotause {
83 struct quotause *next; 82 struct quotause *next;
84 long flags; 83 long flags;
85 struct quota2_entry q2e; 84 struct quota2_entry q2e;
86 char fsname[MAXPATHLEN + 1]; 85 char fsname[MAXPATHLEN + 1];
87}; 86};
88#define FOUND 0x01 87#define FOUND 0x01
89 88
90int alldigits(char *); 89int alldigits(char *);
91int callaurpc(char *, int, int, int, xdrproc_t, void *, xdrproc_t, void *); 90int callaurpc(char *, int, int, int, xdrproc_t, void *, xdrproc_t, void *);
92int main(int, char **); 91int main(int, char **);
93int getnfsquota(struct statvfs *, struct fstab *, struct quotause *, 92int getnfsquota(struct statvfs *, struct fstab *, struct quotause *,
94 long, int); 93 long, int);
95struct quotause *getprivs(long id, int quotatype); 94struct quotause *getprivs(long id, int quotatype);
96int getufsquota(struct statvfs *, struct quotause *, long, int); 
97void heading(int, u_long, const char *, const char *); 95void heading(int, u_long, const char *, const char *);
98void showgid(gid_t); 96void showgid(gid_t);
99void showgrpname(const char *); 97void showgrpname(const char *);
100void showquotas(int, u_long, const char *); 98void showquotas(int, u_long, const char *);
101void showuid(uid_t); 99void showuid(uid_t);
102void showusrname(const char *); 100void showusrname(const char *);
103const char *intprt(uint64_t, int); 
104const char *timeprt(time_t seconds); 
105void usage(void); 101void usage(void);
106 102
 103extern const char *qfextension[];
 104
 105int getufsquota(const char *, struct quota2_entry *, long, int, int, int);
 106
107int qflag = 0; 107int qflag = 0;
108int vflag = 0; 108int vflag = 0;
109int hflag = 0; 109int hflag = 0;
110int dflag = 0; 110int dflag = 0;
111int Dflag = 0; 111int Dflag = 0;
112uid_t myuid; 112uid_t myuid;
113 113
114int 114int
115main(argc, argv) 115main(argc, argv)
116 int argc; 116 int argc;
117 char *argv[]; 117 char *argv[];
118{ 118{
119 int ngroups;  119 int ngroups;
@@ -393,41 +393,42 @@ showquotas(type, id, name) @@ -393,41 +393,42 @@ showquotas(type, id, name)
393 if (vflag || dflag || 393 if (vflag || dflag ||
394 qup->q2e.q2e_val[Q2V_BLOCK].q2v_cur || 394 qup->q2e.q2e_val[Q2V_BLOCK].q2v_cur ||
395 qup->q2e.q2e_val[Q2V_FILE].q2v_cur) { 395 qup->q2e.q2e_val[Q2V_FILE].q2v_cur) {
396 if (lines++ == 0) 396 if (lines++ == 0)
397 heading(type, id, name, ""); 397 heading(type, id, name, "");
398 nam = qup->fsname; 398 nam = qup->fsname;
399 if (strlen(qup->fsname) > 4) { 399 if (strlen(qup->fsname) > 4) {
400 printf("%s\n", qup->fsname); 400 printf("%s\n", qup->fsname);
401 nam = ""; 401 nam = "";
402 }  402 }
403 printf("%12s%9s%c%8s%9s%8s" 403 printf("%12s%9s%c%8s%9s%8s"
404 , nam 404 , nam
405 , intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_cur 405 , intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_cur
406 ,HN_B) 406 ,HN_B, hflag)
407 , (msgb == NULL) ? ' ' : '*' 407 , (msgb == NULL) ? ' ' : '*'
408 , intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_softlimit 408 , intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_softlimit
409 , HN_B) 409 , HN_B, hflag)
410 , intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_hardlimit 410 , intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_hardlimit
411 , HN_B) 411 , HN_B, hflag)
412 , (msgb == NULL) ? "" 412 , (msgb == NULL) ? ""
413 : timeprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_time)); 413 : timeprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_time));
414 printf("%8s%c%7s%8s%8s\n" 414 printf("%8s%c%7s%8s%8s\n"
415 , intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_cur, 0) 415 , intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_cur
 416 , 0, hflag)
416 , (msgi == NULL) ? ' ' : '*' 417 , (msgi == NULL) ? ' ' : '*'
417 , intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_softlimit 418 , intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_softlimit
418 , 0) 419 , 0, hflag)
419 , intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_hardlimit 420 , intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_hardlimit
420 , 0) 421 , 0, hflag)
421 , (msgi == NULL) ? "" 422 , (msgi == NULL) ? ""
422 : timeprt(qup->q2e.q2e_val[Q2V_FILE].q2v_time) 423 : timeprt(qup->q2e.q2e_val[Q2V_FILE].q2v_time)
423 ); 424 );
424 continue; 425 continue;
425 } 426 }
426 } 427 }
427 if (!qflag && lines == 0) 428 if (!qflag && lines == 0)
428 heading(type, id, name, "none"); 429 heading(type, id, name, "none");
429} 430}
430 431
431void 432void
432heading(type, id, name, tag) 433heading(type, id, name, tag)
433 int type; 434 int type;
@@ -448,232 +449,76 @@ heading(type, id, name, tag) @@ -448,232 +449,76 @@ heading(type, id, name, tag)
448 , "blocks" 449 , "blocks"
449 , "quota" 450 , "quota"
450 , "limit" 451 , "limit"
451 , "grace" 452 , "grace"
452 , "files" 453 , "files"
453 , "quota" 454 , "quota"
454 , "limit" 455 , "limit"
455 , "grace" 456 , "grace"
456 ); 457 );
457 } 458 }
458} 459}
459 460
460/* 461/*
461 * convert 64bit value to a printable string 
462 */ 
463const char * 
464intprt(uint64_t val, int flags) 
465{ 
466 static char buf[21]; 
467 
468 if (val == UQUAD_MAX) 
469 return("-"); 
470 
471 if (flags & HN_B) 
472 val = dbtob(val); 
473  
474 if (hflag) { 
475 humanize_number(buf, 6, val, "", HN_AUTOSCALE, flags); 
476 return buf; 
477 } 
478 if (flags & HN_B) { 
479 /* traditionnal display: blocks are in kilobytes */ 
480 val = val / 1024; 
481 } 
482 snprintf(buf, sizeof(buf), "%" PRIu64, val); 
483 return buf; 
484} 
485 
486/* 
487 * Calculate the grace period and return a printable string for it. 
488 */ 
489const char * 
490timeprt(time_t seconds) 
491{ 
492 time_t hours, minutes; 
493 static char buf[20]; 
494 static time_t now; 
495 
496 if (now == 0) 
497 time(&now); 
498 if (now > seconds) 
499 return ("none"); 
500 seconds -= now; 
501 minutes = (seconds + 30) / 60; 
502 hours = (minutes + 30) / 60; 
503 if (hours >= 36) { 
504 (void)snprintf(buf, sizeof buf, "%ddays", 
505 (int)((hours + 12) / 24)); 
506 return (buf); 
507 } 
508 if (minutes >= 60) { 
509 (void)snprintf(buf, sizeof buf, "%2d:%d", 
510 (int)(minutes / 60), (int)(minutes % 60)); 
511 return (buf); 
512 } 
513 (void)snprintf(buf, sizeof buf, "%2d", (int)minutes); 
514 return (buf); 
515} 
516 
517/* 
518 * Collect the requested quota information. 462 * Collect the requested quota information.
519 */ 463 */
520struct quotause * 464struct quotause *
521getprivs(id, quotatype) 465getprivs(id, quotatype)
522 long id; 466 long id;
523 int quotatype; 467 int quotatype;
524{ 468{
525 struct quotause *qup, *quptail; 469 struct quotause *qup, *quptail;
526 struct quotause *quphead; 470 struct quotause *quphead;
527 struct statvfs *fst; 471 struct statvfs *fst;
528 int nfst, i; 472 int nfst, i;
529 473
530 qup = quphead = quptail = NULL; 474 qup = quphead = quptail = NULL;
531 475
532 nfst = getmntinfo(&fst, MNT_WAIT); 476 nfst = getmntinfo(&fst, MNT_WAIT);
533 if (nfst == 0) 477 if (nfst == 0)
534 errx(2, "no filesystems mounted!"); 478 errx(2, "no filesystems mounted!");
535 setfsent(); 
536 for (i = 0; i < nfst; i++) { 479 for (i = 0; i < nfst; i++) {
537 if (qup == NULL) { 480 if (qup == NULL) {
538 if ((qup = 481 if ((qup =
539 (struct quotause *)malloc(sizeof *qup)) == NULL) 482 (struct quotause *)malloc(sizeof *qup)) == NULL)
540 errx(2, "out of memory"); 483 errx(2, "out of memory");
541 } 484 }
542 if (strncmp(fst[i].f_fstypename, "nfs",  485 if (strncmp(fst[i].f_fstypename, "nfs",
543 sizeof(fst[i].f_fstypename)) == 0) { 486 sizeof(fst[i].f_fstypename)) == 0) {
544 if (getnfsquota(&fst[i], NULL, qup, id, quotatype) == 0) 487 if (getnfsquota(&fst[i], NULL, qup, id, quotatype) == 0)
545 continue; 488 continue;
546 } else if (strncmp(fst[i].f_fstypename, "ffs", 489 } else if (strncmp(fst[i].f_fstypename, "ffs",
547 sizeof(fst[i].f_fstypename)) == 0 && 490 sizeof(fst[i].f_fstypename)) == 0 &&
548 (fst[i].f_flag &ST_QUOTA) != 0) { 491 (fst[i].f_flag & ST_QUOTA) != 0) {
549 if (getufsquota(&fst[i], qup, id, quotatype) == 0) 492 if (getufsquota(fst[i].f_mntonname, &qup->q2e,
 493 id, quotatype, dflag, Dflag) == 0)
550 continue; 494 continue;
551 } else 495 } else
552 continue; 496 continue;
553 (void)strncpy(qup->fsname, fst[i].f_mntonname, 497 (void)strncpy(qup->fsname, fst[i].f_mntonname,
554 sizeof(qup->fsname) - 1); 498 sizeof(qup->fsname) - 1);
555 if (quphead == NULL) 499 if (quphead == NULL)
556 quphead = qup; 500 quphead = qup;
557 else 501 else
558 quptail->next = qup; 502 quptail->next = qup;
559 quptail = qup; 503 quptail = qup;
560 quptail->next = 0; 504 quptail->next = 0;
561 qup = NULL; 505 qup = NULL;
562 } 506 }
563 if (qup) 507 if (qup)
564 free(qup); 508 free(qup);
565 endfsent(); 
566 return (quphead); 509 return (quphead);
567} 510}
568 511
569 
570int 
571getufsquota(struct statvfs *fst, struct quotause *qup, long id, int type) 
572{ 
573 prop_dictionary_t dict, data, cmd; 
574 prop_array_t cmds, datas; 
575 struct plistref pref; 
576 int error; 
577 int8_t error8; 
578 bool ret; 
579 
580 dict = quota2_prop_create(); 
581 cmds = prop_array_create(); 
582 datas = prop_array_create(); 
583 data = prop_dictionary_create(); 
584 
585 if (dict == NULL || cmds == NULL || datas == NULL || data == NULL) 
586 errx(1, "can't allocate proplist"); 
587 
588 if (dflag) 
589 ret = prop_dictionary_set_cstring(data, "id", "default"); 
590 else 
591 ret = prop_dictionary_set_uint32(data, "id", id); 
592 if (!ret) 
593 err(1, "prop_dictionary_set(id)"); 
594  
595 if (!prop_array_add(datas, data)) 
596 err(1, "prop_array_add(data)"); 
597 prop_object_release(data); 
598 if (!quota2_prop_add_command(cmds, "get", qfextension[type], datas)) 
599 err(1, "prop_add_command"); 
600 if (!prop_dictionary_set(dict, "commands", cmds)) 
601 err(1, "prop_dictionary_set(command)"); 
602 if (Dflag) 
603 printf("message to kernel:\n%s\n", 
604 prop_dictionary_externalize(dict)); 
605 
606 if (!prop_dictionary_send_syscall(dict, &pref)) 
607 err(1, "prop_dictionary_send_syscall"); 
608 prop_object_release(dict); 
609 
610 if (quotactl(fst->f_mntonname, &pref) != 0) 
611 err(1, "quotactl"); 
612  
613 if ((error = prop_dictionary_recv_syscall(&pref, &dict)) != 0) { 
614 errx(1, "prop_dictionary_recv_syscall: %s\n", 
615 strerror(error)); 
616 } 
617 if (Dflag) 
618 printf("reply from kernel:\n%s\n", 
619 prop_dictionary_externalize(dict)); 
620 if ((error = quota2_get_cmds(dict, &cmds)) != 0) { 
621 errx(1, "quota2_get_cmds: %s\n", 
622 strerror(error)); 
623 } 
624 /* only one command, no need to iter */ 
625 cmd = prop_array_get(cmds, 0); 
626 if (cmd == NULL) 
627 err(1, "prop_array_get(cmd)"); 
628 
629 if (!prop_dictionary_get_int8(cmd, "return", &error8)) 
630 err(1, "prop_get(return)"); 
631 
632 if (error8) { 
633 if (error8 != ENOENT && error8 != ENODEV) { 
634 if (dflag) 
635 fprintf(stderr, "get default %s quota: %s\n", 
636 qfextension[type], strerror(error8)); 
637 else  
638 fprintf(stderr, "get %s quota for %ld: %s\n", 
639 qfextension[type], id, strerror(error8)); 
640 } 
641 prop_object_release(dict); 
642 return (0); 
643 } 
644 datas = prop_dictionary_get(cmd, "data"); 
645 if (datas == NULL) 
646 err(1, "prop_dict_get(datas)"); 
647 
648 /* only one data, no need to iter */ 
649 if (prop_array_count(datas) == 0) { 
650 /* no quota for this user/group */ 
651 prop_object_release(dict); 
652 return (0); 
653 } 
654  
655 data = prop_array_get(datas, 0); 
656 if (data == NULL) 
657 err(1, "prop_array_get(data)"); 
658 
659 error = quota2_dict_get_q2e_usage(data, &qup->q2e); 
660 if (error) { 
661 errx(1, "quota2_dict_get_q2e_usage: %s\n", 
662 strerror(error)); 
663 } 
664 return (1); 
665} 
666 
667int 512int
668getnfsquota(fst, fs, qup, id, quotatype) 513getnfsquota(fst, fs, qup, id, quotatype)
669 struct statvfs *fst; 514 struct statvfs *fst;
670 struct fstab *fs;  515 struct fstab *fs;
671 struct quotause *qup; 516 struct quotause *qup;
672 long id; 517 long id;
673 int quotatype; 518 int quotatype;
674{ 519{
675 struct getquota_args gq_args; 520 struct getquota_args gq_args;
676 struct ext_getquota_args ext_gq_args; 521 struct ext_getquota_args ext_gq_args;
677 struct getquota_rslt gq_rslt; 522 struct getquota_rslt gq_rslt;
678 struct quota2_entry *q2e = &qup->q2e; 523 struct quota2_entry *q2e = &qup->q2e;
679 struct timeval tv; 524 struct timeval tv;
@@ -803,13 +648,114 @@ callaurpc(host, prognum, versnum, procnu @@ -803,13 +648,114 @@ callaurpc(host, prognum, versnum, procnu
803int 648int
804alldigits(s) 649alldigits(s)
805 char *s; 650 char *s;
806{ 651{
807 int c; 652 int c;
808 653
809 c = *s++; 654 c = *s++;
810 do { 655 do {
811 if (!isdigit(c)) 656 if (!isdigit(c))
812 return (0); 657 return (0);
813 } while ((c = *s++) != 0); 658 } while ((c = *s++) != 0);
814 return (1); 659 return (1);
815} 660}
 661
 662const char *qfextension[] = INITQFNAMES;
 663
 664int
 665getufsquota(const char *mp, struct quota2_entry *q2e, long id, int type,
 666 int defaultq, int debug)
 667{
 668 prop_dictionary_t dict, data, cmd;
 669 prop_array_t cmds, datas;
 670 struct plistref pref;
 671 int error;
 672 int8_t error8;
 673 bool ret;
 674
 675 dict = quota2_prop_create();
 676 cmds = prop_array_create();
 677 datas = prop_array_create();
 678 data = prop_dictionary_create();
 679
 680 if (dict == NULL || cmds == NULL || datas == NULL || data == NULL)
 681 errx(1, "can't allocate proplist");
 682
 683 if (defaultq)
 684 ret = prop_dictionary_set_cstring(data, "id", "default");
 685 else
 686 ret = prop_dictionary_set_uint32(data, "id", id);
 687 if (!ret)
 688 err(1, "prop_dictionary_set(id)");
 689
 690 if (!prop_array_add(datas, data))
 691 err(1, "prop_array_add(data)");
 692 prop_object_release(data);
 693 if (!quota2_prop_add_command(cmds, "get", qfextension[type], datas))
 694 err(1, "prop_add_command");
 695 if (!prop_dictionary_set(dict, "commands", cmds))
 696 err(1, "prop_dictionary_set(command)");
 697 if (debug)
 698 printf("message to kernel:\n%s\n",
 699 prop_dictionary_externalize(dict));
 700
 701 if (!prop_dictionary_send_syscall(dict, &pref))
 702 err(1, "prop_dictionary_send_syscall");
 703 prop_object_release(dict);
 704
 705 if (quotactl(mp, &pref) != 0)
 706 err(1, "quotactl");
 707
 708 if ((error = prop_dictionary_recv_syscall(&pref, &dict)) != 0) {
 709 errx(1, "prop_dictionary_recv_syscall: %s\n",
 710 strerror(error));
 711 }
 712 if (debug)
 713 printf("reply from kernel:\n%s\n",
 714 prop_dictionary_externalize(dict));
 715 if ((error = quota2_get_cmds(dict, &cmds)) != 0) {
 716 errx(1, "quota2_get_cmds: %s\n",
 717 strerror(error));
 718 }
 719 /* only one command, no need to iter */
 720 cmd = prop_array_get(cmds, 0);
 721 if (cmd == NULL)
 722 err(1, "prop_array_get(cmd)");
 723
 724 if (!prop_dictionary_get_int8(cmd, "return", &error8))
 725 err(1, "prop_get(return)");
 726
 727 if (error8) {
 728 if (error8 != ENOENT && error8 != ENODEV) {
 729 if (defaultq)
 730 fprintf(stderr, "get default %s quota: %s\n",
 731 qfextension[type], strerror(error8));
 732 else
 733 fprintf(stderr, "get %s quota for %ld: %s\n",
 734 qfextension[type], id, strerror(error8));
 735 }
 736 prop_object_release(dict);
 737 return (0);
 738 }
 739 datas = prop_dictionary_get(cmd, "data");
 740 if (datas == NULL)
 741 err(1, "prop_dict_get(datas)");
 742
 743 /* only one data, no need to iter */
 744 if (prop_array_count(datas) == 0) {
 745 /* no quota for this user/group */
 746 prop_object_release(dict);
 747 return (0);
 748 }
 749
 750 data = prop_array_get(datas, 0);
 751 if (data == NULL)
 752 err(1, "prop_array_get(data)");
 753
 754 error = quota2_dict_get_q2e_usage(data, q2e);
 755 if (error) {
 756 errx(1, "quota2_dict_get_q2e_usage: %s\n",
 757 strerror(error));
 758 }
 759 prop_object_release(dict);
 760 return (1);
 761}

cvs diff -r1.5 -r1.5.64.1 src/usr.sbin/repquota/Makefile (expand / switch to unified diff)

--- src/usr.sbin/repquota/Makefile 1997/10/18 04:37:59 1.5
+++ src/usr.sbin/repquota/Makefile 2011/01/21 16:58:06 1.5.64.1
@@ -1,7 +1,18 @@ @@ -1,7 +1,18 @@
1# from: @(#)Makefile 8.1 (Berkeley) 6/6/93 1# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
2# $NetBSD: Makefile,v 1.5 1997/10/18 04:37:59 lukem Exp $ 2# $NetBSD: Makefile,v 1.5.64.1 2011/01/21 16:58:06 bouyer Exp $
3 3
 4.include <bsd.own.mk>
4PROG= repquota 5PROG= repquota
 6SRCS= repquota.c
5MAN= repquota.8 7MAN= repquota.8
6 8
 9CPPFLAGS+=-I${NETBSDSRCDIR}/sys -I${NETBSDSRCDIR}/usr.bin/quota
 10DPADD= ${LIBPROP}
 11LDADD= -lprop
 12
 13.PATH: ${NETBSDSRCDIR}/usr.bin/quota
 14SRCS+= printquota.c
 15.PATH: ${NETBSDSRCDIR}/sys/ufs/ufs
 16SRCS+= quota2_prop.c
 17
7.include <bsd.prog.mk> 18.include <bsd.prog.mk>

cvs diff -r1.9 -r1.9.50.1 src/usr.sbin/repquota/repquota.8 (expand / switch to unified diff)

--- src/usr.sbin/repquota/repquota.8 2003/08/07 11:25:41 1.9
+++ src/usr.sbin/repquota/repquota.8 2011/01/21 16:58:07 1.9.50.1
@@ -19,81 +19,80 @@ @@ -19,81 +19,80 @@
19.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29.\" SUCH DAMAGE. 29.\" SUCH DAMAGE.
30.\" 30.\"
31.\" from: @(#)repquota.8 8.1 (Berkeley) 6/6/93 31.\" from: @(#)repquota.8 8.1 (Berkeley) 6/6/93
32.\" $NetBSD: repquota.8,v 1.9 2003/08/07 11:25:41 agc Exp $ 32.\" $NetBSD: repquota.8,v 1.9.50.1 2011/01/21 16:58:07 bouyer Exp $
33.\" 33.\"
34.Dd June 6, 1993 34.Dd January 21, 2011
35.Dt REPQUOTA 8 35.Dt REPQUOTA 8
36.Os 36.Os
37.Sh NAME 37.Sh NAME
38.Nm repquota 38.Nm repquota
39.Nd summarize quotas for a file system 39.Nd summarize quotas for a file system
40.Sh SYNOPSIS 40.Sh SYNOPSIS
41.Nm 41.Nm
 42.Op Fl h
 43.Op Fl D
42.Op Fl g 44.Op Fl g
43.Op Fl u 45.Op Fl u
44.Op Fl v 46.Op Fl v
45.Ar filesystem Ar ... 47.Ar filesystem Ar ...
46.Nm 48.Nm
 49.Op Fl h
 50.Op Fl D
47.Op Fl g 51.Op Fl g
48.Op Fl u 52.Op Fl u
49.Op Fl v 53.Op Fl v
50.Fl a 54.Fl a
51.Sh DESCRIPTION 55.Sh DESCRIPTION
52.Nm 56.Nm
53prints a summary of the disk usage and quotas for the 57prints a summary of the disk usage and quotas for the
54specified file systems. 58specified file systems.
55.Pp 59.Pp
56Available options: 60Available options:
57.Bl -tag -width Ds 61.Bl -tag -width Ds
58.It Fl a 62.It Fl a
59Print the quotas of all the filesystems listed in 63Print the quotas of all the mounted filesystems.
60.Pa /etc/fstab . 
61.It Fl g 64.It Fl g
62Print only group quotas (the default is to print both 65Print only group quotas (the default is to print both
63group and user quotas if they exist). 66group and user quotas if they exist).
64.It Fl u 67.It Fl u
65Print only user quotas (the default is to print both 68Print only user quotas (the default is to print both
66group and user quotas if they exist). 69group and user quotas if they exist).
67.It Fl v 70.It Fl v
68Print a header line before printing each filesystem quotas. 71Print a header line before printing each filesystem quotas.
 72.It Fl D
 73Debug: print plist sent to and received from kernel.
 74.It Fl h
 75Numbers are displayed in a human readable format.
69.El 76.El
70.Pp 77.Pp
71For each user or group, the current 78For each user or group, the current
72number files and amount of space (in kilobytes) is 79number files and amount of space (in kilobytes, unless the
 80.Fl h
 81flag is used) is
73printed, along with any quotas created with 82printed, along with any quotas created with
74.Xr edquota 8 . 83.Xr edquota 8 .
75.Pp 84.Pp
76Only members of the operator group or the super-user may 85Only the super-user may use this command.
77use this command. 
78.Sh FILES 
79.Bl -tag -width quota.group -compact 
80.It Pa quota.user 
81at the filesystem root with user quotas 
82.It Pa quota.group 
83at the filesystem root with group quotas 
84.It Pa /etc/fstab 
85for file system names and locations 
86.El 
87.Sh DIAGNOSTICS 86.Sh DIAGNOSTICS
88Various messages about inaccessible files; self-explanatory. 87Various messages about inaccessible files; self-explanatory.
89.Sh SEE ALSO 88.Sh SEE ALSO
90.Xr quota 1 , 89.Xr quota 1 ,
91.Xr quotactl 2 , 90.Xr quotactl 2 ,
92.Xr fstab 5 , 91.Xr fstab 5 ,
93.Xr edquota 8 , 92.Xr edquota 8 ,
94.Xr quotacheck 8 , 93.Xr quotacheck 8 ,
95.Xr quotaon 8 94.Xr quotaon 8
96.Sh HISTORY 95.Sh HISTORY
97The 96The
98.Nm 97.Nm
99command appeared in 98command appeared in

cvs diff -r1.25 -r1.25.2.1 src/usr.sbin/repquota/repquota.c (expand / switch to unified diff)

--- src/usr.sbin/repquota/repquota.c 2010/02/17 18:55:14 1.25
+++ src/usr.sbin/repquota/repquota.c 2011/01/21 16:58:07 1.25.2.1
@@ -30,239 +30,401 @@ @@ -30,239 +30,401 @@
30 * SUCH DAMAGE. 30 * SUCH DAMAGE.
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34#ifndef lint 34#ifndef lint
35__COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\ 35__COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\
36 The Regents of the University of California. All rights reserved."); 36 The Regents of the University of California. All rights reserved.");
37#endif /* not lint */ 37#endif /* not lint */
38 38
39#ifndef lint 39#ifndef lint
40#if 0 40#if 0
41static char sccsid[] = "@(#)repquota.c 8.2 (Berkeley) 11/22/94"; 41static char sccsid[] = "@(#)repquota.c 8.2 (Berkeley) 11/22/94";
42#else 42#else
43__RCSID("$NetBSD: repquota.c,v 1.25 2010/02/17 18:55:14 bouyer Exp $"); 43__RCSID("$NetBSD: repquota.c,v 1.25.2.1 2011/01/21 16:58:07 bouyer Exp $");
44#endif 44#endif
45#endif /* not lint */ 45#endif /* not lint */
46 46
47/* 47/*
48 * Quota report 48 * Quota report
49 */ 49 */
50#include <sys/param.h> 50#include <sys/param.h>
51#include <sys/stat.h> 51#include <sys/stat.h>
52#include <sys/queue.h> 52#include <sys/types.h>
53#include <ufs/ufs/quota.h> 53#include <sys/statvfs.h>
 54#include <prop/proplib.h>
 55#include <sys/quota.h>
 56
54#include <errno.h> 57#include <errno.h>
 58#include <err.h>
55#include <fstab.h> 59#include <fstab.h>
56#include <grp.h> 60#include <grp.h>
57#include <pwd.h> 61#include <pwd.h>
58#include <stdio.h> 62#include <stdio.h>
59#include <stdlib.h> 63#include <stdlib.h>
60#include <string.h> 64#include <string.h>
61#include <unistd.h> 65#include <unistd.h>
62 66
63const char *qfname = QUOTAFILENAME; 67#include <ufs/ufs/quota2_prop.h>
 68#include <ufs/ufs/quota1.h>
 69
 70#include <printquota.h>
 71
64const char *qfextension[] = INITQFNAMES; 72const char *qfextension[] = INITQFNAMES;
 73const char *qfname = QUOTAFILENAME;
65 74
66struct fileusage { 75struct fileusage {
67 struct fileusage *fu_next; 76 struct fileusage *fu_next;
68 struct dqblk fu_dqblk; 77 struct quota2_entry fu_q2e;
69 u_long fu_id; 78 u_long fu_id;
70 char fu_name[1]; 79 char fu_name[1];
71 /* actually bigger */ 80 /* actually bigger */
72}; 81};
73#define FUHASH 1024 /* must be power of two */ 82#define FUHASH 1024 /* must be power of two */
74struct fileusage *fuhead[MAXQUOTAS][FUHASH]; 83struct fileusage *fuhead[MAXQUOTAS][FUHASH];
75u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */ 84u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */
 85struct quota2_entry defaultq2e[MAXQUOTAS];
76 86
77int vflag; /* verbose */ 87int vflag = 0; /* verbose */
78int aflag; /* all file systems */ 88int aflag = 0; /* all file systems */
79 89int Dflag = 0; /* debug */
80struct fileusage *addid __P((u_long, int, const char *)); 90int hflag = 0; /* debug */
81int hasquota __P((struct fstab *, int, char **)); 91
82struct fileusage *lookup __P((u_long, int)); 92struct fileusage *addid(u_long, int, const char *);
83int main __P((int, char **)); 93int hasquota(struct fstab *, int, char **);
84int oneof __P((const char *, char **, int)); 94struct fileusage *lookup(u_long, int);
85int repquota __P((struct fstab *, int, char *)); 95int main(int, char **);
86const char *timeprt __P((time_t)); 96int oneof(const char *, char **, int);
87void usage __P((void)); 97int repquota(const struct statvfs *, int);
 98int repquota2(const struct statvfs *, int);
 99int repquota1(const struct statvfs *, int);
 100void usage(void);
 101void printquotas(int, const struct statvfs *);
 102void dqblk2q2e(const struct dqblk *, struct quota2_entry *);
88 103
89int 104int
90main(argc, argv) 105main(argc, argv)
91 int argc; 106 int argc;
92 char **argv; 107 char **argv;
93{ 108{
94 struct fstab *fs; 
95 struct passwd *pw; 109 struct passwd *pw;
96 struct group *gr; 110 struct group *gr;
97 int gflag = 0, uflag = 0, errs = 0; 111 int gflag = 0, uflag = 0, errs = 0;
98 long i, argnum, done = 0; 112 long i, argnum, done = 0;
99 char *qfnp; 
100 int ch; 113 int ch;
 114 struct statvfs *fst;
 115 int nfst;
101 116
102 while ((ch = getopt(argc, argv, "aguv")) != -1) { 117 while ((ch = getopt(argc, argv, "Daguhv")) != -1) {
103 switch(ch) { 118 switch(ch) {
104 case 'a': 119 case 'a':
105 aflag++; 120 aflag++;
106 break; 121 break;
107 case 'g': 122 case 'g':
108 gflag++; 123 gflag++;
109 break; 124 break;
110 case 'u': 125 case 'u':
111 uflag++; 126 uflag++;
112 break; 127 break;
 128 case 'h':
 129 hflag++;
 130 break;
113 case 'v': 131 case 'v':
114 vflag++; 132 vflag++;
115 break; 133 break;
 134 case 'D':
 135 Dflag++;
 136 break;
116 default: 137 default:
117 usage(); 138 usage();
118 } 139 }
119 } 140 }
120 argc -= optind; 141 argc -= optind;
121 argv += optind; 142 argv += optind;
122 if (argc == 0 && !aflag) 143 if (argc == 0 && !aflag)
123 usage(); 144 usage();
124 if (!gflag && !uflag) { 145 if (!gflag && !uflag) {
125 if (aflag) 146 if (aflag)
126 gflag++; 147 gflag++;
127 uflag++; 148 uflag++;
128 } 149 }
129 if (gflag) { 150 if (gflag) {
130 setgrent(); 151 setgrent();
131 while ((gr = getgrent()) != 0) 152 while ((gr = getgrent()) != 0)
132 (void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name); 153 (void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name);
133 endgrent(); 154 endgrent();
134 } 155 }
135 if (uflag) { 156 if (uflag) {
136 setpwent(); 157 setpwent();
137 while ((pw = getpwent()) != 0) 158 while ((pw = getpwent()) != 0)
138 (void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name); 159 (void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name);
139 endpwent(); 160 endpwent();
140 } 161 }
141 setfsent(); 162
142 while ((fs = getfsent()) != NULL) { 163 nfst = getmntinfo(&fst, MNT_WAIT);
143 if (strcmp(fs->fs_vfstype, "ffs")) 164 if (nfst == 0)
 165 errx(2, "no filesystems mounted!");
 166 for (i = 0; i < nfst; i++) {
 167 if (strncmp(fst[i].f_fstypename, "ffs",
 168 sizeof(fst[i].f_fstypename)) != 0 ||
 169 (fst[i].f_flag & ST_QUOTA) == 0)
144 continue; 170 continue;
145 if (aflag) { 171 if (aflag) {
146 if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) 172 if (gflag)
147 errs += repquota(fs, GRPQUOTA, qfnp); 173 errs += repquota(&fst[i], GRPQUOTA);
148 if (uflag && hasquota(fs, USRQUOTA, &qfnp)) 174 if (uflag)
149 errs += repquota(fs, USRQUOTA, qfnp); 175 errs += repquota(&fst[i], USRQUOTA);
150 continue; 176 continue;
151 } 177 }
152 if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || 178 if ((argnum = oneof(fst[i].f_mntonname, argv, argc)) >= 0 ||
153 (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) { 179 (argnum = oneof(fst[i].f_mntfromname, argv, argc)) >= 0) {
154 done |= 1 << argnum; 180 done |= 1 << argnum;
155 if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) 181 if (gflag)
156 errs += repquota(fs, GRPQUOTA, qfnp); 182 errs += repquota(&fst[i], GRPQUOTA);
157 if (uflag && hasquota(fs, USRQUOTA, &qfnp)) 183 if (uflag)
158 errs += repquota(fs, USRQUOTA, qfnp); 184 errs += repquota(&fst[i], USRQUOTA);
159 } 185 }
160 } 186 }
161 endfsent(); 
162 for (i = 0; i < argc; i++) 187 for (i = 0; i < argc; i++)
163 if ((done & (1 << i)) == 0) 188 if ((done & (1 << i)) == 0)
164 fprintf(stderr, "%s not found in fstab\n", argv[i]); 189 fprintf(stderr, "%s not mounted\n", argv[i]);
165 exit(errs); 190 exit(errs);
166} 191}
167 192
168void 193void
169usage() 194usage()
170{ 195{
171 fprintf(stderr, "usage:\n\t%s\n\t%s\n", 196 fprintf(stderr, "usage:\n\t%s\n\t%s\n",
172 "repquota [-v] [-g] [-u] -a", 197 "repquota [-D] [-v] [-g] [-u] -a",
173 "repquota [-v] [-g] [-u] filesys ..."); 198 "repquota [-D] [-v] [-g] [-u] filesys ...");
174 exit(1); 199 exit(1);
175} 200}
176 201
177int 202int
178repquota(fs, type, qfpathname) 203repquota(const struct statvfs *vfs, int type)
179 struct fstab *fs; 204{
180 int type; 205 if (repquota2(vfs, type) != 0)
181 char *qfpathname; 206 return (repquota1(vfs, type));
 207 return 0;
 208}
 209
 210int
 211repquota2(const struct statvfs *vfs, int type)
182{ 212{
 213 prop_dictionary_t dict, data, cmd;
 214 prop_array_t cmds, datas;
 215 struct plistref pref;
 216 int error;
 217 int8_t error8;
 218 prop_object_iterator_t iter;
 219 struct quota2_entry *q2ep;
 220 struct fileusage *fup;
 221 const char *strid;
 222 uint32_t id;
 223
 224 dict = quota2_prop_create();
 225 cmds = prop_array_create();
 226 datas = prop_array_create();
 227
 228 if (dict == NULL || cmds == NULL || datas == NULL)
 229 errx(1, "can't allocate proplist");
 230 if (!quota2_prop_add_command(cmds, "getall", qfextension[type], datas))
 231 err(1, "prop_add_command");
 232 if (!prop_dictionary_set(dict, "commands", cmds))
 233 err(1, "prop_dictionary_set(command)");
 234 if (Dflag)
 235 printf("message to kernel:\n%s\n",
 236 prop_dictionary_externalize(dict));
 237 if (!prop_dictionary_send_syscall(dict, &pref))
 238 err(1, "prop_dictionary_send_syscall");
 239 prop_object_release(dict);
 240
 241 if (quotactl(vfs->f_mntonname, &pref) != 0)
 242 err(1, "quotactl");
 243
 244 if ((error = prop_dictionary_recv_syscall(&pref, &dict)) != 0) {
 245 errx(1, "prop_dictionary_recv_syscall: %s\n",
 246 strerror(error));
 247 }
 248 if (Dflag)
 249 printf("reply from kernel:\n%s\n",
 250 prop_dictionary_externalize(dict));
 251 if ((error = quota2_get_cmds(dict, &cmds)) != 0) {
 252 errx(1, "quota2_get_cmds: %s\n",
 253 strerror(error));
 254 }
 255 /* only one command, no need to iter */
 256 cmd = prop_array_get(cmds, 0);
 257 if (cmd == NULL)
 258 err(1, "prop_array_get(cmd)");
 259
 260 if (!prop_dictionary_get_int8(cmd, "return", &error8))
 261 err(1, "prop_get(return)");
 262
 263 if (error8) {
 264 prop_object_release(dict);
 265 if (error8 != EOPNOTSUPP) {
 266 fprintf(stderr, "get %s quotas: %s\n",
 267 qfextension[type], strerror(error8));
 268 }
 269 return (error8);
 270 }
 271 datas = prop_dictionary_get(cmd, "data");
 272 if (datas == NULL)
 273 err(1, "prop_dict_get(datas)");
 274
 275 iter = prop_array_iterator(datas);
 276 if (iter == NULL)
 277 err(1, "prop_array_iterator");
 278
 279 while ((data = prop_object_iterator_next(iter)) != NULL) {
 280 strid = NULL;
 281 if (!prop_dictionary_get_uint32(data, "id", &id)) {
 282 if (!prop_dictionary_get_cstring_nocopy(data, "id",
 283 &strid))
 284 errx(1, "can't find id in quota entry");
 285 if (strcmp(strid, "default") != 0) {
 286 errx(1, "wrong id string %s in quota entry",
 287 strid);
 288 }
 289 q2ep = &defaultq2e[type];
 290 } else {
 291 if ((fup = lookup(id, type)) == 0)
 292 fup = addid(id, type, (char *)0);
 293 q2ep = &fup->fu_q2e;
 294 q2ep->q2e_uid = id;
 295 }
 296
 297 error = quota2_dict_get_q2e_usage(data, q2ep);
 298 if (error) {
 299 errx(1, "quota2_dict_get_q2e_usage: %s\n",
 300 strerror(error));
 301 }
 302 }
 303 prop_object_iterator_release(iter);
 304 prop_object_release(dict);
 305 printquotas(type, vfs);
 306 return (0);
 307}
 308
 309int repquota1(const struct statvfs *vfs, int type)
 310{
 311 char *qfpathname;
 312 struct fstab *fs;
183 struct fileusage *fup; 313 struct fileusage *fup;
184 FILE *qf; 314 FILE *qf;
185 u_long id; 315 u_long id;
186 struct dqblk dqbuf; 316 struct dqblk dqbuf;
187 static struct dqblk zerodqblk; 
188 static int warned = 0; 
189 static int multiple = 0; 
190 317
 318#if 0
 319 static int warned = 0;
191 if (quotactl(fs->fs_file, QCMD(Q_SYNC, type), 0, 0) < 0 && 320 if (quotactl(fs->fs_file, QCMD(Q_SYNC, type), 0, 0) < 0 &&
192 errno == EOPNOTSUPP && !warned && vflag) { 321 errno == EOPNOTSUPP && !warned && vflag) {
193 warned++; 322 warned++;
194 fprintf(stdout, 323 fprintf(stdout,
195 "*** Warning: Quotas are not compiled into this kernel\n"); 324 "*** Warning: Quotas are not compiled into this kernel\n");
196 } 325 }
197 if (multiple++) 326#endif
198 printf("\n"); 327 setfsent();
199 if (vflag) 328 while ((fs = getfsent()) != NULL) {
200 fprintf(stdout, "*** Report for %s quotas on %s (%s)\n", 329 if (strcmp(fs->fs_vfstype, "ffs") == 0 &&
201 qfextension[type], fs->fs_file, fs->fs_spec); 330 strcmp(fs->fs_file, vfs->f_mntonname) == 0)
 331 break;
 332 }
 333 endfsent();
 334 if (fs == NULL) {
 335 fprintf(stderr, "%s not found in fstab\n", vfs->f_mntonname);
 336 return 1;
 337 }
 338 if (!hasquota(fs, type, &qfpathname))
 339 return 0;
 340
202 if ((qf = fopen(qfpathname, "r")) == NULL) { 341 if ((qf = fopen(qfpathname, "r")) == NULL) {
203 perror(qfpathname); 342 perror(qfpathname);
204 return (1); 343 return (1);
205 } 344 }
206 for (id = 0; ; id++) { 345 for (id = 0; ; id++) {
207 fread(&dqbuf, sizeof(struct dqblk), 1, qf); 346 fread(&dqbuf, sizeof(struct dqblk), 1, qf);
208 if (feof(qf)) 347 if (feof(qf))
209 break; 348 break;
210 if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0) 349 if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0)
211 continue; 350 continue;
212 if ((fup = lookup(id, type)) == 0) 351 if ((fup = lookup(id, type)) == 0)
213 fup = addid(id, type, (char *)0); 352 fup = addid(id, type, (char *)0);
214 fup->fu_dqblk = dqbuf; 353 dqblk2q2e(&dqbuf, &fup->fu_q2e);
215 } 354 }
216 fclose(qf); 355 fclose(qf);
 356 printquotas(type, vfs);
 357 return (0);
 358}
 359
 360void
 361printquotas(int type, const struct statvfs *vfs)
 362{
 363 static int multiple = 0;
 364 u_long id;
 365 struct fileusage *fup;
 366
 367 if (multiple++)
 368 printf("\n");
 369 if (vflag)
 370 fprintf(stdout, "*** Report for %s quotas on %s (%s)\n",
 371 qfextension[type], vfs->f_mntonname, vfs->f_mntfromname);
217 printf(" Block limits File limits\n"); 372 printf(" Block limits File limits\n");
218 printf(type == USRQUOTA ? "User " : "Group"); 373 printf(type == USRQUOTA ? "User " : "Group");
219 printf(" used soft hard grace used soft hard grace\n"); 374 printf(" used soft hard grace used soft hard grace\n");
220 for (id = 0; id <= highid[type]; id++) { 375 for (id = 0; id <= highid[type]; id++) {
221 fup = lookup(id, type); 376 fup = lookup(id, type);
222 if (fup == 0) 377 if (fup == 0)
223 continue; 378 continue;
224 if (fup->fu_dqblk.dqb_curinodes == 0 && 379 if (fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_cur == 0 &&
225 fup->fu_dqblk.dqb_curblocks == 0) 380 fup->fu_q2e.q2e_val[Q2V_FILE].q2v_cur == 0)
226 continue; 381 continue;
227 if (strlen(fup->fu_name) > 9) 382 if (strlen(fup->fu_name) > 9)
228 printf("%s ", fup->fu_name); 383 printf("%s ", fup->fu_name);
229 else 384 else
230 printf("%-10s", fup->fu_name); 385 printf("%-10s", fup->fu_name);
231 printf("%c%c%9d%9d%9d%7s", 386 printf("%c%c%9s%9s%9s%7s",
232 fup->fu_dqblk.dqb_bsoftlimit &&  387 fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_softlimit &&
233 fup->fu_dqblk.dqb_curblocks >=  388 fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_cur >=
234 fup->fu_dqblk.dqb_bsoftlimit ? '+' : '-', 389 fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_softlimit ?
235 fup->fu_dqblk.dqb_isoftlimit && 390 '+' : '-',
236 fup->fu_dqblk.dqb_curinodes >= 391 fup->fu_q2e.q2e_val[Q2V_FILE].q2v_softlimit &&
237 fup->fu_dqblk.dqb_isoftlimit ? '+' : '-', 392 fup->fu_q2e.q2e_val[Q2V_FILE].q2v_cur >=
238 (int)(dbtob((u_quad_t)fup->fu_dqblk.dqb_curblocks) / 1024), 393 fup->fu_q2e.q2e_val[Q2V_FILE].q2v_softlimit ?
239 (int)(dbtob((u_quad_t)fup->fu_dqblk.dqb_bsoftlimit) / 1024), 394 '+' : '-',
240 (int)(dbtob((u_quad_t)fup->fu_dqblk.dqb_bhardlimit) / 1024), 395 intprt(fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_cur,
241 fup->fu_dqblk.dqb_bsoftlimit &&  396 HN_B, hflag),
242 fup->fu_dqblk.dqb_curblocks >=  397 intprt(fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_softlimit,
243 fup->fu_dqblk.dqb_bsoftlimit ? 398 HN_B, hflag),
244 timeprt(fup->fu_dqblk.dqb_btime) : ""); 399 intprt(fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_hardlimit,
245 printf(" %8d%8d%8d%7s\n", 400 HN_B, hflag),
246 fup->fu_dqblk.dqb_curinodes, 401 (fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_softlimit &&
247 fup->fu_dqblk.dqb_isoftlimit, 402 fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_cur >=
248 fup->fu_dqblk.dqb_ihardlimit, 403 fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_softlimit) ?
249 fup->fu_dqblk.dqb_isoftlimit && 404 timeprt(fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_time) : "");
250 fup->fu_dqblk.dqb_curinodes >= 405 printf(" %8s%8s%8s%7s\n",
251 fup->fu_dqblk.dqb_isoftlimit ? 406 intprt(fup->fu_q2e.q2e_val[Q2V_FILE].q2v_cur,
252 timeprt(fup->fu_dqblk.dqb_itime) : ""); 407 0, hflag),
253 fup->fu_dqblk = zerodqblk; 408 intprt(fup->fu_q2e.q2e_val[Q2V_FILE].q2v_softlimit,
 409 0, hflag),
 410 intprt(fup->fu_q2e.q2e_val[Q2V_FILE].q2v_hardlimit,
 411 0, hflag),
 412 (fup->fu_q2e.q2e_val[Q2V_FILE].q2v_softlimit &&
 413 fup->fu_q2e.q2e_val[Q2V_FILE].q2v_cur >=
 414 fup->fu_q2e.q2e_val[Q2V_FILE].q2v_softlimit) ?
 415 timeprt(fup->fu_q2e.q2e_val[Q2V_FILE].q2v_time) : "");
 416 memset(&fup->fu_q2e, 0, sizeof(fup->fu_q2e));
254 } 417 }
255 return (0); 
256} 418}
257 419
258/* 420/*
259 * Check to see if target appears in list of size cnt. 421 * Check to see if target appears in list of size cnt.
260 */ 422 */
261int 423int
262oneof(target, list, cnt) 424oneof(target, list, cnt)
263 const char *target; 425 const char *target;
264 char *list[]; 426 char *list[];
265 int cnt; 427 int cnt;
266{ 428{
267 int i; 429 int i;
268 430
@@ -355,43 +517,26 @@ addid(id, type, name) @@ -355,43 +517,26 @@ addid(id, type, name)
355 fup->fu_next = *fhp; 517 fup->fu_next = *fhp;
356 *fhp = fup; 518 *fhp = fup;
357 fup->fu_id = id; 519 fup->fu_id = id;
358 if (id > highid[type]) 520 if (id > highid[type])
359 highid[type] = id; 521 highid[type] = id;
360 if (name) { 522 if (name) {
361 memmove(fup->fu_name, name, len + 1); 523 memmove(fup->fu_name, name, len + 1);
362 } else { 524 } else {
363 sprintf(fup->fu_name, "%lu", (u_long)id); 525 sprintf(fup->fu_name, "%lu", (u_long)id);
364 } 526 }
365 return (fup); 527 return (fup);
366} 528}
367 529
368/* 530void
369 * Calculate the grace period and return a printable string for it. 531dqblk2q2e(const struct dqblk *dqblk, struct quota2_entry *q2e)
370 */ 532{
371const char * 533 q2e->q2e_val[Q2V_BLOCK].q2v_hardlimit = dqblk->dqb_bhardlimit;
372timeprt(seconds) 534 q2e->q2e_val[Q2V_BLOCK].q2v_softlimit = dqblk->dqb_bsoftlimit;
373 time_t seconds; 535 q2e->q2e_val[Q2V_BLOCK].q2v_cur = dqblk->dqb_curblocks;
374{ 536 q2e->q2e_val[Q2V_BLOCK].q2v_time = dqblk->dqb_btime;
375 time_t hours, minutes; 537
376 static char buf[20]; 538 q2e->q2e_val[Q2V_FILE].q2v_hardlimit = dqblk->dqb_ihardlimit;
377 static time_t now; 539 q2e->q2e_val[Q2V_FILE].q2v_softlimit = dqblk->dqb_isoftlimit;
378 540 q2e->q2e_val[Q2V_FILE].q2v_cur = dqblk->dqb_curinodes;
379 if (now == 0) 541 q2e->q2e_val[Q2V_FILE].q2v_time = dqblk->dqb_itime;
380 time(&now); 542}
381 if (now > seconds) 
382 return ("none"); 
383 seconds -= now; 
384 minutes = (seconds + 30) / 60; 
385 hours = (minutes + 30) / 60; 
386 if (hours >= 36) { 
387 sprintf(buf, "%lddays", (long)((hours + 12) / 24)); 
388 return (buf); 
389 } 
390 if (minutes >= 60) { 
391 sprintf(buf, "%2ld:%ld", (long)(minutes / 60), 
392 (long)(minutes % 60)); 
393 return (buf); 
394 } 
395 sprintf(buf, "%2ld", (long)minutes); 
396 return (buf); 
397}