mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-07 23:00:55 +03:00
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:
@@ -131,6 +131,9 @@ func TestMain(m *testing.M) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
waitTCPListening(sftpdConf.Bindings[0].GetAddress())
|
||||||
|
waitTCPListening(httpdConf.Bindings[0].GetAddress())
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// start a test HTTP server to receive action notifications
|
// start a test HTTP server to receive action notifications
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -180,9 +183,6 @@ func TestMain(m *testing.M) {
|
|||||||
waitTCPListening(httpProxyAddr)
|
waitTCPListening(httpProxyAddr)
|
||||||
waitTCPListening(smtpServerAddr)
|
waitTCPListening(smtpServerAddr)
|
||||||
|
|
||||||
waitTCPListening(sftpdConf.Bindings[0].GetAddress())
|
|
||||||
waitTCPListening(httpdConf.Bindings[0].GetAddress())
|
|
||||||
|
|
||||||
exitCode := m.Run()
|
exitCode := m.Run()
|
||||||
os.Remove(logFilePath)
|
os.Remove(logFilePath)
|
||||||
os.Exit(exitCode)
|
os.Exit(exitCode)
|
||||||
|
|||||||
@@ -284,20 +284,20 @@ func (c *Connection) StatVFS(r *sftp.Request) (*sftp.StatVFS, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !quotaResult.HasSpace {
|
if !quotaResult.HasSpace {
|
||||||
return c.getStatVFSFromQuotaResult(fs, p, quotaResult), nil
|
return c.getStatVFSFromQuotaResult(fs, p, quotaResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
if quotaResult.QuotaSize == 0 && quotaResult.QuotaFiles == 0 {
|
if quotaResult.QuotaSize == 0 && quotaResult.QuotaFiles == 0 {
|
||||||
// no quota restrictions
|
// no quota restrictions
|
||||||
statvfs, err := fs.GetAvailableDiskSize(p)
|
statvfs, err := fs.GetAvailableDiskSize(p)
|
||||||
if err == vfs.ErrStorageSizeUnavailable {
|
if err == vfs.ErrStorageSizeUnavailable {
|
||||||
return c.getStatVFSFromQuotaResult(fs, p, quotaResult), nil
|
return c.getStatVFSFromQuotaResult(fs, p, quotaResult)
|
||||||
}
|
}
|
||||||
return statvfs, err
|
return statvfs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// there is free space but some limits are configured
|
// 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 {
|
func (c *Connection) canReadLink(name string) error {
|
||||||
@@ -477,17 +477,17 @@ func (c *Connection) Disconnect() error {
|
|||||||
return c.channel.Close()
|
return c.channel.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Connection) getStatVFSFromQuotaResult(fs vfs.Fs, name string, quotaResult vfs.QuotaCheckResult) *sftp.StatVFS {
|
func (c *Connection) getStatVFSFromQuotaResult(fs vfs.Fs, name string, quotaResult vfs.QuotaCheckResult) (*sftp.StatVFS, error) {
|
||||||
if quotaResult.QuotaSize == 0 || quotaResult.QuotaFiles == 0 {
|
s, err := fs.GetAvailableDiskSize(name)
|
||||||
s, err := fs.GetAvailableDiskSize(name)
|
if err == nil {
|
||||||
if err == nil {
|
if quotaResult.QuotaSize == 0 || quotaResult.QuotaSize > int64(s.TotalSpace()) {
|
||||||
if quotaResult.QuotaSize == 0 {
|
quotaResult.QuotaSize = int64(s.TotalSpace())
|
||||||
quotaResult.QuotaSize = int64(s.TotalSpace())
|
|
||||||
}
|
|
||||||
if quotaResult.QuotaFiles == 0 {
|
|
||||||
quotaResult.QuotaFiles = int(s.Files)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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 we are unable to get quota size or quota files we add some arbitrary values
|
||||||
if quotaResult.QuotaSize == 0 {
|
if quotaResult.QuotaSize == 0 {
|
||||||
@@ -520,7 +520,7 @@ func (c *Connection) getStatVFSFromQuotaResult(fs vfs.Fs, name string, quotaResu
|
|||||||
Ffree: ffree,
|
Ffree: ffree,
|
||||||
Favail: ffree,
|
Favail: ffree,
|
||||||
Namemax: 255,
|
Namemax: 255,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getOSOpenFlags(requestFlags sftp.FileOpenFlags) (flags int) {
|
func getOSOpenFlags(requestFlags sftp.FileOpenFlags) (flags int) {
|
||||||
|
|||||||
@@ -8221,6 +8221,10 @@ func TestStatVFS(t *testing.T) {
|
|||||||
err = os.Remove(testFilePath)
|
err = os.Remove(testFilePath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = client.StatVFS("missing-path")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.ErrorIs(t, err, fs.ErrNotExist)
|
||||||
|
|
||||||
stat, err := client.StatVFS("/")
|
stat, err := client.StatVFS("/")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Greater(t, stat.ID, uint32(0))
|
assert.Greater(t, stat.ID, uint32(0))
|
||||||
|
|||||||
Reference in New Issue
Block a user