pointer receivers and statusFromError(uint32, error)

This commit is contained in:
Cassondra Foesch 2021-02-22 12:00:27 +00:00
parent 1d73fd92d5
commit 861a8eaf5c
14 changed files with 283 additions and 274 deletions

View File

@ -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,
})

View File

@ -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))
}

View File

@ -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
View File

@ -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)
}

View File

@ -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,

View File

@ -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,
}},
},
},
}
}

View File

@ -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)
}
}

View File

@ -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
View File

@ -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

View File

@ -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)
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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{

View File

@ -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)
}
}