Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/edquota Make editor-based edquota work again.



details:   https://anonhg.NetBSD.org/src/rev/accec6a58140
branches:  trunk
changeset: 780979:accec6a58140
user:      dholland <dholland%NetBSD.org@localhost>
date:      Tue Aug 14 03:55:48 2012 +0000

description:
Make editor-based edquota work again.

The format is somewhat different; I'm operating under the assumption
that nobody has automated editing scripts for the old format because
it's much easier just to use the command-line interface of
edquota. The new format is more scalable and more parseable.

Also, do a better job of diagnosing editing errors, and don't blindly
erase all quota information for the user being edited when a parse
error occurs after editing.

diffstat:

 usr.sbin/edquota/edquota.c |  634 +++++++++++++++++++++++++-------------------
 1 files changed, 366 insertions(+), 268 deletions(-)

diffs (truncated from 796 to 300 lines):

diff -r 4e09e53efbed -r accec6a58140 usr.sbin/edquota/edquota.c
--- a/usr.sbin/edquota/edquota.c        Tue Aug 14 02:55:00 2012 +0000
+++ b/usr.sbin/edquota/edquota.c        Tue Aug 14 03:55:48 2012 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: edquota.c,v 1.49 2012/08/13 23:08:58 dholland Exp $ */
+/*      $NetBSD: edquota.c,v 1.50 2012/08/14 03:55:48 dholland Exp $ */
 /*
  * Copyright (c) 1980, 1990, 1993
  *     The Regents of the University of California.  All rights reserved.
@@ -41,7 +41,7 @@
 #if 0
 static char sccsid[] = "from: @(#)edquota.c    8.3 (Berkeley) 4/27/95";
 #else
-__RCSID("$NetBSD: edquota.c,v 1.49 2012/08/13 23:08:58 dholland Exp $");
+__RCSID("$NetBSD: edquota.c,v 1.50 2012/08/14 03:55:48 dholland Exp $");
 #endif
 #endif /* not lint */
 
@@ -89,6 +89,13 @@
 
 #define MAX_TMPSTR     (100+MAXPATHLEN)
 
+enum sources {
+       SRC_EDITED,     /* values came from user */
+       SRC_QUOTA,      /* values came from a specific quota entry */
+       SRC_DEFAULT,    /* values were copied from the default quota entry */
+       SRC_CLEAR,      /* values arose by zeroing out a quota entry */
+};
+
 struct quotause {
        struct  quotause *next;
        unsigned found:1,       /* found after running editor */
@@ -96,6 +103,7 @@
                isdefault:1;
 
        struct  quotaval qv[EDQUOTA_NUMOBJTYPES];
+       enum sources source[EDQUOTA_NUMOBJTYPES];
        char    fsname[MAXPATHLEN + 1];
        char    implementation[32];
 };
@@ -149,6 +157,46 @@
        return -1;
 }
 
+/*
+ * check if a source is "real" (reflects actual data) or not
+ */
+static bool
+source_is_real(enum sources source)
+{
+       switch (source) {
+           case SRC_EDITED:
+           case SRC_QUOTA:
+               return true;
+           case SRC_DEFAULT:
+           case SRC_CLEAR:
+               return false;
+       }
+       assert(!"encountered invalid source");
+       return false;
+}
+
+/*
+ * some simple string tools
+ */
+
+static /*const*/ char *
+skipws(/*const*/ char *s)
+{
+       while (*s == ' ' || *s == '\t') {
+               s++;
+       }
+       return s;
+}
+
+static /*const*/ char *
+skipword(/*const*/ char *s)
+{
+       while (*s != '\0' && *s != '\n' && *s != ' ' && *s != '\t') {
+               s++;
+       }
+       return s;
+}
+
 ////////////////////////////////////////////////////////////
 // quotause operations
 
