-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit cf9234e
Showing
5 changed files
with
339 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"targets": [{ | ||
"target_name": "fuse", | ||
"include_dirs": [ | ||
"<!(node -e \"require('napi-macros')\")", | ||
"<!(node -e \"require('fuse-shared-library/include')\")", | ||
], | ||
"libraries": [ | ||
"<!(node -e \"require('fuse-shared-library/lib')\")", | ||
], | ||
"sources": [ | ||
"fuse-native.c" | ||
] | ||
}, { | ||
"target_name": "postinstall", | ||
"type": "none", | ||
"dependencies": ["fuse"], | ||
"copies": [{ | ||
"destination": "build/Release", | ||
"files": [ "<!(node -e \"require('fuse-shared-library/lib')\")" ], | ||
}] | ||
}] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
#define FUSE_USE_VERSION 29 | ||
|
||
#include "semaphore.h" | ||
|
||
#include <uv.h> | ||
#include <node_api.h> | ||
#include <napi-macros.h> | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
#include <fuse.h> | ||
#include <fuse_opt.h> | ||
#include <fuse_lowlevel.h> | ||
|
||
#include <unistd.h> | ||
#include <sys/wait.h> | ||
#include <pthread.h> | ||
|
||
typedef struct { | ||
napi_env env; | ||
pthread_t thread; | ||
pthread_attr_t attr; | ||
napi_ref ctx; | ||
napi_ref on_op; | ||
struct fuse *fuse; | ||
uv_async_t async; | ||
} fuse_thread_t; | ||
|
||
typedef struct { | ||
int hello; | ||
fuse_thread_t *fuse; | ||
fuse_native_semaphore_t sem; | ||
uv_async_t async; | ||
|
||
// char *reply; | ||
|
||
} fuse_thread_locals_t; | ||
|
||
static pthread_key_t thread_locals_key; | ||
|
||
// static fuse_thread_locals_t * thread_local_map[1024]; | ||
// static int thread_local_map_length = 0; | ||
|
||
// static int get_free_thread_id () { | ||
// for (int i = 0; i < thread_local_map_length; i++) { | ||
// if (thread_local_map[i] == NULL) return i; | ||
// } | ||
|
||
// return thread_local_map_length++; | ||
// } | ||
|
||
|
||
static void fin (napi_env env, void *fin_data, void* fin_hint) { | ||
printf("finaliser is run\n"); | ||
// exit(0); | ||
} | ||
|
||
static void fuse_native_dispatch (uv_async_t* handle, int status) { | ||
fuse_thread_locals_t *l = (fuse_thread_locals_t *) handle->data; | ||
fuse_thread_t *ft = l->fuse; | ||
|
||
napi_env env = ft->env; | ||
napi_handle_scope scope; | ||
|
||
napi_open_handle_scope(env, &scope); | ||
|
||
napi_value ctx; | ||
napi_get_reference_value(env, ft->ctx, &ctx); | ||
|
||
napi_value callback; | ||
napi_get_reference_value(env, ft->on_op, &callback); | ||
|
||
// int ptr = get_free_thread_id() | ||
// thread_local_map[ptr] = l | ||
|
||
napi_value argv[1]; | ||
napi_create_external_buffer(env, sizeof(fuse_thread_locals_t), l, &fin, NULL, &(argv[0])); | ||
|
||
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 1, argv, NULL) | ||
|
||
napi_close_handle_scope(env, scope); | ||
} | ||
|
||
static fuse_thread_locals_t* get_thread_locals () { | ||
void *data = pthread_getspecific(thread_locals_key); | ||
|
||
if (data != NULL) { | ||
return (fuse_thread_locals_t *) data; | ||
} | ||
|
||
fuse_thread_locals_t* l = (fuse_thread_locals_t *) malloc(sizeof(fuse_thread_locals_t)); | ||
|
||
l->hello = 42; | ||
|
||
// TODO: mutex me?? | ||
int err = uv_async_init(uv_default_loop(), &(l->async), (uv_async_cb) fuse_native_dispatch); | ||
|
||
l->async.data = l; | ||
|
||
if (err < 0) { | ||
printf("uv_async failed: %i\n", err); | ||
return NULL; | ||
} | ||
|
||
fuse_native_semaphore_init(&(l->sem)); | ||
pthread_setspecific(thread_locals_key, (void *) l); | ||
|
||
return l; | ||
} | ||
|
||
static void* start_fuse_thread (void *data) { | ||
fuse_thread_t *ft = (fuse_thread_t *) data; | ||
fuse_loop_mt(ft->fuse); | ||
|
||
// printf("her nu\n"); | ||
// fuse_unmount(mnt, ch); | ||
// fuse_session_remove_chan(ch); | ||
// fuse_destroy(fuse); | ||
|
||
return NULL; | ||
} | ||
|
||
static int fuse_native_getattr (const char *path, struct stat *stat) { | ||
printf("hi\n"); | ||
|
||
struct fuse_context *ctx = fuse_get_context(); | ||
fuse_thread_t *ft = (fuse_thread_t *) ctx->private_data; | ||
|
||
fuse_thread_locals_t *l = get_thread_locals(); | ||
|
||
l->fuse = ft; | ||
|
||
// b->op = OP_GETATTR; | ||
// b->path = (char *) path; | ||
// b->data = stat; | ||
|
||
uv_async_send(&(l->async)); | ||
fuse_native_semaphore_wait(&(l->sem)); | ||
|
||
return -1; | ||
} | ||
|
||
NAPI_METHOD(fuse_native_signal) { | ||
NAPI_ARGV(5) | ||
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0); | ||
|
||
fuse_native_semaphore_signal(&(l->sem)); | ||
} | ||
|
||
NAPI_METHOD(fuse_native_mount) { | ||
NAPI_ARGV(5) | ||
|
||
NAPI_ARGV_UTF8(mnt, 1024, 0); | ||
NAPI_ARGV_UTF8(mntopts, 1024, 1); | ||
NAPI_ARGV_BUFFER_CAST(fuse_thread_t *, ft, 2); | ||
napi_create_reference(env, argv[3], 1, &(ft->ctx)); | ||
napi_create_reference(env, argv[4], 1, &(ft->on_op)); | ||
|
||
ft->env = env; | ||
|
||
struct fuse_operations ops = { | ||
.getattr = fuse_native_getattr | ||
}; | ||
|
||
int _argc = 2; | ||
char *_argv[] = { | ||
(char *) "fuse_bindings_dummy", | ||
(char *) mntopts | ||
}; | ||
|
||
struct fuse_args args = FUSE_ARGS_INIT(_argc, _argv); | ||
struct fuse_chan *ch = fuse_mount(mnt, &args); | ||
|
||
if (ch == NULL) { | ||
napi_throw_error(env, "fuse failed", "fuse failed"); | ||
return NULL; | ||
} | ||
|
||
struct fuse *fuse = fuse_new(ch, &args, &ops, sizeof(struct fuse_operations), ft); | ||
|
||
ft->fuse = fuse; | ||
|
||
if (fuse == NULL) { | ||
napi_throw_error(env, "fuse failed", "fuse failed"); | ||
return NULL; | ||
} | ||
|
||
pthread_attr_init(&(ft->attr)); | ||
pthread_create(&(ft->thread), &(ft->attr), start_fuse_thread, ft); | ||
|
||
return NULL; | ||
} | ||
|
||
NAPI_INIT() { | ||
pthread_key_create(&(thread_locals_key), NULL); // TODO: add destructor | ||
|
||
NAPI_EXPORT_FUNCTION(fuse_native_mount) | ||
NAPI_EXPORT_FUNCTION(fuse_native_signal) | ||
NAPI_EXPORT_SIZEOF(fuse_thread_t) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
const binding = require('node-gyp-build')(__dirname) | ||
|
||
console.log(binding) | ||
|
||
class Fuse { | ||
constructor () { | ||
this.fuseThread = Buffer.alloc(binding.sizeof_fuse_thread_t) | ||
} | ||
|
||
mount (mnt) { | ||
binding.fuse_native_mount('mnt', '-odebug', data, this, on_op) | ||
} | ||
} | ||
|
||
const ctx = {} | ||
const data = Buffer.alloc(binding.sizeof_fuse_thread_t) | ||
let buffers = [] | ||
let foo | ||
|
||
binding.fuse_native_mount('mnt', '-odebug', data, ctx, on_op) | ||
|
||
let to = 1 | ||
|
||
setTimeout(function () { | ||
to = 5000 | ||
}, 5000) | ||
|
||
setInterval(() => { | ||
console.log(!!(data && buffers && ctx && on_op)) | ||
gc() | ||
}, 1000) | ||
|
||
function on_op (buf) { | ||
// foo = buf | ||
console.log('on_op is called', buf) | ||
// buffers.push(buf) | ||
|
||
setTimeout(function () { | ||
console.log('in timeout') | ||
binding.fuse_native_signal(buf) | ||
}, to) | ||
} | ||
|
||
// setTimeout(function () { | ||
// foo = null | ||
// console.log('now!') | ||
// }, 5000) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "fuse-native", | ||
"version": "0.0.0", | ||
"description": "Fully maintained fuse bindings for Node that aims to cover the entire FUSE api", | ||
"main": "index.js", | ||
"scripts": { | ||
"install": "node-gyp-build", | ||
"prebuild": "prebuildify -a --strip", | ||
"prebuild-ia32": "prebuildify -a --strip --arch=ia32" | ||
}, | ||
"gypfile": true, | ||
"dependencies": { | ||
"fuse-shared-library": "^1.0.1", | ||
"napi-macros": "^2.0.0", | ||
"node-gyp-build": "^3.2.2" | ||
}, | ||
"devDependencies": {}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/fuse-friends/fuse-native.git" | ||
}, | ||
"author": "Mathias Buus (@mafintosh)", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/fuse-friends/fuse-native/issues" | ||
}, | ||
"homepage": "https://github.com/fuse-friends/fuse-native" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
|
||
#ifdef __APPLE__ | ||
|
||
#include <semaphore.h> | ||
#include <dispatch/dispatch.h> | ||
|
||
typedef dispatch_semaphore_t fuse_native_semaphore_t; | ||
|
||
static int fuse_native_semaphore_init (dispatch_semaphore_t *sem) { | ||
*sem = dispatch_semaphore_create(0); | ||
return *sem == NULL ? -1 : 0; | ||
} | ||
|
||
static void fuse_native_semaphore_wait (dispatch_semaphore_t *sem) { | ||
dispatch_semaphore_wait(*sem, DISPATCH_TIME_FOREVER); | ||
} | ||
|
||
static void fuse_native_semaphore_signal (dispatch_semaphore_t *sem) { | ||
dispatch_semaphore_signal(*sem); | ||
} | ||
|
||
#else | ||
|
||
#include <semaphore.h> | ||
|
||
typedef sem_t fuse_native_semaphore_t; | ||
|
||
static int fuse_native_semaphore_init (sem_t *sem) { | ||
return sem_init(sem, 0, 0); | ||
} | ||
|
||
static void fuse_native_semaphore_wait (sem_t *sem) { | ||
sem_wait(sem); | ||
} | ||
|
||
static void fuse_native_semaphore_signal (sem_t *sem) { | ||
sem_post(sem); | ||
} | ||
|
||
#endif |