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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user