Mercurial > dovecot > original-hg > dovecot-1.2
changeset 815:ef64c9a50326 HEAD
Support for separate location of mbox INBOX folder.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 20 Dec 2002 08:00:06 +0200 |
parents | a6d24244c23f |
children | ae9b55f7164e |
files | doc/mail-storages.txt dovecot-example.conf src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/mbox/mbox-list.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/mail-storage.h |
diffstat | 6 files changed, 127 insertions(+), 99 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/mail-storages.txt Fri Dec 20 07:01:09 2002 +0200 +++ b/doc/mail-storages.txt Fri Dec 20 08:00:06 2002 +0200 @@ -16,14 +16,18 @@ mbox ---- -mbox storage currently requires that all mail is in user-writable -directory, eg. ~/mail. Especially using /var/mail/user is NOT supported. -You may however create a ~/mail/inbox hardlink (or symlink if not chrooted) -to pointing to /var/mail/user. All files in the mail directory are -considered as mailboxes. Directories specify subfolders in IMAP. "inbox" -file specifies the INBOX folder and can not be named otherwise. Indexes are -stored into ".imap/<mailbox name>/" directories. +mbox storage requires an IMAP root directory where to store IMAP folders +and some other information. mbox file for INBOX is a special case which may +exist elsewhere in filesystem. +All files in the IMAP root directory not beginning with a "." are treated +as IMAP folders. Directories are treated as being IMAP subfolders. + +Dovecot's indexes are stored in ".imap/<mailbox name>/" directories under +the folder directories. + +MAIL environment for mbox is: <root folder>|<INBOX path>[:INBOX=<path>]. +For example ~/Mail:INBOX=/var/mail/username. Detecting what to use --------------------- @@ -44,9 +48,12 @@ we have rwx access to it. If directory isn't known, / and ~/Maildir are checked. / is checked because we could be chrooted. -mbox storage is autodetected by checking if .imap/ (+rwx), inbox (+rw) or -mbox (+rw) exists in directory. If directory isn't known, / is tried first. -After that, ~/mail and ~/Mail directories are used. +mbox storage requires detecting INBOX location and IMAP root directory. If +MAIL environment points to file (+rw) it's treated as the INBOX file. If it +points to directory (+rwx) which contains .imap/ (+rwx), inbox (+rw) or +mbox (+rw) it's treated as IMAP root directory. If INBOX isn't known, +imap_root/inbox file is used by default. If root directory isn't known, we +try to find it from /, ~/mail or ~/Mail. Files created by Dovecot
--- a/dovecot-example.conf Fri Dec 20 07:01:09 2002 +0200 +++ b/dovecot-example.conf Fri Dec 20 08:00:06 2002 +0200 @@ -153,7 +153,8 @@ # username. Some examples: # # maildir:/var/mail/%1u/%u/Maildir -# mbox:~/mail/ +# mbox:~/mail/:INBOX=/var/mail/%u +# mbox:/var/mail/%d/%n/ # #default_mail_env =
--- a/src/lib-storage/index/maildir/maildir-storage.c Fri Dec 20 07:01:09 2002 +0200 +++ b/src/lib-storage/index/maildir/maildir-storage.c Fri Dec 20 08:00:06 2002 +0200 @@ -518,6 +518,7 @@ NULL, NULL, NULL, + NULL, NULL, NULL };
--- a/src/lib-storage/index/mbox/mbox-list.c Fri Dec 20 07:01:09 2002 +0200 +++ b/src/lib-storage/index/mbox/mbox-list.c Fri Dec 20 08:00:06 2002 +0200 @@ -17,7 +17,7 @@ static int mbox_find_path(MailStorage *storage, ImapMatchGlob *glob, MailboxFunc func, void *context, - const char *relative_dir, int *found_inbox) + const char *relative_dir) { DIR *dirp; struct dirent *d; @@ -113,15 +113,12 @@ func(storage, listpath, MAILBOX_NOSELECT, context); if (!mbox_find_path(storage, glob, func, - context, listpath, NULL)) { + context, listpath)) { failed = TRUE; break; } - } else if (match > 0) { - if (found_inbox != NULL && - strcasecmp(listpath, "inbox") == 0) - *found_inbox = TRUE; - + } else if (match > 0 && + strcmp(fullpath, storage->inbox_file) != 0) { func(storage, listpath, MAILBOX_NOINFERIORS, context); } } @@ -150,7 +147,6 @@ { ImapMatchGlob *glob; const char *relative_dir; - int found_inbox; /* check that we're not trying to do any "../../" lists */ if (!mbox_is_valid_mask(mask)) { @@ -165,18 +161,13 @@ relative_dir = mask_get_dir(mask); glob = imap_match_init(mask, TRUE, '/'); - - found_inbox = FALSE; - if (!mbox_find_path(storage, glob, func, context, - relative_dir, &found_inbox)) - return FALSE; + if (relative_dir == NULL && imap_match(glob, "INBOX") > 0) { + /* INBOX exists always, even if the file doesn't. */ + func(storage, "INBOX", MAILBOX_NOINFERIORS, context); + } - if (!found_inbox && relative_dir == NULL && - imap_match(glob, "INBOX") > 0) { - /* INBOX always exists, even if the file doesn't. */ - func(storage, "INBOX", MAILBOX_UNMARKED | MAILBOX_NOINFERIORS, - context); - } + if (!mbox_find_path(storage, glob, func, context, relative_dir)) + return FALSE; return TRUE; }
--- a/src/lib-storage/index/mbox/mbox-storage.c Fri Dec 20 07:01:09 2002 +0200 +++ b/src/lib-storage/index/mbox/mbox-storage.c Fri Dec 20 08:00:06 2002 +0200 @@ -24,7 +24,13 @@ const char *path; struct stat st; - path = t_strconcat(data, "/.imap", NULL); + /* Is it INBOX file? */ + if (*data != '\0' && stat(data, &st) == 0 && !S_ISDIR(st.st_mode) && + access(data, R_OK|W_OK) == 0) + return TRUE; + + /* or directory for IMAP folders? */ + path = t_strconcat(data, "/.imap", NULL); if (stat(path, &st) == 0 && S_ISDIR(st.st_mode) && access(path, R_OK|W_OK|X_OK) == 0) return TRUE; @@ -42,39 +48,69 @@ return FALSE; } +static const char *get_root_dir(void) +{ + const char *home, *path; + + if (mbox_autodetect("")) + return "/"; + + home = getenv("HOME"); + if (home != NULL) { + path = t_strconcat(home, "/mail", NULL); + if (access(path, R_OK|W_OK|X_OK) == 0) + return path; + + path = t_strconcat(home, "/Mail", NULL); + if (access(path, R_OK|W_OK|X_OK) == 0) + return path; + } + + return NULL; +} + static MailStorage *mbox_create(const char *data, const char *user) { MailStorage *storage; - const char *home, *path; + const char *root_dir, *inbox_file, *p; + struct stat st; + + root_dir = inbox_file = NULL; if (data == NULL || *data == '\0') { /* we'll need to figure out the mail location ourself. it's root dir if we've already chroot()ed, otherwise either $HOME/mail or $HOME/Mail */ - if (mbox_autodetect("")) - data = "/"; - else { - home = getenv("HOME"); - if (home != NULL) { - path = t_strconcat(home, "/mail", NULL); - if (access(path, R_OK|W_OK|X_OK) == 0) - data = path; - else { - path = t_strconcat(home, "/Mail", NULL); - if (access(path, R_OK|W_OK|X_OK) == 0) - data = path; - } + root_dir = get_root_dir(); + } else { + /* <root folder> | <INBOX path> [:INBOX=<path>] + [:<reserved for future>] */ + p = strchr(data, ':'); + if (p == NULL) { + if (stat(data, &st) == 0 && S_ISDIR(st.st_mode)) + root_dir = data; + else { + root_dir = get_root_dir(); + inbox_file = data; } + } else { + root_dir = t_strdup_until(data, p); + if (strncmp(p+1, "INBOX=", 6) == 0) + inbox_file = t_strcut(p+7, ':'); } } - if (data == NULL) + if (root_dir == NULL) return NULL; + if (inbox_file == NULL) + inbox_file = t_strconcat(root_dir, "/inbox", NULL); + storage = i_new(MailStorage, 1); memcpy(storage, &mbox_storage, sizeof(MailStorage)); - storage->dir = i_strdup(data); + storage->dir = i_strdup(root_dir); + storage->inbox_file = i_strdup(inbox_file); storage->user = i_strdup(user); storage->callbacks = i_new(MailStorageCallbacks, 1); return storage; @@ -143,19 +179,25 @@ static void verify_inbox(MailStorage *storage) { - char path[PATH_MAX]; + const char *index_dir; int fd; - if (str_path(path, sizeof(path), storage->dir, "inbox") < 0) - return; - /* make sure inbox file itself exists */ - fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0660); + fd = open(storage->inbox_file, O_RDWR | O_CREAT | O_EXCL, 0660); if (fd != -1) (void)close(fd); /* make sure the index directories exist */ - (void)create_mbox_index_dirs(path, TRUE); + index_dir = t_strconcat(storage->dir, "/INBOX", NULL); + (void)create_mbox_index_dirs(index_dir, TRUE); +} + +static const char *mbox_get_path(MailStorage *storage, const char *name) +{ + if (strcasecmp(name, "INBOX") == 0) + return storage->inbox_file; + else + return t_strconcat(storage->dir, "/", name, NULL); } static Mailbox *mbox_open(MailStorage *storage, const char *name, @@ -165,11 +207,20 @@ MailIndex *index; const char *path, *index_dir; - /* name = "foo/bar" - mbox_path = "/mail/foo/bar" - index_dir = "/mail/foo/.imap/bar" */ - path = t_strconcat(storage->dir, "/", name, NULL); - index_dir = mbox_get_index_dir(path); + if (strcasecmp(name, "INBOX") == 0) { + /* name = "INBOX" + path = "<inbox_file>/INBOX" + index_dir = "/mail/.imap/INBOX" */ + path = storage->inbox_file; + index_dir = mbox_get_index_dir(t_strconcat(storage->dir, + "/INBOX", NULL)); + } else { + /* name = "foo/bar" + path = "/mail/foo/bar" + index_dir = "/mail/foo/.imap/bar" */ + path = mbox_get_path(storage, name); + index_dir = mbox_get_index_dir(path); + } index = index_storage_lookup_ref(index_dir); if (index == NULL) { @@ -189,8 +240,8 @@ static Mailbox *mbox_open_mailbox(MailStorage *storage, const char *name, int readonly, int fast) { + const char *path; struct stat st; - char path[PATH_MAX]; mail_storage_clear_error(storage); @@ -198,7 +249,7 @@ if (strcasecmp(name, "INBOX") == 0) { /* make sure inbox exists */ verify_inbox(storage); - return mbox_open(storage, "inbox", readonly, fast); + return mbox_open(storage, "INBOX", readonly, fast); } if (!mbox_is_valid_name(storage, name)) { @@ -206,8 +257,8 @@ return FALSE; } - if (str_path(path, sizeof(path), storage->dir, name) == 0 && - stat(path, &st) == 0) { + path = mbox_get_path(storage, name); + if (stat(path, &st) == 0) { /* exists - make sure the required directories are also there */ (void)create_mbox_index_dirs(path, TRUE); @@ -225,14 +276,14 @@ static int mbox_create_mailbox(MailStorage *storage, const char *name) { + const char *path; struct stat st; - char path[PATH_MAX]; int fd; mail_storage_clear_error(storage); if (strcasecmp(name, "INBOX") == 0) - name = "inbox"; + name = "INBOX"; if (!mbox_is_valid_name(storage, name)) { mail_storage_set_error(storage, "Invalid mailbox name"); @@ -240,12 +291,7 @@ } /* make sure it doesn't exist already */ - if (str_path(path, sizeof(path), storage->dir, name) < 0) { - mail_storage_set_error(storage, "Mailbox name too long: %s", - name); - return FALSE; - } - + path = mbox_get_path(storage, name); if (stat(path, &st) == 0) { mail_storage_set_error(storage, "Mailbox already exists"); return FALSE; @@ -275,8 +321,7 @@ static int mbox_delete_mailbox(MailStorage *storage, const char *name) { - const char *index_dir; - char path[PATH_MAX]; + const char *index_dir, *path; mail_storage_clear_error(storage); @@ -290,13 +335,8 @@ return FALSE; } - if (str_path(path, sizeof(path), storage->dir, name) < 0) { - mail_storage_set_error(storage, "Mailbox name too long: %s", - name); - return FALSE; - } - /* first unlink the mbox file */ + path = mbox_get_path(storage, name); if (unlink(path) == -1) { if (errno == ENOENT) { mail_storage_set_error(storage, @@ -323,8 +363,7 @@ static int mbox_rename_mailbox(MailStorage *storage, const char *oldname, const char *newname) { - const char *old_indexdir, *new_indexdir; - char oldpath[PATH_MAX], newpath[PATH_MAX]; + const char *oldpath, *newpath, *old_indexdir, *new_indexdir; mail_storage_clear_error(storage); @@ -335,18 +374,10 @@ } if (strcasecmp(oldname, "INBOX") == 0) - oldname = "inbox"; + oldname = "INBOX"; - if (str_path(oldpath, sizeof(oldpath), storage->dir, oldname) < 0) { - mail_storage_set_error(storage, "Mailbox name too long: %s", - oldname); - return FALSE; - } - if (str_path(newpath, sizeof(newpath), storage->dir, newname) < 0) { - mail_storage_set_error(storage, "Mailbox name too long: %s", - newname); - return FALSE; - } + oldpath = mbox_get_path(storage, oldname); + newpath = mbox_get_path(storage, newname); /* NOTE: renaming INBOX works just fine with us, it's simply created the next time it's needed. */ @@ -374,24 +405,19 @@ MailboxNameStatus *status) { struct stat st; - char path[PATH_MAX]; + const char *path; mail_storage_clear_error(storage); if (strcasecmp(name, "INBOX") == 0) - name = "inbox"; + name = "INBOX"; if (!mbox_is_valid_name(storage, name)) { *status = MAILBOX_NAME_INVALID; return TRUE; } - if (str_path(path, sizeof(path), storage->dir, name) < 0) { - mail_storage_set_error(storage, "Mailbox name too long: %s", - name); - return FALSE; - } - + path = mbox_get_path(storage, name); if (stat(path, &st) == 0) { *status = MAILBOX_NAME_EXISTS; return TRUE; @@ -441,6 +467,7 @@ NULL, NULL, NULL, + NULL, NULL, NULL };
--- a/src/lib-storage/mail-storage.h Fri Dec 20 07:01:09 2002 +0200 +++ b/src/lib-storage/mail-storage.h Fri Dec 20 08:00:06 2002 +0200 @@ -115,6 +115,7 @@ /* private: */ char *dir; /* root directory */ + char *inbox_file; /* INBOX file for mbox */ char *user; /* name of user accessing the storage */ char *error;