From 08a1e2e380b166d44cd2129211bacef3eb5c8bc9 Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Thu, 30 Jul 2020 14:52:42 +0200 Subject: [PATCH 1/2] try to read the server response after a failed upload if the upload failed we still need to try to read the server response otherwise if the failure is not due to a connection problem, for example the server denied the upload for quota limits, we miss the response and we cannot use the connection to send other commands Here is what happen before this patch: C->S STOR test_file1.dat S->C 150 Using transfer connection S->C 550 Could not transfer file: denying write due to space limit the client does not read the above 550 response and send the next command, so the response for the STOR response will be readed as response for the next command --- ftp.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ftp.go b/ftp.go index f8b9153..3bf0f1f 100644 --- a/ftp.go +++ b/ftp.go @@ -650,6 +650,11 @@ func (c *ServerConn) StorFrom(path string, r io.Reader, offset uint64) error { _, err = io.Copy(conn, r) conn.Close() if err != nil { + // if the upload failed we still need to try to read the server + // response otherwise if the failure is not due to a connection problem, + // for example the server denied the upload for quota limits, we miss + // the response and we cannot use the connection to send other commands + c.conn.ReadResponse(StatusClosingDataConnection) return err } @@ -671,6 +676,8 @@ func (c *ServerConn) Append(path string, r io.Reader) error { _, err = io.Copy(conn, r) conn.Close() if err != nil { + // see the comment for StorFrom above + c.conn.ReadResponse(StatusClosingDataConnection) return err } From 4a68979b896a741e26720e7e838ce767bac2a599 Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Thu, 6 Aug 2020 16:41:36 +0200 Subject: [PATCH 2/2] always return the ReadResponse error after an upload --- ftp.go | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/ftp.go b/ftp.go index 3bf0f1f..b223567 100644 --- a/ftp.go +++ b/ftp.go @@ -647,16 +647,14 @@ func (c *ServerConn) StorFrom(path string, r io.Reader, offset uint64) error { return err } - _, err = io.Copy(conn, r) + // if the upload fails we still need to try to read the server + // response otherwise if the failure is not due to a connection problem, + // for example the server denied the upload for quota limits, we miss + // 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 + // ReadResponse so the user can see the real error + io.Copy(conn, r) conn.Close() - if err != nil { - // if the upload failed we still need to try to read the server - // response otherwise if the failure is not due to a connection problem, - // for example the server denied the upload for quota limits, we miss - // the response and we cannot use the connection to send other commands - c.conn.ReadResponse(StatusClosingDataConnection) - return err - } _, _, err = c.conn.ReadResponse(StatusClosingDataConnection) return err @@ -673,13 +671,9 @@ func (c *ServerConn) Append(path string, r io.Reader) error { return err } - _, err = io.Copy(conn, r) + // see the comment for StorFrom above + io.Copy(conn, r) conn.Close() - if err != nil { - // see the comment for StorFrom above - c.conn.ReadResponse(StatusClosingDataConnection) - return err - } _, _, err = c.conn.ReadResponse(StatusClosingDataConnection) return err