osfs: add optional buffering

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino
2023-05-16 18:08:14 +02:00
parent e10487ad57
commit adad8e658b
32 changed files with 895 additions and 170 deletions

View File

@@ -282,7 +282,7 @@ func (f *webDavFile) updateTransferQuotaOnSeek() {
}
func (f *webDavFile) checkFile() error {
if f.File == nil && vfs.IsLocalOrUnbufferedSFTPFs(f.Fs) {
if f.File == nil && vfs.FsOpenReturnsFile(f.Fs) {
file, _, _, err := f.Fs.Open(f.GetFsPath(), 0)
if err != nil {
f.Connection.Log(logger.LevelWarn, "could not open file %q for seeking: %v",

View File

@@ -327,7 +327,7 @@ func (fs *MockOsFs) GetMimeType(_ string) (string, error) {
func newMockOsFs(atomicUpload bool, connectionID, rootDir string, reader *pipeat.PipeReaderAt, err error) vfs.Fs {
return &MockOsFs{
Fs: vfs.NewOsFs(connectionID, rootDir, ""),
Fs: vfs.NewOsFs(connectionID, rootDir, "", nil),
isAtomicUploadSupported: atomicUpload,
reader: reader,
err: err,
@@ -484,7 +484,7 @@ func TestResolvePathErrors(t *testing.T) {
}
user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("connID", user.HomeDir, "")
fs := vfs.NewOsFs("connID", user.HomeDir, "", nil)
connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
}
@@ -517,7 +517,7 @@ func TestResolvePathErrors(t *testing.T) {
if runtime.GOOS != "windows" {
user.HomeDir = filepath.Clean(os.TempDir())
connection.User = user
fs := vfs.NewOsFs("connID", connection.User.HomeDir, "")
fs := vfs.NewOsFs("connID", connection.User.HomeDir, "", nil)
subDir := "sub"
testTxtFile := "file.txt"
err = os.MkdirAll(filepath.Join(os.TempDir(), subDir, subDir), os.ModePerm)
@@ -555,7 +555,7 @@ func TestFileAccessErrors(t *testing.T) {
}
user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("connID", user.HomeDir, "")
fs := vfs.NewOsFs("connID", user.HomeDir, "", nil)
connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
}
@@ -648,7 +648,7 @@ func TestCheckRequestMethodWithPrefix(t *testing.T) {
},
},
}
fs := vfs.NewOsFs("connID", user.HomeDir, "")
fs := vfs.NewOsFs("connID", user.HomeDir, "", nil)
connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
}
@@ -672,7 +672,7 @@ func TestContentType(t *testing.T) {
}
user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("connID", user.HomeDir, "")
fs := vfs.NewOsFs("connID", user.HomeDir, "", nil)
connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
}
@@ -699,7 +699,7 @@ func TestContentType(t *testing.T) {
baseTransfer = common.NewBaseTransfer(nil, connection.BaseConnection, nil, testFilePath, testFilePath, testFile+".unknown1",
common.TransferDownload, 0, 0, 0, 0, false, fs, dataprovider.TransferQuota{})
davFile = newWebDavFile(baseTransfer, nil, nil)
davFile.Fs = vfs.NewOsFs("id", user.HomeDir, "")
davFile.Fs = vfs.NewOsFs("id", user.HomeDir, "", nil)
fi, err = davFile.Stat()
if assert.NoError(t, err) {
ctype, err := fi.(*webDavFileInfo).ContentType(ctx)
@@ -712,7 +712,7 @@ func TestContentType(t *testing.T) {
baseTransfer = common.NewBaseTransfer(nil, connection.BaseConnection, nil, testFilePath, testFilePath, testFile,
common.TransferDownload, 0, 0, 0, 0, false, fs, dataprovider.TransferQuota{})
davFile = newWebDavFile(baseTransfer, nil, nil)
davFile.Fs = vfs.NewOsFs("id", user.HomeDir, "")
davFile.Fs = vfs.NewOsFs("id", user.HomeDir, "", nil)
fi, err = davFile.Stat()
if assert.NoError(t, err) {
ctype, err := fi.(*webDavFileInfo).ContentType(ctx)
@@ -727,7 +727,7 @@ func TestContentType(t *testing.T) {
baseTransfer = common.NewBaseTransfer(nil, connection.BaseConnection, nil, testFilePath, testFilePath, testFile+".custom",
common.TransferDownload, 0, 0, 0, 0, false, fs, dataprovider.TransferQuota{})
davFile = newWebDavFile(baseTransfer, nil, nil)
davFile.Fs = vfs.NewOsFs("id", user.HomeDir, "")
davFile.Fs = vfs.NewOsFs("id", user.HomeDir, "", nil)
fi, err = davFile.Stat()
if assert.NoError(t, err) {
ctype, err := fi.(*webDavFileInfo).ContentType(ctx)
@@ -781,7 +781,7 @@ func TestTransferReadWriteErrors(t *testing.T) {
}
user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("connID", user.HomeDir, "")
fs := vfs.NewOsFs("connID", user.HomeDir, "", nil)
connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
}
@@ -937,7 +937,7 @@ func TestTransferSeek(t *testing.T) {
assert.True(t, fs.IsNotExist(err))
davFile.Connection.RemoveTransfer(davFile.BaseTransfer)
fs = vfs.NewOsFs(fs.ConnectionID(), user.GetHomeDir(), "")
fs = vfs.NewOsFs(fs.ConnectionID(), user.GetHomeDir(), "", nil)
baseTransfer = common.NewBaseTransfer(nil, connection.BaseConnection, nil, testFilePath+"1", testFilePath+"1", testFile,
common.TransferDownload, 0, 0, 0, 0, false, fs, dataprovider.TransferQuota{AllowedTotalSize: 100})
davFile = newWebDavFile(baseTransfer, nil, nil)

View File

@@ -52,6 +52,7 @@ import (
"github.com/drakkan/sftpgo/v2/internal/kms"
"github.com/drakkan/sftpgo/v2/internal/logger"
"github.com/drakkan/sftpgo/v2/internal/sftpd"
"github.com/drakkan/sftpgo/v2/internal/util"
"github.com/drakkan/sftpgo/v2/internal/vfs"
"github.com/drakkan/sftpgo/v2/internal/webdavd"
)
@@ -720,6 +721,70 @@ func TestBasicHandlingCryptFs(t *testing.T) {
1*time.Second, 100*time.Millisecond)
}
func TestBufferedUser(t *testing.T) {
u := getTestUser()
u.FsConfig.OSConfig = sdk.OSFsConfig{
WriteBufferSize: 2,
ReadBufferSize: 1,
}
vdirPath := "/crypted"
mappedPath := filepath.Join(os.TempDir(), util.GenerateUniqueID())
folderName := filepath.Base(mappedPath)
u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
BaseVirtualFolder: vfs.BaseVirtualFolder{
Name: folderName,
MappedPath: mappedPath,
FsConfig: vfs.Filesystem{
Provider: sdk.CryptedFilesystemProvider,
CryptConfig: vfs.CryptFsConfig{
OSFsConfig: sdk.OSFsConfig{
WriteBufferSize: 3,
ReadBufferSize: 2,
},
Passphrase: kms.NewPlainSecret(defaultPassword),
},
},
},
VirtualPath: vdirPath,
QuotaFiles: -1,
QuotaSize: -1,
})
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
assert.NoError(t, err)
client := getWebDavClient(user, false, nil)
assert.NoError(t, checkBasicFunc(client))
testFilePath := filepath.Join(homeBasePath, testFileName)
testFileSize := int64(65535)
err = createTestFile(testFilePath, testFileSize)
assert.NoError(t, err)
err = uploadFileWithRawClient(testFilePath, testFileName,
user.Username, defaultPassword, false, testFileSize, client)
assert.NoError(t, err)
err = uploadFileWithRawClient(testFilePath, path.Join(vdirPath, testFileName),
user.Username, defaultPassword, false, testFileSize, client)
assert.NoError(t, err)
localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
assert.NoError(t, err)
err = downloadFile(path.Join(vdirPath, testFileName), localDownloadPath, testFileSize, client)
assert.NoError(t, err)
err = os.Remove(testFilePath)
assert.NoError(t, err)
err = os.Remove(localDownloadPath)
assert.NoError(t, err)
_, err = httpdtest.RemoveUser(user, http.StatusOK)
assert.NoError(t, err)
err = os.RemoveAll(user.GetHomeDir())
assert.NoError(t, err)
_, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
assert.NoError(t, err)
err = os.RemoveAll(mappedPath)
assert.NoError(t, err)
}
func TestLoginEmptyPassword(t *testing.T) {
u := getTestUser()
u.Password = ""
@@ -1497,7 +1562,7 @@ func TestMaxConnections(t *testing.T) {
client := getWebDavClient(user, true, nil)
assert.NoError(t, checkBasicFunc(client))
// now add a fake connection
fs := vfs.NewOsFs("id", os.TempDir(), "")
fs := vfs.NewOsFs("id", os.TempDir(), "", nil)
connection := &webdavd.Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
}
@@ -1576,7 +1641,7 @@ func TestMaxSessions(t *testing.T) {
client := getWebDavClient(user, false, nil)
assert.NoError(t, checkBasicFunc(client))
// now add a fake connection
fs := vfs.NewOsFs("id", os.TempDir(), "")
fs := vfs.NewOsFs("id", os.TempDir(), "", nil)
connection := &webdavd.Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
}