123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782 |
- 'use strict';
- const assert = require('assert');
- const { constants } = require('fs');
- const {
- fixture,
- mustCall,
- mustCallAtLeast,
- mustNotCall,
- setup: setup_,
- setupSimple
- } = require('./common.js');
- const { OPEN_MODE, Stats, STATUS_CODE } = require('../lib/protocol/SFTP.js');
- const DEBUG = false;
- setup('open', mustCall((client, server) => {
- const path_ = '/tmp/foo.txt';
- const handle_ = Buffer.from('node.js');
- const pflags_ = (OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE);
- server.on('OPEN', mustCall((id, path, pflags, attrs) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- assert(pflags === pflags_, `Wrong flags: ${flagsToHuman(pflags)}`);
- server.handle(id, handle_);
- server.end();
- }));
- client.open(path_, 'w', mustCall((err, handle) => {
- assert(!err, `Unexpected open() error: ${err}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- }));
- }));
- setup('close', mustCall((client, server) => {
- const handle_ = Buffer.from('node.js');
- server.on('CLOSE', mustCall((id, handle) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.close(handle_, mustCall((err) => {
- assert(!err, `Unexpected close() error: ${err}`);
- }));
- }));
- setup('read', mustCall((client, server) => {
- const expected = Buffer.from('node.jsnode.jsnode.jsnode.jsnode.jsnode.js');
- const handle_ = Buffer.from('node.js');
- const buf = Buffer.alloc(expected.length);
- server.on('READ', mustCall((id, handle, offset, len) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- assert(offset === 5, `Wrong read offset: ${offset}`);
- assert(len === buf.length, `Wrong read len: ${len}`);
- server.data(id, expected);
- server.end();
- }));
- client.read(handle_, buf, 0, buf.length, 5, mustCall((err, nb) => {
- assert(!err, `Unexpected read() error: ${err}`);
- assert.deepStrictEqual(buf, expected, 'read data mismatch');
- }));
- }));
- setup('read (overflow)', mustCall((client, server) => {
- const maxChunk = client._maxReadLen;
- const expected = Buffer.alloc(3 * maxChunk, 'Q');
- const handle_ = Buffer.from('node.js');
- const buf = Buffer.alloc(expected.length, 0);
- let reqs = 0;
- server.on('READ', mustCall((id, handle, offset, len) => {
- ++reqs;
- assert.strictEqual(id, reqs - 1, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- assert.strictEqual(offset,
- (reqs - 1) * maxChunk,
- `Wrong read offset: ${offset}`);
- server.data(id, expected.slice(offset, offset + len));
- if (reqs === 3)
- server.end();
- }, 3));
- client.read(handle_, buf, 0, buf.length, 0, mustCall((err, nb) => {
- assert(!err, `Unexpected read() error: ${err}`);
- assert.deepStrictEqual(buf, expected);
- assert.strictEqual(nb, buf.length, 'read nb mismatch');
- }));
- }));
- setup('write', mustCall((client, server) => {
- const handle_ = Buffer.from('node.js');
- const buf = Buffer.from('node.jsnode.jsnode.jsnode.jsnode.jsnode.js');
- server.on('WRITE', mustCall((id, handle, offset, data) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- assert(offset === 5, `Wrong write offset: ${offset}`);
- assert.deepStrictEqual(data, buf, 'write data mismatch');
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.write(handle_, buf, 0, buf.length, 5, mustCall((err, nb) => {
- assert(!err, `Unexpected write() error: ${err}`);
- assert.strictEqual(nb, buf.length, 'wrong bytes written');
- }));
- }));
- setup('write (overflow)', mustCall((client, server) => {
- const maxChunk = client._maxWriteLen;
- const handle_ = Buffer.from('node.js');
- const buf = Buffer.allocUnsafe(3 * maxChunk);
- let reqs = 0;
- server.on('WRITE', mustCall((id, handle, offset, data) => {
- ++reqs;
- assert.strictEqual(id, reqs - 1, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- assert.strictEqual(offset,
- (reqs - 1) * maxChunk,
- `Wrong write offset: ${offset}`);
- assert((offset + data.length) <= buf.length, 'bad offset');
- assert.deepStrictEqual(data,
- buf.slice(offset, offset + data.length),
- 'write data mismatch');
- server.status(id, STATUS_CODE.OK);
- if (reqs === 3)
- server.end();
- }, 3));
- client.write(handle_, buf, 0, buf.length, 0, mustCall((err, nb) => {
- assert(!err, `Unexpected write() error: ${err}`);
- assert.strictEqual(nb, buf.length, 'wrote bytes written');
- }));
- }));
- setup('lstat', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- const attrs_ = new Stats({
- size: 10 * 1024,
- uid: 9001,
- gid: 9001,
- atime: (Date.now() / 1000) | 0,
- mtime: (Date.now() / 1000) | 0
- });
- server.on('LSTAT', mustCall((id, path) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- server.attrs(id, attrs_);
- server.end();
- }));
- client.lstat(path_, mustCall((err, attrs) => {
- assert(!err, `Unexpected lstat() error: ${err}`);
- assert.deepStrictEqual(attrs, attrs_, 'attrs mismatch');
- }));
- }));
- setup('fstat', mustCall((client, server) => {
- const handle_ = Buffer.from('node.js');
- const attrs_ = new Stats({
- size: 10 * 1024,
- uid: 9001,
- gid: 9001,
- atime: (Date.now() / 1000) | 0,
- mtime: (Date.now() / 1000) | 0
- });
- server.on('FSTAT', mustCall((id, handle) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- server.attrs(id, attrs_);
- server.end();
- }));
- client.fstat(handle_, mustCall((err, attrs) => {
- assert(!err, `Unexpected fstat() error: ${err}`);
- assert.deepStrictEqual(attrs, attrs_, 'attrs mismatch');
- }));
- }));
- setup('setstat', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- const attrs_ = new Stats({
- uid: 9001,
- gid: 9001,
- atime: (Date.now() / 1000) | 0,
- mtime: (Date.now() / 1000) | 0
- });
- server.on('SETSTAT', mustCall((id, path, attrs) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- assert.deepStrictEqual(attrs, attrs_, 'attrs mismatch');
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.setstat(path_, attrs_, mustCall((err) => {
- assert(!err, `Unexpected setstat() error: ${err}`);
- }));
- }));
- setup('fsetstat', mustCall((client, server) => {
- const handle_ = Buffer.from('node.js');
- const attrs_ = new Stats({
- uid: 9001,
- gid: 9001,
- atime: (Date.now() / 1000) | 0,
- mtime: (Date.now() / 1000) | 0
- });
- server.on('FSETSTAT', mustCall((id, handle, attrs) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- assert.deepStrictEqual(attrs, attrs_, 'attrs mismatch');
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.fsetstat(handle_, attrs_, mustCall((err) => {
- assert(!err, `Unexpected fsetstat() error: ${err}`);
- }));
- }));
- setup('opendir', mustCall((client, server) => {
- const handle_ = Buffer.from('node.js');
- const path_ = '/tmp';
- server.on('OPENDIR', mustCall((id, path) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- server.handle(id, handle_);
- server.end();
- }));
- client.opendir(path_, mustCall((err, handle) => {
- assert(!err, `Unexpected opendir() error: ${err}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- }));
- }));
- setup('readdir', mustCall((client, server) => {
- const handle_ = Buffer.from('node.js');
- const list_ = [
- { filename: '.',
- longname: 'drwxr-xr-x 56 nodejs nodejs 4096 Nov 10 01:05 .',
- attrs: new Stats({
- mode: 0o755 | constants.S_IFDIR,
- size: 4096,
- uid: 9001,
- gid: 8001,
- atime: 1415599549,
- mtime: 1415599590
- })
- },
- { filename: '..',
- longname: 'drwxr-xr-x 4 root root 4096 May 16 2013 ..',
- attrs: new Stats({
- mode: 0o755 | constants.S_IFDIR,
- size: 4096,
- uid: 0,
- gid: 0,
- atime: 1368729954,
- mtime: 1368729999
- })
- },
- { filename: 'foo',
- longname: 'drwxrwxrwx 2 nodejs nodejs 4096 Mar 8 2009 foo',
- attrs: new Stats({
- mode: 0o777 | constants.S_IFDIR,
- size: 4096,
- uid: 9001,
- gid: 8001,
- atime: 1368729954,
- mtime: 1368729999
- })
- },
- { filename: 'bar',
- longname: '-rw-r--r-- 1 nodejs nodejs 513901992 Dec 4 2009 bar',
- attrs: new Stats({
- mode: 0o644 | constants.S_IFREG,
- size: 513901992,
- uid: 9001,
- gid: 8001,
- atime: 1259972199,
- mtime: 1259972199
- })
- }
- ];
- server.on('READDIR', mustCall((id, handle) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- server.name(id, list_);
- server.end();
- }));
- client.readdir(handle_, mustCall((err, list) => {
- assert(!err, `Unexpected readdir() error: ${err}`);
- assert.deepStrictEqual(list,
- list_.slice(2),
- 'dir list mismatch');
- }));
- }));
- setup('readdir (full)', mustCall((client, server) => {
- const handle_ = Buffer.from('node.js');
- const list_ = [
- { filename: '.',
- longname: 'drwxr-xr-x 56 nodejs nodejs 4096 Nov 10 01:05 .',
- attrs: new Stats({
- mode: 0o755 | constants.S_IFDIR,
- size: 4096,
- uid: 9001,
- gid: 8001,
- atime: 1415599549,
- mtime: 1415599590
- })
- },
- { filename: '..',
- longname: 'drwxr-xr-x 4 root root 4096 May 16 2013 ..',
- attrs: new Stats({
- mode: 0o755 | constants.S_IFDIR,
- size: 4096,
- uid: 0,
- gid: 0,
- atime: 1368729954,
- mtime: 1368729999
- })
- },
- { filename: 'foo',
- longname: 'drwxrwxrwx 2 nodejs nodejs 4096 Mar 8 2009 foo',
- attrs: new Stats({
- mode: 0o777 | constants.S_IFDIR,
- size: 4096,
- uid: 9001,
- gid: 8001,
- atime: 1368729954,
- mtime: 1368729999
- })
- },
- { filename: 'bar',
- longname: '-rw-r--r-- 1 nodejs nodejs 513901992 Dec 4 2009 bar',
- attrs: new Stats({
- mode: 0o644 | constants.S_IFREG,
- size: 513901992,
- uid: 9001,
- gid: 8001,
- atime: 1259972199,
- mtime: 1259972199
- })
- }
- ];
- server.on('READDIR', mustCall((id, handle) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- server.name(id, list_);
- server.end();
- }));
- client.readdir(handle_, { full: true }, mustCall((err, list) => {
- assert(!err, `Unexpected readdir() error: ${err}`);
- assert.deepStrictEqual(list, list_, 'dir list mismatch');
- }));
- }));
- setup('readdir (EOF)', mustCall((client, server) => {
- const handle_ = Buffer.from('node.js');
- server.on('READDIR', mustCall((id, handle) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- server.status(id, STATUS_CODE.EOF);
- server.end();
- }));
- client.readdir(handle_, mustCall((err, list) => {
- assert(err && err.code === STATUS_CODE.EOF,
- `Expected EOF, got: ${err}`);
- }));
- }));
- setup('unlink', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- server.on('REMOVE', mustCall((id, path) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.unlink(path_, mustCall((err) => {
- assert(!err, `Unexpected unlink() error: ${err}`);
- }));
- }));
- setup('mkdir', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- server.on('MKDIR', mustCall((id, path) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.mkdir(path_, mustCall((err) => {
- assert(!err, `Unexpected mkdir() error: ${err}`);
- }));
- }));
- setup('rmdir', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- server.on('RMDIR', mustCall((id, path) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.rmdir(path_, mustCall((err) => {
- assert(!err, `Unexpected rmdir() error: ${err}`);
- }));
- }));
- setup('realpath', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- const name_ = { filename: '/tmp/foo' };
- server.on('REALPATH', mustCall((id, path) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- server.name(id, name_);
- server.end();
- }));
- client.realpath(path_, mustCall((err, name) => {
- assert(!err, `Unexpected realpath() error: ${err}`);
- assert.deepStrictEqual(name, name_.filename, 'name mismatch');
- }));
- }));
- setup('stat', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- const attrs_ = new Stats({
- mode: 0o644 | constants.S_IFREG,
- size: 10 * 1024,
- uid: 9001,
- gid: 9001,
- atime: (Date.now() / 1000) | 0,
- mtime: (Date.now() / 1000) | 0
- });
- server.on('STAT', mustCall((id, path) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- server.attrs(id, attrs_);
- server.end();
- }));
- client.stat(path_, mustCall((err, attrs) => {
- assert(!err, `Unexpected stat() error: ${err}`);
- assert.deepStrictEqual(attrs, attrs_, 'attrs mismatch');
- const expectedTypes = {
- isDirectory: false,
- isFile: true,
- isBlockDevice: false,
- isCharacterDevice: false,
- isSymbolicLink: false,
- isFIFO: false,
- isSocket: false
- };
- for (const [fn, expect] of Object.entries(expectedTypes))
- assert(attrs[fn]() === expect, `attrs.${fn}() failed`);
- }));
- }));
- setup('rename', mustCall((client, server) => {
- const oldPath_ = '/foo/bar/baz';
- const newPath_ = '/tmp/foo';
- server.on('RENAME', mustCall((id, oldPath, newPath) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(oldPath === oldPath_, `Wrong old path: ${oldPath}`);
- assert(newPath === newPath_, `Wrong new path: ${newPath}`);
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.rename(oldPath_, newPath_, mustCall((err) => {
- assert(!err, `Unexpected rename() error: ${err}`);
- }));
- }));
- setup('readlink', mustCall((client, server) => {
- const linkPath_ = '/foo/bar/baz';
- const name = { filename: '/tmp/foo' };
- server.on('READLINK', mustCall((id, linkPath) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(linkPath === linkPath_, `Wrong link path: ${linkPath}`);
- server.name(id, name);
- server.end();
- }));
- client.readlink(linkPath_, mustCall((err, targetPath) => {
- assert(!err, `Unexpected readlink() error: ${err}`);
- assert(targetPath === name.filename,
- `Wrong target path: ${targetPath}`);
- }));
- }));
- setup('symlink', mustCall((client, server) => {
- const linkPath_ = '/foo/bar/baz';
- const targetPath_ = '/tmp/foo';
- server.on('SYMLINK', mustCall((id, linkPath, targetPath) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(linkPath === linkPath_, `Wrong link path: ${linkPath}`);
- assert(targetPath === targetPath_, `Wrong target path: ${targetPath}`);
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.symlink(targetPath_, linkPath_, mustCall((err) => {
- assert(!err, `Unexpected symlink() error: ${err}`);
- }));
- }));
- setup('readFile', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- const handle_ = Buffer.from('hi mom!');
- const data_ = Buffer.from('hello world');
- server.on('OPEN', mustCall((id, path, pflags, attrs) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- assert(pflags === OPEN_MODE.READ, `Wrong flags: ${flagsToHuman(pflags)}`);
- server.handle(id, handle_);
- })).on('FSTAT', mustCall((id, handle) => {
- assert(id === 1, `Wrong request id: ${id}`);
- const attrs = new Stats({
- size: data_.length,
- uid: 9001,
- gid: 9001,
- atime: (Date.now() / 1000) | 0,
- mtime: (Date.now() / 1000) | 0
- });
- server.attrs(id, attrs);
- })).on('READ', mustCall((id, handle, offset, len) => {
- assert(id === 2, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- assert(offset === 0, `Wrong read offset: ${offset}`);
- server.data(id, data_);
- })).on('CLOSE', mustCall((id, handle) => {
- assert(id === 3, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.readFile(path_, mustCall((err, buf) => {
- assert(!err, `Unexpected error: ${err}`);
- assert.deepStrictEqual(buf, data_, 'data mismatch');
- }));
- }));
- setup('readFile (no size from fstat)', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- const handle_ = Buffer.from('hi mom!');
- const data_ = Buffer.from('hello world');
- let reads = 0;
- server.on('OPEN', mustCall((id, path, pflags, attrs) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- assert(pflags === OPEN_MODE.READ, `Wrong flags: ${flagsToHuman(pflags)}`);
- server.handle(id, handle_);
- })).on('FSTAT', mustCall((id, handle) => {
- assert(id === 1, `Wrong request id: ${id}`);
- const attrs = new Stats({
- uid: 9001,
- gid: 9001,
- atime: (Date.now() / 1000) | 0,
- mtime: (Date.now() / 1000) | 0
- });
- server.attrs(id, attrs);
- })).on('READ', mustCall((id, handle, offset, len) => {
- assert(++reads + 1 === id, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- switch (id) {
- case 2:
- assert(offset === 0, `Wrong read offset for first read: ${offset}`);
- server.data(id, data_);
- break;
- case 3:
- assert(offset === data_.length,
- `Wrong read offset for second read: ${offset}`);
- server.status(id, STATUS_CODE.EOF);
- break;
- }
- }, 2)).on('CLOSE', mustCall((id, handle) => {
- assert(id === 4, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- client.readFile(path_, mustCall((err, buf) => {
- assert(!err, `Unexpected error: ${err}`);
- assert.deepStrictEqual(buf, data_, 'data mismatch');
- }));
- }));
- setup('ReadStream', mustCall((client, server) => {
- let reads = 0;
- const path_ = '/foo/bar/baz';
- const handle_ = Buffer.from('hi mom!');
- const data_ = Buffer.from('hello world');
- server.on('OPEN', mustCall((id, path, pflags, attrs) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- assert(pflags === OPEN_MODE.READ, `Wrong flags: ${flagsToHuman(pflags)}`);
- server.handle(id, handle_);
- })).on('READ', mustCall((id, handle, offset, len) => {
- assert(id === ++reads, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- if (reads === 1) {
- assert(offset === 0, `Wrong read offset: ${offset}`);
- server.data(id, data_);
- } else {
- server.status(id, STATUS_CODE.EOF);
- }
- }, 2)).on('CLOSE', mustCall((id, handle) => {
- assert(id === 3, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- let buf = [];
- client.createReadStream(path_).on('readable', mustCallAtLeast(function() {
- let chunk;
- while ((chunk = this.read()) !== null)
- buf.push(chunk);
- })).on('end', mustCall(() => {
- buf = Buffer.concat(buf);
- assert.deepStrictEqual(buf, data_, 'data mismatch');
- }));
- }));
- setup('ReadStream (fewer bytes than requested)', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- const handle_ = Buffer.from('hi mom!');
- const data_ = Buffer.from('hello world');
- server.on('OPEN', mustCall((id, path, pflags, attrs) => {
- server.handle(id, handle_);
- })).on('READ', mustCallAtLeast((id, handle, offset, len) => {
- if (offset > data_.length) {
- server.status(id, STATUS_CODE.EOF);
- } else {
- // Only read 4 bytes at a time
- server.data(id, data_.slice(offset, offset + 4));
- }
- })).on('CLOSE', mustCall((id, handle) => {
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- let buf = [];
- client.createReadStream(path_).on('readable', mustCallAtLeast(function() {
- let chunk;
- while ((chunk = this.read()) !== null)
- buf.push(chunk);
- })).on('end', mustCall(() => {
- buf = Buffer.concat(buf);
- assert.deepStrictEqual(buf, data_, 'data mismatch');
- }));
- }));
- setup('ReadStream (error)', mustCall((client, server) => {
- const path_ = '/foo/bar/baz';
- server.on('OPEN', mustCall((id, path, pflags, attrs) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- assert(pflags === OPEN_MODE.READ, `Wrong flags: ${flagsToHuman(pflags)}`);
- server.status(id, STATUS_CODE.NO_SUCH_FILE);
- server.end();
- }));
- client.createReadStream(path_).on('error', mustCall((err) => {
- assert(err.code === STATUS_CODE.NO_SUCH_FILE);
- }));
- }));
- setup('WriteStream', mustCall((client, server) => {
- let writes = 0;
- const path_ = '/foo/bar/baz';
- const handle_ = Buffer.from('hi mom!');
- const data_ = Buffer.from('hello world');
- const pflags_ = OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE;
- server.on('OPEN', mustCall((id, path, pflags, attrs) => {
- assert(id === 0, `Wrong request id: ${id}`);
- assert(path === path_, `Wrong path: ${path}`);
- assert(pflags === pflags_, `Wrong flags: ${flagsToHuman(pflags)}`);
- server.handle(id, handle_);
- })).on('FSETSTAT', mustCall((id, handle, attrs) => {
- assert(id === 1, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- assert.strictEqual(attrs.mode, 0o666, 'Wrong file mode');
- server.status(id, STATUS_CODE.OK);
- })).on('WRITE', mustCall((id, handle, offset, data) => {
- assert(id === ++writes + 1, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- assert(offset === ((writes - 1) * data_.length),
- `Wrong write offset: ${offset}`);
- assert.deepStrictEqual(data, data_, 'Wrong data');
- server.status(id, STATUS_CODE.OK);
- }, 3)).on('CLOSE', mustCall((id, handle) => {
- assert(id === 5, `Wrong request id: ${id}`);
- assert.deepStrictEqual(handle, handle_, 'handle mismatch');
- server.status(id, STATUS_CODE.OK);
- server.end();
- }));
- const writer = client.createWriteStream(path_);
- writer.cork && writer.cork();
- writer.write(data_);
- writer.write(data_);
- writer.write(data_);
- writer.uncork && writer.uncork();
- writer.end();
- }));
- {
- const { client, server } = setup_(
- 'SFTP server aborts with exit-status',
- {
- client: { username: 'foo', password: 'bar' },
- server: { hostKeys: [ fixture('ssh_host_rsa_key') ] },
- },
- );
- server.on('connection', mustCall((conn) => {
- conn.on('authentication', mustCall((ctx) => {
- ctx.accept();
- })).on('ready', mustCall(() => {
- conn.on('session', mustCall((accept, reject) => {
- accept().on('sftp', mustCall((accept, reject) => {
- const sftp = accept();
- // XXX: hack
- sftp._protocol.exitStatus(sftp.outgoing.id, 127);
- sftp._protocol.channelClose(sftp.outgoing.id);
- }));
- }));
- }));
- }));
- client.on('ready', mustCall(() => {
- const timeout = setTimeout(mustNotCall(), 1000);
- client.sftp(mustCall((err, sftp) => {
- clearTimeout(timeout);
- assert(err, 'Expected error');
- assert(err.code === 127, `Expected exit code 127, saw: ${err.code}`);
- client.end();
- }));
- }));
- }
- // =============================================================================
- function setup(title, cb) {
- const { client, server } = setupSimple(DEBUG, title);
- let clientSFTP;
- let serverSFTP;
- const onSFTP = mustCall(() => {
- if (clientSFTP && serverSFTP)
- cb(clientSFTP, serverSFTP);
- }, 2);
- client.on('ready', mustCall(() => {
- client.sftp(mustCall((err, sftp) => {
- assert(!err, `[${title}] Unexpected client sftp start error: ${err}`);
- sftp.on('close', mustCall(() => {
- client.end();
- }));
- clientSFTP = sftp;
- onSFTP();
- }));
- }));
- server.on('connection', mustCall((conn) => {
- conn.on('ready', mustCall(() => {
- conn.on('session', mustCall((accept, reject) => {
- accept().on('sftp', mustCall((accept, reject) => {
- const sftp = accept();
- sftp.on('close', mustCall(() => {
- conn.end();
- }));
- serverSFTP = sftp;
- onSFTP();
- }));
- }));
- }));
- }));
- }
- function flagsToHuman(flags) {
- const ret = [];
- for (const [name, value] of Object.entries(OPEN_MODE)) {
- if (flags & value)
- ret.push(name);
- }
- return ret.join(' | ');
- }
|