mirror of
				https://github.com/fuse-friends/fuse-native
				synced 2025-06-13 12:53:54 +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