On Tue, Aug 02, 2011 at 09:08:38AM +0000, Emmanuel Dreyfus wrote: > It seems this has been adressed by standards: > http://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html Attached is a patch that fixes the problem for systems that implement linkat(2). While there, I have two NetBSD compatibility patches: - allow georeplication to build - use mkfifo(2) to create FIFO instead of mknod(2) -- Emmanuel Dreyfus manu@xxxxxxxxxx
diff --git a/configure.ac b/configure.ac index 6d343a4..7d3b188 100644 --- a/configure.ac +++ b/configure.ac @@ -295,6 +295,9 @@ case $host_os in linux*) #do nothing ;; + netbsd*) +#do nothing + ;; *) #disabling geo replication for non-linux platforms enable_georeplication=no @@ -359,6 +362,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 6b71683..4b4e856 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,