mirror of https://github.com/pkg/sftp.git
sendPacket with context
This commit is contained in:
parent
273341d347
commit
3aa53a572f
51
client.go
51
client.go
|
@ -333,7 +333,7 @@ func (c *Client) ReadDir(p string) ([]os.FileInfo, error) {
|
||||||
// The passed context can be used to cancel the operation
|
// The passed context can be used to cancel the operation
|
||||||
// returning all entries listed up to the cancellation.
|
// returning all entries listed up to the cancellation.
|
||||||
func (c *Client) ReadDirContext(ctx context.Context, p string) ([]os.FileInfo, error) {
|
func (c *Client) ReadDirContext(ctx context.Context, p string) ([]os.FileInfo, error) {
|
||||||
handle, err := c.opendir(p)
|
handle, err := c.opendir(ctx, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -341,11 +341,8 @@ func (c *Client) ReadDirContext(ctx context.Context, p string) ([]os.FileInfo, e
|
||||||
var entries []os.FileInfo
|
var entries []os.FileInfo
|
||||||
var done = false
|
var done = false
|
||||||
for !done {
|
for !done {
|
||||||
if err = ctx.Err(); err != nil {
|
|
||||||
return entries, err
|
|
||||||
}
|
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err1 := c.sendPacket(nil, &sshFxpReaddirPacket{
|
typ, data, err1 := c.sendPacket(ctx, nil, &sshFxpReaddirPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Handle: handle,
|
Handle: handle,
|
||||||
})
|
})
|
||||||
|
@ -386,9 +383,9 @@ func (c *Client) ReadDirContext(ctx context.Context, p string) ([]os.FileInfo, e
|
||||||
return entries, err
|
return entries, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) opendir(path string) (string, error) {
|
func (c *Client) opendir(ctx context.Context, path string) (string, error) {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpOpendirPacket{
|
typ, data, err := c.sendPacket(ctx, nil, &sshFxpOpendirPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Path: path,
|
Path: path,
|
||||||
})
|
})
|
||||||
|
@ -424,7 +421,7 @@ func (c *Client) Stat(p string) (os.FileInfo, error) {
|
||||||
// If 'p' is a symbolic link, the returned FileInfo structure describes the symbolic link.
|
// If 'p' is a symbolic link, the returned FileInfo structure describes the symbolic link.
|
||||||
func (c *Client) Lstat(p string) (os.FileInfo, error) {
|
func (c *Client) Lstat(p string) (os.FileInfo, error) {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpLstatPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpLstatPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Path: p,
|
Path: p,
|
||||||
})
|
})
|
||||||
|
@ -449,7 +446,7 @@ func (c *Client) Lstat(p string) (os.FileInfo, error) {
|
||||||
// ReadLink reads the target of a symbolic link.
|
// ReadLink reads the target of a symbolic link.
|
||||||
func (c *Client) ReadLink(p string) (string, error) {
|
func (c *Client) ReadLink(p string) (string, error) {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpReadlinkPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpReadlinkPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Path: p,
|
Path: p,
|
||||||
})
|
})
|
||||||
|
@ -478,7 +475,7 @@ func (c *Client) ReadLink(p string) (string, error) {
|
||||||
// Link creates a hard link at 'newname', pointing at the same inode as 'oldname'
|
// Link creates a hard link at 'newname', pointing at the same inode as 'oldname'
|
||||||
func (c *Client) Link(oldname, newname string) error {
|
func (c *Client) Link(oldname, newname string) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpHardlinkPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpHardlinkPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Oldpath: oldname,
|
Oldpath: oldname,
|
||||||
Newpath: newname,
|
Newpath: newname,
|
||||||
|
@ -497,7 +494,7 @@ func (c *Client) Link(oldname, newname string) error {
|
||||||
// Symlink creates a symbolic link at 'newname', pointing at target 'oldname'
|
// Symlink creates a symbolic link at 'newname', pointing at target 'oldname'
|
||||||
func (c *Client) Symlink(oldname, newname string) error {
|
func (c *Client) Symlink(oldname, newname string) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpSymlinkPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpSymlinkPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Linkpath: newname,
|
Linkpath: newname,
|
||||||
Targetpath: oldname,
|
Targetpath: oldname,
|
||||||
|
@ -515,7 +512,7 @@ func (c *Client) Symlink(oldname, newname string) error {
|
||||||
|
|
||||||
func (c *Client) setfstat(handle string, flags uint32, attrs interface{}) error {
|
func (c *Client) setfstat(handle string, flags uint32, attrs interface{}) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpFsetstatPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpFsetstatPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Handle: handle,
|
Handle: handle,
|
||||||
Flags: flags,
|
Flags: flags,
|
||||||
|
@ -535,7 +532,7 @@ func (c *Client) setfstat(handle string, flags uint32, attrs interface{}) error
|
||||||
// setstat is a convience wrapper to allow for changing of various parts of the file descriptor.
|
// setstat is a convience wrapper to allow for changing of various parts of the file descriptor.
|
||||||
func (c *Client) setstat(path string, flags uint32, attrs interface{}) error {
|
func (c *Client) setstat(path string, flags uint32, attrs interface{}) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpSetstatPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpSetstatPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Path: path,
|
Path: path,
|
||||||
Flags: flags,
|
Flags: flags,
|
||||||
|
@ -605,7 +602,7 @@ func (c *Client) OpenFile(path string, f int) (*File, error) {
|
||||||
|
|
||||||
func (c *Client) open(path string, pflags uint32) (*File, error) {
|
func (c *Client) open(path string, pflags uint32) (*File, error) {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpOpenPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpOpenPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Path: path,
|
Path: path,
|
||||||
Pflags: pflags,
|
Pflags: pflags,
|
||||||
|
@ -633,7 +630,7 @@ func (c *Client) open(path string, pflags uint32) (*File, error) {
|
||||||
// immediately after this request has been sent.
|
// immediately after this request has been sent.
|
||||||
func (c *Client) close(handle string) error {
|
func (c *Client) close(handle string) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpClosePacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpClosePacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Handle: handle,
|
Handle: handle,
|
||||||
})
|
})
|
||||||
|
@ -650,7 +647,7 @@ func (c *Client) close(handle string) error {
|
||||||
|
|
||||||
func (c *Client) stat(path string) (*FileStat, error) {
|
func (c *Client) stat(path string) (*FileStat, error) {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpStatPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpStatPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Path: path,
|
Path: path,
|
||||||
})
|
})
|
||||||
|
@ -674,7 +671,7 @@ func (c *Client) stat(path string) (*FileStat, error) {
|
||||||
|
|
||||||
func (c *Client) fstat(handle string) (*FileStat, error) {
|
func (c *Client) fstat(handle string) (*FileStat, error) {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpFstatPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpFstatPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Handle: handle,
|
Handle: handle,
|
||||||
})
|
})
|
||||||
|
@ -703,7 +700,7 @@ func (c *Client) fstat(handle string) (*FileStat, error) {
|
||||||
func (c *Client) StatVFS(path string) (*StatVFS, error) {
|
func (c *Client) StatVFS(path string) (*StatVFS, error) {
|
||||||
// send the StatVFS packet to the server
|
// send the StatVFS packet to the server
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpStatvfsPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpStatvfsPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Path: path,
|
Path: path,
|
||||||
})
|
})
|
||||||
|
@ -758,7 +755,7 @@ func (c *Client) Remove(path string) error {
|
||||||
|
|
||||||
func (c *Client) removeFile(path string) error {
|
func (c *Client) removeFile(path string) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpRemovePacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpRemovePacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Filename: path,
|
Filename: path,
|
||||||
})
|
})
|
||||||
|
@ -776,7 +773,7 @@ func (c *Client) removeFile(path string) error {
|
||||||
// RemoveDirectory removes a directory path.
|
// RemoveDirectory removes a directory path.
|
||||||
func (c *Client) RemoveDirectory(path string) error {
|
func (c *Client) RemoveDirectory(path string) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpRmdirPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpRmdirPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Path: path,
|
Path: path,
|
||||||
})
|
})
|
||||||
|
@ -794,7 +791,7 @@ func (c *Client) RemoveDirectory(path string) error {
|
||||||
// Rename renames a file.
|
// Rename renames a file.
|
||||||
func (c *Client) Rename(oldname, newname string) error {
|
func (c *Client) Rename(oldname, newname string) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpRenamePacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpRenamePacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Oldpath: oldname,
|
Oldpath: oldname,
|
||||||
Newpath: newname,
|
Newpath: newname,
|
||||||
|
@ -814,7 +811,7 @@ func (c *Client) Rename(oldname, newname string) error {
|
||||||
// which will replace newname if it already exists.
|
// which will replace newname if it already exists.
|
||||||
func (c *Client) PosixRename(oldname, newname string) error {
|
func (c *Client) PosixRename(oldname, newname string) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpPosixRenamePacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpPosixRenamePacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Oldpath: oldname,
|
Oldpath: oldname,
|
||||||
Newpath: newname,
|
Newpath: newname,
|
||||||
|
@ -836,7 +833,7 @@ func (c *Client) PosixRename(oldname, newname string) error {
|
||||||
// or relative pathnames without a leading slash into absolute paths.
|
// or relative pathnames without a leading slash into absolute paths.
|
||||||
func (c *Client) RealPath(path string) (string, error) {
|
func (c *Client) RealPath(path string) (string, error) {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpRealpathPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpRealpathPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Path: path,
|
Path: path,
|
||||||
})
|
})
|
||||||
|
@ -873,7 +870,7 @@ func (c *Client) Getwd() (string, error) {
|
||||||
// parent folder does not exist (the method cannot create complete paths).
|
// parent folder does not exist (the method cannot create complete paths).
|
||||||
func (c *Client) Mkdir(path string) error {
|
func (c *Client) Mkdir(path string) error {
|
||||||
id := c.nextID()
|
id := c.nextID()
|
||||||
typ, data, err := c.sendPacket(nil, &sshFxpMkdirPacket{
|
typ, data, err := c.sendPacket(context.Background(), nil, &sshFxpMkdirPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Path: path,
|
Path: path,
|
||||||
})
|
})
|
||||||
|
@ -1019,7 +1016,7 @@ func (f *File) Read(b []byte) (int, error) {
|
||||||
func (f *File) readChunkAt(ch chan result, b []byte, off int64) (n int, err error) {
|
func (f *File) readChunkAt(ch chan result, b []byte, off int64) (n int, err error) {
|
||||||
for err == nil && n < len(b) {
|
for err == nil && n < len(b) {
|
||||||
id := f.c.nextID()
|
id := f.c.nextID()
|
||||||
typ, data, err := f.c.sendPacket(ch, &sshFxpReadPacket{
|
typ, data, err := f.c.sendPacket(context.Background(), ch, &sshFxpReadPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Handle: f.handle,
|
Handle: f.handle,
|
||||||
Offset: uint64(off) + uint64(n),
|
Offset: uint64(off) + uint64(n),
|
||||||
|
@ -1487,7 +1484,7 @@ func (f *File) Write(b []byte) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) writeChunkAt(ch chan result, b []byte, off int64) (int, error) {
|
func (f *File) writeChunkAt(ch chan result, b []byte, off int64) (int, error) {
|
||||||
typ, data, err := f.c.sendPacket(ch, &sshFxpWritePacket{
|
typ, data, err := f.c.sendPacket(context.Background(), ch, &sshFxpWritePacket{
|
||||||
ID: f.c.nextID(),
|
ID: f.c.nextID(),
|
||||||
Handle: f.handle,
|
Handle: f.handle,
|
||||||
Offset: uint64(off),
|
Offset: uint64(off),
|
||||||
|
@ -1945,7 +1942,7 @@ func (f *File) Chmod(mode os.FileMode) error {
|
||||||
// Sync requires the server to support the fsync@openssh.com extension.
|
// Sync requires the server to support the fsync@openssh.com extension.
|
||||||
func (f *File) Sync() error {
|
func (f *File) Sync() error {
|
||||||
id := f.c.nextID()
|
id := f.c.nextID()
|
||||||
typ, data, err := f.c.sendPacket(nil, &sshFxpFsyncPacket{
|
typ, data, err := f.c.sendPacket(context.Background(), nil, &sshFxpFsyncPacket{
|
||||||
ID: id,
|
ID: id,
|
||||||
Handle: f.handle,
|
Handle: f.handle,
|
||||||
})
|
})
|
||||||
|
|
12
conn.go
12
conn.go
|
@ -1,6 +1,7 @@
|
||||||
package sftp
|
package sftp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding"
|
"encoding"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -128,14 +129,19 @@ type idmarshaler interface {
|
||||||
encoding.BinaryMarshaler
|
encoding.BinaryMarshaler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientConn) sendPacket(ch chan result, p idmarshaler) (byte, []byte, error) {
|
func (c *clientConn) sendPacket(ctx context.Context, ch chan result, p idmarshaler) (byte, []byte, error) {
|
||||||
if cap(ch) < 1 {
|
if cap(ch) < 1 {
|
||||||
ch = make(chan result, 1)
|
ch = make(chan result, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.dispatchRequest(ch, p)
|
c.dispatchRequest(ch, p)
|
||||||
s := <-ch
|
|
||||||
return s.typ, s.data, s.err
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return 0, nil, ctx.Err()
|
||||||
|
case s := <-ch:
|
||||||
|
return s.typ, s.data, s.err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dispatchRequest should ideally only be called by race-detection tests outside of this file,
|
// dispatchRequest should ideally only be called by race-detection tests outside of this file,
|
||||||
|
|
|
@ -2,6 +2,7 @@ package sftp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -76,7 +77,7 @@ func TestInvalidExtendedPacket(t *testing.T) {
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
badPacket := sshFxpTestBadExtendedPacket{client.nextID(), "thisDoesn'tExist", "foobar"}
|
badPacket := sshFxpTestBadExtendedPacket{client.nextID(), "thisDoesn'tExist", "foobar"}
|
||||||
typ, data, err := client.clientConn.sendPacket(nil, badPacket)
|
typ, data, err := client.clientConn.sendPacket(context.Background(), nil, badPacket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error from sendPacket: %s", err)
|
t.Fatalf("unexpected error from sendPacket: %s", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue