Fix STOR of zero length files to ProFTPd with TLS
Before this change, uploading a zero length file via TLS meant that the tls.Handshake function was never called. ProFTPd quite properly refuses to accept an empty TCP connection with no TLS handshake as a zero length upload and gives the error 425 Unable to build data connection: Operation not See: https://forum.rclone.org/t/rclone-ftps-explicit-rclone-touch-empty-files-proftpd-unable-to-build-data-connection-operation-not-permitted/22522
This commit is contained in:
parent
9aae4d1511
commit
a4e9650823
25
ftp.go
25
ftp.go
@ -681,9 +681,30 @@ func (c *ServerConn) StorFrom(path string, r io.Reader, offset uint64) error {
|
|||||||
// the response and we cannot use the connection to send other commands.
|
// the response and we cannot use the connection to send other commands.
|
||||||
// So we don't check io.Copy error and we return the error from
|
// So we don't check io.Copy error and we return the error from
|
||||||
// ReadResponse so the user can see the real error
|
// ReadResponse so the user can see the real error
|
||||||
_, err = io.Copy(conn, r)
|
var n int64
|
||||||
conn.Close()
|
n, err = io.Copy(conn, r)
|
||||||
|
|
||||||
|
// If we wrote no bytes but got no error, make sure we call
|
||||||
|
// tls.Handshake on the connection as it won't get called
|
||||||
|
// unless Write() is called.
|
||||||
|
//
|
||||||
|
// ProFTP doesn't like this and returns "Unable to build data
|
||||||
|
// connection: Operation not permitted" when trying to upload
|
||||||
|
// an empty file without this.
|
||||||
|
if n == 0 && err == nil {
|
||||||
|
if do, ok := conn.(interface{ Handshake() error }); ok {
|
||||||
|
err = do.Handshake()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use io.Copy or Handshake error in preference to this one
|
||||||
|
closeErr := conn.Close()
|
||||||
|
if err == nil {
|
||||||
|
err = closeErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the response and use this error in preference to
|
||||||
|
// previous errors
|
||||||
_, _, respErr := c.conn.ReadResponse(StatusClosingDataConnection)
|
_, _, respErr := c.conn.ReadResponse(StatusClosingDataConnection)
|
||||||
if respErr != nil {
|
if respErr != nil {
|
||||||
err = respErr
|
err = respErr
|
||||||
|
Loading…
Reference in New Issue
Block a user