SFTP: respect file open flags also for file creation

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino 2022-02-16 16:05:56 +01:00
parent f1832d4478
commit 900e519ff1
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
9 changed files with 23 additions and 20 deletions

View file

@ -661,7 +661,7 @@ func TestTruncateQuotaLimits(t *testing.T) {
if assert.NoError(t, err) {
defer conn.Close()
defer client.Close()
f, err := client.OpenFile(testFileName, os.O_WRONLY)
f, err := client.OpenFile(testFileName, os.O_WRONLY|os.O_CREATE)
if assert.NoError(t, err) {
n, err := f.Write(testFileContent)
assert.NoError(t, err)
@ -779,7 +779,7 @@ func TestTruncateQuotaLimits(t *testing.T) {
if user.Username == defaultUsername {
// basic test inside a virtual folder
vfileName1 := path.Join(vdirPath1, testFileName)
f, err = client.OpenFile(vfileName1, os.O_WRONLY)
f, err = client.OpenFile(vfileName1, os.O_WRONLY|os.O_CREATE)
if assert.NoError(t, err) {
n, err := f.Write(testFileContent)
assert.NoError(t, err)
@ -808,7 +808,7 @@ func TestTruncateQuotaLimits(t *testing.T) {
assert.Equal(t, 1, fold.UsedQuotaFiles)
// now test on vdirPath2, the folder quota is included in the user's quota
vfileName2 := path.Join(vdirPath2, testFileName)
f, err = client.OpenFile(vfileName2, os.O_WRONLY)
f, err = client.OpenFile(vfileName2, os.O_WRONLY|os.O_CREATE)
if assert.NoError(t, err) {
n, err := f.Write(testFileContent)
assert.NoError(t, err)

4
go.mod
View file

@ -58,7 +58,7 @@ require (
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
golang.org/x/sys v0.0.0-20220209214540-3681064d5158
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
google.golang.org/api v0.68.0
google.golang.org/api v0.69.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0
)
@ -127,7 +127,7 @@ require (
golang.org/x/tools v0.1.9 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220211171837-173942840c17 // indirect
google.golang.org/genproto v0.0.0-20220215190005-e57b466719ef // indirect
google.golang.org/grpc v1.44.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect

9
go.sum
View file

@ -950,7 +950,6 @@ golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -1085,8 +1084,8 @@ google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tD
google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM=
google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M=
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
google.golang.org/api v0.68.0 h1:9eJiHhwJKIYX6sX2fUZxQLi7pDRA/MYu8c12q6WbJik=
google.golang.org/api v0.68.0/go.mod h1:sOM8pTpwgflXRhz+oC8H2Dr+UcbMqkPPWNJo88Q7TH8=
google.golang.org/api v0.69.0 h1:yHW5s2SFyDapr/43kYtIQmoaaFVW4baLMLwqV4auj2A=
google.golang.org/api v0.69.0/go.mod h1:boanBiw+h5c3s+tBPgEzLDRHfFLWV0qXxRHz3ws7C80=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -1173,10 +1172,10 @@ google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ6
google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220204002441-d6cc3cc0770e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220211171837-173942840c17 h1:2X+CNIheCutWRyKRte8szGxrE5ggtV4U+NKAbh/oLhg=
google.golang.org/genproto v0.0.0-20220211171837-173942840c17/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220215190005-e57b466719ef h1:LgGaJzny+/at3jTXZUNh/l8VBWyAiskCHrwq6iEYE7I=
google.golang.org/genproto v0.0.0-20220215190005-e57b466719ef/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=

View file

@ -349,7 +349,7 @@ func TestTruncate(t *testing.T) {
if assert.NoError(t, err) {
defer conn.Close()
defer client.Close()
f, err := client.OpenFile(testFileName, os.O_WRONLY)
f, err := client.OpenFile(testFileName, os.O_WRONLY|os.O_CREATE)
if assert.NoError(t, err) {
err = f.Truncate(0)
assert.NoError(t, err)

View file

@ -141,7 +141,7 @@ func (c *Connection) handleFilewrite(request *sftp.Request) (sftp.WriterAtReader
if !c.User.HasPerm(dataprovider.PermUpload, path.Dir(request.Filepath)) {
return nil, sftp.ErrSSHFxPermissionDenied
}
return c.handleSFTPUploadToNewFile(fs, p, filePath, request.Filepath, errForRead)
return c.handleSFTPUploadToNewFile(fs, request.Pflags(), p, filePath, request.Filepath, errForRead)
}
if statErr != nil {
@ -345,7 +345,7 @@ func (c *Connection) handleSFTPRemove(request *sftp.Request) error {
return c.RemoveFile(fs, fsPath, request.Filepath, fi)
}
func (c *Connection) handleSFTPUploadToNewFile(fs vfs.Fs, resolvedPath, filePath, requestPath string, errForRead error) (sftp.WriterAtReaderAt, error) {
func (c *Connection) handleSFTPUploadToNewFile(fs vfs.Fs, pflags sftp.FileOpenFlags, resolvedPath, filePath, requestPath string, errForRead error) (sftp.WriterAtReaderAt, error) {
diskQuota, transferQuota := c.HasSpace(true, false, requestPath)
if !diskQuota.HasSpace || !transferQuota.HasUploadSpace() {
c.Log(logger.LevelInfo, "denying file write due to quota limits")
@ -357,7 +357,8 @@ func (c *Connection) handleSFTPUploadToNewFile(fs vfs.Fs, resolvedPath, filePath
return nil, c.GetPermissionDeniedError()
}
file, w, cancelFn, err := fs.Create(filePath, 0)
osFlags := getOSOpenFlags(pflags)
file, w, cancelFn, err := fs.Create(filePath, osFlags)
if err != nil {
c.Log(logger.LevelError, "error creating file %#v: %+v", resolvedPath, err)
return nil, c.GetFsError(fs, err)

View file

@ -309,7 +309,7 @@ func TestUploadFiles(t *testing.T) {
if runtime.GOOS == osWindows {
missingFile = "missing\\relative\\file.txt"
}
_, err = c.handleSFTPUploadToNewFile(fs, ".", missingFile, "/missing", nil)
_, err = c.handleSFTPUploadToNewFile(fs, flags, ".", missingFile, "/missing", nil)
assert.Error(t, err, "upload new file in missing path must fail")
fs = newMockOsFs(nil, nil, false, "123", os.TempDir())

View file

@ -568,12 +568,12 @@ func TestFolderPrefix(t *testing.T) {
assert.Equal(t, "files", contents[0].Name())
}
}
_, err = client.OpenFile(testFileName, os.O_WRONLY)
_, err = client.OpenFile(testFileName, os.O_WRONLY|os.O_CREATE)
assert.ErrorIs(t, err, os.ErrPermission)
_, err = client.OpenFile(testFileName, os.O_RDONLY)
assert.ErrorIs(t, err, os.ErrPermission)
f, err := client.OpenFile(path.Join("prefix", "files", testFileName), os.O_WRONLY)
f, err := client.OpenFile(path.Join("prefix", "files", testFileName), os.O_WRONLY|os.O_CREATE)
assert.NoError(t, err)
_, err = f.Write([]byte("test"))
assert.NoError(t, err)
@ -4930,7 +4930,7 @@ func TestTruncateQuotaLimits(t *testing.T) {
defer conn.Close()
defer client.Close()
data := []byte("test data")
f, err := client.OpenFile(testFileName, os.O_WRONLY)
f, err := client.OpenFile(testFileName, os.O_WRONLY|os.O_CREATE)
if assert.NoError(t, err) {
n, err := f.Write(data)
assert.NoError(t, err)
@ -5048,7 +5048,7 @@ func TestTruncateQuotaLimits(t *testing.T) {
if user.Username == defaultUsername {
// basic test inside a virtual folder
vfileName := path.Join(vdirPath, testFileName)
f, err = client.OpenFile(vfileName, os.O_WRONLY)
f, err = client.OpenFile(vfileName, os.O_WRONLY|os.O_CREATE)
if assert.NoError(t, err) {
n, err := f.Write(data)
assert.NoError(t, err)

View file

@ -93,7 +93,7 @@ func (*OsFs) Create(name string, flag int) (File, *PipeWriter, func(), error) {
if flag == 0 {
f, err = os.Create(name)
} else {
f, err = os.OpenFile(name, flag, os.ModePerm)
f, err = os.OpenFile(name, flag, 0666)
}
return f, nil, nil, err
}

View file

@ -324,6 +324,9 @@ func (fs *SFTPFs) Rename(source, target string) error {
if err := fs.checkConnection(); err != nil {
return err
}
if _, ok := fs.sftpClient.HasExtension("posix-rename@openssh.com"); ok {
return fs.sftpClient.PosixRename(source, target)
}
return fs.sftpClient.Rename(source, target)
}