request-server: add StatVFS support

This commit is contained in:
Nicola Murino 2021-02-10 19:13:19 +01:00
parent 1cc6c514bd
commit 5dbfeffd12
9 changed files with 75 additions and 8 deletions

View File

@ -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(),

View File

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

View File

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

View File

@ -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()

View File

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

View File

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

View File

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

View File

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

View File

@ -90,6 +90,7 @@ var (
supportedSFTPExtensions = []sshExtensionPair{
{"hardlink@openssh.com", "1"},
{"posix-rename@openssh.com", "1"},
{"statvfs@openssh.com", "2"},
}
sftpExtensions = supportedSFTPExtensions
)