Commit 3bffb302 authored by Julien Fontanet's avatar Julien Fontanet

feat(write): low level write method

parent c489d243
...@@ -254,10 +254,11 @@ smb2Client.createWriteStream('path\\to\\the\\file', function(err, readStream) { ...@@ -254,10 +254,11 @@ smb2Client.createWriteStream('path\\to\\the\\file', function(err, readStream) {
### Low-level API ### Low-level API
```javascript ```javascript
smb2Client.open('path\\to\\the\\file', function(err, fd) { smb2Client.open('path\\to\\the\\file', 'r', function(err, fd) {
if (err) throw err; if (err) throw err;
smb2Client.read( smb2Client.read(
fd, // file descriptor
Buffer.alloc(10), // buffer where to store the data Buffer.alloc(10), // buffer where to store the data
0, // offset in the buffer 0, // offset in the buffer
10, // number of bytes to read 10, // number of bytes to read
...@@ -270,6 +271,24 @@ smb2Client.open('path\\to\\the\\file', function(err, fd) { ...@@ -270,6 +271,24 @@ smb2Client.open('path\\to\\the\\file', function(err, fd) {
} }
); );
}); });
smb2Client.open('path\\to\\the\\file', 'w', function(err, fd) {
if (err) throw err;
smb2Client.write(
fd, // file descriptor
Buffer.from('foo bar\n'), // data to write to the file
0, // offset in the buffer
10, // number of bytes to write
0, // offset in the file
function(err, bytesWritten, buffer) {
smb2Client.close(fd, function() {});
if (err) throw cb(err);
console.log(bytesWritten);
}
);
});
``` ```
> This API is modeled after Node's `fs` module. > This API is modeled after Node's `fs` module.
......
var Writable = require('stream').Writable; var Writable = require('stream').Writable;
var BigInt = require('../tools/bigint'); var BigInt = require('../tools/bigint');
var constants = require('../structures/constants');
var parseFlags = require('../tools/parse-flags'); var parseFlags = require('../tools/parse-flags');
var request = require('../tools/smb2-forge').request; var request = require('../tools/smb2-forge').request;
// Where does it come from?!
var maxPacketSize = 0x00010000 - 0x71;
module.exports = function createWriteStream(path, options, cb) { module.exports = function createWriteStream(path, options, cb) {
if (typeof options === 'function') { if (typeof options === 'function') {
cb = options; cb = options;
...@@ -31,7 +29,7 @@ module.exports = function createWriteStream(path, options, cb) { ...@@ -31,7 +29,7 @@ module.exports = function createWriteStream(path, options, cb) {
var close = request.bind(undefined, 'close', file, connection); var close = request.bind(undefined, 'close', file, connection);
function write(buffer, i, cb) { function write(buffer, i, cb) {
var j = i + maxPacketSize; var j = i + constants.MAX_WRITE_LENGTH;
var chunk = buffer.slice(i, j); var chunk = buffer.slice(i, j);
request( request(
'write', 'write',
......
var assert = require('assert');
var BigInt = require('../tools/bigint');
var request = require('../tools/smb2-forge').request;
var MAX_WRITE_LENGTH = require('../structures/constants').MAX_WRITE_LENGTH;
module.exports = function write(file, buffer, offset, length, start, cb) {
assert(Buffer.isBuffer(buffer));
if (offset == null) {
offset = 0;
} else {
assert.strictEqual(typeof offset, 'number');
assert(offset > 0);
assert(offset < buffer.length);
}
if (length == null) {
length = buffer.length - offset;
} else {
assert.strictEqual(typeof length, 'number');
assert(length > 0);
length = Math.min(length, buffer.length - offset);
}
assert.strictEqual(typeof start, 'number');
var connection = this;
var pos = start;
var chunkLength;
function onWrite(err) {
if (err != null) {
return cb(err, pos - start, buffer);
}
length -= chunkLength;
offset += chunkLength;
pos += chunkLength;
writeChunk();
}
function writeChunk() {
if (length <= 0) {
cb(null, pos - start, buffer);
}
chunkLength = Math.min(MAX_WRITE_LENGTH, length);
request(
'write',
{
Buffer: buffer.slice(offset, offset + chunkLength),
FileId: file.FileId,
Offset: new BigInt(8, pos).toBuffer(),
},
connection,
onWrite
);
}
process.nextTick(writeChunk);
};
var SMB2Forge = require('../tools/smb2-forge'); var SMB2Forge = require('../tools/smb2-forge');
var SMB2Request = SMB2Forge.request; var SMB2Request = SMB2Forge.request;
var BigInt = require('../tools/bigint'); var BigInt = require('../tools/bigint');
var constants = require('../structures/constants');
var parseFlags = require('../tools/parse-flags'); var parseFlags = require('../tools/parse-flags');
/* /*
...@@ -84,7 +85,7 @@ module.exports = function writeFile(filename, data, options, cb) { ...@@ -84,7 +85,7 @@ module.exports = function writeFile(filename, data, options, cb) {
var offset = new BigInt(8); var offset = new BigInt(8);
var stop = false; var stop = false;
var nbRemainingPackets = 0; var nbRemainingPackets = 0;
var maxPacketSize = new BigInt(8, 0x00010000 - 0x71); var maxPacketSize = new BigInt(8, constants.MAX_WRITE_LENGTH);
// callback manager // callback manager
function callback() { function callback() {
return function(err) { return function(err) {
......
...@@ -126,4 +126,13 @@ proto.read = autoPromise(require('./api/read'), function(bytesRead, buffer) { ...@@ -126,4 +126,13 @@ proto.read = autoPromise(require('./api/read'), function(bytesRead, buffer) {
buffer: buffer, buffer: buffer,
}; };
}); });
proto.write = autoPromise(require('./api/write'), function(
bytesWritten,
buffer
) {
return {
bytesWritten: bytesWritten,
buffer: buffer,
};
});
proto.close = autoPromise(require('./api/close')); proto.close = autoPromise(require('./api/close'));
...@@ -10,6 +10,7 @@ module.exports = { ...@@ -10,6 +10,7 @@ module.exports = {
FILE_OVERWRITE: 0x00000004, FILE_OVERWRITE: 0x00000004,
FILE_OVERWRITE_IF: 0x00000005, FILE_OVERWRITE_IF: 0x00000005,
// Where does it come from?! // Where do they come from?!
MAX_READ_LENGTH: 0x00010000, MAX_READ_LENGTH: 0x00010000,
MAX_WRITE_LENGTH: 0x00010000 - 0x71,
}; };
...@@ -29,6 +29,22 @@ const tests = { ...@@ -29,6 +29,22 @@ const tests = {
unlink: function(client) { unlink: function(client) {
return client.unlink(file); return client.unlink(file);
}, },
'open new file and write': asyncFn(function*(client) {
const fd = yield client.open(file, 'w');
try {
try {
t.same(yield client.write(fd, data, undefined, undefined, 0), {
bytesWritten: data.length,
buffer: data,
});
} finally {
yield client.close(fd);
}
t.same(yield client.readFile(file), data);
} finally {
yield client.unlink(file);
}
}),
rmdir: function(client) { rmdir: function(client) {
return client.rmdir(dir); return client.rmdir(dir);
}, },
...@@ -40,7 +56,6 @@ asyncFn(function*() { ...@@ -40,7 +56,6 @@ asyncFn(function*() {
); );
options.autoCloseTimeout = 0; options.autoCloseTimeout = 0;
const client = new Smb2(options); const client = new Smb2(options);
try { try {
let result; let result;
for (const name of Object.keys(tests)) { for (const name of Object.keys(tests)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment