You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fuse-friends_fuse-native/index.js

213 lines
5.6 KiB

5 years ago
const binding = require('node-gyp-build')(__dirname)
5 years ago
const Opcodes = new Map([
[ 'init', 0 ],
[ 'error', 1 ],
[ 'access', 2 ],
[ 'statfs', 3 ],
[ 'fgetattr', 4 ],
[ 'getattr', 5 ],
[ 'flush', 6 ],
[ 'fsync', 7 ],
[ 'fsyncdir', 8 ],
[ 'readdir', 9 ],
[ 'truncate', 10 ],
[ 'ftruncate', 11 ],
[ 'utimens', 12 ],
[ 'readlink', 13 ],
[ 'chown', 14 ],
[ 'chmod', 15 ],
[ 'mknod', 16 ],
[ 'setxattr', 17 ],
[ 'getxattr', 18 ],
[ 'listxattr', 19 ],
[ 'removexattr', 20 ],
[ 'open', 21 ],
[ 'opendir', 22 ],
[ 'read', 23 ],
[ 'write', 24 ],
[ 'release', 25 ],
[ 'releasedir', 26 ],
[ 'create', 27 ],
[ 'unlink', 28 ],
[ 'rename', 29 ],
[ 'link', 30 ],
[ 'symlink', 31 ],
[ 'mkdir', 32 ],
[ 'rmdir', 33 ],
[ 'destroy', 34 ]
])
5 years ago
class Fuse {
5 years ago
constructor (mnt, ops, opts = {}) {
this.opts = opts
this.ops = ops
this.mnt = mnt
5 years ago
this._thread = Buffer.alloc(binding.sizeof_fuse_thread_t)
5 years ago
const implemented = []
if (ops) {
for (const [name, code] of Opcodes) {
if (ops[name]) implemented.push(code)
}
}
this._implemented = new Set(implemented)
// Used to determine if the user-defined callback needs to be nextTick'd.
this._sync = true
}
_signal (signalFunc, args) {
/*
if (this._sync) process.nextTick(() => signalFunc.apply(null, args))
else signalFunc.apply(null, args)
*/
process.nextTick(() => signalFunc.apply(null, args))
}
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)
5 years ago
}
5 years ago
unmount () {
binding.fuse_native_unmount(this.mnt)
5 years ago
}
5 years ago
on_symlink (handle, op, path, target) {
const signalFunc = binding.fuse_native_signal_path.bind(binding)
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1])
}
on_readdir (handle, op, path) {
5 years ago
console.log('IN ONREADDIR')
5 years ago
const signalFunc = binding.fuse_native_signal_readdir.bind(binding)
5 years ago
5 years ago
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1])
5 years ago
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 || []])
})
5 years ago
}
5 years ago
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])
}
5 years ago
on_statfs_op (handle, op, path) {
const signalFunc = binding.fuse_native_signal_statfs.bind(binding)
5 years ago
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1, ...getStatfsArray()])
5 years ago
this.ops.statfs((err, statfs) => {
const arr = getStatfsArray(statfs)
5 years ago
return this._signal(signalFunc, [handle, err, arr])
5 years ago
})
}
5 years ago
on_stat_op (handle, op, path) {
const signalFunc = binding.fuse_native_signal_stat.bind(binding)
5 years ago
if (!this._implemented.has(op)) return this._signal(signalFunc, [handle, -1, getStatArray()])
5 years ago
switch (op) {
case (binding.op_getattr):
this.ops.getattr(path, (err, stat) => {
5 years ago
const arr = getStatArray(stat)
return this._signal(signalFunc, [handle, err, arr])
5 years ago
})
break
default:
5 years ago
return this._signal(signalFunc, [handle, -1, getStatArray()])
5 years ago
}
}
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])
}
}
function getStatfsArray (statfs) {
5 years ago
const ints = new Uint32Array(11)
5 years ago
ints[0] = (statfs && statfs.bsize) || 0
ints[1] = (statfs && statfs.frsize) || 0
ints[2] = (statfs && statfs.blocks) || 0
ints[3] = (statfs && statfs.bfree) || 0
ints[4] = (statfs && statfs.bavail) || 0
ints[5] = (statfs && statfs.files) || 0
ints[6] = (statfs && statfs.ffree) || 0
ints[7] = (statfs && statfs.favail) || 0
ints[8] = (statfs && statfs.fsid) || 0
ints[9] = (statfs && statfs.flag) || 0
ints[10] = (statfs && statfs.namemax) || 0
return ints
5 years ago
}
5 years ago
5 years ago
function setDoubleInt (arr, idx, num) {
arr[idx] = num % 4294967296
arr[idx + 1] = (num - arr[idx]) / 4294967296
}
5 years ago
function getStatArray (stat) {
5 years ago
const ints = new Uint32Array(16)
5 years ago
5 years ago
ints[0] = (stat && stat.mode) || 0
ints[1] = (stat && stat.uid) || 0
ints[2] = (stat && stat.gid) || 0
ints[3] = (stat && stat.size) || 0
ints[4] = (stat && stat.dev) || 0
ints[5] = (stat && stat.nlink) || 1
ints[6] = (stat && stat.ino) || 0
ints[7] = (stat && stat.rdev) || 0
ints[8] = (stat && stat.blksize) || 0
ints[9] = (stat && stat.blocks) || 0
5 years ago
setDoubleInt(ints, 10, (stat && stat.atim) || Date.now())
setDoubleInt(ints, 12, (stat && stat.atim) || Date.now())
setDoubleInt(ints, 14, (stat && stat.atim) || Date.now())
5 years ago
return ints
}
5 years ago
function emptyStat () {
return {
mtime: new Date(),
atime: new Date(),
ctime: new Date(),
nlink: 1,
size: 100,
mode: 16877,
uid: process.getuid ? process.getuid() : 0,
gid: process.getgid ? process.getgid() : 0
}
}
5 years ago
const f = new Fuse('mnt', {
getattr: (path, cb) => {
5 years ago
return cb(0, emptyStat())
},
readdir: (path, cb) => {
if (path === '/') {
return cb(0, ['a', 'b', 'c'], Array(3).fill('a').map(() => emptyStat()))
}
return cb(0, [], [])
5 years ago
}
})
f.mount()
5 years ago
setInterval(() => {
5 years ago
if (global.gc) gc()
5 years ago
}, 1000)
// setTimeout(function () {
// foo = null
// console.log('now!')
// }, 5000)