1 | # SMB2 Client for Node.js
|
2 |
|
3 | [![Node compatibility](https://badgen.net/npm/node/@marsaud/smb2)](https://npmjs.org/package/@marsaud/smb2) [![License](https://badgen.net/npm/license/@marsaud/smb2)](https://npmjs.org/package/@marsaud/smb2) [![PackagePhobia](https://badgen.net/packagephobia/install/@marsaud/smb2)](https://packagephobia.now.sh/result?p=@marsaud/smb2)
|
4 |
|
5 | [![Package Version](https://badgen.net/npm/v/@marsaud/smb2)](https://npmjs.org/package/@marsaud/smb2) [![Build Status](https://travis-ci.org/Node-SMB/marsaud-smb2.png?branch=master)](https://travis-ci.org/Node-SMB/marsaud-smb2) [![Latest Commit](https://badgen.net/github/last-commit/Node-SMB/marsaud-smb2)](https://github.com/Node-SMB/marsaud-smb2/commits/master)
|
6 |
|
7 | ## Introduction
|
8 |
|
9 | This library is a simple implementation of SMB2 for Node.js. It allows you to access a SMB2 share as if you were using the native fs library.
|
10 |
|
11 | The development is still at an experimental stage and should not be yet considered for production environment.
|
12 |
|
13 | ## Installation
|
14 |
|
15 | ```bash
|
16 | npm install -S @marsaud/smb2
|
17 | ```
|
18 |
|
19 | ## API
|
20 |
|
21 | ### Asynchronicity
|
22 |
|
23 | All async methods can be used with Node-style callbacks or return promises if
|
24 | none is passed:
|
25 |
|
26 | ```js
|
27 | // Node-style callback
|
28 | smb2Client.readFile('foo.txt', function(err, content) {
|
29 | if (err) throw err;
|
30 | console.log(content);
|
31 | });
|
32 |
|
33 | // With promise, ideal with ES2017 async functions
|
34 | const content = await smb2Client.readFile('foo.txt');
|
35 | console.log(content);
|
36 | ```
|
37 |
|
38 | ### Construction
|
39 |
|
40 | > `var smb2Client = new SMB2 ( options )`
|
41 |
|
42 | The SMB2 class is the constructor of your SMB2 client.
|
43 |
|
44 | the parameter `options` accepts this list of attributes:
|
45 |
|
46 | - `share`: the share you want to access
|
47 | - `domain`: the domain of which the user is registered
|
48 | - `username`: the username of the user that access the share
|
49 | - `password`: the password
|
50 | - `port` (optional): default `445`, the port of the SMB server
|
51 | - `packetConcurrency` (optional): default `20`, the number of simultaneous packet when writing / reading data from the share
|
52 | - `autoCloseTimeout` (optional): default `10000`, the timeout in milliseconds before to close the SMB2 session and the socket, if set to `0` the connection will never be closed unless you do it
|
53 |
|
54 | Example:
|
55 |
|
56 | ```javascript
|
57 | // load the library
|
58 | var SMB2 = require('@marsaud/smb2');
|
59 |
|
60 | // create an SMB2 instance
|
61 | var smb2Client = new SMB2({
|
62 | share: '\\\\000.000.000.000\\c$',
|
63 | domain: 'DOMAIN',
|
64 | username: 'username',
|
65 | password: 'password!',
|
66 | });
|
67 | ```
|
68 |
|
69 | ### Connection management
|
70 |
|
71 | The connection to the SMB server will be automatically open when necessary.
|
72 |
|
73 | Unless you have set `autoCloseTimeout` to `0` during client construction, the connection will be closed automatically.
|
74 |
|
75 | If you have set `autoCloseTimeout` to `0`, the connection MUST be closed manually:
|
76 |
|
77 | ```js
|
78 | smb2Client.disconnect();
|
79 | ```
|
80 |
|
81 | ### High level methods
|
82 |
|
83 | > `smb2Client.exists ( path, callback )`
|
84 |
|
85 | Test whether or not the given path exists by checking with the file system.
|
86 |
|
87 | Example:
|
88 |
|
89 | ```javascript
|
90 | smb2Client.exists('path\\to\\my\\file.txt', function(err, exists) {
|
91 | if (err) throw err;
|
92 | console.log(exists ? "it's there" : "it's not there!");
|
93 | });
|
94 | ```
|
95 |
|
96 | > `smb2Client.mkdir ( path, [mode], callback )`
|
97 |
|
98 | Asynchronous `mkdir(2)`: create a directory.
|
99 |
|
100 | `mode` defaults to `0o777`.
|
101 |
|
102 | Example:
|
103 |
|
104 | ```javascript
|
105 | smb2Client.mkdir('path\\to\\the\\directory', function(err) {
|
106 | if (err) throw err;
|
107 | console.log('Directory created!');
|
108 | });
|
109 | ```
|
110 |
|
111 | > `smb2Client.readdir ( path, [options], callback )`
|
112 |
|
113 | - `path` String
|
114 | - `options` Object
|
115 | - `encoding` String | Null default = null
|
116 | - `callback` Function
|
117 |
|
118 | Asynchronous `readdir(3)`: reads the contents of a directory.
|
119 |
|
120 | The result is an array of the names of the files in the directory excluding `'.'` and `'..'`.
|
121 |
|
122 | If you want the response to include stats, you need to pass the `stats: true`. Response will be an Array of this form:
|
123 |
|
124 | ```
|
125 | [
|
126 | {
|
127 | name: String,
|
128 | birthtime: Date,
|
129 | mtime: Date,
|
130 | atime: Date,
|
131 | ctime: Date,
|
132 | isDirectory(): boolean
|
133 | },
|
134 | ...
|
135 | ]
|
136 | ```
|
137 |
|
138 | Example:
|
139 |
|
140 | ```javascript
|
141 | smb2Client.readdir('Windows\\System32', function(err, files) {
|
142 | if (err) throw err;
|
143 | console.log(files);
|
144 | });
|
145 | ```
|
146 |
|
147 | > `smb2Client.stat ( path, callback )`
|
148 |
|
149 | - `path` String
|
150 | - `callback` Function
|
151 |
|
152 | Asynchronous `stat`: query stats of a directory or file.
|
153 |
|
154 | Response will be an object with the following structure :
|
155 |
|
156 | ```
|
157 | {
|
158 | birthtime: Date,
|
159 | mtime: Date,
|
160 | atime: Date,
|
161 | ctime: Date,
|
162 | isDirectory(): boolean
|
163 | }
|
164 | ```
|
165 |
|
166 | > `smb2Client.readFile ( path, [options], callback )`
|
167 |
|
168 | - `path` String
|
169 | - `options` Object
|
170 | - `encoding` String | Null default = null
|
171 | - `callback` Function
|
172 |
|
173 | Asynchronously reads the entire content of a file.
|
174 |
|
175 | Example:
|
176 |
|
177 | ```javascript
|
178 | smb2Client.readFile('path\\to\\my\\file.txt', function(err, content) {
|
179 | if (err) throw err;
|
180 | console.log(content);
|
181 | });
|
182 | ```
|
183 |
|
184 | If no encoding is specified, then the raw buffer is returned.
|
185 |
|
186 | > `smb2Client.rename ( oldPath, newPath, [ options, ] callback )`
|
187 |
|
188 | Asynchronous `rename(2)`: rename a file.
|
189 |
|
190 | ```javascript
|
191 | smb2Client.rename(
|
192 | 'path\\to\\my\\file.txt',
|
193 | 'new\\path\\to\\my\\new-file-name.txt',
|
194 | function(err) {
|
195 | if (err) throw err;
|
196 | console.log('file has been renamed');
|
197 | }
|
198 | );
|
199 | ```
|
200 |
|
201 | Existing files are not replaced by default, you need to pass the `replace: true` option for this use case:
|
202 |
|
203 | ```javascript
|
204 | smb2Client.rename(
|
205 | 'path\\to\\my\\file.txt',
|
206 | 'path\\to\\existing\\file.txt',
|
207 | {
|
208 | replace: true
|
209 | }
|
210 | function(err) {
|
211 | if (err) throw err;
|
212 | console.log('file has been renamed');
|
213 | }
|
214 | );
|
215 | ```
|
216 |
|
217 | > `smb2Client.rmdir ( path, callback )`
|
218 |
|
219 | Asynchronous `rmdir(2)`: delete an empty directory.
|
220 |
|
221 | Example:
|
222 |
|
223 | ```javascript
|
224 | smb2Client.rmdir('path\\to\\the\\directory', function(err) {
|
225 | if (err) throw err;
|
226 | console.log('Directory deleted!');
|
227 | });
|
228 | ```
|
229 |
|
230 | > `smb2Client.unlink ( path, callback )`
|
231 |
|
232 | Asynchronous `unlink(2)`: delete a file.
|
233 |
|
234 | ```javascript
|
235 | smb2Client.unlink('path\\to\\my\\file.txt', function(err) {
|
236 | if (err) throw err;
|
237 | console.log('file has been deleted');
|
238 | });
|
239 | ```
|
240 |
|
241 | > `smb2Client.writeFile ( filename, data, [options], callback )`
|
242 |
|
243 | - `filename` String
|
244 | - `data` String | Buffer
|
245 | - `options` Object
|
246 | - `encoding` String | Null default = `'utf8'`
|
247 | - `callback` Function
|
248 |
|
249 | Asynchronously writes data to a file, replacing the file if it already exists. data can be a string or a buffer.
|
250 |
|
251 | The encoding option is ignored if data is a buffer.
|
252 |
|
253 | Example:
|
254 |
|
255 | ```javascript
|
256 | smb2Client.writeFile('path\\to\\my\\file.txt', 'Hello Node', function(err) {
|
257 | if (err) throw err;
|
258 | console.log("It's saved!");
|
259 | });
|
260 | ```
|
261 |
|
262 | > `smb2Client.truncate ( filename, length, callback )`
|
263 |
|
264 | - `filename` String
|
265 | - `length` Number
|
266 | - `callback` Function
|
267 |
|
268 | Asynchronously truncate a file to a size of precisely length bytes.
|
269 |
|
270 | Example:
|
271 |
|
272 | ```javascript
|
273 | smb2Client.truncate('path\\to\\my\\file.txt', 10, function(err) {
|
274 | if (err) throw err;
|
275 | console.log("It's truncated!");
|
276 | });
|
277 | ```
|
278 |
|
279 | ### Streams
|
280 |
|
281 | > `smb2Client.createReadStream ( fileName, [options], callback )`
|
282 |
|
283 | Returns a read stream on the file.
|
284 |
|
285 | > Unlike `fs.createReadStream`, this function is asynchronous, as we need use asynchronous smb requests to get the stream.
|
286 |
|
287 | Example:
|
288 |
|
289 | ```javascript
|
290 | smb2Client.createReadStream('path\\to\\the\\file', function(err, readStream) {
|
291 | if (err) throw err;
|
292 | var writeStream = fs.createWriteStream('localFile');
|
293 | readStream.pipe(writeStream);
|
294 | });
|
295 | ```
|
296 |
|
297 | Supported options:
|
298 |
|
299 | - `autoClose`: whether the `fd` should be closed at the end or on error, default `true`
|
300 | - `end`: offset in the file after which to stop reading, default `Infinity`
|
301 | - `fd`: if specified, the path will be ignored and this opened file will be used instead
|
302 | - `flags`: see [Node documentation](https://nodejs.org/dist/latest-v10.x/docs/api/fs.html#fs_file_system_flags), default `'r'`
|
303 | - `start`: offset in the file from which to start reading, default `0`
|
304 |
|
305 | > `smb2Client.createWriteStream ( fileName, [options], callback )`
|
306 |
|
307 | Returns a write stream on the file.
|
308 |
|
309 | > Unlike `fs.createWriteStream`, this function is asynchronous, as we need use asynchronous smb requests to get the stream.
|
310 |
|
311 | Example:
|
312 |
|
313 | ```javascript
|
314 | smb2Client.createWriteStream('path\\to\\the\\file', function(err, writeStream) {
|
315 | if (err) throw err;
|
316 | var readStream = fs.createReadStream('localFile');
|
317 | readStream.pipe(writeStream);
|
318 | });
|
319 | ```
|
320 |
|
321 | Supported options:
|
322 |
|
323 | - `autoClose`: whether the `fd` should be closed at the end or on error, default `true`
|
324 | - `fd`: if specified, the path will be ignored and this opened file will be used instead
|
325 | - `flags`: see [Node documentation](https://nodejs.org/dist/latest-v10.x/docs/api/fs.html#fs_file_system_flags), default `'wx'`
|
326 | - `start`: offset in the file from which to start writing, default `0`
|
327 |
|
328 | ### Low-level API
|
329 |
|
330 | ```javascript
|
331 | smb2Client.open('path\\to\\the\\file', 'r', function(err, fd) {
|
332 | if (err) throw err;
|
333 |
|
334 | smb2Client.read(
|
335 | fd, // file descriptor
|
336 | Buffer.alloc(10), // buffer where to store the data
|
337 | 0, // offset in the buffer
|
338 | 10, // number of bytes to read
|
339 | 0, // offset in the file
|
340 | function(err, bytesRead, buffer) {
|
341 | smb2Client.close(fd, function() {});
|
342 |
|
343 | if (err) throw cb(err);
|
344 | console.log(bytesRead, buffer);
|
345 | }
|
346 | );
|
347 | });
|
348 |
|
349 | smb2Client.open('path\\to\\the\\file', 'w', function(err, fd) {
|
350 | if (err) throw err;
|
351 |
|
352 | smb2Client.write(
|
353 | fd, // file descriptor
|
354 | Buffer.from('foo bar\n'), // data to write to the file
|
355 | 0, // offset in the buffer
|
356 | 10, // number of bytes to write
|
357 | 0, // offset in the file
|
358 | function(err, bytesWritten, buffer) {
|
359 | smb2Client.close(fd, function() {});
|
360 |
|
361 | if (err) throw cb(err);
|
362 | console.log(bytesWritten);
|
363 | }
|
364 | );
|
365 | });
|
366 | ```
|
367 |
|
368 | > This API is modeled after Node's `fs` module.
|
369 |
|
370 | > Note: be careful of `autoCloseTimeout` with this process as it is not intended to cover multiple method calls, you should set it to `0` and manually `disconnect()`.
|
371 |
|
372 | ## Contributors
|
373 |
|
374 | - [Benjamin Chelli](https://github.com/bchelli)
|
375 | - [Fabrice Marsaud](https://github.com/marsaud)
|
376 |
|
377 | ## References
|
378 |
|
379 | The[MS-SMB2]: Server Message Block (SMB) Protocol Versions 2 and 3
|
380 | Copyright (C) 2014 Microsoft
|
381 | http://msdn.microsoft.com/en-us/library/cc246482.aspx
|
382 |
|
383 | ## License
|
384 |
|
385 | (The MIT License)
|
386 |
|
387 | Copyright (c) 2013-2014 Benjamin Chelli <benjamin@chelli.net>
|
388 |
|
389 | Permission is hereby granted, free of charge, to any person obtaining
|
390 | a copy of this software and associated documentation files (the
|
391 | 'Software'), to deal in the Software without restriction, including
|
392 | without limitation the rights to use, copy, modify, merge, publish,
|
393 | distribute, sublicense, and/or sell copies of the Software, and to
|
394 | permit persons to whom the Software is furnished to do so, subject to
|
395 | the following conditions:
|
396 |
|
397 | The above copyright notice and this permission notice shall be
|
398 | included in all copies or substantial portions of the Software.
|
399 |
|
400 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
401 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
402 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
403 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
404 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
405 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
406 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|