mirror of https://github.com/pkg/sftp.git
added statvfs@openssh.com extension request
This commit is contained in:
parent
506297c901
commit
0b805e96f9
40
client.go
40
client.go
|
@ -7,6 +7,9 @@ import (
|
|||
"path"
|
||||
"sync"
|
||||
"time"
|
||||
"encoding/binary"
|
||||
"bytes"
|
||||
"errors"
|
||||
|
||||
"github.com/kr/fs"
|
||||
|
||||
|
@ -420,6 +423,43 @@ func (c *Client) fstat(handle string) (*FileStat, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Get vfs stats from remote host.
|
||||
// Implementing statvfs@openssh.com SSH_FXP_EXTENDED feature
|
||||
// from http://www.opensource.apple.com/source/OpenSSH/OpenSSH-175/openssh/PROTOCOL?txt
|
||||
func (c *Client) StatVFS(path string) (*StatVFS, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
// send the StatVFS packet to the server
|
||||
id := c.nextId()
|
||||
typ, data, err := c.sendRequest(sshFxpStatvfsPacket{
|
||||
Id: id,
|
||||
Path: path,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch typ {
|
||||
// server responded with valid data
|
||||
case ssh_FXP_EXTENDED_REPLY:
|
||||
var response StatVFS
|
||||
err = binary.Read(bytes.NewReader(data), binary.BigEndian, &response)
|
||||
if err != nil {
|
||||
return nil, errors.New("can not parse reply")
|
||||
}
|
||||
|
||||
return &response, nil
|
||||
|
||||
// the resquest failed
|
||||
case ssh_FXP_STATUS:
|
||||
return nil, errors.New("statvfs@openssh.com failure")
|
||||
|
||||
default:
|
||||
return nil, unimplementedPacketErr(typ)
|
||||
}
|
||||
}
|
||||
|
||||
// Join joins any number of path elements into a single path, adding a
|
||||
// separating slash if necessary. The result is Cleaned; in particular, all
|
||||
// empty strings are ignored.
|
||||
|
|
42
packet.go
42
packet.go
|
@ -329,3 +329,45 @@ func (p sshFxpSetstatPacket) MarshalBinary() ([]byte, error) {
|
|||
b = marshal(b, p.Attrs)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
type sshFxpStatvfsPacket struct {
|
||||
Id uint32
|
||||
Path string
|
||||
}
|
||||
|
||||
func (p sshFxpStatvfsPacket) MarshalBinary() ([]byte, error) {
|
||||
l := 1 + 4 + // type(byte) + uint32
|
||||
len(p.Path) +
|
||||
len("statvfs@openssh.com")
|
||||
|
||||
|
||||
b := make([]byte, 0, l)
|
||||
b = append(b, ssh_FXP_EXTENDED)
|
||||
b = marshalUint32(b, p.Id)
|
||||
b = marshalString(b, "statvfs@openssh.com")
|
||||
b = marshalString(b, p.Path)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
type StatVFS struct {
|
||||
Id uint32
|
||||
Bsize uint64 /* file system block size */
|
||||
Frsize uint64 /* fundamental fs block size */
|
||||
Blocks uint64 /* number of blocks (unit f_frsize) */
|
||||
Bfree uint64 /* free blocks in file system */
|
||||
Bavail uint64 /* free blocks for non-root */
|
||||
Files uint64 /* total file inodes */
|
||||
Ffree uint64 /* free file inodes */
|
||||
Favail uint64 /* free file inodes for to non-root */
|
||||
Fsid uint64 /* file system id */
|
||||
Flag uint64 /* bit mask of f_flag values */
|
||||
Namemax uint64 /* maximum filename length */
|
||||
}
|
||||
|
||||
func (p *StatVFS) TotalSpace() uint64 {
|
||||
return p.Frsize * p.Blocks
|
||||
}
|
||||
|
||||
func (p *StatVFS) FreeSpace() uint64 {
|
||||
return p.Frsize * p.Bfree
|
||||
}
|
Loading…
Reference in New Issue