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