parent
91a4c64390
commit
4748e6f54d
8 changed files with 209 additions and 58 deletions
20
go.mod
20
go.mod
|
@ -3,10 +3,10 @@ module github.com/drakkan/sftpgo
|
|||
go 1.13
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.64.0 // indirect
|
||||
cloud.google.com/go/storage v1.10.0
|
||||
cloud.google.com/go v0.65.0 // indirect
|
||||
cloud.google.com/go/storage v1.11.0
|
||||
github.com/alexedwards/argon2id v0.0.0-20200802152012-2464efd3196b
|
||||
github.com/aws/aws-sdk-go v1.34.10
|
||||
github.com/aws/aws-sdk-go v1.34.13
|
||||
github.com/eikenb/pipeat v0.0.0-20200430215831-470df5986b6d
|
||||
github.com/fclairamb/ftpserverlib v0.8.1-0.20200824203441-87a3864e6de5
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
|
@ -17,14 +17,15 @@ require (
|
|||
github.com/grandcat/zeroconf v1.0.0
|
||||
github.com/jlaffaye/ftp v0.0.0-20200720194710-13949d38913e
|
||||
github.com/lib/pq v1.8.0
|
||||
github.com/mattn/go-sqlite3 v1.14.1
|
||||
github.com/magiconair/properties v1.8.2 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.2
|
||||
github.com/miekg/dns v1.1.31 // indirect
|
||||
github.com/mitchellh/mapstructure v1.3.3 // indirect
|
||||
github.com/nathanaelle/password/v2 v2.0.1
|
||||
github.com/otiai10/copy v1.2.0
|
||||
github.com/pelletier/go-toml v1.8.0 // indirect
|
||||
github.com/pires/go-proxyproto v0.1.3
|
||||
github.com/pkg/sftp v1.11.1-0.20200825160622-06ab92ee3917
|
||||
github.com/pkg/sftp v1.12.0
|
||||
github.com/prometheus/client_golang v1.7.1
|
||||
github.com/prometheus/common v0.13.0 // indirect
|
||||
github.com/rs/cors v1.7.1-0.20200626170627-8b4a00bd362b
|
||||
|
@ -41,15 +42,18 @@ require (
|
|||
go.etcd.io/bbolt v1.3.5
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202
|
||||
golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8
|
||||
golang.org/x/tools v0.0.0-20200823205832-c024452afbcd // indirect
|
||||
golang.org/x/sys v0.0.0-20200828194041-157a740278f4
|
||||
golang.org/x/tools v0.0.0-20200828161849-5deb26317202 // indirect
|
||||
google.golang.org/api v0.30.0
|
||||
gopkg.in/ini.v1 v1.60.1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20200829155447-2bf3329a0021 // indirect
|
||||
google.golang.org/grpc v1.31.1 // indirect
|
||||
gopkg.in/ini.v1 v1.60.2 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20200730125632-b21eac28818c
|
||||
github.com/pkg/sftp => github.com/drakkan/sftp v0.0.0-20200830084022-ea67d57ce589
|
||||
golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20200824205004-9f5ce89c1796
|
||||
golang.org/x/net => github.com/drakkan/net v0.0.0-20200824204746-8b31adf087bf
|
||||
)
|
||||
|
|
46
go.sum
46
go.sum
|
@ -12,8 +12,9 @@ cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bP
|
|||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.64.0 h1:xVP3LPvMjGT4J0a55y02Gw5y/dkY/rxGz58sfK1jqIo=
|
||||
cloud.google.com/go v0.64.0/go.mod h1:xfORb36jGvE+6EexW71nMEtL025s3x6xvuYUKM4JLv4=
|
||||
cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
|
@ -31,8 +32,9 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy
|
|||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.11.0 h1:bSLyzhbGjLMYxCratCDRSSH7+xRGpNApTBmowDUFGLk=
|
||||
cloud.google.com/go/storage v1.11.0/go.mod h1:/PAbprKS+5msVYogBmczjWalDXnQ9mr64yEq9YnyPeo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
|
@ -60,8 +62,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.34.10 h1:VU78gcf/3wA4HNEDCHidK738l7K0Bals4SJnfnvXOtY=
|
||||
github.com/aws/aws-sdk-go v1.34.10/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.34.13 h1:wwNWSUh4FGJxXVOVVNj2lWI8wTe5hK8sGWlK7ziEcgg=
|
||||
github.com/aws/aws-sdk-go v1.34.13/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
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=
|
||||
|
@ -109,6 +111,8 @@ github.com/drakkan/ftp v0.0.0-20200730125632-b21eac28818c h1:QSXIWohSNn0negBVSKE
|
|||
github.com/drakkan/ftp v0.0.0-20200730125632-b21eac28818c/go.mod h1:2lmrmq866uF2tnje75wQHzmPXhmSWUt7Gyx2vgK1RCU=
|
||||
github.com/drakkan/net v0.0.0-20200824204746-8b31adf087bf h1:MbeUXErR+xQ1Yvk+E6wYBKvgK8nvDiXk00jNEyDRvE8=
|
||||
github.com/drakkan/net v0.0.0-20200824204746-8b31adf087bf/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
github.com/drakkan/sftp v0.0.0-20200830084022-ea67d57ce589 h1:iM/xecWdhSbPHaFnsnTsZg0trWuCFxQ9GUE7ZPstvko=
|
||||
github.com/drakkan/sftp v0.0.0-20200830084022-ea67d57ce589/go.mod h1:fUqqXB5vEgVCZ131L+9say31RAri6aF6KDViawhxKK8=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
|
@ -284,15 +288,16 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b
|
|||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.2 h1:znVR8Q4g7/WlcvsxLBRWvo+vtFJUAbDn3w+Yak2xVMI=
|
||||
github.com/magiconair/properties v1.8.2/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/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-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-sqlite3 v1.14.1 h1:AHx9Ra40wIzl+GelgX2X6AWxmT5tfxhI1PL0523HcSw=
|
||||
github.com/mattn/go-sqlite3 v1.14.1/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
github.com/mattn/go-sqlite3 v1.14.2 h1:A2EQLwjYf/hfYaM20FVjs1UewCTTFR7RmjEHkLjldIA=
|
||||
github.com/mattn/go-sqlite3 v1.14.2/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
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=
|
||||
|
@ -364,9 +369,6 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pkg/sftp v1.11.1-0.20200825160622-06ab92ee3917 h1:NO+7wv5cAXYMhTpVX0e97zH349VVp8c2dB0d/SXfmkg=
|
||||
github.com/pkg/sftp v1.11.1-0.20200825160622-06ab92ee3917/go.mod h1:i24A96cQ6ZvWut9G/Uv3LvC4u3VebGsBR5JFvPyChLc=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
|
@ -576,10 +578,9 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8 h1:AvbQYmiaaaza3cW3QXRyPo5kYgpFIzOAfeAAN7m3qQ4=
|
||||
golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200828194041-157a740278f4 h1:kCCpuwSAoYJPkNc6x0xT9yTtV4oKtARo4RGBQWOfg9E=
|
||||
golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
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=
|
||||
|
@ -639,7 +640,9 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
|
|||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200817023811-d00afeaade8f/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200823205832-c024452afbcd/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200828161849-5deb26317202/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
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=
|
||||
|
@ -698,8 +701,11 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY
|
|||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70 h1:wboULUXGF3c5qdUnKp+6gLAccE6PRpa/czkYvQ4UXv8=
|
||||
google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200827165113-ac2560b5e952/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200829155447-2bf3329a0021 h1:14sCoAL+O3izDMSeixcDn4kLi+JrAqQ42r8XD3oYePk=
|
||||
google.golang.org/genproto v0.0.0-20200829155447-2bf3329a0021/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=
|
||||
|
@ -716,8 +722,9 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
|||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -741,8 +748,8 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
|||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.60.1 h1:P5y5shSkb0CFe44qEeMBgn8JLow09MP17jlJHanke5g=
|
||||
gopkg.in/ini.v1 v1.60.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.60.2 h1:7i8mqModL63zqi8nQn8Q3+0zvSCZy1AxhBgthKfi4WU=
|
||||
gopkg.in/ini.v1 v1.60.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
|
@ -755,9 +762,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
@ -74,13 +74,22 @@ func (c *Connection) Fileread(request *sftp.Request) (io.ReaderAt, error) {
|
|||
|
||||
baseTransfer := common.NewBaseTransfer(file, c.BaseConnection, cancelFn, p, request.Filepath, common.TransferDownload,
|
||||
0, 0, 0, false, c.Fs)
|
||||
t := newTransfer(baseTransfer, nil, r)
|
||||
t := newTransfer(baseTransfer, nil, r, nil)
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// OpenFile implements OpenFileWriter interface
|
||||
func (c *Connection) OpenFile(request *sftp.Request) (sftp.WriterAtReaderAt, error) {
|
||||
return c.handleFilewrite(request)
|
||||
}
|
||||
|
||||
// Filewrite handles the write actions for a file on the system.
|
||||
func (c *Connection) Filewrite(request *sftp.Request) (io.WriterAt, error) {
|
||||
return c.handleFilewrite(request)
|
||||
}
|
||||
|
||||
func (c *Connection) handleFilewrite(request *sftp.Request) (sftp.WriterAtReaderAt, error) {
|
||||
c.UpdateLastActivity()
|
||||
|
||||
if !c.User.IsFileAllowed(request.Filepath) {
|
||||
|
@ -98,12 +107,24 @@ func (c *Connection) Filewrite(request *sftp.Request) (io.WriterAt, error) {
|
|||
filePath = c.Fs.GetAtomicUploadPath(p)
|
||||
}
|
||||
|
||||
var errForRead error
|
||||
if !vfs.IsLocalOsFs(c.Fs) && request.Pflags().Read {
|
||||
// read and write mode is only supported for local filesystem
|
||||
errForRead = sftp.ErrSSHFxOpUnsupported
|
||||
}
|
||||
if !c.User.HasPerm(dataprovider.PermDownload, path.Dir(request.Filepath)) {
|
||||
// we can try to read only for local fs here, see above.
|
||||
// os.ErrPermission will become sftp.ErrSSHFxPermissionDenied when sent to
|
||||
// the client
|
||||
errForRead = os.ErrPermission
|
||||
}
|
||||
|
||||
stat, statErr := c.Fs.Lstat(p)
|
||||
if (statErr == nil && stat.Mode()&os.ModeSymlink == os.ModeSymlink) || c.Fs.IsNotExist(statErr) {
|
||||
if !c.User.HasPerm(dataprovider.PermUpload, path.Dir(request.Filepath)) {
|
||||
return nil, sftp.ErrSSHFxPermissionDenied
|
||||
}
|
||||
return c.handleSFTPUploadToNewFile(p, filePath, request.Filepath)
|
||||
return c.handleSFTPUploadToNewFile(p, filePath, request.Filepath, errForRead)
|
||||
}
|
||||
|
||||
if statErr != nil {
|
||||
|
@ -121,7 +142,7 @@ func (c *Connection) Filewrite(request *sftp.Request) (io.WriterAt, error) {
|
|||
return nil, sftp.ErrSSHFxPermissionDenied
|
||||
}
|
||||
|
||||
return c.handleSFTPUploadToExistingFile(request.Pflags(), p, filePath, stat.Size(), request.Filepath)
|
||||
return c.handleSFTPUploadToExistingFile(request.Pflags(), p, filePath, stat.Size(), request.Filepath, errForRead)
|
||||
}
|
||||
|
||||
// Filecmd hander for basic SFTP system calls related to files, but not anything to do with reading
|
||||
|
@ -272,7 +293,7 @@ func (c *Connection) handleSFTPRemove(filePath string, request *sftp.Request) er
|
|||
return c.RemoveFile(filePath, request.Filepath, fi)
|
||||
}
|
||||
|
||||
func (c *Connection) handleSFTPUploadToNewFile(resolvedPath, filePath, requestPath string) (io.WriterAt, error) {
|
||||
func (c *Connection) handleSFTPUploadToNewFile(resolvedPath, filePath, requestPath string, errForRead error) (sftp.WriterAtReaderAt, error) {
|
||||
quotaResult := c.HasSpace(true, requestPath)
|
||||
if !quotaResult.HasSpace {
|
||||
c.Log(logger.LevelInfo, "denying file write due to quota limits")
|
||||
|
@ -292,13 +313,13 @@ func (c *Connection) handleSFTPUploadToNewFile(resolvedPath, filePath, requestPa
|
|||
|
||||
baseTransfer := common.NewBaseTransfer(file, c.BaseConnection, cancelFn, resolvedPath, requestPath,
|
||||
common.TransferUpload, 0, 0, maxWriteSize, true, c.Fs)
|
||||
t := newTransfer(baseTransfer, w, nil)
|
||||
t := newTransfer(baseTransfer, w, nil, errForRead)
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (c *Connection) handleSFTPUploadToExistingFile(pflags sftp.FileOpenFlags, resolvedPath, filePath string,
|
||||
fileSize int64, requestPath string) (io.WriterAt, error) {
|
||||
fileSize int64, requestPath string, errForRead error) (sftp.WriterAtReaderAt, error) {
|
||||
var err error
|
||||
quotaResult := c.HasSpace(false, requestPath)
|
||||
if !quotaResult.HasSpace {
|
||||
|
@ -363,7 +384,7 @@ func (c *Connection) handleSFTPUploadToExistingFile(pflags sftp.FileOpenFlags, r
|
|||
|
||||
baseTransfer := common.NewBaseTransfer(file, c.BaseConnection, cancelFn, resolvedPath, requestPath,
|
||||
common.TransferUpload, minWriteOffset, initialSize, maxWriteSize, false, c.Fs)
|
||||
t := newTransfer(baseTransfer, w, nil)
|
||||
t := newTransfer(baseTransfer, w, nil, errForRead)
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/eikenb/pipeat"
|
||||
"github.com/pkg/sftp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"github.com/drakkan/sftpgo/common"
|
||||
|
@ -159,7 +160,7 @@ func TestUploadResumeInvalidOffset(t *testing.T) {
|
|||
fs := vfs.NewOsFs("", os.TempDir(), nil)
|
||||
conn := common.NewBaseConnection("", common.ProtocolSFTP, user, fs)
|
||||
baseTransfer := common.NewBaseTransfer(file, conn, nil, file.Name(), testfile, common.TransferUpload, 10, 0, 0, false, fs)
|
||||
transfer := newTransfer(baseTransfer, nil, nil)
|
||||
transfer := newTransfer(baseTransfer, nil, nil, nil)
|
||||
_, err = transfer.WriteAt([]byte("test"), 0)
|
||||
assert.Error(t, err, "upload with invalid offset must fail")
|
||||
if assert.Error(t, transfer.ErrTransfer) {
|
||||
|
@ -187,7 +188,7 @@ func TestReadWriteErrors(t *testing.T) {
|
|||
fs := vfs.NewOsFs("", os.TempDir(), nil)
|
||||
conn := common.NewBaseConnection("", common.ProtocolSFTP, user, fs)
|
||||
baseTransfer := common.NewBaseTransfer(file, conn, nil, file.Name(), testfile, common.TransferDownload, 0, 0, 0, false, fs)
|
||||
transfer := newTransfer(baseTransfer, nil, nil)
|
||||
transfer := newTransfer(baseTransfer, nil, nil, nil)
|
||||
err = file.Close()
|
||||
assert.NoError(t, err)
|
||||
_, err = transfer.WriteAt([]byte("test"), 0)
|
||||
|
@ -201,8 +202,8 @@ func TestReadWriteErrors(t *testing.T) {
|
|||
r, _, err := pipeat.Pipe()
|
||||
assert.NoError(t, err)
|
||||
baseTransfer = common.NewBaseTransfer(nil, conn, nil, file.Name(), testfile, common.TransferDownload, 0, 0, 0, false, fs)
|
||||
transfer = newTransfer(baseTransfer, nil, r)
|
||||
err = transfer.closeIO()
|
||||
transfer = newTransfer(baseTransfer, nil, r, nil)
|
||||
err = transfer.Close()
|
||||
assert.NoError(t, err)
|
||||
_, err = transfer.ReadAt(buf, 0)
|
||||
assert.Error(t, err, "reading from a closed pipe must fail")
|
||||
|
@ -211,7 +212,7 @@ func TestReadWriteErrors(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
pipeWriter := vfs.NewPipeWriter(w)
|
||||
baseTransfer = common.NewBaseTransfer(nil, conn, nil, file.Name(), testfile, common.TransferDownload, 0, 0, 0, false, fs)
|
||||
transfer = newTransfer(baseTransfer, pipeWriter, nil)
|
||||
transfer = newTransfer(baseTransfer, pipeWriter, nil, nil)
|
||||
|
||||
err = r.Close()
|
||||
assert.NoError(t, err)
|
||||
|
@ -224,9 +225,12 @@ func TestReadWriteErrors(t *testing.T) {
|
|||
assert.EqualError(t, err, errFake.Error())
|
||||
_, err = transfer.WriteAt([]byte("test"), 0)
|
||||
assert.Error(t, err, "writing to closed pipe must fail")
|
||||
err = transfer.BaseTransfer.Close()
|
||||
assert.EqualError(t, err, errFake.Error())
|
||||
|
||||
err = os.Remove(testfile)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, conn.GetTransfers(), 0)
|
||||
}
|
||||
|
||||
func TestUnsupportedListOP(t *testing.T) {
|
||||
|
@ -254,7 +258,7 @@ func TestTransferCancelFn(t *testing.T) {
|
|||
fs := vfs.NewOsFs("", os.TempDir(), nil)
|
||||
conn := common.NewBaseConnection("", common.ProtocolSFTP, user, fs)
|
||||
baseTransfer := common.NewBaseTransfer(file, conn, cancelFn, file.Name(), testfile, common.TransferDownload, 0, 0, 0, false, fs)
|
||||
transfer := newTransfer(baseTransfer, nil, nil)
|
||||
transfer := newTransfer(baseTransfer, nil, nil, nil)
|
||||
|
||||
errFake := errors.New("fake error, this will trigger cancelFn")
|
||||
transfer.TransferError(errFake)
|
||||
|
@ -293,7 +297,7 @@ func TestMockFsErrors(t *testing.T) {
|
|||
flags.Write = true
|
||||
flags.Trunc = false
|
||||
flags.Append = true
|
||||
_, err = c.handleSFTPUploadToExistingFile(flags, testfile, testfile, 0, "/testfile")
|
||||
_, err = c.handleSFTPUploadToExistingFile(flags, testfile, testfile, 0, "/testfile", nil)
|
||||
assert.EqualError(t, err, sftp.ErrSSHFxOpUnsupported.Error())
|
||||
|
||||
fs = newMockOsFs(errFake, nil, false, "123", os.TempDir())
|
||||
|
@ -321,18 +325,18 @@ func TestUploadFiles(t *testing.T) {
|
|||
var flags sftp.FileOpenFlags
|
||||
flags.Write = true
|
||||
flags.Trunc = true
|
||||
_, err := c.handleSFTPUploadToExistingFile(flags, "missing_path", "other_missing_path", 0, "/missing_path")
|
||||
_, err := c.handleSFTPUploadToExistingFile(flags, "missing_path", "other_missing_path", 0, "/missing_path", nil)
|
||||
assert.Error(t, err, "upload to existing file must fail if one or both paths are invalid")
|
||||
|
||||
common.Config.UploadMode = common.UploadModeStandard
|
||||
_, err = c.handleSFTPUploadToExistingFile(flags, "missing_path", "other_missing_path", 0, "/missing_path")
|
||||
_, err = c.handleSFTPUploadToExistingFile(flags, "missing_path", "other_missing_path", 0, "/missing_path", nil)
|
||||
assert.Error(t, err, "upload to existing file must fail if one or both paths are invalid")
|
||||
|
||||
missingFile := "missing/relative/file.txt"
|
||||
if runtime.GOOS == osWindows {
|
||||
missingFile = "missing\\relative\\file.txt"
|
||||
}
|
||||
_, err = c.handleSFTPUploadToNewFile(".", missingFile, "/missing")
|
||||
_, err = c.handleSFTPUploadToNewFile(".", missingFile, "/missing", nil)
|
||||
assert.Error(t, err, "upload new file in missing path must fail")
|
||||
|
||||
c.BaseConnection.Fs = newMockOsFs(nil, nil, false, "123", os.TempDir())
|
||||
|
@ -341,7 +345,7 @@ func TestUploadFiles(t *testing.T) {
|
|||
err = f.Close()
|
||||
assert.NoError(t, err)
|
||||
|
||||
tr, err := c.handleSFTPUploadToExistingFile(flags, f.Name(), f.Name(), 123, f.Name())
|
||||
tr, err := c.handleSFTPUploadToExistingFile(flags, f.Name(), f.Name(), 123, f.Name(), nil)
|
||||
if assert.NoError(t, err) {
|
||||
transfer := tr.(*transfer)
|
||||
transfers := c.GetTransfers()
|
||||
|
@ -990,7 +994,7 @@ func TestSystemCommandErrors(t *testing.T) {
|
|||
sshCmd.connection.channel = &mockSSHChannel
|
||||
baseTransfer := common.NewBaseTransfer(nil, sshCmd.connection.BaseConnection, nil, "", "", common.TransferDownload,
|
||||
0, 0, 0, false, fs)
|
||||
transfer := newTransfer(baseTransfer, nil, nil)
|
||||
transfer := newTransfer(baseTransfer, nil, nil, nil)
|
||||
destBuff := make([]byte, 65535)
|
||||
dst := bytes.NewBuffer(destBuff)
|
||||
_, err = transfer.copyFromReaderToWriter(dst, sshCmd.connection.channel)
|
||||
|
@ -1542,7 +1546,7 @@ func TestSCPUploadFiledata(t *testing.T) {
|
|||
|
||||
baseTransfer := common.NewBaseTransfer(file, scpCommand.connection.BaseConnection, nil, file.Name(),
|
||||
"/"+testfile, common.TransferDownload, 0, 0, 0, true, fs)
|
||||
transfer := newTransfer(baseTransfer, nil, nil)
|
||||
transfer := newTransfer(baseTransfer, nil, nil, nil)
|
||||
|
||||
err = scpCommand.getUploadFileData(2, transfer)
|
||||
assert.Error(t, err, "upload must fail, we send a fake write error message")
|
||||
|
@ -1574,7 +1578,7 @@ func TestSCPUploadFiledata(t *testing.T) {
|
|||
file, err = os.Create(testfile)
|
||||
assert.NoError(t, err)
|
||||
baseTransfer.File = file
|
||||
transfer = newTransfer(baseTransfer, nil, nil)
|
||||
transfer = newTransfer(baseTransfer, nil, nil, nil)
|
||||
transfer.Connection.AddTransfer(transfer)
|
||||
err = scpCommand.getUploadFileData(2, transfer)
|
||||
assert.Error(t, err, "upload must fail, we have not enough data to read")
|
||||
|
@ -1626,7 +1630,7 @@ func TestUploadError(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
baseTransfer := common.NewBaseTransfer(file, connection.BaseConnection, nil, testfile,
|
||||
testfile, common.TransferUpload, 0, 0, 0, true, fs)
|
||||
transfer := newTransfer(baseTransfer, nil, nil)
|
||||
transfer := newTransfer(baseTransfer, nil, nil, nil)
|
||||
|
||||
errFake := errors.New("fake error")
|
||||
transfer.TransferError(errFake)
|
||||
|
@ -1645,6 +1649,49 @@ func TestUploadError(t *testing.T) {
|
|||
common.Config.UploadMode = oldUploadMode
|
||||
}
|
||||
|
||||
func TestTransferFailingReader(t *testing.T) {
|
||||
user := dataprovider.User{
|
||||
Username: "testuser",
|
||||
}
|
||||
user.Permissions = make(map[string][]string)
|
||||
user.Permissions["/"] = []string{dataprovider.PermAny}
|
||||
|
||||
fs := newMockOsFs(nil, nil, true, "", os.TempDir())
|
||||
connection := &Connection{
|
||||
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, user, fs),
|
||||
}
|
||||
|
||||
request := sftp.NewRequest("Open", "afile.txt")
|
||||
request.Flags = 27 // read,write,create,truncate
|
||||
|
||||
transfer, err := connection.handleFilewrite(request)
|
||||
require.NoError(t, err)
|
||||
buf := make([]byte, 32)
|
||||
_, err = transfer.ReadAt(buf, 0)
|
||||
assert.EqualError(t, err, sftp.ErrSSHFxOpUnsupported.Error())
|
||||
if c, ok := transfer.(io.Closer); ok {
|
||||
err = c.Close()
|
||||
assert.EqualError(t, err, sftp.ErrSSHFxFailure.Error())
|
||||
}
|
||||
|
||||
fsPath := filepath.Join(os.TempDir(), "afile.txt")
|
||||
|
||||
r, _, err := pipeat.Pipe()
|
||||
assert.NoError(t, err)
|
||||
baseTransfer := common.NewBaseTransfer(nil, connection.BaseConnection, nil, fsPath, filepath.Base(fsPath), common.TransferUpload, 0, 0, 0, false, fs)
|
||||
errRead := errors.New("read is not allowed")
|
||||
tr := newTransfer(baseTransfer, nil, r, errRead)
|
||||
_, err = tr.ReadAt(buf, 0)
|
||||
assert.EqualError(t, err, errRead.Error())
|
||||
|
||||
err = tr.Close()
|
||||
assert.EqualError(t, err, sftp.ErrSSHFxFailure.Error())
|
||||
|
||||
err = os.Remove(fsPath)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, connection.GetTransfers(), 0)
|
||||
}
|
||||
|
||||
func TestConnectionStatusStruct(t *testing.T) {
|
||||
var transfers []common.ConnectionTransfer
|
||||
transferUL := common.ConnectionTransfer{
|
||||
|
|
|
@ -227,7 +227,7 @@ func (c *scpCommand) handleUploadFile(resolvedPath, filePath string, sizeToRead
|
|||
|
||||
baseTransfer := common.NewBaseTransfer(file, c.connection.BaseConnection, cancelFn, resolvedPath, requestPath,
|
||||
common.TransferUpload, 0, initialSize, maxWriteSize, isNewFile, c.connection.Fs)
|
||||
t := newTransfer(baseTransfer, w, nil)
|
||||
t := newTransfer(baseTransfer, w, nil, nil)
|
||||
|
||||
return c.getUploadFileData(sizeToRead, t)
|
||||
}
|
||||
|
@ -485,7 +485,7 @@ func (c *scpCommand) handleDownload(filePath string) error {
|
|||
|
||||
baseTransfer := common.NewBaseTransfer(file, c.connection.BaseConnection, cancelFn, p, filePath,
|
||||
common.TransferDownload, 0, 0, 0, false, c.connection.Fs)
|
||||
t := newTransfer(baseTransfer, nil, r)
|
||||
t := newTransfer(baseTransfer, nil, r, nil)
|
||||
|
||||
err = c.sendDownloadFileData(p, stat, t)
|
||||
// we need to call Close anyway and return close error if any and
|
||||
|
|
|
@ -359,6 +359,51 @@ func TestBasicSFTPHandling(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestOpenReadWrite(t *testing.T) {
|
||||
usePubKey := false
|
||||
u := getTestUser(usePubKey)
|
||||
u.QuotaSize = 6553600
|
||||
user, _, err := httpd.AddUser(u, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
client, err := getSftpClient(user, usePubKey)
|
||||
if assert.NoError(t, err) {
|
||||
defer client.Close()
|
||||
sftpFile, err := client.OpenFile(testFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC)
|
||||
if assert.NoError(t, err) {
|
||||
testData := []byte("test data")
|
||||
n, err := sftpFile.Write(testData)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(testData), n)
|
||||
buffer := make([]byte, 128)
|
||||
n, err = sftpFile.ReadAt(buffer, 1)
|
||||
assert.EqualError(t, err, io.EOF.Error())
|
||||
assert.Equal(t, len(testData)-1, n)
|
||||
assert.Equal(t, testData[1:], buffer[:n])
|
||||
sftpFile.Close()
|
||||
}
|
||||
sftpFile, err = client.OpenFile(testFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC)
|
||||
if assert.NoError(t, err) {
|
||||
testData := []byte("new test data")
|
||||
n, err := sftpFile.Write(testData)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(testData), n)
|
||||
buffer := make([]byte, 128)
|
||||
n, err = sftpFile.ReadAt(buffer, 1)
|
||||
assert.EqualError(t, err, io.EOF.Error())
|
||||
assert.Equal(t, len(testData)-1, n)
|
||||
assert.Equal(t, testData[1:], buffer[:n])
|
||||
sftpFile.Close()
|
||||
sftpFile.Close()
|
||||
}
|
||||
}
|
||||
_, err = httpd.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestConcurrency(t *testing.T) {
|
||||
usePubKey := true
|
||||
numLogins := 50
|
||||
|
|
|
@ -354,7 +354,7 @@ func (c *sshCommand) executeSystemCommand(command systemCommand) error {
|
|||
defer stdin.Close()
|
||||
baseTransfer := common.NewBaseTransfer(nil, c.connection.BaseConnection, nil, command.fsPath, sshDestPath,
|
||||
common.TransferUpload, 0, 0, remainingQuotaSize, false, c.connection.Fs)
|
||||
transfer := newTransfer(baseTransfer, nil, nil)
|
||||
transfer := newTransfer(baseTransfer, nil, nil, nil)
|
||||
|
||||
w, e := transfer.copyFromReaderToWriter(stdin, c.connection.channel)
|
||||
c.connection.Log(logger.LevelDebug, "command: %#v, copy from remote command to sdtin ended, written: %v, "+
|
||||
|
@ -367,7 +367,7 @@ func (c *sshCommand) executeSystemCommand(command systemCommand) error {
|
|||
go func() {
|
||||
baseTransfer := common.NewBaseTransfer(nil, c.connection.BaseConnection, nil, command.fsPath, sshDestPath,
|
||||
common.TransferDownload, 0, 0, 0, false, c.connection.Fs)
|
||||
transfer := newTransfer(baseTransfer, nil, nil)
|
||||
transfer := newTransfer(baseTransfer, nil, nil, nil)
|
||||
|
||||
w, e := transfer.copyFromReaderToWriter(c.connection.channel, stdout)
|
||||
c.connection.Log(logger.LevelDebug, "command: %#v, copy from sdtout to remote command ended, written: %v err: %v",
|
||||
|
@ -381,7 +381,7 @@ func (c *sshCommand) executeSystemCommand(command systemCommand) error {
|
|||
go func() {
|
||||
baseTransfer := common.NewBaseTransfer(nil, c.connection.BaseConnection, nil, command.fsPath, sshDestPath,
|
||||
common.TransferDownload, 0, 0, 0, false, c.connection.Fs)
|
||||
transfer := newTransfer(baseTransfer, nil, nil)
|
||||
transfer := newTransfer(baseTransfer, nil, nil, nil)
|
||||
|
||||
w, e := transfer.copyFromReaderToWriter(c.connection.channel.Stderr(), stderr)
|
||||
c.connection.Log(logger.LevelDebug, "command: %#v, copy from sdterr to remote command ended, written: %v err: %v",
|
||||
|
|
|
@ -22,6 +22,19 @@ type readerAtCloser interface {
|
|||
io.Closer
|
||||
}
|
||||
|
||||
type failingReader struct {
|
||||
innerReader readerAtCloser
|
||||
errRead error
|
||||
}
|
||||
|
||||
func (r *failingReader) ReadAt(p []byte, off int64) (n int, err error) {
|
||||
return 0, r.errRead
|
||||
}
|
||||
|
||||
func (r *failingReader) Close() error {
|
||||
return r.innerReader.Close()
|
||||
}
|
||||
|
||||
// transfer defines the transfer details.
|
||||
// It implements the io.ReaderAt and io.WriterAt interfaces to handle SFTP downloads and uploads
|
||||
type transfer struct {
|
||||
|
@ -31,16 +44,31 @@ type transfer struct {
|
|||
isFinished bool
|
||||
}
|
||||
|
||||
func newTransfer(baseTransfer *common.BaseTransfer, pipeWriter *vfs.PipeWriter, pipeReader *pipeat.PipeReaderAt) *transfer {
|
||||
func newTransfer(baseTransfer *common.BaseTransfer, pipeWriter *vfs.PipeWriter, pipeReader *pipeat.PipeReaderAt,
|
||||
errForRead error) *transfer {
|
||||
var writer writerAtCloser
|
||||
var reader readerAtCloser
|
||||
if baseTransfer.File != nil {
|
||||
writer = baseTransfer.File
|
||||
if errForRead == nil {
|
||||
reader = baseTransfer.File
|
||||
} else {
|
||||
reader = &failingReader{
|
||||
innerReader: baseTransfer.File,
|
||||
errRead: errForRead,
|
||||
}
|
||||
}
|
||||
} else if pipeWriter != nil {
|
||||
writer = pipeWriter
|
||||
} else if pipeReader != nil {
|
||||
if errForRead == nil {
|
||||
reader = pipeReader
|
||||
} else {
|
||||
reader = &failingReader{
|
||||
innerReader: pipeReader,
|
||||
errRead: errForRead,
|
||||
}
|
||||
}
|
||||
}
|
||||
return &transfer{
|
||||
BaseTransfer: baseTransfer,
|
||||
|
|
Loading…
Reference in a new issue