11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst { 41cb0ef41Sopenharmony_ci Array, 51cb0ef41Sopenharmony_ci FunctionPrototypeBind, 61cb0ef41Sopenharmony_ci MathMin, 71cb0ef41Sopenharmony_ci ObjectDefineProperty, 81cb0ef41Sopenharmony_ci ObjectSetPrototypeOf, 91cb0ef41Sopenharmony_ci PromisePrototypeThen, 101cb0ef41Sopenharmony_ci ReflectApply, 111cb0ef41Sopenharmony_ci Symbol, 121cb0ef41Sopenharmony_ci} = primordials; 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciconst { 151cb0ef41Sopenharmony_ci ERR_INVALID_ARG_TYPE, 161cb0ef41Sopenharmony_ci ERR_METHOD_NOT_IMPLEMENTED, 171cb0ef41Sopenharmony_ci ERR_OUT_OF_RANGE, 181cb0ef41Sopenharmony_ci ERR_STREAM_DESTROYED, 191cb0ef41Sopenharmony_ci ERR_SYSTEM_ERROR, 201cb0ef41Sopenharmony_ci} = require('internal/errors').codes; 211cb0ef41Sopenharmony_ciconst { 221cb0ef41Sopenharmony_ci deprecate, 231cb0ef41Sopenharmony_ci kEmptyObject, 241cb0ef41Sopenharmony_ci} = require('internal/util'); 251cb0ef41Sopenharmony_ciconst { 261cb0ef41Sopenharmony_ci validateFunction, 271cb0ef41Sopenharmony_ci validateInteger, 281cb0ef41Sopenharmony_ci} = require('internal/validators'); 291cb0ef41Sopenharmony_ciconst { errorOrDestroy } = require('internal/streams/destroy'); 301cb0ef41Sopenharmony_ciconst fs = require('fs'); 311cb0ef41Sopenharmony_ciconst { kRef, kUnref, FileHandle } = require('internal/fs/promises'); 321cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer'); 331cb0ef41Sopenharmony_ciconst { 341cb0ef41Sopenharmony_ci copyObject, 351cb0ef41Sopenharmony_ci getOptions, 361cb0ef41Sopenharmony_ci getValidatedFd, 371cb0ef41Sopenharmony_ci validatePath, 381cb0ef41Sopenharmony_ci} = require('internal/fs/utils'); 391cb0ef41Sopenharmony_ciconst { Readable, Writable, finished } = require('stream'); 401cb0ef41Sopenharmony_ciconst { toPathIfFileURL } = require('internal/url'); 411cb0ef41Sopenharmony_ciconst kIoDone = Symbol('kIoDone'); 421cb0ef41Sopenharmony_ciconst kIsPerformingIO = Symbol('kIsPerformingIO'); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ciconst kFs = Symbol('kFs'); 451cb0ef41Sopenharmony_ciconst kHandle = Symbol('kHandle'); 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_cifunction _construct(callback) { 481cb0ef41Sopenharmony_ci const stream = this; 491cb0ef41Sopenharmony_ci if (typeof stream.fd === 'number') { 501cb0ef41Sopenharmony_ci callback(); 511cb0ef41Sopenharmony_ci return; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci if (stream.open !== openWriteFs && stream.open !== openReadFs) { 551cb0ef41Sopenharmony_ci // Backwards compat for monkey patching open(). 561cb0ef41Sopenharmony_ci const orgEmit = stream.emit; 571cb0ef41Sopenharmony_ci stream.emit = function(...args) { 581cb0ef41Sopenharmony_ci if (args[0] === 'open') { 591cb0ef41Sopenharmony_ci this.emit = orgEmit; 601cb0ef41Sopenharmony_ci callback(); 611cb0ef41Sopenharmony_ci ReflectApply(orgEmit, this, args); 621cb0ef41Sopenharmony_ci } else if (args[0] === 'error') { 631cb0ef41Sopenharmony_ci this.emit = orgEmit; 641cb0ef41Sopenharmony_ci callback(args[1]); 651cb0ef41Sopenharmony_ci } else { 661cb0ef41Sopenharmony_ci ReflectApply(orgEmit, this, args); 671cb0ef41Sopenharmony_ci } 681cb0ef41Sopenharmony_ci }; 691cb0ef41Sopenharmony_ci stream.open(); 701cb0ef41Sopenharmony_ci } else { 711cb0ef41Sopenharmony_ci stream[kFs].open(stream.path, stream.flags, stream.mode, (er, fd) => { 721cb0ef41Sopenharmony_ci if (er) { 731cb0ef41Sopenharmony_ci callback(er); 741cb0ef41Sopenharmony_ci } else { 751cb0ef41Sopenharmony_ci stream.fd = fd; 761cb0ef41Sopenharmony_ci callback(); 771cb0ef41Sopenharmony_ci stream.emit('open', stream.fd); 781cb0ef41Sopenharmony_ci stream.emit('ready'); 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci }); 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci} 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci// This generates an fs operations structure for a FileHandle 851cb0ef41Sopenharmony_ciconst FileHandleOperations = (handle) => { 861cb0ef41Sopenharmony_ci return { 871cb0ef41Sopenharmony_ci open: (path, flags, mode, cb) => { 881cb0ef41Sopenharmony_ci throw new ERR_METHOD_NOT_IMPLEMENTED('open()'); 891cb0ef41Sopenharmony_ci }, 901cb0ef41Sopenharmony_ci close: (fd, cb) => { 911cb0ef41Sopenharmony_ci handle[kUnref](); 921cb0ef41Sopenharmony_ci PromisePrototypeThen(handle.close(), 931cb0ef41Sopenharmony_ci () => cb(), cb); 941cb0ef41Sopenharmony_ci }, 951cb0ef41Sopenharmony_ci read: (fd, buf, offset, length, pos, cb) => { 961cb0ef41Sopenharmony_ci PromisePrototypeThen(handle.read(buf, offset, length, pos), 971cb0ef41Sopenharmony_ci (r) => cb(null, r.bytesRead, r.buffer), 981cb0ef41Sopenharmony_ci (err) => cb(err, 0, buf)); 991cb0ef41Sopenharmony_ci }, 1001cb0ef41Sopenharmony_ci write: (fd, buf, offset, length, pos, cb) => { 1011cb0ef41Sopenharmony_ci PromisePrototypeThen(handle.write(buf, offset, length, pos), 1021cb0ef41Sopenharmony_ci (r) => cb(null, r.bytesWritten, r.buffer), 1031cb0ef41Sopenharmony_ci (err) => cb(err, 0, buf)); 1041cb0ef41Sopenharmony_ci }, 1051cb0ef41Sopenharmony_ci writev: (fd, buffers, pos, cb) => { 1061cb0ef41Sopenharmony_ci PromisePrototypeThen(handle.writev(buffers, pos), 1071cb0ef41Sopenharmony_ci (r) => cb(null, r.bytesWritten, r.buffers), 1081cb0ef41Sopenharmony_ci (err) => cb(err, 0, buffers)); 1091cb0ef41Sopenharmony_ci }, 1101cb0ef41Sopenharmony_ci }; 1111cb0ef41Sopenharmony_ci}; 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_cifunction close(stream, err, cb) { 1141cb0ef41Sopenharmony_ci if (!stream.fd) { 1151cb0ef41Sopenharmony_ci cb(err); 1161cb0ef41Sopenharmony_ci } else { 1171cb0ef41Sopenharmony_ci stream[kFs].close(stream.fd, (er) => { 1181cb0ef41Sopenharmony_ci cb(er || err); 1191cb0ef41Sopenharmony_ci }); 1201cb0ef41Sopenharmony_ci stream.fd = null; 1211cb0ef41Sopenharmony_ci } 1221cb0ef41Sopenharmony_ci} 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_cifunction importFd(stream, options) { 1251cb0ef41Sopenharmony_ci if (typeof options.fd === 'number') { 1261cb0ef41Sopenharmony_ci // When fd is a raw descriptor, we must keep our fingers crossed 1271cb0ef41Sopenharmony_ci // that the descriptor won't get closed, or worse, replaced with 1281cb0ef41Sopenharmony_ci // another one 1291cb0ef41Sopenharmony_ci // https://github.com/nodejs/node/issues/35862 1301cb0ef41Sopenharmony_ci stream[kFs] = options.fs || fs; 1311cb0ef41Sopenharmony_ci return options.fd; 1321cb0ef41Sopenharmony_ci } else if (typeof options.fd === 'object' && 1331cb0ef41Sopenharmony_ci options.fd instanceof FileHandle) { 1341cb0ef41Sopenharmony_ci // When fd is a FileHandle we can listen for 'close' events 1351cb0ef41Sopenharmony_ci if (options.fs) { 1361cb0ef41Sopenharmony_ci // FileHandle is not supported with custom fs operations 1371cb0ef41Sopenharmony_ci throw new ERR_METHOD_NOT_IMPLEMENTED('FileHandle with fs'); 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci stream[kHandle] = options.fd; 1401cb0ef41Sopenharmony_ci stream[kFs] = FileHandleOperations(stream[kHandle]); 1411cb0ef41Sopenharmony_ci stream[kHandle][kRef](); 1421cb0ef41Sopenharmony_ci options.fd.on('close', FunctionPrototypeBind(stream.close, stream)); 1431cb0ef41Sopenharmony_ci return options.fd.fd; 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci throw ERR_INVALID_ARG_TYPE('options.fd', 1471cb0ef41Sopenharmony_ci ['number', 'FileHandle'], options.fd); 1481cb0ef41Sopenharmony_ci} 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_cifunction ReadStream(path, options) { 1511cb0ef41Sopenharmony_ci if (!(this instanceof ReadStream)) 1521cb0ef41Sopenharmony_ci return new ReadStream(path, options); 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci // A little bit bigger buffer and water marks by default 1551cb0ef41Sopenharmony_ci options = copyObject(getOptions(options, kEmptyObject)); 1561cb0ef41Sopenharmony_ci if (options.highWaterMark === undefined) 1571cb0ef41Sopenharmony_ci options.highWaterMark = 64 * 1024; 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci if (options.autoDestroy === undefined) { 1601cb0ef41Sopenharmony_ci options.autoDestroy = false; 1611cb0ef41Sopenharmony_ci } 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci if (options.fd == null) { 1641cb0ef41Sopenharmony_ci this.fd = null; 1651cb0ef41Sopenharmony_ci this[kFs] = options.fs || fs; 1661cb0ef41Sopenharmony_ci validateFunction(this[kFs].open, 'options.fs.open'); 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci // Path will be ignored when fd is specified, so it can be falsy 1691cb0ef41Sopenharmony_ci this.path = toPathIfFileURL(path); 1701cb0ef41Sopenharmony_ci this.flags = options.flags === undefined ? 'r' : options.flags; 1711cb0ef41Sopenharmony_ci this.mode = options.mode === undefined ? 0o666 : options.mode; 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci validatePath(this.path); 1741cb0ef41Sopenharmony_ci } else { 1751cb0ef41Sopenharmony_ci this.fd = getValidatedFd(importFd(this, options)); 1761cb0ef41Sopenharmony_ci } 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci options.autoDestroy = options.autoClose === undefined ? 1791cb0ef41Sopenharmony_ci true : options.autoClose; 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci validateFunction(this[kFs].read, 'options.fs.read'); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci if (options.autoDestroy) { 1841cb0ef41Sopenharmony_ci validateFunction(this[kFs].close, 'options.fs.close'); 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci this.start = options.start; 1881cb0ef41Sopenharmony_ci this.end = options.end; 1891cb0ef41Sopenharmony_ci this.pos = undefined; 1901cb0ef41Sopenharmony_ci this.bytesRead = 0; 1911cb0ef41Sopenharmony_ci this[kIsPerformingIO] = false; 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci if (this.start !== undefined) { 1941cb0ef41Sopenharmony_ci validateInteger(this.start, 'start', 0); 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci this.pos = this.start; 1971cb0ef41Sopenharmony_ci } 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci if (this.end === undefined) { 2011cb0ef41Sopenharmony_ci this.end = Infinity; 2021cb0ef41Sopenharmony_ci } else if (this.end !== Infinity) { 2031cb0ef41Sopenharmony_ci validateInteger(this.end, 'end', 0); 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci if (this.start !== undefined && this.start > this.end) { 2061cb0ef41Sopenharmony_ci throw new ERR_OUT_OF_RANGE( 2071cb0ef41Sopenharmony_ci 'start', 2081cb0ef41Sopenharmony_ci `<= "end" (here: ${this.end})`, 2091cb0ef41Sopenharmony_ci this.start, 2101cb0ef41Sopenharmony_ci ); 2111cb0ef41Sopenharmony_ci } 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci ReflectApply(Readable, this, [options]); 2151cb0ef41Sopenharmony_ci} 2161cb0ef41Sopenharmony_ciObjectSetPrototypeOf(ReadStream.prototype, Readable.prototype); 2171cb0ef41Sopenharmony_ciObjectSetPrototypeOf(ReadStream, Readable); 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ciObjectDefineProperty(ReadStream.prototype, 'autoClose', { 2201cb0ef41Sopenharmony_ci __proto__: null, 2211cb0ef41Sopenharmony_ci get() { 2221cb0ef41Sopenharmony_ci return this._readableState.autoDestroy; 2231cb0ef41Sopenharmony_ci }, 2241cb0ef41Sopenharmony_ci set(val) { 2251cb0ef41Sopenharmony_ci this._readableState.autoDestroy = val; 2261cb0ef41Sopenharmony_ci }, 2271cb0ef41Sopenharmony_ci}); 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ciconst openReadFs = deprecate(function() { 2301cb0ef41Sopenharmony_ci // Noop. 2311cb0ef41Sopenharmony_ci}, 'ReadStream.prototype.open() is deprecated', 'DEP0135'); 2321cb0ef41Sopenharmony_ciReadStream.prototype.open = openReadFs; 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ciReadStream.prototype._construct = _construct; 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ciReadStream.prototype._read = function(n) { 2371cb0ef41Sopenharmony_ci n = this.pos !== undefined ? 2381cb0ef41Sopenharmony_ci MathMin(this.end - this.pos + 1, n) : 2391cb0ef41Sopenharmony_ci MathMin(this.end - this.bytesRead + 1, n); 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci if (n <= 0) { 2421cb0ef41Sopenharmony_ci this.push(null); 2431cb0ef41Sopenharmony_ci return; 2441cb0ef41Sopenharmony_ci } 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci const buf = Buffer.allocUnsafeSlow(n); 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci this[kIsPerformingIO] = true; 2491cb0ef41Sopenharmony_ci this[kFs] 2501cb0ef41Sopenharmony_ci .read(this.fd, buf, 0, n, this.pos, (er, bytesRead, buf) => { 2511cb0ef41Sopenharmony_ci this[kIsPerformingIO] = false; 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci // Tell ._destroy() that it's safe to close the fd now. 2541cb0ef41Sopenharmony_ci if (this.destroyed) { 2551cb0ef41Sopenharmony_ci this.emit(kIoDone, er); 2561cb0ef41Sopenharmony_ci return; 2571cb0ef41Sopenharmony_ci } 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci if (er) { 2601cb0ef41Sopenharmony_ci errorOrDestroy(this, er); 2611cb0ef41Sopenharmony_ci } else if (bytesRead > 0) { 2621cb0ef41Sopenharmony_ci if (this.pos !== undefined) { 2631cb0ef41Sopenharmony_ci this.pos += bytesRead; 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci this.bytesRead += bytesRead; 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci if (bytesRead !== buf.length) { 2691cb0ef41Sopenharmony_ci // Slow path. Shrink to fit. 2701cb0ef41Sopenharmony_ci // Copy instead of slice so that we don't retain 2711cb0ef41Sopenharmony_ci // large backing buffer for small reads. 2721cb0ef41Sopenharmony_ci const dst = Buffer.allocUnsafeSlow(bytesRead); 2731cb0ef41Sopenharmony_ci buf.copy(dst, 0, 0, bytesRead); 2741cb0ef41Sopenharmony_ci buf = dst; 2751cb0ef41Sopenharmony_ci } 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ci this.push(buf); 2781cb0ef41Sopenharmony_ci } else { 2791cb0ef41Sopenharmony_ci this.push(null); 2801cb0ef41Sopenharmony_ci } 2811cb0ef41Sopenharmony_ci }); 2821cb0ef41Sopenharmony_ci}; 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ciReadStream.prototype._destroy = function(err, cb) { 2851cb0ef41Sopenharmony_ci // Usually for async IO it is safe to close a file descriptor 2861cb0ef41Sopenharmony_ci // even when there are pending operations. However, due to platform 2871cb0ef41Sopenharmony_ci // differences file IO is implemented using synchronous operations 2881cb0ef41Sopenharmony_ci // running in a thread pool. Therefore, file descriptors are not safe 2891cb0ef41Sopenharmony_ci // to close while used in a pending read or write operation. Wait for 2901cb0ef41Sopenharmony_ci // any pending IO (kIsPerformingIO) to complete (kIoDone). 2911cb0ef41Sopenharmony_ci if (this[kIsPerformingIO]) { 2921cb0ef41Sopenharmony_ci this.once(kIoDone, (er) => close(this, err || er, cb)); 2931cb0ef41Sopenharmony_ci } else { 2941cb0ef41Sopenharmony_ci close(this, err, cb); 2951cb0ef41Sopenharmony_ci } 2961cb0ef41Sopenharmony_ci}; 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ciReadStream.prototype.close = function(cb) { 2991cb0ef41Sopenharmony_ci if (typeof cb === 'function') finished(this, cb); 3001cb0ef41Sopenharmony_ci this.destroy(); 3011cb0ef41Sopenharmony_ci}; 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_ciObjectDefineProperty(ReadStream.prototype, 'pending', { 3041cb0ef41Sopenharmony_ci __proto__: null, 3051cb0ef41Sopenharmony_ci get() { return this.fd === null; }, 3061cb0ef41Sopenharmony_ci configurable: true, 3071cb0ef41Sopenharmony_ci}); 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_cifunction WriteStream(path, options) { 3101cb0ef41Sopenharmony_ci if (!(this instanceof WriteStream)) 3111cb0ef41Sopenharmony_ci return new WriteStream(path, options); 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci options = copyObject(getOptions(options, kEmptyObject)); 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci // Only buffers are supported. 3161cb0ef41Sopenharmony_ci options.decodeStrings = true; 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci if (options.fd == null) { 3191cb0ef41Sopenharmony_ci this.fd = null; 3201cb0ef41Sopenharmony_ci this[kFs] = options.fs || fs; 3211cb0ef41Sopenharmony_ci validateFunction(this[kFs].open, 'options.fs.open'); 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ci // Path will be ignored when fd is specified, so it can be falsy 3241cb0ef41Sopenharmony_ci this.path = toPathIfFileURL(path); 3251cb0ef41Sopenharmony_ci this.flags = options.flags === undefined ? 'w' : options.flags; 3261cb0ef41Sopenharmony_ci this.mode = options.mode === undefined ? 0o666 : options.mode; 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_ci validatePath(this.path); 3291cb0ef41Sopenharmony_ci } else { 3301cb0ef41Sopenharmony_ci this.fd = getValidatedFd(importFd(this, options)); 3311cb0ef41Sopenharmony_ci } 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci options.autoDestroy = options.autoClose === undefined ? 3341cb0ef41Sopenharmony_ci true : options.autoClose; 3351cb0ef41Sopenharmony_ci 3361cb0ef41Sopenharmony_ci if (!this[kFs].write && !this[kFs].writev) { 3371cb0ef41Sopenharmony_ci throw new ERR_INVALID_ARG_TYPE('options.fs.write', 'function', 3381cb0ef41Sopenharmony_ci this[kFs].write); 3391cb0ef41Sopenharmony_ci } 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci if (this[kFs].write) { 3421cb0ef41Sopenharmony_ci validateFunction(this[kFs].write, 'options.fs.write'); 3431cb0ef41Sopenharmony_ci } 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_ci if (this[kFs].writev) { 3461cb0ef41Sopenharmony_ci validateFunction(this[kFs].writev, 'options.fs.writev'); 3471cb0ef41Sopenharmony_ci } 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci if (options.autoDestroy) { 3501cb0ef41Sopenharmony_ci validateFunction(this[kFs].close, 'options.fs.close'); 3511cb0ef41Sopenharmony_ci } 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci // It's enough to override either, in which case only one will be used. 3541cb0ef41Sopenharmony_ci if (!this[kFs].write) { 3551cb0ef41Sopenharmony_ci this._write = null; 3561cb0ef41Sopenharmony_ci } 3571cb0ef41Sopenharmony_ci if (!this[kFs].writev) { 3581cb0ef41Sopenharmony_ci this._writev = null; 3591cb0ef41Sopenharmony_ci } 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci this.start = options.start; 3621cb0ef41Sopenharmony_ci this.pos = undefined; 3631cb0ef41Sopenharmony_ci this.bytesWritten = 0; 3641cb0ef41Sopenharmony_ci this[kIsPerformingIO] = false; 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci if (this.start !== undefined) { 3671cb0ef41Sopenharmony_ci validateInteger(this.start, 'start', 0); 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_ci this.pos = this.start; 3701cb0ef41Sopenharmony_ci } 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_ci ReflectApply(Writable, this, [options]); 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci if (options.encoding) 3751cb0ef41Sopenharmony_ci this.setDefaultEncoding(options.encoding); 3761cb0ef41Sopenharmony_ci} 3771cb0ef41Sopenharmony_ciObjectSetPrototypeOf(WriteStream.prototype, Writable.prototype); 3781cb0ef41Sopenharmony_ciObjectSetPrototypeOf(WriteStream, Writable); 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_ciObjectDefineProperty(WriteStream.prototype, 'autoClose', { 3811cb0ef41Sopenharmony_ci __proto__: null, 3821cb0ef41Sopenharmony_ci get() { 3831cb0ef41Sopenharmony_ci return this._writableState.autoDestroy; 3841cb0ef41Sopenharmony_ci }, 3851cb0ef41Sopenharmony_ci set(val) { 3861cb0ef41Sopenharmony_ci this._writableState.autoDestroy = val; 3871cb0ef41Sopenharmony_ci }, 3881cb0ef41Sopenharmony_ci}); 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_ciconst openWriteFs = deprecate(function() { 3911cb0ef41Sopenharmony_ci // Noop. 3921cb0ef41Sopenharmony_ci}, 'WriteStream.prototype.open() is deprecated', 'DEP0135'); 3931cb0ef41Sopenharmony_ciWriteStream.prototype.open = openWriteFs; 3941cb0ef41Sopenharmony_ci 3951cb0ef41Sopenharmony_ciWriteStream.prototype._construct = _construct; 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_cifunction writeAll(data, size, pos, cb, retries = 0) { 3981cb0ef41Sopenharmony_ci this[kFs].write(this.fd, data, 0, size, pos, (er, bytesWritten, buffer) => { 3991cb0ef41Sopenharmony_ci // No data currently available and operation should be retried later. 4001cb0ef41Sopenharmony_ci if (er?.code === 'EAGAIN') { 4011cb0ef41Sopenharmony_ci er = null; 4021cb0ef41Sopenharmony_ci bytesWritten = 0; 4031cb0ef41Sopenharmony_ci } 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci if (this.destroyed || er) { 4061cb0ef41Sopenharmony_ci return cb(er || new ERR_STREAM_DESTROYED('write')); 4071cb0ef41Sopenharmony_ci } 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ci this.bytesWritten += bytesWritten; 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci retries = bytesWritten ? 0 : retries + 1; 4121cb0ef41Sopenharmony_ci size -= bytesWritten; 4131cb0ef41Sopenharmony_ci pos += bytesWritten; 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ci // Try writing non-zero number of bytes up to 5 times. 4161cb0ef41Sopenharmony_ci if (retries > 5) { 4171cb0ef41Sopenharmony_ci cb(new ERR_SYSTEM_ERROR('write failed')); 4181cb0ef41Sopenharmony_ci } else if (size) { 4191cb0ef41Sopenharmony_ci writeAll.call(this, buffer.slice(bytesWritten), size, pos, cb, retries); 4201cb0ef41Sopenharmony_ci } else { 4211cb0ef41Sopenharmony_ci cb(); 4221cb0ef41Sopenharmony_ci } 4231cb0ef41Sopenharmony_ci }); 4241cb0ef41Sopenharmony_ci} 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_cifunction writevAll(chunks, size, pos, cb, retries = 0) { 4271cb0ef41Sopenharmony_ci this[kFs].writev(this.fd, chunks, this.pos, (er, bytesWritten, buffers) => { 4281cb0ef41Sopenharmony_ci // No data currently available and operation should be retried later. 4291cb0ef41Sopenharmony_ci if (er?.code === 'EAGAIN') { 4301cb0ef41Sopenharmony_ci er = null; 4311cb0ef41Sopenharmony_ci bytesWritten = 0; 4321cb0ef41Sopenharmony_ci } 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci if (this.destroyed || er) { 4351cb0ef41Sopenharmony_ci return cb(er || new ERR_STREAM_DESTROYED('writev')); 4361cb0ef41Sopenharmony_ci } 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ci this.bytesWritten += bytesWritten; 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ci retries = bytesWritten ? 0 : retries + 1; 4411cb0ef41Sopenharmony_ci size -= bytesWritten; 4421cb0ef41Sopenharmony_ci pos += bytesWritten; 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci // Try writing non-zero number of bytes up to 5 times. 4451cb0ef41Sopenharmony_ci if (retries > 5) { 4461cb0ef41Sopenharmony_ci cb(new ERR_SYSTEM_ERROR('writev failed')); 4471cb0ef41Sopenharmony_ci } else if (size) { 4481cb0ef41Sopenharmony_ci writevAll.call(this, [Buffer.concat(buffers).slice(bytesWritten)], size, pos, cb, retries); 4491cb0ef41Sopenharmony_ci } else { 4501cb0ef41Sopenharmony_ci cb(); 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci }); 4531cb0ef41Sopenharmony_ci} 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ciWriteStream.prototype._write = function(data, encoding, cb) { 4561cb0ef41Sopenharmony_ci this[kIsPerformingIO] = true; 4571cb0ef41Sopenharmony_ci writeAll.call(this, data, data.length, this.pos, (er) => { 4581cb0ef41Sopenharmony_ci this[kIsPerformingIO] = false; 4591cb0ef41Sopenharmony_ci if (this.destroyed) { 4601cb0ef41Sopenharmony_ci // Tell ._destroy() that it's safe to close the fd now. 4611cb0ef41Sopenharmony_ci cb(er); 4621cb0ef41Sopenharmony_ci return this.emit(kIoDone, er); 4631cb0ef41Sopenharmony_ci } 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci cb(er); 4661cb0ef41Sopenharmony_ci }); 4671cb0ef41Sopenharmony_ci 4681cb0ef41Sopenharmony_ci if (this.pos !== undefined) 4691cb0ef41Sopenharmony_ci this.pos += data.length; 4701cb0ef41Sopenharmony_ci}; 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ciWriteStream.prototype._writev = function(data, cb) { 4731cb0ef41Sopenharmony_ci const len = data.length; 4741cb0ef41Sopenharmony_ci const chunks = new Array(len); 4751cb0ef41Sopenharmony_ci let size = 0; 4761cb0ef41Sopenharmony_ci 4771cb0ef41Sopenharmony_ci for (let i = 0; i < len; i++) { 4781cb0ef41Sopenharmony_ci const chunk = data[i].chunk; 4791cb0ef41Sopenharmony_ci 4801cb0ef41Sopenharmony_ci chunks[i] = chunk; 4811cb0ef41Sopenharmony_ci size += chunk.length; 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci this[kIsPerformingIO] = true; 4851cb0ef41Sopenharmony_ci writevAll.call(this, chunks, size, this.pos, (er) => { 4861cb0ef41Sopenharmony_ci this[kIsPerformingIO] = false; 4871cb0ef41Sopenharmony_ci if (this.destroyed) { 4881cb0ef41Sopenharmony_ci // Tell ._destroy() that it's safe to close the fd now. 4891cb0ef41Sopenharmony_ci cb(er); 4901cb0ef41Sopenharmony_ci return this.emit(kIoDone, er); 4911cb0ef41Sopenharmony_ci } 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci cb(er); 4941cb0ef41Sopenharmony_ci }); 4951cb0ef41Sopenharmony_ci 4961cb0ef41Sopenharmony_ci if (this.pos !== undefined) 4971cb0ef41Sopenharmony_ci this.pos += size; 4981cb0ef41Sopenharmony_ci}; 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ciWriteStream.prototype._destroy = function(err, cb) { 5011cb0ef41Sopenharmony_ci // Usually for async IO it is safe to close a file descriptor 5021cb0ef41Sopenharmony_ci // even when there are pending operations. However, due to platform 5031cb0ef41Sopenharmony_ci // differences file IO is implemented using synchronous operations 5041cb0ef41Sopenharmony_ci // running in a thread pool. Therefore, file descriptors are not safe 5051cb0ef41Sopenharmony_ci // to close while used in a pending read or write operation. Wait for 5061cb0ef41Sopenharmony_ci // any pending IO (kIsPerformingIO) to complete (kIoDone). 5071cb0ef41Sopenharmony_ci if (this[kIsPerformingIO]) { 5081cb0ef41Sopenharmony_ci this.once(kIoDone, (er) => close(this, err || er, cb)); 5091cb0ef41Sopenharmony_ci } else { 5101cb0ef41Sopenharmony_ci close(this, err, cb); 5111cb0ef41Sopenharmony_ci } 5121cb0ef41Sopenharmony_ci}; 5131cb0ef41Sopenharmony_ci 5141cb0ef41Sopenharmony_ciWriteStream.prototype.close = function(cb) { 5151cb0ef41Sopenharmony_ci if (cb) { 5161cb0ef41Sopenharmony_ci if (this.closed) { 5171cb0ef41Sopenharmony_ci process.nextTick(cb); 5181cb0ef41Sopenharmony_ci return; 5191cb0ef41Sopenharmony_ci } 5201cb0ef41Sopenharmony_ci this.on('close', cb); 5211cb0ef41Sopenharmony_ci } 5221cb0ef41Sopenharmony_ci 5231cb0ef41Sopenharmony_ci // If we are not autoClosing, we should call 5241cb0ef41Sopenharmony_ci // destroy on 'finish'. 5251cb0ef41Sopenharmony_ci if (!this.autoClose) { 5261cb0ef41Sopenharmony_ci this.on('finish', this.destroy); 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci 5291cb0ef41Sopenharmony_ci // We use end() instead of destroy() because of 5301cb0ef41Sopenharmony_ci // https://github.com/nodejs/node/issues/2006 5311cb0ef41Sopenharmony_ci this.end(); 5321cb0ef41Sopenharmony_ci}; 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci// There is no shutdown() for files. 5351cb0ef41Sopenharmony_ciWriteStream.prototype.destroySoon = WriteStream.prototype.end; 5361cb0ef41Sopenharmony_ci 5371cb0ef41Sopenharmony_ciObjectDefineProperty(WriteStream.prototype, 'pending', { 5381cb0ef41Sopenharmony_ci __proto__: null, 5391cb0ef41Sopenharmony_ci get() { return this.fd === null; }, 5401cb0ef41Sopenharmony_ci configurable: true, 5411cb0ef41Sopenharmony_ci}); 5421cb0ef41Sopenharmony_ci 5431cb0ef41Sopenharmony_cimodule.exports = { 5441cb0ef41Sopenharmony_ci ReadStream, 5451cb0ef41Sopenharmony_ci WriteStream, 5461cb0ef41Sopenharmony_ci}; 547