sftp: fail soft with a debug on hash failure #1474

If md5sum/sha1sum fails we debug what it outputed on stderr and return
an empty hash indicating we didn't have a hash, rather than
hash.ErrUnsupported indicating that we don't support this hash type.

This fixes lots of ERROR messages for sftp and synology NAS which,
while it supports md5sum the SFTP paths and the SSH paths are
different so md5sum doesn't work.

We also stop disabling md5sum/sha1sum on errors since typically Hashes
is only checked at the start of a sync run and isn't expected to
change dynamically.
This commit is contained in:
Nick Craig-Wood 2018-04-19 09:45:46 +01:00
parent b3c6f5f4b8
commit 870c58f7f8

View file

@ -5,6 +5,7 @@
package sftp package sftp
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"io" "io"
@ -733,40 +734,44 @@ func (o *Object) Remote() string {
// Hash returns the selected checksum of the file // Hash returns the selected checksum of the file
// If no checksum is available it returns "" // If no checksum is available it returns ""
func (o *Object) Hash(r hash.Type) (string, error) { func (o *Object) Hash(r hash.Type) (string, error) {
if r == hash.MD5 && o.md5sum != nil { var hashCmd string
if r == hash.MD5 {
if o.md5sum != nil {
return *o.md5sum, nil return *o.md5sum, nil
} else if r == hash.SHA1 && o.sha1sum != nil { }
hashCmd = "md5sum"
} else if r == hash.SHA1 {
if o.sha1sum != nil {
return *o.sha1sum, nil return *o.sha1sum, nil
} }
hashCmd = "sha1sum"
} else {
return "", hash.ErrUnsupported
}
c, err := o.fs.getSftpConnection() c, err := o.fs.getSftpConnection()
if err != nil { if err != nil {
return "", errors.Wrap(err, "Hash") return "", errors.Wrap(err, "Hash get SFTP connection")
} }
session, err := c.sshClient.NewSession() session, err := c.sshClient.NewSession()
o.fs.putSftpConnection(&c, err) o.fs.putSftpConnection(&c, err)
if err != nil { if err != nil {
o.fs.cachedHashes = nil // Something has changed on the remote system return "", errors.Wrap(err, "Hash put SFTP connection")
return "", hash.ErrUnsupported
} }
err = hash.ErrUnsupported var stdout, stderr bytes.Buffer
var outputBytes []byte session.Stdout = &stdout
session.Stderr = &stderr
escapedPath := shellEscape(o.path()) escapedPath := shellEscape(o.path())
if r == hash.MD5 { err = session.Run(hashCmd + " " + escapedPath)
outputBytes, err = session.Output("md5sum " + escapedPath)
} else if r == hash.SHA1 {
outputBytes, err = session.Output("sha1sum " + escapedPath)
}
if err != nil { if err != nil {
o.fs.cachedHashes = nil // Something has changed on the remote system
_ = session.Close() _ = session.Close()
return "", hash.ErrUnsupported fs.Debugf(o, "Failed to calculate %v hash: %v (%s)", r, err, bytes.TrimSpace(stderr.Bytes()))
return "", nil
} }
_ = session.Close() _ = session.Close()
str := parseHash(outputBytes) str := parseHash(stdout.Bytes())
if r == hash.MD5 { if r == hash.MD5 {
o.md5sum = &str o.md5sum = &str
} else if r == hash.SHA1 { } else if r == hash.SHA1 {