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
--- 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,4 +1,4 @@
-/* $NetBSD: quota2.h,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $ */
+/* $NetBSD: quota2.h,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */
/*-
* Copyright (c) 2010 Manuel Bouyer
* All rights reserved.
@@ -97,5 +97,4 @@
/* quota2_subr.c */
void quota2_addfreeq2e(struct quota2_header *, void *, uint64_t, uint64_t, int);
void quota2_create_blk0(uint64_t, void *bp, int, int, int);
-
#endif /* _UFS_UFS_QUOTA2_H_ */
--- 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,4 +1,4 @@
-/* $NetBSD: quota2_prop.c,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $ */
+/* $NetBSD: quota2_prop.c,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */
/*-
* Copyright (c) 2010 Manuel Bouyer
* All rights reserved.
@@ -95,8 +95,6 @@
{
int i, error;
prop_dictionary_t val;
- if (!prop_dictionary_get_uint32(data, "id", &q2e->q2e_uid))
- return EINVAL;
for (i = 0; i < NQ2V; i++) {
val = prop_dictionary_get_dict(data, quota2_valnames[i]);
if (val == NULL)
@@ -135,6 +133,16 @@
return 0;
}
+bool
+prop_array_add_and_rel(prop_array_t array, prop_object_t po)
+{
+ bool ret;
+ if (po == NULL)
+ return false;
+ ret = prop_array_add(array, po);
+ prop_object_release(po);
+ return ret;
+}
bool
prop_dictionary_set_and_rel(prop_dictionary_t dict, const char *key,
--- 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,4 +1,4 @@
-/* $NetBSD: quota2_prop.h,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $ */
+/* $NetBSD: quota2_prop.h,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */
/*-
* Copyright (c) 2010 Manuel Bouyer
* All rights reserved.
@@ -36,6 +36,7 @@
int quota2_dict_get_q2e_usage(prop_dictionary_t, struct quota2_entry *);
int quota2_get_cmds(prop_dictionary_t, prop_array_t *);
+bool prop_array_add_and_rel(prop_array_t, prop_object_t);
bool prop_dictionary_set_and_rel(prop_dictionary_t, const char *,
prop_object_t);
prop_dictionary_t quota2_prop_create(void);
--- 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,4 +1,4 @@
-/* $NetBSD: ufs_quota.h,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $ */
+/* $NetBSD: ufs_quota.h,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */
/*
* Copyright (c) 1982, 1986, 1990, 1993, 1995
@@ -96,8 +96,8 @@
*/
#define NODQUOT NULL
-static kmutex_t dqlock;
-static kcondvar_t dqcv;
+extern kmutex_t dqlock;
+extern kcondvar_t dqcv;
/*
* Quota name to error message mapping.
*/
@@ -128,8 +128,9 @@
int chkdq2(struct inode *, int64_t, kauth_cred_t, int);
int chkiq2(struct inode *, int32_t, kauth_cred_t, int);
-int quota2_handle_cmd_get(struct ufsmount *, const char *, int, int,
+int quota2_handle_cmd_get(struct ufsmount *, int, int, int,
prop_array_t);
+int quota2_handle_cmd_getall(struct ufsmount *, int, prop_array_t);
int q2sync(struct mount *);
int dq2get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *);
int dq2sync(struct vnode *, struct dquot *);
--- 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,4 +1,4 @@
-/* $NetBSD: ufs_quota2.c,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $ */
+/* $NetBSD: ufs_quota2.c,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $ */
/*-
* Copyright (c) 2010 Manuel Bouyer
* All rights reserved.
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.1.2.1 2011/01/20 14:25:03 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.1.2.2 2011/01/21 16:58:06 bouyer Exp $");
#include <sys/buf.h>
#include <sys/param.h>
@@ -58,6 +58,9 @@
struct quota2_header **, int);
static int getq2e(struct ufsmount *, int, daddr_t, int, struct buf **,
struct quota2_entry **, int);
+static int quota2_walk_list(struct ufsmount *, struct buf *, int,
+ uint64_t *, int, void *,
+ int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, uint64_t, void *));
static int
getq2h(struct ufsmount *ump, int type,
@@ -107,6 +110,80 @@
*bpp = bp;
return 0;
}
+
+/* walk a quota entry list, calling the callback for each entry */
+#define Q2WL_ABORT 0x10000000
+
+static int
+quota2_walk_list(struct ufsmount *ump, struct buf *hbp, int type,
+ uint64_t *offp, int flags, void *a,
+ int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, uint64_t, void *))
+{
+ const int needswap = UFS_MPNEEDSWAP(ump);
+ daddr_t off = ufs_rw64(*offp, needswap);
+ struct buf *bp, *obp = hbp;
+ int ret = 0, ret2 = 0;
+ struct quota2_entry *q2e;
+ daddr_t lblkno, blkoff;
+
+ KASSERT(mutex_owner(&dqlock));
+
+ while (off != 0) {
+ lblkno = (off >> ump->um_mountp->mnt_fs_bshift);
+ blkoff = (off & ump->umq2_bmask);
+ if (lblkno == 0) {
+ /* in the header block */
+ bp = hbp;
+ } else {
+ ret = bread(ump->um_quotas[type], lblkno,
+ ump->umq2_bsize,
+ ump->um_cred[type], flags, &bp);
+ if (ret)
+ return ret;
+ if (bp->b_resid != 0) {
+ panic("quota2_walk_list: %s quota file corrupted",
+ quotatypes[type]);
+ }
+ }
+ q2e = (void *)((char *)(bp->b_data) + blkoff);
+ ret = (*func)(ump, offp, q2e, off, a);
+ if (off != ufs_rw64(*offp, needswap)) {
+ /* callback changed parent's pointer, redo */
+ off = ufs_rw64(*offp, needswap);
+ if (bp != hbp && bp != obp)
+ ret2 = VOP_BWRITE(bp);
+ } else {
+ /* parent if now current */
+ if (obp != bp && obp != hbp) {
+ if (flags & B_MODIFY)
+ ret2 = VOP_BWRITE(obp);
+ else
+ brelse(obp, 0);
+ }
+ obp = bp;
+ offp = &(q2e->q2e_next);
+ off = ufs_rw64(*offp, needswap);
+ }
+ if (ret)
+ break;
+ if (ret2) {
+ ret = ret2;
+ break;
+ }
+ }
+ if (obp != hbp) {
+ if (flags & B_MODIFY)
+ ret2 = VOP_BWRITE(obp);
+ else
+ brelse(obp, 0);
+ }
+ if (ret & Q2WL_ABORT)
+ return 0;
+ if (ret == 0)
+ return ret2;
+ return ret;
+}
+
void
quota2_umount(struct mount *mp)
{
@@ -318,7 +395,7 @@
}
int
-quota2_handle_cmd_get(struct ufsmount *ump, const char *type, int id,
+quota2_handle_cmd_get(struct ufsmount *ump, int type, int id,
int defaultq, prop_array_t replies)
{
struct dquot *dq;
@@ -327,24 +404,19 @@
struct quota2_entry *q2e;
struct buf *bp;
prop_dictionary_t dict;
- int q2type;
- if (!strcmp(type, "user")) {
- q2type = USRQUOTA;
- } else if (!strcmp(type, "group")) {
- q2type = GRPQUOTA;
- } else
- return EOPNOTSUPP;
-
- if (ump->um_quotas[q2type] == NULLVP)
+ if (ump->um_quotas[type] == NULLVP)
return ENODEV;
if (defaultq) {
- error = getq2h(ump, q2type, &bp, &q2h, 0);
- if (error)
+ mutex_enter(&dqlock);
+ error = getq2h(ump, type, &bp, &q2h, 0);
+ if (error) {
+ mutex_exit(&dqlock);
return error;
+ }
q2e = &q2h->q2h_defentry;
} else {
- error = dqget(NULLVP, id, ump, q2type, &dq);
+ error = dqget(NULLVP, id, ump, type, &dq);
if (error)
return error;
@@ -353,66 +425,132 @@
dqrele(NULLVP, dq);
return ENOENT;
}
- error = getq2e(ump, q2type, dq->dq2_lblkno, dq->dq2_blkoff,
+ error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff,
&bp, &q2e, 0);
- dqrele(NULLVP, dq);
if (error)
return error;
}
- dict = q2etoprop(q2e, 0);
+ dict = q2etoprop(q2e, defaultq);
+ if (defaultq)
+ mutex_exit(&dqlock);
+ else
+ dqrele(NULLVP, dq);
brelse(bp, 0);
if (dict == NULL)
return ENOMEM;
- if (!prop_array_add(replies, dict)) {
+ if (!prop_array_add_and_rel(replies, dict)) {
error = ENOMEM;
}
- prop_object_release(dict);
return error;
}
+
+static int
+quota2_getall_callback(struct ufsmount *ump, uint64_t *offp,
+ struct quota2_entry *q2e, uint64_t off, void *v)
+{
+ prop_array_t replies = v;
+ prop_dictionary_t dict;
+
+ dict = q2etoprop(q2e, 0);
+ if (!prop_array_add_and_rel(replies, dict)) {
+ return ENOMEM;
+ }
+ return 0;
+}
+
int
+quota2_handle_cmd_getall(struct ufsmount *ump, int type, prop_array_t replies)
+{
+ int error;
+ struct quota2_header *q2h;
+ struct buf *hbp;
+ prop_dictionary_t dict;
+ uint64_t offset;
+ int i;
+ int quota2_hash_size;
+ const int needswap = UFS_MPNEEDSWAP(ump);
+
+ if (ump->um_quotas[type] == NULLVP)
+ return ENODEV;
+ error = getq2h(ump, type, &hbp, &q2h, 0);
+ if (error)
+ return error;
+ dict = q2etoprop(&q2h->q2h_defentry, 1);
+ if (!prop_array_add_and_rel(replies, dict)) {
+ brelse(hbp, 0);
+ return ENOMEM;
+ }
+ quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap);
+ for (i = 0; i < quota2_hash_size ; i++) {
+ offset = ufs_rw64(q2h->q2h_entries[i], needswap);
+ error = quota2_walk_list(ump, hbp, type, &offset, 0, replies,
+ quota2_getall_callback);
+ if (error)
+ break;
+ }
+ brelse(hbp, 0);
+ return error;
+}
+
+int
q2sync(struct mount *mp)
{
return 0;
}
+struct dq2get_callback {
+ uid_t id;
+ struct dquot *dq;
+};
+
+static int
+dq2get_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e,
+ uint64_t off, void *v)
+{
+ struct dq2get_callback *c = v;
+ daddr_t lblkno;
+ int blkoff;
+ const int needswap = UFS_MPNEEDSWAP(ump);
+
+ if (ufs_rw32(q2e->q2e_uid, needswap) == c->id) {
+ lblkno = (off >> ump->um_mountp->mnt_fs_bshift);
+ blkoff = (off & ump->umq2_bmask);
+ c->dq->dq2_lblkno = lblkno;
+ c->dq->dq2_blkoff = blkoff;
+ return Q2WL_ABORT;
+ }
+ return 0;
+}
+
int
dq2get(struct vnode *dqvp, u_long id, struct ufsmount *ump, int type,
struct dquot *dq)
{
struct buf *bp;
struct quota2_header *q2h;
- struct quota2_entry *q2e;
int error;
- daddr_t offset, lblkno;
- int blkoffset;
+ daddr_t offset;
u_long hash_mask;
const int needswap = UFS_MPNEEDSWAP(ump);
+ struct dq2get_callback c = {
+ .id = id,
+ .dq = dq
+ };
+ mutex_enter(&dqlock);
error = getq2h(ump, type, &bp, &q2h, 0);
if (error)
- return error;
+ goto out_mutex;
/* look for our entry */
hash_mask = ((1 << q2h->q2h_hash_shift) - 1);
offset = ufs_rw64(q2h->q2h_entries[id & hash_mask], needswap);
- dq->dq2_lblkno = 0;
- dq->dq2_blkoff = 0;
- while (offset != 0) {
- lblkno = (offset >> ump->um_mountp->mnt_fs_bshift);
- blkoffset = (offset & ump->umq2_bmask);
- brelse(bp, 0);
- error = getq2e(ump, type, lblkno, blkoffset, &bp, &q2e, 0);
- if (error)
- return error;
- if (ufs_rw32(q2e->q2e_uid, needswap) == id) {
- dq->dq2_lblkno = lblkno;
- dq->dq2_blkoff = blkoffset;
- break;
- }
- offset = ufs_rw64(q2e->q2e_next, needswap);
- }
+ error = quota2_walk_list(ump, bp, type, &offset, 0, (void *)&c,
+ dq2get_callback);
brelse(bp, 0);
+out_mutex:
+ mutex_exit(&dqlock);
return error;
}
--- 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,4 +1,4 @@
-/* $NetBSD: ufs_quota.c,v 1.68.4.1 2011/01/20 14:25:03 bouyer Exp $ */
+/* $NetBSD: ufs_quota.c,v 1.68.4.2 2011/01/21 16:58:06 bouyer Exp $ */
/*
* Copyright (c) 1982, 1986, 1990, 1993, 1995
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.68.4.1 2011/01/20 14:25:03 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.68.4.2 2011/01/21 16:58:06 bouyer Exp $");
#if defined(_KERNEL_OPT)
#include "opt_quota.h"
@@ -57,9 +57,13 @@
#include <ufs/ufs/ufs_quota.h>
#include <ufs/ufs/quota2_prop.h>
+kmutex_t dqlock;
+kcondvar_t dqcv;
static int quota_handle_cmd_get(struct mount *, struct lwp *,
- prop_dictionary_t, const char *, prop_array_t);
+ prop_dictionary_t, int, prop_array_t);
+static int quota_handle_cmd_getall(struct mount *, struct lwp *,
+ prop_dictionary_t, int, prop_array_t);
/*
* Initialize the quota fields of an inode.
*/
@@ -126,11 +130,18 @@
int error = 0;
const char *cmd, *type;
prop_array_t datas;
+ int q2type;
if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd))
return EINVAL;
if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type))
return EINVAL;
+ if (!strcmp(type, "user")) {
+ q2type = USRQUOTA;
+ } else if (!strcmp(type, "group")) {
+ q2type = GRPQUOTA;
+ } else
+ return EOPNOTSUPP;
datas = prop_dictionary_get(cmddict, "data");
if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY)
return EINVAL;
@@ -139,12 +150,17 @@
prop_dictionary_remove(cmddict, "data"); /* prepare for return */
if (strcmp(cmd, "get") == 0) {
- error = quota_handle_cmd_get(mp, l, cmddict, type, datas);
+ error = quota_handle_cmd_get(mp, l, cmddict, q2type, datas);
goto end;
}
- if (!prop_dictionary_set_int8(cmddict, "return", EOPNOTSUPP))
- error = ENOMEM;
+ if (strcmp(cmd, "getall") == 0) {
+ error = quota_handle_cmd_getall(mp, l, cmddict, q2type, datas);
+ goto end;
+ }
+ error = EOPNOTSUPP;
end:
+ error = (prop_dictionary_set_int8(cmddict, "return",
+ error) ? 0 : ENOMEM);
prop_object_release(datas);
return error;
}
@@ -161,7 +177,7 @@
static int
quota_handle_cmd_get(struct mount *mp, struct lwp *l,
- prop_dictionary_t cmddict, const char *type, prop_array_t datas)
+ prop_dictionary_t cmddict, int type, prop_array_t datas)
{
prop_array_t replies;
prop_object_iterator_t iter;
@@ -172,19 +188,16 @@
const char *idstr;
if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0)
- return (prop_dictionary_set_int8(cmddict, "return",
- EOPNOTSUPP) ? 0 : ENOMEM);
+ return EOPNOTSUPP;
replies = prop_array_create();
if (replies == NULL)
- return (prop_dictionary_set_int8(cmddict, "return", ENOMEM) ?
- 0 : ENOMEM);
+ return ENOMEM;
iter = prop_array_iterator(datas);
if (iter == NULL) {
prop_object_release(replies);
- return (prop_dictionary_set_int8(cmddict, "return", ENOMEM) ?
- 0 : ENOMEM);
+ return ENOMEM;
}
while ((data = prop_object_iterator_next(iter)) != NULL) {
if (!prop_dictionary_get_uint32(data, "id", &id)) {
@@ -200,8 +213,6 @@
if (error == EPERM)
continue;
if (error != 0) {
- error = (prop_dictionary_set_int8(cmddict, "return",
- error) ? 0 : ENOMEM);
prop_object_release(replies);
return error;
}
@@ -219,18 +230,50 @@
panic("quota_handle_cmd_get: no support ?");
if (error && error != ENOENT) {
- error = (prop_dictionary_set_int8(cmddict, "return",
- error) ? 0 : ENOMEM);
prop_object_release(replies);
return error;
}
}
if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
- error = (prop_dictionary_set_int8(cmddict, "return",
- ENOMEM) ? 0 : ENOMEM);
+ error = ENOMEM;
} else {
- error = (prop_dictionary_set_int8(cmddict, "return", 0) ?
- 0 : ENOMEM);
+ error = 0;
+ }
+ return error;
+}
+
+static int
+quota_handle_cmd_getall(struct mount *mp, struct lwp *l,
+ prop_dictionary_t cmddict, int type, prop_array_t datas)
+{
+ prop_array_t replies;
+ struct ufsmount *ump = VFSTOUFS(mp);
+ int error;
+
+ if ((ump->um_flags & UFS_QUOTA2) == 0)
+ return EOPNOTSUPP;
+
+ error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
+ KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL);
+ if (error)
+ return error;
+
+ replies = prop_array_create();
+ if (replies == NULL)
+ return ENOMEM;
+
+#ifdef QUOTA2
+ if (ump->um_flags & UFS_QUOTA2) {
+ mutex_enter(&dqlock);
+ error = quota2_handle_cmd_getall(ump, type, replies);
+ mutex_exit(&dqlock);
+ } else
+#endif
+ panic("quota_handle_cmd_getall: no support ?");
+ if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
+ error = ENOMEM;
+ } else {
+ error = 0;
}
return error;
}
--- 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,12 +1,12 @@
-# $NetBSD: Makefile,v 1.6.64.1 2011/01/20 14:25:05 bouyer Exp $
+# $NetBSD: Makefile,v 1.6.64.2 2011/01/21 16:58:06 bouyer Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
.include <bsd.own.mk>
PROG= quota
-SRCS= quota.c
+SRCS= quota.c printquota.c
-CPPFLAGS+=-I${NETBSDSRCDIR}/sys
-DPADD= ${LIBRPCSVC}
+CPPFLAGS+=-I${NETBSDSRCDIR}/sys -I${NETBSDSRCDIR}/usr.bin/quota
+DPADD= ${LIBRPCSVC} ${LIBPROP}
LDADD= -lrpcsvc -lprop
.PATH: ${NETBSDSRCDIR}/sys/ufs/ufs
/* $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);
}
/* $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);
--- 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,4 +1,4 @@
-.\" $NetBSD: quota.1,v 1.14.52.2 2011/01/21 16:36:57 bouyer Exp $
+.\" $NetBSD: quota.1,v 1.14.52.3 2011/01/21 16:58:06 bouyer Exp $
.\"
.\" Copyright (c) 1983, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -135,7 +135,6 @@
.Nm
exits with a non-zero status, one or more filesystems
are over quota.
-.El
.Sh SEE ALSO
.Xr quotactl 2 ,
.Xr fstab 5 ,
--- 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,4 +1,4 @@
-/* $NetBSD: quota.c,v 1.33.2.1 2011/01/20 14:25:05 bouyer Exp $ */
+/* $NetBSD: quota.c,v 1.33.2.2 2011/01/21 16:58:06 bouyer Exp $ */
/*
* Copyright (c) 1980, 1990, 1993
@@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)quota.c 8.4 (Berkeley) 4/28/95";
#else
-__RCSID("$NetBSD: quota.c,v 1.33.2.1 2011/01/20 14:25:05 bouyer Exp $");
+__RCSID("$NetBSD: quota.c,v 1.33.2.2 2011/01/21 16:58:06 bouyer Exp $");
#endif
#endif /* not lint */
@@ -55,11 +55,10 @@
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/socket.h>
-#include <sys/queue.h>
-#include <prop/proplib.h>
-#include <sys/quota.h>
#include <ufs/ufs/quota2_prop.h>
+#include <sys/quota.h>
+
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -77,7 +76,7 @@
#include <rpc/pmap_prot.h>
#include <rpcsvc/rquota.h>
-const char *qfextension[] = INITQFNAMES;
+#include <printquota.h>
struct quotause {
struct quotause *next;
@@ -93,17 +92,18 @@
int getnfsquota(struct statvfs *, struct fstab *, struct quotause *,
long, int);
struct quotause *getprivs(long id, int quotatype);
-int getufsquota(struct statvfs *, struct quotause *, long, int);
void heading(int, u_long, const char *, const char *);
void showgid(gid_t);
void showgrpname(const char *);
void showquotas(int, u_long, const char *);
void showuid(uid_t);
void showusrname(const char *);
-const char *intprt(uint64_t, int);
-const char *timeprt(time_t seconds);
void usage(void);
+extern const char *qfextension[];
+
+int getufsquota(const char *, struct quota2_entry *, long, int, int, int);
+
int qflag = 0;
int vflag = 0;
int hflag = 0;
@@ -403,21 +403,22 @@
printf("%12s%9s%c%8s%9s%8s"
, nam
, intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_cur
- ,HN_B)
+ ,HN_B, hflag)
, (msgb == NULL) ? ' ' : '*'
, intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_softlimit
- , HN_B)
+ , HN_B, hflag)
, intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_hardlimit
- , HN_B)
+ , HN_B, hflag)
, (msgb == NULL) ? ""
: timeprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_time));
printf("%8s%c%7s%8s%8s\n"
- , intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_cur, 0)
+ , intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_cur
+ , 0, hflag)
, (msgi == NULL) ? ' ' : '*'
, intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_softlimit
- , 0)
+ , 0, hflag)
, intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_hardlimit
- , 0)
+ , 0, hflag)
, (msgi == NULL) ? ""
: timeprt(qup->q2e.q2e_val[Q2V_FILE].q2v_time)
);
@@ -458,63 +459,6 @@
}
/*
- * convert 64bit value to a printable string
- */
-const char *
-intprt(uint64_t val, int flags)
-{
- 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);
-}
-
-/*
* Collect the requested quota information.
*/
struct quotause *
@@ -532,7 +476,6 @@
nfst = getmntinfo(&fst, MNT_WAIT);
if (nfst == 0)
errx(2, "no filesystems mounted!");
- setfsent();
for (i = 0; i < nfst; i++) {
if (qup == NULL) {
if ((qup =
@@ -545,8 +488,9 @@
continue;
} else if (strncmp(fst[i].f_fstypename, "ffs",
sizeof(fst[i].f_fstypename)) == 0 &&
- (fst[i].f_flag &ST_QUOTA) != 0) {
- if (getufsquota(&fst[i], qup, id, quotatype) == 0)
+ (fst[i].f_flag & ST_QUOTA) != 0) {
+ if (getufsquota(fst[i].f_mntonname, &qup->q2e,
+ id, quotatype, dflag, Dflag) == 0)
continue;
} else
continue;
@@ -562,109 +506,10 @@
}
if (qup)
free(qup);
- endfsent();
return (quphead);
}
-
int
-getufsquota(struct statvfs *fst, struct quotause *qup, long id, int type)
-{
- prop_dictionary_t dict, data, cmd;
- prop_array_t cmds, datas;
- struct plistref pref;
- int error;
- int8_t error8;
- bool ret;
-
- dict = quota2_prop_create();
- cmds = prop_array_create();
- datas = prop_array_create();
- data = prop_dictionary_create();
-
- if (dict == NULL || cmds == NULL || datas == NULL || data == NULL)
- errx(1, "can't allocate proplist");
-
- if (dflag)
- ret = prop_dictionary_set_cstring(data, "id", "default");
- else
- ret = prop_dictionary_set_uint32(data, "id", id);
- if (!ret)
- err(1, "prop_dictionary_set(id)");
-
- if (!prop_array_add(datas, data))
- err(1, "prop_array_add(data)");
- prop_object_release(data);
- if (!quota2_prop_add_command(cmds, "get", qfextension[type], datas))
- err(1, "prop_add_command");
- if (!prop_dictionary_set(dict, "commands", cmds))
- err(1, "prop_dictionary_set(command)");
- if (Dflag)
- printf("message to kernel:\n%s\n",
- prop_dictionary_externalize(dict));
-
- if (!prop_dictionary_send_syscall(dict, &pref))
- err(1, "prop_dictionary_send_syscall");
- prop_object_release(dict);
-
- if (quotactl(fst->f_mntonname, &pref) != 0)
- err(1, "quotactl");
-
- if ((error = prop_dictionary_recv_syscall(&pref, &dict)) != 0) {
- errx(1, "prop_dictionary_recv_syscall: %s\n",
- strerror(error));
- }
- if (Dflag)
- printf("reply from kernel:\n%s\n",
- prop_dictionary_externalize(dict));
- if ((error = quota2_get_cmds(dict, &cmds)) != 0) {
- errx(1, "quota2_get_cmds: %s\n",
- strerror(error));
- }
- /* only one command, no need to iter */
- cmd = prop_array_get(cmds, 0);
- if (cmd == NULL)
- err(1, "prop_array_get(cmd)");
-
- if (!prop_dictionary_get_int8(cmd, "return", &error8))
- err(1, "prop_get(return)");
-
- if (error8) {
- if (error8 != ENOENT && error8 != ENODEV) {
- if (dflag)
- fprintf(stderr, "get default %s quota: %s\n",
- qfextension[type], strerror(error8));
- else
- fprintf(stderr, "get %s quota for %ld: %s\n",
- qfextension[type], id, strerror(error8));
- }
- prop_object_release(dict);
- return (0);
- }
- datas = prop_dictionary_get(cmd, "data");
- if (datas == NULL)
- err(1, "prop_dict_get(datas)");
-
- /* only one data, no need to iter */
- if (prop_array_count(datas) == 0) {
- /* no quota for this user/group */
- prop_object_release(dict);
- return (0);
- }
-
- data = prop_array_get(datas, 0);
- if (data == NULL)
- err(1, "prop_array_get(data)");
-
- error = quota2_dict_get_q2e_usage(data, &qup->q2e);
- if (error) {
- errx(1, "quota2_dict_get_q2e_usage: %s\n",
- strerror(error));
- }
- return (1);
-}
-
-int
getnfsquota(fst, fs, qup, id, quotatype)
struct statvfs *fst;
struct fstab *fs;
@@ -811,5 +656,106 @@
if (!isdigit(c))
return (0);
} while ((c = *s++) != 0);
+ return (1);
+}
+
+const char *qfextension[] = INITQFNAMES;
+
+int
+getufsquota(const char *mp, struct quota2_entry *q2e, long id, int type,
+ int defaultq, int debug)
+{
+ prop_dictionary_t dict, data, cmd;
+ prop_array_t cmds, datas;
+ struct plistref pref;
+ int error;
+ int8_t error8;
+ bool ret;
+
+ dict = quota2_prop_create();
+ cmds = prop_array_create();
+ datas = prop_array_create();
+ data = prop_dictionary_create();
+
+ if (dict == NULL || cmds == NULL || datas == NULL || data == NULL)
+ errx(1, "can't allocate proplist");
+
+ if (defaultq)
+ ret = prop_dictionary_set_cstring(data, "id", "default");
+ else
+ ret = prop_dictionary_set_uint32(data, "id", id);
+ if (!ret)
+ err(1, "prop_dictionary_set(id)");
+
+ if (!prop_array_add(datas, data))
+ err(1, "prop_array_add(data)");
+ prop_object_release(data);
+ if (!quota2_prop_add_command(cmds, "get", qfextension[type], datas))
+ err(1, "prop_add_command");
+ if (!prop_dictionary_set(dict, "commands", cmds))
+ err(1, "prop_dictionary_set(command)");
+ if (debug)
+ printf("message to kernel:\n%s\n",
+ prop_dictionary_externalize(dict));
+
+ if (!prop_dictionary_send_syscall(dict, &pref))
+ err(1, "prop_dictionary_send_syscall");
+ prop_object_release(dict);
+
+ if (quotactl(mp, &pref) != 0)
+ err(1, "quotactl");
+
+ if ((error = prop_dictionary_recv_syscall(&pref, &dict)) != 0) {
+ errx(1, "prop_dictionary_recv_syscall: %s\n",
+ strerror(error));
+ }
+ if (debug)
+ printf("reply from kernel:\n%s\n",
+ prop_dictionary_externalize(dict));
+ if ((error = quota2_get_cmds(dict, &cmds)) != 0) {
+ errx(1, "quota2_get_cmds: %s\n",
+ strerror(error));
+ }
+ /* only one command, no need to iter */
+ cmd = prop_array_get(cmds, 0);
+ if (cmd == NULL)
+ err(1, "prop_array_get(cmd)");
+
+ if (!prop_dictionary_get_int8(cmd, "return", &error8))
+ err(1, "prop_get(return)");
+
+ if (error8) {
+ if (error8 != ENOENT && error8 != ENODEV) {
+ if (defaultq)
+ fprintf(stderr, "get default %s quota: %s\n",
+ qfextension[type], strerror(error8));
+ else
+ fprintf(stderr, "get %s quota for %ld: %s\n",
+ qfextension[type], id, strerror(error8));
+ }
+ prop_object_release(dict);
+ return (0);
+ }
+ datas = prop_dictionary_get(cmd, "data");
+ if (datas == NULL)
+ err(1, "prop_dict_get(datas)");
+
+ /* only one data, no need to iter */
+ if (prop_array_count(datas) == 0) {
+ /* no quota for this user/group */
+ prop_object_release(dict);
+ return (0);
+ }
+
+ data = prop_array_get(datas, 0);
+ if (data == NULL)
+ err(1, "prop_array_get(data)");
+
+ error = quota2_dict_get_q2e_usage(data, q2e);
+ if (error) {
+ errx(1, "quota2_dict_get_q2e_usage: %s\n",
+ strerror(error));
+ }
+ prop_object_release(dict);
return (1);
}
--- 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 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
-# $NetBSD: Makefile,v 1.5 1997/10/18 04:37:59 lukem Exp $
+# $NetBSD: Makefile,v 1.5.64.1 2011/01/21 16:58:06 bouyer Exp $
+.include <bsd.own.mk>
PROG= repquota
+SRCS= repquota.c
MAN= repquota.8
+
+CPPFLAGS+=-I${NETBSDSRCDIR}/sys -I${NETBSDSRCDIR}/usr.bin/quota
+DPADD= ${LIBPROP}
+LDADD= -lprop
+
+.PATH: ${NETBSDSRCDIR}/usr.bin/quota
+SRCS+= printquota.c
+.PATH: ${NETBSDSRCDIR}/sys/ufs/ufs
+SRCS+= quota2_prop.c
.include <bsd.prog.mk>
--- 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
@@ -29,9 +29,9 @@
.\" SUCH DAMAGE.
.\"
.\" from: @(#)repquota.8 8.1 (Berkeley) 6/6/93
-.\" $NetBSD: repquota.8,v 1.9 2003/08/07 11:25:41 agc Exp $
+.\" $NetBSD: repquota.8,v 1.9.50.1 2011/01/21 16:58:07 bouyer Exp $
.\"
-.Dd June 6, 1993
+.Dd January 21, 2011
.Dt REPQUOTA 8
.Os
.Sh NAME
@@ -39,11 +39,15 @@
.Nd summarize quotas for a file system
.Sh SYNOPSIS
.Nm
+.Op Fl h
+.Op Fl D
.Op Fl g
.Op Fl u
.Op Fl v
.Ar filesystem Ar ...
.Nm
+.Op Fl h
+.Op Fl D
.Op Fl g
.Op Fl u
.Op Fl v
@@ -56,8 +60,7 @@
Available options:
.Bl -tag -width Ds
.It Fl a
-Print the quotas of all the filesystems listed in
-.Pa /etc/fstab .
+Print the quotas of all the mounted filesystems.
.It Fl g
Print only group quotas (the default is to print both
group and user quotas if they exist).
@@ -66,24 +69,20 @@
group and user quotas if they exist).
.It Fl v
Print a header line before printing each filesystem quotas.
+.It Fl D
+Debug: print plist sent to and received from kernel.
+.It Fl h
+Numbers are displayed in a human readable format.
.El
.Pp
For each user or group, the current
-number files and amount of space (in kilobytes) is
+number files and amount of space (in kilobytes, unless the
+.Fl h
+flag is used) is
printed, along with any quotas created with
.Xr edquota 8 .
.Pp
-Only members of the operator group or the super-user may
-use this command.
-.Sh FILES
-.Bl -tag -width quota.group -compact
-.It Pa quota.user
-at the filesystem root with user quotas
-.It Pa quota.group
-at the filesystem root with group quotas
-.It Pa /etc/fstab
-for file system names and locations
-.El
+Only the super-user may use this command.
.Sh DIAGNOSTICS
Various messages about inaccessible files; self-explanatory.
.Sh SEE ALSO
--- 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
@@ -40,7 +40,7 @@
#if 0
static char sccsid[] = "@(#)repquota.c 8.2 (Berkeley) 11/22/94";
#else
-__RCSID("$NetBSD: repquota.c,v 1.25 2010/02/17 18:55:14 bouyer Exp $");
+__RCSID("$NetBSD: repquota.c,v 1.25.2.1 2011/01/21 16:58:07 bouyer Exp $");
#endif
#endif /* not lint */
@@ -49,9 +49,13 @@
*/
#include <sys/param.h>
#include <sys/stat.h>
-#include <sys/queue.h>
-#include <ufs/ufs/quota.h>
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#include <prop/proplib.h>
+#include <sys/quota.h>
+
#include <errno.h>
+#include <err.h>
#include <fstab.h>
#include <grp.h>
#include <pwd.h>
@@ -60,12 +64,17 @@
#include <string.h>
#include <unistd.h>
-const char *qfname = QUOTAFILENAME;
+#include <ufs/ufs/quota2_prop.h>
+#include <ufs/ufs/quota1.h>
+
+#include <printquota.h>
+
const char *qfextension[] = INITQFNAMES;
+const char *qfname = QUOTAFILENAME;
struct fileusage {
struct fileusage *fu_next;
- struct dqblk fu_dqblk;
+ struct quota2_entry fu_q2e;
u_long fu_id;
char fu_name[1];
/* actually bigger */
@@ -73,33 +82,39 @@
#define FUHASH 1024 /* must be power of two */
struct fileusage *fuhead[MAXQUOTAS][FUHASH];
u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */
+struct quota2_entry defaultq2e[MAXQUOTAS];
-int vflag; /* verbose */
-int aflag; /* all file systems */
+int vflag = 0; /* verbose */
+int aflag = 0; /* all file systems */
+int Dflag = 0; /* debug */
+int hflag = 0; /* debug */
-struct fileusage *addid __P((u_long, int, const char *));
-int hasquota __P((struct fstab *, int, char **));
-struct fileusage *lookup __P((u_long, int));
-int main __P((int, char **));
-int oneof __P((const char *, char **, int));
-int repquota __P((struct fstab *, int, char *));
-const char *timeprt __P((time_t));
-void usage __P((void));
+struct fileusage *addid(u_long, int, const char *);
+int hasquota(struct fstab *, int, char **);
+struct fileusage *lookup(u_long, int);
+int main(int, char **);
+int oneof(const char *, char **, int);
+int repquota(const struct statvfs *, int);
+int repquota2(const struct statvfs *, int);
+int repquota1(const struct statvfs *, int);
+void usage(void);
+void printquotas(int, const struct statvfs *);
+void dqblk2q2e(const struct dqblk *, struct quota2_entry *);
int
main(argc, argv)
int argc;
char **argv;
{
- struct fstab *fs;
struct passwd *pw;
struct group *gr;
int gflag = 0, uflag = 0, errs = 0;
long i, argnum, done = 0;
- char *qfnp;
int ch;
+ struct statvfs *fst;
+ int nfst;
- while ((ch = getopt(argc, argv, "aguv")) != -1) {
+ while ((ch = getopt(argc, argv, "Daguhv")) != -1) {
switch(ch) {
case 'a':
aflag++;
@@ -110,9 +125,15 @@
case 'u':
uflag++;
break;
+ case 'h':
+ hflag++;
+ break;
case 'v':
vflag++;
break;
+ case 'D':
+ Dflag++;
+ break;
default:
usage();
}
@@ -138,30 +159,34 @@
(void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name);
endpwent();
}
- setfsent();
- while ((fs = getfsent()) != NULL) {
- if (strcmp(fs->fs_vfstype, "ffs"))
+
+ nfst = getmntinfo(&fst, MNT_WAIT);
+ if (nfst == 0)
+ errx(2, "no filesystems mounted!");
+ for (i = 0; i < nfst; i++) {
+ if (strncmp(fst[i].f_fstypename, "ffs",
+ sizeof(fst[i].f_fstypename)) != 0 ||
+ (fst[i].f_flag & ST_QUOTA) == 0)
continue;
if (aflag) {
- if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
- errs += repquota(fs, GRPQUOTA, qfnp);
- if (uflag && hasquota(fs, USRQUOTA, &qfnp))
- errs += repquota(fs, USRQUOTA, qfnp);
+ if (gflag)
+ errs += repquota(&fst[i], GRPQUOTA);
+ if (uflag)
+ errs += repquota(&fst[i], USRQUOTA);
continue;
}
- if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
- (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
+ if ((argnum = oneof(fst[i].f_mntonname, argv, argc)) >= 0 ||
+ (argnum = oneof(fst[i].f_mntfromname, argv, argc)) >= 0) {
done |= 1 << argnum;
- if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
- errs += repquota(fs, GRPQUOTA, qfnp);
- if (uflag && hasquota(fs, USRQUOTA, &qfnp))
- errs += repquota(fs, USRQUOTA, qfnp);
+ if (gflag)
+ errs += repquota(&fst[i], GRPQUOTA);
+ if (uflag)
+ errs += repquota(&fst[i], USRQUOTA);
}
}
- endfsent();
for (i = 0; i < argc; i++)
if ((done & (1 << i)) == 0)
- fprintf(stderr, "%s not found in fstab\n", argv[i]);
+ fprintf(stderr, "%s not mounted\n", argv[i]);
exit(errs);
}
@@ -169,36 +194,150 @@
usage()
{
fprintf(stderr, "usage:\n\t%s\n\t%s\n",
- "repquota [-v] [-g] [-u] -a",
- "repquota [-v] [-g] [-u] filesys ...");
+ "repquota [-D] [-v] [-g] [-u] -a",
+ "repquota [-D] [-v] [-g] [-u] filesys ...");
exit(1);
}
int
-repquota(fs, type, qfpathname)
- struct fstab *fs;
- int type;
- char *qfpathname;
+repquota(const struct statvfs *vfs, int type)
{
+ if (repquota2(vfs, type) != 0)
+ return (repquota1(vfs, type));
+ return 0;
+}
+
+int
+repquota2(const struct statvfs *vfs, int type)
+{
+ prop_dictionary_t dict, data, cmd;
+ prop_array_t cmds, datas;
+ struct plistref pref;
+ int error;
+ int8_t error8;
+ prop_object_iterator_t iter;
+ struct quota2_entry *q2ep;
struct fileusage *fup;
+ const char *strid;
+ uint32_t id;
+
+ dict = quota2_prop_create();
+ cmds = prop_array_create();
+ datas = prop_array_create();
+
+ if (dict == NULL || cmds == NULL || datas == NULL)
+ errx(1, "can't allocate proplist");
+ if (!quota2_prop_add_command(cmds, "getall", qfextension[type], datas))
+ err(1, "prop_add_command");
+ if (!prop_dictionary_set(dict, "commands", cmds))
+ err(1, "prop_dictionary_set(command)");
+ if (Dflag)
+ printf("message to kernel:\n%s\n",
+ prop_dictionary_externalize(dict));
+ if (!prop_dictionary_send_syscall(dict, &pref))
+ err(1, "prop_dictionary_send_syscall");
+ prop_object_release(dict);
+
+ if (quotactl(vfs->f_mntonname, &pref) != 0)
+ err(1, "quotactl");
+
+ if ((error = prop_dictionary_recv_syscall(&pref, &dict)) != 0) {
+ errx(1, "prop_dictionary_recv_syscall: %s\n",
+ strerror(error));
+ }
+ if (Dflag)
+ printf("reply from kernel:\n%s\n",
+ prop_dictionary_externalize(dict));
+ if ((error = quota2_get_cmds(dict, &cmds)) != 0) {
+ errx(1, "quota2_get_cmds: %s\n",
+ strerror(error));
+ }
+ /* only one command, no need to iter */
+ cmd = prop_array_get(cmds, 0);
+ if (cmd == NULL)
+ err(1, "prop_array_get(cmd)");
+
+ if (!prop_dictionary_get_int8(cmd, "return", &error8))
+ err(1, "prop_get(return)");
+
+ if (error8) {
+ prop_object_release(dict);
+ if (error8 != EOPNOTSUPP) {
+ fprintf(stderr, "get %s quotas: %s\n",
+ qfextension[type], strerror(error8));
+ }
+ return (error8);
+ }
+ datas = prop_dictionary_get(cmd, "data");
+ if (datas == NULL)
+ err(1, "prop_dict_get(datas)");
+
+ iter = prop_array_iterator(datas);
+ if (iter == NULL)
+ err(1, "prop_array_iterator");
+
+ while ((data = prop_object_iterator_next(iter)) != NULL) {
+ strid = NULL;
+ if (!prop_dictionary_get_uint32(data, "id", &id)) {
+ if (!prop_dictionary_get_cstring_nocopy(data, "id",
+ &strid))
+ errx(1, "can't find id in quota entry");
+ if (strcmp(strid, "default") != 0) {
+ errx(1, "wrong id string %s in quota entry",
+ strid);
+ }
+ q2ep = &defaultq2e[type];
+ } else {
+ if ((fup = lookup(id, type)) == 0)
+ fup = addid(id, type, (char *)0);
+ q2ep = &fup->fu_q2e;
+ q2ep->q2e_uid = id;
+ }
+
+ error = quota2_dict_get_q2e_usage(data, q2ep);
+ if (error) {
+ errx(1, "quota2_dict_get_q2e_usage: %s\n",
+ strerror(error));
+ }
+ }
+ prop_object_iterator_release(iter);
+ prop_object_release(dict);
+ printquotas(type, vfs);
+ return (0);
+}
+
+int repquota1(const struct statvfs *vfs, int type)
+{
+ char *qfpathname;
+ struct fstab *fs;
+ struct fileusage *fup;
FILE *qf;
u_long id;
struct dqblk dqbuf;
- static struct dqblk zerodqblk;
- static int warned = 0;
- static int multiple = 0;
+#if 0
+ static int warned = 0;
if (quotactl(fs->fs_file, QCMD(Q_SYNC, type), 0, 0) < 0 &&
errno == EOPNOTSUPP && !warned && vflag) {
warned++;
fprintf(stdout,
"*** Warning: Quotas are not compiled into this kernel\n");
}
- if (multiple++)
- printf("\n");
- if (vflag)
- fprintf(stdout, "*** Report for %s quotas on %s (%s)\n",
- qfextension[type], fs->fs_file, fs->fs_spec);
+#endif
+ setfsent();
+ while ((fs = getfsent()) != NULL) {
+ if (strcmp(fs->fs_vfstype, "ffs") == 0 &&
+ strcmp(fs->fs_file, vfs->f_mntonname) == 0)
+ break;
+ }
+ endfsent();
+ if (fs == NULL) {
+ fprintf(stderr, "%s not found in fstab\n", vfs->f_mntonname);
+ return 1;
+ }
+ if (!hasquota(fs, type, &qfpathname))
+ return 0;
+
if ((qf = fopen(qfpathname, "r")) == NULL) {
perror(qfpathname);
return (1);
@@ -211,9 +350,25 @@
continue;
if ((fup = lookup(id, type)) == 0)
fup = addid(id, type, (char *)0);
- fup->fu_dqblk = dqbuf;
+ dqblk2q2e(&dqbuf, &fup->fu_q2e);
}
fclose(qf);
+ printquotas(type, vfs);
+ return (0);
+}
+
+void
+printquotas(int type, const struct statvfs *vfs)
+{
+ static int multiple = 0;
+ u_long id;
+ struct fileusage *fup;
+
+ if (multiple++)
+ printf("\n");
+ if (vflag)
+ fprintf(stdout, "*** Report for %s quotas on %s (%s)\n",
+ qfextension[type], vfs->f_mntonname, vfs->f_mntfromname);
printf(" Block limits File limits\n");
printf(type == USRQUOTA ? "User " : "Group");
printf(" used soft hard grace used soft hard grace\n");
@@ -221,38 +376,45 @@
fup = lookup(id, type);
if (fup == 0)
continue;
- if (fup->fu_dqblk.dqb_curinodes == 0 &&
- fup->fu_dqblk.dqb_curblocks == 0)
+ if (fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_cur == 0 &&
+ fup->fu_q2e.q2e_val[Q2V_FILE].q2v_cur == 0)
continue;
if (strlen(fup->fu_name) > 9)
printf("%s ", fup->fu_name);
else
printf("%-10s", fup->fu_name);
- printf("%c%c%9d%9d%9d%7s",
- fup->fu_dqblk.dqb_bsoftlimit &&
- fup->fu_dqblk.dqb_curblocks >=
- fup->fu_dqblk.dqb_bsoftlimit ? '+' : '-',
- fup->fu_dqblk.dqb_isoftlimit &&
- fup->fu_dqblk.dqb_curinodes >=
- fup->fu_dqblk.dqb_isoftlimit ? '+' : '-',
- (int)(dbtob((u_quad_t)fup->fu_dqblk.dqb_curblocks) / 1024),
- (int)(dbtob((u_quad_t)fup->fu_dqblk.dqb_bsoftlimit) / 1024),
- (int)(dbtob((u_quad_t)fup->fu_dqblk.dqb_bhardlimit) / 1024),
- fup->fu_dqblk.dqb_bsoftlimit &&
- fup->fu_dqblk.dqb_curblocks >=
- fup->fu_dqblk.dqb_bsoftlimit ?
- timeprt(fup->fu_dqblk.dqb_btime) : "");
- printf(" %8d%8d%8d%7s\n",
- fup->fu_dqblk.dqb_curinodes,
- fup->fu_dqblk.dqb_isoftlimit,
- fup->fu_dqblk.dqb_ihardlimit,
- fup->fu_dqblk.dqb_isoftlimit &&
- fup->fu_dqblk.dqb_curinodes >=
- fup->fu_dqblk.dqb_isoftlimit ?
- timeprt(fup->fu_dqblk.dqb_itime) : "");
- fup->fu_dqblk = zerodqblk;
+ printf("%c%c%9s%9s%9s%7s",
+ fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_softlimit &&
+ fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_cur >=
+ fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_softlimit ?
+ '+' : '-',
+ fup->fu_q2e.q2e_val[Q2V_FILE].q2v_softlimit &&
+ fup->fu_q2e.q2e_val[Q2V_FILE].q2v_cur >=
+ fup->fu_q2e.q2e_val[Q2V_FILE].q2v_softlimit ?
+ '+' : '-',
+ intprt(fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_cur,
+ HN_B, hflag),
+ intprt(fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_softlimit,
+ HN_B, hflag),
+ intprt(fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_hardlimit,
+ HN_B, hflag),
+ (fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_softlimit &&
+ fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_cur >=
+ fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_softlimit) ?
+ timeprt(fup->fu_q2e.q2e_val[Q2V_BLOCK].q2v_time) : "");
+ printf(" %8s%8s%8s%7s\n",
+ intprt(fup->fu_q2e.q2e_val[Q2V_FILE].q2v_cur,
+ 0, hflag),
+ intprt(fup->fu_q2e.q2e_val[Q2V_FILE].q2v_softlimit,
+ 0, hflag),
+ intprt(fup->fu_q2e.q2e_val[Q2V_FILE].q2v_hardlimit,
+ 0, hflag),
+ (fup->fu_q2e.q2e_val[Q2V_FILE].q2v_softlimit &&
+ fup->fu_q2e.q2e_val[Q2V_FILE].q2v_cur >=
+ fup->fu_q2e.q2e_val[Q2V_FILE].q2v_softlimit) ?
+ timeprt(fup->fu_q2e.q2e_val[Q2V_FILE].q2v_time) : "");
+ memset(&fup->fu_q2e, 0, sizeof(fup->fu_q2e));
}
- return (0);
}
/*
@@ -365,33 +527,16 @@
return (fup);
}
-/*
+void
- * Calculate the grace period and return a printable string for it.
+dqblk2q2e(const struct dqblk *dqblk, struct quota2_entry *q2e)
- */
+{
-const char *
+ q2e->q2e_val[Q2V_BLOCK].q2v_hardlimit = dqblk->dqb_bhardlimit;
-timeprt(seconds)
+ q2e->q2e_val[Q2V_BLOCK].q2v_softlimit = dqblk->dqb_bsoftlimit;
- time_t seconds;
+ q2e->q2e_val[Q2V_BLOCK].q2v_cur = dqblk->dqb_curblocks;
-{
+ q2e->q2e_val[Q2V_BLOCK].q2v_time = dqblk->dqb_btime;
- time_t hours, minutes;
+
- static char buf[20];
+ q2e->q2e_val[Q2V_FILE].q2v_hardlimit = dqblk->dqb_ihardlimit;
- static time_t now;
+ q2e->q2e_val[Q2V_FILE].q2v_softlimit = dqblk->dqb_isoftlimit;
-
+ q2e->q2e_val[Q2V_FILE].q2v_cur = dqblk->dqb_curinodes;
- if (now == 0)
+ q2e->q2e_val[Q2V_FILE].q2v_time = dqblk->dqb_itime;
- time(&now);
+}
- if (now > seconds)
- return ("none");
- seconds -= now;
- minutes = (seconds + 30) / 60;
- hours = (minutes + 30) / 60;
- if (hours >= 36) {
- sprintf(buf, "%lddays", (long)((hours + 12) / 24));
- return (buf);
- }
- if (minutes >= 60) {
- sprintf(buf, "%2ld:%ld", (long)(minutes / 60),
- (long)(minutes % 60));
- return (buf);
- }
- sprintf(buf, "%2ld", (long)minutes);
- return (buf);
-}