added statvfs@openssh.com extension request

This commit is contained in:
Maximilian Pachl 2015-05-15 20:37:52 +02:00
parent 506297c901
commit 0b805e96f9
2 changed files with 82 additions and 0 deletions

View File

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

View File

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