feat(fs): remove JS based SMB handler
It's not well tested nor maintained.
This commit is contained in:
parent
75a9799e96
commit
b50e95802c
@ -24,7 +24,6 @@
|
|||||||
"@aws-sdk/lib-storage": "^3.54.0",
|
"@aws-sdk/lib-storage": "^3.54.0",
|
||||||
"@aws-sdk/middleware-apply-body-checksum": "^3.58.0",
|
"@aws-sdk/middleware-apply-body-checksum": "^3.58.0",
|
||||||
"@aws-sdk/node-http-handler": "^3.54.0",
|
"@aws-sdk/node-http-handler": "^3.54.0",
|
||||||
"@marsaud/smb2": "^0.18.0",
|
|
||||||
"@sindresorhus/df": "^3.1.1",
|
"@sindresorhus/df": "^3.1.1",
|
||||||
"@vates/async-each": "^1.0.0",
|
"@vates/async-each": "^1.0.0",
|
||||||
"@vates/coalesce-calls": "^0.1.0",
|
"@vates/coalesce-calls": "^0.1.0",
|
||||||
|
@ -5,7 +5,6 @@ import RemoteHandlerLocal from './local'
|
|||||||
import RemoteHandlerNfs from './nfs'
|
import RemoteHandlerNfs from './nfs'
|
||||||
import RemoteHandlerS3 from './s3'
|
import RemoteHandlerS3 from './s3'
|
||||||
import RemoteHandlerSmb from './smb'
|
import RemoteHandlerSmb from './smb'
|
||||||
import RemoteHandlerSmbMount from './smb-mount'
|
|
||||||
|
|
||||||
const HANDLERS = {
|
const HANDLERS = {
|
||||||
file: RemoteHandlerLocal,
|
file: RemoteHandlerLocal,
|
||||||
@ -15,10 +14,8 @@ const HANDLERS = {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
execa.sync('mount.cifs', ['-V'])
|
execa.sync('mount.cifs', ['-V'])
|
||||||
HANDLERS.smb = RemoteHandlerSmbMount
|
|
||||||
} catch (_) {
|
|
||||||
HANDLERS.smb = RemoteHandlerSmb
|
HANDLERS.smb = RemoteHandlerSmb
|
||||||
}
|
} catch (_) {}
|
||||||
|
|
||||||
export const getHandler = (remote, ...rest) => {
|
export const getHandler = (remote, ...rest) => {
|
||||||
const Handler = HANDLERS[parse(remote.url).type]
|
const Handler = HANDLERS[parse(remote.url).type]
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
import { parse } from 'xo-remote-parser'
|
|
||||||
|
|
||||||
import MountHandler from './_mount'
|
|
||||||
import { normalize } from './path'
|
|
||||||
|
|
||||||
export default class SmbMountHandler extends MountHandler {
|
|
||||||
constructor(remote, opts) {
|
|
||||||
const { domain = 'WORKGROUP', host, password, path, username } = parse(remote.url)
|
|
||||||
super(remote, opts, {
|
|
||||||
type: 'cifs',
|
|
||||||
device: '//' + host + normalize(path),
|
|
||||||
options: `domain=${domain}`,
|
|
||||||
env: {
|
|
||||||
USER: username,
|
|
||||||
PASSWD: password,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
get type() {
|
|
||||||
return 'smb'
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,163 +1,23 @@
|
|||||||
import Smb2 from '@marsaud/smb2'
|
import { parse } from 'xo-remote-parser'
|
||||||
|
|
||||||
import RemoteHandlerAbstract from './abstract'
|
import MountHandler from './_mount'
|
||||||
|
import { normalize } from './path'
|
||||||
|
|
||||||
// Normalize the error code for file not found.
|
export default class SmbHandler extends MountHandler {
|
||||||
const wrapError = (error, code) => ({
|
|
||||||
__proto__: error,
|
|
||||||
cause: error,
|
|
||||||
code,
|
|
||||||
})
|
|
||||||
const normalizeError = (error, shouldBeDirectory) => {
|
|
||||||
const { code } = error
|
|
||||||
|
|
||||||
throw code === 'STATUS_DIRECTORY_NOT_EMPTY'
|
|
||||||
? wrapError(error, 'ENOTEMPTY')
|
|
||||||
: code === 'STATUS_FILE_IS_A_DIRECTORY'
|
|
||||||
? wrapError(error, 'EISDIR')
|
|
||||||
: code === 'STATUS_NOT_A_DIRECTORY'
|
|
||||||
? wrapError(error, 'ENOTDIR')
|
|
||||||
: code === 'STATUS_OBJECT_NAME_NOT_FOUND' || code === 'STATUS_OBJECT_PATH_NOT_FOUND'
|
|
||||||
? wrapError(error, 'ENOENT')
|
|
||||||
: code === 'STATUS_OBJECT_NAME_COLLISION'
|
|
||||||
? wrapError(error, 'EEXIST')
|
|
||||||
: code === 'STATUS_NOT_SUPPORTED' || code === 'STATUS_INVALID_PARAMETER'
|
|
||||||
? wrapError(error, shouldBeDirectory ? 'ENOTDIR' : 'EISDIR')
|
|
||||||
: error
|
|
||||||
}
|
|
||||||
const normalizeDirError = error => normalizeError(error, true)
|
|
||||||
|
|
||||||
export default class SmbHandler extends RemoteHandlerAbstract {
|
|
||||||
constructor(remote, opts) {
|
constructor(remote, opts) {
|
||||||
super(remote, opts)
|
const { domain = 'WORKGROUP', host, password, path, username } = parse(remote.url)
|
||||||
|
super(remote, opts, {
|
||||||
// defined in _sync()
|
type: 'cifs',
|
||||||
this._client = undefined
|
device: '//' + host + normalize(path),
|
||||||
|
options: `domain=${domain}`,
|
||||||
const prefix = this._remote.path
|
env: {
|
||||||
this._prefix = prefix !== '' ? prefix + '\\' : prefix
|
USER: username,
|
||||||
|
PASSWD: password,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
get type() {
|
get type() {
|
||||||
return 'smb'
|
return 'smb'
|
||||||
}
|
}
|
||||||
|
|
||||||
_getFilePath(file) {
|
|
||||||
return this._prefix + (typeof file === 'string' ? file : file.path).slice(1).replace(/\//g, '\\')
|
|
||||||
}
|
|
||||||
|
|
||||||
_dirname(file) {
|
|
||||||
const parts = file.split('\\')
|
|
||||||
parts.pop()
|
|
||||||
return parts.join('\\')
|
|
||||||
}
|
|
||||||
|
|
||||||
_closeFile(file) {
|
|
||||||
return this._client.close(file).catch(normalizeError)
|
|
||||||
}
|
|
||||||
|
|
||||||
_createReadStream(file, options) {
|
|
||||||
if (typeof file === 'string') {
|
|
||||||
file = this._getFilePath(file)
|
|
||||||
} else {
|
|
||||||
options = { autoClose: false, ...options, fd: file.fd }
|
|
||||||
file = ''
|
|
||||||
}
|
|
||||||
return this._client.createReadStream(file, options).catch(normalizeError)
|
|
||||||
}
|
|
||||||
|
|
||||||
_createWriteStream(file, options) {
|
|
||||||
if (typeof file === 'string') {
|
|
||||||
file = this._getFilePath(file)
|
|
||||||
} else {
|
|
||||||
options = { autoClose: false, ...options, fd: file.fd }
|
|
||||||
file = ''
|
|
||||||
}
|
|
||||||
return this._client.createWriteStream(file, options).catch(normalizeError)
|
|
||||||
}
|
|
||||||
|
|
||||||
_forget() {
|
|
||||||
const client = this._client
|
|
||||||
this._client = undefined
|
|
||||||
return client.disconnect()
|
|
||||||
}
|
|
||||||
|
|
||||||
_getSize(file) {
|
|
||||||
return this._client.getSize(this._getFilePath(file)).catch(normalizeError)
|
|
||||||
}
|
|
||||||
|
|
||||||
_list(dir) {
|
|
||||||
return this._client.readdir(this._getFilePath(dir)).catch(normalizeDirError)
|
|
||||||
}
|
|
||||||
|
|
||||||
_mkdir(dir, { mode }) {
|
|
||||||
return this._client.mkdir(this._getFilePath(dir), mode).catch(normalizeDirError)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add flags
|
|
||||||
_openFile(path, flags) {
|
|
||||||
return this._client.open(this._getFilePath(path), flags).catch(normalizeError)
|
|
||||||
}
|
|
||||||
|
|
||||||
async _read(file, buffer, position) {
|
|
||||||
const client = this._client
|
|
||||||
const needsClose = typeof file === 'string'
|
|
||||||
file = needsClose ? await client.open(this._getFilePath(file)) : file.fd
|
|
||||||
try {
|
|
||||||
return await client.read(file, buffer, 0, buffer.length, position)
|
|
||||||
} catch (error) {
|
|
||||||
normalizeError(error)
|
|
||||||
} finally {
|
|
||||||
if (needsClose) {
|
|
||||||
await client.close(file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_readFile(file, options) {
|
|
||||||
return this._client.readFile(this._getFilePath(file), options).catch(normalizeError)
|
|
||||||
}
|
|
||||||
|
|
||||||
_rename(oldPath, newPath) {
|
|
||||||
return this._client
|
|
||||||
.rename(this._getFilePath(oldPath), this._getFilePath(newPath), {
|
|
||||||
replace: true,
|
|
||||||
})
|
|
||||||
.catch(normalizeError)
|
|
||||||
}
|
|
||||||
|
|
||||||
_rmdir(dir) {
|
|
||||||
return this._client.rmdir(this._getFilePath(dir)).catch(normalizeDirError)
|
|
||||||
}
|
|
||||||
|
|
||||||
_sync() {
|
|
||||||
const remote = this._remote
|
|
||||||
|
|
||||||
this._client = new Smb2({
|
|
||||||
share: `\\\\${remote.host}`,
|
|
||||||
domain: remote.domain,
|
|
||||||
username: remote.username,
|
|
||||||
password: remote.password,
|
|
||||||
autoCloseTimeout: 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Check access (smb2 does not expose connect in public so far...)
|
|
||||||
return this.list('.')
|
|
||||||
}
|
|
||||||
|
|
||||||
_truncate(file, len) {
|
|
||||||
return this._client.truncate(this._getFilePath(file), len).catch(normalizeError)
|
|
||||||
}
|
|
||||||
|
|
||||||
_unlink(file) {
|
|
||||||
return this._client.unlink(this._getFilePath(file)).catch(normalizeError)
|
|
||||||
}
|
|
||||||
|
|
||||||
_writeFd(file, buffer, position) {
|
|
||||||
return this._client.write(file.fd, buffer, 0, buffer.length, position)
|
|
||||||
}
|
|
||||||
|
|
||||||
_writeFile(file, data, options) {
|
|
||||||
return this._client.writeFile(this._getFilePath(file), data, options).catch(normalizeError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
13
yarn.lock
13
yarn.lock
@ -2365,14 +2365,6 @@
|
|||||||
semver "^7.3.5"
|
semver "^7.3.5"
|
||||||
tar "^6.1.11"
|
tar "^6.1.11"
|
||||||
|
|
||||||
"@marsaud/smb2@^0.18.0":
|
|
||||||
version "0.18.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@marsaud/smb2/-/smb2-0.18.0.tgz#c5c859c2d4ab8ae16f195208bc71561f0a9b92ba"
|
|
||||||
integrity sha512-DxOVZCX0uDe3S9QQqXk6mnnQ7nEaqI5gPwuNQ7dDQCXY00Qp0CIa5N1LNYKCcW1DYTJceOvRvNujL5hgnQmqOA==
|
|
||||||
dependencies:
|
|
||||||
ntlm "~0.1.1"
|
|
||||||
readable-stream "^3.0.6"
|
|
||||||
|
|
||||||
"@mrmlnc/readdir-enhanced@^2.2.1":
|
"@mrmlnc/readdir-enhanced@^2.2.1":
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
|
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
|
||||||
@ -13302,11 +13294,6 @@ nth-check@^2.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
boolbase "^1.0.0"
|
boolbase "^1.0.0"
|
||||||
|
|
||||||
ntlm@~0.1.1:
|
|
||||||
version "0.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/ntlm/-/ntlm-0.1.3.tgz#3b814ebc530a1e6cd712dcf0cf590155931195c1"
|
|
||||||
integrity sha512-pPlHxhAegZP4QAaOYd51vRd6VXTGfF7VLKJwuwN0iEB1aIi3SnqXYuS/bH/6wWBOq+Ehdil49mHm1Nseon085w==
|
|
||||||
|
|
||||||
num2fraction@^1.2.2:
|
num2fraction@^1.2.2:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
||||||
|
Loading…
Reference in New Issue
Block a user