summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Dreyfus <manu@netbsd.org>2011-08-12 09:12:27 +0200
committerAnand Avati <avati@gluster.com>2011-08-12 06:51:01 -0700
commite618c1b59debbb9184874a06cbc64b8ac846a0d3 (patch)
treeedca8b11649f2db8b4685722e5f19e32ef28bb7b
parent53da3edbe5b43a994cc916b6571563491a8a414b (diff)
- Use linkat(2) instead of link(2) so that linking to symlink work on
non Linux systems - Also use mkfifo to create FIFO on NetBSD: it does not wotk with mknod Change-Id: I19ffd22b4d79009ef5f9d4a50fc6dd556c3c3ff4 BUG: 2923 Reviewed-on: http://review.gluster.com/226 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Anand Avati <avati@gluster.com>
-rw-r--r--configure.ac5
-rw-r--r--xlators/storage/posix/src/posix.c20
2 files changed, 25 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index c12beabde..d8840a436 100644
--- a/configure.ac
+++ b/configure.ac
@@ -374,6 +374,11 @@ dnl Linux, Solaris, Cygwin
AC_CHECK_MEMBERS([struct stat.st_atim.tv_nsec])
dnl FreeBSD, NetBSD
AC_CHECK_MEMBERS([struct stat.st_atimespec.tv_nsec])
+AC_CHECK_FUNC([linkat], [have_linkat=yes])
+if test "x${have_linkat}" = "xyes"; then
+ AC_DEFINE(HAVE_LINKAT, 1, [define if found linkat])
+fi
+AC_SUBST(HAVE_LINKAT)
dnl Check for argp
AC_CHECK_HEADER([argp.h], AC_DEFINE(HAVE_ARGP, 1, [have argp]))
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index dce75e736..9ac400a0c 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -37,6 +37,10 @@
#include <alloca.h>
#endif /* GF_BSD_HOST_OS */
+#ifdef HAVE_LINKAT
+#include <fcntl.h>
+#endif /* HAVE_LINKAT */
+
#include "glusterfs.h"
#include "md5.h"
#include "checksum.h"
@@ -779,6 +783,11 @@ posix_mknod (call_frame_t *frame, xlator_t *this,
goto out;
}
+#ifdef __NetBSD__
+ if (S_ISFIFO(mode))
+ op_ret = mkfifo (real_path, mode);
+ else
+#endif /* __NetBSD__ */
op_ret = mknod (real_path, mode, dev);
if (op_ret == -1) {
@@ -1526,7 +1535,18 @@ posix_link (call_frame_t *frame, xlator_t *this,
goto out;
}
+#ifdef HAVE_LINKAT
+ /*
+ * On most systems (Linux being the notable exception), link(2)
+ * first resolves symlinks. If the target is a directory or
+ * is nonexistent, it will fail. linkat(2) operates on the
+ * symlink instead of its target when the AT_SYMLINK_FOLLOW
+ * flag is not supplied.
+ */
+ op_ret = linkat (AT_FDCWD, real_oldpath, AT_FDCWD, real_newpath, 0);
+#else
op_ret = link (real_oldpath, real_newpath);
+#endif
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,