Mailbox quota support in imap4d: initial implementation.
* imap4d/quota.c: New file. * imap4d/Makefile.am (imap4d_SOURCES): Add quota.c * imap4d/append.c (imap4d_append0): Refuse to append if the quota is exceeded or would be exceeded after completing the operation. * imap4d/copy.c (imap4d_copy0): Refuse to copy messages if the quota is exceeded or would be exceeded after completing the operation. Return a meaningful textual description. Attempt to restore mailbox to its original size if the operation failed. * imap4d/imap4d.c (imap4d_session_setup0): Call quota_setup. * imap4d/imap4d.h (quota_setup, quota_check, quota_update): New functions. * include/mailutils/folder.h (mu_list_response) <format>: New member. * include/mailutils/mailbox.h (mu_mailbox_create_from_record): New function. * include/mailutils/types.hin (MU_FOLDER_ATTRIBUTE_LINK): New flag. * libproto/mbox/folder.c (list_helper): Do not return symbolic links unless MU_FOLDER_ATTRIBUTE_LINK is set. Fill in the resp->format member. * mailbox/mailbox.c (_mailbox_create_from_record): New static function. (_create_mailbox0): Rewrite as a wrapper over _mailbox_create_from_record. (mu_mailbox_create_from_record): New function.
Showing
11 changed files
with
533 additions
and
109 deletions
... | @@ -71,10 +71,11 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text, | ... | @@ -71,10 +71,11 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text, |
71 | struct tm *tm; | 71 | struct tm *tm; |
72 | time_t t; | 72 | time_t t; |
73 | mu_envelope_t env; | 73 | mu_envelope_t env; |
74 | 74 | size_t size; | |
75 | |||
75 | if (mu_message_create (&msg, &tm)) | 76 | if (mu_message_create (&msg, &tm)) |
76 | return 1; | 77 | return 1; |
77 | 78 | ||
78 | if (mu_memory_stream_create (&stream, MU_STREAM_RDWR) | 79 | if (mu_memory_stream_create (&stream, MU_STREAM_RDWR) |
79 | || mu_stream_open (stream)) | 80 | || mu_stream_open (stream)) |
80 | { | 81 | { |
... | @@ -94,9 +95,9 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text, | ... | @@ -94,9 +95,9 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text, |
94 | } | 95 | } |
95 | } | 96 | } |
96 | else | 97 | else |
97 | time(&t); | 98 | time (&t); |
98 | 99 | ||
99 | tm = gmtime(&t); | 100 | tm = gmtime (&t); |
100 | 101 | ||
101 | while (*text && mu_isblank (*text)) | 102 | while (*text && mu_isblank (*text)) |
102 | text++; | 103 | text++; |
... | @@ -109,15 +110,40 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text, | ... | @@ -109,15 +110,40 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text, |
109 | mu_envelope_set_date (env, _append_date, msg); | 110 | mu_envelope_set_date (env, _append_date, msg); |
110 | mu_envelope_set_sender (env, _append_sender, msg); | 111 | mu_envelope_set_sender (env, _append_sender, msg); |
111 | mu_message_set_envelope (msg, env, &tm); | 112 | mu_message_set_envelope (msg, env, &tm); |
113 | |||
114 | rc = _append_size (msg, &size); | ||
115 | if (rc) | ||
116 | { | ||
117 | mu_diag_output (MU_DIAG_NOTICE, | ||
118 | _("cannot compute size of the message being appended; " | ||
119 | "using estimated value: %s"), | ||
120 | mu_strerror (rc)); | ||
121 | /* raw estimate */ | ||
122 | size = strlen (text); | ||
123 | } | ||
124 | rc = quota_check (size); | ||
125 | if (rc != RESP_OK) | ||
126 | { | ||
127 | *err_text = rc == RESP_NO ? | ||
128 | "Mailbox quota exceeded" : "Operation failed"; | ||
129 | mu_message_destroy (&msg, &tm); | ||
130 | return 1; | ||
131 | } | ||
132 | |||
112 | rc = mu_mailbox_append_message (mbox, msg); | 133 | rc = mu_mailbox_append_message (mbox, msg); |
113 | if (rc == 0 && flags) | 134 | if (rc == 0) |
114 | { | 135 | { |
115 | size_t num = 0; | 136 | if (flags) |
116 | mu_attribute_t attr = NULL; | 137 | { |
117 | mu_mailbox_messages_count (mbox, &num); | 138 | size_t num = 0; |
118 | mu_mailbox_get_message (mbox, num, &msg); | 139 | mu_attribute_t attr = NULL; |
119 | mu_message_get_attribute (msg, &attr); | 140 | mu_mailbox_messages_count (mbox, &num); |
120 | mu_attribute_set_flags (attr, flags); | 141 | mu_mailbox_get_message (mbox, num, &msg); |
142 | mu_message_get_attribute (msg, &attr); | ||
143 | mu_attribute_set_flags (attr, flags); | ||
144 | } | ||
145 | /* FIXME: If not INBOX */ | ||
146 | quota_update (size); | ||
121 | } | 147 | } |
122 | 148 | ||
123 | mu_message_destroy (&msg, &tm); | 149 | mu_message_destroy (&msg, &tm); | ... | ... |
... | @@ -57,6 +57,153 @@ imap4d_copy (struct imap4d_command *command, imap4d_tokbuf_t tok) | ... | @@ -57,6 +57,153 @@ imap4d_copy (struct imap4d_command *command, imap4d_tokbuf_t tok) |
57 | return io_completion_response (command, rc, "%s", text); | 57 | return io_completion_response (command, rc, "%s", text); |
58 | } | 58 | } |
59 | 59 | ||
60 | static int | ||
61 | copy_check_size (mu_mailbox_t mbox, size_t n, size_t *set, mu_off_t *size) | ||
62 | { | ||
63 | int status; | ||
64 | size_t i; | ||
65 | mu_off_t total = 0; | ||
66 | |||
67 | for (i = 0; i < n; i++) | ||
68 | { | ||
69 | mu_message_t msg = NULL; | ||
70 | size_t msgno = set[i]; | ||
71 | if (msgno) | ||
72 | { | ||
73 | status = mu_mailbox_get_message (mbox, msgno, &msg); | ||
74 | if (status) | ||
75 | { | ||
76 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL, | ||
77 | status); | ||
78 | return RESP_BAD; | ||
79 | } | ||
80 | else | ||
81 | { | ||
82 | size_t size; | ||
83 | status = mu_message_size (msg, &size); | ||
84 | if (status) | ||
85 | { | ||
86 | mu_diag_funcall (MU_DIAG_ERROR, "mu_message_size", NULL, | ||
87 | status); | ||
88 | return RESP_BAD; | ||
89 | } | ||
90 | total += size; | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | *size = total; | ||
95 | return quota_check (total); | ||
96 | } | ||
97 | |||
98 | static int | ||
99 | try_copy (mu_mailbox_t dst, mu_mailbox_t src, size_t n, size_t *set) | ||
100 | { | ||
101 | int result; | ||
102 | size_t i; | ||
103 | mu_off_t total; | ||
104 | |||
105 | result = copy_check_size (src, n, set, &total); | ||
106 | if (result) | ||
107 | return result; | ||
108 | |||
109 | for (i = 0; i < n; i++) | ||
110 | { | ||
111 | mu_message_t msg = NULL; | ||
112 | size_t msgno = set[i]; | ||
113 | |||
114 | if (msgno) | ||
115 | { | ||
116 | int status = mu_mailbox_get_message (src, msgno, &msg); | ||
117 | if (status) | ||
118 | { | ||
119 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL, | ||
120 | status); | ||
121 | return RESP_BAD; | ||
122 | } | ||
123 | |||
124 | status = mu_mailbox_append_message (dst, msg); | ||
125 | if (status) | ||
126 | { | ||
127 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_append_message", | ||
128 | NULL, | ||
129 | status); | ||
130 | return RESP_BAD; | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | quota_update (total); | ||
135 | return RESP_OK; | ||
136 | } | ||
137 | |||
138 | static int | ||
139 | safe_copy (mu_mailbox_t dst, mu_mailbox_t src, size_t n, size_t *set, | ||
140 | char **err_text) | ||
141 | { | ||
142 | size_t nmesg; | ||
143 | int status; | ||
144 | |||
145 | status = mu_mailbox_messages_count (dst, &nmesg); | ||
146 | if (status) | ||
147 | { | ||
148 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_messages_count", | ||
149 | NULL, status); | ||
150 | *err_text = "Operation failed"; | ||
151 | return RESP_NO; | ||
152 | } | ||
153 | |||
154 | status = try_copy (dst, src, n, set); | ||
155 | if (status) | ||
156 | { | ||
157 | size_t maxmesg; | ||
158 | |||
159 | if (status == RESP_NO) | ||
160 | *err_text = "Mailbox quota exceeded"; | ||
161 | else | ||
162 | *err_text = "Operation failed"; | ||
163 | |||
164 | /* If the COPY command is unsuccessful for any reason, server | ||
165 | implementations MUST restore the destination mailbox to its state | ||
166 | before the COPY attempt. */ | ||
167 | |||
168 | status = mu_mailbox_messages_count (dst, &maxmesg); | ||
169 | if (status) | ||
170 | { | ||
171 | mu_url_t url = NULL; | ||
172 | |||
173 | mu_mailbox_get_url (dst, &url); | ||
174 | mu_error (_("cannot count messages in mailbox %s: %s"), | ||
175 | mu_url_to_string (url), mu_strerror (status)); | ||
176 | imap4d_bye (ERR_MAILBOX_CORRUPTED); | ||
177 | } | ||
178 | |||
179 | for (nmesg++; nmesg <= maxmesg; nmesg++) | ||
180 | { | ||
181 | mu_message_t msg; | ||
182 | |||
183 | if (mu_mailbox_get_message (dst, nmesg, &msg) == 0) | ||
184 | { | ||
185 | mu_attribute_t attr; | ||
186 | mu_message_get_attribute (msg, &attr); | ||
187 | mu_attribute_set_userflag (attr, MU_ATTRIBUTE_DELETED); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | status = mu_mailbox_flush (dst, 1); | ||
192 | if (status) | ||
193 | { | ||
194 | mu_url_t url = NULL; | ||
195 | |||
196 | mu_mailbox_get_url (dst, &url); | ||
197 | mu_error (_("cannot flush mailbox %s: %s"), | ||
198 | mu_url_to_string (url), mu_strerror (status)); | ||
199 | imap4d_bye (ERR_MAILBOX_CORRUPTED); | ||
200 | } | ||
201 | return RESP_NO; | ||
202 | } | ||
203 | |||
204 | return RESP_OK; | ||
205 | } | ||
206 | |||
60 | int | 207 | int |
61 | imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | 208 | imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) |
62 | { | 209 | { |
... | @@ -70,7 +217,8 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | ... | @@ -70,7 +217,8 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) |
70 | mu_mailbox_t cmbox = NULL; | 217 | mu_mailbox_t cmbox = NULL; |
71 | int arg = IMAP4_ARG_1 + !!isuid; | 218 | int arg = IMAP4_ARG_1 + !!isuid; |
72 | int ns; | 219 | int ns; |
73 | 220 | ||
221 | *err_text = NULL; | ||
74 | if (imap4d_tokbuf_argc (tok) != arg + 2) | 222 | if (imap4d_tokbuf_argc (tok) != arg + 2) |
75 | { | 223 | { |
76 | *err_text = "Invalid arguments"; | 224 | *err_text = "Invalid arguments"; |
... | @@ -89,11 +237,19 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | ... | @@ -89,11 +237,19 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) |
89 | return RESP_OK; | 237 | return RESP_OK; |
90 | } | 238 | } |
91 | 239 | ||
240 | if (isuid) | ||
241 | { | ||
242 | int i; | ||
243 | /* Fixup the message set. Perhaps util_msgset should do it itself? */ | ||
244 | for (i = 0; i < n; i++) | ||
245 | set[i] = uid_to_msgno (set[i]); | ||
246 | } | ||
247 | |||
92 | mailbox_name = namespace_getfullpath (name, delim, &ns); | 248 | mailbox_name = namespace_getfullpath (name, delim, &ns); |
93 | 249 | ||
94 | if (!mailbox_name) | 250 | if (!mailbox_name) |
95 | { | 251 | { |
96 | *err_text = "NO Copy failed."; | 252 | *err_text = "Copy failed"; |
97 | return RESP_NO; | 253 | return RESP_NO; |
98 | } | 254 | } |
99 | 255 | ||
... | @@ -106,14 +262,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | ... | @@ -106,14 +262,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) |
106 | status = mu_mailbox_open (cmbox, MU_STREAM_RDWR | mailbox_mode[ns]); | 262 | status = mu_mailbox_open (cmbox, MU_STREAM_RDWR | mailbox_mode[ns]); |
107 | if (status == 0) | 263 | if (status == 0) |
108 | { | 264 | { |
109 | size_t i; | 265 | status = safe_copy (cmbox, mbox, n, set, err_text); |
110 | for (i = 0; i < n; i++) | ||
111 | { | ||
112 | mu_message_t msg = NULL; | ||
113 | size_t msgno = (isuid) ? uid_to_msgno (set[i]) : set[i]; | ||
114 | if (msgno && mu_mailbox_get_message (mbox, msgno, &msg) == 0) | ||
115 | mu_mailbox_append_message (cmbox, msg); | ||
116 | } | ||
117 | mu_mailbox_close (cmbox); | 266 | mu_mailbox_close (cmbox); |
118 | } | 267 | } |
119 | mu_mailbox_destroy (&cmbox); | 268 | mu_mailbox_destroy (&cmbox); |
... | @@ -132,6 +281,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | ... | @@ -132,6 +281,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) |
132 | of the text of the tagged NO response. This gives a hint to the | 281 | of the text of the tagged NO response. This gives a hint to the |
133 | client that it can attempt a CREATE command and retry the copy if | 282 | client that it can attempt a CREATE command and retry the copy if |
134 | the CREATE is successful. */ | 283 | the CREATE is successful. */ |
135 | *err_text = "[TRYCREATE] failed"; | 284 | if (!*err_text) |
285 | *err_text = "[TRYCREATE] failed"; | ||
136 | return RESP_NO; | 286 | return RESP_NO; |
137 | } | 287 | } | ... | ... |
... | @@ -352,9 +352,14 @@ imap4d_session_setup0 () | ... | @@ -352,9 +352,14 @@ imap4d_session_setup0 () |
352 | 352 | ||
353 | util_chdir (imap4d_homedir); | 353 | util_chdir (imap4d_homedir); |
354 | namespace_init_session (imap4d_homedir); | 354 | namespace_init_session (imap4d_homedir); |
355 | |||
355 | mu_diag_output (MU_DIAG_INFO, | 356 | mu_diag_output (MU_DIAG_INFO, |
356 | _("user `%s' logged in (source: %s)"), auth_data->name, | 357 | _("user `%s' logged in (source: %s)"), auth_data->name, |
357 | auth_data->source); | 358 | auth_data->source); |
359 | |||
360 | if (auth_data->quota) | ||
361 | quota_setup (); | ||
362 | |||
358 | return 0; | 363 | return 0; |
359 | } | 364 | } |
360 | 365 | ... | ... |
... | @@ -423,7 +423,12 @@ extern void auth_gsasl_init (void); | ... | @@ -423,7 +423,12 @@ extern void auth_gsasl_init (void); |
423 | #else | 423 | #else |
424 | # define auth_gsasl_init() | 424 | # define auth_gsasl_init() |
425 | #endif | 425 | #endif |
426 | 426 | ||
427 | /* Quota support */ | ||
428 | void quota_setup (void); | ||
429 | int quota_check (mu_off_t size); | ||
430 | void quota_update (mu_off_t size); | ||
431 | |||
427 | #ifdef __cplusplus | 432 | #ifdef __cplusplus |
428 | } | 433 | } |
429 | #endif | 434 | #endif | ... | ... |
imap4d/quota.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, | ||
3 | 2009, 2010 Free Software Foundation, Inc. | ||
4 | |||
5 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 3, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | GNU Mailutils is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #include "imap4d.h" | ||
19 | |||
20 | struct imap4d_sizeinfo | ||
21 | { | ||
22 | mu_off_t size; | ||
23 | mu_off_t nfiles; | ||
24 | mu_off_t ndirs; | ||
25 | mu_off_t nerrs; | ||
26 | }; | ||
27 | |||
28 | static int | ||
29 | addsize (mu_folder_t folder, struct mu_list_response *resp, void *data) | ||
30 | { | ||
31 | struct imap4d_sizeinfo *si = data; | ||
32 | |||
33 | if (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY) | ||
34 | si->ndirs++; | ||
35 | |||
36 | if (resp->type & MU_FOLDER_ATTRIBUTE_FILE) | ||
37 | { | ||
38 | mu_off_t size; | ||
39 | mu_mailbox_t mbox; | ||
40 | int rc; | ||
41 | |||
42 | si->nfiles++; | ||
43 | |||
44 | rc = mu_mailbox_create_from_record (&mbox, resp->format, resp->name); | ||
45 | |||
46 | if (rc) | ||
47 | { | ||
48 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_from_record", | ||
49 | resp->name, rc); | ||
50 | si->nerrs++; | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | rc = mu_mailbox_open (mbox, MU_STREAM_READ); | ||
55 | if (rc) | ||
56 | { | ||
57 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open", | ||
58 | resp->name, rc); | ||
59 | si->nerrs++; | ||
60 | mu_mailbox_destroy (&mbox); | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | rc = mu_mailbox_get_size (mbox, &size); | ||
65 | mu_mailbox_destroy (&mbox); | ||
66 | |||
67 | if (rc) | ||
68 | { | ||
69 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open", | ||
70 | resp->name, rc); | ||
71 | si->nerrs++; | ||
72 | return 0; | ||
73 | } | ||
74 | si->size += size; | ||
75 | } | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | void | ||
80 | directory_size (const char *dirname, mu_off_t *size) | ||
81 | { | ||
82 | mu_folder_t folder; | ||
83 | struct imap4d_sizeinfo sizeinfo; | ||
84 | int status; | ||
85 | |||
86 | status = mu_folder_create (&folder, dirname); | ||
87 | if (status) | ||
88 | { | ||
89 | mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", dirname, status); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | status = mu_folder_open (folder, MU_STREAM_READ); | ||
94 | if (status) | ||
95 | { | ||
96 | mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", dirname, status); | ||
97 | mu_folder_destroy (&folder); | ||
98 | return; | ||
99 | } | ||
100 | |||
101 | memset (&sizeinfo, 0, sizeof (sizeinfo)); | ||
102 | status = mu_folder_enumerate (folder, NULL, "*", 0, 0, NULL, | ||
103 | addsize, &sizeinfo); | ||
104 | if (status) | ||
105 | mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_enumerate", dirname, status); | ||
106 | else | ||
107 | { | ||
108 | mu_diag_output (MU_DIAG_INFO, | ||
109 | _("%s statistics: size=%lu, ndirs=%lu, nfiles=%lu, nerrs=%lu"), | ||
110 | dirname, | ||
111 | (unsigned long)sizeinfo.size, | ||
112 | (unsigned long)sizeinfo.ndirs, | ||
113 | (unsigned long)sizeinfo.nfiles, | ||
114 | (unsigned long)sizeinfo.nerrs); | ||
115 | } | ||
116 | *size = sizeinfo.size; | ||
117 | } | ||
118 | |||
119 | |||
120 | mu_off_t used_size; | ||
121 | |||
122 | void | ||
123 | quota_setup () | ||
124 | { | ||
125 | directory_size (imap4d_homedir, &used_size); | ||
126 | } | ||
127 | |||
128 | int | ||
129 | quota_check (mu_off_t size) | ||
130 | { | ||
131 | char *mailbox_name; | ||
132 | mu_mailbox_t mbox; | ||
133 | mu_off_t total; | ||
134 | int rc; | ||
135 | |||
136 | if (auth_data->quota == 0) | ||
137 | return RESP_OK; | ||
138 | |||
139 | total = used_size; | ||
140 | |||
141 | mailbox_name = namespace_getfullpath ("INBOX", "/", NULL); | ||
142 | rc = mu_mailbox_create (&mbox, mailbox_name); | ||
143 | if (rc) | ||
144 | { | ||
145 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create", mailbox_name, rc); | ||
146 | free (mailbox_name); | ||
147 | } | ||
148 | else | ||
149 | { | ||
150 | do | ||
151 | { | ||
152 | mu_off_t mbsize; | ||
153 | |||
154 | rc = mu_mailbox_open (mbox, MU_STREAM_READ); | ||
155 | if (rc) | ||
156 | { | ||
157 | if (rc != ENOENT) | ||
158 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open", | ||
159 | mailbox_name, rc); | ||
160 | break; | ||
161 | } | ||
162 | |||
163 | rc = mu_mailbox_get_size (mbox, &mbsize); | ||
164 | if (rc) | ||
165 | { | ||
166 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_size", | ||
167 | mailbox_name, rc); | ||
168 | mu_mailbox_close (mbox); | ||
169 | break; | ||
170 | } | ||
171 | total += mbsize; | ||
172 | mu_mailbox_close (mbox); | ||
173 | } | ||
174 | while (0); | ||
175 | mu_mailbox_destroy (&mbox); | ||
176 | } | ||
177 | free (mailbox_name); | ||
178 | |||
179 | if (rc) | ||
180 | return RESP_BAD; | ||
181 | |||
182 | if (total > auth_data->quota) | ||
183 | { | ||
184 | mu_diag_output (MU_DIAG_NOTICE, | ||
185 | _("user %s is out of mailbox quota"), | ||
186 | auth_data->name); | ||
187 | return RESP_NO; | ||
188 | } | ||
189 | else if (total + size > auth_data->quota) | ||
190 | { | ||
191 | mu_diag_output (MU_DIAG_NOTICE, | ||
192 | _("user %s: adding %lu bytes would exceed mailbox quota"), | ||
193 | auth_data->name, (unsigned long) size); | ||
194 | return RESP_NO; | ||
195 | } | ||
196 | return RESP_OK; | ||
197 | } | ||
198 | |||
199 | void | ||
200 | quota_update (mu_off_t size) | ||
201 | { | ||
202 | used_size += size; | ||
203 | } |
... | @@ -32,6 +32,7 @@ struct mu_list_response | ... | @@ -32,6 +32,7 @@ struct mu_list_response |
32 | int level; | 32 | int level; |
33 | int separator; | 33 | int separator; |
34 | char *name; | 34 | char *name; |
35 | mu_record_t format; /* Associated mailbox format record */ | ||
35 | }; | 36 | }; |
36 | 37 | ||
37 | typedef int (*mu_folder_match_fp) (const char *, void *, int); | 38 | typedef int (*mu_folder_match_fp) (const char *, void *, int); | ... | ... |
... | @@ -40,9 +40,12 @@ int mu_construct_user_mailbox_url (char **pout, const char *name); | ... | @@ -40,9 +40,12 @@ int mu_construct_user_mailbox_url (char **pout, const char *name); |
40 | /* Constructor/destructor and possible types. */ | 40 | /* Constructor/destructor and possible types. */ |
41 | extern int mu_mailbox_create (mu_mailbox_t *, const char *); | 41 | extern int mu_mailbox_create (mu_mailbox_t *, const char *); |
42 | extern int mu_mailbox_create_from_url (mu_mailbox_t *, mu_url_t); | 42 | extern int mu_mailbox_create_from_url (mu_mailbox_t *, mu_url_t); |
43 | extern int mu_mailbox_create_from_record (mu_mailbox_t *pmbox, | ||
44 | mu_record_t record, | ||
45 | const char *name); | ||
46 | extern int mu_mailbox_create_default (mu_mailbox_t *, const char *); | ||
43 | 47 | ||
44 | extern void mu_mailbox_destroy (mu_mailbox_t *); | 48 | extern void mu_mailbox_destroy (mu_mailbox_t *); |
45 | extern int mu_mailbox_create_default (mu_mailbox_t *, const char *); | ||
46 | 49 | ||
47 | extern int mu_mailbox_open (mu_mailbox_t, int flag); | 50 | extern int mu_mailbox_open (mu_mailbox_t, int flag); |
48 | extern int mu_mailbox_close (mu_mailbox_t); | 51 | extern int mu_mailbox_close (mu_mailbox_t); | ... | ... |
... | @@ -118,8 +118,9 @@ typedef struct _mu_progmailer *mu_progmailer_t; | ... | @@ -118,8 +118,9 @@ typedef struct _mu_progmailer *mu_progmailer_t; |
118 | typedef struct _mu_secret *mu_secret_t; | 118 | typedef struct _mu_secret *mu_secret_t; |
119 | typedef struct _mu_mime_io_buffer *mu_mime_io_buffer_t; | 119 | typedef struct _mu_mime_io_buffer *mu_mime_io_buffer_t; |
120 | 120 | ||
121 | #define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001 | 121 | #define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001 |
122 | #define MU_FOLDER_ATTRIBUTE_FILE 0x002 | 122 | #define MU_FOLDER_ATTRIBUTE_FILE 0x002 |
123 | #define MU_FOLDER_ATTRIBUTE_LINK 0x004 | ||
123 | 124 | ||
124 | #define MU_FOLDER_ATTRIBUTE_ALL \ | 125 | #define MU_FOLDER_ATTRIBUTE_ALL \ |
125 | (MU_FOLDER_ATTRIBUTE_DIRECTORY|MU_FOLDER_ATTRIBUTE_FILE) | 126 | (MU_FOLDER_ATTRIBUTE_DIRECTORY|MU_FOLDER_ATTRIBUTE_FILE) | ... | ... |
... | @@ -315,7 +315,7 @@ list_helper (struct search_data *data, mu_record_t record, | ... | @@ -315,7 +315,7 @@ list_helper (struct search_data *data, mu_record_t record, |
315 | DIR *dirp; | 315 | DIR *dirp; |
316 | struct dirent *dp; | 316 | struct dirent *dp; |
317 | int stop = 0; | 317 | int stop = 0; |
318 | 318 | ||
319 | if (data->max_level && level > data->max_level) | 319 | if (data->max_level && level > data->max_level) |
320 | return 0; | 320 | return 0; |
321 | 321 | ||
... | @@ -345,13 +345,15 @@ list_helper (struct search_data *data, mu_record_t record, | ... | @@ -345,13 +345,15 @@ list_helper (struct search_data *data, mu_record_t record, |
345 | if (ename[ename[0] != '.' ? 0 : ename[1] != '.' ? 1 : 2] == 0) | 345 | if (ename[ename[0] != '.' ? 0 : ename[1] != '.' ? 1 : 2] == 0) |
346 | continue; | 346 | continue; |
347 | fname = get_pathname (dirname, ename); | 347 | fname = get_pathname (dirname, ename); |
348 | if (stat (fname, &st) == 0) | 348 | if (lstat (fname, &st) == 0) |
349 | { | 349 | { |
350 | int f; | 350 | int f; |
351 | if (S_ISDIR (st.st_mode)) | 351 | if (S_ISDIR (st.st_mode)) |
352 | f = MU_FOLDER_ATTRIBUTE_DIRECTORY; | 352 | f = MU_FOLDER_ATTRIBUTE_DIRECTORY; |
353 | else if (S_ISREG (st.st_mode)) | 353 | else if (S_ISREG (st.st_mode)) |
354 | f = MU_FOLDER_ATTRIBUTE_FILE; | 354 | f = MU_FOLDER_ATTRIBUTE_FILE; |
355 | else if (S_ISLNK (st.st_mode)) | ||
356 | f = MU_FOLDER_ATTRIBUTE_LINK; | ||
355 | else | 357 | else |
356 | f = 0; | 358 | f = 0; |
357 | if (mu_record_list_p (record, ename, f)) | 359 | if (mu_record_list_p (record, ename, f)) |
... | @@ -386,6 +388,7 @@ list_helper (struct search_data *data, mu_record_t record, | ... | @@ -386,6 +388,7 @@ list_helper (struct search_data *data, mu_record_t record, |
386 | resp->level = level; | 388 | resp->level = level; |
387 | resp->separator = '/'; | 389 | resp->separator = '/'; |
388 | resp->type = type; | 390 | resp->type = type; |
391 | resp->format = rec; | ||
389 | 392 | ||
390 | if (resp->type == 0) | 393 | if (resp->type == 0) |
391 | { | 394 | { | ... | ... |
... | @@ -69,102 +69,110 @@ mailbox_folder_create (mu_mailbox_t mbox, const char *name, | ... | @@ -69,102 +69,110 @@ mailbox_folder_create (mu_mailbox_t mbox, const char *name, |
69 | return rc; | 69 | return rc; |
70 | } | 70 | } |
71 | 71 | ||
72 | static int | 72 | int |
73 | _create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name) | 73 | _mailbox_create_from_record (mu_mailbox_t *pmbox, |
74 | mu_record_t record, | ||
75 | mu_url_t url, | ||
76 | const char *name) | ||
74 | { | 77 | { |
75 | int status; | 78 | mu_log_level_t level; |
76 | mu_record_t record = NULL; | 79 | int (*m_init) (mu_mailbox_t) = NULL; |
77 | 80 | ||
78 | if (mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL) | 81 | mu_record_get_mailbox (record, &m_init); |
79 | == 0) | 82 | if (m_init) |
80 | { | 83 | { |
81 | mu_log_level_t level; | 84 | int status; |
82 | int (*m_init) (mu_mailbox_t) = NULL; | 85 | int (*u_init) (mu_url_t) = NULL; |
86 | mu_mailbox_t mbox; | ||
83 | 87 | ||
84 | mu_record_get_mailbox (record, &m_init); | 88 | /* Allocate memory for mbox. */ |
85 | if (m_init) | 89 | mbox = calloc (1, sizeof (*mbox)); |
86 | { | 90 | if (mbox == NULL) |
87 | int (*u_init) (mu_url_t) = NULL; | 91 | return ENOMEM; |
88 | mu_mailbox_t mbox; | 92 | |
89 | 93 | /* Initialize the internal lock now, so the concrete mailbox | |
90 | /* Allocate memory for mbox. */ | 94 | could use it. */ |
91 | mbox = calloc (1, sizeof (*mbox)); | 95 | status = mu_monitor_create (&mbox->monitor, 0, mbox); |
92 | if (mbox == NULL) | 96 | if (status != 0) |
93 | return ENOMEM; | 97 | { |
94 | 98 | mu_mailbox_destroy (&mbox); | |
95 | /* Initialize the internal lock now, so the concrete mailbox | 99 | return status; |
96 | could use it. */ | 100 | } |
97 | status = mu_monitor_create (&mbox->monitor, 0, mbox); | 101 | |
98 | if (status != 0) | 102 | /* Make sure scheme contains actual mailbox scheme */ |
99 | { | 103 | /* FIXME: It is appropriate not for all record types. For now we |
100 | mu_mailbox_destroy (&mbox); | 104 | assume that if the record scheme ends with a plus sign, this |
101 | return status; | 105 | should not be done. Probably it requires some flag in struct |
102 | } | 106 | _mu_record? */ |
103 | 107 | if (strcmp (url->scheme, record->scheme)) | |
104 | /* Make sure scheme contains actual mailbox scheme */ | 108 | { |
105 | /* FIXME: It is appropriate not for all record types. For now we | 109 | char *p = strdup (record->scheme); |
106 | assume that if the record scheme ends with a plus sign, this | 110 | if (!p) |
107 | should not be done. Probably it requires some flag in struct | ||
108 | _mu_record? */ | ||
109 | if (strcmp (url->scheme, record->scheme)) | ||
110 | { | ||
111 | char *p = strdup (record->scheme); | ||
112 | if (!p) | ||
113 | { | ||
114 | mu_mailbox_destroy (&mbox); | ||
115 | return errno; | ||
116 | } | ||
117 | free (url->scheme); | ||
118 | url->scheme = p; | ||
119 | } | ||
120 | |||
121 | mu_record_get_url (record, &u_init); | ||
122 | if (u_init && (status = u_init (url)) != 0) | ||
123 | { | 111 | { |
124 | mu_mailbox_destroy (&mbox); | 112 | mu_mailbox_destroy (&mbox); |
125 | return status; | 113 | return errno; |
126 | } | 114 | } |
127 | 115 | free (url->scheme); | |
128 | mbox->url = url; | 116 | url->scheme = p; |
129 | 117 | } | |
130 | /* Create the folder before initializing the concrete mailbox. | 118 | |
131 | The mailbox needs it's back pointer. */ | 119 | mu_record_get_url (record, &u_init); |
132 | status = mailbox_folder_create (mbox, name, record); | 120 | if (u_init && (status = u_init (url)) != 0) |
121 | { | ||
122 | mu_mailbox_destroy (&mbox); | ||
123 | return status; | ||
124 | } | ||
125 | |||
126 | mbox->url = url; | ||
127 | |||
128 | /* Create the folder before initializing the concrete mailbox. | ||
129 | The mailbox needs it's back pointer. */ | ||
130 | status = mailbox_folder_create (mbox, name, record); | ||
131 | |||
132 | if (status == 0) | ||
133 | status = m_init (mbox); /* Create the concrete mailbox type. */ | ||
134 | |||
135 | if (status != 0) | ||
136 | { | ||
137 | /* Take care not to destroy url. Leave it to caller. */ | ||
138 | mbox->url = NULL; | ||
139 | mu_mailbox_destroy (&mbox); | ||
140 | } | ||
141 | else | ||
142 | { | ||
143 | *pmbox = mbox; | ||
133 | 144 | ||
134 | if (status == 0) | 145 | level = mu_global_debug_level ("mailbox"); |
135 | status = m_init (mbox); /* Create the concrete mailbox type. */ | 146 | if (level) |
136 | |||
137 | if (status != 0) | ||
138 | { | ||
139 | /* Take care not to destroy url. Leave it to caller. */ | ||
140 | mbox->url = NULL; | ||
141 | mu_mailbox_destroy (&mbox); | ||
142 | } | ||
143 | else | ||
144 | { | 147 | { |
145 | *pmbox = mbox; | 148 | int status = mu_debug_create (&mbox->debug, mbox); |
146 | 149 | if (status) | |
147 | level = mu_global_debug_level ("mailbox"); | 150 | return 0; /* FIXME: don't want to bail out just because I |
148 | if (level) | 151 | failed to create a *debug* object. But I may |
149 | { | 152 | be wrong... */ |
150 | int status = mu_debug_create (&mbox->debug, mbox); | 153 | mu_debug_set_level (mbox->debug, level); |
151 | if (status) | 154 | if (level & MU_DEBUG_INHERIT) |
152 | return 0; /* FIXME: don't want to bail out just because I | 155 | mu_folder_set_debug (mbox->folder, mbox->debug); |
153 | failed to create a *debug* object. But I may | ||
154 | be wrong... */ | ||
155 | mu_debug_set_level (mbox->debug, level); | ||
156 | if (level & MU_DEBUG_INHERIT) | ||
157 | mu_folder_set_debug (mbox->folder, mbox->debug); | ||
158 | } | ||
159 | } | 156 | } |
160 | |||
161 | return status; | ||
162 | } | 157 | } |
158 | |||
159 | return status; | ||
163 | } | 160 | } |
164 | return MU_ERR_NO_HANDLER; | 161 | return MU_ERR_NO_HANDLER; |
165 | } | 162 | } |
166 | 163 | ||
167 | static int | 164 | static int |
165 | _create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name) | ||
166 | { | ||
167 | mu_record_t record = NULL; | ||
168 | |||
169 | if (mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL) | ||
170 | == 0) | ||
171 | return _mailbox_create_from_record (pmbox, record, url, name); | ||
172 | return MU_ERR_NO_HANDLER; | ||
173 | } | ||
174 | |||
175 | static int | ||
168 | _create_mailbox (mu_mailbox_t *pmbox, const char *name) | 176 | _create_mailbox (mu_mailbox_t *pmbox, const char *name) |
169 | { | 177 | { |
170 | int status; | 178 | int status; |
... | @@ -202,6 +210,24 @@ mu_mailbox_create_from_url (mu_mailbox_t *pmbox, mu_url_t url) | ... | @@ -202,6 +210,24 @@ mu_mailbox_create_from_url (mu_mailbox_t *pmbox, mu_url_t url) |
202 | return _create_mailbox0 (pmbox, url, mu_url_to_string (url)); | 210 | return _create_mailbox0 (pmbox, url, mu_url_to_string (url)); |
203 | } | 211 | } |
204 | 212 | ||
213 | int | ||
214 | mu_mailbox_create_from_record (mu_mailbox_t *pmbox, mu_record_t record, | ||
215 | const char *name) | ||
216 | { | ||
217 | mu_url_t url; | ||
218 | int rc; | ||
219 | |||
220 | rc = mu_url_create (&url, name); | ||
221 | if (rc) | ||
222 | return rc; | ||
223 | rc = mu_url_parse (url); | ||
224 | if (rc == 0) | ||
225 | rc = _mailbox_create_from_record (pmbox, record, url, name); | ||
226 | if (rc) | ||
227 | mu_url_destroy (&url); | ||
228 | return rc; | ||
229 | } | ||
230 | |||
205 | void | 231 | void |
206 | mu_mailbox_destroy (mu_mailbox_t *pmbox) | 232 | mu_mailbox_destroy (mu_mailbox_t *pmbox) |
207 | { | 233 | { | ... | ... |
-
Please register or sign in to post a comment