diff --git a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/index.js b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/index.js index 674b380e6..82c1f8d39 100644 --- a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/index.js +++ b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/index.js @@ -56,8 +56,9 @@ function init(_settings, _runtime) { if (settings.flowFile) { flowsFile = settings.flowFile; - // handle Unix and Windows "C:\" - if ((flowsFile[0] == "/") || (flowsFile[1] == ":")) { + // handle Unix and Windows "C:\" and Windows "\\" for UNC. + if (fspath.isAbsolute(flowsFile)) { + //if (((flowsFile[0] == "\\") && (flowsFile[1] == "\\")) || (flowsFile[0] == "/") || (flowsFile[1] == ":")) { // Absolute path flowsFullPath = flowsFile; } else if (flowsFile.substring(0,2) === "./") { diff --git a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/util.js b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/util.js index 267f8c933..b18c80643 100644 --- a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/util.js +++ b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/util.js @@ -15,6 +15,7 @@ **/ var fs = require('fs-extra'); +var fspath = require('path'); var when = require('when'); var nodeFn = require('when/node/function'); @@ -79,25 +80,31 @@ module.exports = { * the write hits disk. */ writeFile: function(path,content,backupPath) { - if (backupPath) { + if (backupPath) { if (fs.existsSync(path)) { fs.renameSync(path,backupPath); } } return when.promise(function(resolve,reject) { - var stream = fs.createWriteStream(path); - stream.on('open',function(fd) { - stream.write(content,'utf8',function() { - fs.fsync(fd,function(err) { - if (err) { - log.warn(log._("storage.localfilesystem.fsync-fail",{path: path, message: err.toString()})); - } - stream.end(resolve); + fs.ensureDir(fspath.dirname(path), (err)=>{ + if (err) { + reject(err); + return; + } + var stream = fs.createWriteStream(path); + stream.on('open',function(fd) { + stream.write(content,'utf8',function() { + fs.fsync(fd,function(err) { + if (err) { + log.warn(log._("storage.localfilesystem.fsync-fail",{path: path, message: err.toString()})); + } + stream.end(resolve); + }); }); }); - }); - stream.on('error',function(err) { - reject(err); + stream.on('error',function(err) { + reject(err); + }); }); }); }, diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js index 464afa7e0..acfe3db43 100644 --- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js +++ b/test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js @@ -19,6 +19,7 @@ var fs = require('fs-extra'); var path = require('path'); var sinon = require('sinon'); var NR_TEST_UTILS = require("nr-test-utils"); +var process = require("process"); var localfilesystem = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem"); var log = NR_TEST_UTILS.require("@node-red/util").log; @@ -474,4 +475,44 @@ describe('storage/localfilesystem', function() { done(err); }); }); + + it('should handle flow file in random unc path and non-existent subfolder',function(done) { + // only test on win32 + if (process.platform !== 'win32') { + console.log('skipped test as not win32'); + done(); + return; + } + + // get a real windows path + var flowFile = path.win32.resolve(userDir+'/some/random/path'); + var rootdir = path.win32.resolve(userDir+'/some'); + // make it into a local UNC path + flowFile = flowFile.replace('C:\\', '\\\\localhost\\c$\\'); + localfilesystem.init({userDir:userDir, flowFile:flowFile}, mockRuntime).then(function() { + fs.existsSync(flowFile).should.be.false(); + localfilesystem.saveFlows(testFlow).then(function() { + fs.existsSync(flowFile).should.be.true(); + localfilesystem.getFlows().then(function(flows) { + flows.should.eql(testFlow); + // cleanup + fs.removeSync(rootdir); + done(); + }).catch(function(err) { + // cleanup + fs.removeSync(rootdir); + done(err); + }); + }).catch(function(err) { + // cleanup + fs.removeSync(rootdir); + done(err); + }); + }).catch(function(err) { + // cleanup + fs.removeSync(rootdir); + done(err); + }); + }); + });