nicm / fdm

fdm source code
269 stars 50 forks source link

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

Open lisaev1 opened 2 years ago

lisaev1 commented 2 years ago

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!

nicm commented 2 years ago

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