Here's a first try at a patch to check for the historically documented
"link() returning -1 but succeeding" case for NFS.

-- 
Kevin J. McCarthy
GPG Fingerprint: 8975 A9B3 3AA3 7910 385C  5308 ADEF 7684 8031 6BDA
From f0faf6cf205e0b96c2fb93ea12393458843aa485 Mon Sep 17 00:00:00 2001
From: Kevin McCarthy <ke...@8t8.us>
Date: Sun, 26 Aug 2018 18:43:20 -0700
Subject: [PATCH] Add additional error handling to safe_rename().

It is apparently possible for link() to return an error but the link
to still be created.  Add a double check for that case.  If the files
match, unlink the src and return success.
---
 lib.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/lib.c b/lib.c
index 9a5d5325..0f65a641 100644
--- a/lib.c
+++ b/lib.c
@@ -446,12 +446,31 @@ int safe_symlink(const char *oldpath, const char *newpath)
 int safe_rename (const char *src, const char *target)
 {
   struct stat ssb, tsb;
+  int link_errno;
 
   if (!src || !target)
     return -1;
 
   if (link (src, target) != 0)
   {
+    link_errno = errno;
+
+    /*
+     * It is historically documented that link can return -1 if NFS
+     * dies after creating the link.  In that case, we are supposed
+     * to use stat to check if the link was created.
+     */
+    if ((lstat (src, &ssb) == 0) &&
+        (lstat (target, &tsb) == 0) &&
+        (compare_stat (&ssb, &tsb) == 0))
+    {
+      dprint (1, (debugfile,
+                  "safe_rename: link (%s, %s) reported failure: %s (%d) but actually succeded\n",
+                  src, target, strerror (errno), errno));
+      goto success;
+    }
+
+    errno = link_errno;
 
     /*
      * Coda does not allow cross-directory links, but tells
@@ -533,11 +552,11 @@ int safe_rename (const char *src, const char *target)
   }
 #endif
 
+success:
   /*
    * Unlink the original link.  Should we really ignore the return
    * value here? XXX
    */
-
   if (unlink (src) == -1) 
   {
     dprint (1, (debugfile, "safe_rename: unlink (%s) failed: %s (%d)\n",
-- 
2.18.0

Attachment: signature.asc
Description: PGP signature

Reply via email to