1
0
Эх сурвалжийг харах

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 <[email protected]>
Nicola Murino 3 жил өмнө
parent
commit
d2f4edcdb6

+ 3 - 3
common/protocol_test.go

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

+ 14 - 14
sftpd/handler.go

@@ -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 {
-		s, err := fs.GetAvailableDiskSize(name)
-		if err == nil {
-			if quotaResult.QuotaSize == 0 {
-				quotaResult.QuotaSize = int64(s.TotalSpace())
-			}
-			if quotaResult.QuotaFiles == 0 {
-				quotaResult.QuotaFiles = int(s.Files)
-			}
+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 || quotaResult.QuotaSize > int64(s.TotalSpace()) {
+			quotaResult.QuotaSize = int64(s.TotalSpace())
+		}
+		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) {

+ 4 - 0
sftpd/sftpd_test.go

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