diff --git a/bin/dusk.js b/bin/dusk.js index 31a81ae..4e41b72 100755 --- a/bin/dusk.js +++ b/bin/dusk.js @@ -71,6 +71,7 @@ const { colors, animals } = require('unique-names-generator'); +const fuse = require('./fuse.js'); program.version(dusk.version.software); @@ -116,9 +117,8 @@ program.option('--tray', program.option('--install', 'writes linux .desktop entry to $HOME/.local/share/applications'); -program.option('--fuse ', - 'mount the virtual filesystem to the supplied path', - path.join(homedir(), 'Desktop/dusk.virt')); +program.option('--fuse [mountpath]', + 'mount the virtual filesystem to the supplied path'); program.option('--rpc [method] [params]', 'send a command to the daemon'); @@ -1379,6 +1379,10 @@ function exitGracefully() { process.removeListener('exit', exitGracefully); + if (program.fuse) { + Fuse.unmount(program.fuse, console.log); + } + if (controller && parseInt(config.ControlSockEnabled)) { controller.server.close(); } @@ -1476,6 +1480,18 @@ async function initDusk() { config.NetworkBootstrapNodes = config.NetworkBootstrapNodes.trim().split(); } + if (program.fuse) { + program.fuse === true + ? path.join(tmpdir(), 'dusk.vfs') + : program.fuse; + logger.info('mounting fuse virtual filesystem'); + await fuse(program.fuse, program.datadir); + logger.info(`mounted to path ${mnt}`); + if (program.gui) { + Dialog.notify('Virtual filesystem mounted.\n' + mnt); + } + } + async function joinNetwork(callback) { let peers = config.NetworkBootstrapNodes; const seedsdir = path.join(program.datadir, 'seeds'); diff --git a/bin/fuse.js b/bin/fuse.js index 5145054..9510927 100644 --- a/bin/fuse.js +++ b/bin/fuse.js @@ -8,27 +8,42 @@ const { join, extname } = require('node:path'); function _init(mnt, datadir) { return new Promise(async (resolve, reject) => { const ops = { - readdir: function (path, cb) { - if (path === '/') { - return fs.readdir(join(datadir, 'dusk.meta'), (err, list) => { - if (err) { - return cb(1); + readdir: function(path, cb) { + fs.readdir(join(datadir, 'dusk.meta', path), (err, list) => { + if (err) { + return cb(1); + } + cb(0, list.filter(f => { + return fs.statSync(join(datadir, 'dusk.meta', f)).isDirectory(); + }).map(f => { + if (extname(f) === '.duskbundle') { + return f.split('.duskbundle')[0]; + } else { + return f; } - cb(0, list.filter(f => extname(f) === '.duskbundle')); - }); - } - return cb(Fuse.ENOENT) + })); + }); }, getattr: function (path, cb) { - if (path === '/') { - return fs.stat(datadir, (err, stat) => { - if (err) { - return cb(1); - } - cb(0, stat); - }) + const realPath = join(datadir, 'dusk.meta', path); + const isBundle = fs.existsSync(`${realPath}.duskbundle`); + + let statPath = realPath; + + if (isBundle) { + statPath = join( + `${realPath}.duskbundle`, fs.readdirSync(`${realPath}.duskbundle`)[0]); + } - return cb(Fuse.ENOENT) + + return fs.stat(statPath, (err, stat) => { + if (err) { + return cb(1); + } + cb(0, isBundle + ? { ...stat } + : { ...stat }); + }); }, open: function (path, flags, cb) { return cb(0, 161); @@ -45,7 +60,7 @@ function _init(mnt, datadir) { cb(Fuse.ENOENT); }, unlink: function(path, cb) { - fs.unlink(join(datadir, 'dusk.meta', path), err => cb(err ? 1 : 0)); + fs.unlink(join(datadir, 'dusk.meta', `${path}.duskbundle`), err => cb(err ? 1 : 0)); }, mkdir: function(path, mode, cb) { fs.mkdir(join(datadir, 'dusk.meta', path), err => cb(err ? 1 : 0)); diff --git a/bin/tray.js b/bin/tray.js index fcb8538..a58c5f5 100644 --- a/bin/tray.js +++ b/bin/tray.js @@ -47,7 +47,7 @@ function _init(rpc, program, config, exitGracefully) { const FUSE_STATUS_NOT_MOUNTED = { type: 'update-item', - seq_id: 2, + seq_id: 3, item: { title: '🗂 Mount virtual folders', enabled: true, @@ -56,16 +56,16 @@ function _init(rpc, program, config, exitGracefully) { }; const FUSE_STATUS_MOUNTED = { type: 'update-item', - seq_id: 2, + seq_id: 3, item: { - title: '🗂 Unmount virtual folders', - enabled: true, + title: '🗂 Virtual folders mounted', + enabled: false, checked: false } }; const FUSE_STATUS_MOUNTING = { type: 'update-item', - seq_id: 2, + seq_id: 3, item: { title: '🗂 Mounting virtual folders...', enabled: false, @@ -121,7 +121,7 @@ function _init(rpc, program, config, exitGracefully) { debug: false, copyDir: false }); - + tray.onClick(action => { switch (action.seq_id) { case 0: // Status indicator @@ -209,13 +209,15 @@ licensed under the agpl 3 } async function toggleMountVirtualFolders(action) { - const mnt = path.join(tmpdir(), `dusk.vfs.${Date.now()}`); + const mnt = path.join(tmpdir(), 'dusk.vfs.2'); + tray.sendAction(FUSE_STATUS_MOUNTING); try { - mkdirp.sync(mnt); await fuse(mnt, program.datadir); } catch (e) { + tray.sendAction(FUSE_STATUS_NOT_MOUNTED) return Dialog.info(e, 'Sorry', 'error'); } + tray.sendAction(FUSE_STATUS_MOUNTED) Dialog.notify('Virtual filesystem mounted.\n' + mnt); spawn('xdg-open', [mnt], { detached: true }); }