diff --git a/lib/internal/fs/streams.js b/lib/internal/fs/streams.js index a2ae1c9787d288..ca04bc69e7e2e9 100644 --- a/lib/internal/fs/streams.js +++ b/lib/internal/fs/streams.js @@ -308,7 +308,10 @@ WriteStream.prototype._write = function(data, encoding, cb) { }); } - fs.write(this.fd, data, 0, data.length, this.pos, (er, bytes) => { + const len = data.length; + let pos = this.pos; + let offset = 0; + const callback = (er, bytes) => { if (er) { if (this.autoClose) { this.destroy(); @@ -316,8 +319,17 @@ WriteStream.prototype._write = function(data, encoding, cb) { return cb(er); } this.bytesWritten += bytes; - cb(); - }); + offset += bytes; + if (offset < len) { + if (pos !== undefined) { + pos += bytes; + } + fs.write(this.fd, data, offset, len - offset, pos, callback); + } else { + cb(); + } + }; + fs.write(this.fd, data, offset, len, pos, callback); if (this.pos !== undefined) this.pos += data.length; diff --git a/test/parallel/test-fs-write-stream-partial-write.js b/test/parallel/test-fs-write-stream-partial-write.js new file mode 100644 index 00000000000000..7cf73e44903655 --- /dev/null +++ b/test/parallel/test-fs-write-stream-partial-write.js @@ -0,0 +1,42 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); +const fs = require('fs'); + +const tmpdir = require('../common/tmpdir'); +const file = path.join(tmpdir.path, 'out.txt'); + +tmpdir.refresh(); + +{ + const _fs_write = fs.write; + let i = 0; + fs.write = function(fd, data, offset, length, pos, cb) { + if (i === 0) { + const half = Math.floor(length / 2); + _fs_write(fd, data, offset, half, pos, cb); + } else { + assert( + offset > 0, + `second call to fs.write() must provide non-zero offset, got ${offset}` + ); + _fs_write(fd, data, offset, length, pos, cb); + } + i++; + }; + + const stream = fs.createWriteStream(file); + const data = Buffer.from('Hello World, how are you?', 'ascii'); + stream.write(data, 'ascii', common.mustCall(function(err) { + assert.ifError(err); + })); + stream.end(); + + process.on('exit', function() { + assert.strictEqual( + i, 2, 'expected fs.write() to be called twice but got ' + i); + const content = fs.readFileSync(file); + assert.strictEqual(content.toString(), 'Hello World, how are you?'); + }); +}