1
0
mirror of https://github.com/fuse-friends/fuse-native synced 2025-06-13 12:53:54 +00:00

Update for Dokany v1.0.0 RC2 (Windows) (#22)

* Fix compile error MaybeLocal not directly castable to Local

* Fix support for Dokany 1.0.0-RC2

* Fix pre-Visual Studio 2015 lacking struct timespec

* Add explanatory comment for #define FUSE_STAT

* Update README with new Windows info

* Tweak README Windows section a bit
This commit is contained in:
Raymond Hammarling 2016-10-30 10:42:49 +01:00 committed by Mathias Buus
parent 00acbbb310
commit 4af46f1f9d
4 changed files with 47 additions and 35 deletions

View File

@ -17,14 +17,16 @@ You need to have FUSE installed (or Dokany on Windows)
* On OSX * On OSX
* if you use Brew, install [OSXFuse](http://osxfuse.github.com/) and `brew install pkg-config` * if you use Brew, install [OSXFuse](http://osxfuse.github.com/) and `brew install pkg-config`
* if you use MacPorts, `sudo port install osxfuse +devel` * if you use MacPorts, `sudo port install osxfuse +devel`
* On Windows see `Windows` down below... * On Windows install [Dokany](https://github.com/dokan-dev/dokany)
### Windows ### Windows
**WARNING**: Dokany is still not quite stable. It can cause BSODs. Be careful. **WARNING**: Dokany is still not quite stable. It can cause BSODs. Be careful.
Using this on Windows is slightly more complicated. You need to install [Dokany](https://github.com/dokan-dev/dokany) (for `dokanfuse.lib`, `dokanctl.exe`, driver and service) **and** clone its repo (for the headers). ~~Using this on Windows is slightly more complicated. You need to install [Dokany](https://github.com/dokan-dev/dokany) (for `dokanfuse.lib`, `dokanctl.exe`, driver and service) **and** clone its repo (for the headers).~~
Once the Dokany repo is cloned, you also need to set environment variable `DOKAN_INSTALL_DIR` to the path to `DokenLibrary` of your Dokany installaton, and `DOKAN_FUSE_INCLUDE` to the path to `*dokany repo*\dokan_fuse\include`. ~~Once the Dokany repo is cloned, you also need to set environment variable `DOKAN_INSTALL_DIR` to the path to `DokenLibrary` of your Dokany installaton, and `DOKAN_FUSE_INCLUDE` to the path to `*dokany repo*\dokan_fuse\include`.~~
**EDIT**: Dokany now includes needed headers and sets proper environment variables when installing! Just install Dokany and this module should install and work just fine! (Drop an issue otherwise)
## Usage ## Usage

View File

@ -62,10 +62,18 @@ void thread_join (HANDLE thread) {
} }
int fusermount (char *path) { int fusermount (char *path) {
char* dokanPath = getenv("DOKAN_INSTALL_DIR"); char* dokanPath = getenv("DokanLibrary1");
char cmdLine[MAX_PATH]; char cmdLine[MAX_PATH];
if(dokanPath) sprintf(cmdLine, "\"%s/dokanctl.exe\" /u %s", dokanPath, path); if(dokanPath) {
// Let's make sure there aren't no double slashes
const char* dokanPathLast = dokanPath + strlen(dokanPath) - 1;
const char* potentialEndSlash =
(*dokanPathLast == '/' || *dokanPathLast == '\\') ? "" : "\\";
sprintf(cmdLine, "\"%s%sdokanctl.exe\" /u %s", dokanPath, potentialEndSlash, path);
}
else sprintf(cmdLine, "dokanctl.exe /u %s", path); else sprintf(cmdLine, "dokanctl.exe /u %s", path);
STARTUPINFO info = {sizeof(info)}; STARTUPINFO info = {sizeof(info)};

View File

@ -26,15 +26,25 @@
} }
}], }],
['OS=="win"', { ['OS=="win"', {
"variables": {
'dokan__install_dir%': '$(DokanLibrary1)/include/fuse'
},
"include_dirs": [ "include_dirs": [
"$(DOKAN_FUSE_INCLUDE)", "<(dokan__install_dir)",
"$(INCLUDE)" "$(INCLUDE)"
], ],
"link_settings": { "link_settings": {
"libraries": [ "libraries": [
"<!(echo %DOKAN_INSTALL_DIR%)/dokanfuse.lib" "<(dokan__library)"
] ]
} },
"conditions": [
['target_arch=="x64"', {
"variables": { 'dokan__library%': '$(DokanLibrary1_LibraryPath_x64)/dokanfuse1' }
}, {
"variables": { 'dokan__library%': '$(DokanLibrary1_LibraryPath_x86)/dokanfuse1' }
}]
]
}] }]
], ],
"configurations": { "configurations": {

View File

@ -2,9 +2,23 @@
#define FUSE_USE_VERSION 29 #define FUSE_USE_VERSION 29
#if defined(_WIN32) && _MSC_VER < 1900
// Visual Studio 2015 adds struct timespec,
// this #define will make Dokany define its
// own struct timespec on earlier versions
#define _CRT_NO_TIME_T
#endif
#include <fuse.h> #include <fuse.h>
#include <fuse_opt.h> #include <fuse_opt.h>
#ifndef _MSC_VER
// Need to use FUSE_STAT when using Dokany with Visual Studio.
// To keep things simple, when not using Visual Studio,
// define FUSE_STAT to be "stat" so we can use FUSE_STAT in the code anyway.
#define FUSE_STAT stat
#endif
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
@ -56,7 +70,7 @@ enum bindings_ops_t {
static Nan::Persistent<Function> buffer_constructor; static Nan::Persistent<Function> buffer_constructor;
static Nan::Callback *callback_constructor; static Nan::Callback *callback_constructor;
static struct stat empty_stat; static struct FUSE_STAT empty_stat;
struct bindings_t { struct bindings_t {
int index; int index;
@ -220,7 +234,7 @@ static int bindings_ftruncate (const char *path, FUSE_OFF_T size, struct fuse_fi
return bindings_call(b); return bindings_call(b);
} }
static int bindings_getattr (const char *path, struct stat *stat) { static int bindings_getattr (const char *path, struct FUSE_STAT *stat) {
bindings_t *b = bindings_get_context(); bindings_t *b = bindings_get_context();
b->op = OP_GETATTR; b->op = OP_GETATTR;
@ -230,7 +244,7 @@ static int bindings_getattr (const char *path, struct stat *stat) {
return bindings_call(b); return bindings_call(b);
} }
static int bindings_fgetattr (const char *path, struct stat *stat, struct fuse_file_info *info) { static int bindings_fgetattr (const char *path, struct FUSE_STAT *stat, struct fuse_file_info *info) {
bindings_t *b = bindings_get_context(); bindings_t *b = bindings_get_context();
b->op = OP_FGETATTR; b->op = OP_FGETATTR;
@ -679,7 +693,6 @@ static thread_fn_rtn_t bindings_thread (void *data) {
return 0; return 0;
} }
#ifndef _WIN32
NAN_INLINE static Local<Date> bindings_get_date (struct timespec *out) { NAN_INLINE static Local<Date> bindings_get_date (struct timespec *out) {
int ms = (out->tv_nsec / 1000); int ms = (out->tv_nsec / 1000);
return Nan::New<Date>(out->tv_sec * 1000 + ms).ToLocalChecked(); return Nan::New<Date>(out->tv_sec * 1000 + ms).ToLocalChecked();
@ -693,19 +706,8 @@ NAN_INLINE static void bindings_set_date (struct timespec *out, Local<Date> date
out->tv_sec = secs; out->tv_sec = secs;
out->tv_nsec = ns; out->tv_nsec = ns;
} }
#else
NAN_INLINE static Local<Date> bindings_get_date (time_t *out) {
return Nan::New<Date>(*out * 1000.0);
}
NAN_INLINE static void bindings_set_date (time_t *out, Local<Date> date) { NAN_INLINE static void bindings_set_stat (struct FUSE_STAT *stat, Local<Object> obj) {
double ms = date->NumberValue();
time_t secs = (time_t)(ms / 1000.0);
*out = secs;
}
#endif
NAN_INLINE static void bindings_set_stat (struct stat *stat, Local<Object> obj) {
if (obj->Has(LOCAL_STRING("dev"))) stat->st_dev = obj->Get(LOCAL_STRING("dev"))->NumberValue(); if (obj->Has(LOCAL_STRING("dev"))) stat->st_dev = obj->Get(LOCAL_STRING("dev"))->NumberValue();
if (obj->Has(LOCAL_STRING("ino"))) stat->st_ino = obj->Get(LOCAL_STRING("ino"))->NumberValue(); if (obj->Has(LOCAL_STRING("ino"))) stat->st_ino = obj->Get(LOCAL_STRING("ino"))->NumberValue();
if (obj->Has(LOCAL_STRING("mode"))) stat->st_mode = obj->Get(LOCAL_STRING("mode"))->Uint32Value(); if (obj->Has(LOCAL_STRING("mode"))) stat->st_mode = obj->Get(LOCAL_STRING("mode"))->Uint32Value();
@ -714,18 +716,12 @@ NAN_INLINE static void bindings_set_stat (struct stat *stat, Local<Object> obj)
if (obj->Has(LOCAL_STRING("gid"))) stat->st_gid = obj->Get(LOCAL_STRING("gid"))->NumberValue(); if (obj->Has(LOCAL_STRING("gid"))) stat->st_gid = obj->Get(LOCAL_STRING("gid"))->NumberValue();
if (obj->Has(LOCAL_STRING("rdev"))) stat->st_rdev = obj->Get(LOCAL_STRING("rdev"))->NumberValue(); if (obj->Has(LOCAL_STRING("rdev"))) stat->st_rdev = obj->Get(LOCAL_STRING("rdev"))->NumberValue();
if (obj->Has(LOCAL_STRING("size"))) stat->st_size = obj->Get(LOCAL_STRING("size"))->NumberValue(); if (obj->Has(LOCAL_STRING("size"))) stat->st_size = obj->Get(LOCAL_STRING("size"))->NumberValue();
#ifndef _WIN32
if (obj->Has(LOCAL_STRING("blocks"))) stat->st_blocks = obj->Get(LOCAL_STRING("blocks"))->NumberValue(); if (obj->Has(LOCAL_STRING("blocks"))) stat->st_blocks = obj->Get(LOCAL_STRING("blocks"))->NumberValue();
if (obj->Has(LOCAL_STRING("blksize"))) stat->st_blksize = obj->Get(LOCAL_STRING("blksize"))->NumberValue(); if (obj->Has(LOCAL_STRING("blksize"))) stat->st_blksize = obj->Get(LOCAL_STRING("blksize"))->NumberValue();
#endif
#ifdef __APPLE__ #ifdef __APPLE__
if (obj->Has(LOCAL_STRING("mtime"))) bindings_set_date(&stat->st_mtimespec, obj->Get(LOCAL_STRING("mtime")).As<Date>()); if (obj->Has(LOCAL_STRING("mtime"))) bindings_set_date(&stat->st_mtimespec, obj->Get(LOCAL_STRING("mtime")).As<Date>());
if (obj->Has(LOCAL_STRING("ctime"))) bindings_set_date(&stat->st_ctimespec, obj->Get(LOCAL_STRING("ctime")).As<Date>()); if (obj->Has(LOCAL_STRING("ctime"))) bindings_set_date(&stat->st_ctimespec, obj->Get(LOCAL_STRING("ctime")).As<Date>());
if (obj->Has(LOCAL_STRING("atime"))) bindings_set_date(&stat->st_atimespec, obj->Get(LOCAL_STRING("atime")).As<Date>()); if (obj->Has(LOCAL_STRING("atime"))) bindings_set_date(&stat->st_atimespec, obj->Get(LOCAL_STRING("atime")).As<Date>());
#elif defined(_WIN32)
if (obj->Has(LOCAL_STRING("mtime"))) bindings_set_date(&stat->st_mtime, obj->Get(LOCAL_STRING("mtime")).As<Date>());
if (obj->Has(LOCAL_STRING("ctime"))) bindings_set_date(&stat->st_ctime, obj->Get(LOCAL_STRING("ctime")).As<Date>());
if (obj->Has(LOCAL_STRING("atime"))) bindings_set_date(&stat->st_atime, obj->Get(LOCAL_STRING("atime")).As<Date>());
#else #else
if (obj->Has(LOCAL_STRING("mtime"))) bindings_set_date(&stat->st_mtim, obj->Get(LOCAL_STRING("mtime")).As<Date>()); if (obj->Has(LOCAL_STRING("mtime"))) bindings_set_date(&stat->st_mtim, obj->Get(LOCAL_STRING("mtime")).As<Date>());
if (obj->Has(LOCAL_STRING("ctime"))) bindings_set_date(&stat->st_ctim, obj->Get(LOCAL_STRING("ctime")).As<Date>()); if (obj->Has(LOCAL_STRING("ctime"))) bindings_set_date(&stat->st_ctim, obj->Get(LOCAL_STRING("ctime")).As<Date>());
@ -769,7 +765,7 @@ NAN_METHOD(OpCallback) {
case OP_GETATTR: case OP_GETATTR:
case OP_FGETATTR: { case OP_FGETATTR: {
if (info.Length() > 2 && info[2]->IsObject()) bindings_set_stat((struct stat *) b->data, info[2].As<Object>()); if (info.Length() > 2 && info[2]->IsObject()) bindings_set_stat((struct FUSE_STAT *) b->data, info[2].As<Object>());
} }
break; break;
@ -1044,11 +1040,7 @@ static void bindings_dispatch (uv_async_t* handle, int status) {
return; return;
case OP_UTIMENS: { case OP_UTIMENS: {
#ifdef _WIN32
time_t *tv = (time_t *) b->data;
#else
struct timespec *tv = (struct timespec *) b->data; struct timespec *tv = (struct timespec *) b->data;
#endif
Local<Value> tmp[] = {LOCAL_STRING(b->path), bindings_get_date(tv), bindings_get_date(tv + 1), callback}; Local<Value> tmp[] = {LOCAL_STRING(b->path), bindings_get_date(tv), bindings_get_date(tv + 1), callback};
bindings_call_op(b, b->ops_utimens, 4, tmp); bindings_call_op(b, b->ops_utimens, 4, tmp);
} }