<<< Date Index >>>     <<< Thread Index >>>

Re: How to implement save_empty on maildir?



Hallo Derek,

Derek Martin <invalid@xxxxxxxxxxxxxx> wrote:
> On Sun, Jun 28, 2009 at 07:42:53PM +0000, Jörg Sommer wrote:
>> Rocco Rutte <pdmef@xxxxxxx> wrote:
>> > * Wu, Yue wrote:
>> >> I want to let mutt deletes empty maildirs automatically, but 'save_empty' 
>> >> only
>> >> works for mbox, why? How to achieve it for maildir?
>> >
>> > It doesn't work for maildir. I'm not sure why, but probably because
>> > removing an empty maildir has the potential to break something as it
>> > cannot be done atomically.
>> 
>> Mutt can rename the maildir to $maildir-mutt-remove and then remove the
>> subdirectories and then the $maildir-mutt-remove. The rename can be done
>> atomically.
>
> At first glance, this seems like a good solution, but actually it is
> not:
>
> 1. There may be an existing directory by that name already.  
>    Even if Mutt checks for the existence of it first, it is not safe,
>    because the user could (without knowing the behavior of Mutt)
>    create such a directory in between the time that Mutt checks, and
>    executes the rename().

So, create the directory yourself to ensure it's there and yours.

% cat rename-test.c
#include <stdio.h>
#include <sys/stat.h>

int main(void)
{
    mkdir("mdir-mutt-delete", 0)  /* this is a temporary directory to
                                     ensure rename doesn't replace an
                                     existing directory */

      || rename("mdir", "mdir-mutt-delete");

    return 0;
}

The good case:

% mkdir mdir
% strace ./rename-test
…
mkdir("mdir-mutt-delete", 0)            = 0
rename("mdir", "mdir-mutt-delete")      = 0
…
% ls -ld mdir*
drwxr-xr-x 2 joerg users 40  2. Jul 09:51 mdir-mutt-delete

The bad case:

% mkdir mdir mdir-mutt-delete
% strace ./rename-test
…
mkdir("mdir-mutt-delete", 0)            = -1 EEXIST (File exists)

% uname -a
Linux ibook 2.6.29 #1 Fri Mar 27 07:38:10 CET 2009 ppc GNU/Linux

> 2. $maildir may be a symlink. I'm not sure how mutt handles the
>    general case of a maildir being a symlink, but assuming that's
>    allowed, then in this case, it would fail briliantly.

If the maildir is a symlink, the question is what behaviour is expected?
If it's enough to remove the symlink, that's pretty easy. If mutt should
remove the target of the symlink, mutt can do it as described above.

>    Mutt would rename() the symlink, and then delete it.  The user may
>    be using something like fetchmail to deliver mail to the maildir
>    (the actual directory which was the target of the symlink) in which
>    case Mutt will NEVER AGAIN see new mail in that directory, at least
>    until such time as the user realizes what happened and takes some
>    action to fix the problem.

Because the tool rm removes the symlink, I think the user should expect
that the symlink gets removed and not the target.

> 3. In some cases, it may be possible that the directories $maildir and
>    ${maildir}-mutt-remove would not be on the same file system

As mutt creates the temporary directory, mutt can say where the
directory should be created. If mutt creates the temporary directory
in the same directory as the maildir is, I see no problems.

Otherwise, I thinks it's no problem to fall back to the current behaviour
and do _nothing_ or print an error message. Don't care for special cases.
The main case can be handled as described above.

Bye, Jörg.
-- 
Viele Leute glauben, dass sie denken, wenn sie lediglich
ihre Vorurteile neu ordnen.