mirror of
https://github.com/fuse-friends/fuse-native
synced 2024-10-27 18:34:01 +00:00
added utimens + release
This commit is contained in:
parent
b65343696e
commit
2e5dd4298d
498
fuse-native.c
498
fuse-native.c
@ -13,6 +13,7 @@
|
||||
#include <fuse_opt.h>
|
||||
#include <fuse_lowlevel.h>
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <pthread.h>
|
||||
@ -28,6 +29,15 @@
|
||||
blk \
|
||||
napi_close_handle_scope(env, scope);
|
||||
|
||||
#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;
|
||||
|
||||
static const uint32_t op_init = 0;
|
||||
static const uint32_t op_error = 1;
|
||||
static const uint32_t op_access = 2;
|
||||
@ -74,6 +84,7 @@ typedef struct {
|
||||
napi_ref on_path_op;
|
||||
napi_ref on_stat_op;
|
||||
napi_ref on_buffer_op;
|
||||
napi_ref on_xattr_op;
|
||||
napi_ref on_statfs;
|
||||
napi_ref on_readdir;
|
||||
napi_ref on_symlink;
|
||||
@ -88,8 +99,22 @@ typedef struct {
|
||||
|
||||
// Payloads
|
||||
const char *path;
|
||||
struct fuse_file_info *info;
|
||||
void *buf;
|
||||
off_t offset;
|
||||
size_t len;
|
||||
mode_t mode;
|
||||
int32_t res;
|
||||
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;
|
||||
|
||||
// Stat + Statfs
|
||||
struct stat *stat;
|
||||
@ -97,8 +122,6 @@ typedef struct {
|
||||
|
||||
// Readdir
|
||||
fuse_fill_dir_t readdir_filler;
|
||||
off_t readdir_offset;
|
||||
struct fuse_file_info *readdir_info;
|
||||
|
||||
// Internal bookkeeping
|
||||
fuse_thread_t *fuse;
|
||||
@ -109,33 +132,110 @@ typedef struct {
|
||||
|
||||
static pthread_key_t thread_locals_key;
|
||||
|
||||
// Helpers
|
||||
// TODO: Extract into a separate file.
|
||||
|
||||
static void fin (napi_env env, void *fin_data, void* fin_hint) {
|
||||
printf("finaliser is run\n");
|
||||
// exit(0);
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
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, {
|
||||
napi_value argv[3];
|
||||
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]));
|
||||
if (l->info != NULL) {
|
||||
napi_create_uint32(env, l->info->fh, &(argv[3]));
|
||||
} else {
|
||||
napi_create_uint32(env, 0, &(argv[3]));
|
||||
}
|
||||
|
||||
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 3, argv, NULL)
|
||||
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 4, argv, NULL)
|
||||
})
|
||||
}
|
||||
|
||||
static void fuse_native_dispatch_path(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
|
||||
FUSE_NATIVE_CALLBACK(ft->on_path_op, {
|
||||
napi_value argv[3];
|
||||
napi_value argv[7];
|
||||
|
||||
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_uint32(env, l->mode, &(argv[3]));
|
||||
|
||||
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 3, argv, NULL)
|
||||
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]);
|
||||
}
|
||||
|
||||
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 7, argv, NULL)
|
||||
})
|
||||
}
|
||||
|
||||
@ -153,25 +253,65 @@ static void fuse_native_dispatch_readdir(uv_async_t* handle, int status, fuse_th
|
||||
|
||||
static void fuse_native_dispatch_buffer(uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {
|
||||
FUSE_NATIVE_CALLBACK(ft->on_buffer_op, {
|
||||
napi_value argv[3];
|
||||
napi_value argv[7];
|
||||
|
||||
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_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]));
|
||||
|
||||
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, 3, argv, NULL)
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
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_statfs):
|
||||
return fuse_native_dispatch_statfs(handle, status, l, ft);
|
||||
case (op_fgetattr):
|
||||
case (op_getattr):
|
||||
return fuse_native_dispatch_stat(handle, status, l, ft);
|
||||
case (op_readdir):
|
||||
return fuse_native_dispatch_readdir(handle, status, l, ft);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,108 +352,206 @@ static void* start_fuse_thread (void *data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int fuse_native_getattr (const char *path, struct stat *stat) {
|
||||
struct fuse_context *ctx = fuse_get_context();
|
||||
fuse_thread_t *ft = (fuse_thread_t *) ctx->private_data;
|
||||
// Handlers
|
||||
|
||||
fuse_thread_locals_t *l = get_thread_locals();
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
l->fuse = ft;
|
||||
l->stat = stat;
|
||||
l->op = op_getattr;
|
||||
l->path = path;
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
uv_async_send(&(l->async));
|
||||
fuse_native_semaphore_wait(&(l->sem));
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
return l->res;
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
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 l->res;
|
||||
FUSE_NATIVE_HANDLER({
|
||||
l->fuse = ft;
|
||||
l->statvfs = statvfs;
|
||||
l->op = op_statfs;
|
||||
})
|
||||
}
|
||||
|
||||
static int fuse_native_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *info) {
|
||||
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->buf = buf;
|
||||
l->path = path;
|
||||
l->readdir_filler = filler;
|
||||
l->readdir_offset = offset;
|
||||
l->readdir_info = info;
|
||||
l->op = op_readdir;
|
||||
|
||||
uv_async_send(&(l->async));
|
||||
printf("before semaphore wait\n");
|
||||
fuse_native_semaphore_wait(&(l->sem));
|
||||
printf("after semaphore wait\n");
|
||||
|
||||
return l->res;
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
#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;
|
||||
})
|
||||
}
|
||||
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
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;
|
||||
})
|
||||
}
|
||||
|
||||
// Signallers
|
||||
|
||||
NAPI_METHOD(fuse_native_signal_path) {
|
||||
NAPI_ARGV(3)
|
||||
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
||||
NAPI_ARGV_INT32(res, 1)
|
||||
NAPI_ARGV_INT32(fd, 2)
|
||||
|
||||
l->res = res;
|
||||
if (fd != 0) {
|
||||
l->info->fh = fd;
|
||||
}
|
||||
fuse_native_semaphore_signal(&(l->sem));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 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++;
|
||||
}
|
||||
|
||||
NAPI_METHOD(fuse_native_signal_stat) {
|
||||
NAPI_ARGV(4)
|
||||
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
||||
@ -327,19 +565,6 @@ NAPI_METHOD(fuse_native_signal_stat) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NAPI_METHOD(fuse_native_signal_statfs) {
|
||||
NAPI_ARGV(3)
|
||||
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
||||
NAPI_ARGV_INT32(res, 1)
|
||||
NAPI_ARGV_BUFFER_CAST(uint32_t*, ints, 2)
|
||||
|
||||
populate_statvfs(ints, l->statvfs);
|
||||
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);
|
||||
@ -351,8 +576,23 @@ NAPI_METHOD(fuse_native_signal_buffer) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NAPI_METHOD(fuse_native_signal_xattr) {
|
||||
}
|
||||
|
||||
NAPI_METHOD(fuse_native_signal_statfs) {
|
||||
NAPI_ARGV(3)
|
||||
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
||||
NAPI_ARGV_INT32(res, 1)
|
||||
NAPI_ARGV_BUFFER_CAST(uint32_t*, ints, 2)
|
||||
|
||||
populate_statvfs(ints, l->statvfs);
|
||||
l->res = res;
|
||||
fuse_native_semaphore_signal(&(l->sem));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NAPI_METHOD(fuse_native_signal_readdir) {
|
||||
printf("In signal readdir\n");
|
||||
NAPI_ARGV(4)
|
||||
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);
|
||||
NAPI_ARGV_INT32(res, 1)
|
||||
@ -405,45 +645,45 @@ NAPI_METHOD(fuse_native_mount) {
|
||||
napi_create_reference(env, argv[3], 1, &(ft->ctx));
|
||||
|
||||
napi_create_reference(env, argv[4], 1, &(ft->on_path_op));
|
||||
napi_create_reference(env, argv[5], 1, &(ft->on_statfs));
|
||||
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));
|
||||
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));
|
||||
|
||||
ft->env = env;
|
||||
|
||||
struct fuse_operations ops = {
|
||||
.getattr = fuse_native_getattr,
|
||||
.statfs = fuse_native_statfs,
|
||||
.readdir = fuse_native_readdir
|
||||
/*
|
||||
.init = fuse_native_init,
|
||||
.error = fuse_native_error,
|
||||
.access = fuse_native_access,
|
||||
.getattr = fuse_native_fgetattr,
|
||||
.fgetattr = fuse_native_fgetattr,
|
||||
.flush = fuse_native_flush,
|
||||
.fsync = fuse_native_fsync,
|
||||
.fsyncdir = fuse_native_fsyncdir,
|
||||
.statfs = fuse_native_statfs,
|
||||
.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,
|
||||
.create = fuse_native_create,
|
||||
.read = fuse_native_read,
|
||||
.write = fuse_native_write,
|
||||
.release = fuse_native_release,
|
||||
.releasedir = fuse_native_releasedir,
|
||||
.create = fuse_native_create,
|
||||
.access = fuse_native_access,
|
||||
.setxattr = fuse_native_setxattr,
|
||||
.getxattr = fuse_native_getxattr,
|
||||
.listxattr = fuse_native_listxattr,
|
||||
.removexattr = fuse_native_removexattr,
|
||||
.utimens = fuse_native_utimens,
|
||||
/*
|
||||
.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,
|
||||
@ -530,3 +770,5 @@ NAPI_INIT() {
|
||||
NAPI_EXPORT_UINT32(op_rmdir)
|
||||
NAPI_EXPORT_UINT32(op_destroy)
|
||||
}
|
||||
|
||||
|
||||
|
130
index.js
130
index.js
@ -68,8 +68,8 @@ class Fuse {
|
||||
|
||||
mount () {
|
||||
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)
|
||||
this.on_path_op, this.on_stat_op, this.on_fd_op, this.on_xattr_op,
|
||||
this.on_statfs, this.on_readdir, this.on_symlink)
|
||||
}
|
||||
|
||||
unmount () {
|
||||
@ -82,24 +82,17 @@ class Fuse {
|
||||
}
|
||||
|
||||
on_readdir (handle, op, path) {
|
||||
console.log('IN ONREADDIR')
|
||||
const signalFunc = binding.fuse_native_signal_readdir.bind(binding)
|
||||
|
||||
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1])
|
||||
|
||||
this.ops.readdir(path, (err, names, stats) => {
|
||||
if (stats) stats = stats.map(getStatArray)
|
||||
console.error('readdir err:', err, 'names:', names, 'stats:', stats)
|
||||
return this._signal(signalFunc, [handle, err, names, stats || []])
|
||||
})
|
||||
}
|
||||
|
||||
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) {
|
||||
on_statfs (handle, op) {
|
||||
const signalFunc = binding.fuse_native_signal_statfs.bind(binding)
|
||||
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1, ...getStatfsArray()])
|
||||
|
||||
@ -109,27 +102,102 @@ class Fuse {
|
||||
})
|
||||
}
|
||||
|
||||
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()])
|
||||
on_fd_op (handle, op, path, fd, buf, len, offset) {
|
||||
const signalFunc = binding.fuse_native_signal_buffer.bind(binding)
|
||||
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1])
|
||||
|
||||
const cb = (bytesProcessed) => {
|
||||
return this._signal(signalFunc, [handle, bytesProcessed || 0])
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case (binding.op_getattr):
|
||||
this.ops.getattr(path, (err, stat) => {
|
||||
const arr = getStatArray(stat)
|
||||
return this._signal(signalFunc, [handle, err, arr])
|
||||
})
|
||||
case (binding.op_read):
|
||||
this.ops.read(path, fd, buf, len, offset, cb)
|
||||
break
|
||||
case (binding.op_write):
|
||||
this.ops.write(path, fd, buf, len, offset, cb)
|
||||
break
|
||||
case(binding.op_release):
|
||||
this.ops.release(path, fd, cb)
|
||||
break
|
||||
case(binding.op_releasedir):
|
||||
this.ops.releasedir(path, fd, cb)
|
||||
break
|
||||
|
||||
default:
|
||||
return this._signal(signalFunc, [handle, -1, getStatArray()])
|
||||
return this._signal(signalFunc, [handle, 0])
|
||||
}
|
||||
}
|
||||
|
||||
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])
|
||||
on_stat_op (handle, op, path, fd) {
|
||||
const signalFunc = binding.fuse_native_signal_stat.bind(binding)
|
||||
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1, getStatArray()])
|
||||
|
||||
const cb = (err, stat) => {
|
||||
const arr = getStatArray(stat)
|
||||
return this._signal(signalFunc, [handle, err, arr])
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case (binding.op_getattr):
|
||||
this.ops.getattr(path, cb)
|
||||
break
|
||||
case (binding.op_fgetattr):
|
||||
this.ops.fgetattr(path, fd, cb)
|
||||
default:
|
||||
return this._signal(signalFunc, [handle, -1, getStatArray()])
|
||||
}
|
||||
}
|
||||
|
||||
on_path_op (handle, op, path, mode, flags, atim, mtim) {
|
||||
const signalFunc = binding.fuse_native_signal_path.bind(binding)
|
||||
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1, 0])
|
||||
|
||||
const cb = (err, fd) => {
|
||||
return this._signal(signalFunc, [handle, err, fd || 0])
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case (binding.op_open):
|
||||
this.ops.open(path, flags, cb)
|
||||
break
|
||||
case (binding.op_create):
|
||||
this.ops.create(path, mode, cb)
|
||||
break
|
||||
case (binding.op_access):
|
||||
this.ops.access(path, mode, cb)
|
||||
break
|
||||
case (binding.op_utimens):
|
||||
this.ops.utimens(path, getDoubleInt(atim, 0), getDoubleInt(mtim, 0), cb)
|
||||
break
|
||||
default:
|
||||
return this._signal(signalFunc, [handle, -1, 0])
|
||||
}
|
||||
}
|
||||
|
||||
on_xattr_op (handle, op, path, name, value, list, size, flags, position) {
|
||||
const signalFunc = binding.fuse_native_signal_xattr.bind(binding)
|
||||
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1, 0])
|
||||
|
||||
const cb = err => {
|
||||
return this._signal(signalFunc, [handle, -1])
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case (binding.op_setxattr):
|
||||
this.ops.setxattr(path, name, value, size, position || 0, flags, cb)
|
||||
break
|
||||
case (binding.op_getxattr):
|
||||
this.ops.getxattr(path, name, value, size, position || 0, cb)
|
||||
break
|
||||
case (binding.op_listxattr):
|
||||
this.ops.listxattr(path, list, size, cb)
|
||||
break
|
||||
case (binding.op_removexattr):
|
||||
this.ops.removexattr(path, name, cb)
|
||||
break
|
||||
default:
|
||||
return this._signal(signalFunc, [handle, -1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,6 +224,13 @@ function setDoubleInt (arr, idx, num) {
|
||||
arr[idx + 1] = (num - arr[idx]) / 4294967296
|
||||
}
|
||||
|
||||
function getDoubleInt(arr, idx) {
|
||||
arr = new Uint32Array(arr)
|
||||
var num = arr[idx + 1] * 4294967296
|
||||
num += arr[idx]
|
||||
return num
|
||||
}
|
||||
|
||||
function getStatArray (stat) {
|
||||
const ints = new Uint32Array(16)
|
||||
|
||||
@ -193,6 +268,15 @@ const f = new Fuse('mnt', {
|
||||
getattr: (path, cb) => {
|
||||
return cb(0, emptyStat())
|
||||
},
|
||||
access: (path, mode, cb) => {
|
||||
return cb(0, 0)
|
||||
},
|
||||
setxattr: (path, name, buffer, length, offset, cb) => {
|
||||
return cb(0)
|
||||
},
|
||||
utimens: (path, atim, mtim, cb) => {
|
||||
return cb(0)
|
||||
},
|
||||
readdir: (path, cb) => {
|
||||
if (path === '/') {
|
||||
return cb(0, ['a', 'b', 'c'], Array(3).fill('a').map(() => emptyStat()))
|
||||
|
Loading…
Reference in New Issue
Block a user