11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst fs = require('fs');
41cb0ef41Sopenharmony_ciconst path = require('path');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciif (process.argv[2] === 'wasi-child') {
71cb0ef41Sopenharmony_ci  common.expectWarning('ExperimentalWarning',
81cb0ef41Sopenharmony_ci                       'WASI is an experimental feature and might change at any time');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci  const { WASI } = require('wasi');
111cb0ef41Sopenharmony_ci  const wasmDir = path.join(__dirname, 'wasm');
121cb0ef41Sopenharmony_ci  const wasi = new WASI({
131cb0ef41Sopenharmony_ci    args: [],
141cb0ef41Sopenharmony_ci    env: process.env,
151cb0ef41Sopenharmony_ci    preopens: {
161cb0ef41Sopenharmony_ci      '/sandbox': process.argv[4],
171cb0ef41Sopenharmony_ci      '/tmp': process.argv[5],
181cb0ef41Sopenharmony_ci    },
191cb0ef41Sopenharmony_ci  });
201cb0ef41Sopenharmony_ci  const importObject = { wasi_snapshot_preview1: wasi.wasiImport };
211cb0ef41Sopenharmony_ci  const modulePath = path.join(wasmDir, `${process.argv[3]}.wasm`);
221cb0ef41Sopenharmony_ci  const buffer = fs.readFileSync(modulePath);
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci  (async () => {
251cb0ef41Sopenharmony_ci    const { instance } = await WebAssembly.instantiate(buffer, importObject);
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci    wasi.start(instance);
281cb0ef41Sopenharmony_ci  })().then(common.mustCall());
291cb0ef41Sopenharmony_ci} else {
301cb0ef41Sopenharmony_ci  if (!common.canCreateSymLink()) {
311cb0ef41Sopenharmony_ci    common.skip('insufficient privileges');
321cb0ef41Sopenharmony_ci  }
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  const assert = require('assert');
351cb0ef41Sopenharmony_ci  const cp = require('child_process');
361cb0ef41Sopenharmony_ci  const tmpdir = require('../common/tmpdir');
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  // Setup the sandbox environment.
391cb0ef41Sopenharmony_ci  tmpdir.refresh();
401cb0ef41Sopenharmony_ci  const sandbox = path.join(tmpdir.path, 'sandbox');
411cb0ef41Sopenharmony_ci  const sandboxedFile = path.join(sandbox, 'input.txt');
421cb0ef41Sopenharmony_ci  const externalFile = path.join(tmpdir.path, 'outside.txt');
431cb0ef41Sopenharmony_ci  const sandboxedDir = path.join(sandbox, 'subdir');
441cb0ef41Sopenharmony_ci  const sandboxedSymlink = path.join(sandboxedDir, 'input_link.txt');
451cb0ef41Sopenharmony_ci  const escapingSymlink = path.join(sandboxedDir, 'outside.txt');
461cb0ef41Sopenharmony_ci  const loopSymlink1 = path.join(sandboxedDir, 'loop1');
471cb0ef41Sopenharmony_ci  const loopSymlink2 = path.join(sandboxedDir, 'loop2');
481cb0ef41Sopenharmony_ci  const sandboxedTmp = path.join(tmpdir.path, 'tmp');
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  fs.mkdirSync(sandbox);
511cb0ef41Sopenharmony_ci  fs.mkdirSync(sandboxedDir);
521cb0ef41Sopenharmony_ci  fs.mkdirSync(sandboxedTmp);
531cb0ef41Sopenharmony_ci  fs.writeFileSync(sandboxedFile, 'hello from input.txt', 'utf8');
541cb0ef41Sopenharmony_ci  fs.writeFileSync(externalFile, 'this should be inaccessible', 'utf8');
551cb0ef41Sopenharmony_ci  fs.symlinkSync(path.join('.', 'input.txt'), sandboxedSymlink, 'file');
561cb0ef41Sopenharmony_ci  fs.symlinkSync(path.join('..', 'outside.txt'), escapingSymlink, 'file');
571cb0ef41Sopenharmony_ci  fs.symlinkSync(path.join('subdir', 'loop2'),
581cb0ef41Sopenharmony_ci                 loopSymlink1, 'file');
591cb0ef41Sopenharmony_ci  fs.symlinkSync(path.join('subdir', 'loop1'),
601cb0ef41Sopenharmony_ci                 loopSymlink2, 'file');
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  function runWASI(options) {
631cb0ef41Sopenharmony_ci    console.log('executing', options.test);
641cb0ef41Sopenharmony_ci    const opts = { env: { ...process.env, NODE_DEBUG_NATIVE: 'wasi' } };
651cb0ef41Sopenharmony_ci    const child = cp.spawnSync(process.execPath, [
661cb0ef41Sopenharmony_ci      __filename,
671cb0ef41Sopenharmony_ci      'wasi-child',
681cb0ef41Sopenharmony_ci      options.test,
691cb0ef41Sopenharmony_ci      sandbox,
701cb0ef41Sopenharmony_ci      sandboxedTmp,
711cb0ef41Sopenharmony_ci    ], opts);
721cb0ef41Sopenharmony_ci    console.log(child.stderr.toString());
731cb0ef41Sopenharmony_ci    assert.strictEqual(child.status, 0);
741cb0ef41Sopenharmony_ci    assert.strictEqual(child.signal, null);
751cb0ef41Sopenharmony_ci    assert.strictEqual(child.stdout.toString(), options.stdout || '');
761cb0ef41Sopenharmony_ci  }
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  runWASI({ test: 'create_symlink', stdout: 'hello from input.txt' });
791cb0ef41Sopenharmony_ci  runWASI({ test: 'follow_symlink', stdout: 'hello from input.txt' });
801cb0ef41Sopenharmony_ci  runWASI({ test: 'link' });
811cb0ef41Sopenharmony_ci  runWASI({ test: 'symlink_escape' });
821cb0ef41Sopenharmony_ci  runWASI({ test: 'symlink_loop' });
831cb0ef41Sopenharmony_ci}
84