mirror of
https://github.com/fuse-friends/fuse-native
synced 2024-10-27 18:34:01 +00:00
init flow works, getattr fails
This commit is contained in:
parent
bd9d36fb2f
commit
e4732baf83
13
example.js
13
example.js
@ -69,16 +69,3 @@ process.on('SIGINT', function () {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
function emptyStat (mode) {
|
|
||||||
return {
|
|
||||||
mtime: new Date(),
|
|
||||||
atime: new Date(),
|
|
||||||
ctime: new Date(),
|
|
||||||
nlink: 1,
|
|
||||||
size: 100,
|
|
||||||
mode: mode,
|
|
||||||
uid: process.getuid ? process.getuid() : 0,
|
|
||||||
gid: process.getgid ? process.getgid() : 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -39,29 +39,36 @@
|
|||||||
fuse_native_semaphore_wait(&(l->sem)); \
|
fuse_native_semaphore_wait(&(l->sem)); \
|
||||||
return l->res;
|
return l->res;
|
||||||
|
|
||||||
#define FUSE_METHOD(name, callbackArgs, signalArgs, signature, callBlk, callbackBlk, signalBlk) \
|
#define FUSE_METHOD(name, callbackArgs, signalArgs, signature, callBlk, callbackBlk, signalBlk)\
|
||||||
static void fuse_native_dispatch_##name (uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) { \
|
static void fuse_native_dispatch_##name (uv_async_t* handle, int status, fuse_thread_locals_t* l, fuse_thread_t* ft) {\
|
||||||
uint32_t op = op_##name; \
|
printf("at beginning of fuse_native_dispatch_%s\n", #name);\
|
||||||
FUSE_NATIVE_CALLBACK(ft->handlers[op], { \
|
uint32_t op = op_##name;\
|
||||||
napi_value argv[callbackArgs + 2]; \
|
printf("op here: %i\n", op);\
|
||||||
napi_create_external_buffer(env, sizeof(fuse_thread_locals_t), l, &fin, NULL, &(argv[0])); \
|
printf("handler here: %zu\n", ft->handlers[op]);\
|
||||||
napi_create_uint32(env, l->op, &(argv[1])); \
|
printf("in fuse_native_dispatch, op: %i, handler: %zu\n", op, ft->handlers[op]);\
|
||||||
callbackBlk \
|
FUSE_NATIVE_CALLBACK(ft->handlers[op], {\
|
||||||
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, callbackArgs + 2, argv, NULL) \
|
napi_value argv[callbackArgs + 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_METHOD(fuse_native_signal_##name) { \
|
callbackBlk\
|
||||||
NAPI_ARGV(signalArgs + 2) \
|
printf("in fuse_native_callback, calling callback for %s\n", #name);\
|
||||||
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0); \
|
NAPI_MAKE_CALLBACK(env, NULL, ctx, callback, callbackArgs + 2, argv, NULL)\
|
||||||
NAPI_ARGV_INT32(res, 1); \
|
})\
|
||||||
signalBlk \
|
}\
|
||||||
l->res = res; \
|
NAPI_METHOD(fuse_native_signal_##name) {\
|
||||||
fuse_native_semaphore_signal(&(l->sem)); \
|
NAPI_ARGV(signalArgs + 2)\
|
||||||
return NULL; \
|
NAPI_ARGV_BUFFER_CAST(fuse_thread_locals_t *, l, 0);\
|
||||||
} \
|
NAPI_ARGV_INT32(res, 1);\
|
||||||
static int fuse_native_##name signature { \
|
signalBlk\
|
||||||
FUSE_NATIVE_HANDLER(name, callBlk) \
|
l->res = res;\
|
||||||
} \
|
printf("in _fuse_native_signal_%s, signalling semaphore\n", #name);\
|
||||||
|
fuse_native_semaphore_signal(&(l->sem));\
|
||||||
|
return NULL;\
|
||||||
|
}\
|
||||||
|
static int fuse_native_##name signature {\
|
||||||
|
printf("in fuse_native_%s\n", #name);\
|
||||||
|
FUSE_NATIVE_HANDLER(name, callBlk)\
|
||||||
|
}
|
||||||
|
|
||||||
// Opcodes
|
// Opcodes
|
||||||
|
|
||||||
@ -110,7 +117,7 @@ typedef struct {
|
|||||||
napi_ref ctx;
|
napi_ref ctx;
|
||||||
|
|
||||||
// Operation handlers
|
// Operation handlers
|
||||||
napi_ref handlers[34];
|
napi_ref handlers[35];
|
||||||
|
|
||||||
struct fuse *fuse;
|
struct fuse *fuse;
|
||||||
struct fuse_chan *ch;
|
struct fuse_chan *ch;
|
||||||
@ -537,7 +544,13 @@ FUSE_METHOD(removexattr, 2, 0, (const char *path, const char *name), {
|
|||||||
},
|
},
|
||||||
{})
|
{})
|
||||||
|
|
||||||
FUSE_METHOD(init, 0, 0, (struct fuse_conn_info *conn, struct fuse_config *cfg), {}, {}, {})
|
FUSE_METHOD(init, 0, 0, (struct fuse_conn_info *conn, struct fuse_config *cfg), {
|
||||||
|
printf("in fuse_native_init\n");
|
||||||
|
}, {
|
||||||
|
printf("in fuse_native_init_callback\n");
|
||||||
|
}, {
|
||||||
|
printf("in fuse_native_init_signal\n");
|
||||||
|
})
|
||||||
|
|
||||||
FUSE_METHOD(error, 0, 0, (), {}, {}, {})
|
FUSE_METHOD(error, 0, 0, (), {}, {}, {})
|
||||||
|
|
||||||
@ -713,6 +726,8 @@ static void fuse_native_dispatch (uv_async_t* handle, int status) {
|
|||||||
fuse_thread_locals_t *l = (fuse_thread_locals_t *) handle->data;
|
fuse_thread_locals_t *l = (fuse_thread_locals_t *) handle->data;
|
||||||
fuse_thread_t *ft = l->fuse;
|
fuse_thread_t *ft = l->fuse;
|
||||||
|
|
||||||
|
printf("dispatching %i\n", l->op);
|
||||||
|
|
||||||
// TODO: Either use a function pointer (like ft->handlers[op]) or generate with a macro.
|
// TODO: Either use a function pointer (like ft->handlers[op]) or generate with a macro.
|
||||||
switch (l->op) {
|
switch (l->op) {
|
||||||
case (op_init): return fuse_native_dispatch_init(handle, status, l, ft);
|
case (op_init): return fuse_native_dispatch_init(handle, status, l, ft);
|
||||||
@ -799,10 +814,9 @@ NAPI_METHOD(fuse_native_mount) {
|
|||||||
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_ref handlers;
|
napi_value handlers = argv[4];
|
||||||
napi_create_reference(env, argv[4], 1, &handlers);
|
|
||||||
|
|
||||||
NAPI_FOR_EACH(handlers, handler) {
|
NAPI_FOR_EACH(handlers, handler) {
|
||||||
|
printf("creating reference for handler: %d\n", i);
|
||||||
napi_create_reference(env, handler, 1, &ft->handlers[i]);
|
napi_create_reference(env, handler, 1, &ft->handlers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,7 +859,7 @@ NAPI_METHOD(fuse_native_mount) {
|
|||||||
.destroy = fuse_native_destroy
|
.destroy = fuse_native_destroy
|
||||||
};
|
};
|
||||||
|
|
||||||
int _argc = 2;
|
int _argc = (strcmp(mntopts, "-o") <= 0) ? 1 : 2;
|
||||||
char *_argv[] = {
|
char *_argv[] = {
|
||||||
(char *) "fuse_bindings_dummy",
|
(char *) "fuse_bindings_dummy",
|
||||||
(char *) mntopts
|
(char *) mntopts
|
||||||
|
260
index.js
260
index.js
@ -9,115 +9,118 @@ const HAS_FOLDER_ICON = IS_OSX && fs.existsSync(OSX_FOLDER_ICON)
|
|||||||
|
|
||||||
const binding = require('node-gyp-build')(__dirname)
|
const binding = require('node-gyp-build')(__dirname)
|
||||||
const OpcodesAndDefaults = new Map([
|
const OpcodesAndDefaults = new Map([
|
||||||
[ 'init', {
|
['init', {
|
||||||
op: 0
|
op: 0
|
||||||
} ],
|
}],
|
||||||
[ 'error', {
|
['error', {
|
||||||
op: 1
|
op: 1
|
||||||
} ],
|
}],
|
||||||
[ 'access', {
|
['access', {
|
||||||
op: 2,
|
op: 2,
|
||||||
defaults: [ 0 ]
|
defaults: [0]
|
||||||
} ],
|
}],
|
||||||
[ 'statfs', {
|
['statfs', {
|
||||||
op: 3,
|
op: 3,
|
||||||
defaults: [ getStatfsArray() ]
|
defaults: [getStatfsArray()]
|
||||||
} ],
|
}],
|
||||||
[ 'fgetattr', {
|
['fgetattr', {
|
||||||
op: 4,
|
op: 4,
|
||||||
defaults: [ getStatArray() ]
|
defaults: [getStatArray()]
|
||||||
} ],
|
}],
|
||||||
[ 'getattr', {
|
['getattr', {
|
||||||
op: 5,
|
op: 5,
|
||||||
defaults: [ getStatArray() ]
|
defaults: [getStatArray()]
|
||||||
} ],
|
}],
|
||||||
[ 'flush', {
|
['flush', {
|
||||||
op: 6,
|
op: 6
|
||||||
} ],
|
}],
|
||||||
[ 'fsync', {
|
['fsync', {
|
||||||
op: 7
|
op: 7
|
||||||
} ],
|
}],
|
||||||
[ 'fsyncdir', {
|
['fsyncdir', {
|
||||||
op: 8
|
op: 8
|
||||||
} ],
|
}],
|
||||||
[ 'readdir', {
|
['readdir', {
|
||||||
op: 9
|
op: 9
|
||||||
} ],
|
}],
|
||||||
[ 'truncate', {
|
['truncate', {
|
||||||
op: 10
|
op: 10
|
||||||
} ],
|
}],
|
||||||
[ 'ftruncate', {
|
['ftruncate', {
|
||||||
op: 11
|
op: 11
|
||||||
} ],
|
}],
|
||||||
[ 'utimens', {
|
['utimens', {
|
||||||
op: 12
|
op: 12
|
||||||
} ],
|
}],
|
||||||
[ 'readlink', {
|
['readlink', {
|
||||||
op: 13
|
op: 13,
|
||||||
} ],
|
defaults: ['']
|
||||||
[ 'chown', {
|
}],
|
||||||
op: 14
|
['chown', {
|
||||||
} ],
|
op: 14
|
||||||
[ 'chmod', {
|
}],
|
||||||
op: 15
|
['chmod', {
|
||||||
} ],
|
op: 15
|
||||||
[ 'mknod', {
|
}],
|
||||||
op: 16
|
['mknod', {
|
||||||
} ],
|
op: 16
|
||||||
[ 'setxattr', {
|
}],
|
||||||
op: 17
|
['setxattr', {
|
||||||
} ],
|
op: 17
|
||||||
[ 'getxattr', {
|
}],
|
||||||
op: 18
|
['getxattr', {
|
||||||
} ],
|
op: 18
|
||||||
[ 'listxattr', {
|
}],
|
||||||
op: 19
|
['listxattr', {
|
||||||
} ],
|
op: 19
|
||||||
[ 'removexattr', {
|
}],
|
||||||
op: 20
|
['removexattr', {
|
||||||
} ],
|
op: 20
|
||||||
[ 'open', {
|
}],
|
||||||
op: 21
|
['open', {
|
||||||
} ],
|
op: 21
|
||||||
[ 'opendir', {
|
}],
|
||||||
op: 22
|
['opendir', {
|
||||||
} ],
|
op: 22
|
||||||
[ 'read', {
|
}],
|
||||||
op: 23
|
['read', {
|
||||||
} ],
|
op: 23,
|
||||||
[ 'write', {
|
defaults: [0]
|
||||||
op: 24
|
}],
|
||||||
} ],
|
['write', {
|
||||||
[ 'release', {
|
op: 24,
|
||||||
op: 25
|
defaults: [0]
|
||||||
} ],
|
}],
|
||||||
[ 'releasedir', {
|
['release', {
|
||||||
op: 26
|
op: 25
|
||||||
} ],
|
}],
|
||||||
[ 'create', {
|
['releasedir', {
|
||||||
op: 27
|
op: 26
|
||||||
} ],
|
}],
|
||||||
[ 'unlink', {
|
['create', {
|
||||||
op: 28
|
op: 27
|
||||||
} ],
|
}],
|
||||||
[ 'rename', {
|
['unlink', {
|
||||||
op: 29
|
op: 28
|
||||||
} ],
|
}],
|
||||||
[ 'link', {
|
['rename', {
|
||||||
op: 30
|
op: 29
|
||||||
} ],
|
}],
|
||||||
[ 'symlink', {
|
['link', {
|
||||||
op: 31
|
op: 30
|
||||||
} ],
|
}],
|
||||||
[ 'mkdir', {
|
['symlink', {
|
||||||
op: 32
|
op: 31
|
||||||
} ],
|
}],
|
||||||
[ 'rmdir', {
|
['mkdir', {
|
||||||
op: 33
|
op: 32
|
||||||
} ],
|
}],
|
||||||
[ 'destroy', {
|
['rmdir', {
|
||||||
op: 34
|
op: 33
|
||||||
} ]
|
}],
|
||||||
|
['destroy', {
|
||||||
|
op: 34
|
||||||
|
}]
|
||||||
])
|
])
|
||||||
|
|
||||||
class Fuse {
|
class Fuse {
|
||||||
@ -133,8 +136,8 @@ class Fuse {
|
|||||||
|
|
||||||
const implemented = [0, 1, 5]
|
const implemented = [0, 1, 5]
|
||||||
if (ops) {
|
if (ops) {
|
||||||
for (const [name, code] of Opcodes) {
|
for (const [name, { op }] of OpcodesAndDefaults) {
|
||||||
if (ops[name]) implemented.push(code)
|
if (ops[name]) implemented.push(op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._implemented = new Set(implemented)
|
this._implemented = new Set(implemented)
|
||||||
@ -189,7 +192,9 @@ class Fuse {
|
|||||||
// Handlers
|
// Handlers
|
||||||
|
|
||||||
_makeHandlerArray () {
|
_makeHandlerArray () {
|
||||||
|
const self = this
|
||||||
const handlers = new Array(OpcodesAndDefaults.size)
|
const handlers = new Array(OpcodesAndDefaults.size)
|
||||||
|
|
||||||
for (const [name, { op, defaults }] of OpcodesAndDefaults) {
|
for (const [name, { op, defaults }] of OpcodesAndDefaults) {
|
||||||
const nativeSignal = binding[`fuse_native_signal_${name}`]
|
const nativeSignal = binding[`fuse_native_signal_${name}`]
|
||||||
if (!nativeSignal) continue
|
if (!nativeSignal) continue
|
||||||
@ -200,22 +205,25 @@ class Fuse {
|
|||||||
return handlers
|
return handlers
|
||||||
|
|
||||||
function makeHandler (name, op, defaults, nativeSignal) {
|
function makeHandler (name, op, defaults, nativeSignal) {
|
||||||
return () => {
|
return function () {
|
||||||
const boundSignal = signal.bind(arguments[0])
|
const boundSignal = signal.bind(null, arguments[0])
|
||||||
const funcName = `_$name`
|
const funcName = `_${name}`
|
||||||
if (!this[funcName] || !this._implemented.has(op)) return boundSignal(-1, defaults)
|
if (!self[funcName] || !self._implemented.has(op)) return boundSignal(-1, defaults)
|
||||||
return this[funcName].apply(null, [boundSignal, [...arguments].slice(1) ])
|
return self[funcName].apply(self, [boundSignal, ...[...arguments].slice(1)])
|
||||||
}
|
}
|
||||||
|
|
||||||
function signal (nativeHandler, err, args) {
|
function signal (nativeHandler, err, ...args) {
|
||||||
const args = [nativeHandler, err]
|
console.log('nativeHanlder:', nativeHandler, 'err:', err, 'args:', args)
|
||||||
if (defaults) args.concat(defaults)
|
const arr = [nativeHandler, err, ...args]
|
||||||
return nativeSignal(args)
|
if (defaults && (!args || !args.length)) arr.concat(defaults)
|
||||||
|
console.log('signalling with arr:', arr)
|
||||||
|
return nativeSignal(...arr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_init (signal) {
|
_init (signal) {
|
||||||
|
console.log('IN JS INIT')
|
||||||
if (!this.ops.init) {
|
if (!this.ops.init) {
|
||||||
signal(0)
|
signal(0)
|
||||||
return
|
return
|
||||||
@ -461,7 +469,8 @@ class Fuse {
|
|||||||
|
|
||||||
mount (cb) {
|
mount (cb) {
|
||||||
const opts = this._fuseOptions()
|
const opts = this._fuseOptions()
|
||||||
|
console.log('mounting at %s with opts: %s', this.mnt, opts)
|
||||||
|
console.log('handlers:', this._handlers)
|
||||||
fs.stat(this.mnt, (err, stat) => {
|
fs.stat(this.mnt, (err, stat) => {
|
||||||
if (err) return cb(new Error('Mountpoint does not exist'))
|
if (err) return cb(new Error('Mountpoint does not exist'))
|
||||||
if (!stat.isDirectory()) return cb(new Error('Mountpoint is not a directory'))
|
if (!stat.isDirectory()) return cb(new Error('Mountpoint is not a directory'))
|
||||||
@ -646,7 +655,7 @@ function setDoubleInt (arr, idx, num) {
|
|||||||
arr[idx + 1] = (num - arr[idx]) / 4294967296
|
arr[idx + 1] = (num - arr[idx]) / 4294967296
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDoubleInt(arr, idx) {
|
function getDoubleInt (arr, idx) {
|
||||||
arr = new Uint32Array(arr)
|
arr = new Uint32Array(arr)
|
||||||
var num = arr[idx + 1] * 4294967296
|
var num = arr[idx + 1] * 4294967296
|
||||||
num += arr[idx]
|
num += arr[idx]
|
||||||
@ -658,20 +667,17 @@ function getStatArray (stat) {
|
|||||||
|
|
||||||
ints[0] = (stat && stat.mode) || 0
|
ints[0] = (stat && stat.mode) || 0
|
||||||
ints[1] = (stat && stat.uid) || 0
|
ints[1] = (stat && stat.uid) || 0
|
||||||
ints[2] = (stat && stat.gid) || 0
|
ints[2] = (stat && stat.gid) || 0
|
||||||
ints[3] = (stat && stat.size) || 0
|
ints[3] = (stat && stat.size) || 0
|
||||||
ints[4] = (stat && stat.dev) || 0
|
ints[4] = (stat && stat.dev) || 0
|
||||||
ints[5] = (stat && stat.nlink) || 1
|
ints[5] = (stat && stat.nlink) || 1
|
||||||
ints[6] = (stat && stat.ino) || 0
|
ints[6] = (stat && stat.ino) || 0
|
||||||
ints[7] = (stat && stat.rdev) || 0
|
ints[7] = (stat && stat.rdev) || 0
|
||||||
ints[8] = (stat && stat.blksize) || 0
|
ints[8] = (stat && stat.blksize) || 0
|
||||||
ints[9] = (stat && stat.blocks) || 0
|
ints[9] = (stat && stat.blocks) || 0
|
||||||
setDoubleInt(ints, 10, (stat && stat.atim) || Date.now())
|
setDoubleInt(ints, 10, (stat && stat.atim) || Date.now())
|
||||||
setDoubleInt(ints, 12, (stat && stat.atim) || Date.now())
|
setDoubleInt(ints, 12, (stat && stat.atim) || Date.now())
|
||||||
setDoubleInt(ints, 14, (stat && stat.atim) || Date.now())
|
setDoubleInt(ints, 14, (stat && stat.atim) || Date.now())
|
||||||
|
|
||||||
return ints
|
return ints
|
||||||
}
|
}
|
||||||
|
|
||||||
function noop () {}
|
|
||||||
function call (cb) { cb() }
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"install": "node-gyp-build",
|
"install": "node-gyp-build",
|
||||||
|
"test": "standard && test/*.js",
|
||||||
"prebuild": "prebuildify -a --strip",
|
"prebuild": "prebuildify -a --strip",
|
||||||
"prebuild-ia32": "prebuildify -a --strip --arch=ia32"
|
"prebuild-ia32": "prebuildify -a --strip --arch=ia32"
|
||||||
},
|
},
|
||||||
@ -14,7 +15,11 @@
|
|||||||
"napi-macros": "^2.0.0",
|
"napi-macros": "^2.0.0",
|
||||||
"node-gyp-build": "^3.2.2"
|
"node-gyp-build": "^3.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {
|
||||||
|
"concat-stream": "^2.0.0",
|
||||||
|
"standard": "^13.1.0",
|
||||||
|
"tape": "^4.11.0"
|
||||||
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/fuse-friends/fuse-native.git"
|
"url": "https://github.com/fuse-friends/fuse-native.git"
|
||||||
|
13
test/fixtures/mnt.js
vendored
Normal file
13
test/fixtures/mnt.js
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
var os = require('os')
|
||||||
|
var path = require('path')
|
||||||
|
var fs = require('fs')
|
||||||
|
|
||||||
|
var mnt = path.join(os.tmpdir(), 'fuse-bindings-' + process.pid + '-' + Date.now())
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(mnt)
|
||||||
|
} catch (err) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = mnt
|
11
test/fixtures/stat.js
vendored
Normal file
11
test/fixtures/stat.js
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module.exports = function (st) {
|
||||||
|
return {
|
||||||
|
mtime: st.mtime || new Date(),
|
||||||
|
atime: st.atime || new Date(),
|
||||||
|
ctime: st.ctime || new Date(),
|
||||||
|
size: st.size !== undefined ? st.size : 0,
|
||||||
|
mode: st.mode === 'dir' ? 16877 : (st.mode === 'file' ? 33188 : (st.mode === 'link' ? 41453 : st.mode)),
|
||||||
|
uid: st.uid !== undefined ? st.uid : process.getuid(),
|
||||||
|
gid: st.gid !== undefined ? st.gid : process.getgid()
|
||||||
|
}
|
||||||
|
}
|
62
test/links.js
Normal file
62
test/links.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
var mnt = require('./fixtures/mnt')
|
||||||
|
var stat = require('./fixtures/stat')
|
||||||
|
var fuse = require('../')
|
||||||
|
var tape = require('tape')
|
||||||
|
var fs = require('fs')
|
||||||
|
var path = require('path')
|
||||||
|
|
||||||
|
tape('readlink', function (t) {
|
||||||
|
var ops = {
|
||||||
|
force: true,
|
||||||
|
readdir: function (path, cb) {
|
||||||
|
if (path === '/') return cb(null, ['hello', 'link'])
|
||||||
|
return cb(fuse.ENOENT)
|
||||||
|
},
|
||||||
|
readlink: function (path, cb) {
|
||||||
|
cb(0, 'hello')
|
||||||
|
},
|
||||||
|
getattr: function (path, cb) {
|
||||||
|
if (path === '/') return cb(null, stat({ mode: 'dir', size: 4096 }))
|
||||||
|
if (path === '/hello') return cb(null, stat({ mode: 'file', size: 11 }))
|
||||||
|
if (path === '/link') return cb(null, stat({ mode: 'link', size: 5 }))
|
||||||
|
return cb(fuse.ENOENT)
|
||||||
|
},
|
||||||
|
open: function (path, flags, cb) {
|
||||||
|
cb(0, 42)
|
||||||
|
},
|
||||||
|
read: function (path, fd, buf, len, pos, cb) {
|
||||||
|
var str = 'hello world'.slice(pos, pos + len)
|
||||||
|
if (!str) return cb(0)
|
||||||
|
buf.write(str)
|
||||||
|
return cb(str.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fuse.mount(mnt, ops, function (err) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
|
||||||
|
fs.lstat(path.join(mnt, 'link'), function (err, stat) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
t.same(stat.size, 5, 'correct size')
|
||||||
|
|
||||||
|
fs.stat(path.join(mnt, 'hello'), function (err, stat) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
t.same(stat.size, 11, 'correct size')
|
||||||
|
|
||||||
|
fs.readlink(path.join(mnt, 'link'), function (err, dest) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
t.same(dest, 'hello', 'link resolves')
|
||||||
|
|
||||||
|
fs.readFile(path.join(mnt, 'link'), function (err, buf) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
t.same(buf, new Buffer('hello world'), 'can read link content')
|
||||||
|
|
||||||
|
fuse.unmount(mnt, function () {
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
43
test/misc.js
Normal file
43
test/misc.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
var mnt = require('./fixtures/mnt')
|
||||||
|
var fuse = require('../')
|
||||||
|
var tape = require('tape')
|
||||||
|
|
||||||
|
tape('mount', function (t) {
|
||||||
|
fuse.mount(mnt, { force: true }, function (err) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
t.ok(true, 'works')
|
||||||
|
fuse.unmount(mnt, function () {
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
tape('mount + unmount + mount', function (t) {
|
||||||
|
fuse.mount(mnt, { force: true }, function (err) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
t.ok(true, 'works')
|
||||||
|
fuse.unmount(mnt, function () {
|
||||||
|
fuse.mount(mnt, { force: true }, function (err) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
t.ok(true, 'works')
|
||||||
|
fuse.unmount(mnt, function () {
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
tape('mnt point must exist', function (t) {
|
||||||
|
fuse.mount(mnt + '.does-not-exist', {}, function (err) {
|
||||||
|
t.ok(err, 'had error')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
tape('mnt point must be directory', function (t) {
|
||||||
|
fuse.mount(__filename, {}, function (err) {
|
||||||
|
t.ok(err, 'had error')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
64
test/read.js
Normal file
64
test/read.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
const tape = require('tape')
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
const concat = require('concat-stream')
|
||||||
|
|
||||||
|
const Fuse = require('../')
|
||||||
|
const mnt = require('./fixtures/mnt')
|
||||||
|
const stat = require('./fixtures/stat')
|
||||||
|
|
||||||
|
tape('read', function (t) {
|
||||||
|
var ops = {
|
||||||
|
force: true,
|
||||||
|
readdir: function (path, cb) {
|
||||||
|
if (path === '/') return cb(null, ['test'])
|
||||||
|
return cb(fuse.ENOENT)
|
||||||
|
},
|
||||||
|
getattr: function (path, cb) {
|
||||||
|
if (path === '/') return cb(null, stat({ mode: 'dir', size: 4096 }))
|
||||||
|
if (path === '/test') return cb(null, stat({ mode: 'file', size: 11 }))
|
||||||
|
return cb(fuse.ENOENT)
|
||||||
|
},
|
||||||
|
open: function (path, flags, cb) {
|
||||||
|
cb(0, 42)
|
||||||
|
},
|
||||||
|
release: function (path, fd, cb) {
|
||||||
|
t.same(fd, 42, 'fd was passed to release')
|
||||||
|
cb(0)
|
||||||
|
},
|
||||||
|
read: function (path, fd, buf, len, pos, cb) {
|
||||||
|
var str = 'hello world'.slice(pos, pos + len)
|
||||||
|
if (!str) return cb(0)
|
||||||
|
buf.write(str)
|
||||||
|
return cb(str.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fuse = new Fuse(mnt, ops, { debug: true })
|
||||||
|
|
||||||
|
fuse.mount(function (err) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
|
||||||
|
fs.readFile(path.join(mnt, 'test'), function (err, buf) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
t.same(buf, new Buffer('hello world'), 'read file')
|
||||||
|
|
||||||
|
fs.readFile(path.join(mnt, 'test'), function (err, buf) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
t.same(buf, new Buffer('hello world'), 'read file again')
|
||||||
|
|
||||||
|
fs.createReadStream(path.join(mnt, 'test'), { start: 0, end: 4 }).pipe(concat(function (buf) {
|
||||||
|
t.same(buf, new Buffer('hello'), 'partial read file')
|
||||||
|
|
||||||
|
fs.createReadStream(path.join(mnt, 'test'), { start: 6, end: 10 }).pipe(concat(function (buf) {
|
||||||
|
t.same(buf, new Buffer('world'), 'partial read file + start offset')
|
||||||
|
|
||||||
|
fuse.unmount(mnt, function () {
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
54
test/write.js
Normal file
54
test/write.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
var mnt = require('./fixtures/mnt')
|
||||||
|
var stat = require('./fixtures/stat')
|
||||||
|
var fuse = require('../')
|
||||||
|
var tape = require('tape')
|
||||||
|
var fs = require('fs')
|
||||||
|
var path = require('path')
|
||||||
|
|
||||||
|
tape('write', function (t) {
|
||||||
|
var created = false
|
||||||
|
var data = new Buffer(1024)
|
||||||
|
var size = 0
|
||||||
|
|
||||||
|
var ops = {
|
||||||
|
force: true,
|
||||||
|
readdir: function (path, cb) {
|
||||||
|
if (path === '/') return cb(null, created ? ['hello'] : [])
|
||||||
|
return cb(fuse.ENOENT)
|
||||||
|
},
|
||||||
|
truncate: function (path, size, cb) {
|
||||||
|
cb(0)
|
||||||
|
},
|
||||||
|
getattr: function (path, cb) {
|
||||||
|
if (path === '/') return cb(null, stat({ mode: 'dir', size: 4096 }))
|
||||||
|
if (path === '/hello' && created) return cb(null, stat({ mode: 'file', size: size }))
|
||||||
|
return cb(fuse.ENOENT)
|
||||||
|
},
|
||||||
|
create: function (path, flags, cb) {
|
||||||
|
t.ok(!created, 'file not created yet')
|
||||||
|
created = true
|
||||||
|
cb(0, 42)
|
||||||
|
},
|
||||||
|
release: function (path, fd, cb) {
|
||||||
|
cb(0)
|
||||||
|
},
|
||||||
|
write: function (path, fd, buf, len, pos, cb) {
|
||||||
|
buf.slice(0, len).copy(data, pos)
|
||||||
|
size = Math.max(pos + len, size)
|
||||||
|
cb(buf.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fuse.mount(mnt, ops, function (err) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
|
||||||
|
fs.writeFile(path.join(mnt, 'hello'), 'hello world', function (err) {
|
||||||
|
t.error(err, 'no error')
|
||||||
|
t.same(data.slice(0, size), new Buffer('hello world'), 'data was written')
|
||||||
|
|
||||||
|
fuse.unmount(mnt, function () {
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user