diff --git a/internal/common/connection.go b/internal/common/connection.go index 5f1b7630f..31b1ed7ff 100644 --- a/internal/common/connection.go +++ b/internal/common/connection.go @@ -1675,7 +1675,8 @@ func (c *BaseConnection) GetGenericError(err error) error { return sftp.ErrSSHFxFailure default: if err == ErrPermissionDenied || err == ErrNotExist || err == ErrOpUnsupported || - err == ErrQuotaExceeded || err == vfs.ErrStorageSizeUnavailable || err == ErrShuttingDown { + err == ErrQuotaExceeded || err == ErrReadQuotaExceeded || err == vfs.ErrStorageSizeUnavailable || + err == ErrShuttingDown { return err } c.Log(logger.LevelError, "generic error: %+v", err) diff --git a/internal/common/transfer.go b/internal/common/transfer.go index 46ed8e990..0a0a7cbb7 100644 --- a/internal/common/transfer.go +++ b/internal/common/transfer.go @@ -211,6 +211,18 @@ func (t *BaseTransfer) SetCancelFn(cancelFn func()) { t.cancelFn = cancelFn } +// ConvertError accepts an error that occurs during a read or write and +// converts it into a more understandable form for the client if it is a +// well-known type of error +func (t *BaseTransfer) ConvertError(err error) error { + if t.Fs.IsNotExist(err) { + return t.Connection.GetNotExistError() + } else if t.Fs.IsPermission(err) { + return t.Connection.GetPermissionDeniedError() + } + return err +} + // CheckRead returns an error if read if not allowed func (t *BaseTransfer) CheckRead() error { if t.transferQuota.AllowedDLSize == 0 && t.transferQuota.AllowedTotalSize == 0 { diff --git a/internal/common/transfer_test.go b/internal/common/transfer_test.go index dd9b508f2..dcd2eac53 100644 --- a/internal/common/transfer_test.go +++ b/internal/common/transfer_test.go @@ -21,6 +21,7 @@ import ( "testing" "time" + "github.com/pkg/sftp" "github.com/sftpgo/sdk" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -225,6 +226,10 @@ func TestTransferErrors(t *testing.T) { conn := NewBaseConnection("id", ProtocolSFTP, "", "", u) transfer := NewBaseTransfer(file, conn, nil, testFile, testFile, "/transfer_test_file", TransferUpload, 0, 0, 0, 0, true, fs, dataprovider.TransferQuota{}) + err = transfer.ConvertError(os.ErrNotExist) + assert.ErrorIs(t, err, sftp.ErrSSHFxNoSuchFile) + err = transfer.ConvertError(os.ErrPermission) + assert.ErrorIs(t, err, sftp.ErrSSHFxPermissionDenied) assert.Nil(t, transfer.cancelFn) assert.Equal(t, testFile, transfer.GetFsPath()) transfer.SetCancelFn(cancelFn) diff --git a/internal/ftpd/transfer.go b/internal/ftpd/transfer.go index a41dc8005..3bc62b655 100644 --- a/internal/ftpd/transfer.go +++ b/internal/ftpd/transfer.go @@ -67,6 +67,7 @@ func (t *transfer) Read(p []byte) (n int, err error) { } if err != nil && err != io.EOF { t.TransferError(err) + err = t.ConvertError(err) return } t.HandleThrottle() @@ -85,6 +86,7 @@ func (t *transfer) Write(p []byte) (n int, err error) { } if err != nil { t.TransferError(err) + err = t.ConvertError(err) return } t.HandleThrottle() diff --git a/internal/httpd/file.go b/internal/httpd/file.go index f3ec0b205..ba428de9d 100644 --- a/internal/httpd/file.go +++ b/internal/httpd/file.go @@ -67,6 +67,7 @@ func (f *httpdFile) Read(p []byte) (n int, err error) { } if err != nil && err != io.EOF { f.TransferError(err) + err = f.ConvertError(err) return } f.HandleThrottle() @@ -91,6 +92,7 @@ func (f *httpdFile) Write(p []byte) (n int, err error) { } if err != nil { f.TransferError(err) + err = f.ConvertError(err) return } f.HandleThrottle() diff --git a/internal/sftpd/transfer.go b/internal/sftpd/transfer.go index b9139d00a..1919d574c 100644 --- a/internal/sftpd/transfer.go +++ b/internal/sftpd/transfer.go @@ -115,6 +115,7 @@ func (t *transfer) ReadAt(p []byte, off int64) (n int, err error) { if t.GetType() == common.TransferDownload { t.TransferError(err) } + err = t.ConvertError(err) return } t.HandleThrottle() @@ -139,6 +140,7 @@ func (t *transfer) WriteAt(p []byte, off int64) (n int, err error) { } if err != nil { t.TransferError(err) + err = t.ConvertError(err) return } t.HandleThrottle() diff --git a/internal/webdavd/file.go b/internal/webdavd/file.go index 5e6fd88f5..a82a9c56e 100644 --- a/internal/webdavd/file.go +++ b/internal/webdavd/file.go @@ -145,7 +145,7 @@ func (f *webDavFile) Stat() (os.FileInfo, error) { } info, err := f.Fs.Stat(f.GetFsPath()) if err != nil { - return nil, err + return nil, f.Connection.GetFsError(f.Fs, err) } if vfs.IsCryptOsFs(f.Fs) { info = f.Fs.(*vfs.CryptFs).ConvertFileInfo(info) @@ -216,7 +216,7 @@ func (f *webDavFile) Read(p []byte) (n int, err error) { f.startOffset = 0 f.Unlock() if e != nil { - return 0, e + return 0, f.Connection.GetFsError(f.Fs, e) } } @@ -227,6 +227,7 @@ func (f *webDavFile) Read(p []byte) (n int, err error) { } if err != nil && err != io.EOF { f.TransferError(err) + err = f.ConvertError(err) return } f.HandleThrottle() @@ -249,6 +250,7 @@ func (f *webDavFile) Write(p []byte) (n int, err error) { } if err != nil { f.TransferError(err) + err = f.ConvertError(err) return } f.HandleThrottle()