What is the problem you are having with rclone?
I am accessing SMB file share on Windows server and rclone gives me different file list than when I list the files using for instance linux smbclient
.
I found that the issues is in go-smb2
library that Rclone is using for SMB functionality and has relation to following issue:
https://github.com/hirochachacha/go-smb2/issues/40
The author of go-smb2
library acknoledges the problem, but hesitates to fix it, because it implies breaking change in the library public API. (The library does not have access to original hostname).
I created patch based on suggestions and attempts from the issue above that fixes the problem. So I think that either somebody from Rclone community might find it useful or evetually it could be integrated into the Rclone itself somehow.
Please excuse me because the patch is quite "raw", I'm not a go coder, I just wanted to make it work. You can surely find the better way how to integrate this change :)
File go-smb2.patch
diff --git a/client.go b/client.go
index e0f7b36..f0ad2e3 100644
--- a/client.go
+++ b/client.go
@@ -30,8 +30,8 @@ type Dialer struct {
// It returns a session. It doesn't support NetBIOS transport.
// This implementation doesn't support multi-session on the same TCP connection.
// If you want to use another session, you need to prepare another TCP connection at first.
-func (d *Dialer) Dial(tcpConn net.Conn) (*Session, error) {
- return d.DialContext(context.Background(), tcpConn)
+func (d *Dialer) Dial(tcpConn net.Conn, host string) (*Session, error) {
+ return d.DialContext(context.Background(), tcpConn, host)
}
// DialContext performs negotiation and authentication using the provided context.
@@ -39,7 +39,7 @@ func (d *Dialer) Dial(tcpConn net.Conn) (*Session, error) {
// If you want to use the same context, call Session.WithContext manually.
// This implementation doesn't support multi-session on the same TCP connection.
// If you want to use another session, you need to prepare another TCP connection at first.
-func (d *Dialer) DialContext(ctx context.Context, tcpConn net.Conn) (*Session, error) {
+func (d *Dialer) DialContext(ctx context.Context, tcpConn net.Conn, host string) (*Session, error) {
if ctx == nil {
panic("nil context")
}
@@ -69,13 +69,14 @@ func (d *Dialer) DialContext(ctx context.Context, tcpConn net.Conn) (*Session, e
return nil, err
}
- return &Session{s: s, ctx: context.Background(), addr: tcpConn.RemoteAddr().String()}, nil
+ return &Session{s: s, ctx: context.Background(), host: host, addr: tcpConn.RemoteAddr().String()}, nil
}
// Session represents a SMB session.
type Session struct {
s *session
ctx context.Context
+ host string
addr string
}
@@ -83,7 +84,7 @@ func (c *Session) WithContext(ctx context.Context) *Session {
if ctx == nil {
panic("nil context")
}
- return &Session{s: c.s, ctx: ctx, addr: c.addr}
+ return &Session{s: c.s, ctx: ctx, host: c.host, addr: c.addr}
}
// Logoff invalidates the current SMB session.
@@ -99,7 +100,11 @@ func (c *Session) Mount(sharename string) (*Share, error) {
sharename = normPath(sharename)
if !strings.ContainsRune(sharename, '\\') {
- sharename = fmt.Sprintf(`\\%s\%s`, c.addr, sharename)
+ if c.host != "" {
+ sharename = fmt.Sprintf(`\\%s\%s`, c.host, sharename)
+ } else {
+ sharename = fmt.Sprintf(`\\%s\%s`, c.addr, sharename)
+ }
}
if err := validateMountPath(sharename); err != nil {
@@ -116,6 +121,9 @@ func (c *Session) Mount(sharename string) (*Share, error) {
func (c *Session) ListSharenames() ([]string, error) {
servername := c.addr
+ if c.host != "" {
+ servername = c.host
+ }
fs, err := c.Mount(fmt.Sprintf(`\\%s\IPC$`, servername))
if err != nil {
diff --git a/session.go b/session.go
index 0292f9e..5feade5 100644
--- a/session.go
+++ b/session.go
@@ -265,6 +265,8 @@ type session struct {
decrypter cipher.AEAD
// applicationKey []byte
+
+ serverName string
}
func (s *session) logoff(ctx context.Context) error {
File rclone.patch
diff --git a/backend/smb/connpool.go b/backend/smb/connpool.go
index d4bed787c..f4b45a984 100644
--- a/backend/smb/connpool.go
+++ b/backend/smb/connpool.go
@@ -40,7 +40,7 @@ func (f *Fs) dial(ctx context.Context, network, addr string) (*conn, error) {
},
}
- session, err := d.DialContext(ctx, tconn)
+ session, err := d.DialContext(ctx, tconn, addr)
if err != nil {
return nil, err
}
File Dockerfile
FROM golang
COPY *.patch /usr/src/
RUN set -o errexit \
&& mkdir -p /go/src/github.com/rclone \
&& git clone -b v1.61.1 https://github.com/rclone/rclone.git /go/src/github.com/rclone/rclone
WORKDIR /go/src/github.com/rclone/rclone/
RUN set -o errexit \
&& git apply < /usr/src/rclone.patch \
&& go get \
&& ( set -o errexit; \
cd /go/pkg/mod/github.com/hirochachacha/[email protected]; \
git apply < /usr/src/go-smb2.patch \
) \
&& CGO_ENABLED=0 \
make
RUN ./rclone version
What is your rclone version (output from rclone version
)
1.61.1
Which OS you are using and how many bits (e.g. Windows 7, 64 bit)
Ubuntu 20.04, 64bit
Which cloud storage system are you using? (e.g. Google Drive)
smb
How to use GitHub
- Please use the π reaction to show that you are affected by the same issue.
- Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
- Subscribe to receive notifications on status change and new comments.