mirror of https://github.com/pkg/sftp.git
pointer receivers and statusFromError(uint32, error)
This commit is contained in:
parent
1d73fd92d5
commit
861a8eaf5c
46
client.go
46
client.go
|
@ -235,7 +235,7 @@ func (c *Client) Create(path string) (*File, error) {
|
|||
const sftpProtocolVersion = 3 // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
|
||||
|
||||
func (c *Client) sendInit() error {
|
||||
return c.clientConn.conn.sendPacket(sshFxInitPacket{
|
||||
return c.clientConn.conn.sendPacket(&sshFxInitPacket{
|
||||
Version: sftpProtocolVersion, // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
|
||||
})
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ func (c *Client) ReadDir(p string) ([]os.FileInfo, error) {
|
|||
var done = false
|
||||
for !done {
|
||||
id := c.nextID()
|
||||
typ, data, err1 := c.sendPacket(nil, sshFxpReaddirPacket{
|
||||
typ, data, err1 := c.sendPacket(nil, &sshFxpReaddirPacket{
|
||||
ID: id,
|
||||
Handle: handle,
|
||||
})
|
||||
|
@ -340,7 +340,7 @@ func (c *Client) ReadDir(p string) ([]os.FileInfo, error) {
|
|||
|
||||
func (c *Client) opendir(path string) (string, error) {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpOpendirPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpOpendirPacket{
|
||||
ID: id,
|
||||
Path: path,
|
||||
})
|
||||
|
@ -366,7 +366,7 @@ func (c *Client) opendir(path string) (string, error) {
|
|||
// If 'p' is a symbolic link, the returned FileInfo structure describes the referent file.
|
||||
func (c *Client) Stat(p string) (os.FileInfo, error) {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpStatPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpStatPacket{
|
||||
ID: id,
|
||||
Path: p,
|
||||
})
|
||||
|
@ -392,7 +392,7 @@ func (c *Client) Stat(p string) (os.FileInfo, error) {
|
|||
// If 'p' is a symbolic link, the returned FileInfo structure describes the symbolic link.
|
||||
func (c *Client) Lstat(p string) (os.FileInfo, error) {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpLstatPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpLstatPacket{
|
||||
ID: id,
|
||||
Path: p,
|
||||
})
|
||||
|
@ -417,7 +417,7 @@ func (c *Client) Lstat(p string) (os.FileInfo, error) {
|
|||
// ReadLink reads the target of a symbolic link.
|
||||
func (c *Client) ReadLink(p string) (string, error) {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpReadlinkPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpReadlinkPacket{
|
||||
ID: id,
|
||||
Path: p,
|
||||
})
|
||||
|
@ -446,7 +446,7 @@ func (c *Client) ReadLink(p string) (string, error) {
|
|||
// Link creates a hard link at 'newname', pointing at the same inode as 'oldname'
|
||||
func (c *Client) Link(oldname, newname string) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpHardlinkPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpHardlinkPacket{
|
||||
ID: id,
|
||||
Oldpath: oldname,
|
||||
Newpath: newname,
|
||||
|
@ -465,7 +465,7 @@ func (c *Client) Link(oldname, newname string) error {
|
|||
// Symlink creates a symbolic link at 'newname', pointing at target 'oldname'
|
||||
func (c *Client) Symlink(oldname, newname string) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpSymlinkPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpSymlinkPacket{
|
||||
ID: id,
|
||||
Linkpath: newname,
|
||||
Targetpath: oldname,
|
||||
|
@ -483,7 +483,7 @@ func (c *Client) Symlink(oldname, newname string) error {
|
|||
|
||||
func (c *Client) setfstat(handle string, flags uint32, attrs interface{}) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpFsetstatPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpFsetstatPacket{
|
||||
ID: id,
|
||||
Handle: handle,
|
||||
Flags: flags,
|
||||
|
@ -503,7 +503,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.
|
||||
func (c *Client) setstat(path string, flags uint32, attrs interface{}) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpSetstatPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpSetstatPacket{
|
||||
ID: id,
|
||||
Path: path,
|
||||
Flags: flags,
|
||||
|
@ -569,7 +569,7 @@ func (c *Client) OpenFile(path string, f int) (*File, error) {
|
|||
|
||||
func (c *Client) open(path string, pflags uint32) (*File, error) {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpOpenPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpOpenPacket{
|
||||
ID: id,
|
||||
Path: path,
|
||||
Pflags: pflags,
|
||||
|
@ -597,7 +597,7 @@ func (c *Client) open(path string, pflags uint32) (*File, error) {
|
|||
// immediately after this request has been sent.
|
||||
func (c *Client) close(handle string) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpClosePacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpClosePacket{
|
||||
ID: id,
|
||||
Handle: handle,
|
||||
})
|
||||
|
@ -614,7 +614,7 @@ func (c *Client) close(handle string) error {
|
|||
|
||||
func (c *Client) fstat(handle string) (*FileStat, error) {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpFstatPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpFstatPacket{
|
||||
ID: id,
|
||||
Handle: handle,
|
||||
})
|
||||
|
@ -643,7 +643,7 @@ func (c *Client) fstat(handle string) (*FileStat, error) {
|
|||
func (c *Client) StatVFS(path string) (*StatVFS, error) {
|
||||
// send the StatVFS packet to the server
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpStatvfsPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpStatvfsPacket{
|
||||
ID: id,
|
||||
Path: path,
|
||||
})
|
||||
|
@ -698,7 +698,7 @@ func (c *Client) Remove(path string) error {
|
|||
|
||||
func (c *Client) removeFile(path string) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpRemovePacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpRemovePacket{
|
||||
ID: id,
|
||||
Filename: path,
|
||||
})
|
||||
|
@ -716,7 +716,7 @@ func (c *Client) removeFile(path string) error {
|
|||
// RemoveDirectory removes a directory path.
|
||||
func (c *Client) RemoveDirectory(path string) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpRmdirPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpRmdirPacket{
|
||||
ID: id,
|
||||
Path: path,
|
||||
})
|
||||
|
@ -734,7 +734,7 @@ func (c *Client) RemoveDirectory(path string) error {
|
|||
// Rename renames a file.
|
||||
func (c *Client) Rename(oldname, newname string) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpRenamePacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpRenamePacket{
|
||||
ID: id,
|
||||
Oldpath: oldname,
|
||||
Newpath: newname,
|
||||
|
@ -754,7 +754,7 @@ func (c *Client) Rename(oldname, newname string) error {
|
|||
// which will replace newname if it already exists.
|
||||
func (c *Client) PosixRename(oldname, newname string) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpPosixRenamePacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpPosixRenamePacket{
|
||||
ID: id,
|
||||
Oldpath: oldname,
|
||||
Newpath: newname,
|
||||
|
@ -772,7 +772,7 @@ func (c *Client) PosixRename(oldname, newname string) error {
|
|||
|
||||
func (c *Client) realpath(path string) (string, error) {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpRealpathPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpRealpathPacket{
|
||||
ID: id,
|
||||
Path: path,
|
||||
})
|
||||
|
@ -809,7 +809,7 @@ func (c *Client) Getwd() (string, error) {
|
|||
// parent folder does not exist (the method cannot create complete paths).
|
||||
func (c *Client) Mkdir(path string) error {
|
||||
id := c.nextID()
|
||||
typ, data, err := c.sendPacket(nil, sshFxpMkdirPacket{
|
||||
typ, data, err := c.sendPacket(nil, &sshFxpMkdirPacket{
|
||||
ID: id,
|
||||
Path: path,
|
||||
})
|
||||
|
@ -916,7 +916,7 @@ func (f *File) Read(b []byte) (int, error) {
|
|||
func (f *File) readChunkAt(ch chan result, b []byte, off int64) (n int, err error) {
|
||||
for err == nil && n < len(b) {
|
||||
id := f.c.nextID()
|
||||
typ, data, err := f.c.sendPacket(ch, sshFxpReadPacket{
|
||||
typ, data, err := f.c.sendPacket(ch, &sshFxpReadPacket{
|
||||
ID: id,
|
||||
Handle: f.handle,
|
||||
Offset: uint64(off) + uint64(n),
|
||||
|
@ -1282,7 +1282,7 @@ func (f *File) Write(b []byte) (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(ch, &sshFxpWritePacket{
|
||||
ID: f.c.nextID(),
|
||||
Handle: f.handle,
|
||||
Offset: uint64(off),
|
||||
|
@ -1674,7 +1674,7 @@ func (f *File) Chmod(mode os.FileMode) error {
|
|||
// Sync requires the server to support the fsync@openssh.com extension.
|
||||
func (f *File) Sync() error {
|
||||
id := f.c.nextID()
|
||||
typ, data, err := f.c.sendPacket(nil, sshFxpFsyncPacket{
|
||||
typ, data, err := f.c.sendPacket(nil, &sshFxpFsyncPacket{
|
||||
ID: id,
|
||||
Handle: f.handle,
|
||||
})
|
||||
|
|
4
conn.go
4
conn.go
|
@ -186,6 +186,6 @@ type serverConn struct {
|
|||
conn
|
||||
}
|
||||
|
||||
func (s *serverConn) sendError(p ider, err error) error {
|
||||
return s.sendPacket(statusFromError(p, err))
|
||||
func (s *serverConn) sendError(id uint32, err error) error {
|
||||
return s.sendPacket(statusFromError(id, err))
|
||||
}
|
||||
|
|
|
@ -34,51 +34,51 @@ type notReadOnly interface {
|
|||
|
||||
//// define types by adding methods
|
||||
// hasPath
|
||||
func (p sshFxpLstatPacket) getPath() string { return p.Path }
|
||||
func (p sshFxpStatPacket) getPath() string { return p.Path }
|
||||
func (p sshFxpRmdirPacket) getPath() string { return p.Path }
|
||||
func (p sshFxpReadlinkPacket) getPath() string { return p.Path }
|
||||
func (p sshFxpRealpathPacket) getPath() string { return p.Path }
|
||||
func (p sshFxpMkdirPacket) getPath() string { return p.Path }
|
||||
func (p sshFxpSetstatPacket) getPath() string { return p.Path }
|
||||
func (p sshFxpStatvfsPacket) getPath() string { return p.Path }
|
||||
func (p sshFxpRemovePacket) getPath() string { return p.Filename }
|
||||
func (p sshFxpRenamePacket) getPath() string { return p.Oldpath }
|
||||
func (p sshFxpSymlinkPacket) getPath() string { return p.Targetpath }
|
||||
func (p sshFxpOpendirPacket) getPath() string { return p.Path }
|
||||
func (p sshFxpOpenPacket) getPath() string { return p.Path }
|
||||
func (p *sshFxpLstatPacket) getPath() string { return p.Path }
|
||||
func (p *sshFxpStatPacket) getPath() string { return p.Path }
|
||||
func (p *sshFxpRmdirPacket) getPath() string { return p.Path }
|
||||
func (p *sshFxpReadlinkPacket) getPath() string { return p.Path }
|
||||
func (p *sshFxpRealpathPacket) getPath() string { return p.Path }
|
||||
func (p *sshFxpMkdirPacket) getPath() string { return p.Path }
|
||||
func (p *sshFxpSetstatPacket) getPath() string { return p.Path }
|
||||
func (p *sshFxpStatvfsPacket) getPath() string { return p.Path }
|
||||
func (p *sshFxpRemovePacket) getPath() string { return p.Filename }
|
||||
func (p *sshFxpRenamePacket) getPath() string { return p.Oldpath }
|
||||
func (p *sshFxpSymlinkPacket) getPath() string { return p.Targetpath }
|
||||
func (p *sshFxpOpendirPacket) getPath() string { return p.Path }
|
||||
func (p *sshFxpOpenPacket) getPath() string { return p.Path }
|
||||
|
||||
func (p sshFxpExtendedPacketPosixRename) getPath() string { return p.Oldpath }
|
||||
func (p sshFxpExtendedPacketHardlink) getPath() string { return p.Oldpath }
|
||||
func (p *sshFxpExtendedPacketPosixRename) getPath() string { return p.Oldpath }
|
||||
func (p *sshFxpExtendedPacketHardlink) getPath() string { return p.Oldpath }
|
||||
|
||||
// getHandle
|
||||
func (p sshFxpFstatPacket) getHandle() string { return p.Handle }
|
||||
func (p sshFxpFsetstatPacket) getHandle() string { return p.Handle }
|
||||
func (p sshFxpReadPacket) getHandle() string { return p.Handle }
|
||||
func (p sshFxpWritePacket) getHandle() string { return p.Handle }
|
||||
func (p sshFxpReaddirPacket) getHandle() string { return p.Handle }
|
||||
func (p sshFxpClosePacket) getHandle() string { return p.Handle }
|
||||
func (p *sshFxpFstatPacket) getHandle() string { return p.Handle }
|
||||
func (p *sshFxpFsetstatPacket) getHandle() string { return p.Handle }
|
||||
func (p *sshFxpReadPacket) getHandle() string { return p.Handle }
|
||||
func (p *sshFxpWritePacket) getHandle() string { return p.Handle }
|
||||
func (p *sshFxpReaddirPacket) getHandle() string { return p.Handle }
|
||||
func (p *sshFxpClosePacket) getHandle() string { return p.Handle }
|
||||
|
||||
// notReadOnly
|
||||
func (p sshFxpWritePacket) notReadOnly() {}
|
||||
func (p sshFxpSetstatPacket) notReadOnly() {}
|
||||
func (p sshFxpFsetstatPacket) notReadOnly() {}
|
||||
func (p sshFxpRemovePacket) notReadOnly() {}
|
||||
func (p sshFxpMkdirPacket) notReadOnly() {}
|
||||
func (p sshFxpRmdirPacket) notReadOnly() {}
|
||||
func (p sshFxpRenamePacket) notReadOnly() {}
|
||||
func (p sshFxpSymlinkPacket) notReadOnly() {}
|
||||
func (p sshFxpExtendedPacketPosixRename) notReadOnly() {}
|
||||
func (p sshFxpExtendedPacketHardlink) notReadOnly() {}
|
||||
func (p *sshFxpWritePacket) notReadOnly() {}
|
||||
func (p *sshFxpSetstatPacket) notReadOnly() {}
|
||||
func (p *sshFxpFsetstatPacket) notReadOnly() {}
|
||||
func (p *sshFxpRemovePacket) notReadOnly() {}
|
||||
func (p *sshFxpMkdirPacket) notReadOnly() {}
|
||||
func (p *sshFxpRmdirPacket) notReadOnly() {}
|
||||
func (p *sshFxpRenamePacket) notReadOnly() {}
|
||||
func (p *sshFxpSymlinkPacket) notReadOnly() {}
|
||||
func (p *sshFxpExtendedPacketPosixRename) notReadOnly() {}
|
||||
func (p *sshFxpExtendedPacketHardlink) notReadOnly() {}
|
||||
|
||||
// some packets with ID are missing id()
|
||||
func (p sshFxpDataPacket) id() uint32 { return p.ID }
|
||||
func (p sshFxpStatusPacket) id() uint32 { return p.ID }
|
||||
func (p sshFxpStatResponse) id() uint32 { return p.ID }
|
||||
func (p sshFxpNamePacket) id() uint32 { return p.ID }
|
||||
func (p sshFxpHandlePacket) id() uint32 { return p.ID }
|
||||
func (p StatVFS) id() uint32 { return p.ID }
|
||||
func (p sshFxVersionPacket) id() uint32 { return 0 }
|
||||
func (p *sshFxpDataPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpStatusPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpStatResponse) id() uint32 { return p.ID }
|
||||
func (p *sshFxpNamePacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpHandlePacket) id() uint32 { return p.ID }
|
||||
func (p *StatVFS) id() uint32 { return p.ID }
|
||||
func (p *sshFxVersionPacket) id() uint32 { return 0 }
|
||||
|
||||
// take raw incoming packet data and build packet objects
|
||||
func makePacket(p rxPacket) (requestPacket, error) {
|
||||
|
|
142
packet.go
142
packet.go
|
@ -218,7 +218,7 @@ type sshFxInitPacket struct {
|
|||
Extensions []extensionPair
|
||||
}
|
||||
|
||||
func (p sshFxInitPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxInitPacket) MarshalBinary() ([]byte, error) {
|
||||
l := 4 + 1 + 4 // uint32(length) + byte(type) + uint32(version)
|
||||
for _, e := range p.Extensions {
|
||||
l += 4 + len(e.Name) + 4 + len(e.Data)
|
||||
|
@ -261,7 +261,7 @@ type sshExtensionPair struct {
|
|||
Name, Data string
|
||||
}
|
||||
|
||||
func (p sshFxVersionPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxVersionPacket) MarshalBinary() ([]byte, error) {
|
||||
l := 4 + 1 + 4 // uint32(length) + byte(type) + uint32(version)
|
||||
for _, e := range p.Extensions {
|
||||
l += 4 + len(e.Name) + 4 + len(e.Data)
|
||||
|
@ -306,9 +306,9 @@ type sshFxpReaddirPacket struct {
|
|||
Handle string
|
||||
}
|
||||
|
||||
func (p sshFxpReaddirPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpReaddirPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpReaddirPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpReaddirPacket) MarshalBinary() ([]byte, error) {
|
||||
return marshalIDStringPacket(sshFxpReaddir, p.ID, p.Handle)
|
||||
}
|
||||
|
||||
|
@ -321,9 +321,9 @@ type sshFxpOpendirPacket struct {
|
|||
Path string
|
||||
}
|
||||
|
||||
func (p sshFxpOpendirPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpOpendirPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpOpendirPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpOpendirPacket) MarshalBinary() ([]byte, error) {
|
||||
return marshalIDStringPacket(sshFxpOpendir, p.ID, p.Path)
|
||||
}
|
||||
|
||||
|
@ -336,9 +336,9 @@ type sshFxpLstatPacket struct {
|
|||
Path string
|
||||
}
|
||||
|
||||
func (p sshFxpLstatPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpLstatPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpLstatPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpLstatPacket) MarshalBinary() ([]byte, error) {
|
||||
return marshalIDStringPacket(sshFxpLstat, p.ID, p.Path)
|
||||
}
|
||||
|
||||
|
@ -351,9 +351,9 @@ type sshFxpStatPacket struct {
|
|||
Path string
|
||||
}
|
||||
|
||||
func (p sshFxpStatPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpStatPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpStatPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpStatPacket) MarshalBinary() ([]byte, error) {
|
||||
return marshalIDStringPacket(sshFxpStat, p.ID, p.Path)
|
||||
}
|
||||
|
||||
|
@ -366,9 +366,9 @@ type sshFxpFstatPacket struct {
|
|||
Handle string
|
||||
}
|
||||
|
||||
func (p sshFxpFstatPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpFstatPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpFstatPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpFstatPacket) MarshalBinary() ([]byte, error) {
|
||||
return marshalIDStringPacket(sshFxpFstat, p.ID, p.Handle)
|
||||
}
|
||||
|
||||
|
@ -381,9 +381,9 @@ type sshFxpClosePacket struct {
|
|||
Handle string
|
||||
}
|
||||
|
||||
func (p sshFxpClosePacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpClosePacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpClosePacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpClosePacket) MarshalBinary() ([]byte, error) {
|
||||
return marshalIDStringPacket(sshFxpClose, p.ID, p.Handle)
|
||||
}
|
||||
|
||||
|
@ -396,9 +396,9 @@ type sshFxpRemovePacket struct {
|
|||
Filename string
|
||||
}
|
||||
|
||||
func (p sshFxpRemovePacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpRemovePacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpRemovePacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpRemovePacket) MarshalBinary() ([]byte, error) {
|
||||
return marshalIDStringPacket(sshFxpRemove, p.ID, p.Filename)
|
||||
}
|
||||
|
||||
|
@ -411,9 +411,9 @@ type sshFxpRmdirPacket struct {
|
|||
Path string
|
||||
}
|
||||
|
||||
func (p sshFxpRmdirPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpRmdirPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpRmdirPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpRmdirPacket) MarshalBinary() ([]byte, error) {
|
||||
return marshalIDStringPacket(sshFxpRmdir, p.ID, p.Path)
|
||||
}
|
||||
|
||||
|
@ -427,9 +427,9 @@ type sshFxpSymlinkPacket struct {
|
|||
Linkpath string
|
||||
}
|
||||
|
||||
func (p sshFxpSymlinkPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpSymlinkPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpSymlinkPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpSymlinkPacket) MarshalBinary() ([]byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(p.Targetpath) +
|
||||
4 + len(p.Linkpath)
|
||||
|
@ -461,9 +461,9 @@ type sshFxpHardlinkPacket struct {
|
|||
Newpath string
|
||||
}
|
||||
|
||||
func (p sshFxpHardlinkPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpHardlinkPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpHardlinkPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpHardlinkPacket) MarshalBinary() ([]byte, error) {
|
||||
const ext = "hardlink@openssh.com"
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(ext) +
|
||||
|
@ -485,9 +485,9 @@ type sshFxpReadlinkPacket struct {
|
|||
Path string
|
||||
}
|
||||
|
||||
func (p sshFxpReadlinkPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpReadlinkPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpReadlinkPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpReadlinkPacket) MarshalBinary() ([]byte, error) {
|
||||
return marshalIDStringPacket(sshFxpReadlink, p.ID, p.Path)
|
||||
}
|
||||
|
||||
|
@ -500,9 +500,9 @@ type sshFxpRealpathPacket struct {
|
|||
Path string
|
||||
}
|
||||
|
||||
func (p sshFxpRealpathPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpRealpathPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpRealpathPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpRealpathPacket) MarshalBinary() ([]byte, error) {
|
||||
return marshalIDStringPacket(sshFxpRealpath, p.ID, p.Path)
|
||||
}
|
||||
|
||||
|
@ -516,7 +516,7 @@ type sshFxpNameAttr struct {
|
|||
Attrs []interface{}
|
||||
}
|
||||
|
||||
func (p sshFxpNameAttr) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpNameAttr) MarshalBinary() ([]byte, error) {
|
||||
var b []byte
|
||||
b = marshalString(b, p.Name)
|
||||
b = marshalString(b, p.LongName)
|
||||
|
@ -528,10 +528,10 @@ func (p sshFxpNameAttr) MarshalBinary() ([]byte, error) {
|
|||
|
||||
type sshFxpNamePacket struct {
|
||||
ID uint32
|
||||
NameAttrs []sshFxpNameAttr
|
||||
NameAttrs []*sshFxpNameAttr
|
||||
}
|
||||
|
||||
func (p sshFxpNamePacket) marshalPacket() ([]byte, []byte, error) {
|
||||
func (p *sshFxpNamePacket) marshalPacket() ([]byte, []byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4
|
||||
|
||||
|
@ -553,7 +553,7 @@ func (p sshFxpNamePacket) marshalPacket() ([]byte, []byte, error) {
|
|||
return b, payload, nil
|
||||
}
|
||||
|
||||
func (p sshFxpNamePacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpNamePacket) MarshalBinary() ([]byte, error) {
|
||||
header, payload, err := p.marshalPacket()
|
||||
return append(header, payload...), err
|
||||
}
|
||||
|
@ -565,9 +565,9 @@ type sshFxpOpenPacket struct {
|
|||
Flags uint32 // ignored
|
||||
}
|
||||
|
||||
func (p sshFxpOpenPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpOpenPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpOpenPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpOpenPacket) MarshalBinary() ([]byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(p.Path) +
|
||||
4 + 4
|
||||
|
@ -603,9 +603,9 @@ type sshFxpReadPacket struct {
|
|||
Handle string
|
||||
}
|
||||
|
||||
func (p sshFxpReadPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpReadPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpReadPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpReadPacket) MarshalBinary() ([]byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(p.Handle) +
|
||||
8 + 4 // uint64 + uint32
|
||||
|
@ -655,9 +655,9 @@ type sshFxpRenamePacket struct {
|
|||
Newpath string
|
||||
}
|
||||
|
||||
func (p sshFxpRenamePacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpRenamePacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpRenamePacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpRenamePacket) MarshalBinary() ([]byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(p.Oldpath) +
|
||||
4 + len(p.Newpath)
|
||||
|
@ -689,9 +689,9 @@ type sshFxpPosixRenamePacket struct {
|
|||
Newpath string
|
||||
}
|
||||
|
||||
func (p sshFxpPosixRenamePacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpPosixRenamePacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpPosixRenamePacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpPosixRenamePacket) MarshalBinary() ([]byte, error) {
|
||||
const ext = "posix-rename@openssh.com"
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(ext) +
|
||||
|
@ -716,9 +716,9 @@ type sshFxpWritePacket struct {
|
|||
Data []byte
|
||||
}
|
||||
|
||||
func (p sshFxpWritePacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpWritePacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpWritePacket) marshalPacket() ([]byte, []byte, error) {
|
||||
func (p *sshFxpWritePacket) marshalPacket() ([]byte, []byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(p.Handle) +
|
||||
8 + // uint64
|
||||
|
@ -734,7 +734,7 @@ func (p sshFxpWritePacket) marshalPacket() ([]byte, []byte, error) {
|
|||
return b, p.Data, nil
|
||||
}
|
||||
|
||||
func (p sshFxpWritePacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpWritePacket) MarshalBinary() ([]byte, error) {
|
||||
header, payload, err := p.marshalPacket()
|
||||
return append(header, payload...), err
|
||||
}
|
||||
|
@ -763,9 +763,9 @@ type sshFxpMkdirPacket struct {
|
|||
Path string
|
||||
}
|
||||
|
||||
func (p sshFxpMkdirPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpMkdirPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpMkdirPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpMkdirPacket) MarshalBinary() ([]byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(p.Path) +
|
||||
4 // uint32
|
||||
|
@ -805,10 +805,10 @@ type sshFxpFsetstatPacket struct {
|
|||
Attrs interface{}
|
||||
}
|
||||
|
||||
func (p sshFxpSetstatPacket) id() uint32 { return p.ID }
|
||||
func (p sshFxpFsetstatPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpSetstatPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpFsetstatPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpSetstatPacket) marshalPacket() ([]byte, []byte, error) {
|
||||
func (p *sshFxpSetstatPacket) marshalPacket() ([]byte, []byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(p.Path) +
|
||||
4 // uint32
|
||||
|
@ -824,12 +824,12 @@ func (p sshFxpSetstatPacket) marshalPacket() ([]byte, []byte, error) {
|
|||
return b, payload, nil
|
||||
}
|
||||
|
||||
func (p sshFxpSetstatPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpSetstatPacket) MarshalBinary() ([]byte, error) {
|
||||
header, payload, err := p.marshalPacket()
|
||||
return append(header, payload...), err
|
||||
}
|
||||
|
||||
func (p sshFxpFsetstatPacket) marshalPacket() ([]byte, []byte, error) {
|
||||
func (p *sshFxpFsetstatPacket) marshalPacket() ([]byte, []byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(p.Handle) +
|
||||
4 // uint32
|
||||
|
@ -845,7 +845,7 @@ func (p sshFxpFsetstatPacket) marshalPacket() ([]byte, []byte, error) {
|
|||
return b, payload, nil
|
||||
}
|
||||
|
||||
func (p sshFxpFsetstatPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpFsetstatPacket) MarshalBinary() ([]byte, error) {
|
||||
header, payload, err := p.marshalPacket()
|
||||
return append(header, payload...), err
|
||||
}
|
||||
|
@ -881,7 +881,7 @@ type sshFxpHandlePacket struct {
|
|||
Handle string
|
||||
}
|
||||
|
||||
func (p sshFxpHandlePacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpHandlePacket) MarshalBinary() ([]byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(p.Handle)
|
||||
|
||||
|
@ -898,7 +898,7 @@ type sshFxpStatusPacket struct {
|
|||
StatusError
|
||||
}
|
||||
|
||||
func (p sshFxpStatusPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpStatusPacket) MarshalBinary() ([]byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 +
|
||||
4 + len(p.StatusError.msg) +
|
||||
|
@ -918,7 +918,7 @@ type sshFxpDataPacket struct {
|
|||
Data []byte
|
||||
}
|
||||
|
||||
func (p sshFxpDataPacket) marshalPacket() ([]byte, []byte, error) {
|
||||
func (p *sshFxpDataPacket) marshalPacket() ([]byte, []byte, error) {
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4
|
||||
|
||||
|
@ -935,7 +935,7 @@ func (p sshFxpDataPacket) marshalPacket() ([]byte, []byte, error) {
|
|||
//
|
||||
// This is hand-coded rather than just append(header, payload...),
|
||||
// in order to try and reuse the r.Data backing store in the packet.
|
||||
func (p sshFxpDataPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpDataPacket) MarshalBinary() ([]byte, error) {
|
||||
b := append(p.Data, make([]byte, dataHeaderLen)...)
|
||||
copy(b[dataHeaderLen:], p.Data[:p.Length])
|
||||
// b[0:4] will be overwritten with the length in sendPacket
|
||||
|
@ -964,9 +964,9 @@ type sshFxpStatvfsPacket struct {
|
|||
Path string
|
||||
}
|
||||
|
||||
func (p sshFxpStatvfsPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpStatvfsPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpStatvfsPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpStatvfsPacket) MarshalBinary() ([]byte, error) {
|
||||
const ext = "statvfs@openssh.com"
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(ext) +
|
||||
|
@ -1027,9 +1027,9 @@ type sshFxpFsyncPacket struct {
|
|||
Handle string
|
||||
}
|
||||
|
||||
func (p sshFxpFsyncPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpFsyncPacket) id() uint32 { return p.ID }
|
||||
|
||||
func (p sshFxpFsyncPacket) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpFsyncPacket) MarshalBinary() ([]byte, error) {
|
||||
const ext = "fsync@openssh.com"
|
||||
l := 4 + 1 + 4 + // uint32(length) + byte(type) + uint32(id)
|
||||
4 + len(ext) +
|
||||
|
@ -1053,17 +1053,17 @@ type sshFxpExtendedPacket struct {
|
|||
}
|
||||
}
|
||||
|
||||
func (p sshFxpExtendedPacket) id() uint32 { return p.ID }
|
||||
func (p sshFxpExtendedPacket) readonly() bool {
|
||||
func (p *sshFxpExtendedPacket) id() uint32 { return p.ID }
|
||||
func (p *sshFxpExtendedPacket) readonly() bool {
|
||||
if p.SpecificPacket == nil {
|
||||
return true
|
||||
}
|
||||
return p.SpecificPacket.readonly()
|
||||
}
|
||||
|
||||
func (p sshFxpExtendedPacket) respond(svr *Server) responsePacket {
|
||||
func (p *sshFxpExtendedPacket) respond(svr *Server) responsePacket {
|
||||
if p.SpecificPacket == nil {
|
||||
return statusFromError(p, nil)
|
||||
return statusFromError(p.ID, nil)
|
||||
}
|
||||
return p.SpecificPacket.respond(svr)
|
||||
}
|
||||
|
@ -1098,8 +1098,8 @@ type sshFxpExtendedPacketStatVFS struct {
|
|||
Path string
|
||||
}
|
||||
|
||||
func (p sshFxpExtendedPacketStatVFS) id() uint32 { return p.ID }
|
||||
func (p sshFxpExtendedPacketStatVFS) readonly() bool { return true }
|
||||
func (p *sshFxpExtendedPacketStatVFS) id() uint32 { return p.ID }
|
||||
func (p *sshFxpExtendedPacketStatVFS) readonly() bool { return true }
|
||||
func (p *sshFxpExtendedPacketStatVFS) UnmarshalBinary(b []byte) error {
|
||||
var err error
|
||||
if p.ID, b, err = unmarshalUint32Safe(b); err != nil {
|
||||
|
@ -1119,8 +1119,8 @@ type sshFxpExtendedPacketPosixRename struct {
|
|||
Newpath string
|
||||
}
|
||||
|
||||
func (p sshFxpExtendedPacketPosixRename) id() uint32 { return p.ID }
|
||||
func (p sshFxpExtendedPacketPosixRename) readonly() bool { return false }
|
||||
func (p *sshFxpExtendedPacketPosixRename) id() uint32 { return p.ID }
|
||||
func (p *sshFxpExtendedPacketPosixRename) readonly() bool { return false }
|
||||
func (p *sshFxpExtendedPacketPosixRename) UnmarshalBinary(b []byte) error {
|
||||
var err error
|
||||
if p.ID, b, err = unmarshalUint32Safe(b); err != nil {
|
||||
|
@ -1135,9 +1135,9 @@ func (p *sshFxpExtendedPacketPosixRename) UnmarshalBinary(b []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p sshFxpExtendedPacketPosixRename) respond(s *Server) responsePacket {
|
||||
func (p *sshFxpExtendedPacketPosixRename) respond(s *Server) responsePacket {
|
||||
err := os.Rename(p.Oldpath, p.Newpath)
|
||||
return statusFromError(p, err)
|
||||
return statusFromError(p.ID, err)
|
||||
}
|
||||
|
||||
type sshFxpExtendedPacketHardlink struct {
|
||||
|
@ -1148,8 +1148,8 @@ type sshFxpExtendedPacketHardlink struct {
|
|||
}
|
||||
|
||||
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL
|
||||
func (p sshFxpExtendedPacketHardlink) id() uint32 { return p.ID }
|
||||
func (p sshFxpExtendedPacketHardlink) readonly() bool { return true }
|
||||
func (p *sshFxpExtendedPacketHardlink) id() uint32 { return p.ID }
|
||||
func (p *sshFxpExtendedPacketHardlink) readonly() bool { return true }
|
||||
func (p *sshFxpExtendedPacketHardlink) UnmarshalBinary(b []byte) error {
|
||||
var err error
|
||||
if p.ID, b, err = unmarshalUint32Safe(b); err != nil {
|
||||
|
@ -1164,7 +1164,7 @@ func (p *sshFxpExtendedPacketHardlink) UnmarshalBinary(b []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p sshFxpExtendedPacketHardlink) respond(s *Server) responsePacket {
|
||||
func (p *sshFxpExtendedPacketHardlink) respond(s *Server) responsePacket {
|
||||
err := os.Link(p.Oldpath, p.Newpath)
|
||||
return statusFromError(p, err)
|
||||
return statusFromError(p.ID, err)
|
||||
}
|
||||
|
|
|
@ -142,20 +142,20 @@ var sendPacketTests = []struct {
|
|||
p encoding.BinaryMarshaler
|
||||
want []byte
|
||||
}{
|
||||
{sshFxInitPacket{
|
||||
{&sshFxInitPacket{
|
||||
Version: 3,
|
||||
Extensions: []extensionPair{
|
||||
{"posix-rename@openssh.com", "1"},
|
||||
},
|
||||
}, []byte{0x0, 0x0, 0x0, 0x26, 0x1, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x18, 0x70, 0x6f, 0x73, 0x69, 0x78, 0x2d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x73, 0x68, 0x2e, 0x63, 0x6f, 0x6d, 0x0, 0x0, 0x0, 0x1, 0x31}},
|
||||
|
||||
{sshFxpOpenPacket{
|
||||
{&sshFxpOpenPacket{
|
||||
ID: 1,
|
||||
Path: "/foo",
|
||||
Pflags: flags(os.O_RDONLY),
|
||||
}, []byte{0x0, 0x0, 0x0, 0x15, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x4, 0x2f, 0x66, 0x6f, 0x6f, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0}},
|
||||
|
||||
{sshFxpWritePacket{
|
||||
{&sshFxpWritePacket{
|
||||
ID: 124,
|
||||
Handle: "foo",
|
||||
Offset: 13,
|
||||
|
@ -163,7 +163,7 @@ var sendPacketTests = []struct {
|
|||
Data: []byte("bar"),
|
||||
}, []byte{0x0, 0x0, 0x0, 0x1b, 0x6, 0x0, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x0, 0x3, 0x66, 0x6f, 0x6f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x3, 0x62, 0x61, 0x72}},
|
||||
|
||||
{sshFxpSetstatPacket{
|
||||
{&sshFxpSetstatPacket{
|
||||
ID: 31,
|
||||
Path: "/bar",
|
||||
Flags: flags(os.O_WRONLY),
|
||||
|
@ -195,7 +195,7 @@ var recvPacketTests = []struct {
|
|||
want uint8
|
||||
rest []byte
|
||||
}{
|
||||
{sp(sshFxInitPacket{
|
||||
{sp(&sshFxInitPacket{
|
||||
Version: 3,
|
||||
Extensions: []extensionPair{
|
||||
{"posix-rename@openssh.com", "1"},
|
||||
|
@ -299,7 +299,7 @@ func TestSSHFxpOpenPackethasPflags(t *testing.T) {
|
|||
|
||||
func BenchmarkMarshalInit(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
sp(sshFxInitPacket{
|
||||
sp(&sshFxInitPacket{
|
||||
Version: 3,
|
||||
Extensions: []extensionPair{
|
||||
{"posix-rename@openssh.com", "1"},
|
||||
|
@ -310,7 +310,7 @@ func BenchmarkMarshalInit(b *testing.B) {
|
|||
|
||||
func BenchmarkMarshalOpen(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
sp(sshFxpOpenPacket{
|
||||
sp(&sshFxpOpenPacket{
|
||||
ID: 1,
|
||||
Path: "/home/test/some/random/path",
|
||||
Pflags: flags(os.O_RDONLY),
|
||||
|
@ -321,7 +321,7 @@ func BenchmarkMarshalOpen(b *testing.B) {
|
|||
func BenchmarkMarshalWriteWorstCase(b *testing.B) {
|
||||
data := make([]byte, 32*1024)
|
||||
for i := 0; i < b.N; i++ {
|
||||
sp(sshFxpWritePacket{
|
||||
sp(&sshFxpWritePacket{
|
||||
ID: 1,
|
||||
Handle: "someopaquehandle",
|
||||
Offset: 0,
|
||||
|
@ -334,7 +334,7 @@ func BenchmarkMarshalWriteWorstCase(b *testing.B) {
|
|||
func BenchmarkMarshalWrite1k(b *testing.B) {
|
||||
data := make([]byte, 1024)
|
||||
for i := 0; i < b.N; i++ {
|
||||
sp(sshFxpWritePacket{
|
||||
sp(&sshFxpWritePacket{
|
||||
ID: 1,
|
||||
Handle: "someopaquehandle",
|
||||
Offset: 0,
|
||||
|
|
|
@ -193,10 +193,10 @@ func (rs *RequestServer) packetWorker(
|
|||
var rpkt responsePacket
|
||||
switch pkt := pkt.requestPacket.(type) {
|
||||
case *sshFxInitPacket:
|
||||
rpkt = sshFxVersionPacket{Version: sftpProtocolVersion, Extensions: sftpExtensions}
|
||||
rpkt = &sshFxVersionPacket{Version: sftpProtocolVersion, Extensions: sftpExtensions}
|
||||
case *sshFxpClosePacket:
|
||||
handle := pkt.getHandle()
|
||||
rpkt = statusFromError(pkt, rs.closeRequest(handle))
|
||||
rpkt = statusFromError(pkt.ID, rs.closeRequest(handle))
|
||||
case *sshFxpRealpathPacket:
|
||||
rpkt = cleanPacketPath(pkt)
|
||||
case *sshFxpOpendirPacket:
|
||||
|
@ -219,7 +219,7 @@ func (rs *RequestServer) packetWorker(
|
|||
handle := pkt.getHandle()
|
||||
request, ok := rs.getRequest(handle)
|
||||
if !ok {
|
||||
rpkt = statusFromError(pkt, EBADF)
|
||||
rpkt = statusFromError(pkt.ID, EBADF)
|
||||
} else {
|
||||
request = NewRequest("Stat", request.Filepath)
|
||||
rpkt = request.call(rs.Handlers, pkt, rs.pktMgr.alloc, orderID)
|
||||
|
@ -228,7 +228,7 @@ func (rs *RequestServer) packetWorker(
|
|||
handle := pkt.getHandle()
|
||||
request, ok := rs.getRequest(handle)
|
||||
if !ok {
|
||||
rpkt = statusFromError(pkt, EBADF)
|
||||
rpkt = statusFromError(pkt.ID, EBADF)
|
||||
} else {
|
||||
request = NewRequest("Setstat", request.Filepath)
|
||||
rpkt = request.call(rs.Handlers, pkt, rs.pktMgr.alloc, orderID)
|
||||
|
@ -244,7 +244,7 @@ func (rs *RequestServer) packetWorker(
|
|||
handle := pkt.getHandle()
|
||||
request, ok := rs.getRequest(handle)
|
||||
if !ok {
|
||||
rpkt = statusFromError(pkt, EBADF)
|
||||
rpkt = statusFromError(pkt.id(), EBADF)
|
||||
} else {
|
||||
rpkt = request.call(rs.Handlers, pkt, rs.pktMgr.alloc, orderID)
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ func (rs *RequestServer) packetWorker(
|
|||
rpkt = request.call(rs.Handlers, pkt, rs.pktMgr.alloc, orderID)
|
||||
request.close()
|
||||
default:
|
||||
rpkt = statusFromError(pkt, ErrSSHFxOpUnsupported)
|
||||
rpkt = statusFromError(pkt.id(), ErrSSHFxOpUnsupported)
|
||||
}
|
||||
|
||||
rs.pktMgr.readyPacket(
|
||||
|
@ -267,11 +267,13 @@ func cleanPacketPath(pkt *sshFxpRealpathPacket) responsePacket {
|
|||
path := cleanPath(pkt.getPath())
|
||||
return &sshFxpNamePacket{
|
||||
ID: pkt.id(),
|
||||
NameAttrs: []sshFxpNameAttr{{
|
||||
NameAttrs: []*sshFxpNameAttr{
|
||||
&sshFxpNameAttr{
|
||||
Name: path,
|
||||
LongName: path,
|
||||
Attrs: emptyFileStat,
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
73
request.go
73
request.go
|
@ -219,7 +219,7 @@ func (r *Request) call(handlers Handlers, pkt requestPacket, alloc *allocator, o
|
|||
case "Stat", "Lstat", "Readlink":
|
||||
return filestat(handlers.FileList, r, pkt)
|
||||
default:
|
||||
return statusFromError(pkt,
|
||||
return statusFromError(pkt.id(),
|
||||
errors.Errorf("unexpected method: %s", r.Method))
|
||||
}
|
||||
}
|
||||
|
@ -228,6 +228,8 @@ func (r *Request) call(handlers Handlers, pkt requestPacket, alloc *allocator, o
|
|||
func (r *Request) open(h Handlers, pkt requestPacket) responsePacket {
|
||||
flags := r.Pflags()
|
||||
|
||||
id := pkt.id()
|
||||
|
||||
switch {
|
||||
case flags.Write, flags.Append, flags.Creat, flags.Trunc:
|
||||
if flags.Read {
|
||||
|
@ -235,36 +237,37 @@ func (r *Request) open(h Handlers, pkt requestPacket) responsePacket {
|
|||
r.Method = "Open"
|
||||
rw, err := openFileWriter.OpenFile(r)
|
||||
if err != nil {
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(id, err)
|
||||
}
|
||||
r.state.writerReaderAt = rw
|
||||
return &sshFxpHandlePacket{ID: pkt.id(), Handle: r.handle}
|
||||
return &sshFxpHandlePacket{ID: id, Handle: r.handle}
|
||||
}
|
||||
}
|
||||
|
||||
r.Method = "Put"
|
||||
wr, err := h.FilePut.Filewrite(r)
|
||||
if err != nil {
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(id, err)
|
||||
}
|
||||
r.state.writerAt = wr
|
||||
case flags.Read:
|
||||
r.Method = "Get"
|
||||
rd, err := h.FileGet.Fileread(r)
|
||||
if err != nil {
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(id, err)
|
||||
}
|
||||
r.state.readerAt = rd
|
||||
default:
|
||||
return statusFromError(pkt, errors.New("bad file flags"))
|
||||
return statusFromError(id, errors.New("bad file flags"))
|
||||
}
|
||||
return &sshFxpHandlePacket{ID: pkt.id(), Handle: r.handle}
|
||||
return &sshFxpHandlePacket{ID: id, Handle: r.handle}
|
||||
}
|
||||
|
||||
func (r *Request) opendir(h Handlers, pkt requestPacket) responsePacket {
|
||||
r.Method = "List"
|
||||
la, err := h.FileList.Filelist(r)
|
||||
if err != nil {
|
||||
return statusFromError(pkt, wrapPathError(r.Filepath, err))
|
||||
return statusFromError(pkt.id(), wrapPathError(r.Filepath, err))
|
||||
}
|
||||
r.state.listerAt = la
|
||||
return &sshFxpHandlePacket{ID: pkt.id(), Handle: r.handle}
|
||||
|
@ -276,14 +279,14 @@ func fileget(h FileReader, r *Request, pkt requestPacket, alloc *allocator, orde
|
|||
reader := r.state.readerAt
|
||||
r.state.RUnlock()
|
||||
if reader == nil {
|
||||
return statusFromError(pkt, errors.New("unexpected read packet"))
|
||||
return statusFromError(pkt.id(), errors.New("unexpected read packet"))
|
||||
}
|
||||
|
||||
data, offset, _ := packetData(pkt, alloc, orderID)
|
||||
n, err := reader.ReadAt(data, offset)
|
||||
// only return EOF error if no data left to read
|
||||
if err != nil && (err != io.EOF || n == 0) {
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
return &sshFxpDataPacket{
|
||||
ID: pkt.id(),
|
||||
|
@ -298,12 +301,12 @@ func fileput(h FileWriter, r *Request, pkt requestPacket, alloc *allocator, orde
|
|||
writer := r.state.writerAt
|
||||
r.state.RUnlock()
|
||||
if writer == nil {
|
||||
return statusFromError(pkt, errors.New("unexpected write packet"))
|
||||
return statusFromError(pkt.id(), errors.New("unexpected write packet"))
|
||||
}
|
||||
|
||||
data, offset, _ := packetData(pkt, alloc, orderID)
|
||||
_, err := writer.WriteAt(data, offset)
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
|
||||
// wrap OpenFileWriter handler
|
||||
|
@ -312,7 +315,7 @@ func fileputget(h FileWriter, r *Request, pkt requestPacket, alloc *allocator, o
|
|||
writerReader := r.state.writerReaderAt
|
||||
r.state.RUnlock()
|
||||
if writerReader == nil {
|
||||
return statusFromError(pkt, errors.New("unexpected write and read packet"))
|
||||
return statusFromError(pkt.id(), errors.New("unexpected write and read packet"))
|
||||
}
|
||||
switch p := pkt.(type) {
|
||||
case *sshFxpReadPacket:
|
||||
|
@ -320,7 +323,7 @@ func fileputget(h FileWriter, r *Request, pkt requestPacket, alloc *allocator, o
|
|||
n, err := writerReader.ReadAt(data, offset)
|
||||
// only return EOF error if no data left to read
|
||||
if err != nil && (err != io.EOF || n == 0) {
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
return &sshFxpDataPacket{
|
||||
ID: pkt.id(),
|
||||
|
@ -330,9 +333,9 @@ func fileputget(h FileWriter, r *Request, pkt requestPacket, alloc *allocator, o
|
|||
case *sshFxpWritePacket:
|
||||
data, offset := p.Data, int64(p.Offset)
|
||||
_, err := writerReader.WriteAt(data, offset)
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
default:
|
||||
return statusFromError(pkt, errors.New("unexpected packet type for read or write"))
|
||||
return statusFromError(pkt.id(), errors.New("unexpected packet type for read or write"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,30 +361,30 @@ func filecmd(h FileCmder, r *Request, pkt requestPacket) responsePacket {
|
|||
if r.Method == "PosixRename" {
|
||||
if posixRenamer, ok := h.(PosixRenameFileCmder); ok {
|
||||
err := posixRenamer.PosixRename(r)
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
|
||||
// PosixRenameFileCmder not implemented handle this request as a Rename
|
||||
r.Method = "Rename"
|
||||
err := h.Filecmd(r)
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
|
||||
if r.Method == "StatVFS" {
|
||||
if statVFSCmdr, ok := h.(StatVFSFileCmder); ok {
|
||||
stat, err := statVFSCmdr.StatVFS(r)
|
||||
if err != nil {
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
stat.ID = pkt.id()
|
||||
return stat
|
||||
}
|
||||
|
||||
return statusFromError(pkt, ErrSSHFxOpUnsupported)
|
||||
return statusFromError(pkt.id(), ErrSSHFxOpUnsupported)
|
||||
}
|
||||
|
||||
err := h.Filecmd(r)
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
|
||||
// wrap FileLister handler
|
||||
|
@ -389,7 +392,7 @@ func filelist(h FileLister, r *Request, pkt requestPacket) responsePacket {
|
|||
var err error
|
||||
lister := r.getLister()
|
||||
if lister == nil {
|
||||
return statusFromError(pkt, errors.New("unexpected dir packet"))
|
||||
return statusFromError(pkt.id(), errors.New("unexpected dir packet"))
|
||||
}
|
||||
|
||||
offset := r.lsNext()
|
||||
|
@ -402,16 +405,16 @@ func filelist(h FileLister, r *Request, pkt requestPacket) responsePacket {
|
|||
switch r.Method {
|
||||
case "List":
|
||||
if err != nil && err != io.EOF {
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
if err == io.EOF && n == 0 {
|
||||
return statusFromError(pkt, io.EOF)
|
||||
return statusFromError(pkt.id(), io.EOF)
|
||||
}
|
||||
dirname := filepath.ToSlash(path.Base(r.Filepath))
|
||||
ret := &sshFxpNamePacket{ID: pkt.id()}
|
||||
|
||||
for _, fi := range finfo {
|
||||
ret.NameAttrs = append(ret.NameAttrs, sshFxpNameAttr{
|
||||
ret.NameAttrs = append(ret.NameAttrs, &sshFxpNameAttr{
|
||||
Name: fi.Name(),
|
||||
LongName: runLs(dirname, fi),
|
||||
Attrs: []interface{}{fi},
|
||||
|
@ -420,7 +423,7 @@ func filelist(h FileLister, r *Request, pkt requestPacket) responsePacket {
|
|||
return ret
|
||||
default:
|
||||
err = errors.Errorf("unexpected method: %s", r.Method)
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,7 +443,7 @@ func filestat(h FileLister, r *Request, pkt requestPacket) responsePacket {
|
|||
lister, err = h.Filelist(r)
|
||||
}
|
||||
if err != nil {
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
finfo := make([]os.FileInfo, 1)
|
||||
n, err := lister.ListAt(finfo, 0)
|
||||
|
@ -449,12 +452,12 @@ func filestat(h FileLister, r *Request, pkt requestPacket) responsePacket {
|
|||
switch r.Method {
|
||||
case "Stat", "Lstat":
|
||||
if err != nil && err != io.EOF {
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
if n == 0 {
|
||||
err = &os.PathError{Op: strings.ToLower(r.Method), Path: r.Filepath,
|
||||
Err: syscall.ENOENT}
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
return &sshFxpStatResponse{
|
||||
ID: pkt.id(),
|
||||
|
@ -462,25 +465,27 @@ func filestat(h FileLister, r *Request, pkt requestPacket) responsePacket {
|
|||
}
|
||||
case "Readlink":
|
||||
if err != nil && err != io.EOF {
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
if n == 0 {
|
||||
err = &os.PathError{Op: "readlink", Path: r.Filepath,
|
||||
Err: syscall.ENOENT}
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
filename := finfo[0].Name()
|
||||
return &sshFxpNamePacket{
|
||||
ID: pkt.id(),
|
||||
NameAttrs: []sshFxpNameAttr{{
|
||||
NameAttrs: []*sshFxpNameAttr{
|
||||
&sshFxpNameAttr{
|
||||
Name: filename,
|
||||
LongName: filename,
|
||||
Attrs: emptyFileStat,
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
default:
|
||||
err = errors.Errorf("unexpected method: %s", r.Method)
|
||||
return statusFromError(pkt, err)
|
||||
return statusFromError(pkt.id(), err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,11 +118,11 @@ func (h *Handlers) returnError(err error) {
|
|||
}
|
||||
|
||||
func getStatusMsg(p interface{}) string {
|
||||
pkt := p.(sshFxpStatusPacket)
|
||||
pkt := p.(*sshFxpStatusPacket)
|
||||
return pkt.StatusError.msg
|
||||
}
|
||||
func checkOkStatus(t *testing.T, p interface{}) {
|
||||
pkt := p.(sshFxpStatusPacket)
|
||||
pkt := p.(*sshFxpStatusPacket)
|
||||
assert.Equal(t, pkt.StatusError.Code, uint32(sshFxOk),
|
||||
"sshFxpStatusPacket not OK\n", pkt.StatusError.msg)
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ func TestRequestCustomError(t *testing.T) {
|
|||
cmdErr := errors.New("stat not supported")
|
||||
handlers.returnError(cmdErr)
|
||||
rpkt := request.call(handlers, pkt, nil, 0)
|
||||
assert.Equal(t, rpkt, statusFromError(rpkt, cmdErr))
|
||||
assert.Equal(t, rpkt, statusFromError(pkt.myid, cmdErr))
|
||||
}
|
||||
|
||||
// XXX can't just set method to Get, need to use Open to setup Get/Put
|
||||
|
@ -194,7 +194,7 @@ func TestRequestCmdr(t *testing.T) {
|
|||
|
||||
handlers.returnError(errTest)
|
||||
rpkt = request.call(handlers, pkt, nil, 0)
|
||||
assert.Equal(t, rpkt, statusFromError(rpkt, errTest))
|
||||
assert.Equal(t, rpkt, statusFromError(pkt.myid, errTest))
|
||||
}
|
||||
|
||||
func TestRequestInfoStat(t *testing.T) {
|
||||
|
@ -227,7 +227,7 @@ func TestRequestInfoReadlink(t *testing.T) {
|
|||
rpkt := request.call(handlers, pkt, nil, 0)
|
||||
npkt, ok := rpkt.(*sshFxpNamePacket)
|
||||
if assert.True(t, ok) {
|
||||
assert.IsType(t, sshFxpNameAttr{}, npkt.NameAttrs[0])
|
||||
assert.IsType(t, &sshFxpNameAttr{}, npkt.NameAttrs[0])
|
||||
assert.Equal(t, npkt.NameAttrs[0].Name, "request_test.go")
|
||||
}
|
||||
}
|
||||
|
|
108
server.go
108
server.go
|
@ -152,7 +152,7 @@ func (svr *Server) sftpServerWorker(pktChan chan orderedRequest) error {
|
|||
// return permission denied
|
||||
if !readonly && svr.readOnly {
|
||||
svr.pktMgr.readyPacket(
|
||||
svr.pktMgr.newOrderedResponse(statusFromError(pkt, syscall.EPERM), pkt.orderID()),
|
||||
svr.pktMgr.newOrderedResponse(statusFromError(pkt.id(), syscall.EPERM), pkt.orderID()),
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
@ -169,29 +169,29 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||
orderID := p.orderID()
|
||||
switch p := p.requestPacket.(type) {
|
||||
case *sshFxInitPacket:
|
||||
rpkt = sshFxVersionPacket{
|
||||
rpkt = &sshFxVersionPacket{
|
||||
Version: sftpProtocolVersion,
|
||||
Extensions: sftpExtensions,
|
||||
}
|
||||
case *sshFxpStatPacket:
|
||||
// stat the requested file
|
||||
info, err := os.Stat(p.Path)
|
||||
rpkt = sshFxpStatResponse{
|
||||
rpkt = &sshFxpStatResponse{
|
||||
ID: p.ID,
|
||||
info: info,
|
||||
}
|
||||
if err != nil {
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
}
|
||||
case *sshFxpLstatPacket:
|
||||
// stat the requested file
|
||||
info, err := os.Lstat(p.Path)
|
||||
rpkt = sshFxpStatResponse{
|
||||
rpkt = &sshFxpStatResponse{
|
||||
ID: p.ID,
|
||||
info: info,
|
||||
}
|
||||
if err != nil {
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
}
|
||||
case *sshFxpFstatPacket:
|
||||
f, ok := s.getHandle(p.Handle)
|
||||
|
@ -199,71 +199,75 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||
var info os.FileInfo
|
||||
if ok {
|
||||
info, err = f.Stat()
|
||||
rpkt = sshFxpStatResponse{
|
||||
rpkt = &sshFxpStatResponse{
|
||||
ID: p.ID,
|
||||
info: info,
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
}
|
||||
case *sshFxpMkdirPacket:
|
||||
// TODO FIXME: ignore flags field
|
||||
err := os.Mkdir(p.Path, 0755)
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
case *sshFxpRmdirPacket:
|
||||
err := os.Remove(p.Path)
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
case *sshFxpRemovePacket:
|
||||
err := os.Remove(p.Filename)
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
case *sshFxpRenamePacket:
|
||||
err := os.Rename(p.Oldpath, p.Newpath)
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
case *sshFxpSymlinkPacket:
|
||||
err := os.Symlink(p.Targetpath, p.Linkpath)
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
case *sshFxpClosePacket:
|
||||
rpkt = statusFromError(p, s.closeHandle(p.Handle))
|
||||
rpkt = statusFromError(p.ID, s.closeHandle(p.Handle))
|
||||
case *sshFxpReadlinkPacket:
|
||||
f, err := os.Readlink(p.Path)
|
||||
rpkt = sshFxpNamePacket{
|
||||
rpkt = &sshFxpNamePacket{
|
||||
ID: p.ID,
|
||||
NameAttrs: []sshFxpNameAttr{{
|
||||
NameAttrs: []*sshFxpNameAttr{
|
||||
&sshFxpNameAttr{
|
||||
Name: f,
|
||||
LongName: f,
|
||||
Attrs: emptyFileStat,
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err != nil {
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
}
|
||||
case *sshFxpRealpathPacket:
|
||||
f, err := filepath.Abs(p.Path)
|
||||
f = cleanPath(f)
|
||||
rpkt = sshFxpNamePacket{
|
||||
rpkt = &sshFxpNamePacket{
|
||||
ID: p.ID,
|
||||
NameAttrs: []sshFxpNameAttr{{
|
||||
NameAttrs: []*sshFxpNameAttr{
|
||||
&sshFxpNameAttr{
|
||||
Name: f,
|
||||
LongName: f,
|
||||
Attrs: emptyFileStat,
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err != nil {
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
}
|
||||
case *sshFxpOpendirPacket:
|
||||
if stat, err := os.Stat(p.Path); err != nil {
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
} else if !stat.IsDir() {
|
||||
rpkt = statusFromError(p, &os.PathError{
|
||||
rpkt = statusFromError(p.ID, &os.PathError{
|
||||
Path: p.Path, Err: syscall.ENOTDIR})
|
||||
} else {
|
||||
rpkt = sshFxpOpenPacket{
|
||||
rpkt = (&sshFxpOpenPacket{
|
||||
ID: p.ID,
|
||||
Path: p.Path,
|
||||
Pflags: sshFxfRead,
|
||||
}.respond(s)
|
||||
}).respond(s)
|
||||
}
|
||||
case *sshFxpReadPacket:
|
||||
var err error = EBADF
|
||||
|
@ -275,7 +279,7 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||
if _err != nil && (_err != io.EOF || n == 0) {
|
||||
err = _err
|
||||
}
|
||||
rpkt = sshFxpDataPacket{
|
||||
rpkt = &sshFxpDataPacket{
|
||||
ID: p.ID,
|
||||
Length: uint32(n),
|
||||
Data: data[:n],
|
||||
|
@ -283,7 +287,7 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||
}
|
||||
}
|
||||
if err != nil {
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
}
|
||||
|
||||
case *sshFxpWritePacket:
|
||||
|
@ -292,10 +296,10 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||
if ok {
|
||||
_, err = f.WriteAt(p.Data, int64(p.Offset))
|
||||
}
|
||||
rpkt = statusFromError(p, err)
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
case *sshFxpExtendedPacket:
|
||||
if p.SpecificPacket == nil {
|
||||
rpkt = statusFromError(p, ErrSSHFxOpUnsupported)
|
||||
rpkt = statusFromError(p.ID, ErrSSHFxOpUnsupported)
|
||||
} else {
|
||||
rpkt = p.respond(s)
|
||||
}
|
||||
|
@ -375,14 +379,14 @@ type ider interface {
|
|||
}
|
||||
|
||||
// The init packet has no ID, so we just return a zero-value ID
|
||||
func (p sshFxInitPacket) id() uint32 { return 0 }
|
||||
func (p *sshFxInitPacket) id() uint32 { return 0 }
|
||||
|
||||
type sshFxpStatResponse struct {
|
||||
ID uint32
|
||||
info os.FileInfo
|
||||
}
|
||||
|
||||
func (p sshFxpStatResponse) marshalPacket() ([]byte, []byte, error) {
|
||||
func (p *sshFxpStatResponse) marshalPacket() ([]byte, []byte, error) {
|
||||
l := 4 + 1 + 4 // uint32(length) + byte(type) + uint32(id)
|
||||
|
||||
b := make([]byte, 4, l)
|
||||
|
@ -395,18 +399,18 @@ func (p sshFxpStatResponse) marshalPacket() ([]byte, []byte, error) {
|
|||
return b, payload, nil
|
||||
}
|
||||
|
||||
func (p sshFxpStatResponse) MarshalBinary() ([]byte, error) {
|
||||
func (p *sshFxpStatResponse) MarshalBinary() ([]byte, error) {
|
||||
header, payload, err := p.marshalPacket()
|
||||
return append(header, payload...), err
|
||||
}
|
||||
|
||||
var emptyFileStat = []interface{}{uint32(0)}
|
||||
|
||||
func (p sshFxpOpenPacket) readonly() bool {
|
||||
func (p *sshFxpOpenPacket) readonly() bool {
|
||||
return !p.hasPflags(sshFxfWrite)
|
||||
}
|
||||
|
||||
func (p sshFxpOpenPacket) hasPflags(flags ...uint32) bool {
|
||||
func (p *sshFxpOpenPacket) hasPflags(flags ...uint32) bool {
|
||||
for _, f := range flags {
|
||||
if p.Pflags&f == 0 {
|
||||
return false
|
||||
|
@ -415,7 +419,7 @@ func (p sshFxpOpenPacket) hasPflags(flags ...uint32) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (p sshFxpOpenPacket) respond(svr *Server) responsePacket {
|
||||
func (p *sshFxpOpenPacket) respond(svr *Server) responsePacket {
|
||||
var osFlags int
|
||||
if p.hasPflags(sshFxfRead, sshFxfWrite) {
|
||||
osFlags |= os.O_RDWR
|
||||
|
@ -425,7 +429,7 @@ func (p sshFxpOpenPacket) respond(svr *Server) responsePacket {
|
|||
osFlags |= os.O_RDONLY
|
||||
} else {
|
||||
// how are they opening?
|
||||
return statusFromError(p, syscall.EINVAL)
|
||||
return statusFromError(p.ID, syscall.EINVAL)
|
||||
}
|
||||
|
||||
// Don't use O_APPEND flag as it conflicts with WriteAt.
|
||||
|
@ -443,28 +447,28 @@ func (p sshFxpOpenPacket) respond(svr *Server) responsePacket {
|
|||
|
||||
f, err := os.OpenFile(p.Path, osFlags, 0644)
|
||||
if err != nil {
|
||||
return statusFromError(p, err)
|
||||
return statusFromError(p.ID, err)
|
||||
}
|
||||
|
||||
handle := svr.nextHandle(f)
|
||||
return sshFxpHandlePacket{ID: p.id(), Handle: handle}
|
||||
return &sshFxpHandlePacket{ID: p.ID, Handle: handle}
|
||||
}
|
||||
|
||||
func (p sshFxpReaddirPacket) respond(svr *Server) responsePacket {
|
||||
func (p *sshFxpReaddirPacket) respond(svr *Server) responsePacket {
|
||||
f, ok := svr.getHandle(p.Handle)
|
||||
if !ok {
|
||||
return statusFromError(p, EBADF)
|
||||
return statusFromError(p.ID, EBADF)
|
||||
}
|
||||
|
||||
dirname := f.Name()
|
||||
dirents, err := f.Readdir(128)
|
||||
if err != nil {
|
||||
return statusFromError(p, err)
|
||||
return statusFromError(p.ID, err)
|
||||
}
|
||||
|
||||
ret := sshFxpNamePacket{ID: p.ID}
|
||||
ret := &sshFxpNamePacket{ID: p.ID}
|
||||
for _, dirent := range dirents {
|
||||
ret.NameAttrs = append(ret.NameAttrs, sshFxpNameAttr{
|
||||
ret.NameAttrs = append(ret.NameAttrs, &sshFxpNameAttr{
|
||||
Name: dirent.Name(),
|
||||
LongName: runLs(dirname, dirent),
|
||||
Attrs: []interface{}{dirent},
|
||||
|
@ -473,7 +477,7 @@ func (p sshFxpReaddirPacket) respond(svr *Server) responsePacket {
|
|||
return ret
|
||||
}
|
||||
|
||||
func (p sshFxpSetstatPacket) respond(svr *Server) responsePacket {
|
||||
func (p *sshFxpSetstatPacket) respond(svr *Server) responsePacket {
|
||||
// additional unmarshalling is required for each possibility here
|
||||
b := p.Attrs.([]byte)
|
||||
var err error
|
||||
|
@ -512,13 +516,13 @@ func (p sshFxpSetstatPacket) respond(svr *Server) responsePacket {
|
|||
}
|
||||
}
|
||||
|
||||
return statusFromError(p, err)
|
||||
return statusFromError(p.ID, err)
|
||||
}
|
||||
|
||||
func (p sshFxpFsetstatPacket) respond(svr *Server) responsePacket {
|
||||
func (p *sshFxpFsetstatPacket) respond(svr *Server) responsePacket {
|
||||
f, ok := svr.getHandle(p.Handle)
|
||||
if !ok {
|
||||
return statusFromError(p, EBADF)
|
||||
return statusFromError(p.ID, EBADF)
|
||||
}
|
||||
|
||||
// additional unmarshalling is required for each possibility here
|
||||
|
@ -559,12 +563,12 @@ func (p sshFxpFsetstatPacket) respond(svr *Server) responsePacket {
|
|||
}
|
||||
}
|
||||
|
||||
return statusFromError(p, err)
|
||||
return statusFromError(p.ID, err)
|
||||
}
|
||||
|
||||
func statusFromError(p ider, err error) sshFxpStatusPacket {
|
||||
ret := sshFxpStatusPacket{
|
||||
ID: p.id(),
|
||||
func statusFromError(id uint32, err error) *sshFxpStatusPacket {
|
||||
ret := &sshFxpStatusPacket{
|
||||
ID: id,
|
||||
StatusError: StatusError{
|
||||
// sshFXOk = 0
|
||||
// sshFXEOF = 1
|
||||
|
|
|
@ -9,21 +9,20 @@ import (
|
|||
"syscall"
|
||||
)
|
||||
|
||||
func (p sshFxpExtendedPacketStatVFS) respond(svr *Server) responsePacket {
|
||||
func (p *sshFxpExtendedPacketStatVFS) respond(svr *Server) responsePacket {
|
||||
retPkt, err := getStatVFSForPath(p.Path)
|
||||
if err != nil {
|
||||
return statusFromError(p, err)
|
||||
return statusFromError(p.ID, err)
|
||||
}
|
||||
retPkt.ID = p.ID
|
||||
|
||||
return retPkt
|
||||
}
|
||||
|
||||
func getStatVFSForPath(name string) (*StatVFS, error) {
|
||||
stat := &syscall.Statfs_t{}
|
||||
if err := syscall.Statfs(name, stat); err != nil {
|
||||
var stat syscall.Statfs_t
|
||||
if err := syscall.Statfs(name, &stat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return statvfsFromStatfst(stat)
|
||||
return statvfsFromStatfst(&stat)
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"syscall"
|
||||
)
|
||||
|
||||
func (p sshFxpExtendedPacketStatVFS) respond(svr *Server) responsePacket {
|
||||
return statusFromError(p, syscall.EPLAN9)
|
||||
func (p *sshFxpExtendedPacketStatVFS) respond(svr *Server) responsePacket {
|
||||
return statusFromError(p.ID, syscall.EPLAN9)
|
||||
}
|
||||
|
||||
func getStatVFSForPath(name string) (*StatVFS, error) {
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
"syscall"
|
||||
)
|
||||
|
||||
func (p sshFxpExtendedPacketStatVFS) respond(svr *Server) responsePacket {
|
||||
return statusFromError(p, syscall.ENOTSUP)
|
||||
func (p *sshFxpExtendedPacketStatVFS) respond(svr *Server) responsePacket {
|
||||
return statusFromError(p.ID, syscall.ENOTSUP)
|
||||
}
|
||||
|
||||
func getStatVFSForPath(name string) (*StatVFS, error) {
|
||||
|
|
|
@ -281,10 +281,10 @@ func TestConcurrentRequests(t *testing.T) {
|
|||
func TestStatusFromError(t *testing.T) {
|
||||
type test struct {
|
||||
err error
|
||||
pkt sshFxpStatusPacket
|
||||
pkt *sshFxpStatusPacket
|
||||
}
|
||||
tpkt := func(id, code uint32) sshFxpStatusPacket {
|
||||
return sshFxpStatusPacket{
|
||||
tpkt := func(id, code uint32) *sshFxpStatusPacket {
|
||||
return &sshFxpStatusPacket{
|
||||
ID: id,
|
||||
StatusError: StatusError{Code: code},
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ func TestStatusFromError(t *testing.T) {
|
|||
}
|
||||
for _, tc := range testCases {
|
||||
tc.pkt.StatusError.msg = tc.err.Error()
|
||||
assert.Equal(t, tc.pkt, statusFromError(tc.pkt, tc.err))
|
||||
assert.Equal(t, tc.pkt, statusFromError(tc.pkt.ID, tc.err))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,13 +327,13 @@ func TestOpenStatRace(t *testing.T) {
|
|||
pflags := flags(os.O_RDWR | os.O_CREATE | os.O_TRUNC)
|
||||
ch := make(chan result, 3)
|
||||
id1 := client.nextID()
|
||||
client.dispatchRequest(ch, sshFxpOpenPacket{
|
||||
client.dispatchRequest(ch, &sshFxpOpenPacket{
|
||||
ID: id1,
|
||||
Path: tmppath,
|
||||
Pflags: pflags,
|
||||
})
|
||||
id2 := client.nextID()
|
||||
client.dispatchRequest(ch, sshFxpLstatPacket{
|
||||
client.dispatchRequest(ch, &sshFxpLstatPacket{
|
||||
ID: id2,
|
||||
Path: tmppath,
|
||||
})
|
||||
|
@ -370,8 +370,8 @@ func TestStatNonExistent(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestServerWithBrokenClient(t *testing.T) {
|
||||
validInit := sp(sshFxInitPacket{Version: 3})
|
||||
brokenOpen := sp(sshFxpOpenPacket{Path: "foo"})
|
||||
validInit := sp(&sshFxInitPacket{Version: 3})
|
||||
brokenOpen := sp(&sshFxpOpenPacket{Path: "foo"})
|
||||
brokenOpen = brokenOpen[:len(brokenOpen)-2]
|
||||
|
||||
for _, clientInput := range [][]byte{
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
)
|
||||
|
||||
func TestErrFxCode(t *testing.T) {
|
||||
ider := sshFxpStatusPacket{ID: 1}
|
||||
table := []struct {
|
||||
err error
|
||||
fx fxerr
|
||||
|
@ -22,7 +21,7 @@ func TestErrFxCode(t *testing.T) {
|
|||
{err: io.EOF, fx: ErrSSHFxEOF},
|
||||
}
|
||||
for _, tt := range table {
|
||||
statusErr := statusFromError(ider, tt.err).StatusError
|
||||
statusErr := statusFromError(1, tt.err).StatusError
|
||||
assert.Equal(t, statusErr.FxCode(), tt.fx)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue