/ lib / core / fs.js
fs.js
  1  const parseJson = require('parse-json');
  2  const os = require('os');
  3  let path = require('path');
  4  let fs = require('fs-extra');
  5  let utils = require('../utils/utils.js');
  6  require('colors');
  7  
  8  const pathConfigs = {
  9    DAPP_PATH: process.env.DAPP_PATH,
 10    EMBARK_PATH: process.env.EMBARK_PATH
 11  };
 12  
 13  function restrictPath(receiver, binding, count, args) {
 14    const dapp = dappPath();
 15    const embark = embarkPath();
 16  
 17    const allowedRoots = [
 18      dapp,
 19      embark,
 20      os.tmpdir()
 21    ];
 22  
 23    let allInsideRestricted = true;
 24  
 25    for(let i = 0; i < count; i++) {
 26      let resolved = path.resolve(dapp, args[i]);
 27      allInsideRestricted = allowedRoots.some(p => { return resolved.indexOf(p) === 0; });
 28      if(!allInsideRestricted) break;
 29    }
 30  
 31    if(allInsideRestricted) return receiver.apply(binding, args);
 32    throw new Error('EPERM: Operation not permitted');
 33  }
 34  
 35  function mkdirpSync() {
 36    return restrictPath(fs.mkdirpSync, fs.mkdirpSync, 1, arguments);
 37  }
 38  
 39  function mkdirp() {
 40    return restrictPath(fs.mkdirp, fs.mkdirp, 1, arguments);
 41  }
 42  
 43  function readdir() {
 44    return restrictPath(fs.readdir, fs.readdir, 1, arguments);
 45  }
 46  
 47  function stat() {
 48    return restrictPath(fs.stat, fs.stat, 1, arguments);
 49  }
 50  
 51  function remove() {
 52    return restrictPath(fs.remove, fs.remove, 1, arguments);
 53  }
 54  
 55  function copy() {
 56    return restrictPath(fs.copy, fs.copy, 2, arguments);
 57  }
 58  
 59  function copySync() {
 60    return restrictPath(fs.copySync, fs.copySync, 2, arguments);
 61  }
 62  
 63  function move(){
 64    return restrictPath(fs.move, fs.move, 2, arguments);
 65  }
 66  
 67  function moveSync() {
 68    return restrictPath(fs.moveSync, fs.moveSync, 2, arguments);
 69  }
 70  
 71  function appendFileSync() {
 72    return restrictPath(fs.appendFileSync, fs.writeFileSync, 1, arguments);
 73  }
 74  
 75  function writeFile() {
 76    return restrictPath(fs.writeFile, fs.writeFileSync, 1, arguments);
 77  }
 78  
 79  function writeFileSync() {
 80    return restrictPath(fs.writeFileSync, fs.writeFileSync, 1, arguments);
 81  }
 82  
 83  function readFile() {
 84    return restrictPath(fs.readFile, fs.readFile, 1, arguments);
 85  }
 86  
 87  function readFileSync() {
 88    return restrictPath(fs.readFileSync, fs.readFileSync, 1, arguments);
 89  }
 90  
 91  function readdirSync() {
 92    return restrictPath(fs.readdirSync, fs.readdirSync, 1, arguments);
 93  }
 94  
 95  function statSync() {
 96    return restrictPath(fs.statSync, fs.statSync, 1, arguments);
 97  }
 98  
 99  function readJSONSync() {
100    let content = readFileSync.apply(readFileSync, arguments);
101    try {
102      return parseJson(content);
103    } catch(e) {
104      console.error("error: ".red + arguments[0].green.underline + " " + e.message.green);
105      process.exit(0);
106    }
107  }
108  
109  function writeJSONSync() {
110    return restrictPath(fs.writeJSONSync, fs.writeJSONSync, 1, arguments);
111  }
112  
113  function writeJson() {
114    return restrictPath(fs.writeJson, fs.writeJson, 1, arguments);
115  }
116  
117  function existsSync() {
118    return restrictPath(fs.existsSync, fs.existsSync, 1, arguments);
119  }
120  
121  function access() {
122    return restrictPath(fs.access, fs.access, 1, arguments);
123  }
124  
125  function removeSync() {
126    return restrictPath(fs.removeSync, fs.removeSync, 1, arguments);
127  }
128  
129  function anchoredPath(envAnchor, ...args) {
130    let anchor = pathConfigs[envAnchor];
131    if (!pathConfigs[envAnchor]) {
132      console.error(`process.env.${envAnchor} was not set`.bold.red);
133      process.exit(1);
134    }
135    return utils.joinPath(anchor, ...args);
136  }
137  
138  function embarkPath() {
139    return anchoredPath('EMBARK_PATH', ...arguments);
140  }
141  
142  function dappPath() {
143    return anchoredPath('DAPP_PATH', ...arguments);
144  }
145  
146  function pkgPath() {
147    return anchoredPath('PKG_PATH', ...arguments);
148  }
149  
150  function createWriteStream() {
151    return restrictPath(fs.createWriteStream, fs.createWriteStream, 1, arguments);
152  }
153  
154  function tmpDir() {
155    let os = require('os');
156    return utils.joinPath(os.tmpdir(), ...arguments);
157  }
158  
159  function copyPreserve(sourceFilePath, targetFilePath) {
160    const path = require('path');
161    let ext = 1;
162    let preserved = targetFilePath;
163    while (fs.existsSync(preserved)) {
164      let extname = path.extname(targetFilePath);
165      preserved = utils.joinPath(
166        path.dirname(targetFilePath),
167        `${path.basename(targetFilePath, extname)}.${ext}${extname}`
168      );
169      ext++;
170    }
171    if (preserved !== targetFilePath) {
172      fs.copySync(targetFilePath, preserved);
173    }
174    fs.copySync(sourceFilePath, targetFilePath);
175  }
176  
177  function outputFileSync(){
178    return fs.outputFileSync.apply(fs.outputFile, arguments);
179  }
180  
181  module.exports = {
182    access,
183    appendFileSync,
184    copy,
185    copySync,
186    createWriteStream,
187    embarkPath,
188    existsSync,
189    mkdirp,
190    mkdirpSync,
191    move,
192    moveSync,
193    outputFileSync,
194    readFile,
195    readFileSync,
196    readJSONSync,
197    readdir,
198    readdirSync,
199    remove,
200    removeSync,
201    stat,
202    statSync,
203    tmpDir,
204    writeFile,
205    writeFileSync,
206    writeJSONSync,
207    copyPreserve,
208    dappPath,
209    pkgPath,
210    outputFileSync,
211    writeJson
212  };