]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/cyrus-imapd-2.2.12-rmquota+deletemailbox-0.2-1.diff
Tripwire aktualisiert.
[people/pmueller/ipfire-2.x.git] / src / patches / cyrus-imapd-2.2.12-rmquota+deletemailbox-0.2-1.diff
CommitLineData
b40388bb
MT
1diff -Naur cyrus-imapd-2.2.12.orig/imap/ctl_cyrusdb.c cyrus-imapd-2.2.12/imap/ctl_cyrusdb.c
2--- cyrus-imapd-2.2.12.orig/imap/ctl_cyrusdb.c Tue Jul 13 04:34:20 2004
3+++ cyrus-imapd-2.2.12/imap/ctl_cyrusdb.c Mon Mar 7 11:30:58 2005
4@@ -136,7 +136,7 @@
5 /* if it is MBTYPE_RESERVED, unset it & call mboxlist_delete */
6 if(!r && (mbtype & MBTYPE_RESERVE)) {
7 if(!r) {
8- r = mboxlist_deletemailbox(name, 1, NULL, NULL, 0, 0, 1);
9+ r = mboxlist_deletemailbox(name, 1, NULL, NULL, 0, 0, 1, 1);
10 if(r) {
11 /* log the error */
12 syslog(LOG_ERR,
13diff -Naur cyrus-imapd-2.2.12.orig/imap/ctl_mboxlist.c cyrus-imapd-2.2.12/imap/ctl_mboxlist.c
14--- cyrus-imapd-2.2.12.orig/imap/ctl_mboxlist.c Sat May 22 05:45:48 2004
15+++ cyrus-imapd-2.2.12/imap/ctl_mboxlist.c Mon Mar 7 11:30:58 2005
16@@ -456,7 +456,7 @@
17
18 wipe_head = wipe_head->next;
19
20- ret = mboxlist_deletemailbox(me->mailbox, 1, "", NULL, 0, 1, 1);
21+ ret = mboxlist_deletemailbox(me->mailbox, 1, "", NULL, 0, 1, 1, 1);
22 if(ret) {
23 fprintf(stderr, "couldn't delete defunct mailbox %s\n",
24 me->mailbox);
25diff -Naur cyrus-imapd-2.2.12.orig/imap/imapd.c cyrus-imapd-2.2.12/imap/imapd.c
26--- cyrus-imapd-2.2.12.orig/imap/imapd.c Mon Feb 14 07:39:55 2005
27+++ cyrus-imapd-2.2.12/imap/imapd.c Mon Mar 7 11:30:58 2005
28@@ -3724,7 +3724,7 @@
29
30 r = mboxlist_deletemailbox(name, imapd_userisadmin,
31 imapd_userid, imapd_authstate,
32- 0, 0, 0);
33+ 0, 0, 0, 1);
34
35 if(r) {
36 prot_printf(imapd_out, "* NO delete %s: %s\r\n",
37@@ -3743,6 +3743,12 @@
38 char mailboxname[MAX_MAILBOX_NAME+1];
39 char *p;
40 int domainlen = 0;
41+ int keepQuota = 1;
42+
43+ if(name && *name == '+') {
44+ keepQuota = 0;
45+ name++;
46+ }
47
48 r = (*imapd_namespace.mboxname_tointernal)(&imapd_namespace, name,
49 imapd_userid, mailboxname);
50@@ -3753,7 +3759,7 @@
51
52 r = mboxlist_deletemailbox(mailboxname, imapd_userisadmin,
53 imapd_userid, imapd_authstate, 1,
54- localonly, 0);
55+ localonly, 0, keepQuota);
56 }
57
58 /* was it a top-level user mailbox? */
59@@ -4718,6 +4724,7 @@
60 {
61 int newquota = -1;
62 int badresource = 0;
63+ int rmquota = 0;
64 int c;
65 int force = 0;
66 static struct buf arg;
67@@ -4732,7 +4739,8 @@
68 if (c != ')' || arg.s[0] != '\0') {
69 for (;;) {
70 if (c != ' ') goto badlist;
71- if (strcasecmp(arg.s, "storage") != 0) badresource = 1;
72+ if (strcasecmp(arg.s, "remove") == 0) rmquota = 1;
73+ else if (strcasecmp(arg.s, "storage") != 0) badresource = 1;
74 c = getword(imapd_in, &arg);
75 if (c != ' ' && c != ')') goto badlist;
76 if (arg.s[0] == '\0') goto badlist;
77@@ -4769,7 +4777,10 @@
78 imapd_userid, mailboxname);
79
80 if (!r) {
81- r = mboxlist_setquota(mailboxname, newquota, force);
82+ if(!rmquota)
83+ r = mboxlist_setquota(mailboxname, newquota, force);
84+ else
85+ r = mboxlist_unsetquota(mailboxname);
86 }
87 }
88
89@@ -6416,7 +6427,7 @@
90 /* note also that we need to remember to let proxyadmins do this */
91 r = mboxlist_deletemailbox(mailboxname,
92 imapd_userisadmin || imapd_userisproxyadmin,
93- imapd_userid, imapd_authstate, 0, 1, 0);
94+ imapd_userid, imapd_authstate, 0, 1, 0, 1);
95 if(r) syslog(LOG_ERR,
96 "Could not delete local mailbox during move of %s",
97 mailboxname);
98diff -Naur cyrus-imapd-2.2.12.orig/imap/mailbox.c cyrus-imapd-2.2.12/imap/mailbox.c
99--- cyrus-imapd-2.2.12.orig/imap/mailbox.c Mon Feb 14 07:39:57 2005
100+++ cyrus-imapd-2.2.12/imap/mailbox.c Mon Mar 7 11:30:58 2005
101@@ -2117,27 +2117,7 @@
102
103 seen_delete_mailbox(mailbox);
104
105- if (delete_quota_root && !rquota) {
106- quota_delete(&mailbox->quota, &tid);
107- free(mailbox->quota.root);
108- mailbox->quota.root = NULL;
109- } else if (!rquota) {
110- /* Free any quota being used by this mailbox */
111- if (mailbox->quota.used >= mailbox->quota_mailbox_used) {
112- mailbox->quota.used -= mailbox->quota_mailbox_used;
113- }
114- else {
115- mailbox->quota.used = 0;
116- }
117- r = quota_write(&mailbox->quota, &tid);
118- if (r) {
119- syslog(LOG_ERR,
120- "LOSTQUOTA: unable to record free of %lu bytes in quota %s",
121- mailbox->quota_mailbox_used, mailbox->quota.root);
122- }
123- else
124- quota_commit(&tid);
125- }
126+ mailbox_updatequota(mailbox,NULL);
127
128 /* remove all files in directory */
129 strlcpy(buf, mailbox->path, sizeof(buf));
130@@ -2751,3 +2731,49 @@
131 if (*p == '.') *p = '/';
132 }
133 }
134+
135+
136+/* This function is used to update the quota. Can be used to replace
137+ * identical parts of the code, and can be quite handy some times
138+ * The tid is used in order to make possible to make the quota update
139+ * being a part of a bigger transaction to the quota db */
140+int mailbox_updatequota(struct mailbox *mailbox, struct txn **tid)
141+{
142+ int r = 0, havetid = 0;
143+ struct txn **ltid = NULL;
144+
145+ if(tid) {
146+ ltid = tid;
147+ havetid = 1;
148+ }
149+ /* Ensure that we are locked */
150+ if(!mailbox->header_lock_count) return IMAP_INTERNAL;
151+
152+
153+ if(mailbox->quota.root) {
154+ r = quota_read(&mailbox->quota, ltid, 1);
155+ if( r == 0 ) {
156+ if (mailbox->quota.used >= mailbox->quota_mailbox_used) {
157+ mailbox->quota.used -= mailbox->quota_mailbox_used;
158+ }
159+ else {
160+ mailbox->quota.used = 0;
161+ }
162+ r = quota_write(&mailbox->quota, ltid);
163+ if (r) {
164+ syslog(LOG_ERR,
165+ "LOSTQUOTA: unable to record free of %lu bytes in quota %s",
166+ mailbox->quota_mailbox_used, mailbox->quota.root);
167+ }
168+ else if(!havetid)
169+ quota_commit(tid);
170+ }
171+ /* It is not a big mistake not to have quota .. just remove from the mailbox */
172+ else if ( r == IMAP_QUOTAROOT_NONEXISTENT) {
173+ free(mailbox->quota.root);
174+ r = 0;
175+ }
176+ }
177+ return r;
178+}
179+
180diff -Naur cyrus-imapd-2.2.12.orig/imap/mailbox.h cyrus-imapd-2.2.12/imap/mailbox.h
181--- cyrus-imapd-2.2.12.orig/imap/mailbox.h Thu Jan 22 22:17:09 2004
182+++ cyrus-imapd-2.2.12/imap/mailbox.h Mon Mar 7 11:30:58 2005
183@@ -305,6 +305,8 @@
184 struct mailbox *mailboxp);
185 extern int mailbox_delete(struct mailbox *mailbox, int delete_quota_root);
186
187+extern int mailbox_updatequota(struct mailbox *mailbox, struct txn **tid);
188+
189 extern int mailbox_rename_copy(struct mailbox *oldmailbox,
190 const char *newname, char *newpath,
191 bit32 *olduidvalidityp, bit32 *newuidvalidityp,
192diff -Naur cyrus-imapd-2.2.12.orig/imap/mboxlist.c cyrus-imapd-2.2.12/imap/mboxlist.c
193--- cyrus-imapd-2.2.12.orig/imap/mboxlist.c Mon Jul 26 20:08:03 2004
194+++ cyrus-imapd-2.2.12/imap/mboxlist.c Mon Mar 7 11:30:58 2005
195@@ -93,6 +93,11 @@
196 static int mboxlist_opensubs();
197 static void mboxlist_closesubs();
198
199+static int child_cb(char *name,
200+ int matchlen __attribute__((unused)),
201+ int maycreate __attribute__((unused)),
202+ void *rock);
203+
204 static int mboxlist_rmquota(const char *name, int matchlen, int maycreate,
205 void *rock);
206 static int mboxlist_changequota(const char *name, int matchlen, int maycreate,
207@@ -100,6 +105,7 @@
208
209 struct change_rock {
210 struct quota *quota;
211+ struct quota *oldquota;
212 struct txn **tid;
213 };
214
215@@ -893,9 +899,9 @@
216 */
217 int mboxlist_deletemailbox(const char *name, int isadmin, char *userid,
218 struct auth_state *auth_state, int checkacl,
219- int local_only, int force)
220+ int local_only, int force, int keepQuota)
221 {
222- int r;
223+ int r, has_children = 0;
224 char *acl;
225 long access;
226 struct mailbox mailbox;
227@@ -907,6 +913,7 @@
228 int deleteright = get_deleteright();
229 const char *p;
230 mupdate_handle *mupdate_h = NULL;
231+ char *quotaroot = NULL;
232
233 if(!isadmin && force) return IMAP_PERMISSION_DENIED;
234
235@@ -1018,13 +1025,44 @@
236
237 if ((r && !force) || isremote) goto done;
238
239- if (!r || force) r = mailbox_delete(&mailbox, deletequotaroot);
240+ if (!r || force) {
241+ /* first we have to keep the previous quota root in order to delete it */
242+ if(mailbox.quota.root)
243+ quotaroot = xstrdup(mailbox.quota.root);
244+ r = mailbox_delete(&mailbox, deletequotaroot);
245+ }
246
247 /*
248 * See if we have to remove mailbox's quota root
249 */
250- if (!r && mailbox.quota.root != NULL) {
251+ if (!r && quotaroot != NULL) {
252 /* xxx look for any other mailboxes in this quotaroot */
253+ /* If we have not asked to remove the quota (default behaviour), we check
254+ * whether there are any subfolders beneeth the quota root. If there aren't
255+ * any subfolders the reasonable thing is to delete the quota */
256+ if(keepQuota) {
257+ char pattern[MAX_MAILBOX_PATH+1];
258+ strlcpy(pattern, quotaroot, sizeof(pattern));
259+ if (config_virtdomains && name[strlen(name)-1] == '!') {
260+ strlcat(pattern, "*", sizeof(pattern));
261+ }
262+ else {
263+ strlcat(pattern, ".*", sizeof(pattern));
264+ }
265+ /* find if there are subfolders. Then we want to
266+ * keep the existing quota */
267+ mboxlist_findall(NULL, pattern, isadmin, userid,
268+ auth_state, child_cb, (void *) &has_children);
269+
270+ if(!has_children)
271+ if(!mboxlist_mylookup(quotaroot, NULL, NULL, NULL, NULL, NULL, 0 ))
272+ has_children = 1;
273+ }
274+ /* If we want to remove the quota explicitely or the quota root folder has no subfolders
275+ * we execute the rmquota patch */
276+ if(!keepQuota || !has_children )
277+ mboxlist_unsetquota(quotaroot);
278+ free(quotaroot);
279 }
280
281 done:
282@@ -2357,6 +2395,7 @@
283 if (r) return r;
284
285 crock.quota = &quota;
286+ crock.oldquota = NULL;
287 crock.tid = &tid;
288 /* top level mailbox */
289 if(have_mailbox)
290@@ -2375,17 +2414,21 @@
291 */
292 int mboxlist_unsetquota(const char *root)
293 {
294+ char newquota[MAX_MAILBOX_PATH+1];
295 char pattern[MAX_MAILBOX_PATH+1];
296 struct quota quota;
297- int r=0;
298+ struct change_rock crock;
299+ int r=0, k=0;
300
301 if (!root[0] || root[0] == '.' || strchr(root, '/')
302 || strchr(root, '*') || strchr(root, '%') || strchr(root, '?')) {
303 return IMAP_MAILBOX_BADNAME;
304 }
305+
306+ crock.tid=NULL;
307
308 quota.root = (char *) root;
309- r = quota_read(&quota, NULL, 0);
310+ r = quota_read(&quota, crock.tid, 0);
311 if (r == IMAP_QUOTAROOT_NONEXISTENT) {
312 /* already unset */
313 return 0;
314@@ -2402,13 +2445,45 @@
315 }
316 else
317 strlcat(pattern, ".*", sizeof(pattern));
318-
319- /* top level mailbox */
320- mboxlist_rmquota(root, 0, 0, (void *)root);
321- /* submailboxes - we're using internal names here */
322- mboxlist_findall(NULL, pattern, 1, 0, 0, mboxlist_rmquota, (void *)root);
323
324- r = quota_delete(&quota, NULL);
325+ r = quota_delete(&quota, crock.tid);
326+
327+ /* If we cannot delete the quota then abort the operation */
328+ if(!r) {
329+ /* quota_findroot performs several checks that we can
330+ * assume that are already done, and don't have to perform
331+ * them again. One of them is that it returns 1 only if
332+ * quotaroot exists.
333+ */
334+ if(quota_findroot(newquota, sizeof(newquota), root)) {
335+ struct quota rootquota;
336+ rootquota.root = newquota;
337+ k = quota_read(&rootquota, crock.tid, 0);
338+ if (!k) {
339+ crock.quota = &rootquota;
340+ crock.oldquota = &quota;
341+ /* top level mailbox */
342+ k = mboxlist_changequota(root, 0, 0, &crock);
343+ }
344+ /* submailboxes - we're using internal names here */
345+ if (!k)
346+ k = mboxlist_findall(NULL, pattern, 1, 0, 0, mboxlist_changequota, &crock);
347+ if(!k)
348+ k = quota_write(&rootquota, crock.tid);
349+
350+ }
351+ else {
352+ /* top level mailbox */
353+ mboxlist_rmquota(root, 0, 0, (void *)root);
354+ /* submailboxes - we're using internal names here */
355+ mboxlist_findall(NULL, pattern, 1, 0, 0, mboxlist_rmquota, (void *)root);
356+ }
357+ }
358+
359+ if(!r && !k)
360+ quota_commit(crock.tid);
361+ else
362+ quota_abort(crock.tid);
363
364 return r;
365 }
366@@ -2506,6 +2581,7 @@
367 struct mailbox mailbox;
368 struct change_rock *crock = (struct change_rock *) rock;
369 struct quota *mboxlist_newquota = crock->quota;
370+ struct quota *mboxlist_oldquota = crock->oldquota;
371 struct txn **tid = crock->tid;
372
373 assert(rock != NULL);
374@@ -2523,27 +2599,24 @@
375 if (r) goto error;
376
377 if (mailbox.quota.root) {
378- if (strlen(mailbox.quota.root) >= strlen(mboxlist_newquota->root)) {
379- /* Part of a child quota root */
380- mailbox_close(&mailbox);
381- return 0;
382- }
383-
384- r = quota_read(&mailbox.quota, tid, 1);
385- if (r) goto error;
386- if (mailbox.quota.used >= mailbox.quota_mailbox_used) {
387- mailbox.quota.used -= mailbox.quota_mailbox_used;
388- }
389- else {
390- mailbox.quota.used = 0;
391- }
392- r = quota_write(&mailbox.quota, tid);
393- if (r) {
394- syslog(LOG_ERR,
395- "LOSTQUOTA: unable to record free of %lu bytes in quota %s",
396- mailbox.quota_mailbox_used, mailbox.quota.root);
397- }
398- free(mailbox.quota.root);
399+ if(mboxlist_oldquota) {
400+ if (strlen(mailbox.quota.root) > strlen(mboxlist_oldquota->root)) {
401+ /* Part of a child quota root */
402+ mailbox_close(&mailbox);
403+ return 0;
404+ }
405+ }
406+ else {
407+ if (strlen(mailbox.quota.root) >= strlen(mboxlist_newquota->root)) {
408+ /* Part of a child quota root */
409+ mailbox_close(&mailbox);
410+ return 0;
411+ }
412+ }
413+
414+ r = mailbox_updatequota(&mailbox,tid);
415+ if (r)
416+ goto error;
417 }
418
419 mailbox.quota.root = xstrdup(mboxlist_newquota->root);
420@@ -2553,18 +2626,24 @@
421 mboxlist_newquota->used += mailbox.quota_mailbox_used;
422 mailbox_close(&mailbox);
423 return 0;
424-
425+
426 error:
427 mailbox_close(&mailbox);
428+ syslog(LOG_ERR, "LOSTQUOTA: unable to change quota root for %s to %s: %s. \
429+ Command aborted. Run reconstruct to make sure mailboxes \
430+ are in consistent state",
431+ name, mboxlist_newquota->root, error_message(r));
432+ return 1;
433 error_noclose:
434 syslog(LOG_ERR, "LOSTQUOTA: unable to change quota root for %s to %s: %s",
435- name, mboxlist_newquota->root, error_message(r));
436+ name, mboxlist_newquota->root, error_message(r));
437
438 /* Note, we're a callback, and it's not a huge tragedy if we
439 * fail, so we don't ever return a failure */
440 return 0;
441 }
442
443+
444 /* must be called after cyrus_init */
445 void mboxlist_init(int myflags)
446 {
447diff -Naur cyrus-imapd-2.2.12.orig/imap/mboxlist.h cyrus-imapd-2.2.12/imap/mboxlist.h
448--- cyrus-imapd-2.2.12.orig/imap/mboxlist.h Wed Mar 17 19:07:49 2004
449+++ cyrus-imapd-2.2.12/imap/mboxlist.h Mon Mar 7 11:30:58 2005
450@@ -122,7 +122,7 @@
451 * the planet */
452 int mboxlist_deletemailbox(const char *name, int isadmin, char *userid,
453 struct auth_state *auth_state, int checkacl,
454- int local_only, int force);
455+ int local_only, int force, int keepQuota);
456
457 /* Rename/move a mailbox (hierarchical) */
458 int mboxlist_renamemailbox(char *oldname, char *newname, char *partition,
459diff -Naur cyrus-imapd-2.2.12.orig/imap/mupdate.c cyrus-imapd-2.2.12/imap/mupdate.c
460--- cyrus-imapd-2.2.12.orig/imap/mupdate.c Fri Dec 17 17:32:16 2004
461+++ cyrus-imapd-2.2.12/imap/mupdate.c Mon Mar 7 11:30:58 2005
462@@ -2190,7 +2190,7 @@
463 remote_boxes.head = r->next;
464 } else if (ret < 0) {
465 /* Local without corresponding remote, delete it */
466- mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0);
467+ mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0, 1);
468 local_boxes.head = l->next;
469 } else /* (ret > 0) */ {
470 /* Remote without corresponding local, insert it */
471@@ -2205,7 +2205,7 @@
472 if(l && !r) {
473 /* we have more deletes to do */
474 while(l) {
475- mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0);
476+ mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0, 1);
477 local_boxes.head = l->next;
478 l = local_boxes.head;
479 }
480diff -Naur cyrus-imapd-2.2.12.orig/imap/nntpd.c cyrus-imapd-2.2.12/imap/nntpd.c
481--- cyrus-imapd-2.2.12.orig/imap/nntpd.c Fri Jan 7 21:59:04 2005
482+++ cyrus-imapd-2.2.12/imap/nntpd.c Mon Mar 7 11:30:58 2005
483@@ -3298,7 +3298,7 @@
484 /* XXX should we delete right away, or wait until empty? */
485
486 r = mboxlist_deletemailbox(mailboxname, 0,
487- newsmaster, newsmaster_authstate, 1, 0, 0);
488+ newsmaster, newsmaster_authstate, 1, 0, 0, 1);
489
490 return r;
491 }