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

SFTP: respect file open flags also for file creation

Signed-off-by: Nicola Murino <[email protected]>
Nicola Murino 3 жил өмнө
parent
commit
900e519ff1

+ 3 - 3
common/protocol_test.go

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

+ 2 - 2
go.mod

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

+ 4 - 5
go.sum

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

+ 1 - 1
sftpd/cryptfs_test.go

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

+ 4 - 3
sftpd/handler.go

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

+ 1 - 1
sftpd/internal_test.go

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

+ 4 - 4
sftpd/sftpd_test.go

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

+ 1 - 1
vfs/osfs.go

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

+ 3 - 0
vfs/sftpfs.go

@@ -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("[email protected]"); ok {
+		return fs.sftpClient.PosixRename(source, target)
+	}
 	return fs.sftpClient.Rename(source, target)
 }