Module Name: src
Committed By: dholland
Date: Wed Nov 30 16:09:29 UTC 2011
Modified Files:
src/usr.bin/quota: quota.c
Log Message:
Clean up the printout code to support more than the old fixed two
object types.
To generate a diff of this commit:
cvs rdiff -u -r1.41 -r1.42 src/usr.bin/quota/quota.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/quota/quota.c
diff -u src/usr.bin/quota/quota.c:1.41 src/usr.bin/quota/quota.c:1.42
--- src/usr.bin/quota/quota.c:1.41 Wed Nov 30 16:07:28 2011
+++ src/usr.bin/quota/quota.c Wed Nov 30 16:09:29 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: quota.c,v 1.41 2011/11/30 16:07:28 dholland Exp $ */
+/* $NetBSD: quota.c,v 1.42 2011/11/30 16:09:29 dholland Exp $ */
/*
* Copyright (c) 1980, 1990, 1993
@@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 19
#if 0
static char sccsid[] = "@(#)quota.c 8.4 (Berkeley) 4/28/95";
#else
-__RCSID("$NetBSD: quota.c,v 1.41 2011/11/30 16:07:28 dholland Exp $");
+__RCSID("$NetBSD: quota.c,v 1.42 2011/11/30 16:09:29 dholland Exp $");
#endif
#endif /* not lint */
@@ -56,6 +56,7 @@ __RCSID("$NetBSD: quota.c,v 1.41 2011/11
#include <sys/mount.h>
#include <sys/socket.h>
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -85,14 +86,20 @@ struct quotause {
#define FOUND 0x01
#define QUOTA2 0x02
+static int anyusage(struct quotaval *, unsigned);
+static int anyover(struct quotaval *, unsigned, time_t);
+static const char *getovermsg(struct quotaval *, const char *, time_t);
static struct quotause *getprivs(id_t, int);
static void heading(int, id_t, const char *, const char *);
+static int isover(struct quotaval *qv, time_t now);
+static void printqv(struct quotaval *, int, int, time_t);
static void showgid(gid_t);
static void showgrpname(const char *);
static void showonequota(int, id_t, const char *, struct quotause *);
static void showquotas(int, id_t, const char *);
static void showuid(uid_t);
static void showusrname(const char *);
+static int unlimited(struct quotaval *qvs, unsigned numqvs);
static void usage(void) __dead;
static int qflag = 0;
@@ -316,7 +323,7 @@ showgrpname(const char *name)
}
static void
-showquotas(int type, id_t id, const char *name)
+showquotas(int type, id_t id, const char *idname)
{
struct quotause *qup;
struct quotause *quplist;
@@ -325,131 +332,81 @@ showquotas(int type, id_t id, const char
quplist = getprivs(id, type);
for (qup = quplist; qup; qup = qup->next) {
- showonequota(type, id, name, qup);
+ showonequota(type, id, idname, qup);
}
if (!qflag) {
/* In case nothing printed, issue a header saying "none" */
- heading(type, id, name, "none");
+ heading(type, id, idname, "none");
}
}
static void
-showonequota(int type, id_t id, const char *name, struct quotause *qup)
+showonequota(int type, id_t id, const char *idname, struct quotause *qup)
{
- char b0[20], b1[20], b2[20], b3[20];
- const char *msgi, *msgb, *nam, *timemsg;
- int ql_stat;
- struct quotaval *q = qup->qv;
+ static const int isbytes[QUOTA_NLIMITS] = {
+ [QUOTA_LIMIT_BLOCK] = 1,
+ [QUOTA_LIMIT_FILE] = 0,
+ };
static time_t now;
+ struct quotaval *qvs;
+ unsigned numqvs, i;
+ const char *msg;
+ int isquota2;
+
+ qvs = qup->qv;
+ numqvs = QUOTA_NLIMITS;
if (now == 0) {
time(&now);
}
- if (!vflag &&
- q[QUOTA_LIMIT_BLOCK].qv_softlimit == UQUAD_MAX &&
- q[QUOTA_LIMIT_BLOCK].qv_hardlimit == UQUAD_MAX &&
- q[QUOTA_LIMIT_FILE].qv_softlimit == UQUAD_MAX &&
- q[QUOTA_LIMIT_FILE].qv_hardlimit == UQUAD_MAX)
+ if (!vflag && unlimited(qvs, numqvs)) {
return;
- ql_stat = quota_check_limit(q[QUOTA_LIMIT_FILE].qv_usage, 1,
- q[QUOTA_LIMIT_FILE].qv_softlimit,
- q[QUOTA_LIMIT_FILE].qv_hardlimit,
- q[QUOTA_LIMIT_FILE].qv_expiretime, now);
- switch(QL_STATUS(ql_stat)) {
- case QL_S_DENY_HARD:
- msgi = "File limit reached on";
- break;
- case QL_S_DENY_GRACE:
- msgi = "Over file quota on";
- break;
- case QL_S_ALLOW_SOFT:
- msgi = "In file grace period on";
- break;
- default:
- msgi = NULL;
- }
- ql_stat = quota_check_limit(q[QUOTA_LIMIT_BLOCK].qv_usage, 1,
- q[QUOTA_LIMIT_BLOCK].qv_softlimit,
- q[QUOTA_LIMIT_BLOCK].qv_hardlimit,
- q[QUOTA_LIMIT_BLOCK].qv_expiretime, now);
- switch(QL_STATUS(ql_stat)) {
- case QL_S_DENY_HARD:
- msgb = "Block limit reached on";
- break;
- case QL_S_DENY_GRACE:
- msgb = "Over block quota on";
- break;
- case QL_S_ALLOW_SOFT:
- msgb = "In block grace period on";
- break;
- default:
- msgb = NULL;
}
+
if (qflag) {
- if (msgi != NULL) {
- heading(type, id, name, "");
- printf("\t%s %s\n", msgi, qup->fsname);
- }
- if (msgb != NULL) {
- heading(type, id, name, "");
- printf("\t%s %s\n", msgb, qup->fsname);
+ for (i=0; i<numqvs; i++) {
+ msg = getovermsg(&qvs[i], ufs_quota_limit_names[i],
+ now);
+ if (msg != NULL) {
+ heading(type, id, idname, "");
+ printf("\t%s %s\n", msg, qup->fsname);
+ }
}
return;
}
- if (vflag || dflag || msgi || msgb ||
- q[QUOTA_LIMIT_BLOCK].qv_usage ||
- q[QUOTA_LIMIT_FILE].qv_usage) {
- heading(type, id, name, "");
- nam = qup->fsname;
+
+ /*
+ * XXX: anyover can in fact be true if anyusage is not true,
+ * if there's a quota of zero set on some volume. This is
+ * because the check we do checks if adding one more thing
+ * will go over. That is reasonable, I suppose, but Arguably
+ * the resulting behavior with usage 0 is a bug. (Also, what
+ * reason do we have to believe that the reported grace expire
+ * time is valid if we aren't in fact over yet?)
+ */
+
+ if (vflag || dflag || anyover(qvs, numqvs, now) ||
+ anyusage(qvs, numqvs)) {
+ heading(type, id, idname, "");
if (strlen(qup->fsname) > 4) {
printf("%s\n", qup->fsname);
- nam = "";
- }
- if (msgb)
- timemsg = timeprt(b0, 9, now,
- q[QUOTA_LIMIT_BLOCK].qv_expiretime);
- else if ((qup->flags & QUOTA2) != 0 && vflag)
- timemsg = timeprt(b0, 9, 0,
- q[QUOTA_LIMIT_BLOCK].qv_grace);
- else
- timemsg = "";
-
- printf("%12s%9s%c%8s%9s%8s",
- nam,
- intprt(b1, 9, q[QUOTA_LIMIT_BLOCK].qv_usage,
- HN_B, hflag),
- (msgb == NULL) ? ' ' : '*',
- intprt(b2, 9, q[QUOTA_LIMIT_BLOCK].qv_softlimit,
- HN_B, hflag),
- intprt(b3, 9, q[QUOTA_LIMIT_BLOCK].qv_hardlimit,
- HN_B, hflag),
- timemsg);
-
- if (msgi)
- timemsg = timeprt(b0, 9, now,
- q[QUOTA_LIMIT_FILE].qv_expiretime);
- else if ((qup->flags & QUOTA2) != 0 && vflag)
- timemsg = timeprt(b0, 9, 0,
- q[QUOTA_LIMIT_FILE].qv_grace);
- else
- timemsg = "";
-
- printf("%8s%c%7s%8s%8s\n",
- intprt(b1, 8, q[QUOTA_LIMIT_FILE].qv_usage, 0,
- hflag),
- (msgi == NULL) ? ' ' : '*',
- intprt(b2, 8, q[QUOTA_LIMIT_FILE].qv_softlimit,
- 0, hflag),
- intprt(b3, 8, q[QUOTA_LIMIT_FILE].qv_hardlimit,
- 0, hflag),
- timemsg);
- return;
+ printf("%12s", "");
+ } else {
+ printf("%12s", qup->fsname);
+ }
+
+ isquota2 = (qup->flags & QUOTA2) != 0;
+
+ for (i=0; i<numqvs; i++) {
+ printqv(&qvs[i], isquota2, isbytes[i], now);
+ }
+ printf("\n");
}
}
static void
-heading(int type, id_t id, const char *name, const char *tag)
+heading(int type, id_t id, const char *idname, const char *tag)
{
if (needheading == 0)
return;
@@ -460,7 +417,7 @@ heading(int type, id_t id, const char *n
ufs_quota_class_names[type], tag);
else
printf("Disk quotas for %s %s (%cid %u): %s\n",
- ufs_quota_class_names[type], name,
+ ufs_quota_class_names[type], idname,
*ufs_quota_class_names[type], id, tag);
if (!qflag && tag[0] == '\0') {
@@ -478,6 +435,45 @@ heading(int type, id_t id, const char *n
}
}
+static void
+printqv(struct quotaval *qv, int isquota2, int isbytes, time_t now)
+{
+ char buf[20];
+ const char *str;
+ int intprtflags, over, width;
+
+ /*
+ * The assorted finagling of width is to match the previous
+ * open-coded formatting for exactly two quota object types,
+ * which was chosen to make the default report fit in 80
+ * columns.
+ */
+
+ width = isbytes ? 9 : 8;
+ intprtflags = isbytes ? HN_B : 0;
+ over = isover(qv, now);
+
+ str = intprt(buf, width, qv->qv_usage, intprtflags, hflag);
+ printf("%*s", width, str);
+
+ printf("%c", over ? '*' : ' ');
+
+ str = intprt(buf, width, qv->qv_softlimit, intprtflags, hflag);
+ printf("%*s", width-1, str);
+
+ str = intprt(buf, width, qv->qv_hardlimit, intprtflags, hflag);
+ printf("%*s", width, str);
+
+ if (over) {
+ str = timeprt(buf, 9, now, qv->qv_expiretime);
+ } else if (isquota2 && vflag) {
+ str = timeprt(buf, 9, 0, qv->qv_grace);
+ } else {
+ str = "";
+ }
+ printf("%8s", str);
+}
+
/*
* Collect the requested quota information.
*/
@@ -527,3 +523,90 @@ getprivs(id_t id, int quotatype)
free(qup);
return quphead;
}
+
+static int
+unlimited(struct quotaval *qvs, unsigned numqvs)
+{
+ unsigned i;
+
+ for (i=0; i<numqvs; i++) {
+ if (qvs[i].qv_softlimit != UQUAD_MAX ||
+ qvs[i].qv_hardlimit != UQUAD_MAX) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int
+anyusage(struct quotaval *qvs, unsigned numqvs)
+{
+ unsigned i;
+
+ for (i=0; i<numqvs; i++) {
+ if (qvs[i].qv_usage > 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+anyover(struct quotaval *qvs, unsigned numqvs, time_t now)
+{
+ unsigned i;
+
+ for (i=0; i<numqvs; i++) {
+ if (isover(&qvs[i], now)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+isover(struct quotaval *qv, time_t now)
+{
+ int ql_stat;
+
+ ql_stat = quota_check_limit(qv->qv_usage, 1,
+ qv->qv_softlimit,
+ qv->qv_hardlimit,
+ qv->qv_expiretime, now);
+ switch(QL_STATUS(ql_stat)) {
+ case QL_S_DENY_HARD:
+ case QL_S_DENY_GRACE:
+ case QL_S_ALLOW_SOFT:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static const char *
+getovermsg(struct quotaval *qv, const char *what, time_t now)
+{
+ static char buf[64];
+ int ql_stat;
+
+ ql_stat = quota_check_limit(qv->qv_usage, 1,
+ qv->qv_softlimit,
+ qv->qv_hardlimit,
+ qv->qv_expiretime, now);
+ switch(QL_STATUS(ql_stat)) {
+ case QL_S_DENY_HARD:
+ snprintf(buf, sizeof(buf), "%c%s limit reached on",
+ toupper((unsigned char)what[0]), what+1);
+ break;
+ case QL_S_DENY_GRACE:
+ snprintf(buf, sizeof(buf), "Over %s quota on", what);
+ break;
+ case QL_S_ALLOW_SOFT:
+ snprintf(buf, sizeof(buf), "In %s grace period on", what);
+ break;
+ default:
+ return NULL;
+ }
+ return buf;
+}