bdy 1.14.1-dev → 1.14.2-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,497 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const logger_1 = __importDefault(require("../logger"));
7
- const ssh2_1 = __importDefault(require("ssh2"));
8
- const promises_1 = __importDefault(require("fs/promises"));
9
- const path_1 = __importDefault(require("path"));
10
- const node_os_1 = require("node:os");
11
- const { flagsToString, STATUS_CODE } = ssh2_1.default.utils.sftp;
12
- class ServerSftp {
13
- constructor(sftp) {
14
- logger_1.default.debug('Creating sftp server');
15
- this.openHandlers = new Map();
16
- this.count = 0;
17
- this.sftp = sftp;
18
- this.sftp.on('OPEN', (reqId, fileName, flags, attrs) => this.open(reqId, fileName, flags, attrs));
19
- this.sftp.on('READ', (reqId, handle, offset, length) => this.read(reqId, handle, offset, length));
20
- this.sftp.on('WRITE', (reqId, handle, offset, data) => this.write(reqId, handle, offset, data));
21
- this.sftp.on('FSTAT', (reqId, handle) => this.fstat(reqId, handle));
22
- this.sftp.on('FSETSTAT', (reqId, handle, attrs) => this.fsetstat(reqId, handle, attrs));
23
- this.sftp.on('CLOSE', (reqId, handle) => this.close(reqId, handle));
24
- this.sftp.on('OPENDIR', (reqId, path) => this.opendir(reqId, path));
25
- this.sftp.on('READDIR', (reqId, handle) => this.readdir(reqId, handle));
26
- this.sftp.on('LSTAT', (reqId, path) => this.lstat(reqId, path));
27
- this.sftp.on('STAT', (reqId, path) => this.stat(reqId, path));
28
- this.sftp.on('REMOVE', (reqId, path) => this.remove(reqId, path));
29
- this.sftp.on('RMDIR', (reqId, path) => this.rmdir(reqId, path));
30
- this.sftp.on('REALPATH', (reqId, path) => this.realpath(reqId, path));
31
- this.sftp.on('READLINK', (reqId, path) => this.readlink(reqId, path));
32
- this.sftp.on('SETSTAT', (reqId, path, attrs) => this.setstat(reqId, path, attrs));
33
- this.sftp.on('MKDIR', (reqId, path, attrs) => this.mkdir(reqId, path, attrs));
34
- this.sftp.on('RENAME', (reqId, oldPath, newPath) => this.rename(reqId, oldPath, newPath));
35
- this.sftp.on('SYMLINK', (reqId, linkPath, targetPath) => this.symlink(reqId, linkPath, targetPath));
36
- }
37
- debugStart(txt) {
38
- logger_1.default.debug(txt);
39
- return process.hrtime();
40
- }
41
- debugEnd(txt, s, err) {
42
- const [seconds, nano] = process.hrtime(s);
43
- const ms = seconds * 1000 + nano / 1000 / 1000;
44
- logger_1.default.debug(`${txt} in ${ms}ms`);
45
- if (err)
46
- logger_1.default.debug(err);
47
- }
48
- async open(reqId, fileName, flags, attrs) {
49
- const s = this.debugStart(`SFTP want to open file ${fileName}`);
50
- try {
51
- const flag = flagsToString(flags);
52
- if (!flag) {
53
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
54
- this.debugEnd('SFTP open file failed', s);
55
- return;
56
- }
57
- const id = ++this.count;
58
- const handle = Buffer.alloc(4);
59
- handle.writeUint32BE(id, 0);
60
- const fd = await promises_1.default.open(fileName, flag);
61
- this.openHandlers.set(id, fd);
62
- await this._fsetstat(fd, attrs);
63
- this.sftp.handle(reqId, handle);
64
- this.debugEnd('SFTP open file succeed', s);
65
- }
66
- catch (err) {
67
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
68
- this.debugEnd('SFTP open file failed', s, err);
69
- }
70
- }
71
- async read(reqId, handle, offset, length) {
72
- const s = this.debugStart('SFTP want to read file');
73
- try {
74
- const id = handle.readUInt32BE(0);
75
- if (!this.openHandlers.has(id)) {
76
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
77
- this.debugEnd('SFTP read file failed', s);
78
- return;
79
- }
80
- const fd = this.openHandlers.get(id);
81
- const buffer = Buffer.alloc(length);
82
- const r = await fd.read(buffer, {
83
- offset: 0,
84
- length,
85
- position: offset,
86
- });
87
- if (r.bytesRead <= 0) {
88
- this.sftp.status(reqId, STATUS_CODE.EOF);
89
- }
90
- else if (r.bytesRead < length) {
91
- // strip buffer
92
- const buffer2 = Buffer.alloc(r.bytesRead);
93
- buffer.copy(buffer2, 0, 0, r.bytesRead);
94
- this.sftp.data(reqId, buffer2);
95
- }
96
- else {
97
- this.sftp.data(reqId, buffer);
98
- }
99
- this.debugEnd('SFTP read file succeed', s);
100
- }
101
- catch (err) {
102
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
103
- this.debugEnd('SFTP read file failed', s, err);
104
- }
105
- }
106
- async write(reqId, handle, offset, data) {
107
- const s = this.debugStart('SFTP want to write file');
108
- try {
109
- const id = handle.readUInt32BE(0);
110
- if (!this.openHandlers.has(id)) {
111
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
112
- this.debugEnd('SFTP write file failed', s);
113
- return;
114
- }
115
- const fd = this.openHandlers.get(id);
116
- await fd.write(data, 0, data.length, offset);
117
- this.sftp.status(reqId, STATUS_CODE.OK);
118
- this.debugEnd('SFTP write file succeed', s);
119
- }
120
- catch (err) {
121
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
122
- this.debugEnd('SFTP write file failed', s, err);
123
- }
124
- }
125
- async close(reqId, handle) {
126
- const s = this.debugStart('SFTP want to close handler');
127
- try {
128
- const id = handle.readUInt32BE(0);
129
- if (!this.openHandlers.has(id)) {
130
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
131
- this.debugEnd('SFTP close handler failed', s);
132
- return;
133
- }
134
- const fd = this.openHandlers.get(id);
135
- await fd.close();
136
- this.openHandlers.delete(id);
137
- this.sftp.status(reqId, STATUS_CODE.OK);
138
- this.debugEnd('SFTP closed handler succeed', s);
139
- }
140
- catch (err) {
141
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
142
- this.debugEnd('SFTP close handler failed', s, err);
143
- }
144
- }
145
- async fstat(reqId, handle) {
146
- const s = this.debugStart('SFTP want to stat file');
147
- try {
148
- const id = handle.readUInt32BE(0);
149
- if (!this.openHandlers.has(id)) {
150
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
151
- this.debugEnd('SFTP stat file failed', s);
152
- return;
153
- }
154
- const fd = this.openHandlers.get(id);
155
- const attrs = await fd.stat();
156
- this.sftp.attrs(reqId, attrs);
157
- this.debugEnd('SFTP stat file succeed', s);
158
- }
159
- catch (err) {
160
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
161
- this.debugEnd('SFTP stat file failed', s, err);
162
- }
163
- }
164
- async _fsetstat(fd, attrs) {
165
- if (Number.isInteger(attrs.uid) && Number.isInteger(attrs.gid)) {
166
- const s = this.debugStart(`SFTP want to chown with uid: ${attrs.uid}, gid: ${attrs.gid}`);
167
- try {
168
- await fd.chown(attrs.uid, attrs.gid);
169
- this.debugEnd('SFTP chown succeed', s);
170
- }
171
- catch (err) {
172
- this.debugEnd('SFTP chown failed', s, err);
173
- }
174
- }
175
- if (attrs.mode) {
176
- const s = this.debugStart(`SFTP want to chmod with mode: ${attrs.mode}`);
177
- try {
178
- await fd.chmod(attrs.mode);
179
- this.debugEnd('SFTP chmod succeed', s);
180
- }
181
- catch (err) {
182
- this.debugEnd('SFTP chmod failed', s, err);
183
- }
184
- }
185
- if (attrs.atime && attrs.mtime) {
186
- const s = this.debugStart(`SFTP want to utimes with atime: ${attrs.atime}, mtime: ${attrs.mtime}`);
187
- try {
188
- await fd.utimes(attrs.atime, attrs.mtime);
189
- this.debugEnd('SFTP utimes succeed', s);
190
- }
191
- catch (err) {
192
- this.debugEnd('SFTP utimes failed', s, err);
193
- }
194
- }
195
- }
196
- async fsetstat(reqId, handle, attrs) {
197
- const s = this.debugStart('SFTP want to set attrs of file');
198
- try {
199
- const id = handle.readUInt32BE(0);
200
- if (!this.openHandlers.has(id)) {
201
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
202
- this.debugEnd('SFTP set attrs of file failed', s);
203
- return;
204
- }
205
- const fd = this.openHandlers.get(id);
206
- await this._fsetstat(fd, attrs);
207
- this.sftp.status(reqId, STATUS_CODE.OK);
208
- this.debugEnd('SFTP set attrs of file succeed', s);
209
- }
210
- catch (err) {
211
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
212
- this.debugEnd('SFTP set attrs of file failed', s, err);
213
- }
214
- }
215
- async opendir(reqId, path) {
216
- const s = this.debugStart(`SFTP want to open directory ${path}`);
217
- try {
218
- const id = ++this.count;
219
- const handle = Buffer.alloc(4);
220
- handle.writeUint32BE(id, 0);
221
- const fd = await promises_1.default.opendir(path);
222
- this.openHandlers.set(id, fd);
223
- this.sftp.handle(reqId, handle);
224
- this.debugEnd('SFTP open directory succeed', s);
225
- }
226
- catch (err) {
227
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
228
- this.debugEnd('SFTP open directory failed', s, err);
229
- }
230
- }
231
- formatMode(mode) {
232
- const types = ['---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx'];
233
- return [
234
- types[(mode >> 6) & 7],
235
- types[(mode >> 3) & 7],
236
- types[mode & 7],
237
- ].join('');
238
- }
239
- async longname(fullPath, name, stats) {
240
- // -rw-r--r-- 1 Michal staff 160543 Jul 29 09:31 cli.log
241
- const isDir = stats.isDirectory();
242
- const isLink = stats.isSymbolicLink();
243
- let displayName = name;
244
- if (isLink) {
245
- const link = await promises_1.default.readlink(fullPath);
246
- displayName = `${name} -> ${link}`;
247
- }
248
- return [
249
- isDir ? 'd' : isLink ? 'l' : '-',
250
- this.formatMode(stats.mode),
251
- ' ',
252
- (stats.nlink || 1).toString().padEnd(4),
253
- ' ',
254
- stats.uid.toString().padEnd(4),
255
- ' ',
256
- stats.gid.toString().padEnd(4),
257
- ' ',
258
- stats.size.toString().padStart(10),
259
- ' ',
260
- stats.mtime.toISOString().slice(0, 19).replace('T', ' '),
261
- ' ',
262
- displayName,
263
- ].join('');
264
- }
265
- async readdir(reqId, handle) {
266
- const s = this.debugStart('SFTP want to read directory');
267
- try {
268
- const id = handle.readUInt32BE(0);
269
- if (!this.openHandlers.has(id)) {
270
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
271
- this.debugEnd('SFTP read directory failed', s);
272
- return;
273
- }
274
- const fd = this.openHandlers.get(id);
275
- const names = [];
276
- let r = 0;
277
- const m = 1000;
278
- while (r < m) {
279
- const dir = await fd.read();
280
- if (!dir && !r) {
281
- this.sftp.status(reqId, STATUS_CODE.EOF);
282
- this.debugEnd('SFTP read directory ended', s);
283
- return;
284
- }
285
- else if (!dir) {
286
- break;
287
- }
288
- else {
289
- const name = dir.name;
290
- const fullPath = path_1.default.join(fd.path, name);
291
- const stat = await promises_1.default.lstat(fullPath);
292
- const longname = await this.longname(fullPath, name, stat);
293
- names.push({
294
- filename: name,
295
- longname,
296
- attrs: stat,
297
- });
298
- r += 1;
299
- }
300
- }
301
- this.sftp.name(reqId, names);
302
- this.debugEnd(`SFTP read directory ${fd.path} succeed`, s);
303
- }
304
- catch (err) {
305
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
306
- this.debugEnd('SFTP read directory failed', s, err);
307
- }
308
- }
309
- async stat(reqId, path) {
310
- const s = this.debugStart(`SFTP want to stat ${path}`);
311
- try {
312
- const attrs = await promises_1.default.stat(path);
313
- this.sftp.attrs(reqId, attrs);
314
- this.debugEnd('SFTP stat path succeed', s);
315
- }
316
- catch (err) {
317
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
318
- this.debugEnd('SFTP stat path failed', s, err);
319
- }
320
- }
321
- async remove(reqId, path) {
322
- const s = this.debugStart(`SFTP want to remove file ${path}`);
323
- try {
324
- await promises_1.default.rm(path);
325
- this.sftp.status(reqId, STATUS_CODE.OK);
326
- this.debugEnd('SFTP removed file succeed', s);
327
- }
328
- catch (err) {
329
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
330
- this.debugEnd('SFTP remove file failed', s, err);
331
- }
332
- }
333
- async rmdir(reqId, path) {
334
- const s = this.debugStart(`SFTP want to remove directory ${path}`);
335
- try {
336
- await promises_1.default.rmdir(path, {
337
- recursive: true,
338
- });
339
- this.sftp.status(reqId, STATUS_CODE.OK);
340
- this.debugEnd('SFTP remove directory succeed', s);
341
- }
342
- catch (err) {
343
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
344
- this.debugEnd('SFTP remove directory failed', s, err);
345
- }
346
- }
347
- async realpath(reqId, path) {
348
- const s = this.debugStart(`SFTP want realpath ${path}`);
349
- try {
350
- let p = path || '~/';
351
- if (p.includes('~')) {
352
- p = p.replaceAll('~', (0, node_os_1.homedir)());
353
- }
354
- const realPath = await promises_1.default.realpath(p);
355
- this.sftp.name(reqId, [
356
- {
357
- filename: realPath,
358
- },
359
- ]);
360
- this.debugEnd('SFTP realpath succeed', s);
361
- }
362
- catch (err) {
363
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
364
- this.debugEnd('SFTP realpath failed', s, err);
365
- }
366
- }
367
- async readlink(reqId, path) {
368
- const s = this.debugStart(`SFTP want readlink ${path}`);
369
- try {
370
- const realPath = await promises_1.default.readlink(path);
371
- this.sftp.name(reqId, [
372
- {
373
- filename: realPath,
374
- },
375
- ]);
376
- this.debugEnd('SFTP readlink succeed', s);
377
- }
378
- catch (err) {
379
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
380
- this.debugEnd('SFTP readlink failed', s, err);
381
- }
382
- }
383
- async _setstat(path, attrs) {
384
- if (Number.isInteger(attrs.uid) && Number.isInteger(attrs.gid)) {
385
- const s = this.debugStart(`SFTP want chown with uid: ${attrs.uid}, gid: ${attrs.gid}`);
386
- try {
387
- await promises_1.default.chown(path, attrs.uid, attrs.gid);
388
- this.debugEnd('SFTP chown succeed', s);
389
- }
390
- catch (err) {
391
- this.debugEnd('SFTP chown failed', s, err);
392
- }
393
- }
394
- if (attrs.mode) {
395
- const s = this.debugStart(`SFTP want to chmod with mode: ${attrs.mode}`);
396
- try {
397
- await promises_1.default.chmod(path, attrs.mode);
398
- this.debugEnd('SFTP chmod succeed', s);
399
- }
400
- catch (err) {
401
- this.debugEnd('SFTP chmod failed', s, err);
402
- }
403
- }
404
- if (attrs.atime && attrs.mtime) {
405
- const s = this.debugStart(`SFTP want to utimes with atime: ${attrs.atime}, mtime: ${attrs.mtime}`);
406
- try {
407
- await promises_1.default.utimes(path, attrs.atime, attrs.mtime);
408
- this.debugEnd('SFTP utimes succeed', s);
409
- }
410
- catch (err) {
411
- this.debugEnd('SFTP utimes failed', s, err);
412
- }
413
- }
414
- }
415
- async setstat(reqId, path, attrs) {
416
- const s = this.debugStart(`SFTP want to set attrs ${path}`);
417
- try {
418
- await this._setstat(path, attrs);
419
- this.sftp.status(reqId, STATUS_CODE.OK);
420
- this.debugEnd('SFTP set attrs succeed', s);
421
- }
422
- catch (err) {
423
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
424
- this.debugEnd('SFTP set attrs failed', s, err);
425
- }
426
- }
427
- async mkdir(reqId, path, attrs) {
428
- const s = this.debugStart(`SFTP want to create directory ${path}`);
429
- try {
430
- await promises_1.default.mkdir(path);
431
- await this._setstat(path, attrs);
432
- this.sftp.status(reqId, STATUS_CODE.OK);
433
- this.debugEnd('SFTP create directory succeed', s);
434
- }
435
- catch (err) {
436
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
437
- this.debugEnd('SFTP create directory failed', s, err);
438
- }
439
- }
440
- async rename(reqId, oldPath, newPath) {
441
- const s = this.debugStart(`SFTP want to rename path ${oldPath} to ${newPath}`);
442
- try {
443
- await promises_1.default.rename(oldPath, newPath);
444
- this.sftp.status(reqId, STATUS_CODE.OK);
445
- this.debugEnd('SFTP rename path succeed', s);
446
- }
447
- catch (err) {
448
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
449
- this.debugEnd('SFTP rename path failed', s, err);
450
- }
451
- }
452
- async symlink(reqId, linkPath, targetPath) {
453
- const s = this.debugStart(`SFTP want to symlink ${targetPath} at ${linkPath}`);
454
- try {
455
- await promises_1.default.symlink(targetPath, linkPath);
456
- this.sftp.status(reqId, STATUS_CODE.OK);
457
- this.debugEnd('SFTP symlink succeed', s);
458
- }
459
- catch (err) {
460
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
461
- this.debugEnd('SFTP symlink failed', s, err);
462
- }
463
- }
464
- async lstat(reqId, path) {
465
- const s = this.debugStart(`SFTP want to lstat ${path}`);
466
- try {
467
- const attrs = await promises_1.default.lstat(path);
468
- this.sftp.attrs(reqId, attrs);
469
- this.debugEnd('SFTP lstat path succeed', s);
470
- }
471
- catch (err) {
472
- this.sftp.status(reqId, STATUS_CODE.FAILURE);
473
- this.debugEnd('SFTP lstat path failed', s, err);
474
- }
475
- }
476
- destroy() {
477
- if (this.sftp) {
478
- this.sftp.removeAllListeners();
479
- this.sftp.end();
480
- this.sftp = null;
481
- }
482
- if (this.openHandlers) {
483
- this.openHandlers.forEach((fd) => {
484
- try {
485
- fd.close();
486
- }
487
- catch {
488
- // do nothing
489
- }
490
- fd = null;
491
- });
492
- this.openHandlers = null;
493
- }
494
- this.count = 0;
495
- }
496
- }
497
- exports.default = ServerSftp;