add a File interface so we can avoid to use os.File directly

This commit is contained in:
Nicola Murino 2020-11-17 19:36:39 +01:00
parent 969b38586e
commit ca0ff0d630
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
17 changed files with 63 additions and 47 deletions

View file

@ -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) 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)) vfolder, err := c.User.GetVirtualFolderForPath(path.Dir(virtualPath))
if err == nil { if err == nil {
dataprovider.UpdateVirtualFolderQuota(vfolder.BaseVirtualFolder, -1, -size, false) //nolint:errcheck 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) c.Log(logger.LevelWarn, "failed to remove a dir %#v: stat error: %+v", fsPath, err)
return c.GetFsError(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) c.Log(logger.LevelDebug, "cannot remove %#v is not a directory", fsPath)
return c.GetGenericError(nil) return c.GetGenericError(nil)
} }
@ -638,7 +638,7 @@ func (c *BaseConnection) isRenamePermitted(fsSourcePath, virtualSourcePath, virt
if fi != nil { if fi != nil {
if fi.IsDir() { if fi.IsDir() {
return c.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(virtualTargetPath)) 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)) return c.User.HasPerm(dataprovider.PermCreateSymlinks, path.Dir(virtualTargetPath))
} }
} }

View file

@ -806,7 +806,7 @@ func TestRenamePermission(t *testing.T) {
} }
info, err = os.Lstat(tmpDirLink) info, err = os.Lstat(tmpDirLink)
if assert.NoError(t, err) { 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 // the source is a symlink and the target has createDirs and upload perm
assert.False(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info)) assert.False(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
} }

View file

