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