Source-Changes-HG archive

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

[src/trunk]: src/lib/libquota Implement quota_put() and quota_delete() using ...



details:   https://anonhg.NetBSD.org/src/rev/57c8fb4cbfd7
branches:  trunk
changeset: 772614:57c8fb4cbfd7
user:      dholland <dholland%NetBSD.org@localhost>
date:      Mon Jan 09 15:43:19 2012 +0000

description:
Implement quota_put() and quota_delete() using code from edquota(8).

diffstat:

 lib/libquota/quota_delete.c  |   14 +-
 lib/libquota/quota_proplib.c |  237 ++++++++++++++++++++++++++++++++++++++++++-
 lib/libquota/quota_put.c     |   14 +-
 lib/libquota/quotapvt.h      |    5 +-
 4 files changed, 257 insertions(+), 13 deletions(-)

diffs (truncated from 346 to 300 lines):

diff -r aa2664e77cf3 -r 57c8fb4cbfd7 lib/libquota/quota_delete.c
--- a/lib/libquota/quota_delete.c       Mon Jan 09 15:42:37 2012 +0000
+++ b/lib/libquota/quota_delete.c       Mon Jan 09 15:43:19 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: quota_delete.c,v 1.1 2012/01/09 15:22:38 dholland Exp $        */
+/*     $NetBSD: quota_delete.c,v 1.2 2012/01/09 15:43:19 dholland Exp $        */
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -29,16 +29,20 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: quota_delete.c,v 1.1 2012/01/09 15:22:38 dholland Exp $");
+__RCSID("$NetBSD: quota_delete.c,v 1.2 2012/01/09 15:43:19 dholland Exp $");
 
 #include <errno.h>
 
 #include <quota.h>
+#include "quotapvt.h"
 
-/* ARGSUSED */
 int
 quota_delete(struct quotahandle *qh, const struct quotakey *qk)
 {
-       errno = ENOSYS;
-       return -1;
+       if (qh->qh_isnfs) {
+               errno = EOPNOTSUPP;
+               return -1;
+       } else {
+               return __quota_proplib_delete(qh, qk);
+       }
 }
diff -r aa2664e77cf3 -r 57c8fb4cbfd7 lib/libquota/quota_proplib.c
--- a/lib/libquota/quota_proplib.c      Mon Jan 09 15:42:37 2012 +0000
+++ b/lib/libquota/quota_proplib.c      Mon Jan 09 15:43:19 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: quota_proplib.c,v 1.5 2012/01/09 15:41:58 dholland Exp $       */
+/*     $NetBSD: quota_proplib.c,v 1.6 2012/01/09 15:43:19 dholland Exp $       */
 /*-
   * Copyright (c) 2011 Manuel Bouyer
   * All rights reserved.
@@ -26,7 +26,7 @@
   */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: quota_proplib.c,v 1.5 2012/01/09 15:41:58 dholland Exp $");
+__RCSID("$NetBSD: quota_proplib.c,v 1.6 2012/01/09 15:43:19 dholland Exp $");
 
 #include <stdlib.h>
 #include <string.h>
@@ -468,6 +468,239 @@
        return 0;
 }
 
