Sophie

Sophie

distrib > Mandriva > 2007.0 > x86_64 > by-pkgid > 08b68bca035167118f0784235c7182ec > files > 6

cyrus-imapd-2.2.13-4mdv2007.0.src.rpm

diff -Naur cyrus-imapd-2.2.12/imap/imapd.c cyrus-imapd-2.2.12.rmquota.uncompiled/imap/imapd.c
--- cyrus-imapd-2.2.12/imap/imapd.c	2005-02-14 08:39:55.000000000 +0200
+++ cyrus-imapd-2.2.12.rmquota.uncompiled/imap/imapd.c	2005-03-03 16:08:19.000000000 +0200
@@ -4718,6 +4718,7 @@
 {
     int newquota = -1;
     int badresource = 0;
+    int rmquota = 0;
     int c;
     int force = 0;
     static struct buf arg;
@@ -4732,7 +4733,8 @@
     if (c != ')' || arg.s[0] != '\0') {
 	for (;;) {
 	    if (c != ' ') goto badlist;
-	    if (strcasecmp(arg.s, "storage") != 0) badresource = 1;
+	    if (strcasecmp(arg.s, "remove") == 0) rmquota = 1;
+	    else if (strcasecmp(arg.s, "storage") != 0) badresource = 1;
 	    c = getword(imapd_in, &arg);
 	    if (c != ' ' && c != ')') goto badlist;
 	    if (arg.s[0] == '\0') goto badlist;
@@ -4769,7 +4771,10 @@
 						   imapd_userid, mailboxname);
 
 	if (!r) {
-	    r = mboxlist_setquota(mailboxname, newquota, force);
+            if(!rmquota)
+                r = mboxlist_setquota(mailboxname, newquota, force);
+            else
+                r = mboxlist_unsetquota(mailboxname);
 	}
     }
 
diff -Naur cyrus-imapd-2.2.12/imap/mailbox.c cyrus-imapd-2.2.12.rmquota.uncompiled/imap/mailbox.c
--- cyrus-imapd-2.2.12/imap/mailbox.c	2005-02-14 08:39:57.000000000 +0200
+++ cyrus-imapd-2.2.12.rmquota.uncompiled/imap/mailbox.c	2005-03-03 16:08:19.000000000 +0200
@@ -2117,27 +2117,7 @@
 
     seen_delete_mailbox(mailbox);
 
-    if (delete_quota_root && !rquota) {
-	quota_delete(&mailbox->quota, &tid);
-	free(mailbox->quota.root);
-	mailbox->quota.root = NULL;
-    } else if (!rquota) {
-	/* Free any quota being used by this mailbox */
-	if (mailbox->quota.used >= mailbox->quota_mailbox_used) {
-	    mailbox->quota.used -= mailbox->quota_mailbox_used;
-	}
-	else {
-	    mailbox->quota.used = 0;
-	}
-	r = quota_write(&mailbox->quota, &tid);
-	if (r) {
-	    syslog(LOG_ERR,
-		   "LOSTQUOTA: unable to record free of %lu bytes in quota %s",
-		   mailbox->quota_mailbox_used, mailbox->quota.root);
-	}
-	else
-	    quota_commit(&tid);
-    }
+    mailbox_updatequota(mailbox,NULL);
 
     /* remove all files in directory */
     strlcpy(buf, mailbox->path, sizeof(buf));
@@ -2751,3 +2731,49 @@
 	if (*p == '.') *p = '/';
     }
 }
