11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ci// Test that mkdir with recursive option returns appropriate error
41cb0ef41Sopenharmony_ci// when executed on folder it does not have permission to access.
51cb0ef41Sopenharmony_ci// Ref: https://github.com/nodejs/node/issues/31481
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst common = require('../common');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciif (!common.isWindows && process.getuid() === 0)
101cb0ef41Sopenharmony_ci  common.skip('as this test should not be run as `root`');
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciif (common.isIBMi)
131cb0ef41Sopenharmony_ci  common.skip('IBMi has a different access permission mechanism');
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir');
161cb0ef41Sopenharmony_citmpdir.refresh();
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciconst assert = require('assert');
191cb0ef41Sopenharmony_ciconst { execSync } = require('child_process');
201cb0ef41Sopenharmony_ciconst fs = require('fs');
211cb0ef41Sopenharmony_ciconst path = require('path');
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_cilet n = 0;
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_cifunction makeDirectoryReadOnly(dir) {
261cb0ef41Sopenharmony_ci  let accessErrorCode = 'EACCES';
271cb0ef41Sopenharmony_ci  if (common.isWindows) {
281cb0ef41Sopenharmony_ci    accessErrorCode = 'EPERM';
291cb0ef41Sopenharmony_ci    execSync(`icacls ${dir} /deny "everyone:(OI)(CI)(DE,DC,AD,WD)"`);
301cb0ef41Sopenharmony_ci  } else {
311cb0ef41Sopenharmony_ci    fs.chmodSync(dir, '444');
321cb0ef41Sopenharmony_ci  }
331cb0ef41Sopenharmony_ci  return accessErrorCode;
341cb0ef41Sopenharmony_ci}
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_cifunction makeDirectoryWritable(dir) {
371cb0ef41Sopenharmony_ci  if (common.isWindows) {
381cb0ef41Sopenharmony_ci    execSync(`icacls ${dir} /remove:d "everyone"`);
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci}
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci// Synchronous API should return an EACCESS error with path populated.
431cb0ef41Sopenharmony_ci{
441cb0ef41Sopenharmony_ci  const dir = path.join(tmpdir.path, `mkdirp_${n++}`);
451cb0ef41Sopenharmony_ci  fs.mkdirSync(dir);
461cb0ef41Sopenharmony_ci  const codeExpected = makeDirectoryReadOnly(dir);
471cb0ef41Sopenharmony_ci  let err = null;
481cb0ef41Sopenharmony_ci  try {
491cb0ef41Sopenharmony_ci    fs.mkdirSync(path.join(dir, '/foo'), { recursive: true });
501cb0ef41Sopenharmony_ci  } catch (_err) {
511cb0ef41Sopenharmony_ci    err = _err;
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci  makeDirectoryWritable(dir);
541cb0ef41Sopenharmony_ci  assert(err);
551cb0ef41Sopenharmony_ci  assert.strictEqual(err.code, codeExpected);
561cb0ef41Sopenharmony_ci  assert(err.path);
571cb0ef41Sopenharmony_ci}
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci// Asynchronous API should return an EACCESS error with path populated.
601cb0ef41Sopenharmony_ci{
611cb0ef41Sopenharmony_ci  const dir = path.join(tmpdir.path, `mkdirp_${n++}`);
621cb0ef41Sopenharmony_ci  fs.mkdirSync(dir);
631cb0ef41Sopenharmony_ci  const codeExpected = makeDirectoryReadOnly(dir);
641cb0ef41Sopenharmony_ci  fs.mkdir(path.join(dir, '/bar'), { recursive: true }, (err) => {
651cb0ef41Sopenharmony_ci    makeDirectoryWritable(dir);
661cb0ef41Sopenharmony_ci    assert(err);
671cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, codeExpected);
681cb0ef41Sopenharmony_ci    assert(err.path);
691cb0ef41Sopenharmony_ci  });
701cb0ef41Sopenharmony_ci}
71