mirror of https://github.com/pkg/sftp.git
DO NOT close the CopyStderrTo writer
This commit is contained in:
parent
f1b135a6f5
commit
8a0fc6568b
24
client.go
24
client.go
|
@ -159,7 +159,10 @@ func UseFstat(value bool) ClientOption {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyStderrTo specifies a writer to which the standard error of the remote sftp-server command should be written.
|
// CopyStderrTo specifies a writer to which the standard error of the remote sftp-server command should be written.
|
||||||
func CopyStderrTo(wr io.WriteCloser) ClientOption {
|
//
|
||||||
|
// The writer passed in will not be automatically closed.
|
||||||
|
// It is the responsibility of the caller to coordinate closure of any writers.
|
||||||
|
func CopyStderrTo(wr io.Writer) ClientOption {
|
||||||
return func(c *Client) error {
|
return func(c *Client) error {
|
||||||
c.stderrTo = wr
|
c.stderrTo = wr
|
||||||
return nil
|
return nil
|
||||||
|
@ -174,7 +177,7 @@ func CopyStderrTo(wr io.WriteCloser) ClientOption {
|
||||||
type Client struct {
|
type Client struct {
|
||||||
clientConn
|
clientConn
|
||||||
|
|
||||||
stderrTo io.WriteCloser
|
stderrTo io.Writer
|
||||||
|
|
||||||
ext map[string]string // Extensions (name -> data).
|
ext map[string]string // Extensions (name -> data).
|
||||||
|
|
||||||
|
@ -214,17 +217,17 @@ func NewClient(conn *ssh.Client, opts ...ClientOption) (*Client, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return newClientPipe(pr, pw, perr, s.Wait, opts...)
|
return newClientPipe(pr, perr, pw, s.Wait, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClientPipe creates a new SFTP client given a Reader and a WriteCloser.
|
// NewClientPipe creates a new SFTP client given a Reader and a WriteCloser.
|
||||||
// This can be used for connecting to an SFTP server over TCP/TLS or by using
|
// This can be used for connecting to an SFTP server over TCP/TLS or by using
|
||||||
// the system's ssh client program (e.g. via exec.Command).
|
// the system's ssh client program (e.g. via exec.Command).
|
||||||
func NewClientPipe(rd io.Reader, wr io.WriteCloser, opts ...ClientOption) (*Client, error) {
|
func NewClientPipe(rd io.Reader, wr io.WriteCloser, opts ...ClientOption) (*Client, error) {
|
||||||
return newClientPipe(rd, wr, nil, nil, opts...)
|
return newClientPipe(rd, nil, wr, nil, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newClientPipe(rd io.Reader, wr io.WriteCloser, stderr io.Reader, wait func() error, opts ...ClientOption) (*Client, error) {
|
func newClientPipe(rd, stderr io.Reader, wr io.WriteCloser, wait func() error, opts ...ClientOption) (*Client, error) {
|
||||||
c := &Client{
|
c := &Client{
|
||||||
clientConn: clientConn{
|
clientConn: clientConn{
|
||||||
conn: conn{
|
conn: conn{
|
||||||
|
@ -256,13 +259,10 @@ func newClientPipe(rd io.Reader, wr io.WriteCloser, stderr io.Reader, wait func(
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
// DO NOT close the writer!
|
||||||
if closer, ok := wr.(io.Closer); ok {
|
// Programs may pass in `os.Stderr` to write the remote stderr to,
|
||||||
if err := closer.Close(); err != nil {
|
// and the program may continue after disconnect by reconnecting.
|
||||||
debug("error closing stderrTo: %v", err)
|
// But if we've closed their stderr, then we just messed everything up.
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if _, err := io.Copy(wr, stderr); err != nil {
|
if _, err := io.Copy(wr, stderr); err != nil {
|
||||||
debug("error copying stderr: %v", err)
|
debug("error copying stderr: %v", err)
|
||||||
|
|
Loading…
Reference in New Issue