mirror of https://github.com/pkg/sftp.git
request-server: add StatVFS support
This commit is contained in:
parent
1cc6c514bd
commit
5dbfeffd12
|
@ -266,6 +266,14 @@ func (fs *root) PosixRename(r *Request) error {
|
|||
return fs.rename(r.Filepath, r.Target)
|
||||
}
|
||||
|
||||
func (fs *root) StatVFS(r *Request) (*StatVFS, error) {
|
||||
if fs.mockErr != nil {
|
||||
return nil, fs.mockErr
|
||||
}
|
||||
|
||||
return getStatVFSForPath(r.Filepath)
|
||||
}
|
||||
|
||||
func (fs *root) mkdir(pathname string) error {
|
||||
dir := &memFile{
|
||||
modtime: time.Now(),
|
||||
|
|
|
@ -55,7 +55,7 @@ type FileCmder interface {
|
|||
Filecmd(*Request) error
|
||||
}
|
||||
|
||||
// PosixRenameFileCmder is a FileCmder that implements the Lstat method.
|
||||
// PosixRenameFileCmder is a FileCmder that implements the PosixRename method.
|
||||
// If this interface is implemented PosixRename requests will call it
|
||||
// otherwise they will be handled in the same way as Rename
|
||||
type PosixRenameFileCmder interface {
|
||||
|
@ -63,6 +63,14 @@ type PosixRenameFileCmder interface {
|
|||
PosixRename(*Request) error
|
||||
}
|
||||
|
||||
// StatVFSFileCmder is a FileCmder that implements the StatVFS method.
|
||||
// You need to implement this interface if you want to handle statvfs requests.
|
||||
// Please also be sure that the statvfs@openssh.com extension is enabled
|
||||
type StatVFSFileCmder interface {
|
||||
FileCmder
|
||||
StatVFS(*Request) (*StatVFS, error)
|
||||
}
|
||||
|
||||
// FileLister should return an object that fulfils the ListerAt interface
|
||||
// Note in cases of an error, the error text will be sent to the client.
|
||||
// Called for Methods: List, Stat, Readlink
|
||||
|
|
|
@ -237,6 +237,9 @@ func (rs *RequestServer) packetWorker(
|
|||
request := NewRequest("PosixRename", pkt.Oldpath)
|
||||
request.Target = pkt.Newpath
|
||||
rpkt = request.call(rs.Handlers, pkt, rs.pktMgr.alloc, orderID)
|
||||
case *sshFxpExtendedPacketStatVFS:
|
||||
request := NewRequest("StatVFS", pkt.Path)
|
||||
rpkt = request.call(rs.Handlers, pkt, rs.pktMgr.alloc, orderID)
|
||||
case hasHandle:
|
||||
handle := pkt.getHandle()
|
||||
request, ok := rs.getRequest(handle)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -725,6 +726,27 @@ func TestRequestReaddir(t *testing.T) {
|
|||
checkRequestServerAllocator(t, p)
|
||||
}
|
||||
|
||||
func TestRequestStatVFS(t *testing.T) {
|
||||
if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
|
||||
t.Skip("StatVFS is implemented on linux and darwin")
|
||||
}
|
||||
|
||||
p := clientRequestServerPair(t)
|
||||
defer p.Close()
|
||||
|
||||
_, ok := p.cli.HasExtension("statvfs@openssh.com")
|
||||
require.True(t, ok, "request server doesn't list statvfs extension")
|
||||
vfs, err := p.cli.StatVFS("/")
|
||||
require.NoError(t, err)
|
||||
expected, err := getStatVFSForPath("/")
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, 0, expected.ID)
|
||||
// check some stats
|
||||
require.Equal(t, expected.Bavail, vfs.Bavail)
|
||||
require.Equal(t, expected.Bfree, vfs.Bfree)
|
||||
require.Equal(t, expected.Blocks, vfs.Blocks)
|
||||
}
|
||||
|
||||
func TestCleanDisconnect(t *testing.T) {
|
||||
p := clientRequestServerPair(t)
|
||||
defer p.Close()
|
||||
|
|
15
request.go
15
request.go
|
@ -212,7 +212,7 @@ func (r *Request) call(handlers Handlers, pkt requestPacket, alloc *allocator, o
|
|||
return fileput(handlers.FilePut, r, pkt, alloc, orderID)
|
||||
case "Open":
|
||||
return fileputget(handlers.FilePut, r, pkt, alloc, orderID)
|
||||
case "Setstat", "Rename", "Rmdir", "Mkdir", "Link", "Symlink", "Remove", "PosixRename":
|
||||
case "Setstat", "Rename", "Rmdir", "Mkdir", "Link", "Symlink", "Remove", "PosixRename", "StatVFS":
|
||||
return filecmd(handlers.FileCmd, r, pkt)
|
||||
case "List":
|
||||
return filelist(handlers.FileList, r, pkt)
|
||||
|
@ -371,6 +371,19 @@ func filecmd(h FileCmder, r *Request, pkt requestPacket) responsePacket {
|
|||
return statusFromError(pkt, err)
|
||||
}
|
||||
|
||||
if r.Method == "StatVFS" {
|
||||
if statVFSCmdr, ok := h.(StatVFSFileCmder); ok {
|
||||
stat, err := statVFSCmdr.StatVFS(r)
|
||||
if err != nil {
|
||||
return statusFromError(pkt, err)
|
||||
}
|
||||
stat.ID = pkt.id()
|
||||
return stat
|
||||
}
|
||||
|
||||
return statusFromError(pkt, ErrSSHFxOpUnsupported)
|
||||
}
|
||||
|
||||
err := h.Filecmd(r)
|
||||
return statusFromError(pkt, err)
|
||||
}
|
||||
|
|
|
@ -10,12 +10,7 @@ import (
|
|||
)
|
||||
|
||||
func (p sshFxpExtendedPacketStatVFS) respond(svr *Server) responsePacket {
|
||||
stat := &syscall.Statfs_t{}
|
||||
if err := syscall.Statfs(p.Path, stat); err != nil {
|
||||
return statusFromError(p, err)
|
||||
}
|
||||
|
||||
retPkt, err := statvfsFromStatfst(stat)
|
||||
retPkt, err := getStatVFSForPath(p.Path)
|
||||
if err != nil {
|
||||
return statusFromError(p, err)
|
||||
}
|
||||
|
@ -23,3 +18,12 @@ func (p sshFxpExtendedPacketStatVFS) respond(svr *Server) responsePacket {
|
|||
|
||||
return retPkt
|
||||
}
|
||||
|
||||
func getStatVFSForPath(name string) (*StatVFS, error) {
|
||||
stat := &syscall.Statfs_t{}
|
||||
if err := syscall.Statfs(name, stat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return statvfsFromStatfst(stat)
|
||||
}
|
||||
|
|
|
@ -7,3 +7,7 @@ import (
|
|||
func (p sshFxpExtendedPacketStatVFS) respond(svr *Server) responsePacket {
|
||||
return statusFromError(p, syscall.EPLAN9)
|
||||
}
|
||||
|
||||
func getStatVFSForPath(name string) (*StatVFS, error) {
|
||||
return nil, syscall.EPLAN9
|
||||
}
|
||||
|
|
|
@ -9,3 +9,7 @@ import (
|
|||
func (p sshFxpExtendedPacketStatVFS) respond(svr *Server) responsePacket {
|
||||
return statusFromError(p, syscall.ENOTSUP)
|
||||
}
|
||||
|
||||
func getStatVFSForPath(name string) (*StatVFS, error) {
|
||||
return nil, syscall.ENOTSUP
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue