fdm icon indicating copy to clipboard operation
fdm copied to clipboard

Maildir support is broken on systems that don't allow hard links

Open lisaev1 opened this issue 3 years ago • 1 comments

While setting up fdm in Termux, I encountered a delivery failure into a maildir mailbox. Specifically, fdm would successfully fetch mail to tmp/, but fail to move it to new/.

I tracked this down to file.c::safemove() :

   331	int
   332	safemove(const char *oldpath, const char *newpath)
   333	{
   334		int		ret;
   335		int		errsave;
   336		struct stat	sb;
   337	
   338		ret = link(oldpath, newpath);
   339		if (ret != 0 && errno == EXDEV) {
   340			ret = stat(newpath, &sb);
   341			if (ret == -1) {
   342				if (errno == ENOENT)
   343					ret = rename(oldpath, newpath);
   344			} else {
   345				ret = -1;
   346				errno = EEXIST;
   347			}
   348		}
   349	
   350		errsave = errno;
   351		if (unlink(oldpath) != 0 && errno != ENOENT)
   352			fatal("unlink failed");
   353		errno = errsave;
   354	
   355		return (ret);
   356	}

An unrooted Android doesn't allow creation of hard links, so link() fails, but not with EXDEV. As a result, the whole fetch transaction fails...

Does it make sense to handle ~~EPERM~~ EACCES the same way as EXDEV in safemove()?

Thanks!

lisaev1 avatar Aug 31 '22 21:08 lisaev1

Yes that seems OK, if it is a genuine failure then rename will also fail.

nicm avatar Sep 06 '22 07:09 nicm