]> granicus.if.org Git - uw-imap/commitdiff
add files for 2006-08-31T01:37:52Z
authorUnknown <>
Thu, 31 Aug 2006 01:37:52 +0000 (01:37 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Fri, 7 Sep 2018 00:02:32 +0000 (00:02 +0000)
src/osdep/unix/flocklnx.c [new file with mode: 0644]

diff --git a/src/osdep/unix/flocklnx.c b/src/osdep/unix/flocklnx.c
new file mode 100644 (file)
index 0000000..ca0112a
--- /dev/null
@@ -0,0 +1,76 @@
+/* ========================================================================
+ * Copyright 1988-2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 
+ * ========================================================================
+ */
+
+/*
+ * Program:    Safe File Lock for Linux
+ *
+ * Author:     Mark Crispin
+ *             Networks and Distributed Computing
+ *             Computing & Communications
+ *             University of Washington
+ *             Administration Building, AG-44
+ *             Seattle, WA  98195
+ *             Internet: MRC@CAC.Washington.EDU
+ *
+ * Date:       20 April 2005
+ * Last Edited:        30 August 2006
+ */
+\f 
+#undef flock
+
+#include <sys/vfs.h>
+#ifndef NFS_SUPER_MAGIC
+#define NFS_SUPER_MAGIC 0x6969
+#endif
+
+int safe_flock (int fd,int op)
+{
+  struct statfs sfbuf;
+  char tmp[MAILTMPLEN];
+  int e;
+  int logged = 0;
+  /* Check for NFS because Linux 2.6 broke flock() on NFS.  Instead of being
+   * a no-op, flock() on NFS now returns ENOLCK.  Read
+   *   https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=123415
+   * for the gruesome details.
+   */
+                               /* check filesystem type */
+  while ((e = fstatfs (fd,&sfbuf)) && (errno == EINTR));
+  if (!e) switch (sfbuf.f_type) {
+  case NFS_SUPER_MAGIC:                /* always a fast no-op on NFS */
+    break;
+  default:                     /* allow on other filesystem types */
+                               /* do the lock */
+    while (flock (fd,op)) switch (errno) {
+    case EINTR:                        /* interrupt */
+      break;
+    case ENOLCK:               /* lock table is full */
+      sprintf (tmp,"File locking failure: %s",strerror (errno));
+      mm_log (tmp,WARN);       /* give the user a warning of what happened */
+      if (!logged++) syslog (LOG_ERR,tmp);
+                               /* return failure if non-blocking lock */
+      if (op & LOCK_NB) return -1;
+      sleep (5);               /* slow down in case it loops */
+      break;
+    case EWOULDBLOCK:          /* file is locked, LOCK_NB should be set */
+      if (op & LOCK_NB) return -1;
+    case EBADF:                        /* not valid open file descriptor */
+    case EINVAL:               /* invalid operator */
+    default:                   /* other error code? */
+      sprintf (tmp,"Unexpected file locking failure: %s",strerror (errno));
+      fatal (tmp);
+    }
+    break;
+  }
+  return 0;                    /* success */
+}