diff --git a/opt/cygfuse/Makefile b/opt/cygfuse/Makefile index d127c328..f8fc26ed 100755 --- a/opt/cygfuse/Makefile +++ b/opt/cygfuse/Makefile @@ -6,21 +6,34 @@ usage: @echo "make cygport|dist" 1>&2 @exit 2 -.PHONY: cygport -cygport: +.PHONY: cygport dist clean +cygport: clean cygport2 cygport3 +dist: cygport dist2 dist3 +clean: rm -rf $(Build) + +.PHONY: cygport2 +cygport2: $(Build)/winfsp-work-$(Arch).tar.gz + cp fuse/fuse.cygport $(Build)/fuse.cygport + CYGPORT_SRC_URI=winfsp-work-$(Arch).tar.gz CYGPORT_SRC_DIR=winfsp-work-$(Arch) \ + cygport $(Build)/fuse.cygport download prep compile install package + +.PHONY: cygport3 +cygport3: $(Build)/winfsp-work-$(Arch).tar.gz + cp fuse3/fuse3.cygport $(Build)/fuse3.cygport + CYGPORT_SRC_URI=winfsp-work-$(Arch).tar.gz CYGPORT_SRC_DIR=winfsp-work-$(Arch) \ + cygport $(Build)/fuse3.cygport download prep compile install package + +$(Build)/winfsp-work-$(Arch).tar.gz: mkdir -p $(Build) ( \ cd `git rev-parse --show-toplevel` && \ Stash=`git stash create` && \ git archive --prefix=winfsp-work-$(Arch)/ --format=tar.gz $${Stash:-HEAD} \ ) > $(Build)/winfsp-work-$(Arch).tar.gz - cp fuse/fuse.cygport $(Build)/fuse.cygport - CYGPORT_SRC_URI=winfsp-work-$(Arch).tar.gz CYGPORT_SRC_DIR=winfsp-work-$(Arch) \ - cygport $(Build)/fuse.cygport download prep compile install package -.PHONY: dist -dist: cygport +.PHONY: dist2 +dist2: cygport2 case $(Arch) in \ x86_64) \ mkdir -p dist/x64 && \ @@ -31,3 +44,16 @@ dist: cygport rm -f dist/x86/fuse-*[0-9].tar.xz && \ cp build/fuse-*[0-9].$(Arch)/dist/fuse/fuse-*[0-9].tar.xz dist/x86 ;; \ esac + +.PHONY: dist3 +dist3: cygport3 + case $(Arch) in \ + x86_64) \ + mkdir -p dist/x64 && \ + rm -f dist/x64/fuse3-*[0-9].tar.xz && \ + cp build/fuse3-*[0-9].$(Arch)/dist/fuse3/fuse3-*[0-9].tar.xz dist/x64 ;; \ + i686) \ + mkdir -p dist/x86 && \ + rm -f dist/x86/fuse3-*[0-9].tar.xz && \ + cp build/fuse3-*[0-9].$(Arch)/dist/fuse3/fuse3-*[0-9].tar.xz dist/x86 ;; \ + esac diff --git a/opt/cygfuse/dist/install.sh b/opt/cygfuse/dist/install.sh index 460971c0..c9314437 100644 --- a/opt/cygfuse/dist/install.sh +++ b/opt/cygfuse/dist/install.sh @@ -1,8 +1,15 @@ cd "$(dirname "$0")" case $(uname -m) in x86_64) - tar -C/ -xaf x64/fuse-2.8-*.tar.xz ;; + tar -C/ -xaf x64/fuse-2.*.tar.xz + tar -C/ -xaf x64/fuse-3.*.tar.xz + ;; +i686) + tar -C/ -xaf x86/fuse-2.*.tar.xz + tar -C/ -xaf x86/fuse-3.*.tar.xz + ;; *) - tar -C/ -xaf x86/fuse-2.8-*.tar.xz ;; + echo unsupported architecture 1>&2 + exit 1 esac echo FUSE for Cygwin installed. diff --git a/opt/cygfuse/dist/uninstall.sh b/opt/cygfuse/dist/uninstall.sh index cbe55145..d2cf6a20 100644 --- a/opt/cygfuse/dist/uninstall.sh +++ b/opt/cygfuse/dist/uninstall.sh @@ -1,8 +1,13 @@ cd "$(dirname "$0")" case $(uname -m) in x86_64) - tar -taf x64/fuse-2.8-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f ;; + tar -taf x64/fuse-2.*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f ;; + tar -taf x64/fuse-3.*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f ;; +i686) + tar -taf x86/fuse-2.*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f ;; + tar -taf x86/fuse-3.*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f ;; *) - tar -taf x86/fuse-2.8-*.tar.xz | sed -e '/\/$/d' -e 's/.*/\/&/' | xargs rm -f ;; + echo unsupported architecture 1>&2 + exit 1 esac echo FUSE for Cygwin uninstalled. diff --git a/opt/cygfuse/dist/x64/fuse-2.8-8.tar.xz b/opt/cygfuse/dist/x64/fuse-2.8-8.tar.xz deleted file mode 100644 index b1d63e56..00000000 Binary files a/opt/cygfuse/dist/x64/fuse-2.8-8.tar.xz and /dev/null differ diff --git a/opt/cygfuse/dist/x64/fuse-2.8-9.tar.xz b/opt/cygfuse/dist/x64/fuse-2.8-9.tar.xz new file mode 100644 index 00000000..8cc31fbd Binary files /dev/null and b/opt/cygfuse/dist/x64/fuse-2.8-9.tar.xz differ diff --git a/opt/cygfuse/dist/x64/fuse3-3.2-1.tar.xz b/opt/cygfuse/dist/x64/fuse3-3.2-1.tar.xz new file mode 100644 index 00000000..14b3bf08 Binary files /dev/null and b/opt/cygfuse/dist/x64/fuse3-3.2-1.tar.xz differ diff --git a/opt/cygfuse/dist/x86/fuse-2.8-8.tar.xz b/opt/cygfuse/dist/x86/fuse-2.8-8.tar.xz deleted file mode 100644 index c9c5a56c..00000000 Binary files a/opt/cygfuse/dist/x86/fuse-2.8-8.tar.xz and /dev/null differ diff --git a/opt/cygfuse/dist/x86/fuse-2.8-9.tar.xz b/opt/cygfuse/dist/x86/fuse-2.8-9.tar.xz new file mode 100644 index 00000000..0104796c Binary files /dev/null and b/opt/cygfuse/dist/x86/fuse-2.8-9.tar.xz differ diff --git a/opt/cygfuse/dist/x86/fuse3-3.2-1.tar.xz b/opt/cygfuse/dist/x86/fuse3-3.2-1.tar.xz new file mode 100644 index 00000000..a04df79a Binary files /dev/null and b/opt/cygfuse/dist/x86/fuse3-3.2-1.tar.xz differ diff --git a/opt/cygfuse/fuse3/Makefile b/opt/cygfuse/fuse3/Makefile new file mode 100644 index 00000000..ad6e646d --- /dev/null +++ b/opt/cygfuse/fuse3/Makefile @@ -0,0 +1,29 @@ +Version = $(shell sed -n '/^VERSION=/s/VERSION=\(.*\)/\1/p' fuse3.cygport) +Arch = $(shell uname -m) +Build = build/$(Arch) +#Debug = -g + +.PHONY: build test +build: $(Build)/cygfuse-$(Version).dll $(Build)/fuse3.pc +test: $(Build)/cygfuse-test.exe + +$(Build)/cygfuse-$(Version).dll: cygfuse.c fuse3.cygport + @mkdir -p $(Build) + gcc $(Debug) \ + -shared -o $(Build)/cygfuse-$(Version).dll \ + -Wl,--out-implib=$(Build)/libfuse-$(Version).dll.a \ + -I../../../inc/fuse3 \ + cygfuse.c + [ -n "$(Debug)" ] || strip $(Build)/cygfuse-$(Version).dll + +$(Build)/fuse3.pc: fuse3.pc.in fuse3.cygport + @mkdir -p $(Build) + sed "s/@Version@/$(Version)/g" fuse3.pc.in > $(Build)/fuse3.pc + +$(Build)/cygfuse-test.exe: cygfuse-test.c $(Build)/cygfuse-$(Version).dll + @mkdir -p $(Build) + gcc $(Debug) \ + -o $(Build)/cygfuse-test.exe \ + -I../../../inc/fuse3 -DCYGFUSE \ + cygfuse-test.c \ + -L$(PWD)/$(Build) -lfuse-$(Version) diff --git a/opt/cygfuse/fuse3/cygfuse-test.c b/opt/cygfuse/fuse3/cygfuse-test.c new file mode 100644 index 00000000..993d8e61 --- /dev/null +++ b/opt/cygfuse/fuse3/cygfuse-test.c @@ -0,0 +1,6 @@ +#include + +int main() +{ + return !(FUSE_VERSION == fuse_version()); +} diff --git a/opt/cygfuse/fuse3/cygfuse.c b/opt/cygfuse/fuse3/cygfuse.c new file mode 100644 index 00000000..390abdcc --- /dev/null +++ b/opt/cygfuse/fuse3/cygfuse.c @@ -0,0 +1,169 @@ +/** + * @file fuse3/cygfuse.c + * + * @copyright 2015-2018 Bill Zissimopoulos + */ +/* + * This file is part of WinFsp. + * + * You can redistribute it and/or modify it under the terms of the GNU + * General Public License version 3 as published by the Free Software + * Foundation. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + */ + +#include +#include +#include +#include +#include +#include + +static void *cygfuse_init_slow(int force); +static void *cygfuse_init_winfsp(); + +static pthread_mutex_t cygfuse_mutex = PTHREAD_MUTEX_INITIALIZER; +static void *cygfuse_handle = 0; + +static inline void *cygfuse_init_fast(void) +{ + void *handle = cygfuse_handle; + __sync_synchronize(); /* memory barrier */ + if (0 == handle) + handle = cygfuse_init_slow(0); + return handle; +} + +static void *cygfuse_init_slow(int force) +{ + void *handle; + pthread_mutex_lock(&cygfuse_mutex); + handle = cygfuse_handle; + if (force || 0 == handle) + { + handle = cygfuse_init_winfsp(); + __sync_synchronize(); /* memory barrier */ + cygfuse_handle = handle; + } + pthread_mutex_unlock(&cygfuse_mutex); + return handle; +} + +/* + * Unfortunately Cygwin fork is very fragile and cannot even correctly + * handle dlopen'ed DLL's if they are native (rather than Cygwin ones). + * + * So we have this very nasty hack where we reset the dlopen'ed handle + * immediately after daemonization. This will force cygfuse_init() to + * reload the WinFsp DLL and reset all API pointers in the daemonized + * process. + */ +static inline int cygfuse_daemon(int nochdir, int noclose) +{ + if (-1 == daemon(nochdir, noclose)) + return -1; + + /* force reload of WinFsp DLL to workaround fork() problems */ + cygfuse_init_slow(1); + + return 0; +} +#define daemon cygfuse_daemon + +#define FSP_FUSE_API static +#define FSP_FUSE_API_NAME(api) (* pfn_ ## api) +#define FSP_FUSE_API_CALL(api) (cygfuse_init_fast(), pfn_ ## api) +#define FSP_FUSE_SYM(proto, ...) __attribute__ ((visibility("default"))) proto { __VA_ARGS__ } +#include +#include +#include + +#if defined(__LP64__) +#define CYGFUSE_WINFSP_NAME "winfsp-x64.dll" +#else +#define CYGFUSE_WINFSP_NAME "winfsp-x86.dll" +#endif +#define CYGFUSE_WINFSP_PATH "bin\\" CYGFUSE_WINFSP_NAME +#define CYGFUSE_GET_API(h, n) \ + if (0 == (*(void **)&(pfn_ ## n) = dlsym(h, #n)))\ + return cygfuse_init_fail(); + +static void *cygfuse_init_fail(); +static void *cygfuse_init_winfsp() +{ + void *h; + + h = dlopen(CYGFUSE_WINFSP_NAME, RTLD_NOW); + if (0 == h) + { + char winpath[260], *psxpath; + int regfd, bytes; + + regfd = open("/proc/registry32/HKEY_LOCAL_MACHINE/Software/WinFsp/InstallDir", O_RDONLY); + if (-1 == regfd) + return cygfuse_init_fail(); + + bytes = read(regfd, winpath, sizeof winpath - sizeof CYGFUSE_WINFSP_PATH); + close(regfd); + if (-1 == bytes || 0 == bytes) + return cygfuse_init_fail(); + + if ('\0' == winpath[bytes - 1]) + bytes--; + memcpy(winpath + bytes, CYGFUSE_WINFSP_PATH, sizeof CYGFUSE_WINFSP_PATH); + + psxpath = (char *)cygwin_create_path(CCP_WIN_A_TO_POSIX | CCP_PROC_CYGDRIVE, winpath); + if (0 == psxpath) + return cygfuse_init_fail(); + + h = dlopen(psxpath, RTLD_NOW); + free(psxpath); + if (0 == h) + return cygfuse_init_fail(); + } + + /* winfsp_fuse.h */ + CYGFUSE_GET_API(h, fsp_fuse_signal_handler); + + /* fuse_common.h */ + CYGFUSE_GET_API(h, fsp_fuse3_parse_conn_info_opts); + CYGFUSE_GET_API(h, fsp_fuse3_apply_conn_info_opts); + CYGFUSE_GET_API(h, fsp_fuse3_version); + CYGFUSE_GET_API(h, fsp_fuse3_pkgversion); + CYGFUSE_GET_API(h, fsp_fuse_ntstatus_from_errno); + + /* fuse.h */ + CYGFUSE_GET_API(h, fsp_fuse3_main_real); + CYGFUSE_GET_API(h, fsp_fuse3_lib_help); + CYGFUSE_GET_API(h, fsp_fuse3_new_30); + CYGFUSE_GET_API(h, fsp_fuse3_new); + CYGFUSE_GET_API(h, fsp_fuse3_destroy); + CYGFUSE_GET_API(h, fsp_fuse3_mount); + CYGFUSE_GET_API(h, fsp_fuse3_unmount); + CYGFUSE_GET_API(h, fsp_fuse3_loop); + CYGFUSE_GET_API(h, fsp_fuse3_loop_mt_31); + CYGFUSE_GET_API(h, fsp_fuse3_loop_mt); + CYGFUSE_GET_API(h, fsp_fuse3_exit); + CYGFUSE_GET_API(h, fsp_fuse3_get_context); + + /* fuse_opt.h */ + CYGFUSE_GET_API(h, fsp_fuse_opt_parse); + CYGFUSE_GET_API(h, fsp_fuse_opt_add_arg); + CYGFUSE_GET_API(h, fsp_fuse_opt_insert_arg); + CYGFUSE_GET_API(h, fsp_fuse_opt_free_args); + CYGFUSE_GET_API(h, fsp_fuse_opt_add_opt); + CYGFUSE_GET_API(h, fsp_fuse_opt_add_opt_escaped); + CYGFUSE_GET_API(h, fsp_fuse_opt_match); + + return h; +} + +static void *cygfuse_init_fail() +{ + fprintf(stderr, "cygfuse: initialization failed: " CYGFUSE_WINFSP_NAME " not found\n"); + exit(1); + return 0; +} diff --git a/opt/cygfuse/fuse3/fuse3.cygport b/opt/cygfuse/fuse3/fuse3.cygport new file mode 100644 index 00000000..b7906db5 --- /dev/null +++ b/opt/cygfuse/fuse3/fuse3.cygport @@ -0,0 +1,35 @@ +NAME="fuse3" +VERSION=3.2 +RELEASE=1 +CATEGORY="Utils" +SUMMARY="WinFsp FUSE3 compatibility layer" +DESCRIPTION="Enables FUSE3 file systems to be run on Cygwin." +HOMEPAGE="http://www.secfs.net/winfsp/" + +SRC_URI=${CYGPORT_SRC_URI:-"https://github.com/billziss-gh/winfsp/archive/master.tar.gz"} +SRC_DIR=${CYGPORT_SRC_DIR:-winfsp-master} + +src_compile() +{ + lndirs + cd ${B}/opt/cygfuse/fuse3 + make +} + +src_install() +{ + cd ${B}/inc/fuse3 + includeinto fuse3 + doinclude fuse.h + doinclude fuse_common.h + doinclude fuse_opt.h + doinclude winfsp_fuse.h + + cd ${B}/opt/cygfuse/fuse3/build/$(ARCH) + dobin cygfuse-${VERSION}.dll + dolib libfuse-${VERSION}.dll.a + dosym libfuse-${VERSION}.dll.a /usr/lib/libfuse3.dll.a + dopkgconfig fuse3.pc +} + +RESTRICT="strip postinst-doc" diff --git a/opt/cygfuse/fuse3/fuse3.pc.in b/opt/cygfuse/fuse3/fuse3.pc.in new file mode 100644 index 00000000..ea9ff0b2 --- /dev/null +++ b/opt/cygfuse/fuse3/fuse3.pc.in @@ -0,0 +1,9 @@ +prefix=/usr +incdir=${prefix}/include/fuse3 + +Name: fuse +Description: WinFsp FUSE3 compatible API +Version: @Version@ +URL: http://www.secfs.net/winfsp/ +Libs: -lfuse-@Version@ +Cflags: -I"${incdir}" -DCYGFUSE