embark/lib/core/fs.js

239 lines
5.3 KiB
JavaScript

const parseJson = require('parse-json');
const os = require('os');
let path = require('path');
let fs = require('fs-extra');
let utils = require('../utils/utils.js');
require('colors');
// set PWD to process.cwd() since Windows doesn't have a value for PWD
if (!process.env.PWD) {
process.env.PWD = process.cwd();
}
// set the anchor for embark's fs.dappPath()
if (!process.env.DAPP_PATH) {
process.env.DAPP_PATH = process.env.PWD;
}
// set the anchor for embark's fs.embarkPath()
if (!process.env.EMBARK_PATH) {
process.env.EMBARK_PATH = utils.joinPath(__dirname, '..');
}
// set the anchor for embark's fs.pkgPath()
if (!process.env.PKG_PATH) {
process.env.PKG_PATH = process.env.PWD;
}
const pathConfigs = {
DAPP_PATH: process.env.DAPP_PATH,
EMBARK_PATH: process.env.EMBARK_PATH,
PKG_PATH: process.env.PKG_PATH
};
function restrictPath(receiver, binding, count, args) {
const dapp = dappPath();
const embark = embarkPath();
const pkg = pkgPath();
const allowedRoots = [
dapp,
embark,
pkg,
os.tmpdir()
];
let allInsideRestricted = true;
for(let i = 0; i < count; i++) {
let resolved = path.resolve(dapp, args[i]);
allInsideRestricted = allowedRoots.some(p => { return resolved.indexOf(p) === 0; });
if(!allInsideRestricted) break;
}
if(allInsideRestricted) return receiver.apply(binding, args);
throw new Error('EPERM: Operation not permitted');
}
function mkdirpSync() {
return restrictPath(fs.mkdirpSync, fs.mkdirpSync, 1, arguments);
}
function mkdirp() {
return restrictPath(fs.mkdirp, fs.mkdirp, 1, arguments);
}
function readdir() {
return restrictPath(fs.readdir, fs.readdir, 1, arguments);
}
function stat() {
return restrictPath(fs.stat, fs.stat, 1, arguments);
}
function remove() {
return restrictPath(fs.remove, fs.remove, 1, arguments);
}
function copy() {
return restrictPath(fs.copy, fs.copy, 2, arguments);
}
function copySync() {
return restrictPath(fs.copySync, fs.copySync, 2, arguments);
}
function move(){
return restrictPath(fs.move, fs.move, 2, arguments);
}
function moveSync() {
return restrictPath(fs.moveSync, fs.moveSync, 2, arguments);
}
function appendFileSync() {
return restrictPath(fs.appendFileSync, fs.writeFileSync, 1, arguments);
}
function writeFile() {
return restrictPath(fs.writeFile, fs.writeFileSync, 1, arguments);
}
function writeFileSync() {
return restrictPath(fs.writeFileSync, fs.writeFileSync, 1, arguments);
}
function readFile() {
return restrictPath(fs.readFile, fs.readFile, 1, arguments);
}
function readFileSync() {
return restrictPath(fs.readFileSync, fs.readFileSync, 1, arguments);
}
function readdirSync() {
return restrictPath(fs.readdirSync, fs.readdirSync, 1, arguments);
}
function statSync() {
return restrictPath(fs.statSync, fs.statSync, 1, arguments);
}
function readJSONSync() {
let content = readFileSync.apply(readFileSync, arguments);
try {
return parseJson(content);
} catch(e) {
console.error("error: ".red + arguments[0].green.underline + " " + e.message.green);
process.exit(0);
}
}
function writeJSONSync() {
return restrictPath(fs.writeJSONSync, fs.writeJSONSync, 1, arguments);
}
function writeJson() {
return restrictPath(fs.writeJson, fs.writeJson, 1, arguments);
}
function existsSync() {
return restrictPath(fs.existsSync, fs.existsSync, 1, arguments);
}
function access() {
return restrictPath(fs.access, fs.access, 1, arguments);
}
function removeSync() {
return restrictPath(fs.removeSync, fs.removeSync, 1, arguments);
}
function anchoredPath(envAnchor, ...args) {
let anchor = pathConfigs[envAnchor];
if (!pathConfigs[envAnchor]) {
console.error(`process.env.${envAnchor} was not set`.bold.red);
process.exit(1);
}
return utils.joinPath(anchor, ...args);
}
function embarkPath() {
return anchoredPath('EMBARK_PATH', ...arguments);
}
function dappPath() {
return anchoredPath('DAPP_PATH', ...arguments);
}
function pkgPath() {
return anchoredPath('PKG_PATH', ...arguments);
}
function createWriteStream() {
return restrictPath(fs.createWriteStream, fs.createWriteStream, 1, arguments);
}
function tmpDir() {
let os = require('os');
return utils.joinPath(os.tmpdir(), ...arguments);
}
function copyPreserve(sourceFilePath, targetFilePath) {
const implementation = (sourceFilePath, targetFilePath) => {
const path = require('path');
let ext = 1;
let preserved = targetFilePath;
while (fs.existsSync(preserved)) {
let extname = path.extname(targetFilePath);
preserved = utils.joinPath(
path.dirname(targetFilePath),
`${path.basename(targetFilePath, extname)}.${ext}${extname}`
);
ext++;
}
if (preserved !== targetFilePath) {
fs.copySync(targetFilePath, preserved);
}
fs.copySync(sourceFilePath, targetFilePath);
};
return restrictPath(implementation, implementation, 2, [sourceFilePath, targetFilePath]);
}
function outputFileSync(){
return restrictPath(fs.outputFileSync, fs.outputFile, 1, arguments);
}
module.exports = {
access,
appendFileSync,
copy,
copySync,
createWriteStream,
embarkPath,
existsSync,
mkdirp,
mkdirpSync,
move,
moveSync,
outputFileSync,
readFile,
readFileSync,
readJSONSync,
readdir,
readdirSync,
remove,
removeSync,
stat,
statSync,
tmpDir,
writeFile,
writeFileSync,
writeJSONSync,
copyPreserve,
dappPath,
pkgPath,
writeJson
};