changeset 6811:9bc620b934f4 HEAD

Added nfs_safe_link().
author Timo Sirainen <tss@iki.fi>
date Thu, 15 Nov 2007 16:27:41 +0200
parents a4c87d5d881c
children ebe88bc73154
files src/lib/nfs-workarounds.c src/lib/nfs-workarounds.h
diffstat 2 files changed, 32 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/nfs-workarounds.c	Thu Nov 15 15:01:27 2007 +0200
+++ b/src/lib/nfs-workarounds.c	Thu Nov 15 16:27:41 2007 +0200
@@ -129,6 +129,35 @@
 	return nfs_safe_do(path, nfs_safe_lstat_callback, buf);
 }
 
+int nfs_safe_link(const char *oldpath, const char *newpath)
+{
+	struct stat st;
+
+#ifdef DEBUG
+	if (stat(oldpath, &st) == 0 && st.st_nlink != 1) {
+		i_panic("nfs_safe_link(): %s link count = %d",
+			oldpath, (int)st.st_nlink);
+	}
+#endif
+	if (link(oldpath, newpath) == 0) {
+#ifndef __FreeBSD__
+		return 0;
+#endif
+		/* FreeBSD at least up to v6.2 converts EEXIST errors to
+		   success. */
+	} else if (errno != EEXIST)
+		return -1;
+
+	/* We don't know if it succeeded or failed. stat() to make sure. */
+	if (stat(oldpath, &st) < 0)
+		return -1;
+	if (st.st_nlink < 2) {
+		errno = EEXIST;
+		return -1;
+	}
+	return 0;
+}
+
 static bool nfs_flush_fchown_uid(const char *path, int fd)
 {
 	struct stat st;
--- a/src/lib/nfs-workarounds.h	Thu Nov 15 15:01:27 2007 +0200
+++ b/src/lib/nfs-workarounds.h	Thu Nov 15 16:27:41 2007 +0200
@@ -14,6 +14,9 @@
    Doesn't flush attribute cache. */
 int nfs_safe_stat(const char *path, struct stat *buf);
 int nfs_safe_lstat(const char *path, struct stat *buf);
+/* Same as link(), but handle UDP retries by stat()ing to see if the success
+   reply just got lost. Assumes that oldpath's link count is initially 1. */
+int nfs_safe_link(const char *oldpath, const char *newpath);
 
 /* Flush attribute cache for given path. If flush_dir is TRUE, also the
    directory's cache is flushed. */