diff src/lib/nfs-workarounds.c @ 4225:abdef9d86a94 HEAD

Added nfs_safe_stat() to transparently work around ESTALE with stat().
author Timo Sirainen <timo.sirainen@movial.fi>
date Tue, 25 Apr 2006 16:40:18 +0300
parents cd3d26cf124a
children 885ed4d5c51d
line wrap: on
line diff
--- a/src/lib/nfs-workarounds.c	Mon Apr 24 16:18:45 2006 +0300
+++ b/src/lib/nfs-workarounds.c	Tue Apr 25 16:40:18 2006 +0300
@@ -7,19 +7,19 @@
 #include <unistd.h>
 #include <sys/stat.h>
 
-int nfs_safe_open(const char *path, int flags)
+static int
+nfs_safe_do(const char *path, int (*callback)(const char *path, void *context),
+	    void *context)
 {
         const char *dir = NULL;
         struct stat st;
         unsigned int i;
-        int fd;
-
-        i_assert((flags & O_CREAT) == 0);
+	int ret;
 
         t_push();
         for (i = 1;; i++) {
-                fd = open(path, flags);
-                if (fd != -1 || errno != ESTALE || i == NFS_ESTALE_RETRY_COUNT)
+		ret = callback(path, context);
+                if (ret == 0 || errno != ESTALE || i == NFS_ESTALE_RETRY_COUNT)
                         break;
 
                 /* ESTALE: Some operating systems may fail with this if they
@@ -44,5 +44,43 @@
                 /* directory still exists, try reopening */
         }
         t_pop();
-        return fd;
+        return ret;
+}
+
+struct nfs_safe_open_context {
+	int flags;
+	int fd;
+};
+
+static int nfs_safe_open_callback(const char *path, void *context)
+{
+	struct nfs_safe_open_context *ctx = context;
+
+	ctx->fd = open(path, ctx->flags);
+	return ctx->fd == -1 ? -1 : 0;
 }
+
+int nfs_safe_open(const char *path, int flags)
+{
+	struct nfs_safe_open_context ctx;
+
+        i_assert((flags & O_CREAT) == 0);
+
+	ctx.flags = flags;
+	if (nfs_safe_do(path, nfs_safe_open_callback, &ctx) < 0)
+		return -1;
+
+	return ctx.fd;
+}
+
+static int nfs_safe_stat_callback(const char *path, void *context)
+{
+	struct stat *buf = context;
+
+	return stat(path, buf);
+}
+
+int nfs_safe_stat(const char *path, struct stat *buf)
+{
+	return nfs_safe_do(path, nfs_safe_stat_callback, buf);
+}