fs: added fs.writev() which exposes syscalls writev() by AnasAboreeda · Pull Request #25925 · nodejs/node · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions doc/api/fs.md
65 changes: 64 additions & 1 deletion lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,19 @@ function maybeCallback(cb) {
throw new ERR_INVALID_CALLBACK(cb);
}

function isBuffersArray(value) {
if (!Array.isArray(value))
return false;

for (var i = 0; i < value.length; i += 1) {
if (!isArrayBufferView(value[i])) {
return false;
}
}

return true;
}

// 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.
Expand Down Expand Up @@ -559,7 +572,7 @@ function write(fd, buffer, offset, length, position, callback) {
Object.defineProperty(write, internalUtil.customPromisifyArgs,
{ value: ['bytesWritten', 'buffer'], enumerable: false });

// usage:
// Usage:
// fs.writeSync(fd, buffer[, offset[, length[, position]]]);
// OR
// fs.writeSync(fd, string[, position[, encoding]]);
Expand Down Expand Up @@ -589,6 +602,54 @@ function writeSync(fd, buffer, offset, length, position) {
return result;
}

// usage:
Comment thread
addaleax marked this conversation as resolved.
Outdated
// fs.writev(fd, buffers[, position], callback);
function writev(fd, buffers, position, callback) {
Comment thread
AnasAboreeda marked this conversation as resolved.
Outdated
function wrapper(err, written) {
callback(err, written || 0, buffers);
}

validateUint32(fd, 'fd');

if (!isBuffersArray(buffers)) {
throw new ERR_INVALID_ARG_TYPE('buffers', 'ArrayBufferView[]', buffers);
}

const req = new FSReqCallback();
req.oncomplete = wrapper;

callback = maybeCallback(callback || position);

if (typeof position !== 'number')
position = null;

return binding.writeBuffers(fd, buffers, position, req);
}

Object.defineProperty(writev, internalUtil.customPromisifyArgs, {
value: ['bytesWritten', 'buffer'],
enumerable: false
});

// fs.writevSync(fd, buffers[, position]);
function writevSync(fd, buffers, position) {

validateUint32(fd, 'fd');
const ctx = {};

if (!isBuffersArray(buffers)) {
throw new ERR_INVALID_ARG_TYPE('buffers', 'ArrayBufferView[]', buffers);
}

if (typeof position !== 'number')
position = null;

const result = binding.writeBuffers(fd, buffers, position, undefined, ctx);

handleErrorFromBinding(ctx);
return result;
}

function rename(oldPath, newPath, callback) {
callback = makeCallback(callback);
oldPath = getValidatedPath(oldPath, 'oldPath');
Expand Down Expand Up @@ -1825,6 +1886,8 @@ module.exports = fs = {
writeFileSync,
write,
writeSync,
writev,
writevSync,
Dirent,
Stats,

Expand Down
87 changes: 87 additions & 0 deletions test/parallel/test-fs-writev-sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const path = require('path');
const fs = require('fs');
const tmpdir = require('../common/tmpdir');

tmpdir.refresh();

const expected = 'ümlaut. Лорем 運務ホソモ指及 आपको करने विकास 紙読決多密所 أضف';

const getFileName = (i) => path.join(tmpdir.path, `writev_sync_${i}.txt`);

/**
* Testing with a array of buffers input
*/

// fs.writevSync with array of buffers with all parameters
{
const filename = getFileName(1);
const fd = fs.openSync(filename, 'w');

const buffer = Buffer.from(expected);
const bufferArr = [buffer, buffer];
const expectedLength = bufferArr.length * buffer.byteLength;

let written = fs.writevSync(fd, [Buffer.from('')], null);
assert.deepStrictEqual(written, 0);

written = fs.writevSync(fd, bufferArr, null);
assert.deepStrictEqual(written, expectedLength);

fs.closeSync(fd);

assert(Buffer.concat(bufferArr).equals(fs.readFileSync(filename)));
}

// fs.writevSync with array of buffers without position
{
const filename = getFileName(2);
const fd = fs.openSync(filename, 'w');

const buffer = Buffer.from(expected);
const bufferArr = [buffer, buffer, buffer];
const expectedLength = bufferArr.length * buffer.byteLength;

let written = fs.writevSync(fd, [Buffer.from('')]);
assert.deepStrictEqual(written, 0);

written = fs.writevSync(fd, bufferArr);
assert.deepStrictEqual(written, expectedLength);

fs.closeSync(fd);

assert(Buffer.concat(bufferArr).equals(fs.readFileSync(filename)));
}

/**
* Testing with wrong input types
*/
{
const filename = getFileName(3);
const fd = fs.openSync(filename, 'w');

[false, 'test', {}, [{}], ['sdf'], null, undefined].forEach((i) => {
common.expectsError(
() => fs.writevSync(fd, i, null), {
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError
}
);
});

fs.closeSync(fd);
}

// fs.writevSync with wrong fd types
[false, 'test', {}, [{}], null, undefined].forEach((i) => {
common.expectsError(
() => fs.writevSync(i),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError
}
);
});
92 changes: 92 additions & 0 deletions test/parallel/test-fs-writev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const path = require('path');
const fs = require('fs');
const tmpdir = require('../common/tmpdir');

tmpdir.refresh();

const expected = 'ümlaut. Лорем 運務ホソモ指及 आपको करने विकास 紙読決多密所 أضف';

const getFileName = (i) => path.join(tmpdir.path, `writev_${i}.txt`);

/**
* Testing with a array of buffers input
*/

// fs.writev with array of buffers with all parameters
{
const filename = getFileName(1);
const fd = fs.openSync(filename, 'w');

const buffer = Buffer.from(expected);
const bufferArr = [buffer, buffer];

const done = common.mustCall((err, written, buffers) => {
assert.ifError(err);

assert.deepStrictEqual(bufferArr, buffers);
const expectedLength = bufferArr.length * buffer.byteLength;
assert.deepStrictEqual(written, expectedLength);
fs.closeSync(fd);

assert(Buffer.concat(bufferArr).equals(fs.readFileSync(filename)));
});

fs.writev(fd, bufferArr, null, done);
}

// fs.writev with array of buffers without position
{
const filename = getFileName(2);
const fd = fs.openSync(filename, 'w');

const buffer = Buffer.from(expected);
const bufferArr = [buffer, buffer];

const done = common.mustCall((err, written, buffers) => {
assert.ifError(err);

assert.deepStrictEqual(bufferArr, buffers);

const expectedLength = bufferArr.length * buffer.byteLength;
assert.deepStrictEqual(written, expectedLength);
fs.closeSync(fd);

assert(Buffer.concat(bufferArr).equals(fs.readFileSync(filename)));
});

fs.writev(fd, bufferArr, done);
}

/**
* Testing with wrong input types
*/
{
const filename = getFileName(3);
const fd = fs.openSync(filename, 'w');

[false, 'test', {}, [{}], ['sdf'], null, undefined].forEach((i) => {
common.expectsError(
() => fs.writev(fd, i, null, common.mustNotCall()), {
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError
}
);
});

fs.closeSync(fd);
}

// fs.writev with wrong fd types
[false, 'test', {}, [{}], null, undefined].forEach((i) => {
common.expectsError(
() => fs.writev(i, common.mustNotCall()),
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError
}
);
});
8 changes: 4 additions & 4 deletions tools/doc/type-parser.js