chiark / gitweb /
locking.c, locking.1: Make the protocol safe if the lockfile is (re)moved.
[misc] / locking.c
index 68cbc749a56f59ad0f9c44b38460e5d503165490..bfc5c771927e13d04703108224992ce92aef6933 100644 (file)
--- a/locking.c
+++ b/locking.c
@@ -39,6 +39,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/wait.h>
+#include <sys/stat.h>
 
 #include <mLib/mdwopt.h>
 #include <mLib/quis.h>
@@ -95,6 +96,7 @@ int main(int argc, char *argv[])
   int t = -1;
   int oflag;
   unsigned int ot = 0;
+  struct stat st, nst;
   time_t nt;
   pid_t kid;
   int rc;
@@ -184,9 +186,18 @@ doneopts:
   ot = alarm(0);
   oalrm = signal(SIGALRM, alrm);
   if (t >= 0) alarm(t);
+again:
   if ((fd = open(file, oflag, 0666)) < 0)
     die(111, "error opening `%s': %s", file, strerror(errno));
+  if (fstat(fd, &st))
+    die(111, "error from fstat on `%s': %s", file, strerror(errno));
   err = fcntl(fd, f & f_wait ? F_SETLKW : F_SETLK, &l) >= 0 ? 0 : errno;
+  if (stat(file, &nst)) {
+    if (errno == ENOENT) { close(fd); goto again; }
+    else die(111, "error from stat on `%s': %s", file, strerror(errno));
+  }
+  if (st.st_dev != nst.st_dev || st.st_ino != nst.st_ino)
+    { close(fd); goto again; }
 done:
   signal(SIGALRM, oalrm);
   if (!ot)