fdm
fdm copied to clipboard
Maildir support is broken on systems that don't allow hard links
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!
Yes that seems OK, if it is a genuine failure then rename will also fail.