@ -23,7 +23,7 @@ var (
type BaseTransfer struct { //nolint:maligned type BaseTransfer struct { //nolint:maligned
ID uint64 ID uint64
Fs vfs.Fs Fs vfs.Fs
File *os.File File vfs.File
Connection *BaseConnection Connection *BaseConnection
cancelFn func() cancelFn func()
fsPath string fsPath string
@ -42,7 +42,7 @@ type BaseTransfer struct { //nolint:maligned
} }
// NewBaseTransfer returns a new BaseTransfer and adds it to the given connection // 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 { minWriteOffset, initialSize, maxWriteSize int64, isNewFile bool, fs vfs.Fs) *BaseTransfer {
t := &BaseTransfer{ t := &BaseTransfer{
ID: conn.GetTransferID(), ID: conn.GetTransferID(),

View file

@ -99,7 +99,7 @@ func (c *Connection) Remove(name string) error {
return c.GetFsError(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", p) c.Log(logger.LevelDebug, "cannot remove %#v is not a file/symlink", p)
return c.GetGenericError(nil) 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) 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)) { if !c.User.HasPerm(dataprovider.PermUpload, path.Dir(ftpPath)) {
return nil, c.GetPermissionDeniedError() return nil, c.GetPermissionDeniedError()
} }

14
go.mod
View file

@ -8,7 +8,7 @@ require (
github.com/Azure/azure-storage-blob-go v0.11.0 github.com/Azure/azure-storage-blob-go v0.11.0
github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962
github.com/alexedwards/argon2id v0.0.0-20200802152012-2464efd3196b 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/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
github.com/eikenb/pipeat v0.0.0-20200430215831-470df5986b6d github.com/eikenb/pipeat v0.0.0-20200430215831-470df5986b6d
github.com/fclairamb/ftpserverlib v0.9.1-0.20201105003045-1edd6bf7ae53 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/jlaffaye/ftp v0.0.0-20201112195030-9aae4d151126
github.com/lib/pq v1.8.0 github.com/lib/pq v1.8.0
github.com/magiconair/properties v1.8.4 // indirect 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/miekg/dns v1.1.35 // indirect
github.com/mitchellh/mapstructure v1.3.3 // indirect github.com/mitchellh/mapstructure v1.3.3 // indirect
github.com/otiai10/copy v1.2.0 github.com/otiai10/copy v1.2.0
@ -43,14 +43,14 @@ require (
github.com/studio-b12/gowebdav v0.0.0-20200929080739-bdacfab94796 github.com/studio-b12/gowebdav v0.0.0-20200929080739-bdacfab94796
go.etcd.io/bbolt v1.3.5 go.etcd.io/bbolt v1.3.5
go.uber.org/automaxprocs v1.3.0 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/net v0.0.0-20201110031124-69a78807bb2b
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 // indirect golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 // indirect
golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba golang.org/x/sys v0.0.0-20201116194326-cc9327a14d48
golang.org/x/tools v0.0.0-20201116002733-ac45abd4c88c // indirect golang.org/x/tools v0.0.0-20201117021029-3c3a81204b10 // indirect
google.golang.org/api v0.35.0 google.golang.org/api v0.35.0
google.golang.org/appengine v1.6.7 // indirect 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/ini.v1 v1.62.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0
) )
@ -58,6 +58,6 @@ require (
replace ( replace (
github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9 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 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 golang.org/x/net => github.com/drakkan/net v0.0.0-20201114074615-8a2467084c77
) )

24
go.sum
View file

@ -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/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-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.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.29 h1:1kYnwrWTp2e+lI9yYFaDo7OFaLug8yXC6Qdj+u8451Q=
github.com/aws/aws-sdk-go v1.35.28/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= 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/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 v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 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/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/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/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-20201117140033-e88a43c86bda h1:YiF1OveSSl1o5QTgz0Fj0UQvWS8TVO0kwSCPGDeqR1s=
github.com/drakkan/crypto v0.0.0-20201114074711-d051624c4fd2/go.mod h1:v3bhWOXGYda7H5d2s5t9XA6th3fxW3s0MQxU1R96G/w= 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 h1:LPH1dEblAOO/LoG7yHPMtBLXhQmjaga91/DDjWk9jWA=
github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9/go.mod h1:2lmrmq866uF2tnje75wQHzmPXhmSWUt7Gyx2vgK1RCU= 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= 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.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 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-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.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= 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 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 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= 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-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-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-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-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-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/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-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-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-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba h1:xmhUJGQGbxlod18iJGqVEp9cHIPLl7QiX2aA3to708s= golang.org/x/sys v0.0.0-20201116194326-cc9327a14d48 h1:AYCWBZhgIw6XobZ5CibNJr0Rc4ZofGGKvWa1vcx2IGk=
golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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.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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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-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-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-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-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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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-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-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-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-20201117123952-62d171c70ae1 h1:EVow1AaDgdoMjdO64/fntn4+RGTVor8YE/mkmIYsqFM=
google.golang.org/genproto v0.0.0-20201113130914-ce600e9a6f9e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 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.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.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=

View file

@ -113,7 +113,7 @@ func (c *Connection) handleFilewrite(request *sftp.Request) (sftp.WriterAtReader
} }
stat, statErr := c.Fs.Lstat(p) 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)) { if !c.User.HasPerm(dataprovider.PermUpload, path.Dir(request.Filepath)) {
return nil, sftp.ErrSSHFxPermissionDenied 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) c.Log(logger.LevelWarn, "failed to remove a file %#v: stat error: %+v", filePath, err)
return c.GetFsError(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) c.Log(logger.LevelDebug, "cannot remove %#v is not a file/symlink", filePath)
return sftp.ErrSSHFxFailure return sftp.ErrSSHFxFailure
} }

View file