+
+
+/* This function is used to update the quota. Can be used to replace
+ * identical parts of the code, and can be quite handy some times 
+ * The tid is used in order to make possible to make the quota update
+ * being a part of a bigger transaction to the quota db */
+int mailbox_updatequota(struct mailbox *mailbox, struct txn **tid)
+{
+    int r = 0, havetid = 0;
+    struct txn **ltid = NULL;
+
+    if(tid) {
+        ltid = tid;
+        havetid = 1;
+    }
+    /* Ensure that we are locked */
+    if(!mailbox->header_lock_count) return IMAP_INTERNAL;
+
+
+    if(mailbox->quota.root) {
+        r = quota_read(&mailbox->quota, ltid, 1);
+        if( r == 0 ) {
+            if (mailbox->quota.used >= mailbox->quota_mailbox_used) {
+                mailbox->quota.used -= mailbox->quota_mailbox_used;
+            }
+            else {
+                mailbox->quota.used = 0;
+            }
+            r = quota_write(&mailbox->quota, ltid);
+            if (r) {
+                syslog(LOG_ERR,
+                   "LOSTQUOTA: unable to record free of %lu bytes in quota %s",
+                   mailbox->quota_mailbox_used, mailbox->quota.root);
+            }
+            else if(!havetid)
+                quota_commit(&tid);
+        }
+        /* It is not a big mistake not to have quota .. just remove from the mailbox */
+        else if ( r == IMAP_QUOTAROOT_NONEXISTENT) {
+                free(mailbox->quota.root);
+                r = 0;
+        }
+    }
+    return r;
+}
+
diff -Naur cyrus-imapd-2.2.12/imap/mailbox.h cyrus-imapd-2.2.12.rmquota.uncompiled/imap/mailbox.h
--- cyrus-imapd-2.2.12/imap/mailbox.h	2004-01-22 23:17:09.000000000 +0200
+++ cyrus-imapd-2.2.12.rmquota.uncompiled/imap/mailbox.h	2005-03-03 16:08:19.000000000 +0200
@@ -305,6 +305,8 @@
 			  struct mailbox *mailboxp);
 extern int mailbox_delete(struct mailbox *mailbox, int delete_quota_root);
 