@@ -159,6 +207,7 @@
 quotause_create(void)
 {
        struct quotause *qup;
+       unsigned i;
 
        qup = malloc(sizeof(*qup));
        if (qup == NULL) {
@@ -169,7 +218,10 @@
        qup->found = 0;
        qup->xgrace = 0;
        qup->isdefault = 0;
-       memset(qup->qv, 0, sizeof(qup->qv));
+       for (i=0; i<EDQUOTA_NUMOBJTYPES; i++) {
+               quotaval_clear(&qup->qv[i]);
+               qup->source[i] = SRC_CLEAR;
+       }
        qup->fsname[0] = '\0';
 
        return qup;
@@ -360,13 +412,30 @@
        qk.qk_idtype = idtype;
        qk.qk_id = defaultq ? QUOTA_DEFAULTID : id;
        qk.qk_objtype = objtype;
-       if (quota_get(qh, &qk, &qup->qv[objtype])) {
-               /* no entry, get default entry */
-               qk.qk_id = QUOTA_DEFAULTID;
-               if (quota_get(qh, &qk, &qup->qv[objtype])) {
-                       return -1;
-               }
+       if (quota_get(qh, &qk, &qup->qv[objtype]) == 0) {
+               /* succeeded */
+               qup->source[objtype] = SRC_QUOTA;
+               return 0;
+       }
+       if (errno != ENOENT) {
+               /* serious failure */
+               return -1;
        }
+
+       /* no entry, get default entry */
+       qk.qk_id = QUOTA_DEFAULTID;
+       if (quota_get(qh, &qk, &qup->qv[objtype]) == 0) {
+               /* succeeded */
+               qup->source[objtype] = SRC_DEFAULT;
+               return 0;
+       }
+       if (errno != ENOENT) {
+               return -1;
+       }
+
+       /* use a zeroed-out entry */
+       quotaval_clear(&qup->qv[objtype]);
+       qup->source[objtype] = SRC_CLEAR;
        return 0;
 }
 
@@ -448,18 +517,24 @@
                err(1, "%s: quota_open", qup->fsname);
        }
 
-       qk.qk_idtype = idtype;
-       qk.qk_id = id;
-       qk.qk_objtype = QUOTA_OBJTYPE_BLOCKS;
-       if (quota_put(qh, &qk, &qup->qv[QO_BLK])) {
-               err(1, "%s: quota_put (%s blocks)", qup->fsname, idname);
+       if (source_is_real(qup->source[QUOTA_OBJTYPE_BLOCKS])) {
+               qk.qk_idtype = idtype;
+               qk.qk_id = id;
+               qk.qk_objtype = QUOTA_OBJTYPE_BLOCKS;
+               if (quota_put(qh, &qk, &qup->qv[QO_BLK])) {
+                       err(1, "%s: quota_put (%s blocks)", qup->fsname,
+                           idname);
+               }
        }
 
-       qk.qk_idtype = idtype;
-       qk.qk_id = id;
-       qk.qk_objtype = QUOTA_OBJTYPE_FILES;
-       if (quota_put(qh, &qk, &qup->qv[QO_FL])) {
-               err(1, "%s: quota_put (%s files)", qup->fsname, idname);
+       if (source_is_real(qup->source[QUOTA_OBJTYPE_FILES])) {
+               qk.qk_idtype = idtype;
+               qk.qk_id = id;
+               qk.qk_objtype = QUOTA_OBJTYPE_FILES;
+               if (quota_put(qh, &qk, &qup->qv[QO_FL])) {
+                       err(1, "%s: quota_put (%s files)", qup->fsname,
+                           idname);
+               }
        }
 
        quota_close(qh);
@@ -497,18 +572,7 @@
                qup = getprivs2(id, idtype, fst[i].f_mntonname, defaultq,
                                &qlist->idtypename);
                if (qup == NULL) {
-                       /*
-                        * XXX: returning NULL is totally wrong. On
-                        * serious error, abort; on minor error, warn
-                        * and continue.
-                        *
-                        * Note: we cannot warn unconditionally here
-                        * because this case apparently includes "no
-                        * quota entry on this volume" and that causes
-                        * the atf tests to fail. Bletch.
-                        */
-                       /*return NULL;*/
-                       /*warnx("getprivs2 failed");*/
+                       warnx("getprivs2 failed for id %ld", id);
                        continue;
                }
 
@@ -526,9 +590,7 @@
                /* if we get there, filesys is not mounted. try the old way */
                qup = getprivs1(id, idtype, filesys);
                if (qup == NULL) {
-                       /* XXX. see above */
-                       /*return NULL;*/
-                       /*warnx("getprivs1 failed");*/
+                       warnx("getprivs1 failed");
                        return qlist;
                }
                quotalist_append(qlist, qup);
@@ -710,6 +772,7 @@
        struct quotause *qup;
        FILE *fd;
        char b0[32], b1[32], b2[32], b3[32];
+       const char *comm;
 
        (void)ftruncate(outfd, 0);
        (void)lseek(outfd, (off_t)0, SEEK_SET);
@@ -722,46 +785,38 @@
        }
        for (qup = qlist->head; qup; qup = qup->next) {
                struct quotaval *q = qup->qv;
-               fprintf(fd, "%s (%s):\n",
-                    qup->fsname, qup->implementation);
-               if (!qup->isdefault || qup->xgrace) {
-                       fprintf(fd, "\tblocks in use: %s, "
-                           "limits (soft = %s, hard = %s",
-                           intprt(b1, 21, q[QO_BLK].qv_usage,
-                           HN_NOSPACE | HN_B, Hflag), 
-                           intprt(b2, 21, q[QO_BLK].qv_softlimit,
-                           HN_NOSPACE | HN_B, Hflag),
-                           intprt(b3, 21, q[QO_BLK].qv_hardlimit,
-                               HN_NOSPACE | HN_B, Hflag));
-                       if (qup->xgrace)
-                               fprintf(fd, ", ");
-               } else
-                       fprintf(fd, "\tblocks: (");
-                       
+
+               fprintf(fd, "%s (%s):\n", qup->fsname, qup->implementation);
+
+               comm = source_is_real(qup->source[QO_BLK]) ? "" : "#";
+               fprintf(fd, "\tblocks:\n");
+               fprintf(fd, "\t\t%susage: %s\n", comm,
+                       intprt(b1, 21, q[QO_BLK].qv_usage,
+                              HN_NOSPACE | HN_B, Hflag));
+               fprintf(fd, "\t\t%slimits: soft %s, hard %s\n", comm,
+                       intprt(b2, 21, q[QO_BLK].qv_softlimit,
+                              HN_NOSPACE | HN_B, Hflag),
+                       intprt(b3, 21, q[QO_BLK].qv_hardlimit,
+                              HN_NOSPACE | HN_B, Hflag));
                if (qup->xgrace || qup->isdefault) {
-                   fprintf(fd, "grace = %s",
-                       timepprt(b0, 21, q[QO_BLK].qv_grace, Hflag));
+                       fprintf(fd, "\t\t%sgrace: %s\n", comm,
+                               timepprt(b0, 21, q[QO_BLK].qv_grace, Hflag));
                }
-               fprintf(fd, ")\n");
-               if (!qup->isdefault || qup->xgrace) {
-                       fprintf(fd, "\tinodes in use: %s, "
-                           "limits (soft = %s, hard = %s",
-                           intprt(b1, 21, q[QO_FL].qv_usage,
-                           HN_NOSPACE, Hflag),
-                           intprt(b2, 21, q[QO_FL].qv_softlimit,
-                           HN_NOSPACE, Hflag),
-                           intprt(b3, 21, q[QO_FL].qv_hardlimit,
-                            HN_NOSPACE, Hflag));
-                       if (qup->xgrace)
-                               fprintf(fd, ", ");
-               } else
-                       fprintf(fd, "\tinodes: (");
 
+               comm = source_is_real(qup->source[QO_FL]) ? "" : "#";
+               fprintf(fd, "\tinodes:\n");
+               fprintf(fd, "\t\t%susage: %s\n", comm,
+                       intprt(b1, 21, q[QO_FL].qv_usage,
+                              HN_NOSPACE, Hflag));
+               fprintf(fd, "\t\t%slimits: soft %s, hard %s\n", comm,
+                       intprt(b2, 21, q[QO_FL].qv_softlimit,
+                              HN_NOSPACE, Hflag),
+                       intprt(b3, 21, q[QO_FL].qv_hardlimit,
+                              HN_NOSPACE, Hflag));
                if (qup->xgrace || qup->isdefault) {
-                   fprintf(fd, "grace = %s",
-                       timepprt(b0, 21, q[QO_FL].qv_grace, Hflag));
+                       fprintf(fd, "\t\t%sgrace: %s\n", comm,
+                               timepprt(b0, 21, q[QO_FL].qv_grace, Hflag));
                }
-               fprintf(fd, ")\n");
        }
        fclose(fd);
        return 1;
@@ -773,239 +828,278 @@
 static int
 readprivs(struct quotalist *qlist, int infd, int dflag)
 {
-       struct quotause *qup;
-       FILE *fd;
-       int cnt;
-       char fsp[BUFSIZ];



Home | Main Index | Thread Index | Old Index