11cb0ef41Sopenharmony_ci// This file is a modified version of the rimraf module on npm. It has been 21cb0ef41Sopenharmony_ci// modified in the following ways: 31cb0ef41Sopenharmony_ci// - Use of the assert module has been replaced with core's error system. 41cb0ef41Sopenharmony_ci// - All code related to the glob dependency has been removed. 51cb0ef41Sopenharmony_ci// - Bring your own custom fs module is not currently supported. 61cb0ef41Sopenharmony_ci// - Some basic code cleanup. 71cb0ef41Sopenharmony_ci'use strict'; 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciconst { 101cb0ef41Sopenharmony_ci ArrayPrototypeForEach, 111cb0ef41Sopenharmony_ci Promise, 121cb0ef41Sopenharmony_ci SafeSet, 131cb0ef41Sopenharmony_ci} = primordials; 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer'); 161cb0ef41Sopenharmony_ciconst fs = require('fs'); 171cb0ef41Sopenharmony_ciconst { 181cb0ef41Sopenharmony_ci chmod, 191cb0ef41Sopenharmony_ci chmodSync, 201cb0ef41Sopenharmony_ci lstat, 211cb0ef41Sopenharmony_ci lstatSync, 221cb0ef41Sopenharmony_ci readdir, 231cb0ef41Sopenharmony_ci readdirSync, 241cb0ef41Sopenharmony_ci rmdir, 251cb0ef41Sopenharmony_ci rmdirSync, 261cb0ef41Sopenharmony_ci stat, 271cb0ef41Sopenharmony_ci statSync, 281cb0ef41Sopenharmony_ci unlink, 291cb0ef41Sopenharmony_ci unlinkSync, 301cb0ef41Sopenharmony_ci} = fs; 311cb0ef41Sopenharmony_ciconst { sep } = require('path'); 321cb0ef41Sopenharmony_ciconst { setTimeout } = require('timers'); 331cb0ef41Sopenharmony_ciconst { sleep } = require('internal/util'); 341cb0ef41Sopenharmony_ciconst notEmptyErrorCodes = new SafeSet(['ENOTEMPTY', 'EEXIST', 'EPERM']); 351cb0ef41Sopenharmony_ciconst retryErrorCodes = new SafeSet( 361cb0ef41Sopenharmony_ci ['EBUSY', 'EMFILE', 'ENFILE', 'ENOTEMPTY', 'EPERM']); 371cb0ef41Sopenharmony_ciconst isWindows = process.platform === 'win32'; 381cb0ef41Sopenharmony_ciconst epermHandler = isWindows ? fixWinEPERM : _rmdir; 391cb0ef41Sopenharmony_ciconst epermHandlerSync = isWindows ? fixWinEPERMSync : _rmdirSync; 401cb0ef41Sopenharmony_ciconst readdirEncoding = 'buffer'; 411cb0ef41Sopenharmony_ciconst separator = Buffer.from(sep); 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_cifunction rimraf(path, options, callback) { 451cb0ef41Sopenharmony_ci let retries = 0; 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci _rimraf(path, options, function CB(err) { 481cb0ef41Sopenharmony_ci if (err) { 491cb0ef41Sopenharmony_ci if (retryErrorCodes.has(err.code) && retries < options.maxRetries) { 501cb0ef41Sopenharmony_ci retries++; 511cb0ef41Sopenharmony_ci const delay = retries * options.retryDelay; 521cb0ef41Sopenharmony_ci return setTimeout(_rimraf, delay, path, options, CB); 531cb0ef41Sopenharmony_ci } 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci // The file is already gone. 561cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') 571cb0ef41Sopenharmony_ci err = null; 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci callback(err); 611cb0ef41Sopenharmony_ci }); 621cb0ef41Sopenharmony_ci} 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_cifunction _rimraf(path, options, callback) { 661cb0ef41Sopenharmony_ci // SunOS lets the root user unlink directories. Use lstat here to make sure 671cb0ef41Sopenharmony_ci // it's not a directory. 681cb0ef41Sopenharmony_ci lstat(path, (err, stats) => { 691cb0ef41Sopenharmony_ci if (err) { 701cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') 711cb0ef41Sopenharmony_ci return callback(null); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci // Windows can EPERM on stat. 741cb0ef41Sopenharmony_ci if (isWindows && err.code === 'EPERM') 751cb0ef41Sopenharmony_ci return fixWinEPERM(path, options, err, callback); 761cb0ef41Sopenharmony_ci } else if (stats.isDirectory()) { 771cb0ef41Sopenharmony_ci return _rmdir(path, options, err, callback); 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci unlink(path, (err) => { 811cb0ef41Sopenharmony_ci if (err) { 821cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') 831cb0ef41Sopenharmony_ci return callback(null); 841cb0ef41Sopenharmony_ci if (err.code === 'EISDIR') 851cb0ef41Sopenharmony_ci return _rmdir(path, options, err, callback); 861cb0ef41Sopenharmony_ci if (err.code === 'EPERM') { 871cb0ef41Sopenharmony_ci return epermHandler(path, options, err, callback); 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci return callback(err); 921cb0ef41Sopenharmony_ci }); 931cb0ef41Sopenharmony_ci }); 941cb0ef41Sopenharmony_ci} 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_cifunction fixWinEPERM(path, options, originalErr, callback) { 981cb0ef41Sopenharmony_ci chmod(path, 0o666, (err) => { 991cb0ef41Sopenharmony_ci if (err) 1001cb0ef41Sopenharmony_ci return callback(err.code === 'ENOENT' ? null : originalErr); 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci stat(path, (err, stats) => { 1031cb0ef41Sopenharmony_ci if (err) 1041cb0ef41Sopenharmony_ci return callback(err.code === 'ENOENT' ? null : originalErr); 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci if (stats.isDirectory()) 1071cb0ef41Sopenharmony_ci _rmdir(path, options, originalErr, callback); 1081cb0ef41Sopenharmony_ci else 1091cb0ef41Sopenharmony_ci unlink(path, callback); 1101cb0ef41Sopenharmony_ci }); 1111cb0ef41Sopenharmony_ci }); 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_cifunction _rmdir(path, options, originalErr, callback) { 1161cb0ef41Sopenharmony_ci rmdir(path, (err) => { 1171cb0ef41Sopenharmony_ci if (err) { 1181cb0ef41Sopenharmony_ci if (notEmptyErrorCodes.has(err.code)) 1191cb0ef41Sopenharmony_ci return _rmchildren(path, options, callback); 1201cb0ef41Sopenharmony_ci if (err.code === 'ENOTDIR') 1211cb0ef41Sopenharmony_ci return callback(originalErr); 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci callback(err); 1251cb0ef41Sopenharmony_ci }); 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_cifunction _rmchildren(path, options, callback) { 1301cb0ef41Sopenharmony_ci const pathBuf = Buffer.from(path); 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci readdir(pathBuf, readdirEncoding, (err, files) => { 1331cb0ef41Sopenharmony_ci if (err) 1341cb0ef41Sopenharmony_ci return callback(err); 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci let numFiles = files.length; 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci if (numFiles === 0) 1391cb0ef41Sopenharmony_ci return rmdir(path, callback); 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci let done = false; 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci ArrayPrototypeForEach(files, (child) => { 1441cb0ef41Sopenharmony_ci const childPath = Buffer.concat([pathBuf, separator, child]); 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci rimraf(childPath, options, (err) => { 1471cb0ef41Sopenharmony_ci if (done) 1481cb0ef41Sopenharmony_ci return; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci if (err) { 1511cb0ef41Sopenharmony_ci done = true; 1521cb0ef41Sopenharmony_ci return callback(err); 1531cb0ef41Sopenharmony_ci } 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci numFiles--; 1561cb0ef41Sopenharmony_ci if (numFiles === 0) 1571cb0ef41Sopenharmony_ci rmdir(path, callback); 1581cb0ef41Sopenharmony_ci }); 1591cb0ef41Sopenharmony_ci }); 1601cb0ef41Sopenharmony_ci }); 1611cb0ef41Sopenharmony_ci} 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_cifunction rimrafPromises(path, options) { 1651cb0ef41Sopenharmony_ci return new Promise((resolve, reject) => { 1661cb0ef41Sopenharmony_ci rimraf(path, options, (err) => { 1671cb0ef41Sopenharmony_ci if (err) 1681cb0ef41Sopenharmony_ci return reject(err); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci resolve(); 1711cb0ef41Sopenharmony_ci }); 1721cb0ef41Sopenharmony_ci }); 1731cb0ef41Sopenharmony_ci} 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_cifunction rimrafSync(path, options) { 1771cb0ef41Sopenharmony_ci let stats; 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci try { 1801cb0ef41Sopenharmony_ci stats = lstatSync(path); 1811cb0ef41Sopenharmony_ci } catch (err) { 1821cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') 1831cb0ef41Sopenharmony_ci return; 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci // Windows can EPERM on stat. 1861cb0ef41Sopenharmony_ci if (isWindows && err.code === 'EPERM') 1871cb0ef41Sopenharmony_ci fixWinEPERMSync(path, options, err); 1881cb0ef41Sopenharmony_ci } 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci try { 1911cb0ef41Sopenharmony_ci // SunOS lets the root user unlink directories. 1921cb0ef41Sopenharmony_ci if (stats?.isDirectory()) 1931cb0ef41Sopenharmony_ci _rmdirSync(path, options, null); 1941cb0ef41Sopenharmony_ci else 1951cb0ef41Sopenharmony_ci _unlinkSync(path, options); 1961cb0ef41Sopenharmony_ci } catch (err) { 1971cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') 1981cb0ef41Sopenharmony_ci return; 1991cb0ef41Sopenharmony_ci if (err.code === 'EPERM') 2001cb0ef41Sopenharmony_ci return epermHandlerSync(path, options, err); 2011cb0ef41Sopenharmony_ci if (err.code !== 'EISDIR') 2021cb0ef41Sopenharmony_ci throw err; 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci _rmdirSync(path, options, err); 2051cb0ef41Sopenharmony_ci } 2061cb0ef41Sopenharmony_ci} 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_cifunction _unlinkSync(path, options) { 2101cb0ef41Sopenharmony_ci const tries = options.maxRetries + 1; 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci for (let i = 1; i <= tries; i++) { 2131cb0ef41Sopenharmony_ci try { 2141cb0ef41Sopenharmony_ci return unlinkSync(path); 2151cb0ef41Sopenharmony_ci } catch (err) { 2161cb0ef41Sopenharmony_ci // Only sleep if this is not the last try, and the delay is greater 2171cb0ef41Sopenharmony_ci // than zero, and an error was encountered that warrants a retry. 2181cb0ef41Sopenharmony_ci if (retryErrorCodes.has(err.code) && 2191cb0ef41Sopenharmony_ci i < tries && 2201cb0ef41Sopenharmony_ci options.retryDelay > 0) { 2211cb0ef41Sopenharmony_ci sleep(i * options.retryDelay); 2221cb0ef41Sopenharmony_ci } else if (err.code === 'ENOENT') { 2231cb0ef41Sopenharmony_ci // The file is already gone. 2241cb0ef41Sopenharmony_ci return; 2251cb0ef41Sopenharmony_ci } else if (i === tries) { 2261cb0ef41Sopenharmony_ci throw err; 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci } 2291cb0ef41Sopenharmony_ci } 2301cb0ef41Sopenharmony_ci} 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_cifunction _rmdirSync(path, options, originalErr) { 2341cb0ef41Sopenharmony_ci try { 2351cb0ef41Sopenharmony_ci rmdirSync(path); 2361cb0ef41Sopenharmony_ci } catch (err) { 2371cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') 2381cb0ef41Sopenharmony_ci return; 2391cb0ef41Sopenharmony_ci if (err.code === 'ENOTDIR') { 2401cb0ef41Sopenharmony_ci throw originalErr || err; 2411cb0ef41Sopenharmony_ci } 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci if (notEmptyErrorCodes.has(err.code)) { 2441cb0ef41Sopenharmony_ci // Removing failed. Try removing all children and then retrying the 2451cb0ef41Sopenharmony_ci // original removal. Windows has a habit of not closing handles promptly 2461cb0ef41Sopenharmony_ci // when files are deleted, resulting in spurious ENOTEMPTY failures. Work 2471cb0ef41Sopenharmony_ci // around that issue by retrying on Windows. 2481cb0ef41Sopenharmony_ci const pathBuf = Buffer.from(path); 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci ArrayPrototypeForEach(readdirSync(pathBuf, readdirEncoding), (child) => { 2511cb0ef41Sopenharmony_ci const childPath = Buffer.concat([pathBuf, separator, child]); 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci rimrafSync(childPath, options); 2541cb0ef41Sopenharmony_ci }); 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci const tries = options.maxRetries + 1; 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci for (let i = 1; i <= tries; i++) { 2591cb0ef41Sopenharmony_ci try { 2601cb0ef41Sopenharmony_ci return fs.rmdirSync(path); 2611cb0ef41Sopenharmony_ci } catch (err) { 2621cb0ef41Sopenharmony_ci // Only sleep if this is not the last try, and the delay is greater 2631cb0ef41Sopenharmony_ci // than zero, and an error was encountered that warrants a retry. 2641cb0ef41Sopenharmony_ci if (retryErrorCodes.has(err.code) && 2651cb0ef41Sopenharmony_ci i < tries && 2661cb0ef41Sopenharmony_ci options.retryDelay > 0) { 2671cb0ef41Sopenharmony_ci sleep(i * options.retryDelay); 2681cb0ef41Sopenharmony_ci } else if (err.code === 'ENOENT') { 2691cb0ef41Sopenharmony_ci // The file is already gone. 2701cb0ef41Sopenharmony_ci return; 2711cb0ef41Sopenharmony_ci } else if (i === tries) { 2721cb0ef41Sopenharmony_ci throw err; 2731cb0ef41Sopenharmony_ci } 2741cb0ef41Sopenharmony_ci } 2751cb0ef41Sopenharmony_ci } 2761cb0ef41Sopenharmony_ci } 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ci throw originalErr || err; 2791cb0ef41Sopenharmony_ci } 2801cb0ef41Sopenharmony_ci} 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_cifunction fixWinEPERMSync(path, options, originalErr) { 2841cb0ef41Sopenharmony_ci try { 2851cb0ef41Sopenharmony_ci chmodSync(path, 0o666); 2861cb0ef41Sopenharmony_ci } catch (err) { 2871cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') 2881cb0ef41Sopenharmony_ci return; 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci throw originalErr; 2911cb0ef41Sopenharmony_ci } 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_ci let stats; 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci try { 2961cb0ef41Sopenharmony_ci stats = statSync(path, { throwIfNoEntry: false }); 2971cb0ef41Sopenharmony_ci } catch { 2981cb0ef41Sopenharmony_ci throw originalErr; 2991cb0ef41Sopenharmony_ci } 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci if (stats === undefined) return; 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_ci if (stats.isDirectory()) 3041cb0ef41Sopenharmony_ci _rmdirSync(path, options, originalErr); 3051cb0ef41Sopenharmony_ci else 3061cb0ef41Sopenharmony_ci _unlinkSync(path, options); 3071cb0ef41Sopenharmony_ci} 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_cimodule.exports = { rimraf, rimrafPromises, rimrafSync }; 311