+extern int mailbox_updatequota(struct mailbox *mailbox, struct txn **tid);
+
 extern int mailbox_rename_copy(struct mailbox *oldmailbox, 
 			       const char *newname, char *newpath,
 			       bit32 *olduidvalidityp, bit32 *newuidvalidityp,
diff -Naur cyrus-imapd-2.2.12/imap/mboxlist.c cyrus-imapd-2.2.12.rmquota.uncompiled/imap/mboxlist.c
--- cyrus-imapd-2.2.12/imap/mboxlist.c	2004-07-26 21:08:03.000000000 +0300
+++ cyrus-imapd-2.2.12.rmquota.uncompiled/imap/mboxlist.c	2005-03-03 16:08:19.000000000 +0200
@@ -100,6 +100,7 @@
 
 struct change_rock {
     struct quota *quota;
+    struct quota *oldquota;
     struct txn **tid;
 };
 
@@ -2357,6 +2358,7 @@
     if (r) return r;
 
     crock.quota = &quota;
+    crock.oldquota = NULL;
     crock.tid = &tid;
     /* top level mailbox */
     if(have_mailbox)
@@ -2375,17 +2377,21 @@
  */
 int mboxlist_unsetquota(const char *root)
 {
+    char newquota[MAX_MAILBOX_PATH+1];
     char pattern[MAX_MAILBOX_PATH+1];
     struct quota quota;
-    int r=0;
+    struct change_rock crock;
+    int r=0, k=0;
 
     if (!root[0] || root[0] == '.' || strchr(root, '/')
 	|| strchr(root, '*') || strchr(root, '%') || strchr(root, '?')) {
 	return IMAP_MAILBOX_BADNAME;
     }
     
+    crock.tid = NULL;
+
     quota.root = (char *) root;
-    r = quota_read(&quota, NULL, 0);
+    r = quota_read(&quota, crock.tid, 0);
     if (r == IMAP_QUOTAROOT_NONEXISTENT) {
 	/* already unset */
 	return 0;
@@ -2402,13 +2408,45 @@
     }
     else
 	strlcat(pattern, ".*", sizeof(pattern));
-    
-    /* top level mailbox */
-    mboxlist_rmquota(root, 0, 0, (void *)root);
-    /* submailboxes - we're using internal names here */
-    mboxlist_findall(NULL, pattern, 1, 0, 0, mboxlist_rmquota, (void *)root);
 
-    r = quota_delete(&quota, NULL);
+    r = quota_delete(&quota, crock.tid);
+
+    /* If we cannot delete the quota then abort the operation */
+    if(!r) {
+       /* quota_findroot performs several checks that we can
+        * assume that are already done, and don't have to perform
+        * them again. One of them is that it returns 1 only if
+        * quotaroot exists.
+        */
+        if(quota_findroot(newquota, sizeof(newquota), root)) {
+            struct quota rootquota;
+            rootquota.root = newquota;
+            k = quota_read(&rootquota, crock.tid, 0);
+            if (!k) {
+                crock.quota = &rootquota;
+                crock.oldquota = &quota;
+                /* top level mailbox */
+                k = mboxlist_changequota(root, 0, 0, &crock);
+            }
+            /* submailboxes - we're using internal names here */
+            if (!k)
+                k = mboxlist_findall(NULL, pattern, 1, 0, 0, mboxlist_changequota, &crock);
+            if(!k)
+                k = quota_write(&rootquota, crock.tid);
+
+         }
+         else {
+           /* top level mailbox */
+           mboxlist_rmquota(root, 0, 0, (void *)root);
+           /* submailboxes - we're using internal names here */
+           mboxlist_findall(NULL, pattern, 1, 0, 0, mboxlist_rmquota, (void *)root);
+       }
+    }
+
+    if(!r && !k)
+        quota_commit(crock.tid);
+    else
+        quota_abort(crock.tid);
 
     return r;
 }
@@ -2506,6 +2544,7 @@
     struct mailbox mailbox;
     struct change_rock *crock = (struct change_rock *) rock;
     struct quota *mboxlist_newquota = crock->quota;
+    struct quota *mboxlist_oldquota = crock->oldquota;
     struct txn **tid = crock->tid;
 
     assert(rock != NULL);
@@ -2523,27 +2562,24 @@
     if (r) goto error;
 
     if (mailbox.quota.root) {
-	if (strlen(mailbox.quota.root) >= strlen(mboxlist_newquota->root)) {
-	    /* Part of a child quota root */
-	    mailbox_close(&mailbox);
-	    return 0;
-	}
-
-	r = quota_read(&mailbox.quota, tid, 1);
-	if (r) goto error;
-	if (mailbox.quota.used >= mailbox.quota_mailbox_used) {
-	    mailbox.quota.used -= mailbox.quota_mailbox_used;
-	}
-	else {
-	    mailbox.quota.used = 0;
-	}
-	r = quota_write(&mailbox.quota, tid);
-	if (r) {
-	    syslog(LOG_ERR,
-		   "LOSTQUOTA: unable to record free of %lu bytes in quota %s",
-		   mailbox.quota_mailbox_used, mailbox.quota.root);
-	}
-	free(mailbox.quota.root);
+        if(mboxlist_oldquota) {
+            if (strlen(mailbox.quota.root) > strlen(mboxlist_oldquota->root)) {
+                /* Part of a child quota root */
+                mailbox_close(&mailbox);
+                return 0;
+            }
+        }
+        else {
+            if (strlen(mailbox.quota.root) >= strlen(mboxlist_newquota->root)) {
+                /* Part of a child quota root */
+                mailbox_close(&mailbox);
+                return 0;
+            }
+        }
+
+        r = mailbox_updatequota(&mailbox,tid);
+        if (r)
+            goto error;
     }
 
     mailbox.quota.root = xstrdup(mboxlist_newquota->root);
@@ -2553,18 +2589,24 @@
     mboxlist_newquota->used += mailbox.quota_mailbox_used;
     mailbox_close(&mailbox);
     return 0;
-
+ 
  error:
     mailbox_close(&mailbox);
+    syslog(LOG_ERR, "LOSTQUOTA: unable to change quota root for %s to %s: %s. \
+                        Command aborted. Run reconstruct to make sure mailboxes \
+                         are in consistent state",
+           name, mboxlist_newquota->root, error_message(r));
+    return 1;
  error_noclose:
     syslog(LOG_ERR, "LOSTQUOTA: unable to change quota root for %s to %s: %s",
-	   name, mboxlist_newquota->root, error_message(r));
+           name, mboxlist_newquota->root, error_message(r));
 
     /* Note, we're a callback, and it's not a huge tragedy if we
      * fail, so we don't ever return a failure */
     return 0;
 }
 
+
 /* must be called after cyrus_init */
 void mboxlist_init(int myflags)
 {