mirror of
https://github.com/fuse-friends/fuse-native
synced 2024-10-27 18:34:01 +00:00
working getattr
This commit is contained in:
parent
5a2c2b5d03
commit
a01ebc477d
350
fuse-native.c
350
fuse-native.c
@ -17,25 +17,75 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
static const uint32_t op_init = 0;
|
||||||
|
static const uint32_t op_error = 1;
|
||||||
|
static const uint32_t op_access = 2;
|
||||||
|
static const uint32_t op_statfs = 3;
|
||||||
|
static const uint32_t op_fgetattr = 4;
|
||||||
|
static const uint32_t op_getattr = 5;
|
||||||
|
static const uint32_t op_flush = 6;
|
||||||
|
static const uint32_t op_fsync = 7;
|
||||||
|
static const uint32_t op_fsyncdir = 8;
|
||||||
|
static const uint32_t op_readdir = 9;
|
||||||
|
static const uint32_t op_truncate = 10;
|
||||||
|
static const uint32_t op_ftruncate = 11;
|
||||||
|
static const uint32_t op_utimens = 12;
|
||||||
|
static const uint32_t op_readlink = 13;
|
||||||
|
static const uint32_t op_chown = 14;
|
||||||
|
static const uint32_t op_chmod = 15;
|
||||||
|
static const uint32_t op_mknod = 16;
|
||||||
|
static const uint32_t op_setxattr = 17;
|
||||||
|
static const uint32_t op_getxattr = 18;
|
||||||
|
static const uint32_t op_listxattr = 19;
|
||||||
|
static const uint32_t op_removexattr = 20;
|
||||||
|
static const uint32_t op_open = 21;
|
||||||
|
static const uint32_t op_opendir = 22;
|
||||||
|
static const uint32_t op_read = 23;
|
||||||
|
static const uint32_t op_write = 24;
|
||||||
|
static const uint32_t op_release = 25;
|
||||||
|
static const uint32_t op_releasedir = 26;
|
||||||
|
static const uint32_t op_create = 27;
|
||||||
|
static const uint32_t op_unlink = 28;
|
||||||
|
static const uint32_t op_rename = 29;
|
||||||
|
static const uint32_t op_link = 30;
|
||||||
|
static const uint32_t op_symlink = 31;
|
||||||
|
static const uint32_t op_mkdir = 32;
|
||||||
|
static const uint32_t op_rmdir = 33;
|
||||||
|
static const uint32_t op_destroy = 34;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
napi_env env;
|
napi_env env;
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
napi_ref ctx;
|
napi_ref ctx;
|
||||||
napi_ref on_op;
|
|
||||||
|
// Operation handlers
|
||||||
|
napi_ref on_path_op;
|
||||||
|
napi_ref on_stat_op;
|
||||||
|
napi_ref on_statfs_op;
|
||||||
|
napi_ref on_buffer_op;
|
||||||
|
napi_ref on_readdir;
|
||||||
|
napi_ref on_symlink;
|
||||||
|
|
||||||
struct fuse *fuse;
|
struct fuse *fuse;
|
||||||
uv_async_t async;
|
uv_async_t async;
|
||||||
} fuse_thread_t;
|
} fuse_thread_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t ints[32];
|
// Opcode
|
||||||
|
uint32_t op;
|
||||||
|
|
||||||
|
// Payloads
|
||||||
|
struct stat *stat;
|
||||||
|
struct statvfs *statvfs;
|
||||||
|
const char *path;
|
||||||
int32_t res;
|
int32_t res;
|
||||||
|
|
||||||
|
// Internal bookkeeping
|
||||||
fuse_thread_t *fuse;
|
fuse_thread_t *fuse;
|
||||||
fuse_native_semaphore_t sem;
|
fuse_native_semaphore_t sem;
|
||||||
uv_async_t async;
|
uv_async_t async;
|
||||||
|
|
||||||
// char *reply;
|
|
||||||
|
|
||||||
} fuse_thread_locals_t;
|
} fuse_thread_locals_t;
|
||||||
|
|
||||||
static pthread_key_t thread_locals_key;
|
static pthread_key_t thread_locals_key;
|
||||||
@ -45,10 +95,7 @@ static void fin (napi_env env, void *fin_data, void* fin_hint) {
|
|||||||
// exit(0);
|
// exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fuse_native_dispatch (uv_async_t* handle, int status) {
|
static void fuse_native_dispatch_stat(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
|
||||||
fuse_thread_locals_t *l = (fuse_thread_locals_t *) handle->data;
|
|
||||||
fuse_thread_t *ft = l->fuse;
|
|
||||||
|
|
||||||
napi_env env = ft->env;
|
napi_env env = ft->env;
|
||||||
napi_handle_scope scope;
|
napi_handle_scope scope;
|
||||||
|
|
||||||
@ -58,19 +105,75 @@ static void fuse_native_dispatch (uv_async_t* handle, int status) {
|
|||||||
napi_get_reference_value(env, ft->ctx, &ctx);
|
napi_get_reference_value(env, ft->ctx, &ctx);
|
||||||
|
|
||||||
napi_value callback;
|
napi_value callback;
|
||||||
napi_get_reference_value(env, ft->on_op, &callback);
|
napi_get_reference_value(env, ft->on_stat_op, &callback);
|
||||||
|
|
||||||
// int ptr = get_free_thread_id()
|
napi_value argv[3];
|
||||||
// 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_create_external_buffer(env, sizeof(fuse_thread_locals_t), l, &fin, NULL, &(argv[0]));
|
||||||
|
napi_create_uint32(env, l->op, &(argv[1]));
|
||||||
|
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
||||||
|
|
||||||
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 1, argv, NULL)
|
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 3, argv, NULL)
|
||||||
|
|
||||||
napi_close_handle_scope(env, scope);
|
napi_close_handle_scope(env, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fuse_native_dispatch_path(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
|
||||||
|
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_path_op, &callback);
|
||||||
|
|
||||||
|
napi_value argv[3];
|
||||||
|
|
||||||
|
napi_create_external_buffer(env, sizeof(fuse_thread_locals_t), l, &fin, NULL, &(argv[0]));
|
||||||
|
napi_create_uint32(env, l->op, &(argv[1]));
|
||||||
|
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
||||||
|
|
||||||
|
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 3, argv, NULL)
|
||||||
|
|
||||||
|
napi_close_handle_scope(env, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fuse_native_dispatch_buffer(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
|
||||||
|
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_buffer_op, &callback);
|
||||||
|
|
||||||
|
napi_value argv[4];
|
||||||
|
|
||||||
|
napi_create_external_buffer(env, sizeof(fuse_thread_locals_t), l, &fin, NULL, &(argv[0]));
|
||||||
|
napi_create_uint32(env, l->op, &(argv[1]));
|
||||||
|
napi_create_string_utf8(env, l->path, NAPI_AUTO_LENGTH, &(argv[2]));
|
||||||
|
|
||||||
|
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 4, argv, NULL)
|
||||||
|
|
||||||
|
napi_close_handle_scope(env, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
switch (l->op) {
|
||||||
|
case (op_getattr):
|
||||||
|
return fuse_native_dispatch_stat(handle, status, l, ft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static fuse_thread_locals_t* get_thread_locals () {
|
static fuse_thread_locals_t* get_thread_locals () {
|
||||||
void *data = pthread_getspecific(thread_locals_key);
|
void *data = pthread_getspecific(thread_locals_key);
|
||||||
|
|
||||||
@ -109,31 +212,140 @@ static void* start_fuse_thread (void *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int fuse_native_getattr (const char *path, struct stat *stat) {
|
static int fuse_native_getattr (const char *path, struct stat *stat) {
|
||||||
printf("hi\n");
|
|
||||||
|
|
||||||
struct fuse_context *ctx = fuse_get_context();
|
struct fuse_context *ctx = fuse_get_context();
|
||||||
fuse_thread_t *ft = (fuse_thread_t *) ctx->private_data;
|
fuse_thread_t *ft = (fuse_thread_t *) ctx->private_data;
|
||||||
|
|
||||||
fuse_thread_locals_t *l = get_thread_locals();
|
fuse_thread_locals_t *l = get_thread_locals();
|
||||||
|
|
||||||
l->fuse = ft;
|
l->fuse = ft;
|
||||||
|
l->stat = stat;
|
||||||
// b->op = OP_GETATTR;
|
l->op = op_getattr;
|
||||||
// b->path = (char *) path;
|
l->path = path;
|
||||||
// b->data = stat;
|
|
||||||
|
|
||||||
uv_async_send(&(l->async));
|
uv_async_send(&(l->async));
|
||||||
fuse_native_semaphore_wait(&(l->sem));
|
fuse_native_semaphore_wait(&(l->sem));
|
||||||
|
|
||||||
printf("l->res: %i\n", l->res);
|
return l->res;
|
||||||
printf("l->ints[0]: %u\n", l->ints[0]);
|
}
|
||||||
printf("l->ints[1]: %u\n", l->ints[1]);
|
|
||||||
printf("l->ints[2]: %u\n", l->ints[2]);
|
static int fuse_native_statfs (struct statvfs *statvfs) {
|
||||||
|
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;
|
||||||
|
l->statvfs = statvfs;
|
||||||
|
l->op = op_statfs;
|
||||||
|
|
||||||
|
uv_async_send(&(l->async));
|
||||||
|
fuse_native_semaphore_wait(&(l->sem));
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NAPI_METHOD(fuse_native_signal) {
|
NAPI_METHOD(fuse_native_signal_path) {
|
||||||
|
NAPI_ARGV(3)
|
||||||
|
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
||||||
|
NAPI_ARGV_INT32(res, 1)
|
||||||
|
|
||||||
|
l->res = res;
|
||||||
|
fuse_native_semaphore_signal(&(l->sem));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void to_timespec (struct timespec* ts, uint32_t ms) {
|
||||||
|
ts->tv_sec = ms / 1000;
|
||||||
|
ts->tv_nsec = (ms % 1000) * 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
NAPI_METHOD(fuse_native_signal_stat) {
|
||||||
|
NAPI_ARGV(15)
|
||||||
|
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
||||||
|
|
||||||
|
NAPI_ARGV_INT32(res, 1)
|
||||||
|
NAPI_ARGV_INT32(mode, 2)
|
||||||
|
NAPI_ARGV_INT32(uid, 3)
|
||||||
|
NAPI_ARGV_INT32(gid, 4)
|
||||||
|
NAPI_ARGV_INT32(size, 5)
|
||||||
|
NAPI_ARGV_INT32(dev, 6)
|
||||||
|
NAPI_ARGV_INT32(nlink, 7)
|
||||||
|
NAPI_ARGV_INT32(ino, 8)
|
||||||
|
NAPI_ARGV_INT32(rdev, 9)
|
||||||
|
NAPI_ARGV_INT32(blksize, 10)
|
||||||
|
NAPI_ARGV_INT32(blocks, 11)
|
||||||
|
NAPI_ARGV_INT32(atim, 12)
|
||||||
|
NAPI_ARGV_INT32(mtim, 13)
|
||||||
|
NAPI_ARGV_INT32(ctim, 14)
|
||||||
|
|
||||||
|
l->stat->st_mode = mode;
|
||||||
|
l->stat->st_uid = uid;
|
||||||
|
l->stat->st_gid = gid;
|
||||||
|
l->stat->st_size = size;
|
||||||
|
l->stat->st_dev = dev;
|
||||||
|
l->stat->st_nlink = nlink;
|
||||||
|
l->stat->st_ino = ino;
|
||||||
|
l->stat->st_rdev = rdev;
|
||||||
|
l->stat->st_blksize = blksize;
|
||||||
|
l->stat->st_blocks = blocks;
|
||||||
|
to_timespec(&l->stat->st_atim, atim);
|
||||||
|
to_timespec(&l->stat->st_mtim, mtim);
|
||||||
|
to_timespec(&l->stat->st_ctim, ctim);
|
||||||
|
|
||||||
|
l->res = res;
|
||||||
|
fuse_native_semaphore_signal(&(l->sem));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NAPI_METHOD(fuse_native_signal_statfs) {
|
||||||
|
NAPI_ARGV(15)
|
||||||
|
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
||||||
|
NAPI_ARGV_INT32(res, 1)
|
||||||
|
|
||||||
|
NAPI_ARGV_INT32(bsize, 2)
|
||||||
|
NAPI_ARGV_INT32(frsize, 3)
|
||||||
|
NAPI_ARGV_INT32(blocks, 4)
|
||||||
|
NAPI_ARGV_INT32(bfree, 5)
|
||||||
|
NAPI_ARGV_INT32(bavail, 6)
|
||||||
|
NAPI_ARGV_INT32(files, 7)
|
||||||
|
NAPI_ARGV_INT32(ffree, 8)
|
||||||
|
NAPI_ARGV_INT32(favail, 9)
|
||||||
|
NAPI_ARGV_INT32(fsid, 10)
|
||||||
|
NAPI_ARGV_INT32(flag, 11)
|
||||||
|
NAPI_ARGV_INT32(namemax, 12)
|
||||||
|
|
||||||
|
l->statvfs->f_bsize = bsize;
|
||||||
|
l->statvfs->f_frsize = frsize;
|
||||||
|
l->statvfs->f_blocks = blocks;
|
||||||
|
l->statvfs->f_bfree = bfree;
|
||||||
|
l->statvfs->f_bavail = bavail;
|
||||||
|
l->statvfs->f_files = files;
|
||||||
|
l->statvfs->f_ffree = ffree;
|
||||||
|
l->statvfs->f_favail = favail;
|
||||||
|
l->statvfs->f_fsid = fsid;
|
||||||
|
l->statvfs->f_flag = flag;
|
||||||
|
l->statvfs->f_namemax = namemax;
|
||||||
|
|
||||||
|
l->res = res;
|
||||||
|
fuse_native_semaphore_signal(&(l->sem));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NAPI_METHOD(fuse_native_signal_buffer) {
|
||||||
|
NAPI_ARGV(2)
|
||||||
|
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
||||||
|
NAPI_ARGV_INT32(res, 1)
|
||||||
|
|
||||||
|
l->res = res;
|
||||||
|
fuse_native_semaphore_signal(&(l->sem));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NAPI_METHOD(fuse_native_signal_readdir) {
|
||||||
NAPI_ARGV(2)
|
NAPI_ARGV(2)
|
||||||
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
||||||
NAPI_ARGV_INT32(res, 1)
|
NAPI_ARGV_INT32(res, 1)
|
||||||
@ -145,18 +357,60 @@ NAPI_METHOD(fuse_native_signal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NAPI_METHOD(fuse_native_mount) {
|
NAPI_METHOD(fuse_native_mount) {
|
||||||
NAPI_ARGV(5)
|
NAPI_ARGV(10)
|
||||||
|
|
||||||
NAPI_ARGV_UTF8(mnt, 1024, 0);
|
NAPI_ARGV_UTF8(mnt, 1024, 0);
|
||||||
NAPI_ARGV_UTF8(mntopts, 1024, 1);
|
NAPI_ARGV_UTF8(mntopts, 1024, 1);
|
||||||
NAPI_ARGV_BUFFER_CAST(fuse_thread_t *, ft, 2);
|
NAPI_ARGV_BUFFER_CAST(fuse_thread_t *, ft, 2);
|
||||||
napi_create_reference(env, argv[3], 1, &(ft->ctx));
|
napi_create_reference(env, argv[3], 1, &(ft->ctx));
|
||||||
napi_create_reference(env, argv[4], 1, &(ft->on_op));
|
|
||||||
|
napi_create_reference(env, argv[4], 1, &(ft->on_path_op));
|
||||||
|
napi_create_reference(env, argv[5], 1, &(ft->on_statfs_op));
|
||||||
|
napi_create_reference(env, argv[6], 1, &(ft->on_stat_op));
|
||||||
|
napi_create_reference(env, argv[7], 1, &(ft->on_buffer_op));
|
||||||
|
napi_create_reference(env, argv[8], 1, &(ft->on_readdir));
|
||||||
|
napi_create_reference(env, argv[9], 1, &(ft->on_symlink));
|
||||||
|
|
||||||
ft->env = env;
|
ft->env = env;
|
||||||
|
|
||||||
struct fuse_operations ops = {
|
struct fuse_operations ops = {
|
||||||
.getattr = fuse_native_getattr
|
.getattr = fuse_native_getattr,
|
||||||
|
.statfs = fuse_native_statfs,
|
||||||
|
/*
|
||||||
|
.init = fuse_native_init,
|
||||||
|
.error = fuse_native_error,
|
||||||
|
.access = fuse_native_access,
|
||||||
|
.fgetattr = fuse_native_fgetattr,
|
||||||
|
.flush = fuse_native_flush,
|
||||||
|
.fsync = fuse_native_fsync,
|
||||||
|
.fsyncdir = fuse_native_fsyncdir,
|
||||||
|
.readdir = fuse_native_readdir,
|
||||||
|
.truncate = fuse_native_truncate,
|
||||||
|
.ftruncate = fuse_native_ftruncate,
|
||||||
|
.utimens = fuse_native_utimens,
|
||||||
|
.readlink = fuse_native_readlink,
|
||||||
|
.chown = fuse_native_chown,
|
||||||
|
.chmod = fuse_native_chmod,
|
||||||
|
.mknod = fuse_native_mknod,
|
||||||
|
.setxattr = fuse_native_setxattr,
|
||||||
|
.getxattr = fuse_native_getxattr,
|
||||||
|
.listxattr = fuse_native_listxattr,
|
||||||
|
.removexattr = fuse_native_removexattr,
|
||||||
|
.open = fuse_native_open,
|
||||||
|
.opendir = fuse_native_opendir,
|
||||||
|
.read = fuse_native_read,
|
||||||
|
.write = fuse_native_write,
|
||||||
|
.release = fuse_native_release,
|
||||||
|
.releasedir = fuse_native_releasedir,
|
||||||
|
.create = fuse_native_create,
|
||||||
|
.unlink = fuse_native_unlink,
|
||||||
|
.rename = fuse_native_rename,
|
||||||
|
.link = fuse_native_link,
|
||||||
|
.symlink = fuse_native_symlink,
|
||||||
|
.mkdir = fuse_native_mkdir,
|
||||||
|
.rmdir = fuse_native_rmdir,
|
||||||
|
.destroy = fuse_native_destroy,
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
int _argc = 2;
|
int _argc = 2;
|
||||||
@ -192,6 +446,46 @@ NAPI_INIT() {
|
|||||||
pthread_key_create(&(thread_locals_key), NULL); // TODO: add destructor
|
pthread_key_create(&(thread_locals_key), NULL); // TODO: add destructor
|
||||||
|
|
||||||
NAPI_EXPORT_FUNCTION(fuse_native_mount)
|
NAPI_EXPORT_FUNCTION(fuse_native_mount)
|
||||||
NAPI_EXPORT_FUNCTION(fuse_native_signal)
|
NAPI_EXPORT_FUNCTION(fuse_native_signal_path)
|
||||||
|
NAPI_EXPORT_FUNCTION(fuse_native_signal_stat)
|
||||||
|
NAPI_EXPORT_FUNCTION(fuse_native_signal_statfs)
|
||||||
|
NAPI_EXPORT_FUNCTION(fuse_native_signal_buffer)
|
||||||
|
NAPI_EXPORT_FUNCTION(fuse_native_signal_readdir)
|
||||||
NAPI_EXPORT_SIZEOF(fuse_thread_t)
|
NAPI_EXPORT_SIZEOF(fuse_thread_t)
|
||||||
|
NAPI_EXPORT_UINT32(op_getattr)
|
||||||
|
NAPI_EXPORT_UINT32(op_init)
|
||||||
|
NAPI_EXPORT_UINT32(op_error)
|
||||||
|
NAPI_EXPORT_UINT32(op_access)
|
||||||
|
NAPI_EXPORT_UINT32(op_statfs)
|
||||||
|
NAPI_EXPORT_UINT32(op_fgetattr)
|
||||||
|
NAPI_EXPORT_UINT32(op_getattr)
|
||||||
|
NAPI_EXPORT_UINT32(op_flush)
|
||||||
|
NAPI_EXPORT_UINT32(op_fsync)
|
||||||
|
NAPI_EXPORT_UINT32(op_fsyncdir)
|
||||||
|
NAPI_EXPORT_UINT32(op_readdir)
|
||||||
|
NAPI_EXPORT_UINT32(op_truncate)
|
||||||
|
NAPI_EXPORT_UINT32(op_ftruncate)
|
||||||
|
NAPI_EXPORT_UINT32(op_utimens)
|
||||||
|
NAPI_EXPORT_UINT32(op_readlink)
|
||||||
|
NAPI_EXPORT_UINT32(op_chown)
|
||||||
|
NAPI_EXPORT_UINT32(op_chmod)
|
||||||
|
NAPI_EXPORT_UINT32(op_mknod)
|
||||||
|
NAPI_EXPORT_UINT32(op_setxattr)
|
||||||
|
NAPI_EXPORT_UINT32(op_getxattr)
|
||||||
|
NAPI_EXPORT_UINT32(op_listxattr)
|
||||||
|
NAPI_EXPORT_UINT32(op_removexattr)
|
||||||
|
NAPI_EXPORT_UINT32(op_open)
|
||||||
|
NAPI_EXPORT_UINT32(op_opendir)
|
||||||
|
NAPI_EXPORT_UINT32(op_read)
|
||||||
|
NAPI_EXPORT_UINT32(op_write)
|
||||||
|
NAPI_EXPORT_UINT32(op_release)
|
||||||
|
NAPI_EXPORT_UINT32(op_releasedir)
|
||||||
|
NAPI_EXPORT_UINT32(op_create)
|
||||||
|
NAPI_EXPORT_UINT32(op_unlink)
|
||||||
|
NAPI_EXPORT_UINT32(op_rename)
|
||||||
|
NAPI_EXPORT_UINT32(op_link)
|
||||||
|
NAPI_EXPORT_UINT32(op_symlink)
|
||||||
|
NAPI_EXPORT_UINT32(op_mkdir)
|
||||||
|
NAPI_EXPORT_UINT32(op_rmdir)
|
||||||
|
NAPI_EXPORT_UINT32(op_destroy)
|
||||||
}
|
}
|
||||||
|
178
index.js
178
index.js
@ -1,35 +1,185 @@
|
|||||||
const binding = require('node-gyp-build')(__dirname)
|
const binding = require('node-gyp-build')(__dirname)
|
||||||
|
|
||||||
console.log(binding)
|
const Opcodes = new Map([
|
||||||
|
[ 'init', 0 ],
|
||||||
|
[ 'error', 1 ],
|
||||||
|
[ 'access', 2 ],
|
||||||
|
[ 'statfs', 3 ],
|
||||||
|
[ 'fgetattr', 4 ],
|
||||||
|
[ 'getattr', 5 ],
|
||||||
|
[ 'flush', 6 ],
|
||||||
|
[ 'fsync', 7 ],
|
||||||
|
[ 'fsyncdir', 8 ],
|
||||||
|
[ 'readdir', 9 ],
|
||||||
|
[ 'truncate', 10 ],
|
||||||
|
[ 'ftruncate', 11 ],
|
||||||
|
[ 'utimens', 12 ],
|
||||||
|
[ 'readlink', 13 ],
|
||||||
|
[ 'chown', 14 ],
|
||||||
|
[ 'chmod', 15 ],
|
||||||
|
[ 'mknod', 16 ],
|
||||||
|
[ 'setxattr', 17 ],
|
||||||
|
[ 'getxattr', 18 ],
|
||||||
|
[ 'listxattr', 19 ],
|
||||||
|
[ 'removexattr', 20 ],
|
||||||
|
[ 'open', 21 ],
|
||||||
|
[ 'opendir', 22 ],
|
||||||
|
[ 'read', 23 ],
|
||||||
|
[ 'write', 24 ],
|
||||||
|
[ 'release', 25 ],
|
||||||
|
[ 'releasedir', 26 ],
|
||||||
|
[ 'create', 27 ],
|
||||||
|
[ 'unlink', 28 ],
|
||||||
|
[ 'rename', 29 ],
|
||||||
|
[ 'link', 30 ],
|
||||||
|
[ 'symlink', 31 ],
|
||||||
|
[ 'mkdir', 32 ],
|
||||||
|
[ 'rmdir', 33 ],
|
||||||
|
[ 'destroy', 34 ]
|
||||||
|
])
|
||||||
|
|
||||||
class Fuse {
|
class Fuse {
|
||||||
constructor () {
|
constructor (mnt, ops, opts = {}) {
|
||||||
|
this.opts = opts
|
||||||
|
this.ops = ops
|
||||||
|
this.mnt = mnt
|
||||||
|
|
||||||
this._thread = Buffer.alloc(binding.sizeof_fuse_thread_t)
|
this._thread = Buffer.alloc(binding.sizeof_fuse_thread_t)
|
||||||
|
|
||||||
|
const implemented = []
|
||||||
|
if (ops) {
|
||||||
|
for (const [name, code] of Opcodes) {
|
||||||
|
if (ops[name]) implemented.push(code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._implemented = new Set(implemented)
|
||||||
|
|
||||||
|
// Used to determine if the user-defined callback needs to be nextTick'd.
|
||||||
|
this._sync = true
|
||||||
}
|
}
|
||||||
|
|
||||||
mount (mnt) {
|
_signal (signalFunc, args) {
|
||||||
binding.fuse_native_mount(mnt, '-odebug', this._thread, this, this.onop)
|
/*
|
||||||
|
if (this._sync) process.nextTick(() => signalFunc.apply(null, args))
|
||||||
|
else signalFunc.apply(null, args)
|
||||||
|
*/
|
||||||
|
process.nextTick(() => signalFunc.apply(null, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
onop (handle) {
|
mount () {
|
||||||
const ints = new Uint32Array(handle.buffer, handle.byteOffset, 32)
|
binding.fuse_native_mount(this.mnt, '-odebug', this._thread, this,
|
||||||
|
this.on_path_op, this.on_statfs_op, this.on_stat_op,
|
||||||
|
this.on_buffer_op, this.on_readdir, this.on_symlink)
|
||||||
|
}
|
||||||
|
|
||||||
ints[0] = 1
|
unmount () {
|
||||||
ints[1] = 42
|
binding.fuse_native_unmount(this.mnt)
|
||||||
ints[2] = 10
|
}
|
||||||
|
|
||||||
process.nextTick(function () {
|
on_symlink (handle, op, path, target) {
|
||||||
binding.fuse_native_signal(handle, -1)
|
const signalFunc = binding.fuse_native_signal_path.bind(binding)
|
||||||
|
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1])
|
||||||
|
}
|
||||||
|
|
||||||
|
on_readdir (handle, op, path) {
|
||||||
|
const signalFunc = binding.fuse_native_signal_readdir.bind(binding)
|
||||||
|
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1])
|
||||||
|
}
|
||||||
|
|
||||||
|
on_buffer_op (handle, op, path, buf) {
|
||||||
|
const signalFunc = binding.fuse_native_signal_buffer.bind(binding)
|
||||||
|
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1])
|
||||||
|
}
|
||||||
|
|
||||||
|
on_statfs_op (handle, op, path) {
|
||||||
|
const signalFunc = binding.fuse_native_signal_statfs.bind(binding)
|
||||||
|
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1])
|
||||||
|
|
||||||
|
this.ops.statfs((err, statfs) => {
|
||||||
|
const arr = getStatfsArray(statfs)
|
||||||
|
return this._signal(signalFunc, [handle, err, ...arr])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on_stat_op (handle, op, path) {
|
||||||
|
const signalFunc = binding.fuse_native_signal_stat.bind(binding)
|
||||||
|
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1, ...getStatArray()])
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case (binding.op_getattr):
|
||||||
|
this.ops.getattr(path, (err, stat) => {
|
||||||
|
const arrs = getStatArray(stat)
|
||||||
|
return this._signal(signalFunc, [handle, err, ...arrs])
|
||||||
|
})
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
return this._signal(signalFunc, [handle, -1, ...getStatArray()])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const f = new Fuse()
|
on_path_op (handle, op, path) {
|
||||||
|
const signalFunc = binding.fuse_native_signal_path.bind(binding)
|
||||||
|
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1])
|
||||||
|
|
||||||
f.mount('mnt')
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatfsArray (statfs) {
|
||||||
|
const ints = Array(11)
|
||||||
|
|
||||||
|
ints[0] = (statfs && statfs.bsize) || 0
|
||||||
|
ints[1] = (statfs && statfs.frsize) || 0
|
||||||
|
ints[2] = (statfs && statfs.blocks) || 0
|
||||||
|
ints[3] = (statfs && statfs.bfree) || 0
|
||||||
|
ints[4] = (statfs && statfs.bavail) || 0
|
||||||
|
ints[5] = (statfs && statfs.files) || 0
|
||||||
|
ints[6] = (statfs && statfs.ffree) || 0
|
||||||
|
ints[7] = (statfs && statfs.favail) || 0
|
||||||
|
ints[8] = (statfs && statfs.fsid) || 0
|
||||||
|
ints[9] = (statfs && statfs.flag) || 0
|
||||||
|
ints[10] = (statfs && statfs.namemax) || 0
|
||||||
|
|
||||||
|
return ints
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatArray (stat) {
|
||||||
|
const ints = Array(13)
|
||||||
|
|
||||||
|
ints[0] = (stat && stat.mode) || 0
|
||||||
|
ints[1] = (stat && stat.uid) || 0
|
||||||
|
ints[2] = (stat && stat.gid) || 0
|
||||||
|
ints[3] = (stat && stat.size) || 0
|
||||||
|
ints[4] = (stat && stat.dev) || 0
|
||||||
|
ints[5] = (stat && stat.nlink) || 1
|
||||||
|
ints[6] = (stat && stat.ino) || 0
|
||||||
|
ints[7] = (stat && stat.rdev) || 0
|
||||||
|
ints[8] = (stat && stat.blksize) || 0
|
||||||
|
ints[9] = (stat && stat.blocks) || 0
|
||||||
|
ints[10] = (stat && stat.atim) || Date.now()
|
||||||
|
ints[11] = (stat && stat.mtim) || Date.now()
|
||||||
|
ints[12] = (stat && stat.ctim) || Date.now()
|
||||||
|
|
||||||
|
return ints
|
||||||
|
}
|
||||||
|
|
||||||
|
const f = new Fuse('mnt', {
|
||||||
|
getattr: (path, cb) => {
|
||||||
|
return cb(0, {
|
||||||
|
mtime: new Date(),
|
||||||
|
atime: new Date(),
|
||||||
|
ctime: new Date(),
|
||||||
|
nlink: 1,
|
||||||
|
size: 100,
|
||||||
|
mode: 16877,
|
||||||
|
uid: process.getuid ? process.getuid() : 0,
|
||||||
|
gid: process.getgid ? process.getgid() : 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
f.mount()
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
console.log(!!(f))
|
|
||||||
if (global.gc) gc()
|
if (global.gc) gc()
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user