Commit 154c67f4 154c67f47ba231d3e269ad59714dcf5870a658c3 by Sergey Poznyakoff

imap4d: revamp namespace translation

Instead of translating names to full mailbox URLs, translate them
to the filesystem pathname and record (mu_record_t) that should be
used when creating the mailbox.  Never use mu_mailbox_create_default.

This patch also fixes memory leaks in some functions (the return
value from namespace_get_url was never freed).

* imap4d/imap4d.h (namespace_get_url): Remove.
(namespace_get_name): New proto.
* imap4d/namespace.c (namespace_init): Always intialize the
pfx->record member.  This requires that the default record be
initialized.
(namespace_get_url): Remove.
(namespace_get_name): New function.

* imap4d/create.c: Use namespace_get_name and
mu_mailbox_create_from_record to create mailboxes.  Fix folder
creation.
* imap4d/append.c: Use namespace_get_name and
mu_mailbox_create_from_record to create mailboxes.
* imap4d/copy.c: Likewise.
* imap4d/delete.c: Likewise.
* imap4d/quota.c: Likewise.
* imap4d/rename.c: Likewise.
* imap4d/status.c: Likewise.
1 parent b39b471f
...@@ -201,6 +201,7 @@ imap4d_append (struct imap4d_session *session, ...@@ -201,6 +201,7 @@ imap4d_append (struct imap4d_session *session,
201 { 201 {
202 int i; 202 int i;
203 char *mboxname; 203 char *mboxname;
204 mu_record_t record;
204 int flags = 0; 205 int flags = 0;
205 mu_mailbox_t dest_mbox = NULL; 206 mu_mailbox_t dest_mbox = NULL;
206 int status; 207 int status;
...@@ -253,11 +254,11 @@ imap4d_append (struct imap4d_session *session, ...@@ -253,11 +254,11 @@ imap4d_append (struct imap4d_session *session,
253 254
254 msg_text = imap4d_tokbuf_getarg (tok, i); 255 msg_text = imap4d_tokbuf_getarg (tok, i);
255 256
256 mboxname = namespace_get_url (mboxname, NULL); 257 mboxname = namespace_get_name (mboxname, &record, NULL);
257 if (!mboxname) 258 if (!mboxname)
258 return io_completion_response (command, RESP_NO, "Couldn't open mailbox"); 259 return io_completion_response (command, RESP_NO, "Couldn't open mailbox");
259 260
260 status = mu_mailbox_create_default (&dest_mbox, mboxname); 261 status = mu_mailbox_create_from_record (&dest_mbox, record, mboxname);
261 if (status == 0) 262 if (status == 0)
262 { 263 {
263 /* It SHOULD NOT automatically create the mailbox. */ 264 /* It SHOULD NOT automatically create the mailbox. */
......
...@@ -212,6 +212,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) ...@@ -212,6 +212,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
212 mu_mailbox_t cmbox = NULL; 212 mu_mailbox_t cmbox = NULL;
213 int arg = IMAP4_ARG_1 + !!isuid; 213 int arg = IMAP4_ARG_1 + !!isuid;
214 int mode = 0; 214 int mode = 0;
215 mu_record_t record;
215 216
216 *err_text = NULL; 217 *err_text = NULL;
217 if (imap4d_tokbuf_argc (tok) != arg + 2) 218 if (imap4d_tokbuf_argc (tok) != arg + 2)
...@@ -240,7 +241,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) ...@@ -240,7 +241,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
240 return RESP_BAD; 241 return RESP_BAD;
241 } 242 }
242 243
243 mailbox_name = namespace_get_url (name, &mode); 244 mailbox_name = namespace_get_name (name, &record, &mode);
244 245
245 if (!mailbox_name) 246 if (!mailbox_name)
246 { 247 {
...@@ -251,7 +252,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) ...@@ -251,7 +252,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
251 252
252 /* If the destination mailbox does not exist, a server should return 253 /* If the destination mailbox does not exist, a server should return
253 an error. */ 254 an error. */
254 status = mu_mailbox_create_default (&cmbox, mailbox_name); 255 status = mu_mailbox_create_from_record (&cmbox, record, mailbox_name);
255 if (status == 0) 256 if (status == 0)
256 { 257 {
257 /* It SHOULD NOT automatifcllly create the mailbox. */ 258 /* It SHOULD NOT automatifcllly create the mailbox. */
...@@ -267,6 +268,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) ...@@ -267,6 +268,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
267 mu_mailbox_destroy (&cmbox); 268 mu_mailbox_destroy (&cmbox);
268 } 269 }
269 mu_msgset_free (msgset); 270 mu_msgset_free (msgset);
271 free (mailbox_name);
270 272
271 if (status == 0) 273 if (status == 0)
272 { 274 {
......
...@@ -39,9 +39,10 @@ imap4d_create (struct imap4d_session *session, ...@@ -39,9 +39,10 @@ imap4d_create (struct imap4d_session *session,
39 { 39 {
40 char *name; 40 char *name;
41 int isdir = 0; 41 int isdir = 0;
42 int mode = 0;
43 int rc = RESP_OK; 42 int rc = RESP_OK;
44 const char *msg = "Completed"; 43 const char *msg = "Completed";
44 mu_record_t record;
45 int mode;
45 46
46 if (imap4d_tokbuf_argc (tok) != 3) 47 if (imap4d_tokbuf_argc (tok) != 3)
47 return io_completion_response (command, RESP_BAD, "Invalid arguments"); 48 return io_completion_response (command, RESP_BAD, "Invalid arguments");
...@@ -67,7 +68,7 @@ imap4d_create (struct imap4d_session *session, ...@@ -67,7 +68,7 @@ imap4d_create (struct imap4d_session *session,
67 isdir = 1; 68 isdir = 1;
68 69
69 /* Allocates memory. */ 70 /* Allocates memory. */
70 name = namespace_get_url (name, &mode); 71 name = namespace_get_name (name, &record, &mode);
71 72
72 if (!name) 73 if (!name)
73 return io_completion_response (command, RESP_NO, "Cannot create mailbox"); 74 return io_completion_response (command, RESP_NO, "Cannot create mailbox");
...@@ -76,33 +77,42 @@ imap4d_create (struct imap4d_session *session, ...@@ -76,33 +77,42 @@ imap4d_create (struct imap4d_session *session,
76 if (access (name, F_OK) != 0) 77 if (access (name, F_OK) != 0)
77 { 78 {
78 if (make_interdir (name, MU_HIERARCHY_DELIMITER, MKDIR_PERMISSIONS)) 79 if (make_interdir (name, MU_HIERARCHY_DELIMITER, MKDIR_PERMISSIONS))
80 rc = RESP_NO;
81
82 if (rc == RESP_OK)
83 {
84 if (isdir)
85 {
86 if (mkdir (name, MKDIR_PERMISSIONS))
79 { 87 {
88 mu_diag_output (MU_DIAG_ERR,
89 _("Cannot create directory %s: %s"), name,
90 mu_strerror (errno));
80 rc = RESP_NO; 91 rc = RESP_NO;
81 msg = "Cannot create mailbox";
82 } 92 }
83 93 }
84 if (rc == RESP_OK && !isdir) 94 else
85 { 95 {
86 mu_mailbox_t mbox; 96 mu_mailbox_t mbox;
87 97
88 rc = mu_mailbox_create_default (&mbox, name); 98 rc = mu_mailbox_create_from_record (&mbox, record, name);
89 if (rc) 99 if (rc)
90 { 100 {
91 mu_diag_output (MU_DIAG_ERR, 101 mu_diag_output (MU_DIAG_ERR,
92 _("Cannot create mailbox %s: %s"), name, 102 _("Cannot create mailbox (%s) %s: %s"), name,
103 record->scheme,
93 mu_strerror (rc)); 104 mu_strerror (rc));
94 rc = RESP_NO; 105 rc = RESP_NO;
95 msg = "Cannot create mailbox";
96 } 106 }
97 else if ((rc = mu_mailbox_open (mbox, 107 else if ((rc = mu_mailbox_open (mbox,
98 MU_STREAM_RDWR | MU_STREAM_CREAT 108 MU_STREAM_RDWR | MU_STREAM_CREAT
99 | mode))) 109 | mode)))
100 { 110 {
101 mu_diag_output (MU_DIAG_ERR, 111 mu_diag_output (MU_DIAG_ERR,
102 _("Cannot open mailbox %s: %s"), 112 _("Cannot open mailbox (%s) %s: %s"),
113 record->scheme,
103 name, mu_strerror (rc)); 114 name, mu_strerror (rc));
104 rc = RESP_NO; 115 rc = RESP_NO;
105 msg = "Cannot create mailbox";
106 } 116 }
107 else 117 else
108 { 118 {
...@@ -112,11 +122,14 @@ imap4d_create (struct imap4d_session *session, ...@@ -112,11 +122,14 @@ imap4d_create (struct imap4d_session *session,
112 } 122 }
113 } 123 }
114 } 124 }
125 if (rc != RESP_OK)
126 msg = "Cannot create mailbox";
127 }
115 else 128 else
116 { 129 {
117 rc = RESP_NO; 130 rc = RESP_NO;
118 msg = "already exists"; 131 msg = "already exists";
119 } 132 }
120 133 free (name);
121 return io_completion_response (command, rc, "%s", msg); 134 return io_completion_response (command, rc, "%s", msg);
122 } 135 }
......
...@@ -36,6 +36,7 @@ imap4d_delete (struct imap4d_session *session, ...@@ -36,6 +36,7 @@ imap4d_delete (struct imap4d_session *session,
36 const char *msg = "Completed"; 36 const char *msg = "Completed";
37 char *name; 37 char *name;
38 mu_mailbox_t tmpbox; 38 mu_mailbox_t tmpbox;
39 mu_record_t record;
39 40
40 if (imap4d_tokbuf_argc (tok) != 3) 41 if (imap4d_tokbuf_argc (tok) != 3)
41 return io_completion_response (command, RESP_BAD, "Invalid arguments"); 42 return io_completion_response (command, RESP_BAD, "Invalid arguments");
...@@ -49,11 +50,11 @@ imap4d_delete (struct imap4d_session *session, ...@@ -49,11 +50,11 @@ imap4d_delete (struct imap4d_session *session,
49 return io_completion_response (command, RESP_NO, "Already exist"); 50 return io_completion_response (command, RESP_NO, "Already exist");
50 51
51 /* Allocates memory. */ 52 /* Allocates memory. */
52 name = namespace_get_url (name, NULL); 53 name = namespace_get_name (name, &record, NULL);
53 if (!name) 54 if (!name)
54 return io_completion_response (command, RESP_NO, "Cannot remove"); 55 return io_completion_response (command, RESP_NO, "Cannot remove");
55 56
56 rc = mu_mailbox_create (&tmpbox, name); 57 rc = mu_mailbox_create_from_record (&tmpbox, record, name);
57 if (rc == 0) 58 if (rc == 0)
58 { 59 {
59 imap4d_enter_critical (); 60 imap4d_enter_critical ();
...@@ -69,6 +70,7 @@ imap4d_delete (struct imap4d_session *session, ...@@ -69,6 +70,7 @@ imap4d_delete (struct imap4d_session *session,
69 if (rc) 70 if (rc)
70 mu_diag_funcall (MU_DIAG_ERROR, "remove", name, errno); 71 mu_diag_funcall (MU_DIAG_ERROR, "remove", name, errno);
71 } 72 }
73 free (name);
72 74
73 if (rc) 75 if (rc)
74 { 76 {
......
...@@ -413,7 +413,7 @@ struct namespace *namespace_lookup (char const *name); ...@@ -413,7 +413,7 @@ struct namespace *namespace_lookup (char const *name);
413 413
414 char *namespace_translate_name (char const *name, int url, 414 char *namespace_translate_name (char const *name, int url,
415 struct namespace_prefix const **pfx); 415 struct namespace_prefix const **pfx);
416 char *namespace_get_url (char const *name, int *mode); 416 char *namespace_get_name (char const *name, mu_record_t *rec, int *mode);
417 417
418 void translate_delim (char *dst, char const *src, int dst_delim, int src_delim); 418 void translate_delim (char *dst, char const *src, int dst_delim, int src_delim);
419 419
......
...@@ -92,7 +92,6 @@ namespace_init (void) ...@@ -92,7 +92,6 @@ namespace_init (void)
92 if (mu_list_get_iterator (namespace[i].prefixes, &itr)) 92 if (mu_list_get_iterator (namespace[i].prefixes, &itr))
93 imap4d_bye (ERR_NO_MEM); 93 imap4d_bye (ERR_NO_MEM);
94 94
95
96 for (mu_iterator_first (itr); 95 for (mu_iterator_first (itr);
97 !mu_iterator_is_done (itr); mu_iterator_next (itr)) 96 !mu_iterator_is_done (itr); mu_iterator_next (itr))
98 { 97 {
...@@ -106,6 +105,9 @@ namespace_init (void) ...@@ -106,6 +105,9 @@ namespace_init (void)
106 105
107 trim_delim (pfx->dir, '/'); 106 trim_delim (pfx->dir, '/');
108 107
108 if (!pfx->scheme)
109 mu_registrar_get_default_record (&pfx->record);
110
109 rc = mu_assoc_install (prefixes, pfx->prefix, pfx); 111 rc = mu_assoc_install (prefixes, pfx->prefix, pfx);
110 if (rc == MU_ERR_EXISTS) 112 if (rc == MU_ERR_EXISTS)
111 { 113 {
...@@ -351,20 +353,12 @@ namespace_translate_name (char const *name, int url, ...@@ -351,20 +353,12 @@ namespace_translate_name (char const *name, int url,
351 } 353 }
352 354
353 char * 355 char *
354 namespace_get_url (char const *name, int *mode) 356 namespace_get_name (char const *name, mu_record_t *rec, int *mode)
355 { 357 {
356 struct namespace_prefix const *pfx; 358 struct namespace_prefix const *pfx;
357 char *path = namespace_translate_name (name, 1, &pfx); 359 char *path = namespace_translate_name (name, 0, &pfx);
358 360 if (rec)
359 if (path && pfx->scheme) 361 *rec = pfx->record;
360 {
361 char *p = mu_alloc (strlen (pfx->scheme) + 3 + strlen (path) + 1);
362 strcpy (p, pfx->scheme);
363 strcat (p, "://");
364 strcat (p, path);
365 free (path);
366 path = p;
367 }
368 if (mode) 362 if (mode)
369 *mode = namespace[pfx->ns].mode; 363 *mode = namespace[pfx->ns].mode;
370 return path; 364 return path;
......
...@@ -132,19 +132,17 @@ quota_check (mu_off_t size) ...@@ -132,19 +132,17 @@ quota_check (mu_off_t size)
132 mu_mailbox_t mbox; 132 mu_mailbox_t mbox;
133 mu_off_t total; 133 mu_off_t total;
134 int rc; 134 int rc;
135 mu_record_t record;
135 136
136 if (auth_data->quota == 0) 137 if (auth_data->quota == 0)
137 return RESP_OK; 138 return RESP_OK;
138 139
139 total = used_size; 140 total = used_size;
140 141
141 mailbox_name = namespace_get_url ("INBOX", NULL); 142 mailbox_name = namespace_get_name ("INBOX", &record, NULL);
142 rc = mu_mailbox_create (&mbox, mailbox_name); 143 rc = mu_mailbox_create_from_record (&mbox, record, mailbox_name);
143 if (rc) 144 if (rc)
144 {
145 mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create", mailbox_name, rc); 145 mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create", mailbox_name, rc);
146 free (mailbox_name);
147 }
148 else 146 else
149 { 147 {
150 do 148 do
......
...@@ -110,6 +110,7 @@ imap4d_rename (struct imap4d_session *session, ...@@ -110,6 +110,7 @@ imap4d_rename (struct imap4d_session *session,
110 const char *msg = "Completed"; 110 const char *msg = "Completed";
111 struct stat newst; 111 struct stat newst;
112 int mode = 0; 112 int mode = 0;
113 mu_record_t newrec;
113 114
114 if (imap4d_tokbuf_argc (tok) != 4) 115 if (imap4d_tokbuf_argc (tok) != 4)
115 return io_completion_response (command, RESP_BAD, "Invalid arguments"); 116 return io_completion_response (command, RESP_BAD, "Invalid arguments");
...@@ -121,7 +122,7 @@ imap4d_rename (struct imap4d_session *session, ...@@ -121,7 +122,7 @@ imap4d_rename (struct imap4d_session *session,
121 return io_completion_response (command, RESP_NO, "Name Inbox is reservered"); 122 return io_completion_response (command, RESP_NO, "Name Inbox is reservered");
122 123
123 /* Allocates memory. */ 124 /* Allocates memory. */
124 newname = namespace_get_url (newname, &mode); 125 newname = namespace_get_name (newname, &newrec, &mode);
125 if (!newname) 126 if (!newname)
126 return io_completion_response (command, RESP_NO, "Permission denied"); 127 return io_completion_response (command, RESP_NO, "Permission denied");
127 128
...@@ -158,7 +159,7 @@ imap4d_rename (struct imap4d_session *session, ...@@ -158,7 +159,7 @@ imap4d_rename (struct imap4d_session *session,
158 return io_completion_response (command, RESP_NO, 159 return io_completion_response (command, RESP_NO,
159 "Cannot be a directory"); 160 "Cannot be a directory");
160 } 161 }
161 if (mu_mailbox_create (&newmbox, newname) != 0 162 if (mu_mailbox_create_from_record (&newmbox, newrec, newname) != 0
162 || mu_mailbox_open (newmbox, 163 || mu_mailbox_open (newmbox,
163 MU_STREAM_CREAT | MU_STREAM_RDWR | mode) != 0) 164 MU_STREAM_CREAT | MU_STREAM_RDWR | mode) != 0)
164 { 165 {
...@@ -199,7 +200,7 @@ imap4d_rename (struct imap4d_session *session, ...@@ -199,7 +200,7 @@ imap4d_rename (struct imap4d_session *session,
199 return io_completion_response (command, RESP_OK, "Rename successful"); 200 return io_completion_response (command, RESP_OK, "Rename successful");
200 } 201 }
201 202
202 oldname = namespace_get_url (oldname, NULL); 203 oldname = namespace_get_name (oldname, NULL, NULL);
203 204
204 /* It must exist. */ 205 /* It must exist. */
205 /* FIXME: 1. What if odlname or newname is a remote mailbox? 206 /* FIXME: 1. What if odlname or newname is a remote mailbox?
...@@ -240,6 +241,7 @@ imap4d_rename (struct imap4d_session *session, ...@@ -240,6 +241,7 @@ imap4d_rename (struct imap4d_session *session,
240 } 241 }
241 free (oldname); 242 free (oldname);
242 } 243 }
244
243 free (newname); 245 free (newname);
244 return io_completion_response (command, rc, "%s", msg); 246 return io_completion_response (command, rc, "%s", msg);
245 } 247 }
......
...@@ -75,13 +75,14 @@ imap4d_status (struct imap4d_session *session, ...@@ -75,13 +75,14 @@ imap4d_status (struct imap4d_session *session,
75 int count = 0; 75 int count = 0;
76 char *err_msg = NULL; 76 char *err_msg = NULL;
77 int argc = imap4d_tokbuf_argc (tok); 77 int argc = imap4d_tokbuf_argc (tok);
78 mu_record_t record;
78 79
79 if (argc < 4) 80 if (argc < 4)
80 return io_completion_response (command, RESP_BAD, "Invalid arguments"); 81 return io_completion_response (command, RESP_BAD, "Invalid arguments");
81 82
82 name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1); 83 name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
83 84
84 mailbox_name = namespace_get_url (name, NULL); 85 mailbox_name = namespace_get_name (name, &record, NULL);
85 86
86 if (!mailbox_name) 87 if (!mailbox_name)
87 return io_completion_response (command, RESP_NO, "Error opening mailbox"); 88 return io_completion_response (command, RESP_NO, "Error opening mailbox");
...@@ -92,7 +93,7 @@ imap4d_status (struct imap4d_session *session, ...@@ -92,7 +93,7 @@ imap4d_status (struct imap4d_session *session,
92 mu_mailbox_sync (mbox); 93 mu_mailbox_sync (mbox);
93 imap4d_leave_critical (); 94 imap4d_leave_critical ();
94 95
95 status = mu_mailbox_create_default (&smbox, mailbox_name); 96 status = mu_mailbox_create_from_record (&smbox, record, mailbox_name);
96 if (status == 0) 97 if (status == 0)
97 { 98 {
98 status = mu_mailbox_open (smbox, MU_STREAM_READ); 99 status = mu_mailbox_open (smbox, MU_STREAM_READ);
......