136 lines
4.3 KiB
Go
136 lines
4.3 KiB
Go
|
package sftp
|
||
|
|
||
|
import (
|
||
|
"encoding"
|
||
|
"fmt"
|
||
|
)
|
||
|
|
||
|
// all incoming packets
|
||
|
type requestPacket interface {
|
||
|
encoding.BinaryUnmarshaler
|
||
|
id() uint32
|
||
|
}
|
||
|
|
||
|
type responsePacket interface {
|
||
|
encoding.BinaryMarshaler
|
||
|
id() uint32
|
||
|
}
|
||
|
|
||
|
// interfaces to group types
|
||
|
type hasPath interface {
|
||
|
requestPacket
|
||
|
getPath() string
|
||
|
}
|
||
|
|
||
|
type hasHandle interface {
|
||
|
requestPacket
|
||
|
getHandle() string
|
||
|
}
|
||
|
|
||
|
type notReadOnly interface {
|
||
|
notReadOnly()
|
||
|
}
|
||
|
|
||
|
//// 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 *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 }
|
||
|
|
||
|
// 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 }
|
||
|
|
||
|
// take raw incoming packet data and build packet objects
|
||
|
func makePacket(p rxPacket) (requestPacket, error) {
|
||
|
var pkt requestPacket
|
||
|
switch p.pktType {
|
||
|
case sshFxpInit:
|
||
|
pkt = &sshFxInitPacket{}
|
||
|
case sshFxpLstat:
|
||
|
pkt = &sshFxpLstatPacket{}
|
||
|
case sshFxpOpen:
|
||
|
pkt = &sshFxpOpenPacket{}
|
||
|
case sshFxpClose:
|
||
|
pkt = &sshFxpClosePacket{}
|
||
|
case sshFxpRead:
|
||
|
pkt = &sshFxpReadPacket{}
|
||
|
case sshFxpWrite:
|
||
|
pkt = &sshFxpWritePacket{}
|
||
|
case sshFxpFstat:
|
||
|
pkt = &sshFxpFstatPacket{}
|
||
|
case sshFxpSetstat:
|
||
|
pkt = &sshFxpSetstatPacket{}
|
||
|
case sshFxpFsetstat:
|
||
|
pkt = &sshFxpFsetstatPacket{}
|
||
|
case sshFxpOpendir:
|
||
|
pkt = &sshFxpOpendirPacket{}
|
||
|
case sshFxpReaddir:
|
||
|
pkt = &sshFxpReaddirPacket{}
|
||
|
case sshFxpRemove:
|
||
|
pkt = &sshFxpRemovePacket{}
|
||
|
case sshFxpMkdir:
|
||
|
pkt = &sshFxpMkdirPacket{}
|
||
|
case sshFxpRmdir:
|
||
|
pkt = &sshFxpRmdirPacket{}
|
||
|
case sshFxpRealpath:
|
||
|
pkt = &sshFxpRealpathPacket{}
|
||
|
case sshFxpStat:
|
||
|
pkt = &sshFxpStatPacket{}
|
||
|
case sshFxpRename:
|
||
|
pkt = &sshFxpRenamePacket{}
|
||
|
case sshFxpReadlink:
|
||
|
pkt = &sshFxpReadlinkPacket{}
|
||
|
case sshFxpSymlink:
|
||
|
pkt = &sshFxpSymlinkPacket{}
|
||
|
case sshFxpExtended:
|
||
|
pkt = &sshFxpExtendedPacket{}
|
||
|
default:
|
||
|
return nil, fmt.Errorf("unhandled packet type: %s", p.pktType)
|
||
|
}
|
||
|
if err := pkt.UnmarshalBinary(p.pktBytes); err != nil {
|
||
|
// Return partially unpacked packet to allow callers to return
|
||
|
// error messages appropriately with necessary id() method.
|
||
|
return pkt, err
|
||
|
}
|
||
|
return pkt, nil
|
||
|
}
|