|
@@ -47,8 +47,9 @@ type Entry struct {
|
|
|
|
|
|
|
|
// Response represents a data-connection
|
|
// Response represents a data-connection
|
|
|
type Response struct {
|
|
type Response struct {
|
|
|
- conn net.Conn
|
|
|
|
|
- c *ServerConn
|
|
|
|
|
|
|
+ conn net.Conn
|
|
|
|
|
+ c *ServerConn
|
|
|
|
|
+ closed bool
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Connect is an alias to Dial, for backward compatibility
|
|
// Connect is an alias to Dial, for backward compatibility
|
|
@@ -337,7 +338,7 @@ func (c *ServerConn) NameList(path string) (entries []string, err error) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- r := &Response{conn, c}
|
|
|
|
|
|
|
+ r := &Response{conn: conn, c: c}
|
|
|
defer r.Close()
|
|
defer r.Close()
|
|
|
|
|
|
|
|
scanner := bufio.NewScanner(r)
|
|
scanner := bufio.NewScanner(r)
|
|
@@ -368,7 +369,7 @@ func (c *ServerConn) List(path string) (entries []*Entry, err error) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- r := &Response{conn, c}
|
|
|
|
|
|
|
+ r := &Response{conn: conn, c: c}
|
|
|
defer r.Close()
|
|
defer r.Close()
|
|
|
|
|
|
|
|
scanner := bufio.NewScanner(r)
|
|
scanner := bufio.NewScanner(r)
|
|
@@ -445,7 +446,7 @@ func (c *ServerConn) RetrFrom(path string, offset uint64) (*Response, error) {
|
|
|
return nil, err
|
|
return nil, err
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return &Response{conn, c}, nil
|
|
|
|
|
|
|
+ return &Response{conn: conn, c: c}, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Stor issues a STOR FTP command to store a file to the remote FTP server.
|
|
// Stor issues a STOR FTP command to store a file to the remote FTP server.
|
|
@@ -536,12 +537,17 @@ func (r *Response) Read(buf []byte) (int, error) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Close implements the io.Closer interface on a FTP data connection.
|
|
// Close implements the io.Closer interface on a FTP data connection.
|
|
|
|
|
+// After the first call, Close will do nothing and return nil.
|
|
|
func (r *Response) Close() error {
|
|
func (r *Response) Close() error {
|
|
|
|
|
+ if r.closed {
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
err := r.conn.Close()
|
|
err := r.conn.Close()
|
|
|
_, _, err2 := r.c.conn.ReadResponse(StatusClosingDataConnection)
|
|
_, _, err2 := r.c.conn.ReadResponse(StatusClosingDataConnection)
|
|
|
if err2 != nil {
|
|
if err2 != nil {
|
|
|
err = err2
|
|
err = err2
|
|
|
}
|
|
}
|
|
|
|
|
+ r.closed = true
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
|
|
|
|