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;
+}

Reply via email to