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

Re: How to implement save_empty on maildir?



Hi Jörg,

On Thu, Jul 02, 2009 at 08:10:21AM +0000, Jörg Sommer wrote:
> 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;
> }

There are several problems with this.  If the directory exists when
you do the mkdir, it fails with no clear course of action to take to
fix the failure; that seems like clearly a bug to me.  Also, if some
process puts a file in mdir-mutt-delete before you rename it, the
rename will fail.  In either case, Mutt didn't do what you told it to
do (remove the maildir when it's empty).  You can't code stuff that
works sometimes in applications that other people are going to use...

Also, while this test may work as you expect on your system, not all
operating systems on which Mutt runs may have the same semantics.
More importantly these operations are not atomic, and therefore can not
be done safely.  It is possible, for example, for the user to do
exacty the same thing, in between the time you create the directory,
and the time you rename the maildir.

It also means the user can not use ${maildir}-mutt-delete as a mailbox
name (or anything else).  Which in turn means that the user must KNOW
that they can't use it safely.  That's yucky (to say the least)... the
user should not need to know the intimate details of the
implementation of your software in order to use it safely, by and
large.
 
> > 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?

Presumably the expected behavior is that it should work exactly the
same way whether it's a symlink or not.  For the most part, this is
the point of symlinks; to make transparent the ability to have files
appear to exist someplace other than where they actually exist.

> 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.

As I described previously, this is clearly unacceptable.  New mail
will accumulate, but Mutt won't see it, because it's configured to
look at a non-existant symlink.

> >    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.

Why should the user expect that it gets removed?  Even if you document
it, the user may set it up as a symlink, and then set this option on
the folder at a later time, and never make the connection between what
they just did and the problem they just caused.  This is exactly why
most sysadmins have a job.  ;-)

> 
> > 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.

I already gave you two examples where it IS a problem.  I'll spell it
out:

  /home/user/mail: root of user's mail directory
  /home/user/mail/maildir1: a specific folder which is NFS-mounted
  from another system (because the user is slightly crazy).
  /home/user/mail/maildir1-mutt-delete: a directory under
  /home/user/mail, on the same device

In other words, the user executed something like:

/sbin/mount -t NFS server:/my/other/maildir /home/user/mail/maildir1

Now you have maildir1 and maildir1-mutt-delete on two different
physical filesystems.  That won't work (a call to rename will fail;
you need to copy the files to the new location, and unlink() the old
ones).

Another case:  The user ran out of space in /home, so created a
directory in /var for more folders.  But they still want the maildir
structure to look like it's all in one place, so they do this:

/sbin/mount -o bindmount /var/my/new/maildr /home/user/mail/maildir1

Same problem as before.  This may seem weird to you (and it probably
should), but I promise you, people really do this stuff.  Because they
can, and because they think it's cool.  And for the most part, it
works just fine...  until an application like Mutt comes along and
makes assumptions about the arrangement of the filesystem.

Some filesystems (like ENCFS) are not really file systems at all...
they make files that exist elsewhere look like a filesystem.  I don't
know how that would work, to be honest, but I can imagine there might
be problems, depending on the file system implementation.

For what it's worth, there are probably other problems with this that
I didn't think of.  But someone would find them... ;-)  The point is,
you can't do any of this atomically, which means it's not reliably
safe to do, which means you just can't do it.

> 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.

Nope, that's unacceptable.  Because it means your solution only works
*sometimes*, and other times the behavior is undefined.  That's a
recipe for bad application design.

-- 
Derek D. Martin    http://www.pizzashack.org/   GPG Key ID: 0xDFBEAD02
-=-=-=-=-
This message is posted from an invalid address.  Replying to it will result in
undeliverable mail due to spam prevention.  Sorry for the inconvenience.

Attachment: pgpQF6C_d6rHX.pgp
Description: PGP signature