tools/node-hermes/nodelib/fs.js (1,768 lines of code) (raw):

// @nolint // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. // Maintainers, keep in mind that ES1-style octal literals (`0666`) are not // allowed in strict mode. Use ES6-style octal literals instead (`0o666`). 'use strict'; // When using FSReqCallback, make sure to create the object only *after* all // parameter validation has happened, so that the objects are not kept in memory // in case they are created but never used due to an exception. function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var _primordials = primordials, ArrayPrototypePush = _primordials.ArrayPrototypePush, BigIntPrototypeToString = _primordials.BigIntPrototypeToString, MathMax = _primordials.MathMax, Number = _primordials.Number, ObjectCreate = _primordials.ObjectCreate, ObjectDefineProperties = _primordials.ObjectDefineProperties, ObjectDefineProperty = _primordials.ObjectDefineProperty, Promise = _primordials.Promise, ReflectApply = _primordials.ReflectApply, RegExpPrototypeExec = _primordials.RegExpPrototypeExec, SafeMap = _primordials.SafeMap, String = _primordials.String, StringPrototypeCharCodeAt = _primordials.StringPrototypeCharCodeAt, StringPrototypeIndexOf = _primordials.StringPrototypeIndexOf, StringPrototypeSlice = _primordials.StringPrototypeSlice; var _internalBinding = internalBinding('constants'), constants = _internalBinding.fs; var S_IFIFO = constants.S_IFIFO, S_IFLNK = constants.S_IFLNK, S_IFMT = constants.S_IFMT, S_IFREG = constants.S_IFREG, S_IFSOCK = constants.S_IFSOCK, F_OK = constants.F_OK, R_OK = constants.R_OK, W_OK = constants.W_OK, X_OK = constants.X_OK, O_WRONLY = constants.O_WRONLY, O_SYMLINK = constants.O_SYMLINK; var pathModule = require('path'); // var _require = require('internal/util/types'), // isArrayBufferView = _require.isArrayBufferView; // We need to get the statValues from the binding at the callsite since // it's re-initialized after deserialization. var binding = internalBinding('fs'); var _require2 = require('buffer'), Buffer = _require2.Buffer; // var _require3 = require('internal/errors'), // aggregateTwoErrors = _require3.aggregateTwoErrors, // _require3$codes = _require3.codes, // ERR_FS_FILE_TOO_LARGE = _require3$codes.ERR_FS_FILE_TOO_LARGE, // ERR_INVALID_ARG_VALUE = _require3$codes.ERR_INVALID_ARG_VALUE, // ERR_INVALID_ARG_TYPE = _require3$codes.ERR_INVALID_ARG_TYPE, // ERR_FEATURE_UNAVAILABLE_ON_PLATFORM = _require3$codes.ERR_FEATURE_UNAVAILABLE_ON_PLATFORM, // AbortError = _require3.AbortError, // uvErrmapGet = _require3.uvErrmapGet, // uvException = _require3.uvException; // var FSReqCallback = binding.FSReqCallback; // var _require4 = require('internal/url'), // toPathIfFileURL = _require4.toPathIfFileURL; var internalUtil = require('internal/util'); var _require5 = require('internal/fs/utils'), _require5$constants = _require5.constants, kIoMaxLength = _require5$constants.kIoMaxLength, kMaxUserId = _require5$constants.kMaxUserId, copyObject = _require5.copyObject, // Dirent = _require5.Dirent, // emitRecursiveRmdirWarning = _require5.emitRecursiveRmdirWarning, // getDirents = _require5.getDirents, getOptions = _require5.getOptions, getValidatedFd = _require5.getValidatedFd, getValidatedPath = _require5.getValidatedPath, // getValidMode = _require5.getValidMode, handleErrorFromBinding = _require5.handleErrorFromBinding, // nullCheck = _require5.nullCheck, // preprocessSymlinkDestination = _require5.preprocessSymlinkDestination, // Stats = _require5.Stats, // getStatsFromBinding = _require5.getStatsFromBinding, // realpathCacheKey = _require5.realpathCacheKey, stringToFlags = _require5.stringToFlags, // stringToSymlinkType = _require5.stringToSymlinkType, // toUnixTimestamp = _require5.toUnixTimestamp, // validateBufferArray = _require5.validateBufferArray, validateOffsetLengthRead = _require5.validateOffsetLengthRead, // validateOffsetLengthWrite = _require5.validateOffsetLengthWrite, // validatePath = _require5.validatePath, validatePosition = _require5.validatePosition; // validateRmOptions = _require5.validateRmOptions, // validateRmOptionsSync = _require5.validateRmOptionsSync, // validateRmdirOptions = _require5.validateRmdirOptions, // validateStringAfterArrayBufferView = _require5.validateStringAfterArrayBufferView, // warnOnNonPortableTemplate = _require5.warnOnNonPortableTemplate; // var _require6 = require('internal/fs/dir'), // Dir = _require6.Dir, // opendir = _require6.opendir, // opendirSync = _require6.opendirSync; // var _require7 = require('internal/constants'), // CHAR_FORWARD_SLASH = _require7.CHAR_FORWARD_SLASH, // CHAR_BACKWARD_SLASH = _require7.CHAR_BACKWARD_SLASH; var _require8 = require('internal/validators'), isUint32 = _require8.isUint32, parseFileMode = _require8.parseFileMode, // validateBoolean = _require8.validateBoolean, validateBuffer = _require8.validateBuffer, // validateCallback = _require8.validateCallback, // validateEncoding = _require8.validateEncoding, // validateFunction = _require8.validateFunction, validateInteger = _require8.validateInteger; // var watchers = require('internal/fs/watchers'); // var ReadFileContext = require('internal/fs/read_file_context'); var truncateWarn = true; var fs; // Lazy loaded var promises = null; var ReadStream; var WriteStream; var rimraf; var rimrafSync; // These have to be separate because of how graceful-fs happens to do it's // monkeypatching. var FileReadStream; var FileWriteStream; // var isWindows = process.platform === 'win32'; // var isOSX = process.platform === 'darwin'; function showTruncateDeprecation() { if (truncateWarn) { process.emitWarning('Using fs.truncate with a file descriptor is deprecated. Please use ' + 'fs.ftruncate with a file descriptor instead.', 'DeprecationWarning', 'DEP0081'); truncateWarn = false; } } function maybeCallback(cb) { validateCallback(cb); return cb; } // Ensure that callbacks run in the global context. Only use this function // for callbacks that are passed to the binding layer, callbacks that are // invoked from JS already run in the proper scope. function makeCallback(cb) { var _this = this; validateCallback(cb); return function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return ReflectApply(cb, _this, args); }; } // Special case of `makeCallback()` that is specific to async `*stat()` calls as // an optimization, since the data passed back to the callback needs to be // transformed anyway. function makeStatsCallback(cb) { validateCallback(cb); return function (err, stats) { if (err) return cb(err); cb(err, getStatsFromBinding(stats)); }; } var isFd = isUint32; function isFileType(stats, fileType) { // Use stats array directly to avoid creating an fs.Stats instance just for // our internal use. var mode = stats[1]; if(mode == undefined) mode = stats.mode; // New if (typeof mode === 'bigint') mode = Number(mode); return (mode & S_IFMT) === fileType; } /** * Tests a user's permissions for the file or directory * specified by `path`. * @param {string | Buffer | URL} path * @param {number} [mode] * @param {(err?: Error) => any} callback * @returns {void} */ function access(path, mode, callback) { if (typeof mode === 'function') { callback = mode; mode = F_OK; } path = getValidatedPath(path); mode = getValidMode(mode, 'access'); callback = makeCallback(callback); var req = new FSReqCallback(); req.oncomplete = callback; binding.access(pathModule.toNamespacedPath(path), mode, req); } /** * Synchronously tests a user's permissions for the file or * directory specified by `path`. * @param {string | Buffer | URL} path * @param {number} [mode] * @returns {void | never} */ function accessSync(path, mode) { path = getValidatedPath(path); mode = getValidMode(mode, 'access'); var ctx = { path: path }; binding.access(pathModule.toNamespacedPath(path), mode, undefined, ctx); handleErrorFromBinding(ctx); } /** * Tests whether or not the given path exists. * @param {string | Buffer | URL} path * @param {(exists?: boolean) => any} callback * @returns {void} */ function exists(path, callback) { maybeCallback(callback); function suppressedCallback(err) { callback(err ? false : true); } try { fs.access(path, F_OK, suppressedCallback); } catch (_unused) { return callback(false); } } ObjectDefineProperty(exists, internalUtil.promisify.custom, { value: function value(path) { return new Promise(function (resolve) { return fs.exists(path, resolve); }); } }); // fs.existsSync never throws, it only returns true or false. // Since fs.existsSync never throws, users have established // the expectation that passing invalid arguments to it, even like // fs.existsSync(), would only get a false in return, so we cannot signal // validation errors to users properly out of compatibility concerns. // TODO(joyeecheung): deprecate the never-throw-on-invalid-arguments behavior /** * Synchronously tests whether or not the given path exists. * @param {string | Buffer | URL} path * @returns {boolean} */ function existsSync(path) { try { path = getValidatedPath(path); } catch (_unused2) { return false; } var ctx = { path: path }; var nPath = pathModule.toNamespacedPath(path); binding.access(nPath, F_OK, undefined, ctx); // In case of an invalid symlink, `binding.access()` on win32 // will **not** return an error and is therefore not enough. // Double check with `binding.stat()`. if (isWindows && ctx.errno === undefined) { binding.stat(nPath, false, undefined, ctx); } return ctx.errno === undefined; } function readFileAfterOpen(err, fd) { var context = this.context; if (err) { context.callback(err); return; } context.fd = fd; var req = new FSReqCallback(); req.oncomplete = readFileAfterStat; req.context = context; binding.fstat(fd, false, req); } function readFileAfterStat(err, stats) { var context = this.context; if (err) return context.close(err); var size = context.size = isFileType(stats, S_IFREG) ? stats[8] : 0; if (size > kIoMaxLength) { err = new ERR_FS_FILE_TOO_LARGE(size); return context.close(err); } try { if (size === 0) { context.buffers = []; } else { context.buffer = Buffer.allocUnsafeSlow(size); } } catch (err) { return context.close(err); } context.read(); } function checkAborted(signal, callback) { if (signal !== null && signal !== void 0 && signal.aborted) { callback(new AbortError()); return true; } return false; } /** * Asynchronously reads the entire contents of a file. * @param {string | Buffer | URL | number} path * @param {{ * encoding?: string | null; * flag?: string; * signal?: AbortSignal; * } | string} [options] * @param {( * err?: Error, * data?: string | Buffer * ) => any} callback * @returns {void} */ function readFile(path, options, callback) { callback = maybeCallback(callback || options); options = getOptions(options, { flag: 'r' }); var context = new ReadFileContext(callback, options.encoding); context.isUserFd = isFd(path); // File descriptor ownership if (options.signal) { context.signal = options.signal; } if (context.isUserFd) { process.nextTick(function tick(context) { ReflectApply(readFileAfterOpen, { context: context }, [null, path]); }, context); return; } if (checkAborted(options.signal, callback)) return; var flagsNumber = stringToFlags(options.flag, 'options.flag'); path = getValidatedPath(path); var req = new FSReqCallback(); req.context = context; req.oncomplete = readFileAfterOpen; binding.open(pathModule.toNamespacedPath(path), flagsNumber, 438, req); } function tryStatSync(fd, isUserFd) { var ctx = {}; var stats = binding.fstat(fd, false, undefined, ctx); if (ctx.errno !== undefined && !isUserFd) { fs.closeSync(fd); throw uvException(ctx); } return stats; } function tryCreateBuffer(size, fd, isUserFd) { var threw = true; var buffer; try { if (size > kIoMaxLength) { throw new ERR_FS_FILE_TOO_LARGE(size); } buffer = Buffer.allocUnsafeSlow(size); //Changed from allocUnsafe threw = false; } finally { if (threw && !isUserFd) fs.closeSync(fd); } return buffer; } function tryReadSync(fd, isUserFd, buffer, pos, len) { var threw = true; var bytesRead; try { bytesRead = fs.readSync(fd, buffer, pos, len); threw = false; } finally { if (threw && !isUserFd) fs.closeSync(fd); } return bytesRead; } /** * Synchronously reads the entire contents of a file. * @param {string | Buffer | URL | number} path * @param {{ * encoding?: string | null; * flag?: string; * }} [options] * @returns {string | Buffer} */ function readFileSync(path, options) { options = getOptions(options, { flag: 'r' }); var isUserFd = isFd(path); // File descriptor ownership var fd = isUserFd ? path : fs.openSync(path, options.flag, 438); var stats = tryStatSync(fd, isUserFd); var size = isFileType(stats, S_IFREG) ? stats.size : 0; // Change from stats[8] var pos = 0; var buffer; // Single buffer with file data var buffers; // List for when size is unknown if (size === 0) { buffers = []; } else { buffer = tryCreateBuffer(size, fd, isUserFd); } var bytesRead; if (size !== 0) { do { bytesRead = tryReadSync(fd, isUserFd, buffer, pos, size - pos); pos += bytesRead; } while (bytesRead !== 0 && pos < size); } else { do { // The kernel lies about many files. // Go ahead and try to read some bytes. buffer = Buffer.allocUnsafeSlow(8192); bytesRead = tryReadSync(fd, isUserFd, buffer, 0, 8192); if (bytesRead !== 0) { ArrayPrototypePush(buffers, buffer.slice(0, bytesRead)); } pos += bytesRead; } while (bytesRead !== 0); } if (!isUserFd) fs.closeSync(fd); if (size === 0) { // Data was collected into the buffers list. buffer = Buffer.concat(buffers, pos); } else if (pos < size) { buffer = buffer.slice(0, pos); } if (options.encoding) buffer = buffer.toString(options.encoding); return buffer; } function defaultCloseCallback(err) { if (err != null) throw err; } /** * Closes the file descriptor. * @param {number} fd * @param {(err?: Error) => any} [callback] * @returns {void} */ function close(fd) { var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultCloseCallback; fd = getValidatedFd(fd); if (callback !== defaultCloseCallback) callback = makeCallback(callback); var req = new FSReqCallback(); req.oncomplete = callback; binding.close(fd, req); } /** * Synchronously closes the file descriptor. * @param {number} fd * @returns {void} */ function closeSync(fd) { fd = getValidatedFd(fd); var ctx = {}; binding.close(fd, undefined, ctx); handleErrorFromBinding(ctx); } /** * Asynchronously opens a file. * @param {string | Buffer | URL} path * @param {string | number} [flags] * @param {string | number} [mode] * @param {( * err?: Error, * fd?: number * ) => any} callback * @returns {void} */ function open(path, flags, mode, callback) { path = getValidatedPath(path); if (arguments.length < 3) { callback = flags; flags = 'r'; mode = 438; } else if (typeof mode === 'function') { callback = mode; mode = 438; } else { mode = parseFileMode(mode, 'mode', 438); } var flagsNumber = stringToFlags(flags); callback = makeCallback(callback); var req = new FSReqCallback(); req.oncomplete = callback; binding.open(pathModule.toNamespacedPath(path), flagsNumber, mode, req); } /** * Synchronously opens a file. * @param {string | Buffer | URL} path * @param {string | number} [flags] * @param {string | number} [mode] * @returns {number} */ function openSync(path, flags, mode) { path = getValidatedPath(path); var flagsNumber = stringToFlags(flags); mode = parseFileMode(mode, 'mode', 438); var ctx = { path: path }; var result = binding.open(pathModule.toNamespacedPath(path), flagsNumber, mode, undefined, ctx); handleErrorFromBinding(ctx); return result; } /** * Reads file from the specified `fd` (file descriptor). * @param {number} fd * @param {Buffer | TypedArray | DataView} buffer * @param {number} offset * @param {number} length * @param {number | bigint} position * @param {( * err?: Error, * bytesRead?: number, * buffer?: Buffer * ) => any} callback * @returns {void} */ function read(fd, buffer, offset, length, position, callback) { fd = getValidatedFd(fd); if (arguments.length <= 3) { // Assume fs.read(fd, options, callback) var options = {}; if (arguments.length < 3) { // This is fs.read(fd, callback) // buffer will be the callback callback = buffer; } else { // This is fs.read(fd, {}, callback) // buffer will be the options object // offset is the callback options = buffer; callback = offset; } var _options = options; var _options$buffer = _options.buffer; buffer = _options$buffer === void 0 ? Buffer.alloc(16384) : _options$buffer; var _options$offset = _options.offset; offset = _options$offset === void 0 ? 0 : _options$offset; var _options$length = _options.length; length = _options$length === void 0 ? buffer.byteLength : _options$length; position = _options.position; } validateBuffer(buffer); callback = maybeCallback(callback); if (offset == null) { offset = 0; } else { validateInteger(offset, 'offset', 0); } length |= 0; if (length === 0) { return process.nextTick(function tick() { callback(null, 0, buffer); }); } if (buffer.byteLength === 0) { throw new ERR_INVALID_ARG_VALUE('buffer', buffer, 'is empty and cannot be written'); } validateOffsetLengthRead(offset, length, buffer.byteLength); if (position == null) position = -1; validatePosition(position, 'position'); function wrapper(err, bytesRead) { // Retain a reference to buffer so that it can't be GC'ed too soon. callback(err, bytesRead || 0, buffer); } var req = new FSReqCallback(); req.oncomplete = wrapper; binding.read(fd, buffer, offset, length, position, req); } ObjectDefineProperty(read, internalUtil.customPromisifyArgs, { value: ['bytesRead', 'buffer'], enumerable: false }); /** * Synchronously reads the file from the * specified `fd` (file descriptor). * @param {number} fd * @param {Buffer | TypedArray | DataView} buffer * @param {{ * offset?: number; * length?: number; * position?: number | bigint; * }} [offset] * @returns {number} */ function readSync(fd, buffer, offset, length, position) { fd = getValidatedFd(fd); validateBuffer(buffer); if (arguments.length <= 3) { // Assume fs.read(fd, buffer, options) var options = offset || {}; var _options$offset2 = options.offset; offset = _options$offset2 === void 0 ? 0 : _options$offset2; var _options$length2 = options.length; length = _options$length2 === void 0 ? buffer.byteLength : _options$length2; position = options.position; } if (offset == null) { offset = 0; } else { validateInteger(offset, 'offset', 0); } length |= 0; if (length === 0) { return 0; } if (buffer.byteLength === 0) { throw new ERR_INVALID_ARG_VALUE('buffer', buffer, 'is empty and cannot be written'); } validateOffsetLengthRead(offset, length, buffer.byteLength); if (position == null) position = -1; validatePosition(position, 'position'); var ctx = {}; var result = binding.read(fd, buffer, offset, length, position, undefined, ctx); handleErrorFromBinding(ctx); return result; } /** * Reads file from the specified `fd` (file descriptor) * and writes to an array of `ArrayBufferView`s. * @param {number} fd * @param {ArrayBufferView[]} buffers * @param {number} [position] * @param {( * err?: Error, * bytesRead?: number, * buffers?: ArrayBufferView[]; * ) => any} callback * @returns {void} */ function readv(fd, buffers, position, callback) { function wrapper(err, read) { callback(err, read || 0, buffers); } fd = getValidatedFd(fd); validateBufferArray(buffers); callback = maybeCallback(callback || position); var req = new FSReqCallback(); req.oncomplete = wrapper; if (typeof position !== 'number') position = null; return binding.readBuffers(fd, buffers, position, req); } ObjectDefineProperty(readv, internalUtil.customPromisifyArgs, { value: ['bytesRead', 'buffers'], enumerable: false }); /** * Synchronously reads file from the * specified `fd` (file descriptor) and writes to an array * of `ArrayBufferView`s. * @param {number} fd * @param {ArrayBufferView[]} buffers * @param {number} [position] * @returns {number} */ function readvSync(fd, buffers, position) { fd = getValidatedFd(fd); validateBufferArray(buffers); var ctx = {}; if (typeof position !== 'number') position = null; var result = binding.readBuffers(fd, buffers, position, undefined, ctx); handleErrorFromBinding(ctx); return result; } /** * Writes `buffer` to the specified `fd` (file descriptor). * @param {number} fd * @param {Buffer | TypedArray | DataView | string | Object} buffer * @param {number} [offset] * @param {number} [length] * @param {number} [position] * @param {( * err?: Error, * bytesWritten?: number; * buffer?: Buffer | TypedArray | DataView * ) => any} callback * @returns {void} */ function write(fd, buffer, offset, length, position, callback) { function wrapper(err, written) { // Retain a reference to buffer so that it can't be GC'ed too soon. callback(err, written || 0, buffer); } fd = getValidatedFd(fd); if (isArrayBufferView(buffer)) { callback = maybeCallback(callback || position || length || offset); if (offset == null || typeof offset === 'function') { offset = 0; } else { validateInteger(offset, 'offset', 0); } if (typeof length !== 'number') length = buffer.byteLength - offset; if (typeof position !== 'number') position = null; validateOffsetLengthWrite(offset, length, buffer.byteLength); var _req = new FSReqCallback(); _req.oncomplete = wrapper; return binding.writeBuffer(fd, buffer, offset, length, position, _req); } validateStringAfterArrayBufferView(buffer, 'buffer'); if (typeof position !== 'function') { if (typeof offset === 'function') { position = offset; offset = null; } else { position = length; } length = 'utf8'; } var str = String(buffer); validateEncoding(str, length); callback = maybeCallback(position); var req = new FSReqCallback(); req.oncomplete = wrapper; return binding.writeString(fd, str, offset, length, req); } ObjectDefineProperty(write, internalUtil.customPromisifyArgs, { value: ['bytesWritten', 'buffer'], enumerable: false }); /** * Synchronously writes `buffer` to the * specified `fd` (file descriptor). * @param {number} fd * @param {Buffer | TypedArray | DataView | string | Object} buffer * @param {number} [offset] * @param {number} [length] * @param {number} [position] * @returns {number} */ function writeSync(fd, buffer, offset, length, position) { fd = getValidatedFd(fd); var ctx = {}; var result; if (isArrayBufferView(buffer)) { if (position === undefined) position = null; if (offset == null) { offset = 0; } else { validateInteger(offset, 'offset', 0); } if (typeof length !== 'number') length = buffer.byteLength - offset; validateOffsetLengthWrite(offset, length, buffer.byteLength); result = binding.writeBuffer(fd, buffer, offset, length, position, undefined, ctx); } else { validateStringAfterArrayBufferView(buffer, 'buffer'); validateEncoding(buffer, length); if (offset === undefined) offset = null; result = binding.writeString(fd, buffer, offset, length, undefined, ctx); } handleErrorFromBinding(ctx); return result; } /** * Writes an array of `ArrayBufferView`s to the * specified `fd` (file descriptor). * @param {number} fd * @param {ArrayBufferView[]} buffers * @param {number} [position] * @param {( * err?: Error, * bytesWritten?: number, * buffers?: ArrayBufferView[] * ) => any} callback * @returns {void} */ function writev(fd, buffers, position, callback) { function wrapper(err, written) { callback(err, written || 0, buffers); } fd = getValidatedFd(fd); validateBufferArray(buffers); callback = maybeCallback(callback || position); var req = new FSReqCallback(); req.oncomplete = wrapper; if (typeof position !== 'number') position = null; return binding.writeBuffers(fd, buffers, position, req); } ObjectDefineProperty(writev, internalUtil.customPromisifyArgs, { value: ['bytesWritten', 'buffer'], enumerable: false }); /** * Synchronously writes an array of `ArrayBufferView`s * to the specified `fd` (file descriptor). * @param {number} fd * @param {ArrayBufferView[]} buffers * @param {number} [position] * @returns {number} */ function writevSync(fd, buffers, position) { fd = getValidatedFd(fd); validateBufferArray(buffers); var ctx = {}; if (typeof position !== 'number') position = null; var result = binding.writeBuffers(fd, buffers, position, undefined, ctx); handleErrorFromBinding(ctx); return result; } /** * Asynchronously renames file at `oldPath` to * the pathname provided as `newPath`. * @param {string | Buffer | URL} oldPath * @param {string | Buffer | URL} newPath * @param {(err?: Error) => any} callback * @returns {void} */ function rename(oldPath, newPath, callback) { callback = makeCallback(callback); oldPath = getValidatedPath(oldPath, 'oldPath'); newPath = getValidatedPath(newPath, 'newPath'); var req = new FSReqCallback(); req.oncomplete = callback; binding.rename(pathModule.toNamespacedPath(oldPath), pathModule.toNamespacedPath(newPath), req); } /** * Synchronously renames file at `oldPath` to * the pathname provided as `newPath`. * @param {string | Buffer | URL} oldPath * @param {string | Buffer | URL} newPath * @returns {void} */ function renameSync(oldPath, newPath) { oldPath = getValidatedPath(oldPath, 'oldPath'); newPath = getValidatedPath(newPath, 'newPath'); var ctx = { path: oldPath, dest: newPath }; binding.rename(pathModule.toNamespacedPath(oldPath), pathModule.toNamespacedPath(newPath), undefined, ctx); handleErrorFromBinding(ctx); } /** * Truncates the file. * @param {string | Buffer | URL} path * @param {number} [len] * @param {(err?: Error) => any} callback * @returns {void} */ function truncate(path, len, callback) { if (typeof path === 'number') { showTruncateDeprecation(); return fs.ftruncate(path, len, callback); } if (typeof len === 'function') { callback = len; len = 0; } else if (len === undefined) { len = 0; } validateInteger(len, 'len'); len = MathMax(0, len); callback = maybeCallback(callback); fs.open(path, 'r+', function (er, fd) { if (er) return callback(er); var req = new FSReqCallback(); req.oncomplete = function oncomplete(er) { fs.close(fd, function (er2) { callback(aggregateTwoErrors(er2, er)); }); }; binding.ftruncate(fd, len, req); }); } /** * Synchronously truncates the file. * @param {string | Buffer | URL} path * @param {number} [len] * @returns {void} */ function truncateSync(path, len) { if (typeof path === 'number') { // legacy showTruncateDeprecation(); return fs.ftruncateSync(path, len); } if (len === undefined) { len = 0; } // Allow error to be thrown, but still close fd. var fd = fs.openSync(path, 'r+'); var ret; try { ret = fs.ftruncateSync(fd, len); } finally { fs.closeSync(fd); } return ret; } /** * Truncates the file descriptor. * @param {number} fd * @param {number} [len] * @param {(err?: Error) => any} callback * @returns {void} */ function ftruncate(fd) { var len = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var callback = arguments.length > 2 ? arguments[2] : undefined; if (typeof len === 'function') { callback = len; len = 0; } fd = getValidatedFd(fd); validateInteger(len, 'len'); len = MathMax(0, len); callback = makeCallback(callback); var req = new FSReqCallback(); req.oncomplete = callback; binding.ftruncate(fd, len, req); } /** * Synchronously truncates the file descriptor. * @param {number} fd * @param {number} [len] * @returns {void} */ function ftruncateSync(fd) { var len = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; fd = getValidatedFd(fd); validateInteger(len, 'len'); len = MathMax(0, len); var ctx = {}; binding.ftruncate(fd, len, undefined, ctx); handleErrorFromBinding(ctx); } function lazyLoadRimraf() { if (rimraf === undefined) { var _require9 = require('internal/fs/rimraf'); rimraf = _require9.rimraf; rimrafSync = _require9.rimrafSync; } } /** * Asynchronously removes a directory. * @param {string | Buffer | URL} path * @param {{ * maxRetries?: number; * recursive?: boolean; * retryDelay?: number; * }} [options] * @param {(err?: Error) => any} callback * @returns {void} */ function rmdir(path, options, callback) { var _options2; if (typeof options === 'function') { callback = options; options = undefined; } callback = makeCallback(callback); path = pathModule.toNamespacedPath(getValidatedPath(path)); if ((_options2 = options) !== null && _options2 !== void 0 && _options2.recursive) { emitRecursiveRmdirWarning(); validateRmOptions(path, _objectSpread(_objectSpread({}, options), {}, { force: false }), true, function (err, options) { if (err === false) { var req = new FSReqCallback(); req.oncomplete = callback; return binding.rmdir(path, req); } if (err) { return callback(err); } lazyLoadRimraf(); rimraf(path, options, callback); }); } else { validateRmdirOptions(options); var req = new FSReqCallback(); req.oncomplete = callback; return binding.rmdir(path, req); } } /** * Synchronously removes a directory. * @param {string | Buffer | URL} path * @param {{ * maxRetries?: number; * recursive?: boolean; * retryDelay?: number; * }} [options] * @returns {void} */ function rmdirSync(path, options) { var _options3; path = getValidatedPath(path); if ((_options3 = options) !== null && _options3 !== void 0 && _options3.recursive) { emitRecursiveRmdirWarning(); options = validateRmOptionsSync(path, _objectSpread(_objectSpread({}, options), {}, { force: false }), true); if (options !== false) { lazyLoadRimraf(); return rimrafSync(pathModule.toNamespacedPath(path), options); } } else { validateRmdirOptions(options); } var ctx = { path: path }; binding.rmdir(pathModule.toNamespacedPath(path), undefined, ctx); return handleErrorFromBinding(ctx); } /** * Asynchronously removes files and * directories (modeled on the standard POSIX `rm` utility). * @param {string | Buffer | URL} path * @param {{ * force?: boolean; * maxRetries?: number; * recursive?: boolean; * retryDelay?: number; * }} [options] * @param {(err?: Error) => any} callback * @returns {void} */ function rm(path, options, callback) { if (typeof options === 'function') { callback = options; options = undefined; } validateRmOptions(path, options, false, function (err, options) { if (err) { return callback(err); } lazyLoadRimraf(); return rimraf(pathModule.toNamespacedPath(path), options, callback); }); } /** * Synchronously removes files and * directories (modeled on the standard POSIX `rm` utility). * @param {string | Buffer | URL} path * @param {{ * force?: boolean; * maxRetries?: number; * recursive?: boolean; * retryDelay?: number; * }} [options] * @returns {void} */ function rmSync(path, options) { options = validateRmOptionsSync(path, options, false); lazyLoadRimraf(); return rimrafSync(pathModule.toNamespacedPath(path), options); } /** * Forces all currently queued I/O operations associated * with the file to the operating system's synchronized * I/O completion state. * @param {number} fd * @param {(err?: Error) => any} callback * @returns {void} */ function fdatasync(fd, callback) { fd = getValidatedFd(fd); var req = new FSReqCallback(); req.oncomplete = makeCallback(callback); binding.fdatasync(fd, req); } /** * Synchronously forces all currently queued I/O operations * associated with the file to the operating * system's synchronized I/O completion state. * @param {number} fd * @returns {void} */ function fdatasyncSync(fd) { fd = getValidatedFd(fd); var ctx = {}; binding.fdatasync(fd, undefined, ctx); handleErrorFromBinding(ctx); } /** * Requests for all data for the open file descriptor * to be flushed to the storage device. * @param {number} fd * @param {(err?: Error) => any} callback * @returns {void} */ function fsync(fd, callback) { fd = getValidatedFd(fd); var req = new FSReqCallback(); req.oncomplete = makeCallback(callback); binding.fsync(fd, req); } /** * Synchronously requests for all data for the open * file descriptor to be flushed to the storage device. * @param {number} fd * @returns {void} */ function fsyncSync(fd) { fd = getValidatedFd(fd); var ctx = {}; binding.fsync(fd, undefined, ctx); handleErrorFromBinding(ctx); } /** * Asynchronously creates a directory. * @param {string | Buffer | URL} path * @param {{ * recursive?: boolean; * mode?: string | number; * } | number} [options] * @param {(err?: Error) => any} callback * @returns {void} */ function mkdir(path, options, callback) { var mode = 511; var recursive = false; if (typeof options === 'function') { callback = options; } else if (typeof options === 'number' || typeof options === 'string') { mode = options; } else if (options) { if (options.recursive !== undefined) recursive = options.recursive; if (options.mode !== undefined) mode = options.mode; } callback = makeCallback(callback); path = getValidatedPath(path); validateBoolean(recursive, 'options.recursive'); var req = new FSReqCallback(); req.oncomplete = callback; binding.mkdir(pathModule.toNamespacedPath(path), parseFileMode(mode, 'mode'), recursive, req); } /** * Synchronously creates a directory. * @param {string | Buffer | URL} path * @param {{ * recursive?: boolean; * mode?: string | number; * } | number} [options] * @returns {string | void} */ function mkdirSync(path, options) { var mode = 511; var recursive = false; if (typeof options === 'number' || typeof options === 'string') { mode = options; } else if (options) { if (options.recursive !== undefined) recursive = options.recursive; if (options.mode !== undefined) mode = options.mode; } path = getValidatedPath(path); validateBoolean(recursive, 'options.recursive'); var ctx = { path: path }; var result = binding.mkdir(pathModule.toNamespacedPath(path), parseFileMode(mode, 'mode'), recursive, undefined, ctx); handleErrorFromBinding(ctx); if (recursive) { return result; } } /** * Reads the contents of a directory. * @param {string | Buffer | URL} path * @param {string | { * encoding?: string; * withFileTypes?: boolean; * }} [options] * @param {( * err?: Error, * files?: string[] | Buffer[] | Direct[]; * ) => any} callback * @returns {void} */ function readdir(path, options, callback) { callback = makeCallback(typeof options === 'function' ? options : callback); options = getOptions(options, {}); path = getValidatedPath(path); var req = new FSReqCallback(); if (!options.withFileTypes) { req.oncomplete = callback; } else { req.oncomplete = function (err, result) { if (err) { callback(err); return; } getDirents(path, result, callback); }; } binding.readdir(pathModule.toNamespacedPath(path), options.encoding, !!options.withFileTypes, req); } /** * Synchronously reads the contents of a directory. * @param {string | Buffer | URL} path * @param {string | { * encoding?: string; * withFileTypes?: boolean; * }} [options] * @returns {string | Buffer[] | Dirent[]} */ function readdirSync(path, options) { options = getOptions(options, {}); path = getValidatedPath(path); var ctx = { path: path }; var result = binding.readdir(pathModule.toNamespacedPath(path), options.encoding, !!options.withFileTypes, undefined, ctx); handleErrorFromBinding(ctx); return options.withFileTypes ? getDirents(path, result) : result; } /** * Invokes the callback with the `fs.Stats` * for the file descriptor. * @param {number} fd * @param {{ bigint?: boolean; }} [options] * @param {( * err?: Error, * stats?: Stats * ) => any} callback * @returns {void} */ function fstat(fd) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { bigint: false }; var callback = arguments.length > 2 ? arguments[2] : undefined; if (typeof options === 'function') { callback = options; options = {}; } fd = getValidatedFd(fd); callback = makeStatsCallback(callback); var req = new FSReqCallback(options.bigint); req.oncomplete = callback; binding.fstat(fd, options.bigint, req); } /** * Retrieves the `fs.Stats` for the symbolic link * referred to by the `path`. * @param {string | Buffer | URL} path * @param {{ bigint?: boolean; }} [options] * @param {( * err?: Error, * stats?: Stats * ) => any} callback * @returns {void} */ function lstat(path) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { bigint: false }; var callback = arguments.length > 2 ? arguments[2] : undefined; if (typeof options === 'function') { callback = options; options = {}; } callback = makeStatsCallback(callback); path = getValidatedPath(path); var req = new FSReqCallback(options.bigint); req.oncomplete = callback; binding.lstat(pathModule.toNamespacedPath(path), options.bigint, req); } /** * Asynchronously gets the stats of a file. * @param {string | Buffer | URL} path * @param {{ bigint?: boolean; }} [options] * @param {( * err?: Error, * stats?: Stats * ) => any} callback * @returns {void} */ function stat(path) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { bigint: false }; var callback = arguments.length > 2 ? arguments[2] : undefined; if (typeof options === 'function') { callback = options; options = {}; } callback = makeStatsCallback(callback); path = getValidatedPath(path); var req = new FSReqCallback(options.bigint); req.oncomplete = callback; binding.stat(pathModule.toNamespacedPath(path), options.bigint, req); } function hasNoEntryError(ctx) { if (ctx.errno) { var uvErr = uvErrmapGet(ctx.errno); return (uvErr === null || uvErr === void 0 ? void 0 : uvErr[0]) === 'ENOENT'; } if (ctx.error) { return ctx.error.code === 'ENOENT'; } return false; } /** * Synchronously retrieves the `fs.Stats` for * the file descriptor. * @param {number} fd * @param {{ * bigint?: boolean; * throwIfNoEntry?: boolean; * }} [options] * @returns {Stats} */ function fstatSync(fd) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { bigint: false, throwIfNoEntry: true }; fd = getValidatedFd(fd); var ctx = { fd: fd }; var stats = binding.fstat(fd, options.bigint, undefined, ctx); handleErrorFromBinding(ctx); return getStatsFromBinding(stats); } /** * Synchronously retrieves the `fs.Stats` for * the symbolic link referred to by the `path`. * @param {string | Buffer | URL} path * @param {{ * bigint?: boolean; * throwIfNoEntry?: boolean; * }} [options] * @returns {Stats} */ function lstatSync(path) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { bigint: false, throwIfNoEntry: true }; path = getValidatedPath(path); var ctx = { path: path }; var stats = binding.lstat(pathModule.toNamespacedPath(path), options.bigint, undefined, ctx); if (options.throwIfNoEntry === false && hasNoEntryError(ctx)) { return undefined; } handleErrorFromBinding(ctx); return getStatsFromBinding(stats); } /** * Synchronously retrieves the `fs.Stats` * for the `path`. * @param {string | Buffer | URL} path * @param {{ * bigint?: boolean; * throwIfNoEntry?: boolean; * }} [options] * @returns {Stats} */ function statSync(path) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { bigint: false, throwIfNoEntry: true }; path = getValidatedPath(path); var ctx = { path: path }; var stats = binding.stat(pathModule.toNamespacedPath(path), options.bigint, undefined, ctx); if (options.throwIfNoEntry === false && hasNoEntryError(ctx)) { return undefined; } handleErrorFromBinding(ctx); return getStatsFromBinding(stats); } /** * Reads the contents of a symbolic link * referred to by `path`. * @param {string | Buffer | URL} path * @param {{ encoding?: string; } | string} [options] * @param {( * err?: Error, * linkString?: string | Buffer * ) => any} callback * @returns {void} */ function readlink(path, options, callback) { callback = makeCallback(typeof options === 'function' ? options : callback); options = getOptions(options, {}); path = getValidatedPath(path, 'oldPath'); var req = new FSReqCallback(); req.oncomplete = callback; binding.readlink(pathModule.toNamespacedPath(path), options.encoding, req); } /** * Synchronously reads the contents of a symbolic link * referred to by `path`. * @param {string | Buffer | URL} path * @param {{ encoding?: string; } | string} [options] * @returns {string | Buffer} */ function readlinkSync(path, options) { options = getOptions(options, {}); path = getValidatedPath(path, 'oldPath'); var ctx = { path: path }; var result = binding.readlink(pathModule.toNamespacedPath(path), options.encoding, undefined, ctx); handleErrorFromBinding(ctx); return result; } /** * Creates the link called `path` pointing to `target`. * @param {string | Buffer | URL} target * @param {string | Buffer | URL} path * @param {string} [type_] * @param {(err?: Error) => any} callback_ * @returns {void} */ function symlink(target, path, type_, callback_) { var type = typeof type_ === 'string' ? type_ : null; var callback = makeCallback(arguments[arguments.length - 1]); target = getValidatedPath(target, 'target'); path = getValidatedPath(path); if (isWindows && type === null) { var absoluteTarget; try { // Symlinks targets can be relative to the newly created path. // Calculate absolute file name of the symlink target, and check // if it is a directory. Ignore resolve error to keep symlink // errors consistent between platforms if invalid path is // provided. absoluteTarget = pathModule.resolve(path, '..', target); } catch (_unused3) {} if (absoluteTarget !== undefined) { stat(absoluteTarget, function (err, stat) { var resolvedType = !err && stat.isDirectory() ? 'dir' : 'file'; var resolvedFlags = stringToSymlinkType(resolvedType); var destination = preprocessSymlinkDestination(target, resolvedType, path); var req = new FSReqCallback(); req.oncomplete = callback; binding.symlink(destination, pathModule.toNamespacedPath(path), resolvedFlags, req); }); return; } } var destination = preprocessSymlinkDestination(target, type, path); var flags = stringToSymlinkType(type); var req = new FSReqCallback(); req.oncomplete = callback; binding.symlink(destination, pathModule.toNamespacedPath(path), flags, req); } /** * Synchronously creates the link called `path` * pointing to `target`. * @param {string | Buffer | URL} target * @param {string | Buffer | URL} path * @param {string} [type] * @returns {void} */ function symlinkSync(target, path, type) { type = typeof type === 'string' ? type : null; if (isWindows && type === null) { var _statSync; var absoluteTarget = pathModule.resolve("".concat(path), '..', "".concat(target)); if ((_statSync = statSync(absoluteTarget, { throwIfNoEntry: false })) !== null && _statSync !== void 0 && _statSync.isDirectory()) { type = 'dir'; } } target = getValidatedPath(target, 'target'); path = getValidatedPath(path); var flags = stringToSymlinkType(type); var ctx = { path: target, dest: path }; binding.symlink(preprocessSymlinkDestination(target, type, path), pathModule.toNamespacedPath(path), flags, undefined, ctx); handleErrorFromBinding(ctx); } /** * Creates a new link from the `existingPath` * to the `newPath`. * @param {string | Buffer | URL} existingPath * @param {string | Buffer | URL} newPath * @param {(err?: Error) => any} callback * @returns {void} */ function link(existingPath, newPath, callback) { callback = makeCallback(callback); existingPath = getValidatedPath(existingPath, 'existingPath'); newPath = getValidatedPath(newPath, 'newPath'); var req = new FSReqCallback(); req.oncomplete = callback; binding.link(pathModule.toNamespacedPath(existingPath), pathModule.toNamespacedPath(newPath), req); } /** * Synchronously creates a new link from the `existingPath` * to the `newPath`. * @param {string | Buffer | URL} existingPath * @param {string | Buffer | URL} newPath * @returns {void} */ function linkSync(existingPath, newPath) { existingPath = getValidatedPath(existingPath, 'existingPath'); newPath = getValidatedPath(newPath, 'newPath'); var ctx = { path: existingPath, dest: newPath }; var result = binding.link(pathModule.toNamespacedPath(existingPath), pathModule.toNamespacedPath(newPath), undefined, ctx); handleErrorFromBinding(ctx); return result; } /** * Asynchronously removes a file or symbolic link. * @param {string | Buffer | URL} path * @param {(err?: Error) => any} callback * @returns {void} */ function unlink(path, callback) { callback = makeCallback(callback); path = getValidatedPath(path); var req = new FSReqCallback(); req.oncomplete = callback; binding.unlink(pathModule.toNamespacedPath(path), req); } /** * Synchronously removes a file or symbolic link. * @param {string | Buffer | URL} path * @returns {void} */ function unlinkSync(path) { path = getValidatedPath(path); var ctx = { path: path }; binding.unlink(pathModule.toNamespacedPath(path), undefined, ctx); handleErrorFromBinding(ctx); } /** * Sets the permissions on the file. * @param {number} fd * @param {string | number} mode * @param {(err?: Error) => any} callback * @returns {void} */ function fchmod(fd, mode, callback) { fd = getValidatedFd(fd); mode = parseFileMode(mode, 'mode'); callback = makeCallback(callback); var req = new FSReqCallback(); req.oncomplete = callback; binding.fchmod(fd, mode, req); } /** * Synchronously sets the permissions on the file. * @param {number} fd * @param {string | number} mode * @returns {void} */ function fchmodSync(fd, mode) { fd = getValidatedFd(fd); mode = parseFileMode(mode, 'mode'); var ctx = {}; binding.fchmod(fd, mode, undefined, ctx); handleErrorFromBinding(ctx); } /** * Changes the permissions on a symbolic link. * @param {string | Buffer | URL} path * @param {number} mode * @param {(err?: Error) => any} callback * @returns {void} */ function lchmod(path, mode, callback) { callback = maybeCallback(callback); mode = parseFileMode(mode, 'mode'); fs.open(path, O_WRONLY | O_SYMLINK, function (err, fd) { if (err) { callback(err); return; } // Prefer to return the chmod error, if one occurs, // but still try to close, and report closing errors if they occur. fs.fchmod(fd, mode, function (err) { fs.close(fd, function (err2) { callback(aggregateTwoErrors(err2, err)); }); }); }); } /** * Synchronously changes the permissions on a symbolic link. * @param {string | Buffer | URL} path * @param {number} mode * @returns {void} */ function lchmodSync(path, mode) { var fd = fs.openSync(path, O_WRONLY | O_SYMLINK); // Prefer to return the chmod error, if one occurs, // but still try to close, and report closing errors if they occur. var ret; try { ret = fs.fchmodSync(fd, mode); } finally { fs.closeSync(fd); } return ret; } /** * Asynchronously changes the permissions of a file. * @param {string | Buffer | URL} path * @param {string | number} mode * @param {(err?: Error) => any} callback * @returns {void} */ function chmod(path, mode, callback) { path = getValidatedPath(path); mode = parseFileMode(mode, 'mode'); callback = makeCallback(callback); var req = new FSReqCallback(); req.oncomplete = callback; binding.chmod(pathModule.toNamespacedPath(path), mode, req); } /** * Synchronously changes the permissions of a file. * @param {string | Buffer | URL} path * @param {string | number} mode * @returns {void} */ function chmodSync(path, mode) { path = getValidatedPath(path); mode = parseFileMode(mode, 'mode'); var ctx = { path: path }; binding.chmod(pathModule.toNamespacedPath(path), mode, undefined, ctx); handleErrorFromBinding(ctx); } /** * Sets the owner of the symbolic link. * @param {string | Buffer | URL} path * @param {number} uid * @param {number} gid * @param {(err?: Error) => any} callback * @returns {void} */ function lchown(path, uid, gid, callback) { callback = makeCallback(callback); path = getValidatedPath(path); validateInteger(uid, 'uid', -1, kMaxUserId); validateInteger(gid, 'gid', -1, kMaxUserId); var req = new FSReqCallback(); req.oncomplete = callback; binding.lchown(pathModule.toNamespacedPath(path), uid, gid, req); } /** * Synchronously sets the owner of the symbolic link. * @param {string | Buffer | URL} path * @param {number} uid * @param {number} gid * @returns {void} */ function lchownSync(path, uid, gid) { path = getValidatedPath(path); validateInteger(uid, 'uid', -1, kMaxUserId); validateInteger(gid, 'gid', -1, kMaxUserId); var ctx = { path: path }; binding.lchown(pathModule.toNamespacedPath(path), uid, gid, undefined, ctx); handleErrorFromBinding(ctx); } /** * Sets the owner of the file. * @param {number} fd * @param {number} uid * @param {number} gid * @param {(err?: Error) => any} callback * @returns {void} */ function fchown(fd, uid, gid, callback) { fd = getValidatedFd(fd); validateInteger(uid, 'uid', -1, kMaxUserId); validateInteger(gid, 'gid', -1, kMaxUserId); callback = makeCallback(callback); var req = new FSReqCallback(); req.oncomplete = callback; binding.fchown(fd, uid, gid, req); } /** * Synchronously sets the owner of the file. * @param {number} fd * @param {number} uid * @param {number} gid * @returns {void} */ function fchownSync(fd, uid, gid) { fd = getValidatedFd(fd); validateInteger(uid, 'uid', -1, kMaxUserId); validateInteger(gid, 'gid', -1, kMaxUserId); var ctx = {}; binding.fchown(fd, uid, gid, undefined, ctx); handleErrorFromBinding(ctx); } /** * Asynchronously changes the owner and group * of a file. * @param {string | Buffer | URL} path * @param {number} uid * @param {number} gid * @param {(err?: Error) => any} callback * @returns {void} */ function chown(path, uid, gid, callback) { callback = makeCallback(callback); path = getValidatedPath(path); validateInteger(uid, 'uid', -1, kMaxUserId); validateInteger(gid, 'gid', -1, kMaxUserId); var req = new FSReqCallback(); req.oncomplete = callback; binding.chown(pathModule.toNamespacedPath(path), uid, gid, req); } /** * Synchronously changes the owner and group * of a file. * @param {string | Buffer | URL} path * @param {number} uid * @param {number} gid * @returns {void} */ function chownSync(path, uid, gid) { path = getValidatedPath(path); validateInteger(uid, 'uid', -1, kMaxUserId); validateInteger(gid, 'gid', -1, kMaxUserId); var ctx = { path: path }; binding.chown(pathModule.toNamespacedPath(path), uid, gid, undefined, ctx); handleErrorFromBinding(ctx); } /** * Changes the file system timestamps of the object * referenced by `path`. * @param {string | Buffer | URL} path * @param {number | string | Date} atime * @param {number | string | Date} mtime * @param {(err?: Error) => any} callback * @returns {void} */ function utimes(path, atime, mtime, callback) { callback = makeCallback(callback); path = getValidatedPath(path); var req = new FSReqCallback(); req.oncomplete = callback; binding.utimes(pathModule.toNamespacedPath(path), toUnixTimestamp(atime), toUnixTimestamp(mtime), req); } /** * Synchronously changes the file system timestamps * of the object referenced by `path`. * @param {string | Buffer | URL} path * @param {number | string | Date} atime * @param {number | string | Date} mtime * @returns {void} */ function utimesSync(path, atime, mtime) { path = getValidatedPath(path); var ctx = { path: path }; binding.utimes(pathModule.toNamespacedPath(path), toUnixTimestamp(atime), toUnixTimestamp(mtime), undefined, ctx); handleErrorFromBinding(ctx); } /** * Changes the file system timestamps of the object * referenced by the supplied `fd` (file descriptor). * @param {number} fd * @param {number | string | Date} atime * @param {number | string | Date} mtime * @param {(err?: Error) => any} callback * @returns {void} */ function futimes(fd, atime, mtime, callback) { fd = getValidatedFd(fd); atime = toUnixTimestamp(atime, 'atime'); mtime = toUnixTimestamp(mtime, 'mtime'); callback = makeCallback(callback); var req = new FSReqCallback(); req.oncomplete = callback; binding.futimes(fd, atime, mtime, req); } /** * Synchronously changes the file system timestamps * of the object referenced by the * supplied `fd` (file descriptor). * @param {number} fd * @param {number | string | Date} atime * @param {number | string | Date} mtime * @returns {void} */ function futimesSync(fd, atime, mtime) { fd = getValidatedFd(fd); atime = toUnixTimestamp(atime, 'atime'); mtime = toUnixTimestamp(mtime, 'mtime'); var ctx = {}; binding.futimes(fd, atime, mtime, undefined, ctx); handleErrorFromBinding(ctx); } /** * Changes the access and modification times of * a file in the same way as `fs.utimes()`. * @param {string | Buffer | URL} path * @param {number | string | Date} atime * @param {number | string | Date} mtime * @param {(err?: Error) => any} callback * @returns {void} */ function lutimes(path, atime, mtime, callback) { callback = makeCallback(callback); path = getValidatedPath(path); var req = new FSReqCallback(); req.oncomplete = callback; binding.lutimes(pathModule.toNamespacedPath(path), toUnixTimestamp(atime), toUnixTimestamp(mtime), req); } /** * Synchronously changes the access and modification * times of a file in the same way as `fs.utimesSync()`. * @param {string | Buffer | URL} path * @param {number | string | Date} atime * @param {number | string | Date} mtime * @returns {void} */ function lutimesSync(path, atime, mtime) { path = getValidatedPath(path); var ctx = { path: path }; binding.lutimes(pathModule.toNamespacedPath(path), toUnixTimestamp(atime), toUnixTimestamp(mtime), undefined, ctx); handleErrorFromBinding(ctx); } function writeAll(fd, isUserFd, buffer, offset, length, signal, callback) { if (signal !== null && signal !== void 0 && signal.aborted) { var abortError = new AbortError(); if (isUserFd) { callback(abortError); } else { fs.close(fd, function (err) { callback(aggregateTwoErrors(err, abortError)); }); } return; } // write(fd, buffer, offset, length, position, callback) fs.write(fd, buffer, offset, length, null, function (writeErr, written) { if (writeErr) { if (isUserFd) { callback(writeErr); } else { fs.close(fd, function (err) { callback(aggregateTwoErrors(err, writeErr)); }); } } else if (written === length) { if (isUserFd) { callback(null); } else { fs.close(fd, callback); } } else { offset += written; length -= written; writeAll(fd, isUserFd, buffer, offset, length, signal, callback); } }); } /** * Asynchronously writes data to the file. * @param {string | Buffer | URL | number} path * @param {string | Buffer | TypedArray | DataView | Object} data * @param {{ * encoding?: string | null; * mode?: number; * flag?: string; * signal?: AbortSignal; * } | string} [options] * @param {(err?: Error) => any} callback * @returns {void} */ function writeFile(path, data, options, callback) { callback = maybeCallback(callback || options); options = getOptions(options, { encoding: 'utf8', mode: 438, flag: 'w' }); var flag = options.flag || 'w'; if (!isArrayBufferView(data)) { validateStringAfterArrayBufferView(data, 'data'); data = Buffer.from(String(data), options.encoding || 'utf8'); } if (isFd(path)) { var isUserFd = true; var signal = options.signal; writeAll(path, isUserFd, data, 0, data.byteLength, signal, callback); return; } if (checkAborted(options.signal, callback)) return; fs.open(path, flag, options.mode, function (openErr, fd) { if (openErr) { callback(openErr); } else { var _isUserFd = false; var _signal = options.signal; writeAll(fd, _isUserFd, data, 0, data.byteLength, _signal, callback); } }); } /** * Synchronously writes data to the file. * @param {string | Buffer | URL | number} path * @param {string | Buffer | TypedArray | DataView | Object} data * @param {{ * encoding?: string | null; * mode?: number; * flag?: string; * } | string} [options] * @returns {void} */ function writeFileSync(path, data, options) { options = getOptions(options, { encoding: 'utf8', mode: 438, flag: 'w' }); if (!isArrayBufferView(data)) { validateStringAfterArrayBufferView(data, 'data'); data = Buffer.from(String(data), options.encoding || 'utf8'); } var flag = options.flag || 'w'; var isUserFd = isFd(path); // File descriptor ownership var fd = isUserFd ? path : fs.openSync(path, flag, options.mode); var offset = 0; var length = data.byteLength; try { while (length > 0) { var written = fs.writeSync(fd, data, offset, length); offset += written; length -= written; } } finally { if (!isUserFd) fs.closeSync(fd); } } /** * Asynchronously appends data to a file. * @param {string | Buffer | URL | number} path * @param {string | Buffer} data * @param {{ * encoding?: string | null; * mode?: number; * flag?: string; * } | string} [options] * @param {(err?: Error) => any} callback * @returns {void} */ function appendFile(path, data, options, callback) { callback = maybeCallback(callback || options); options = getOptions(options, { encoding: 'utf8', mode: 438, flag: 'a' }); // Don't make changes directly on options object options = copyObject(options); // Force append behavior when using a supplied file descriptor if (!options.flag || isFd(path)) options.flag = 'a'; fs.writeFile(path, data, options, callback); } /** * Synchronously appends data to a file. * @param {string | Buffer | URL | number} path * @param {string | Buffer} data * @param {{ * encoding?: string | null; * mode?: number; * flag?: string; * } | string} [options] * @returns {void} */ function appendFileSync(path, data, options) { options = getOptions(options, { encoding: 'utf8', mode: 438, flag: 'a' }); // Don't make changes directly on options object options = copyObject(options); // Force append behavior when using a supplied file descriptor if (!options.flag || isFd(path)) options.flag = 'a'; fs.writeFileSync(path, data, options); } /** * Watches for the changes on `filename`. * @param {string | Buffer | URL} filename * @param {string | { * persistent?: boolean; * recursive?: boolean; * encoding?: string; * signal?: AbortSignal; * }} [options] * @param {( * eventType?: string, * filename?: string | Buffer * ) => any} [listener] * @returns {watchers.FSWatcher} */ function watch(filename, options, listener) { if (typeof options === 'function') { listener = options; } options = getOptions(options, {}); // Don't make changes directly on options object options = copyObject(options); if (options.persistent === undefined) options.persistent = true; if (options.recursive === undefined) options.recursive = false; if (options.recursive && !(isOSX || isWindows)) throw new ERR_FEATURE_UNAVAILABLE_ON_PLATFORM('watch recursively'); var watcher = new watchers.FSWatcher(); watcher[watchers.kFSWatchStart](filename, options.persistent, options.recursive, options.encoding); if (listener) { watcher.addListener('change', listener); } if (options.signal) { if (options.signal.aborted) { process.nextTick(function () { return watcher.close(); }); } else { var _listener = function _listener() { return watcher.close(); }; options.signal.addEventListener('abort', _listener); watcher.once('close', function () { options.signal.removeEventListener('abort', _listener); }); } } return watcher; } var statWatchers = new SafeMap(); /** * Watches for changes on `filename`. * @param {string | Buffer | URL} filename * @param {{ * bigint?: boolean; * persistent?: boolean; * interval?: number; * }} [options] * @param {( * current?: Stats, * previous?: Stats * ) => any} listener * @returns {watchers.StatWatcher} */ function watchFile(filename, options, listener) { filename = getValidatedPath(filename); filename = pathModule.resolve(filename); var stat; if (options === null || _typeof(options) !== 'object') { listener = options; options = null; } options = _objectSpread({ // Poll interval in milliseconds. 5007 is what libev used to use. It's // a little on the slow side but let's stick with it for now to keep // behavioral changes to a minimum. interval: 5007, persistent: true }, options); validateFunction(listener, 'listener'); stat = statWatchers.get(filename); if (stat === undefined) { stat = new watchers.StatWatcher(options.bigint); stat[watchers.kFSStatWatcherStart](filename, options.persistent, options.interval); statWatchers.set(filename, stat); } else { stat[watchers.kFSStatWatcherAddOrCleanRef]('add'); } stat.addListener('change', listener); return stat; } /** * Stops watching for changes on `filename`. * @param {string | Buffer | URL} filename * @param {() => any} [listener] * @returns {void} */ function unwatchFile(filename, listener) { filename = getValidatedPath(filename); filename = pathModule.resolve(filename); var stat = statWatchers.get(filename); if (stat === undefined) return; if (typeof listener === 'function') { var beforeListenerCount = stat.listenerCount('change'); stat.removeListener('change', listener); if (stat.listenerCount('change') < beforeListenerCount) stat[watchers.kFSStatWatcherAddOrCleanRef]('clean'); } else { stat.removeAllListeners('change'); stat[watchers.kFSStatWatcherAddOrCleanRef]('cleanAll'); } if (stat.listenerCount('change') === 0) { stat.stop(); statWatchers["delete"](filename); } } var splitRoot; // if (isWindows) { // // Regex to find the device root on Windows (e.g. 'c:\\'), including trailing // // slash. // var splitRootRe = /^(?:[a-zA-Z]:|[\\/]{2}[^\\/]+[\\/][^\\/]+)?[\\/]*/; // splitRoot = function splitRoot(str) { // return RegExpPrototypeExec(splitRootRe, str)[0]; // }; // } else { // splitRoot = function splitRoot(str) { // for (var i = 0; i < str.length; ++i) { // if (StringPrototypeCharCodeAt(str, i) !== CHAR_FORWARD_SLASH) return StringPrototypeSlice(str, 0, i); // } // return str; // }; // } function encodeRealpathResult(result, options) { if (!options || !options.encoding || options.encoding === 'utf8') return result; var asBuffer = Buffer.from(result); if (options.encoding === 'buffer') { return asBuffer; } return asBuffer.toString(options.encoding); } // Finds the next portion of a (partial) path, up to the next path delimiter var nextPart; // if (isWindows) { // nextPart = function nextPart(p, i) { // for (; i < p.length; ++i) { // var ch = StringPrototypeCharCodeAt(p, i); // Check for a separator character // if (ch === CHAR_BACKWARD_SLASH || ch === CHAR_FORWARD_SLASH) return i; // } // return -1; // }; // } else { // nextPart = function nextPart(p, i) { // return StringPrototypeIndexOf(p, '/', i); // }; // } var emptyObj = ObjectCreate(null); /** * Returns the resolved pathname. * @param {string | Buffer | URL} p * @param {string | { encoding?: string | null; }} [options] * @returns {string | Buffer} */ function realpathSync(p, options) { options = getOptions(options, emptyObj); p = toPathIfFileURL(p); if (typeof p !== 'string') { p += ''; } validatePath(p); p = pathModule.resolve(p); var cache = options[realpathCacheKey]; var maybeCachedResult = cache === null || cache === void 0 ? void 0 : cache.get(p); if (maybeCachedResult) { return maybeCachedResult; } var seenLinks = ObjectCreate(null); var knownHard = ObjectCreate(null); var original = p; // Current character position in p var pos; // The partial path so far, including a trailing slash if any var current; // The partial path without a trailing slash (except when pointing at a root) var base; // The partial path scanned in the previous round, with slash var previous; // Skip over roots current = base = splitRoot(p); pos = current.length; // On windows, check that the root exists. On unix there is no need. if (isWindows) { var ctx = { path: base }; binding.lstat(pathModule.toNamespacedPath(base), false, undefined, ctx); handleErrorFromBinding(ctx); knownHard[base] = true; } // Walk down the path, swapping out linked path parts for their real // values // NB: p.length changes. while (pos < p.length) { // find the next part var result = nextPart(p, pos); previous = current; if (result === -1) { var last = StringPrototypeSlice(p, pos); current += last; base = previous + last; pos = p.length; } else { current += StringPrototypeSlice(p, pos, result + 1); base = previous + StringPrototypeSlice(p, pos, result); pos = result + 1; } // Continue if not a symlink, break if a pipe/socket if (knownHard[base] || (cache === null || cache === void 0 ? void 0 : cache.get(base)) === base) { if (isFileType(binding.statValues, S_IFIFO) || isFileType(binding.statValues, S_IFSOCK)) { break; } continue; } var resolvedLink = void 0; var maybeCachedResolved = cache === null || cache === void 0 ? void 0 : cache.get(base); if (maybeCachedResolved) { resolvedLink = maybeCachedResolved; } else { // Use stats array directly to avoid creating an fs.Stats instance just // for our internal use. var baseLong = pathModule.toNamespacedPath(base); var _ctx = { path: base }; var stats = binding.lstat(baseLong, true, undefined, _ctx); handleErrorFromBinding(_ctx); if (!isFileType(stats, S_IFLNK)) { knownHard[base] = true; cache === null || cache === void 0 ? void 0 : cache.set(base, base); continue; } // Read the link if it wasn't read before // dev/ino always return 0 on windows, so skip the check. var linkTarget = null; var id = void 0; if (!isWindows) { var dev = BigIntPrototypeToString(stats[0], 32); var ino = BigIntPrototypeToString(stats[7], 32); id = "".concat(dev, ":").concat(ino); if (seenLinks[id]) { linkTarget = seenLinks[id]; } } if (linkTarget === null) { var _ctx2 = { path: base }; binding.stat(baseLong, false, undefined, _ctx2); handleErrorFromBinding(_ctx2); linkTarget = binding.readlink(baseLong, undefined, undefined, _ctx2); handleErrorFromBinding(_ctx2); } resolvedLink = pathModule.resolve(previous, linkTarget); if (cache) cache.set(base, resolvedLink); if (!isWindows) seenLinks[id] = linkTarget; } // Resolve the link, then start over p = pathModule.resolve(resolvedLink, StringPrototypeSlice(p, pos)); // Skip over roots current = base = splitRoot(p); pos = current.length; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { var _ctx3 = { path: base }; binding.lstat(pathModule.toNamespacedPath(base), false, undefined, _ctx3); handleErrorFromBinding(_ctx3); knownHard[base] = true; } } cache === null || cache === void 0 ? void 0 : cache.set(original, p); return encodeRealpathResult(p, options); } /** * Returns the resolved pathname. * @param {string | Buffer | URL} p * @param {string | { encoding?: string; }} [options] * @returns {string | Buffer} */ realpathSync["native"] = function (path, options) { options = getOptions(options, {}); path = getValidatedPath(path); var ctx = { path: path }; var result = binding.realpath(path, options.encoding, undefined, ctx); handleErrorFromBinding(ctx); return result; }; /** * Asynchronously computes the canonical pathname by * resolving `.`, `..` and symbolic links. * @param {string | Buffer | URL} p * @param {string | { encoding?: string; }} [options] * @param {( * err?: Error, * resolvedPath?: string | Buffer * ) => any} callback * @returns {void} */ function realpath(p, options, callback) { callback = typeof options === 'function' ? options : maybeCallback(callback); options = getOptions(options, {}); p = toPathIfFileURL(p); if (typeof p !== 'string') { p += ''; } validatePath(p); p = pathModule.resolve(p); var seenLinks = ObjectCreate(null); var knownHard = ObjectCreate(null); // Current character position in p var pos; // The partial path so far, including a trailing slash if any var current; // The partial path without a trailing slash (except when pointing at a root) var base; // The partial path scanned in the previous round, with slash var previous; current = base = splitRoot(p); pos = current.length; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstat(base, function (err, stats) { if (err) return callback(err); knownHard[base] = true; LOOP(); }); } else { process.nextTick(LOOP); } // Walk down the path, swapping out linked path parts for their real // values function LOOP() { // Stop if scanned past end of path if (pos >= p.length) { return callback(null, encodeRealpathResult(p, options)); } // find the next part var result = nextPart(p, pos); previous = current; if (result === -1) { var last = StringPrototypeSlice(p, pos); current += last; base = previous + last; pos = p.length; } else { current += StringPrototypeSlice(p, pos, result + 1); base = previous + StringPrototypeSlice(p, pos, result); pos = result + 1; } // Continue if not a symlink, break if a pipe/socket if (knownHard[base]) { if (isFileType(binding.statValues, S_IFIFO) || isFileType(binding.statValues, S_IFSOCK)) { return callback(null, encodeRealpathResult(p, options)); } return process.nextTick(LOOP); } return fs.lstat(base, { bigint: true }, gotStat); } function gotStat(err, stats) { if (err) return callback(err); // If not a symlink, skip to the next path part if (!stats.isSymbolicLink()) { knownHard[base] = true; return process.nextTick(LOOP); } // Stat & read the link if not read before. // Call `gotTarget()` as soon as the link target is known. // `dev`/`ino` always return 0 on windows, so skip the check. var id; if (!isWindows) { var dev = BigIntPrototypeToString(stats.dev, 32); var ino = BigIntPrototypeToString(stats.ino, 32); id = "".concat(dev, ":").concat(ino); if (seenLinks[id]) { return gotTarget(null, seenLinks[id]); } } fs.stat(base, function (err) { if (err) return callback(err); fs.readlink(base, function (err, target) { if (!isWindows) seenLinks[id] = target; gotTarget(err, target); }); }); } function gotTarget(err, target) { if (err) return callback(err); gotResolvedLink(pathModule.resolve(previous, target)); } function gotResolvedLink(resolvedLink) { // Resolve the link, then start over p = pathModule.resolve(resolvedLink, StringPrototypeSlice(p, pos)); current = base = splitRoot(p); pos = current.length; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstat(base, function (err) { if (err) return callback(err); knownHard[base] = true; LOOP(); }); } else { process.nextTick(LOOP); } } } /** * Asynchronously computes the canonical pathname by * resolving `.`, `..` and symbolic links. * @param {string | Buffer | URL} p * @param {string | { encoding?: string; }} [options] * @param {( * err?: Error, * resolvedPath?: string | Buffer * ) => any} callback * @returns {void} */ realpath["native"] = function (path, options, callback) { callback = makeCallback(callback || options); options = getOptions(options, {}); path = getValidatedPath(path); var req = new FSReqCallback(); req.oncomplete = callback; return binding.realpath(path, options.encoding, req); }; /** * Creates a unique temporary directory. * @param {string} prefix * @param {string | { encoding?: string; }} [options] * @param {( * err?: Error, * directory?: string * ) => any} callback * @returns {void} */ function mkdtemp(prefix, options, callback) { callback = makeCallback(typeof options === 'function' ? options : callback); options = getOptions(options, {}); if (!prefix || typeof prefix !== 'string') { throw new ERR_INVALID_ARG_TYPE('prefix', 'string', prefix); } nullCheck(prefix, 'prefix'); warnOnNonPortableTemplate(prefix); var req = new FSReqCallback(); req.oncomplete = callback; binding.mkdtemp("".concat(prefix, "XXXXXX"), options.encoding, req); } /** * Synchronously creates a unique temporary directory. * @param {string} prefix * @param {string | { encoding?: string; }} [options] * @returns {string} */ function mkdtempSync(prefix, options) { options = getOptions(options, {}); if (!prefix || typeof prefix !== 'string') { throw new ERR_INVALID_ARG_TYPE('prefix', 'string', prefix); } nullCheck(prefix, 'prefix'); warnOnNonPortableTemplate(prefix); var path = "".concat(prefix, "XXXXXX"); var ctx = { path: path }; var result = binding.mkdtemp(path, options.encoding, undefined, ctx); handleErrorFromBinding(ctx); return result; } /** * Asynchronously copies `src` to `dest`. By * default, `dest` is overwritten if it already exists. * @param {string | Buffer | URL} src * @param {string | Buffer | URL} dest * @param {number} [mode] * @param {() => any} callback * @returns {void} */ function copyFile(src, dest, mode, callback) { if (typeof mode === 'function') { callback = mode; mode = 0; } src = getValidatedPath(src, 'src'); dest = getValidatedPath(dest, 'dest'); src = pathModule._makeLong(src); dest = pathModule._makeLong(dest); mode = getValidMode(mode, 'copyFile'); callback = makeCallback(callback); var req = new FSReqCallback(); req.oncomplete = callback; binding.copyFile(src, dest, mode, req); } /** * Synchronously copies `src` to `dest`. By * default, `dest` is overwritten if it already exists. * @param {string | Buffer | URL} src * @param {string | Buffer | URL} dest * @param {number} [mode] * @returns {void} */ function copyFileSync(src, dest, mode) { src = getValidatedPath(src, 'src'); dest = getValidatedPath(dest, 'dest'); var ctx = { path: src, dest: dest }; // non-prefixed src = pathModule._makeLong(src); dest = pathModule._makeLong(dest); mode = getValidMode(mode, 'copyFile'); binding.copyFile(src, dest, mode, undefined, ctx); handleErrorFromBinding(ctx); } function lazyLoadStreams() { if (!ReadStream) { var _require10 = require('internal/fs/streams'); ReadStream = _require10.ReadStream; WriteStream = _require10.WriteStream; FileReadStream = ReadStream; FileWriteStream = WriteStream; } } /** * Creates a readable stream with a default `highWaterMark` * of 64 kb. * @param {string | Buffer | URL} path * @param {string | { * flags?: string; * encoding?: string; * fd?: number | FileHandle; * mode?: number; * autoClose?: boolean; * emitClose?: boolean; * start: number; * end?: number; * highWaterMark?: number; * fs?: Object | null; * }} [options] * @returns {ReadStream} */ function createReadStream(path, options) { lazyLoadStreams(); return new ReadStream(path, options); } /** * Creates a write stream. * @param {string | Buffer | URL} path * @param {string | { * flags?: string; * encoding?: string; * fd?: number | FileHandle; * mode?: number; * autoClose?: boolean; * emitClose?: boolean; * start: number; * fs?: Object | null; * }} [options] * @returns {WriteStream} */ function createWriteStream(path, options) { lazyLoadStreams(); return new WriteStream(path, options); } module.exports = fs = { appendFile: appendFile, appendFileSync: appendFileSync, access: access, accessSync: accessSync, chown: chown, chownSync: chownSync, chmod: chmod, chmodSync: chmodSync, close: close, closeSync: closeSync, copyFile: copyFile, copyFileSync: copyFileSync, createReadStream: createReadStream, createWriteStream: createWriteStream, exists: exists, existsSync: existsSync, fchown: fchown, fchownSync: fchownSync, fchmod: fchmod, fchmodSync: fchmodSync, fdatasync: fdatasync, fdatasyncSync: fdatasyncSync, fstat: fstat, fstatSync: fstatSync, fsync: fsync, fsyncSync: fsyncSync, ftruncate: ftruncate, ftruncateSync: ftruncateSync, futimes: futimes, futimesSync: futimesSync, lchown: lchown, lchownSync: lchownSync, lchmod: constants.O_SYMLINK !== undefined ? lchmod : undefined, lchmodSync: constants.O_SYMLINK !== undefined ? lchmodSync : undefined, link: link, linkSync: linkSync, lstat: lstat, lstatSync: lstatSync, lutimes: lutimes, lutimesSync: lutimesSync, mkdir: mkdir, mkdirSync: mkdirSync, mkdtemp: mkdtemp, mkdtempSync: mkdtempSync, open: open, openSync: openSync, // opendir: opendir, // opendirSync: opendirSync, readdir: readdir, readdirSync: readdirSync, read: read, readSync: readSync, readv: readv, readvSync: readvSync, readFile: readFile, readFileSync: readFileSync, readlink: readlink, readlinkSync: readlinkSync, realpath: realpath, realpathSync: realpathSync, rename: rename, renameSync: renameSync, rm: rm, rmSync: rmSync, rmdir: rmdir, rmdirSync: rmdirSync, stat: stat, statSync: statSync, symlink: symlink, symlinkSync: symlinkSync, truncate: truncate, truncateSync: truncateSync, unwatchFile: unwatchFile, unlink: unlink, unlinkSync: unlinkSync, utimes: utimes, utimesSync: utimesSync, watch: watch, watchFile: watchFile, writeFile: writeFile, writeFileSync: writeFileSync, write: write, writeSync: writeSync, writev: writev, writevSync: writevSync, // Dir: Dir, // Dirent: Dirent, // Stats: Stats, get ReadStream() { lazyLoadStreams(); return ReadStream; }, set ReadStream(val) { ReadStream = val; }, get WriteStream() { lazyLoadStreams(); return WriteStream; }, set WriteStream(val) { WriteStream = val; }, // Legacy names... these have to be separate because of how graceful-fs // (and possibly other) modules monkey patch the values. get FileReadStream() { lazyLoadStreams(); return FileReadStream; }, set FileReadStream(val) { FileReadStream = val; }, get FileWriteStream() { lazyLoadStreams(); return FileWriteStream; }, set FileWriteStream(val) { FileWriteStream = val; }, // For tests // _toUnixTimestamp: toUnixTimestamp }; ObjectDefineProperties(fs, { F_OK: { enumerable: true, value: F_OK || 0 }, R_OK: { enumerable: true, value: R_OK || 0 }, W_OK: { enumerable: true, value: W_OK || 0 }, X_OK: { enumerable: true, value: X_OK || 0 }, constants: { configurable: false, enumerable: true, value: constants }, promises: { configurable: true, enumerable: true, get: function get() { if (promises === null) promises = require('internal/fs/promises').exports; return promises; } } });