diff options
author | Benjamin Fleischer <fleiben@gmail.com> | 2013-01-08 14:53:09 +0100 |
---|---|---|
committer | Benjamin Fleischer <fleiben@gmail.com> | 2013-01-08 15:32:57 +0100 |
commit | 14581937282486ab7ce057ec79f226181ef1d45d (patch) | |
tree | 74dc8d75bcc78d1aae3f17d9975ebd9f0c60767c | |
parent | 66458931ddd09fc15244c5ddf3c1ec73e2fd08b9 (diff) | |
download | sshfs-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.am | 3 | ||||
-rw-r--r-- | compat/darwin_compat.c | 246 | ||||
-rw-r--r-- | compat/darwin_compat.h | 51 | ||||
-rw-r--r-- | configure.ac | 12 | ||||
-rw-r--r-- | sshfs.c | 3 |
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 @@ -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" |