diff --git a/common/connection.go b/common/connection.go index 2ac4d77f..57956cdc 100644 --- a/common/connection.go +++ b/common/connection.go @@ -260,7 +260,7 @@ func (c *BaseConnection) RemoveFile(fsPath, virtualPath string, info os.FileInfo } logger.CommandLog(removeLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1) - if info.Mode()&os.ModeSymlink != os.ModeSymlink { + if info.Mode()&os.ModeSymlink == 0 { vfolder, err := c.User.GetVirtualFolderForPath(path.Dir(virtualPath)) if err == nil { dataprovider.UpdateVirtualFolderQuota(vfolder.BaseVirtualFolder, -1, -size, false) //nolint:errcheck @@ -318,7 +318,7 @@ func (c *BaseConnection) RemoveDir(fsPath, virtualPath string) error { c.Log(logger.LevelWarn, "failed to remove a dir %#v: stat error: %+v", fsPath, err) return c.GetFsError(err) } - if !fi.IsDir() || fi.Mode()&os.ModeSymlink == os.ModeSymlink { + if !fi.IsDir() || fi.Mode()&os.ModeSymlink != 0 { c.Log(logger.LevelDebug, "cannot remove %#v is not a directory", fsPath) return c.GetGenericError(nil) } @@ -638,7 +638,7 @@ func (c *BaseConnection) isRenamePermitted(fsSourcePath, virtualSourcePath, virt if fi != nil { if fi.IsDir() { return c.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(virtualTargetPath)) - } else if fi.Mode()&os.ModeSymlink == os.ModeSymlink { + } else if fi.Mode()&os.ModeSymlink != 0 { return c.User.HasPerm(dataprovider.PermCreateSymlinks, path.Dir(virtualTargetPath)) } } diff --git a/common/connection_test.go b/common/connection_test.go index 50857e52..2ab0f5f0 100644 --- a/common/connection_test.go +++ b/common/connection_test.go @@ -806,7 +806,7 @@ func TestRenamePermission(t *testing.T) { } info, err = os.Lstat(tmpDirLink) if assert.NoError(t, err) { - assert.True(t, info.Mode()&os.ModeSymlink == os.ModeSymlink) + assert.True(t, info.Mode()&os.ModeSymlink != 0) // the source is a symlink and the target has createDirs and upload perm assert.False(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info)) } diff --git a/common/transfer.go b/common/transfer.go index 80bd6ac3..246f4736 100644 --- a/common/transfer.go +++ b/common/transfer.go @@ -23,7 +23,7 @@ var ( type BaseTransfer struct { //nolint:maligned ID uint64 Fs vfs.Fs - File *os.File + File vfs.File Connection *BaseConnection cancelFn func() fsPath string @@ -42,7 +42,7 @@ type BaseTransfer struct { //nolint:maligned } // NewBaseTransfer returns a new BaseTransfer and adds it to the given connection -func NewBaseTransfer(file *os.File, conn *BaseConnection, cancelFn func(), fsPath, requestPath string, transferType int, +func NewBaseTransfer(file vfs.File, conn *BaseConnection, cancelFn func(), fsPath, requestPath string, transferType int, minWriteOffset, initialSize, maxWriteSize int64, isNewFile bool, fs vfs.Fs) *BaseTransfer { t := &BaseTransfer{ ID: conn.GetTransferID(), diff --git a/ftpd/handler.go b/ftpd/handler.go index e51fbbd5..36e7efcf 100644 --- a/ftpd/handler.go +++ b/ftpd/handler.go @@ -99,7 +99,7 @@ func (c *Connection) Remove(name string) error { return c.GetFsError(err) } - if fi.IsDir() && fi.Mode()&os.ModeSymlink != os.ModeSymlink { + if fi.IsDir() && fi.Mode()&os.ModeSymlink == 0 { c.Log(logger.LevelDebug, "cannot remove %#v is not a file/symlink", p) return c.GetGenericError(nil) } @@ -307,7 +307,7 @@ func (c *Connection) uploadFile(fsPath, ftpPath string, flags int) (ftpserver.Fi } stat, statErr := c.Fs.Lstat(fsPath) - if (statErr == nil && stat.Mode()&os.ModeSymlink == os.ModeSymlink) || c.Fs.IsNotExist(statErr) { + if (statErr == nil && stat.Mode()&os.ModeSymlink != 0) || c.Fs.IsNotExist(statErr) { if !c.User.HasPerm(dataprovider.PermUpload, path.Dir(ftpPath)) { return nil, c.GetPermissionDeniedError() } diff --git a/go.mod b/go.mod index 3df7ca07..3e1ecb6b 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Azure/azure-storage-blob-go v0.11.0 github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 github.com/alexedwards/argon2id v0.0.0-20200802152012-2464efd3196b - github.com/aws/aws-sdk-go v1.35.28 + github.com/aws/aws-sdk-go v1.35.29 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect github.com/eikenb/pipeat v0.0.0-20200430215831-470df5986b6d github.com/fclairamb/ftpserverlib v0.9.1-0.20201105003045-1edd6bf7ae53 @@ -21,7 +21,7 @@ require ( github.com/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126 github.com/lib/pq v1.8.0 github.com/magiconair/properties v1.8.4 // indirect - github.com/mattn/go-sqlite3 v1.14.4 + github.com/mattn/go-sqlite3 v1.14.5 github.com/miekg/dns v1.1.35 // indirect github.com/mitchellh/mapstructure v1.3.3 // indirect github.com/otiai10/copy v1.2.0 @@ -43,14 +43,14 @@ require ( github.com/studio-b12/gowebdav v0.0.0-20200929080739-bdacfab94796 go.etcd.io/bbolt v1.3.5 go.uber.org/automaxprocs v1.3.0 - golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 + golang.org/x/crypto v0.0.0-20201116153603-4be66e5b6582 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 // indirect - golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba - golang.org/x/tools v0.0.0-20201116002733-ac45abd4c88c // indirect + golang.org/x/sys v0.0.0-20201116194326-cc9327a14d48 + golang.org/x/tools v0.0.0-20201117021029-3c3a81204b10 // indirect google.golang.org/api v0.35.0 google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20201113130914-ce600e9a6f9e // indirect + google.golang.org/genproto v0.0.0-20201117123952-62d171c70ae1 // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) @@ -58,6 +58,6 @@ require ( replace ( github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9 github.com/pkg/sftp => github.com/drakkan/sftp v0.0.0-20201116163812-863783342b7c - golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20201114074711-d051624c4fd2 + golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20201117140033-e88a43c86bda golang.org/x/net => github.com/drakkan/net v0.0.0-20201114074615-8a2467084c77 ) diff --git a/go.sum b/go.sum index 5bbcfb07..1b08a09c 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,8 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.35.28 h1:S2LuRnfC8X05zgZLC8gy/Sb82TGv2Cpytzbzz7tkeHc= -github.com/aws/aws-sdk-go v1.35.28/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= +github.com/aws/aws-sdk-go v1.35.29 h1:1kYnwrWTp2e+lI9yYFaDo7OFaLug8yXC6Qdj+u8451Q= +github.com/aws/aws-sdk-go v1.35.29/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -115,8 +115,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/drakkan/crypto v0.0.0-20201114074711-d051624c4fd2 h1:1X+tt8X6lyGWn17TJaKOybGkRuGm1Rd0ErPhIY1Zy4A= -github.com/drakkan/crypto v0.0.0-20201114074711-d051624c4fd2/go.mod h1:v3bhWOXGYda7H5d2s5t9XA6th3fxW3s0MQxU1R96G/w= +github.com/drakkan/crypto v0.0.0-20201117140033-e88a43c86bda h1:YiF1OveSSl1o5QTgz0Fj0UQvWS8TVO0kwSCPGDeqR1s= +github.com/drakkan/crypto v0.0.0-20201117140033-e88a43c86bda/go.mod h1:Y+hk0JcLG7/moavCckN+J0fs8kd8mUEUPg5sSgBKDMQ= github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9 h1:LPH1dEblAOO/LoG7yHPMtBLXhQmjaga91/DDjWk9jWA= github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9/go.mod h1:2lmrmq866uF2tnje75wQHzmPXhmSWUt7Gyx2vgK1RCU= github.com/drakkan/net v0.0.0-20201114074615-8a2467084c77 h1:keiJPG0lodjq5Ep9XuDKGRQRC52pp/8NB8/1xbqmw+Y= @@ -316,8 +316,8 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI= -github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= +github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ= +github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -587,6 +587,7 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -610,8 +611,9 @@ golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba h1:xmhUJGQGbxlod18iJGqVEp9cHIPLl7QiX2aA3to708s= -golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201116194326-cc9327a14d48 h1:AYCWBZhgIw6XobZ5CibNJr0Rc4ZofGGKvWa1vcx2IGk= +golang.org/x/sys v0.0.0-20201116194326-cc9327a14d48/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201113234701-d7a72108b828/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -677,7 +679,7 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20200915173823-2db8f0ff891c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201116002733-ac45abd4c88c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201117021029-3c3a81204b10/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -746,8 +748,8 @@ google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200914193844-75d14daec038/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200921151605-7abf4a1a14d5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201113130914-ce600e9a6f9e h1:jRAe+6EDD0LNrVzmjx7FxBivivOZTKnXMbH5lvmxLP8= -google.golang.org/genproto v0.0.0-20201113130914-ce600e9a6f9e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201117123952-62d171c70ae1 h1:EVow1AaDgdoMjdO64/fntn4+RGTVor8YE/mkmIYsqFM= +google.golang.org/genproto v0.0.0-20201117123952-62d171c70ae1/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= diff --git a/sftpd/handler.go b/sftpd/handler.go index b0a999df..b24b2efb 100644 --- a/sftpd/handler.go +++ b/sftpd/handler.go @@ -113,7 +113,7 @@ func (c *Connection) handleFilewrite(request *sftp.Request) (sftp.WriterAtReader } stat, statErr := c.Fs.Lstat(p) - if (statErr == nil && stat.Mode()&os.ModeSymlink == os.ModeSymlink) || c.Fs.IsNotExist(statErr) { + if (statErr == nil && stat.Mode()&os.ModeSymlink != 0) || c.Fs.IsNotExist(statErr) { if !c.User.HasPerm(dataprovider.PermUpload, path.Dir(request.Filepath)) { return nil, sftp.ErrSSHFxPermissionDenied } @@ -300,7 +300,7 @@ func (c *Connection) handleSFTPRemove(filePath string, request *sftp.Request) er c.Log(logger.LevelWarn, "failed to remove a file %#v: stat error: %+v", filePath, err) return c.GetFsError(err) } - if fi.IsDir() && fi.Mode()&os.ModeSymlink != os.ModeSymlink { + if fi.IsDir() && fi.Mode()&os.ModeSymlink == 0 { c.Log(logger.LevelDebug, "cannot remove %#v is not a file/symlink", filePath) return sftp.ErrSSHFxFailure } diff --git a/sftpd/scp.go b/sftpd/scp.go index 657af42c..e3254114 100644 --- a/sftpd/scp.go +++ b/sftpd/scp.go @@ -260,7 +260,7 @@ func (c *scpCommand) handleUpload(uploadFilePath string, sizeToRead int64) error filePath = c.connection.Fs.GetAtomicUploadPath(p) } stat, statErr := c.connection.Fs.Lstat(p) - if (statErr == nil && stat.Mode()&os.ModeSymlink == os.ModeSymlink) || c.connection.Fs.IsNotExist(statErr) { + if (statErr == nil && stat.Mode()&os.ModeSymlink != 0) || c.connection.Fs.IsNotExist(statErr) { if !c.connection.User.HasPerm(dataprovider.PermUpload, path.Dir(uploadFilePath)) { c.connection.Log(logger.LevelWarn, "cannot upload file: %#v, permission denied", uploadFilePath) c.sendErrorMessage(common.ErrPermissionDenied) @@ -352,7 +352,7 @@ func (c *scpCommand) handleRecursiveDownload(dirPath string, stat os.FileInfo) e var dirs []string for _, file := range files { filePath := c.connection.Fs.GetRelativePath(c.connection.Fs.Join(dirPath, file.Name())) - if file.Mode().IsRegular() || file.Mode()&os.ModeSymlink == os.ModeSymlink { + if file.Mode().IsRegular() || file.Mode()&os.ModeSymlink != 0 { err = c.handleDownload(filePath) if err != nil { break diff --git a/sftpd/sftpd_test.go b/sftpd/sftpd_test.go index bc498f4e..b18de796 100644 --- a/sftpd/sftpd_test.go +++ b/sftpd/sftpd_test.go @@ -753,11 +753,11 @@ func TestStat(t *testing.T) { assert.NoError(t, err) info, err := client.Lstat(symlinkName) if assert.NoError(t, err) { - assert.True(t, info.Mode()&os.ModeSymlink == os.ModeSymlink) + assert.True(t, info.Mode()&os.ModeSymlink != 0) } info, err = client.Stat(symlinkName) if assert.NoError(t, err) { - assert.False(t, info.Mode()&os.ModeSymlink == os.ModeSymlink) + assert.False(t, info.Mode()&os.ModeSymlink != 0) } linkName, err := client.ReadLink(symlinkName) assert.NoError(t, err) diff --git a/sftpd/ssh_cmd.go b/sftpd/ssh_cmd.go index 75e5910a..26e2ff0d 100644 --- a/sftpd/ssh_cmd.go +++ b/sftpd/ssh_cmd.go @@ -552,7 +552,7 @@ func (c *sshCommand) hasCopyPermissions(sshSourcePath, sshDestPath string, srcIn } if srcInfo.IsDir() { return c.connection.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(sshDestPath)) - } else if srcInfo.Mode()&os.ModeSymlink == os.ModeSymlink { + } else if srcInfo.Mode()&os.ModeSymlink != 0 { return c.connection.User.HasPerm(dataprovider.PermCreateSymlinks, path.Dir(sshDestPath)) } return c.connection.User.HasPerm(dataprovider.PermUpload, path.Dir(sshDestPath)) diff --git a/vfs/azblobfs.go b/vfs/azblobfs.go index 39e18f86..5a8262fb 100644 --- a/vfs/azblobfs.go +++ b/vfs/azblobfs.go @@ -189,7 +189,7 @@ func (fs *AzureBlobFs) Lstat(name string) (os.FileInfo, error) { } // Open opens the named file for reading -func (fs *AzureBlobFs) Open(name string, offset int64) (*os.File, *pipeat.PipeReaderAt, func(), error) { +func (fs *AzureBlobFs) Open(name string, offset int64) (File, *pipeat.PipeReaderAt, func(), error) { r, w, err := pipeat.PipeInDir(fs.localTempDir) if err != nil { return nil, nil, nil, err @@ -221,7 +221,7 @@ func (fs *AzureBlobFs) Open(name string, offset int64) (*os.File, *pipeat.PipeRe } // Create creates or opens the named file for writing -func (fs *AzureBlobFs) Create(name string, flag int) (*os.File, *PipeWriter, func(), error) { +func (fs *AzureBlobFs) Create(name string, flag int) (File, *PipeWriter, func(), error) { r, w, err := pipeat.PipeInDir(fs.localTempDir) if err != nil { return nil, nil, nil, err diff --git a/vfs/gcsfs.go b/vfs/gcsfs.go index e0e3aee9..e5d80c53 100644 --- a/vfs/gcsfs.go +++ b/vfs/gcsfs.go @@ -163,7 +163,7 @@ func (fs *GCSFs) Lstat(name string) (os.FileInfo, error) { } // Open opens the named file for reading -func (fs *GCSFs) Open(name string, offset int64) (*os.File, *pipeat.PipeReaderAt, func(), error) { +func (fs *GCSFs) Open(name string, offset int64) (File, *pipeat.PipeReaderAt, func(), error) { r, w, err := pipeat.PipeInDir(fs.localTempDir) if err != nil { return nil, nil, nil, err @@ -194,7 +194,7 @@ func (fs *GCSFs) Open(name string, offset int64) (*os.File, *pipeat.PipeReaderAt } // Create creates or opens the named file for writing -func (fs *GCSFs) Create(name string, flag int) (*os.File, *PipeWriter, func(), error) { +func (fs *GCSFs) Create(name string, flag int) (File, *PipeWriter, func(), error) { r, w, err := pipeat.PipeInDir(fs.localTempDir) if err != nil { return nil, nil, nil, err diff --git a/vfs/osfs.go b/vfs/osfs.go index c01cc2eb..3fb8ad33 100644 --- a/vfs/osfs.go +++ b/vfs/osfs.go @@ -81,13 +81,13 @@ func (fs *OsFs) Lstat(name string) (os.FileInfo, error) { } // Open opens the named file for reading -func (*OsFs) Open(name string, offset int64) (*os.File, *pipeat.PipeReaderAt, func(), error) { +func (*OsFs) Open(name string, offset int64) (File, *pipeat.PipeReaderAt, func(), error) { f, err := os.Open(name) return f, nil, nil, err } // Create creates or opens the named file for writing -func (*OsFs) Create(name string, flag int) (*os.File, *PipeWriter, func(), error) { +func (*OsFs) Create(name string, flag int) (File, *PipeWriter, func(), error) { var err error var f *os.File if flag == 0 { diff --git a/vfs/s3fs.go b/vfs/s3fs.go index cd8c3317..6b275306 100644 --- a/vfs/s3fs.go +++ b/vfs/s3fs.go @@ -189,7 +189,7 @@ func (fs *S3Fs) Lstat(name string) (os.FileInfo, error) { } // Open opens the named file for reading -func (fs *S3Fs) Open(name string, offset int64) (*os.File, *pipeat.PipeReaderAt, func(), error) { +func (fs *S3Fs) Open(name string, offset int64) (File, *pipeat.PipeReaderAt, func(), error) { r, w, err := pipeat.PipeInDir(fs.localTempDir) if err != nil { return nil, nil, nil, err @@ -216,7 +216,7 @@ func (fs *S3Fs) Open(name string, offset int64) (*os.File, *pipeat.PipeReaderAt, } // Create creates or opens the named file for writing -func (fs *S3Fs) Create(name string, flag int) (*os.File, *PipeWriter, func(), error) { +func (fs *S3Fs) Create(name string, flag int) (File, *PipeWriter, func(), error) { r, w, err := pipeat.PipeInDir(fs.localTempDir) if err != nil { return nil, nil, nil, err diff --git a/vfs/vfs.go b/vfs/vfs.go index b1aa11d1..e60a68cd 100644 --- a/vfs/vfs.go +++ b/vfs/vfs.go @@ -4,6 +4,7 @@ package vfs import ( "errors" "fmt" + "io" "net/url" "os" "path" @@ -28,8 +29,8 @@ type Fs interface { ConnectionID() string Stat(name string) (os.FileInfo, error) Lstat(name string) (os.FileInfo, error) - Open(name string, offset int64) (*os.File, *pipeat.PipeReaderAt, func(), error) - Create(name string, flag int) (*os.File, *PipeWriter, func(), error) + Open(name string, offset int64) (File, *pipeat.PipeReaderAt, func(), error) + Create(name string, flag int) (File, *PipeWriter, func(), error) Rename(source, target string) error Remove(name string, isDir bool) error Mkdir(name string) error @@ -57,6 +58,19 @@ type Fs interface { GetMimeType(name string) (string, error) } +// File defines an interface representing a SFTPGo file +type File interface { + io.Reader + io.Writer + io.Closer + io.ReaderAt + io.WriterAt + io.Seeker + Stat() (os.FileInfo, error) + Name() string + Truncate(size int64) error +} + // ErrVfsUnsupported defines the error for an unsupported VFS operation var ErrVfsUnsupported = errors.New("Not supported") diff --git a/webdavd/handler.go b/webdavd/handler.go index 95ca9e0b..c46a3aaf 100644 --- a/webdavd/handler.go +++ b/webdavd/handler.go @@ -127,7 +127,7 @@ func (c *Connection) RemoveAll(ctx context.Context, name string) error { return c.GetFsError(err) } - if fi.IsDir() && fi.Mode()&os.ModeSymlink != os.ModeSymlink { + if fi.IsDir() && fi.Mode()&os.ModeSymlink == 0 { return c.removeDirTree(p, name) } return c.RemoveFile(p, name, fi) @@ -152,7 +152,7 @@ func (c *Connection) OpenFile(ctx context.Context, name string, flag int, perm o func (c *Connection) getFile(fsPath, virtualPath string) (webdav.File, error) { var err error - var file *os.File + var file vfs.File var r *pipeat.PipeReaderAt var cancelFn func() @@ -184,7 +184,7 @@ func (c *Connection) putFile(fsPath, virtualPath string) (webdav.File, error) { } stat, statErr := c.Fs.Lstat(fsPath) - if (statErr == nil && stat.Mode()&os.ModeSymlink == os.ModeSymlink) || c.Fs.IsNotExist(statErr) { + if (statErr == nil && stat.Mode()&os.ModeSymlink != 0) || c.Fs.IsNotExist(statErr) { if !c.User.HasPerm(dataprovider.PermUpload, path.Dir(virtualPath)) { return nil, c.GetPermissionDeniedError() } diff --git a/webdavd/internal_test.go b/webdavd/internal_test.go index 6a72c628..217a678d 100644 --- a/webdavd/internal_test.go +++ b/webdavd/internal_test.go @@ -50,7 +50,7 @@ func (fs *MockOsFs) Name() string { } // Open returns nil -func (fs *MockOsFs) Open(name string, offset int64) (*os.File, *pipeat.PipeReaderAt, func(), error) { +func (fs *MockOsFs) Open(name string, offset int64) (vfs.File, *pipeat.PipeReaderAt, func(), error) { return nil, fs.reader, nil, nil }