aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Fleischer <fleiben@gmail.com>2013-01-08 14:53:09 +0100
committerBenjamin Fleischer <fleiben@gmail.com>2013-01-08 15:32:57 +0100
commit14581937282486ab7ce057ec79f226181ef1d45d (patch)
tree74dc8d75bcc78d1aae3f17d9975ebd9f0c60767c
parent66458931ddd09fc15244c5ddf3c1ec73e2fd08b9 (diff)
downloadsshfs-14581937282486ab7ce057ec79f226181ef1d45d.tar
sshfs-14581937282486ab7ce057ec79f226181ef1d45d.tar.gz
sshfs-14581937282486ab7ce057ec79f226181ef1d45d.tar.bz2
sshfs-14581937282486ab7ce057ec79f226181ef1d45d.zip
Add unnamed semaphore implementation for Mac OS X
In the past we relied on libosxfuse including a working unnamed semaphore implmentation for Mac OS X. This will not be the case in future releases of OSXFUSE, therefore we need to add our own implementation.
-rw-r--r--Makefile.am3
-rw-r--r--compat/darwin_compat.c246
-rw-r--r--compat/darwin_compat.h51
-rw-r--r--configure.ac12
-rw-r--r--sshfs.c3
5 files changed, 313 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index b43956c..078b2b7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,6 +6,9 @@ sshfs_SOURCES = sshfs.c cache.c cache.h
if FUSE_OPT_COMPAT
sshfs_SOURCES += compat/fuse_opt.c compat/fuse_opt.h
endif
+if DARWIN_COMPAT
+sshfs_SOURCES += compat/darwin_compat.c compat/darwin_compat.h
+endif
sshfs_LDADD = $(SSHFS_LIBS)
sshfs_CFLAGS = $(SSHFS_CFLAGS)
diff --git a/compat/darwin_compat.c b/compat/darwin_compat.c
new file mode 100644
index 0000000..3883ec6
--- /dev/null
+++ b/compat/darwin_compat.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2006-2008 Amit Singh/Google Inc.
+ * Copyright (c) 2012 Anatol Pomozov
+ * Copyright (c) 2011-2012 Benjamin Fleischer
+ */
+
+#include "darwin_compat.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/types.h>
+
+/*
+ * Semaphore implementation based on:
+ *
+ * Copyright (C) 2000,02 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ * Written by Ga<EB>l Le Mignot <address@hidden>
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the GNU C Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Semaphores */
+
+#define __SEM_ID_NONE ((int)0x0)
+#define __SEM_ID_LOCAL ((int)0xcafef00d)
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_init.html */
+int
+darwin_sem_init(darwin_sem_t *sem, int pshared, unsigned int value)
+{
+ if (pshared) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ sem->id = __SEM_ID_NONE;
+
+ if (pthread_cond_init(&sem->__data.local.count_cond, NULL)) {
+ goto cond_init_fail;
+ }
+
+ if (pthread_mutex_init(&sem->__data.local.count_lock, NULL)) {
+ goto mutex_init_fail;
+ }
+
+ sem->__data.local.count = value;
+ sem->id = __SEM_ID_LOCAL;
+
+ return 0;
+
+mutex_init_fail:
+
+ pthread_cond_destroy(&sem->__data.local.count_cond);
+
+cond_init_fail:
+
+ return -1;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_destroy.html */
+int
+darwin_sem_destroy(darwin_sem_t *sem)
+{
+ int res = 0;
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ sem->id = __SEM_ID_NONE;
+ pthread_cond_broadcast(&sem->__data.local.count_cond);
+
+ if (pthread_cond_destroy(&sem->__data.local.count_cond)) {
+ res = -1;
+ }
+
+ pthread_mutex_unlock(&sem->__data.local.count_lock);
+
+ if (pthread_mutex_destroy(&sem->__data.local.count_lock)) {
+ res = -1;
+ }
+
+ return res;
+}
+
+int
+darwin_sem_getvalue(darwin_sem_t *sem, unsigned int *sval)
+{
+ int res = 0;
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else {
+ *sval = sem->__data.local.count;
+ }
+
+ pthread_mutex_unlock(&sem->__data.local.count_lock);
+
+ return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_post.html */
+int
+darwin_sem_post(darwin_sem_t *sem)
+{
+ int res = 0;
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else if (sem->__data.local.count < DARWIN_SEM_VALUE_MAX) {
+ sem->__data.local.count++;
+ if (sem->__data.local.count == 1) {
+ pthread_cond_signal(&sem->__data.local.count_cond);
+ }
+ } else {
+ errno = ERANGE;
+ res = -1;
+ }
+
+ pthread_mutex_unlock(&sem->__data.local.count_lock);
+
+ return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/009695399/functions/sem_timedwait.html */
+int
+darwin_sem_timedwait(darwin_sem_t *sem, const struct timespec *abs_timeout)
+{
+ int res = 0;
+
+ if (abs_timeout &&
+ (abs_timeout->tv_nsec < 0 || abs_timeout->tv_nsec >= 1000000000)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ pthread_cleanup_push((void(*)(void*))&pthread_mutex_unlock,
+ &sem->__data.local.count_lock);
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ if (sem->id != __SEM_ID_LOCAL) {
+ errno = EINVAL;
+ res = -1;
+ } else {
+ if (!sem->__data.local.count) {
+ res = pthread_cond_timedwait(&sem->__data.local.count_cond,
+ &sem->__data.local.count_lock,
+ abs_timeout);
+ }
+ if (res) {
+ assert(res == ETIMEDOUT);
+ res = -1;
+ errno = ETIMEDOUT;
+ } else if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else {
+ sem->__data.local.count--;
+ }
+ }
+
+ pthread_cleanup_pop(1);
+
+ return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_trywait.html */
+int
+darwin_sem_trywait(darwin_sem_t *sem)
+{
+ int res = 0;
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else if (sem->__data.local.count) {
+ sem->__data.local.count--;
+ } else {
+ res = -1;
+ errno = EAGAIN;
+ }
+
+ pthread_mutex_unlock (&sem->__data.local.count_lock);
+
+ return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_wait.html */
+int
+darwin_sem_wait(darwin_sem_t *sem)
+{
+ int res = 0;
+
+ pthread_cleanup_push((void(*)(void*))&pthread_mutex_unlock,
+ &sem->__data.local.count_lock);
+
+ pthread_mutex_lock(&sem->__data.local.count_lock);
+
+ if (sem->id != __SEM_ID_LOCAL) {
+ errno = EINVAL;
+ res = -1;
+ } else {
+ if (!sem->__data.local.count) {
+ pthread_cond_wait(&sem->__data.local.count_cond,
+ &sem->__data.local.count_lock);
+ if (!sem->__data.local.count) {
+ /* spurious wakeup, assume it is an interruption */
+ res = -1;
+ errno = EINTR;
+ goto out;
+ }
+ }
+ if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else {
+ sem->__data.local.count--;
+ }
+ }
+
+out:
+ pthread_cleanup_pop(1);
+
+ return res;
+}
diff --git a/compat/darwin_compat.h b/compat/darwin_compat.h
new file mode 100644
index 0000000..1cdbcce
--- /dev/null
+++ b/compat/darwin_compat.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006-2008 Amit Singh/Google Inc.
+ * Copyright (c) 2011-2012 Benjamin Fleischer
+ */
+
+#ifndef _DARWIN_COMPAT_
+#define _DARWIN_COMPAT_
+
+#include <pthread.h>
+
+/* Semaphores */
+
+struct __local_sem_t
+{
+ unsigned int count;
+ pthread_mutex_t count_lock;
+ pthread_cond_t count_cond;
+};
+
+typedef struct fuse_sem {
+ int id;
+ union {
+ struct __local_sem_t local;
+ } __data;
+} darwin_sem_t;
+
+#define DARWIN_SEM_VALUE_MAX ((int32_t)32767)
+
+int darwin_sem_init(darwin_sem_t *sem, int pshared, unsigned int value);
+int darwin_sem_destroy(darwin_sem_t *sem);
+int darwin_sem_getvalue(darwin_sem_t *sem, unsigned int *value);
+int darwin_sem_post(darwin_sem_t *sem);
+int darwin_sem_timedwait(darwin_sem_t *sem, const struct timespec *abs_timeout);
+int darwin_sem_trywait(darwin_sem_t *sem);
+int darwin_sem_wait(darwin_sem_t *sem);
+
+/* Caller must not include <semaphore.h> */
+
+typedef darwin_sem_t sem_t;
+
+#define sem_init(s, p, v) darwin_sem_init(s, p, v)
+#define sem_destroy(s) darwin_sem_destroy(s)
+#define sem_getvalue(s, v) darwin_sem_getvalue(s, v)
+#define sem_post(s) darwin_sem_post(s)
+#define sem_timedwait(s, t) darwin_sem_timedwait(s, t)
+#define sem_trywait(s) darwin_sem_trywait(s)
+#define sem_wait(s) darwin_sem_wait(s)
+
+#define SEM_VALUE_MAX DARWIN_SEM_VALUE_MAX
+
+#endif /* _DARWIN_COMPAT_ */
diff --git a/configure.ac b/configure.ac
index d433038..b2556f2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,5 @@
AC_INIT(sshfs-fuse, 2.4)
+AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(config.h)
@@ -11,6 +12,14 @@ sshnodelay_libs=$LIBS
AC_SUBST(sshnodelay_libs)
LIBS=
+case $target_os in
+ *linux*) arch=linux;;
+ *netbsd*) arch=netbsd;;
+ *bsd*) arch=bsd;;
+ *darwin*) arch=darwin;;
+ *) arch=unknown;;
+esac
+
AC_ARG_ENABLE(sshnodelay,
[ --disable-sshnodelay Don't compile NODELAY workaround for ssh])
@@ -43,10 +52,11 @@ oldlibs="$LIBS"
LIBS="$LIBS $SSHFS_LIBS"
AC_CHECK_FUNC([fuse_opt_parse], [have_fuse_opt_parse=yes])
LIBS="$oldlibs"
-if test "$have_fuse_opt_parse" = no; then
+if test "$have_fuse_opt_parse" = no -o "$arch" = darwin; then
CFLAGS="$CFLAGS -Icompat"
fi
AM_CONDITIONAL(FUSE_OPT_COMPAT, test "$have_fuse_opt_parse" = no)
+AM_CONDITIONAL(DARWIN_COMPAT, test "$arch" = darwin)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
diff --git a/sshfs.c b/sshfs.c
index bf65aea..5658412 100644
--- a/sshfs.c
+++ b/sshfs.c
@@ -23,7 +23,7 @@
#include <string.h>
#include <stdint.h>
#include <errno.h>
-#if !__APPLE__
+#ifndef __APPLE__
# include <semaphore.h>
#endif
#include <pthread.h>
@@ -46,6 +46,7 @@
#ifdef __APPLE__
# include <strings.h>
# include <libgen.h>
+# include <darwin_compat.h>
#endif
#include "cache.h"