From 4aa5a3da3a35aed2905c77711717b257a20687cf Mon Sep 17 00:00:00 2001 From: Raymond Hammarling Date: Thu, 6 Aug 2015 21:33:27 +0200 Subject: [PATCH] added Windows abstractions + dokany (still wip) dokany found at `dokan-dev/dokany` --- abstractions.cc | 23 +++++++++++++++++-- abstractions.h | 52 +++++++++++++++++++++++++++++++++++++----- binding.gyp | 59 ++++++++++++++++++++++++++++++++++++------------ example.js | 8 ++++--- fuse-bindings.cc | 31 +++++++++++++------------ index.js | 20 +++++++++------- 6 files changed, 144 insertions(+), 49 deletions(-) diff --git a/abstractions.cc b/abstractions.cc index 8312474..b983f95 100644 --- a/abstractions.cc +++ b/abstractions.cc @@ -1,10 +1,10 @@ #include "abstractions.h" +#ifdef __APPLE__ + #include #include -#ifdef __APPLE__ - pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void thread_create (thread_t* thread, thread_fn fn, void* data) { @@ -25,8 +25,27 @@ void fusermount (char *path) { else execvp(argv[0], argv); } +#elif defined(_WIN32) + +HANDLE mutex = CreateMutex(NULL, false, NULL); + +void thread_create (HANDLE* thread, thread_fn fn, void* data) { + *thread = CreateThread(NULL, 0, fn, data, 0, NULL); +} + +void thread_join (HANDLE thread) { + WaitForSingleObject(thread, INFINITE); +} + +void fusermount (char *path) { + // TODO +} + #else +#include +#include + pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void thread_create (thread_t* thread, thread_fn fn, void* data) { diff --git a/abstractions.h b/abstractions.h index 64ff076..9e7d615 100644 --- a/abstractions.h +++ b/abstractions.h @@ -1,10 +1,10 @@ #include -typedef void*(*thread_fn)(void*); - #ifdef __APPLE__ // OS X +#include + #include #include @@ -34,13 +34,50 @@ NAN_INLINE static void mutex_unlock (pthread_mutex_t *mutex) { } typedef pthread_t thread_t; +typedef void* thread_fn_rtn_t; -void thread_create (thread_t*, thread_fn, void*); -void thread_join (thread_t); +#elif defined(_WIN32) + +#include +#include +#include + +typedef HANDLE bindings_sem_t; + +NAN_INLINE static int semaphore_init (HANDLE *sem) { + *sem = CreateSemaphore(NULL, 0, 10, NULL); + return *sem == NULL ? -1 : 0; +} + +NAN_INLINE static void semaphore_wait (HANDLE *sem) { + WaitForSingleObject(*sem, INFINITE); +} + +NAN_INLINE static void semaphore_signal (HANDLE *sem) { + ReleaseSemaphore(*sem, 1, NULL); +} + +extern HANDLE mutex; + +NAN_INLINE static void mutex_lock (HANDLE *mutex) { + WaitForSingleObject(*mutex, INFINITE); +} + +NAN_INLINE static void mutex_unlock (HANDLE *mutex) { + ReleaseMutex(*mutex); +} + +typedef HANDLE thread_t; +typedef DWORD thread_fn_rtn_t; + +#define fuse_session_remove_chan(x) +#define stat _stati64 #else // Linux and whatnot +#include + #include typedef sem_t bindings_sem_t; @@ -68,10 +105,13 @@ NAN_INLINE static void mutex_unlock (pthread_mutex_t *mutex) { } typedef pthread_t thread_t; +typedef void* thread_fn_rtn_t; + +#endif + +typedef thread_fn_rtn_t(*thread_fn)(void*); void thread_create (thread_t*, thread_fn, void*); void thread_join (thread_t); void fusermount (char*); - -#endif diff --git a/binding.gyp b/binding.gyp index 4f1ed49..249777d 100644 --- a/binding.gyp +++ b/binding.gyp @@ -1,17 +1,46 @@ { - "targets": [ - { - "target_name": "fuse_bindings", - "sources": [ "fuse-bindings.cc", "abstractions.cc" ], - "include_dirs": [ - " #include -#include +// #include #include #include #include #include -#include #include #include "abstractions.h" @@ -116,8 +115,8 @@ struct bindings_t { struct fuse_file_info *info; char *path; char *name; - off_t offset; - off_t length; + FUSE_OFF_T offset; + FUSE_OFF_T length; void *data; // various structs int mode; int dev; @@ -194,7 +193,7 @@ static int bindings_mknod (const char *path, mode_t mode, dev_t dev) { return bindings_call(b); } -static int bindings_truncate (const char *path, off_t size) { +static int bindings_truncate (const char *path, FUSE_OFF_T size) { bindings_t *b = bindings_get_context(); b->op = OP_TRUNCATE; @@ -204,7 +203,7 @@ static int bindings_truncate (const char *path, off_t size) { return bindings_call(b); } -static int bindings_ftruncate (const char *path, off_t size, struct fuse_file_info *info) { +static int bindings_ftruncate (const char *path, FUSE_OFF_T size, struct fuse_file_info *info) { bindings_t *b = bindings_get_context(); b->op = OP_FTRUNCATE; @@ -268,7 +267,7 @@ static int bindings_fsyncdir (const char *path, int datasync, struct fuse_file_i return bindings_call(b); } -static int bindings_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *info) { +static int bindings_readdir (const char *path, void *buf, fuse_fill_dir_t filler, FUSE_OFF_T offset, struct fuse_file_info *info) { bindings_t *b = bindings_get_context(); b->op = OP_READDIR; @@ -399,7 +398,7 @@ static int bindings_opendir (const char *path, struct fuse_file_info *info) { return bindings_call(b); } -static int bindings_read (const char *path, char *buf, size_t len, off_t offset, struct fuse_file_info *info) { +static int bindings_read (const char *path, char *buf, size_t len, FUSE_OFF_T offset, struct fuse_file_info *info) { bindings_t *b = bindings_get_context(); b->op = OP_READ; @@ -412,7 +411,7 @@ static int bindings_read (const char *path, char *buf, size_t len, off_t offset, return bindings_call(b); } -static int bindings_write (const char *path, const char *buf, size_t len, off_t offset, struct fuse_file_info * info) { +static int bindings_write (const char *path, const char *buf, size_t len, FUSE_OFF_T offset, struct fuse_file_info * info) { bindings_t *b = bindings_get_context(); b->op = OP_WRITE; @@ -600,7 +599,7 @@ static void bindings_on_close (uv_handle_t *handle) { mutex_unlock(&mutex); } -static void *bindings_thread (void *data) { +static thread_fn_rtn_t bindings_thread (void *data) { bindings_t *b = (bindings_t *) data; struct fuse_operations ops = { }; @@ -671,7 +670,7 @@ static void *bindings_thread (void *data) { uv_close((uv_handle_t*) &(b->async), &bindings_on_close); - return NULL; + return 0; } NAN_INLINE static Local bindings_get_date (struct timespec *out) { @@ -697,6 +696,7 @@ NAN_INLINE static void bindings_set_stat (struct stat *stat, Local obj) if (obj->Has(NanNew("gid"))) stat->st_gid = obj->Get(NanNew("gid"))->NumberValue(); if (obj->Has(NanNew("rdev"))) stat->st_rdev = obj->Get(NanNew("rdev"))->NumberValue(); if (obj->Has(NanNew("size"))) stat->st_size = obj->Get(NanNew("size"))->NumberValue(); +#ifndef _WIN32 if (obj->Has(NanNew("blksize"))) stat->st_blksize = obj->Get(NanNew("blksize"))->NumberValue(); if (obj->Has(NanNew("blocks"))) stat->st_blocks = obj->Get(NanNew("blocks"))->NumberValue(); #ifdef __APPLE__ @@ -708,6 +708,7 @@ NAN_INLINE static void bindings_set_stat (struct stat *stat, Local obj) if (obj->Has(NanNew("ctime"))) bindings_set_date(&stat->st_ctim, obj->Get(NanNew("ctime")).As()); if (obj->Has(NanNew("atime"))) bindings_set_date(&stat->st_atim, obj->Get(NanNew("atime")).As()); #endif +#endif } NAN_INLINE static void bindings_set_statfs (struct statvfs *statfs, Local obj) { // from http://linux.die.net/man/2/stat @@ -768,7 +769,7 @@ NAN_METHOD(OpCallback) { case OP_READLINK: { if (args.Length() > 2 && args[2]->IsString()) { NanUtf8String path(args[2]); - stpcpy((char *) b->data, *path); + strcpy((char *) b->data, *path); } } break; @@ -1130,8 +1131,8 @@ NAN_METHOD(Mount) { Local tmp[] = {NanNew(index), NanNew(OpCallback)->GetFunction()}; b->callback = new NanCallback(callback_constructor->Call(2, tmp).As()); - stpcpy(b->mnt, *path); - stpcpy(b->mntopts, "-o"); + strcpy(b->mnt, *path); + strcpy(b->mntopts, "-o"); Local options = ops->Get(NanNew("options")).As(); if (options->IsArray()) { @@ -1203,7 +1204,7 @@ NAN_METHOD(Unmount) { Local callback = args[1].As(); char *path_alloc = (char *) malloc(1024); - stpcpy(path_alloc, *path); + strcpy(path_alloc, *path); NanAsyncQueueWorker(new UnmountWorker(new NanCallback(callback), path_alloc)); NanReturnUndefined(); diff --git a/index.js b/index.js index 0bc3ea0..c02e53e 100644 --- a/index.js +++ b/index.js @@ -68,14 +68,18 @@ exports.mount = function (mnt, ops, cb) { } var mount = function () { - fs.stat(mnt, function (err, stat) { - if (err) return cb(new Error('Mountpoint does not exist')) - if (!stat.isDirectory()) return cb(new Error('Mountpoint is not a directory')) - fs.stat(path.join(mnt, '..'), function (_, parent) { - if (parent && parent.dev !== stat.dev) return cb(new Error('Mountpoint in use')) - fuse.mount(mnt, ops) - }) - }) + // TODO: I got a feeling this can be done better + if(os.platform() !== 'win32') { + fs.stat(mnt, function (err, stat) { + if (err) return cb(new Error('Mountpoint does not exist')) + if (!stat.isDirectory()) return cb(new Error('Mountpoint is not a directory')) + fs.stat(path.join(mnt, '..'), function (_, parent) { + if (parent && parent.dev !== stat.dev) return cb(new Error('Mountpoint in use')) + fuse.mount(mnt, ops) + }) + }) + } + else fuse.mount(mnt, ops) } if (!ops.force) return mount()