@ -260,7 +260,7 @@ func (c *scpCommand) handleUpload(uploadFilePath string, sizeToRead int64) error
filePath = c.connection.Fs.GetAtomicUploadPath(p) filePath = c.connection.Fs.GetAtomicUploadPath(p)
} }
stat, statErr := c.connection.Fs.Lstat(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)) { if !c.connection.User.HasPerm(dataprovider.PermUpload, path.Dir(uploadFilePath)) {
c.connection.Log(logger.LevelWarn, "cannot upload file: %#v, permission denied", uploadFilePath) c.connection.Log(logger.LevelWarn, "cannot upload file: %#v, permission denied", uploadFilePath)
c.sendErrorMessage(common.ErrPermissionDenied) c.sendErrorMessage(common.ErrPermissionDenied)
@ -352,7 +352,7 @@ func (c *scpCommand) handleRecursiveDownload(dirPath string, stat os.FileInfo) e
var dirs []string var dirs []string
for _, file := range files { for _, file := range files {
filePath := c.connection.Fs.GetRelativePath(c.connection.Fs.Join(dirPath, file.Name())) 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) err = c.handleDownload(filePath)
if err != nil { if err != nil {
break break

View file

@ -753,11 +753,11 @@ func TestStat(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
info, err := client.Lstat(symlinkName) info, err := client.Lstat(symlinkName)
if assert.NoError(t, err) { 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) info, err = client.Stat(symlinkName)
if assert.NoError(t, err) { 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) linkName, err := client.ReadLink(symlinkName)
assert.NoError(t, err) assert.NoError(t, err)

View file

@ -552,7 +552,7 @@ func (c *sshCommand) hasCopyPermissions(sshSourcePath, sshDestPath string, srcIn
} }
if srcInfo.IsDir() { if srcInfo.IsDir() {
return c.connection.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(sshDestPath)) 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.PermCreateSymlinks, path.Dir(sshDestPath))
} }
return c.connection.User.HasPerm(dataprovider.PermUpload, path.Dir(sshDestPath)) return c.connection.User.HasPerm(dataprovider.PermUpload, path.Dir(sshDestPath))

View file

@ -189,7 +189,7 @@ func (fs *AzureBlobFs) Lstat(name string) (os.FileInfo, error) {
} }
// Open opens the named file for reading // 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) r, w, err := pipeat.PipeInDir(fs.localTempDir)
if err != nil { if err != nil {
return nil, nil, nil, err 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 // 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) r, w, err := pipeat.PipeInDir(fs.localTempDir)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err

View file

@ -163,7 +163,7 @@ func (fs *GCSFs) Lstat(name string) (os.FileInfo, error) {
} }
// Open opens the named file for reading // 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) r, w, err := pipeat.PipeInDir(fs.localTempDir)
if err != nil { if err != nil {
return nil, nil, nil, err 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 // 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) r, w, err := pipeat.PipeInDir(fs.localTempDir)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err

View file

@ -81,13 +81,13 @@ func (fs *OsFs) Lstat(name string) (os.FileInfo, error) {
} }
// Open opens the named file for reading // 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) f, err := os.Open(name)
return f, nil, nil, err return f, nil, nil, err
} }
// Create creates or opens the named file for writing // 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 err error
var f *os.File var f *os.File
if flag == 0 { if flag == 0 {

View file

@ -189,7 +189,7 @@ func (fs *S3Fs) Lstat(name string) (os.FileInfo, error) {
} }
// Open opens the named file for reading // 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) r, w, err := pipeat.PipeInDir(fs.localTempDir)
if err != nil { if err != nil {
return nil, nil, nil, err 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 // 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) r, w, err := pipeat.PipeInDir(fs.localTempDir)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err

View file

@ -4,6 +4,7 @@ package vfs
import ( import (
"errors" "errors"
"fmt" "fmt"
"io"
"net/url" "net/url"
"os" "os"
"path" "path"
@ -28,8 +29,8 @@ type Fs interface {
ConnectionID() string ConnectionID() string
Stat(name string) (os.FileInfo, error) Stat(name string) (os.FileInfo, error)
Lstat(name string) (os.FileInfo, error) Lstat(name string) (os.FileInfo, error)
Open(name string, offset int64) (*os.File, *pipeat.PipeReaderAt, func(), error) Open(name string, offset int64) (File, *pipeat.PipeReaderAt, func(), error)
Create(name string, flag int) (*os.File, *PipeWriter, func(), error) Create(name string, flag int) (File, *PipeWriter, func(), error)
Rename(source, target string) error Rename(source, target string) error
Remove(name string, isDir bool) error Remove(name string, isDir bool) error
Mkdir(name string) error Mkdir(name string) error
@ -57,6 +58,19 @@ type Fs interface {
GetMimeType(name string) (string, error) 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 // ErrVfsUnsupported defines the error for an unsupported VFS operation
var ErrVfsUnsupported = errors.New("Not supported") var ErrVfsUnsupported = errors.New("Not supported")

View file

@ -127,7 +127,7 @@ func (c *Connection) RemoveAll(ctx context.Context, name string) error {
return c.GetFsError(err) 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.removeDirTree(p, name)
} }
return c.RemoveFile(p, name, fi) 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) { func (c *Connection) getFile(fsPath, virtualPath string) (webdav.File, error) {
var err error var err error
var file *os.File var file vfs.File
var r *pipeat.PipeReaderAt var r *pipeat.PipeReaderAt
var cancelFn func() var cancelFn func()
@ -184,7 +184,7 @@ func (c *Connection) putFile(fsPath, virtualPath string) (webdav.File, error) {
} }
stat, statErr := c.Fs.Lstat(fsPath) 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)) { if !c.User.HasPerm(dataprovider.PermUpload, path.Dir(virtualPath)) {
return nil, c.GetPermissionDeniedError() return nil, c.GetPermissionDeniedError()
} }

View file

@ -50,7 +50,7 @@ func (fs *MockOsFs) Name() string {
} }
// Open returns nil // 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 return nil, fs.reader, nil, nil
} }