domotz-remote-pawn
Version:
Domotz Agent
275 lines (255 loc) • 9.19 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2016 Domotz Ltd
*
* Domotz Agent is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Domotz Agent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>.
*
* Created by Iacopo Papalini <ipapalini@domotz.com> on 16/06/15.
*/
var os = require('os');
var factory = function (fs, q) {
function rename(src, dst, async) {
if (async) {
throw new Error('Not Implemented');
} else {
fs.renameSync(src, dst);
}
}
function readFile(fileName, parse, async) {
console.info('FILE - (%s): %synchronous reading', fileName, async ? 'As' : 'S');
var content;
if (async) {
var deferred = q.defer();
fs.readFile(fileName, function (err, data) {
if (err) {
deferred.reject(err);
} else {
data = data.toString('utf8');
data = parse ? parse(data) : data;
deferred.resolve(data);
}
});
return deferred.promise;
} else {
try {
content = fs.readFileSync(fileName).toString('utf8');
if (parse) {
content = parse(content);
}
} catch (e) {
console.info('FILE - (%s): Failure in reading --> %s', fileName, e.message);
content = undefined;
}
}
return content;
}
function writeFileSafe(fileName, data, async) {
console.info('FILE - (%s): %synchronous safe writing', fileName, async ? 'As' : 'S');
if (async) {
throw new Error('Not Implemented');
} else {
try {
var filePrefix = '.tmp-write';
fs.writeFileSync(fileName + filePrefix, data);
fs.renameSync(fileName + filePrefix, fileName);
} catch (e) {
console.warn('FILE - (%s): Failure in safe writing --> %s', fileName, e.message);
}
}
}
function writeFile(fileName, data, async) {
console.info('FILE - (%s): %synchronous writing', fileName, async ? 'As' : 'S');
if (async) {
var deferred = q.defer();
fs.writeFile(fileName, data, function (err) {
if (err) {
deferred.reject(err);
} else {
deferred.resolve();
}
});
return deferred.promise;
} else {
try {
fs.writeFileSync(fileName, data);
} catch (e) {
console.warn('FILE - (%s): Failure in safe writing --> %s', fileName, e.message);
}
}
}
function appendFile(fileName, data, async) {
console.info('FILE - (%s): Appending %s bytes', fileName, data.length);
if (async) {
var deferred = q.defer();
fs.appendFile(fileName, data, function (err) {
if (err) {
deferred.reject(err);
} else {
deferred.resolve();
}
});
return deferred.promise;
} else {
try {
fs.appendFileSync(fileName, data);
} catch (e) {
console.warn('FILE - (%s): Failure in appending --> %s', fileName, e.message);
}
}
}
function replaceInFile(fileName, replacements) {
console.info('FILE - (%s): Patching', fileName);
var data = fs.readFileSync(fileName, 'utf-8');
replacements.forEach(function (replace) {
var key = replace[0];
var regExp = new RegExp('^' + key + '=.*$', 'm');
if (!regExp.test(data)) {
console.warn('FILE - (%s): No match found for regexp: %s', fileName, regExp);
} else {
var value = String(replace[1]);
console.info('FILE - (%s): Replacing %s with %s in file ', fileName, key, value);
data = data.replace(regExp, key + '=' + value);
}
});
fs.writeFileSync(fileName, data);
}
function createFile(path, content, options) {
console.info('Creating file - options: %s', options);
console.info('Creating file - path: %s', path);
try {
var mode = options.mode;
delete options.mode;
fs.writeFileSync(path, '');
console.info('Creating file - created at path %s', path);
var stream = fs.createWriteStream(path, options);
content.split('\n').forEach(function (row) {
stream.write(row + os.EOL);
console.info('FILE - %s', row);
});
stream.end();
console.info('Creating file - written');
fs.chmodSync(path, mode);
console.info('Creating file - %s mode set', mode);
} catch (e) {
console.error(e.stack);
console.warn('FILE - (%s): Failure in creating', path);
return false;
}
return true;
}
function deleteFile(fileName, async) {
console.info('FILE - (%s): Removing', fileName);
if (async) {
var deferred = q.defer();
fs.unlink(fileName, function (err) {
if (err) {
deferred.reject(err);
} else {
deferred.resolve();
}
});
return deferred.promise;
} else {
try {
fs.unlinkSync(fileName);
} catch (e) {
console.warn('FILE - (%s): Failure in removing', fileName);
}
}
}
function getFileStats(fileName) {
var stats;
try {
stats = fs.statSync(fileName);
} catch (err) {
/**
* stat is an operation used also to check the existence of a file.
* A failure is note a real issue, so the "DEBUG" level
*/
console.info('FILE - Recover stats for ' + fileName + '. ' + 'Error Code: ' + err.code);
return undefined;
}
return stats;
}
function getSize(fileName) {
var stats = getFileStats(fileName);
return stats ? stats.size : 0;
}
// http://www.geedew.com/remove-a-directory-that-is-not-empty-in-nodejs/
function listDir(path, options, async) {
if (typeof options === 'boolean') {
async = options;
}
if (async) {
var deferred = q.defer();
fs.readdir(path, options, function (err, out) {
if (err) {
deferred.reject(err);
} else {
deferred.resolve(out);
}
});
return deferred.promise;
} else {
return fs.readdirSync(path, options);
}
}
function copyFileAsync(source, destination) {
'use strict';
return readFile(source, null, true).then(function (data) {
return writeFile(destination, data, true);
});
}
function touchFile(fileName) {
'use strict';
fs.closeSync(fs.openSync(fileName, 'a'));
var defer = q.defer();
defer.resolve();
return defer.promise;
}
function isExecutableAvailableInPATH(executableName) {
var envPath = process.env.PATH;
if (!envPath) {
return false;
}
var envPaths = envPath.split(':');
var result = envPaths.some(function (directory) {
var files = [];
try {
files = fs.readdirSync(directory);
} catch (e) {
console.warn('FILE - directory %s unavailable', directory);
}
return files.indexOf(executableName) >= 0;
});
console.info('FILE - checking if %s executable is available in PATH, result: %s', executableName, result);
return result;
}
return {
rename: rename,
readFile: readFile,
writeFile: writeFile,
writeFileSafe: writeFileSafe,
appendFile: appendFile,
createFile: createFile,
deleteFile: deleteFile,
getFileStats: getFileStats,
replaceInFile: replaceInFile,
getSize: getSize,
listDir: listDir,
copyFileAsync: copyFileAsync,
touchFile: touchFile,
isExecutableAvailableInPATH: isExecutableAvailableInPATH,
};
};
module.exports.factory = factory;