forked from Deuxfleurs/bagage
256 lines
8.5 KiB
Go
256 lines
8.5 KiB
Go
package openssh
|
||
|
||
import (
|
||
sshfx "github.com/pkg/sftp/internal/encoding/ssh/filexfer"
|
||
)
|
||
|
||
const extensionStatVFS = "statvfs@openssh.com"
|
||
|
||
// RegisterExtensionStatVFS registers the "statvfs@openssh.com" extended packet with the encoding/ssh/filexfer package.
|
||
func RegisterExtensionStatVFS() {
|
||
sshfx.RegisterExtendedPacketType(extensionStatVFS, func() sshfx.ExtendedData {
|
||
return new(StatVFSExtendedPacket)
|
||
})
|
||
}
|
||
|
||
// ExtensionStatVFS returns an ExtensionPair suitable to append into an sshfx.InitPacket or sshfx.VersionPacket.
|
||
func ExtensionStatVFS() *sshfx.ExtensionPair {
|
||
return &sshfx.ExtensionPair{
|
||
Name: extensionStatVFS,
|
||
Data: "2",
|
||
}
|
||
}
|
||
|
||
// StatVFSExtendedPacket defines the statvfs@openssh.com extend packet.
|
||
type StatVFSExtendedPacket struct {
|
||
Path string
|
||
}
|
||
|
||
// Type returns the SSH_FXP_EXTENDED packet type.
|
||
func (ep *StatVFSExtendedPacket) Type() sshfx.PacketType {
|
||
return sshfx.PacketTypeExtended
|
||
}
|
||
|
||
// MarshalPacket returns ep as a two-part binary encoding of the full extended packet.
|
||
func (ep *StatVFSExtendedPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||
p := &sshfx.ExtendedPacket{
|
||
ExtendedRequest: extensionStatVFS,
|
||
|
||
Data: ep,
|
||
}
|
||
return p.MarshalPacket(reqid, b)
|
||
}
|
||
|
||
// MarshalInto encodes ep into the binary encoding of the statvfs@openssh.com extended packet-specific data.
|
||
func (ep *StatVFSExtendedPacket) MarshalInto(buf *sshfx.Buffer) {
|
||
buf.AppendString(ep.Path)
|
||
}
|
||
|
||
// MarshalBinary encodes ep into the binary encoding of the statvfs@openssh.com extended packet-specific data.
|
||
//
|
||
// NOTE: This _only_ encodes the packet-specific data, it does not encode the full extended packet.
|
||
func (ep *StatVFSExtendedPacket) MarshalBinary() ([]byte, error) {
|
||
size := 4 + len(ep.Path) // string(path)
|
||
|
||
buf := sshfx.NewBuffer(make([]byte, 0, size))
|
||
|
||
ep.MarshalInto(buf)
|
||
|
||
return buf.Bytes(), nil
|
||
}
|
||
|
||
// UnmarshalFrom decodes the statvfs@openssh.com extended packet-specific data into ep.
|
||
func (ep *StatVFSExtendedPacket) UnmarshalFrom(buf *sshfx.Buffer) (err error) {
|
||
if ep.Path, err = buf.ConsumeString(); err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// UnmarshalBinary decodes the statvfs@openssh.com extended packet-specific data into ep.
|
||
func (ep *StatVFSExtendedPacket) UnmarshalBinary(data []byte) (err error) {
|
||
return ep.UnmarshalFrom(sshfx.NewBuffer(data))
|
||
}
|
||
|
||
const extensionFStatVFS = "fstatvfs@openssh.com"
|
||
|
||
// RegisterExtensionFStatVFS registers the "fstatvfs@openssh.com" extended packet with the encoding/ssh/filexfer package.
|
||
func RegisterExtensionFStatVFS() {
|
||
sshfx.RegisterExtendedPacketType(extensionFStatVFS, func() sshfx.ExtendedData {
|
||
return new(FStatVFSExtendedPacket)
|
||
})
|
||
}
|
||
|
||
// ExtensionFStatVFS returns an ExtensionPair suitable to append into an sshfx.InitPacket or sshfx.VersionPacket.
|
||
func ExtensionFStatVFS() *sshfx.ExtensionPair {
|
||
return &sshfx.ExtensionPair{
|
||
Name: extensionFStatVFS,
|
||
Data: "2",
|
||
}
|
||
}
|
||
|
||
// FStatVFSExtendedPacket defines the fstatvfs@openssh.com extend packet.
|
||
type FStatVFSExtendedPacket struct {
|
||
Path string
|
||
}
|
||
|
||
// Type returns the SSH_FXP_EXTENDED packet type.
|
||
func (ep *FStatVFSExtendedPacket) Type() sshfx.PacketType {
|
||
return sshfx.PacketTypeExtended
|
||
}
|
||
|
||
// MarshalPacket returns ep as a two-part binary encoding of the full extended packet.
|
||
func (ep *FStatVFSExtendedPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||
p := &sshfx.ExtendedPacket{
|
||
ExtendedRequest: extensionFStatVFS,
|
||
|
||
Data: ep,
|
||
}
|
||
return p.MarshalPacket(reqid, b)
|
||
}
|
||
|
||
// MarshalInto encodes ep into the binary encoding of the statvfs@openssh.com extended packet-specific data.
|
||
func (ep *FStatVFSExtendedPacket) MarshalInto(buf *sshfx.Buffer) {
|
||
buf.AppendString(ep.Path)
|
||
}
|
||
|
||
// MarshalBinary encodes ep into the binary encoding of the statvfs@openssh.com extended packet-specific data.
|
||
//
|
||
// NOTE: This _only_ encodes the packet-specific data, it does not encode the full extended packet.
|
||
func (ep *FStatVFSExtendedPacket) MarshalBinary() ([]byte, error) {
|
||
size := 4 + len(ep.Path) // string(path)
|
||
|
||
buf := sshfx.NewBuffer(make([]byte, 0, size))
|
||
|
||
ep.MarshalInto(buf)
|
||
|
||
return buf.Bytes(), nil
|
||
}
|
||
|
||
// UnmarshalFrom decodes the statvfs@openssh.com extended packet-specific data into ep.
|
||
func (ep *FStatVFSExtendedPacket) UnmarshalFrom(buf *sshfx.Buffer) (err error) {
|
||
if ep.Path, err = buf.ConsumeString(); err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// UnmarshalBinary decodes the statvfs@openssh.com extended packet-specific data into ep.
|
||
func (ep *FStatVFSExtendedPacket) UnmarshalBinary(data []byte) (err error) {
|
||
return ep.UnmarshalFrom(sshfx.NewBuffer(data))
|
||
}
|
||
|
||
// The values for the MountFlags field.
|
||
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL
|
||
const (
|
||
MountFlagsReadOnly = 0x1 // SSH_FXE_STATVFS_ST_RDONLY
|
||
MountFlagsNoSUID = 0x2 // SSH_FXE_STATVFS_ST_NOSUID
|
||
)
|
||
|
||
// StatVFSExtendedReplyPacket defines the extended reply packet for statvfs@openssh.com and fstatvfs@openssh.com requests.
|
||
type StatVFSExtendedReplyPacket struct {
|
||
BlockSize uint64 /* f_bsize: file system block size */
|
||
FragmentSize uint64 /* f_frsize: fundamental fs block size / fagment size */
|
||
Blocks uint64 /* f_blocks: number of blocks (unit f_frsize) */
|
||
BlocksFree uint64 /* f_bfree: free blocks in filesystem */
|
||
BlocksAvail uint64 /* f_bavail: free blocks for non-root */
|
||
Files uint64 /* f_files: total file inodes */
|
||
FilesFree uint64 /* f_ffree: free file inodes */
|
||
FilesAvail uint64 /* f_favail: free file inodes for to non-root */
|
||
FilesystemID uint64 /* f_fsid: file system id */
|
||
MountFlags uint64 /* f_flag: bit mask of mount flag values */
|
||
MaxNameLength uint64 /* f_namemax: maximum filename length */
|
||
}
|
||
|
||
// Type returns the SSH_FXP_EXTENDED_REPLY packet type.
|
||
func (ep *StatVFSExtendedReplyPacket) Type() sshfx.PacketType {
|
||
return sshfx.PacketTypeExtendedReply
|
||
}
|
||
|
||
// MarshalPacket returns ep as a two-part binary encoding of the full extended reply packet.
|
||
func (ep *StatVFSExtendedReplyPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||
p := &sshfx.ExtendedReplyPacket{
|
||
Data: ep,
|
||
}
|
||
return p.MarshalPacket(reqid, b)
|
||
}
|
||
|
||
// UnmarshalPacketBody returns ep as a two-part binary encoding of the full extended reply packet.
|
||
func (ep *StatVFSExtendedReplyPacket) UnmarshalPacketBody(buf *sshfx.Buffer) (err error) {
|
||
p := &sshfx.ExtendedReplyPacket{
|
||
Data: ep,
|
||
}
|
||
return p.UnmarshalPacketBody(buf)
|
||
}
|
||
|
||
// MarshalInto encodes ep into the binary encoding of the (f)statvfs@openssh.com extended reply packet-specific data.
|
||
func (ep *StatVFSExtendedReplyPacket) MarshalInto(buf *sshfx.Buffer) {
|
||
buf.AppendUint64(ep.BlockSize)
|
||
buf.AppendUint64(ep.FragmentSize)
|
||
buf.AppendUint64(ep.Blocks)
|
||
buf.AppendUint64(ep.BlocksFree)
|
||
buf.AppendUint64(ep.BlocksAvail)
|
||
buf.AppendUint64(ep.Files)
|
||
buf.AppendUint64(ep.FilesFree)
|
||
buf.AppendUint64(ep.FilesAvail)
|
||
buf.AppendUint64(ep.FilesystemID)
|
||
buf.AppendUint64(ep.MountFlags)
|
||
buf.AppendUint64(ep.MaxNameLength)
|
||
}
|
||
|
||
// MarshalBinary encodes ep into the binary encoding of the (f)statvfs@openssh.com extended reply packet-specific data.
|
||
//
|
||
// NOTE: This _only_ encodes the packet-specific data, it does not encode the full extended reply packet.
|
||
func (ep *StatVFSExtendedReplyPacket) MarshalBinary() ([]byte, error) {
|
||
size := 11 * 8 // 11 × uint64(various)
|
||
|
||
b := sshfx.NewBuffer(make([]byte, 0, size))
|
||
ep.MarshalInto(b)
|
||
return b.Bytes(), nil
|
||
}
|
||
|
||
// UnmarshalFrom decodes the fstatvfs@openssh.com extended reply packet-specific data into ep.
|
||
func (ep *StatVFSExtendedReplyPacket) UnmarshalFrom(buf *sshfx.Buffer) (err error) {
|
||
if ep.BlockSize, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
if ep.FragmentSize, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
if ep.Blocks, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
if ep.BlocksFree, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
if ep.BlocksAvail, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
if ep.Files, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
if ep.FilesFree, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
if ep.FilesAvail, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
if ep.FilesystemID, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
if ep.MountFlags, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
if ep.MaxNameLength, err = buf.ConsumeUint64(); err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// UnmarshalBinary decodes the fstatvfs@openssh.com extended reply packet-specific data into ep.
|
||
func (ep *StatVFSExtendedReplyPacket) UnmarshalBinary(data []byte) (err error) {
|
||
return ep.UnmarshalFrom(sshfx.NewBuffer(data))
|
||
}
|