1
0
mirror of https://github.com/fuse-friends/fuse-native synced 2024-10-27 18:34:01 +00:00
fuse-friends_fuse-native/fuse-native.c

775 lines
21 KiB
C
Raw Normal View History

2019-07-24 14:52:17 +00:00
#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>
2019-07-30 16:58:39 +00:00
2019-07-24 14:52:17 +00:00
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
2019-07-29 14:44:54 +00:00
#define FUSE_NATIVE_CALLBACK(fn, blk) \
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, fn, &callback); \
blk \
napi_close_handle_scope(env, scope);
2019-07-30 16:58:39 +00:00
#define FUSE_NATIVE_HANDLER(blk) \
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(); \
blk \
uv_async_send(&(l->async)); \
fuse_native_semaphore_wait(&(l->sem)); \
return l->res;
2019-07-29 11:57:46 +00:00
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;
2019-07-24 14:52:17 +00:00
typedef struct {
napi_env env;
pthread_t thread;
pthread_attr_t attr;
napi_ref ctx;
2019-07-29 11:57:46 +00:00
// Operation handlers
napi_ref on_path_op;
napi_ref on_stat_op;
napi_ref on_buffer_op;
2019-07-30 16:58:39 +00:00
napi_ref on_xattr_op;
2019-07-29 14:44:54 +00:00
napi_ref on_statfs;
2019-07-29 11:57:46 +00:00
napi_ref on_readdir;
napi_ref on_symlink;
2019-07-24 14:52:17 +00:00
struct fuse *fuse;
uv_async_t async;
} fuse_thread_t;
typedef struct {
2019-07-29 11:57:46 +00:00
// Opcode
uint32_t op;
// Payloads
const char *path;
2019-07-30 16:58:39 +00:00
struct fuse_file_info *info;
2019-07-29 14:44:54 +00:00
void *buf;
2019-07-30 16:58:39 +00:00
off_t offset;
size_t len;
mode_t mode;
int32_t res;
2019-07-30 16:58:39 +00:00
uint32_t atim[2];
uint32_t mtim[2];
// Extended attributes
const char *name;
const char *value;
char *list;
size_t size;
uint32_t position;
int flags;
2019-07-29 11:57:46 +00:00
2019-07-29 14:44:54 +00:00
// Stat + Statfs
struct stat *stat;
struct statvfs *statvfs;
// Readdir
fuse_fill_dir_t readdir_filler;
2019-07-29 11:57:46 +00:00
// Internal bookkeeping
2019-07-24 14:52:17 +00:00
fuse_thread_t *fuse;
fuse_native_semaphore_t sem;
uv_async_t async;
} fuse_thread_locals_t;
static pthread_key_t thread_locals_key;
2019-07-30 16:58:39 +00:00
// Helpers
// TODO: Extract into a separate file.
2019-07-24 14:52:17 +00:00
static void fin (napi_env env, void *fin_data, void* fin_hint) {
printf("finaliser is run\n");
// exit(0);
}
2019-07-30 16:58:39 +00:00
static void to_timespec (struct timespec* ts, uint32_t* int_ptr) {
long unsigned int ms = *int_ptr + (*(int_ptr + 1) * 4294967296);
ts->tv_sec = ms / 1000;
ts->tv_nsec = (ms % 1000) * 1000000;
}
static void from_timespec(const struct timespec* ts, uint32_t* int_ptr) {
long unsigned int ms = (ts->tv_sec * 1000) + (ts->tv_nsec / 1000000);
*int_ptr = ms % 4294967296;
*(int_ptr + 1) = (ms - *int_ptr) / 4294967296;
}
static void populate_stat (uint32_t *ints, struct stat* stat) {
stat->st_mode = *ints++;
stat->st_uid = *ints++;
stat->st_gid = *ints++;
stat->st_size = *ints++;
stat->st_dev = *ints++;
stat->st_nlink = *ints++;
stat->st_ino = *ints++;
stat->st_rdev = *ints++;
stat->st_blksize = *ints++;
stat->st_blocks = *ints++;
to_timespec(&stat->st_atim, ints);
to_timespec(&stat->st_mtim, ints + 2);
to_timespec(&stat->st_ctim, ints + 4);
}
static void populate_statvfs (uint32_t *ints, struct statvfs* statvfs) {
statvfs->f_bsize = *ints++;
statvfs->f_frsize = *ints++;
statvfs->f_blocks = *ints++;
statvfs->f_bfree = *ints++;
statvfs->f_bavail = *ints++;
statvfs->f_files = *ints++;
statvfs->f_ffree = *ints++;
statvfs->f_favail = *ints++;
statvfs->f_fsid = *ints++;
statvfs->f_flag = *ints++;
statvfs->f_namemax = *ints++;
}
// Dispatchers
static void fuse_native_dispatch_statfs(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
FUSE_NATIVE_CALLBACK(ft->on_statfs, {
napi_value argv[2];
napi_create_external_buffer(env, sizeof(fuse_thread_locals_t), l, &fin, NULL, &(argv[0]));
napi_create_uint32(env, l->op, &(argv[1]));
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 2, argv, NULL)
})
}
2019-07-29 11:57:46 +00:00
2019-07-29 14:44:54 +00:00
static void fuse_native_dispatch_stat(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
FUSE_NATIVE_CALLBACK(ft->on_stat_op, {
2019-07-30 16:58:39 +00:00
napi_value argv[4];
2019-07-29 11:57:46 +00:00
2019-07-29 14:44:54 +00:00
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]));
2019-07-30 16:58:39 +00:00
if (l->info != NULL) {
napi_create_uint32(env, l->info->fh, &(argv[3]));
} else {
napi_create_uint32(env, 0, &(argv[3]));
}
2019-07-29 11:57:46 +00:00
2019-07-30 16:58:39 +00:00
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 4, argv, NULL)
2019-07-29 14:44:54 +00:00
})
2019-07-29 11:57:46 +00:00
}
static void fuse_native_dispatch_path(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
2019-07-29 14:44:54 +00:00
FUSE_NATIVE_CALLBACK(ft->on_path_op, {
2019-07-30 16:58:39 +00:00
napi_value argv[7];
2019-07-29 11:57:46 +00:00
2019-07-29 14:44:54 +00:00
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]));
2019-07-30 16:58:39 +00:00
napi_create_uint32(env, l->mode, &(argv[3]));
if (l->info != NULL) {
napi_create_uint32(env, l->info->fh, &(argv[4]));
} else {
napi_create_uint32(env, 0, &(argv[4]));
}
if (l->atim != NULL) {
napi_create_external_arraybuffer(env, l->atim, 2 * sizeof(uint32_t), &fin, NULL, &argv[5]);
napi_create_external_arraybuffer(env, l->mtim, 2 * sizeof(uint32_t), &fin, NULL, &argv[6]);
} else {
napi_create_external_arraybuffer(env, NULL, 0, &fin, NULL, &argv[5]);
napi_create_external_arraybuffer(env, NULL, 0, &fin, NULL, &argv[6]);
}
2019-07-29 11:57:46 +00:00
2019-07-30 16:58:39 +00:00
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 7, argv, NULL)
2019-07-29 14:44:54 +00:00
})
}
2019-07-29 11:57:46 +00:00
2019-07-29 14:44:54 +00:00
static void fuse_native_dispatch_readdir(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
FUSE_NATIVE_CALLBACK(ft->on_readdir, {
napi_value argv[3];
2019-07-29 11:57:46 +00:00
2019-07-29 14:44:54 +00:00
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]));
2019-07-24 14:52:17 +00:00
2019-07-29 14:44:54 +00:00
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 3, argv, NULL)
})
2019-07-29 11:57:46 +00:00
}
static void fuse_native_dispatch_buffer(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
2019-07-29 14:44:54 +00:00
FUSE_NATIVE_CALLBACK(ft->on_buffer_op, {
2019-07-30 16:58:39 +00:00
napi_value argv[7];
2019-07-24 14:52:17 +00:00
2019-07-29 14:44:54 +00:00
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]));
2019-07-30 16:58:39 +00:00
napi_create_uint32(env, l->info->fh, &(argv[3]));
napi_create_external_buffer(env, l->len, l->buf, &fin, NULL, &(argv[4]));
napi_create_uint32(env, l->len, &(argv[5]));
napi_create_uint32(env, l->offset, &(argv[6]));
2019-07-24 14:52:17 +00:00
2019-07-29 14:44:54 +00:00
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 3, argv, NULL)
})
2019-07-24 14:52:17 +00:00
}
2019-07-30 16:58:39 +00:00
static void fuse_native_dispatch_xattr(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
FUSE_NATIVE_CALLBACK(ft->on_xattr_op, {
napi_value argv[9];
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_create_string_utf8(env, l->name, NAPI_AUTO_LENGTH, &(argv[3]));
napi_create_string_utf8(env, l->value, NAPI_AUTO_LENGTH, &(argv[4]));
napi_create_external_buffer(env, l->size, l->list, &fin, NULL, &(argv[5]));
napi_create_uint32(env, l->size, &(argv[6]));
napi_create_uint32(env, l->flags, &(argv[7]));
napi_create_uint32(env, l->position, &(argv[8]));
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 9, argv, NULL)
})
}
2019-07-29 11:57:46 +00:00
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) {
2019-07-30 16:58:39 +00:00
case (op_statfs):
return fuse_native_dispatch_statfs(handle, status, l, ft);
case (op_fgetattr):
2019-07-29 11:57:46 +00:00
case (op_getattr):
return fuse_native_dispatch_stat(handle, status, l, ft);
2019-07-29 14:44:54 +00:00
case (op_readdir):
return fuse_native_dispatch_readdir(handle, status, l, ft);
2019-07-30 16:58:39 +00:00
case (op_open):
case (op_create):
case (op_access):
case (op_utimens):
return fuse_native_dispatch_path(handle, status, l, ft);
case (op_release):
case (op_releasedir):
case (op_read):
case (op_write):
return fuse_native_dispatch_buffer(handle, status, l, ft);
case (op_getxattr):
case (op_setxattr):
case (op_listxattr):
case (op_removexattr):
return fuse_native_dispatch_xattr(handle, status, l, ft);
2019-07-29 11:57:46 +00:00
}
}
2019-07-24 14:52:17 +00:00
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));
// 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;
}
2019-07-30 16:58:39 +00:00
// Handlers
2019-07-24 14:52:17 +00:00
2019-07-30 16:58:39 +00:00
static int fuse_native_create (const char *path, mode_t mode, struct fuse_file_info *info) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->mode = mode;
l->info = info;
l->op = op_create;
})
}
2019-07-24 14:52:17 +00:00
2019-07-30 16:58:39 +00:00
static int fuse_native_access(const char *path, int mode) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->mode = mode;
l->op = op_access;
})
}
2019-07-24 14:52:17 +00:00
2019-07-30 16:58:39 +00:00
static int fuse_native_open(const char *path, struct fuse_file_info *info) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->info = info;
l->op = op_open;
})
}
2019-07-24 14:52:17 +00:00
2019-07-30 16:58:39 +00:00
static int fuse_native_release (const char *path, struct fuse_file_info *info) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->info = info;
l->op = op_release;
})
2019-07-29 11:57:46 +00:00
}
2019-07-30 16:58:39 +00:00
static int fuse_native_releasedir (const char *path, struct fuse_file_info *info) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->info = info;
l->op = op_releasedir;
})
}
2019-07-29 11:57:46 +00:00
2019-07-30 16:58:39 +00:00
static int fuse_native_write (const char *path, const char *buf, size_t len, off_t offset, struct fuse_file_info * info) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->buf = buf;
l->len = len;
l->offset = offset;
l->info = info;
l->op = op_write;
})
}
2019-07-29 11:57:46 +00:00
2019-07-30 16:58:39 +00:00
static int fuse_native_read (const char *path, char *buf, size_t len, off_t offset, struct fuse_file_info *info) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->buf = buf;
l->len = len;
l->offset = offset;
l->info = info;
l->op = op_read;
})
}
2019-07-29 11:57:46 +00:00
2019-07-30 16:58:39 +00:00
static int fuse_native_fgetattr (const char *path, struct stat *stat, struct fuse_file_info *info) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->stat = stat;
l->info = info;
l->op = op_getattr;
})
}
2019-07-30 16:58:39 +00:00
static int fuse_native_statfs (struct statvfs *statvfs) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->statvfs = statvfs;
l->op = op_statfs;
})
2019-07-29 14:44:54 +00:00
}
static int fuse_native_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *info) {
2019-07-30 16:58:39 +00:00
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->buf = buf;
l->path = path;
l->offset = offset;
l->info = info;
l->readdir_filler = filler;
l->op = op_readdir;
})
}
2019-07-29 14:44:54 +00:00
2019-07-30 16:58:39 +00:00
#ifdef __APPLE__
static int fuse_native_setxattr (const char *path, const char *name, const char *value, size_t size, int flags, uint32_t position) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->name = name;
l->value = value;
l->size = size;
l->flags = flags;
l->position = position;
l->op = op_setxattr;
})
}
static int fuse_native_getxattr (const char *path, const char *name, const char *value, size_t size, uint32_t position) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->name = name;
l->value = value;
l->size = size;
l->position = position;
l->op = op_getxattr;
})
}
#else
static int fuse_native_setxattr (const char *path, const char *name, const char *value, size_t size, int flags, uint32_t position) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->name = name;
l->value = value;
l->size = size;
l->flags = flags;
l->position = position;
l->op = op_setxattr;
})
}
2019-07-29 14:44:54 +00:00
2019-07-30 16:58:39 +00:00
static int fuse_native_getxattr (const char *path, const char *name, const char *value, size_t size, uint32_t position) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->name = name;
l->value = value;
l->size = size;
l->position = position;
l->op = op_getxattr;
})
}
#endif
static int fuse_native_listxattr (const char *path, char *list, size_t size) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->list = list;
l->size = size;
l->op = op_listxattr;
})
}
2019-07-29 14:44:54 +00:00
2019-07-30 16:58:39 +00:00
static int fuse_native_removexattr (const char *path, const char *name) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
l->name = name;
l->op = op_removexattr;
})
}
2019-07-29 14:44:54 +00:00
2019-07-30 16:58:39 +00:00
static int fuse_native_utimens (const char *path, const struct timespec tv[2]) {
FUSE_NATIVE_HANDLER({
l->fuse = ft;
l->path = path;
from_timespec(&tv[0], l->atim);
from_timespec(&tv[1], l->mtim);
l->op = op_utimens;
})
2019-07-24 14:52:17 +00:00
}
2019-07-30 16:58:39 +00:00
// Signallers
2019-07-29 11:57:46 +00:00
NAPI_METHOD(fuse_native_signal_path) {
NAPI_ARGV(3)
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
NAPI_ARGV_INT32(res, 1)
2019-07-30 16:58:39 +00:00
NAPI_ARGV_INT32(fd, 2)
2019-07-29 11:57:46 +00:00
l->res = res;
2019-07-30 16:58:39 +00:00
if (fd != 0) {
l->info->fh = fd;
}
2019-07-29 11:57:46 +00:00
fuse_native_semaphore_signal(&(l->sem));
return NULL;
}
NAPI_METHOD(fuse_native_signal_stat) {
2019-07-29 14:44:54 +00:00
NAPI_ARGV(4)
2019-07-29 11:57:46 +00:00
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
NAPI_ARGV_INT32(res, 1)
2019-07-29 14:44:54 +00:00
NAPI_ARGV_BUFFER_CAST(uint32_t*, ints, 2)
2019-07-29 11:57:46 +00:00
2019-07-29 14:44:54 +00:00
populate_stat(ints, l->stat);
2019-07-29 11:57:46 +00:00
l->res = res;
fuse_native_semaphore_signal(&(l->sem));
return NULL;
}
2019-07-30 16:58:39 +00:00
NAPI_METHOD(fuse_native_signal_buffer) {
NAPI_ARGV(2)
2019-07-29 11:57:46 +00:00
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;
}
2019-07-30 16:58:39 +00:00
NAPI_METHOD(fuse_native_signal_xattr) {
}
NAPI_METHOD(fuse_native_signal_statfs) {
NAPI_ARGV(3)
2019-07-29 11:57:46 +00:00
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
NAPI_ARGV_INT32(res, 1)
2019-07-30 16:58:39 +00:00
NAPI_ARGV_BUFFER_CAST(uint32_t*, ints, 2)
2019-07-29 11:57:46 +00:00
2019-07-30 16:58:39 +00:00
populate_statvfs(ints, l->statvfs);
2019-07-29 11:57:46 +00:00
l->res = res;
fuse_native_semaphore_signal(&(l->sem));
return NULL;
}
NAPI_METHOD(fuse_native_signal_readdir) {
2019-07-29 14:44:54 +00:00
NAPI_ARGV(4)
2019-07-24 14:52:17 +00:00
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
NAPI_ARGV_INT32(res, 1)
2019-07-24 14:52:17 +00:00
2019-07-29 14:44:54 +00:00
uint32_t stats_length;
uint32_t names_length;
napi_get_array_length(env, argv[3], &stats_length);
napi_get_array_length(env, argv[2], &names_length);
napi_value raw_names = argv[2];
napi_value raw_stats = argv[3];
if (names_length != stats_length) {
NAPI_FOR_EACH(raw_names, raw_name) {
NAPI_UTF8(name, 1024, raw_name)
int err = l->readdir_filler(l->buf, name, NULL, 0);
if (err == 1) {
break;
}
}
} else {
NAPI_FOR_EACH(raw_names, raw_name) {
NAPI_UTF8(name, 1024, raw_name)
napi_value raw_stat;
napi_get_element(env, raw_stats, i, &raw_stat);
NAPI_BUFFER_CAST(uint32_t*, stats_array, raw_stat);
struct stat st;
populate_stat(stats_array, &st);
int err = l->readdir_filler(l->buf, name, stat, 0);
if (err == 1) {
break;
}
}
}
l->res = res;
2019-07-24 14:52:17 +00:00
fuse_native_semaphore_signal(&(l->sem));
return NULL;
2019-07-24 14:52:17 +00:00
}
NAPI_METHOD(fuse_native_mount) {
2019-07-29 11:57:46 +00:00
NAPI_ARGV(10)
2019-07-24 14:52:17 +00:00
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));
2019-07-29 11:57:46 +00:00
napi_create_reference(env, argv[4], 1, &(ft->on_path_op));
2019-07-30 16:58:39 +00:00
napi_create_reference(env, argv[5], 1, &(ft->on_stat_op));
napi_create_reference(env, argv[6], 1, &(ft->on_buffer_op));
napi_create_reference(env, argv[7], 1, &(ft->on_xattr_op));
napi_create_reference(env, argv[8], 1, &(ft->on_statfs));
napi_create_reference(env, argv[9], 1, &(ft->on_readdir));
napi_create_reference(env, argv[10], 1, &(ft->on_symlink));
2019-07-24 14:52:17 +00:00
ft->env = env;
struct fuse_operations ops = {
2019-07-30 16:58:39 +00:00
.getattr = fuse_native_fgetattr,
.fgetattr = fuse_native_fgetattr,
2019-07-29 11:57:46 +00:00
.statfs = fuse_native_statfs,
2019-07-30 16:58:39 +00:00
.readdir = fuse_native_readdir,
.open = fuse_native_open,
.create = fuse_native_create,
.read = fuse_native_read,
.write = fuse_native_write,
.release = fuse_native_release,
.releasedir = fuse_native_releasedir,
.access = fuse_native_access,
.setxattr = fuse_native_setxattr,
.getxattr = fuse_native_getxattr,
.listxattr = fuse_native_listxattr,
.removexattr = fuse_native_removexattr,
.utimens = fuse_native_utimens,
2019-07-29 11:57:46 +00:00
/*
.init = fuse_native_init,
.error = fuse_native_error,
.flush = fuse_native_flush,
.fsync = fuse_native_fsync,
.fsyncdir = fuse_native_fsyncdir,
.truncate = fuse_native_truncate,
.ftruncate = fuse_native_ftruncate,
.readlink = fuse_native_readlink,
.chown = fuse_native_chown,
.chmod = fuse_native_chmod,
.mknod = fuse_native_mknod,
.opendir = fuse_native_opendir,
.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,
*/
2019-07-24 14:52:17 +00:00
};
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)
2019-07-29 11:57:46 +00:00
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)
2019-07-24 14:52:17 +00:00
NAPI_EXPORT_SIZEOF(fuse_thread_t)
2019-07-29 11:57:46 +00:00
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)
2019-07-24 14:52:17 +00:00
}
2019-07-30 16:58:39 +00:00