[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-storage.c,1.13,1.14
cras at procontrol.fi
cras at procontrol.fi
Wed Nov 20 18:03:39 EET 2002
Update of /home/cvs/dovecot/src/lib-storage/index/maildir
In directory danu:/tmp/cvs-serv31239/maildir
Modified Files:
maildir-storage.c
Log Message:
Don't allow '*' and '%' characters in mailbox names. Maildir RENAME works
now properly when renaming folders having subfolders.
Index: maildir-storage.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- maildir-storage.c 12 Nov 2002 05:27:30 -0000 1.13
+++ maildir-storage.c 20 Nov 2002 16:03:36 -0000 1.14
@@ -13,6 +13,12 @@
#define CREATE_MODE 0770 /* umask() should limit it more */
+typedef struct {
+ int found;
+ size_t oldnamelen;
+ const char *newname;
+} RenameContext;
+
extern MailStorage maildir_storage;
extern Mailbox maildir_mailbox;
@@ -68,7 +74,9 @@
static int maildir_is_valid_name(MailStorage *storage, const char *name)
{
return name[0] != '\0' && name[0] != storage->hierarchy_sep &&
- strchr(name, '/') == NULL && strchr(name, '\\') == NULL;
+ name[strlen(name)-1] != storage->hierarchy_sep &&
+ strchr(name, '/') == NULL && strchr(name, '\\') == NULL &&
+ strchr(name, '*') == NULL && strchr(name, '%') == NULL;
}
/* create or fix maildir, ignore if it already exists */
@@ -309,10 +317,39 @@
return TRUE;
}
+static void rename_subfolder(MailStorage *storage, const char *name,
+ MailboxFlags flags __attr_unused__, void *context)
+{
+ RenameContext *ctx = context;
+ char oldpath[1024], newpath[1024];
+
+ i_assert(ctx->oldnamelen <= strlen(name));
+
+ i_snprintf(oldpath, sizeof(oldpath), "%s/.%s", storage->dir, name);
+ i_snprintf(newpath, sizeof(newpath), "%s/.%s.%s",
+ storage->dir, ctx->newname, name + ctx->oldnamelen);
+
+ /* FIXME: it's possible to merge two folders if either one of them
+ doesn't have existing root folder. We could check this but I'm not
+ sure if it's worth it. It could be even considered as a feature.
+
+ Anyway, the bug with merging is that if both folders have
+ identically named subfolder they conflict. Just ignore those and
+ leave them under the old folder. */
+ if (rename(oldpath, newpath) == 0 || errno == EEXIST)
+ ctx->found = TRUE;
+ else {
+ mail_storage_set_critical(storage, "rename(%s, %s) failed: %m",
+ oldpath, newpath);
+ }
+}
+
static int maildir_rename_mailbox(MailStorage *storage, const char *oldname,
const char *newname)
{
+ RenameContext ctx;
char oldpath[1024], newpath[1024];
+ int ret;
mail_storage_clear_error(storage);
@@ -325,12 +362,31 @@
/* NOTE: renaming INBOX works just fine with us, it's simply created
the next time it's needed. Only problem with it is that it's not
- atomic operation but that can't be really helped. */
+ atomic operation but that can't be really helped.
+
+ NOTE: is't possible to rename a nonexisting folder which has
+ subfolders. In that case we should ignore the rename() error. */
i_snprintf(oldpath, sizeof(oldpath), "%s/.%s", storage->dir, oldname);
i_snprintf(newpath, sizeof(newpath), "%s/.%s", storage->dir, newname);
- if (rename(oldpath, newpath) == 0) {
+
+ ret = rename(oldpath, newpath);
+ if (ret == 0 || (errno == ENOENT && strcmp(oldname, "INBOX") != 0)) {
if (strcmp(oldname, "INBOX") == 0)
return move_inbox_data(storage, newpath);
+
+ ctx.found = ret == 0;
+ ctx.oldnamelen = strlen(oldname)+1;
+ ctx.newname = newname;
+ if (!maildir_find_mailboxes(storage,
+ t_strconcat(oldname, ".*", NULL),
+ rename_subfolder, &ctx))
+ return FALSE;
+
+ if (!ctx.found) {
+ mail_storage_set_error(storage,
+ "Mailbox doesn't exist");
+ return FALSE;
+ }
return TRUE;
}
More information about the dovecot-cvs
mailing list