+int
+__quota_proplib_put(struct quotahandle *qh, const struct quotakey *qk,
+                   const struct quotaval *qv)
+{
+       prop_dictionary_t dict, data, cmd;
+       prop_array_t cmds, datas;
+       struct plistref pref;
+       int8_t error8;
+       uint64_t *valuesp[QUOTA_NLIMITS];
+       const char *idtype;
+       unsigned limitcode, otherlimitcode;
+       unsigned otherobjtype;
+       struct quotakey qk2;
+       struct quotaval qv2;
+
+       switch (qk->qk_idtype) {
+           case QUOTA_IDTYPE_USER:
+               idtype = ufs_quota_class_names[QUOTA_CLASS_USER];
+               break;
+           case QUOTA_IDTYPE_GROUP:
+               idtype = ufs_quota_class_names[QUOTA_CLASS_GROUP];
+               break;
+           default:
+               errno = EINVAL;
+               return -1;
+       }
+
+       switch (qk->qk_objtype) {
+           case QUOTA_OBJTYPE_BLOCKS:
+               limitcode = QUOTA_LIMIT_BLOCK;
+               otherlimitcode = QUOTA_LIMIT_FILE;
+               otherobjtype = QUOTA_OBJTYPE_FILES;
+               break;
+           case QUOTA_OBJTYPE_FILES:
+               limitcode = QUOTA_LIMIT_FILE;
+               otherlimitcode = QUOTA_LIMIT_BLOCK;
+               otherobjtype = QUOTA_OBJTYPE_BLOCKS;
+               break;
+           default:
+               errno = EINVAL;
+               return -1;
+       }
+
+       /* XXX in addition to being invalid/unsafe this also discards const */
+       valuesp[limitcode] = __UNCONST(&qv->qv_hardlimit);
+
+       /*
+        * You cannot set just the block info or just the file info.
+        * You have to set both together, or EINVAL comes back. So we
+        * have to fetch the current values for the other object type,
+        * and stuff both into the RPC packet. Blah. XXX.
+        */
+       qk2.qk_idtype = qk->qk_idtype;
+       qk2.qk_id = qk->qk_id;
+       qk2.qk_objtype = otherobjtype;
+       if (__quota_proplib_get(qh, &qk2, &qv2)) {
+               if (errno == ENOENT) {
+                       /* Nothing there yet, use a blank value */
+                       quotaval_clear(&qv2);
+               } else {
+                       return -1;
+               }
+       }
+       valuesp[otherlimitcode] = &qv2.qv_hardlimit;
+
+       data = quota64toprop(qk->qk_id, qk->qk_id == QUOTA_DEFAULTID ? 1 : 0,
+           valuesp, ufs_quota_entry_names, UFS_QUOTA_NENTRIES,
+           ufs_quota_limit_names, QUOTA_NLIMITS);
+
+       if (data == NULL)
+               err(1, "quota64toprop(id)");
+
+       dict = quota_prop_create();
+       cmds = prop_array_create();
+       datas = prop_array_create();
+
+       if (dict == NULL || cmds == NULL || datas == NULL) {
+               errx(1, "can't allocate proplist");
+       }
+
+       if (!prop_array_add_and_rel(datas, data))
+               err(1, "prop_array_add(data)");
+       
+       if (!quota_prop_add_command(cmds, "set", idtype, datas))
+               err(1, "prop_add_command");
+       if (!prop_dictionary_set(dict, "commands", cmds))
+               err(1, "prop_dictionary_set(command)");
+#if 0
+       if (Dflag)
+               printf("message to kernel:\n%s\n",
+                   prop_dictionary_externalize(dict));
+#endif
+
+       if (prop_dictionary_send_syscall(dict, &pref) != 0)
+               err(1, "prop_dictionary_send_syscall");
+       prop_object_release(dict);
+
+       if (quotactl(qh->qh_mountpoint, &pref) != 0)
+               err(1, "quotactl");
+
+       if (prop_dictionary_recv_syscall(&pref, &dict) != 0) {
+               err(1, "prop_dictionary_recv_syscall");
+       }
+
+#if 0
+       if (Dflag)
+               printf("reply from kernel:\n%s\n",
+                   prop_dictionary_externalize(dict));
+#endif
+
+       if ((errno = quota_get_cmds(dict, &cmds)) != 0) {
+               err(1, "quota_get_cmds");
+       }
+       /* 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);
+               errno = error8;
+               return -1;
+       }
+       prop_object_release(dict);
+       return 0;
+}
+
+int
+__quota_proplib_delete(struct quotahandle *qh, const struct quotakey *qk)
+{
+       prop_array_t cmds, datas;
+       prop_dictionary_t protodict, dict, data, cmd;
+       struct plistref pref;
+       int8_t error8;
+       bool ret;
+       const char *idtype;
+
+       /*
+        * XXX for now we always clear quotas for all objtypes no
+        * matter what's passed in. This is ok (sort of) for now
+        * because the only caller is edquota, which only calls delete
+        * for both blocks and files in immediate succession. But it's
+        * wrong in the long run. I'm not fixing it at the moment
+        * because I expect all this code to be deleted in the near
+        * future.
+        */
+       (void)qk->qk_objtype;
+
+       switch (qk->qk_idtype) {
+           case QUOTA_IDTYPE_USER:
+               idtype = ufs_quota_class_names[QUOTA_CLASS_USER];
+               break;
+           case QUOTA_IDTYPE_GROUP:
+               idtype = ufs_quota_class_names[QUOTA_CLASS_GROUP];
+               break;
+           default:
+               errno = EINVAL;
+               return -1;
+       }
+
+       /* build a generic command */
+       protodict = quota_prop_create();
+       cmds = prop_array_create();
+       datas = prop_array_create();
+       if (protodict == NULL || cmds == NULL || datas == NULL) {
+               errx(1, "can't allocate proplist");
+       }
+
+       data = prop_dictionary_create();
+       if (data == NULL)
+               errx(1, "can't allocate proplist");
+
+       ret = prop_dictionary_set_uint32(data, "id", qk->qk_id);
+       if (!ret)
+               err(1, "prop_dictionary_set(id)");
+       if (!prop_array_add_and_rel(datas, data))
+               err(1, "prop_array_add(data)");
+
+       if (!quota_prop_add_command(cmds, "clear", idtype, datas))
+               err(1, "prop_add_command");
+
+       if (!prop_dictionary_set(protodict, "commands", cmds))
+               err(1, "prop_dictionary_set(command)");
+
+#if 0
+       if (Dflag) {
+               fprintf(stderr, "message to kernel for %s:\n%s\n",
+                       qh->qh_mountpoint,
+                       prop_dictionary_externalize(protodict));
+       }
+#endif
+
+       if (prop_dictionary_send_syscall(protodict, &pref) != 0)
+               err(1, "prop_dictionary_send_syscall");
+       if (quotactl(qh->qh_mountpoint, &pref) != 0)
+               err(1, "quotactl");
+
+       if (prop_dictionary_recv_syscall(&pref, &dict) != 0) {
+               err(1, "prop_dictionary_recv_syscall");
+       }
+
+#if 0
+       if (Dflag) {
+               fprintf(stderr, "reply from kernel for %s:\n%s\n",
+                       qh->qh_mountpoint,
+                       prop_dictionary_externalize(dict));
+       }
+#endif
+
+       if ((errno = quota_get_cmds(dict, &cmds)) != 0) {
+               err(1, "quota_get_cmds");
+       }
+       /* 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);
+               prop_object_release(protodict);
+               errno = error8;
+               return -1;
+       }
+       prop_object_release(dict);
+       prop_object_release(protodict);
+       return 0;
+}
+
 static int
 __quota_proplib_getall(struct quotahandle *qh, int idtype, prop_array_t *ret)
 {
diff -r aa2664e77cf3 -r 57c8fb4cbfd7 lib/libquota/quota_put.c
--- a/lib/libquota/quota_put.c  Mon Jan 09 15:42:37 2012 +0000
+++ b/lib/libquota/quota_put.c  Mon Jan 09 15:43:19 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: quota_put.c,v 1.1 2012/01/09 15:22:38 dholland Exp $   */
+/*     $NetBSD: quota_put.c,v 1.2 2012/01/09 15:43:19 dholland Exp $   */
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.



Home | Main Index | Thread Index | Old Index