sftpd statvfs: check the virtual quota against that of the filesystem

if the virtual quota limit is greater than the filesystem available space,
we need to return the filesystem limits

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino 2022-05-14 14:53:26 +02:00
parent 67abf03fe3
commit d2f4edcdb6
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
3 changed files with 21 additions and 17 deletions

View file

@ -131,6 +131,9 @@ func TestMain(m *testing.M) {
}
}()
waitTCPListening(sftpdConf.Bindings[0].GetAddress())
waitTCPListening(httpdConf.Bindings[0].GetAddress())
go func() {
// start a test HTTP server to receive action notifications
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
@ -180,9 +183,6 @@ func TestMain(m *testing.M) {
waitTCPListening(httpProxyAddr)
waitTCPListening(smtpServerAddr)
waitTCPListening(sftpdConf.Bindings[0].GetAddress())
waitTCPListening(httpdConf.Bindings[0].GetAddress())
exitCode := m.Run()
os.Remove(logFilePath)
os.Exit(exitCode)

View file

@ -284,20 +284,20 @@ func (c *Connection) StatVFS(r *sftp.Request) (*sftp.StatVFS, error) {
}
if !quotaResult.HasSpace {
return c.getStatVFSFromQuotaResult(fs, p, quotaResult), nil
return c.getStatVFSFromQuotaResult(fs, p, quotaResult)
}
if quotaResult.QuotaSize == 0 && quotaResult.QuotaFiles == 0 {
// no quota restrictions
statvfs, err := fs.GetAvailableDiskSize(p)
if err == vfs.ErrStorageSizeUnavailable {
return c.getStatVFSFromQuotaResult(fs, p, quotaResult), nil
return c.getStatVFSFromQuotaResult(fs, p, quotaResult)
}
return statvfs, err
}
// there is free space but some limits are configured
return c.getStatVFSFromQuotaResult(fs, p, quotaResult), nil
return c.getStatVFSFromQuotaResult(fs, p, quotaResult)
}
func (c *Connection) canReadLink(name string) error {
@ -477,17 +477,17 @@ func (c *Connection) Disconnect() error {
return c.channel.Close()
}
func (c *Connection) getStatVFSFromQuotaResult(fs vfs.Fs, name string, quotaResult vfs.QuotaCheckResult) *sftp.StatVFS {
if quotaResult.QuotaSize == 0 || quotaResult.QuotaFiles == 0 {
func (c *Connection) getStatVFSFromQuotaResult(fs vfs.Fs, name string, quotaResult vfs.QuotaCheckResult) (*sftp.StatVFS, error) {
s, err := fs.GetAvailableDiskSize(name)
if err == nil {
if quotaResult.QuotaSize == 0 {
if quotaResult.QuotaSize == 0 || quotaResult.QuotaSize > int64(s.TotalSpace()) {
quotaResult.QuotaSize = int64(s.TotalSpace())
}
if quotaResult.QuotaFiles == 0 {
if quotaResult.QuotaFiles == 0 || quotaResult.QuotaFiles > int(s.Files) {
quotaResult.QuotaFiles = int(s.Files)
}
}
} else if err != vfs.ErrStorageSizeUnavailable {
return nil, err
}
// if we are unable to get quota size or quota files we add some arbitrary values
if quotaResult.QuotaSize == 0 {
@ -520,7 +520,7 @@ func (c *Connection) getStatVFSFromQuotaResult(fs vfs.Fs, name string, quotaResu
Ffree: ffree,
Favail: ffree,
Namemax: 255,
}
}, nil
}
func getOSOpenFlags(requestFlags sftp.FileOpenFlags) (flags int) {

View file

@ -8221,6 +8221,10 @@ func TestStatVFS(t *testing.T) {
err = os.Remove(testFilePath)
assert.NoError(t, err)
_, err = client.StatVFS("missing-path")
assert.Error(t, err)
assert.ErrorIs(t, err, fs.ErrNotExist)
stat, err := client.StatVFS("/")
assert.NoError(t, err)
assert.Greater(t, stat.ID, uint32(0))