mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-22 07:30:25 +00:00
sftpd: fix relative symlinks handling
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
1e21aa9453
commit
0e8c41bbd1
6 changed files with 101 additions and 24 deletions
7
go.mod
7
go.mod
|
@ -15,7 +15,7 @@ require (
|
|||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.33
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.13.19
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.11
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.1
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.2
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.19
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.2.16
|
||||
github.com/coreos/go-oidc/v3 v3.4.0
|
||||
|
@ -109,7 +109,7 @@ require (
|
|||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.5.1 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
|
@ -156,7 +156,7 @@ require (
|
|||
golang.org/x/tools v0.1.12 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220927151529-dcaddaf36704 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220929141241-1ce7b20da813 // indirect
|
||||
google.golang.org/grpc v1.49.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
|
@ -167,6 +167,7 @@ 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-20220930161944-e8c89afc13a7
|
||||
golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20220925175854-fd2128ac8ea8
|
||||
golang.org/x/net => github.com/drakkan/net v0.0.0-20220925175748-018cd5f6a745
|
||||
)
|
||||
|
|
17
go.sum
17
go.sum
|
@ -190,8 +190,8 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.26.3/go.mod h1:g1qvDuRsJY+XghsV6zg00Z
|
|||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.11 h1:3/gm/JTX9bX8CpzTgIlrtYpB3EVBDxyg/GY/QdcIEZw=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.11/go.mod h1:fmgDANqTUCxciViKl9hb/zD5LFbvPINFRgWhDbR+vZo=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.4/go.mod h1:PJc8s+lxyU8rrre0/4a0pn2wgwiDvOEzoOjcJUBr67o=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.1 h1:eMsEmvJR6zQ1lDi59RDtCc62x9fKs1kv2b8A8nPpWmY=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.1/go.mod h1:HEBBc70BYi5eUvxBqC3xXjU/04NO96X/XNUe5qhC7Bc=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.2 h1:3x1Qilin49XQ1rK6pDNAfG+DmCFPfB7Rrpl+FUDAR/0=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.2/go.mod h1:HEBBc70BYi5eUvxBqC3xXjU/04NO96X/XNUe5qhC7Bc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sns v1.17.4/go.mod h1:kElt+uCcXxcqFyc+bQqZPFD9DME/eC6oHBXvFzQ9Bcw=
|
||||
github.com/aws/aws-sdk-go-v2/service/sqs v1.18.3/go.mod h1:skmQo0UPvsjsuYYSYMVmrPc1HWCbHUJyrCEp+ZaLzqM=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.24.1/go.mod h1:NR/xoKjdbRJ+qx0pMR4mI+N/H1I1ynHwXnO6FowXJc0=
|
||||
|
@ -270,6 +270,8 @@ github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9 h1:LPH1dEblAOO/LoG7yHP
|
|||
github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9/go.mod h1:2lmrmq866uF2tnje75wQHzmPXhmSWUt7Gyx2vgK1RCU=
|
||||
github.com/drakkan/net v0.0.0-20220925175748-018cd5f6a745 h1:Lgtp3izEEJFPxMLJfLWxc1htWNMZhK7EkBo0/dmEX4E=
|
||||
github.com/drakkan/net v0.0.0-20220925175748-018cd5f6a745/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
github.com/drakkan/sftp v0.0.0-20220930161944-e8c89afc13a7 h1:Hj7AAfZ5yt9QuCxSQDllRygmL33xJ2sZLOmcyyOAdYU=
|
||||
github.com/drakkan/sftp v0.0.0-20220930161944-e8c89afc13a7/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg=
|
||||
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001 h1:/ZshrfQzayqRSBDodmp3rhNCHJCff+utvgBuWRbiqu4=
|
||||
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001/go.mod h1:kltMsfRMTHSFdMbK66XdS8mfMW77+FZA1fGY1xYMF84=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
|
@ -441,8 +443,9 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
|||
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
|
||||
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0 h1:zO8WHNx/MYiAKJ3d5spxZXZE6KHmIQGQcAzwUzV7qQw=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
|
@ -665,9 +668,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pkg/sftp v1.13.6-0.20220831160757-628507938ec6 h1:hxLT9qX4jw+GjGuPA6XHtooT1+nf/hr5anQtACaXZmY=
|
||||
github.com/pkg/sftp v1.13.6-0.20220831160757-628507938ec6/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg=
|
||||
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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
|
@ -945,7 +945,6 @@ golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -1230,8 +1229,8 @@ google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP
|
|||
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220927151529-dcaddaf36704 h1:H1AcWFV69NFCMeBJ8nVLtv8uHZZ5Ozcgoq012hHEFuU=
|
||||
google.golang.org/genproto v0.0.0-20220927151529-dcaddaf36704/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
|
||||
google.golang.org/genproto v0.0.0-20220929141241-1ce7b20da813 h1:buul04Ikd79A5tP8nGhKEyMfr+/HplsO6nqSUapWZ/M=
|
||||
google.golang.org/genproto v0.0.0-20220929141241-1ce7b20da813/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
|
|
@ -546,6 +546,13 @@ func (c *BaseConnection) Rename(virtualSourcePath, virtualTargetPath string) err
|
|||
|
||||
// CreateSymlink creates fsTargetPath as a symbolic link to fsSourcePath
|
||||
func (c *BaseConnection) CreateSymlink(virtualSourcePath, virtualTargetPath string) error {
|
||||
var relativePath string
|
||||
if !path.IsAbs(virtualSourcePath) {
|
||||
relativePath = virtualSourcePath
|
||||
virtualSourcePath = path.Join(path.Dir(virtualTargetPath), relativePath)
|
||||
c.Log(logger.LevelDebug, "link relative path %q resolved as %q, target path %q",
|
||||
relativePath, virtualSourcePath, virtualTargetPath)
|
||||
}
|
||||
if c.isCrossFoldersRequest(virtualSourcePath, virtualTargetPath) {
|
||||
c.Log(logger.LevelWarn, "cross folder symlink is not supported, src: %v dst: %v", virtualSourcePath, virtualTargetPath)
|
||||
return c.GetOpUnsupportedError()
|
||||
|
@ -579,6 +586,9 @@ func (c *BaseConnection) CreateSymlink(virtualSourcePath, virtualTargetPath stri
|
|||
c.Log(logger.LevelError, "symlink target path %#v is not allowed", virtualTargetPath)
|
||||
return c.GetPermissionDeniedError()
|
||||
}
|
||||
if relativePath != "" {
|
||||
fsSourcePath = relativePath
|
||||
}
|
||||
if err := fs.Symlink(fsSourcePath, fsTargetPath); err != nil {
|
||||
c.Log(logger.LevelError, "failed to create symlink %#v -> %#v: %+v", fsSourcePath, fsTargetPath, err)
|
||||
return c.GetFsError(fs, err)
|
||||
|
|
|
@ -313,6 +313,71 @@ func TestBaseConnection(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestRelativeSymlinks(t *testing.T) {
|
||||
u := getTestUser()
|
||||
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
conn, client, err := getSftpClient(user)
|
||||
if assert.NoError(t, err) {
|
||||
defer conn.Close()
|
||||
defer client.Close()
|
||||
|
||||
linkName := testFileName + "_link"
|
||||
err = client.Symlink("non-existent-file", linkName)
|
||||
assert.NoError(t, err)
|
||||
err = client.Remove(linkName)
|
||||
assert.NoError(t, err)
|
||||
testDir := "sub"
|
||||
err = client.Mkdir(testDir)
|
||||
assert.NoError(t, err)
|
||||
f, err := client.Create(path.Join(testDir, testFileName))
|
||||
assert.NoError(t, err)
|
||||
_, err = f.Write(testFileContent)
|
||||
assert.NoError(t, err)
|
||||
err = f.Close()
|
||||
assert.NoError(t, err)
|
||||
err = client.Symlink(path.Join(testDir, testFileName), linkName)
|
||||
assert.NoError(t, err)
|
||||
_, err = client.Stat(linkName)
|
||||
assert.NoError(t, err)
|
||||
p, err := client.ReadLink(linkName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, path.Join("/", testDir, testFileName), p)
|
||||
err = client.Remove(linkName)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = client.Symlink(testFileName, path.Join(testDir, linkName))
|
||||
assert.NoError(t, err)
|
||||
_, err = client.Stat(path.Join(testDir, linkName))
|
||||
assert.NoError(t, err)
|
||||
p, err = client.ReadLink(path.Join(testDir, linkName))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, path.Join("/", testDir, testFileName), p)
|
||||
|
||||
f, err = client.Create(testFileName)
|
||||
assert.NoError(t, err)
|
||||
_, err = f.Write(testFileContent)
|
||||
assert.NoError(t, err)
|
||||
err = f.Close()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = client.Symlink(testFileName, linkName)
|
||||
assert.NoError(t, err)
|
||||
_, err = client.Stat(linkName)
|
||||
assert.NoError(t, err)
|
||||
p, err = client.ReadLink(linkName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, path.Join("/", testFileName), p)
|
||||
}
|
||||
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestCheckFsAfterUpdate(t *testing.T) {
|
||||
u := getTestUser()
|
||||
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||
|
@ -2264,19 +2329,19 @@ func TestVirtualFoldersLink(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath2, testDir, testFileName+".link"))
|
||||
assert.NoError(t, err)
|
||||
err = client.Symlink(testFileName, path.Join(vdirPath1, testFileName+".link1"))
|
||||
err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath1, testFileName+".link1"))
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
|
||||
}
|
||||
err = client.Symlink(testFileName, path.Join(vdirPath1, testDir, testFileName+".link1"))
|
||||
err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath1, testDir, testFileName+".link1"))
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
|
||||
}
|
||||
err = client.Symlink(testFileName, path.Join(vdirPath2, testFileName+".link1"))
|
||||
err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath2, testFileName+".link1"))
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
|
||||
}
|
||||
err = client.Symlink(testFileName, path.Join(vdirPath2, testDir, testFileName+".link1"))
|
||||
err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath2, testDir, testFileName+".link1"))
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
|
||||
}
|
||||
|
|
|
@ -607,7 +607,7 @@ func TestBasicSFTPFsHandling(t *testing.T) {
|
|||
err = client.Mkdir(linkDir)
|
||||
assert.NoError(t, err)
|
||||
linkToLinkPath := path.Join(linkDir, testLinkToLinkName)
|
||||
err = client.Symlink(testLinkName, linkToLinkPath)
|
||||
err = client.Symlink(path.Join("/", testLinkName), linkToLinkPath)
|
||||
assert.NoError(t, err)
|
||||
info, err = client.Lstat(linkToLinkPath)
|
||||
if assert.NoError(t, err) {
|
||||
|
@ -733,6 +733,8 @@ func TestSFTPFsEscapeHomeDir(t *testing.T) {
|
|||
// linkName points to a link inside the home dir and this link points to a dir outside the home dir
|
||||
_, err = client.ReadLink(linkName)
|
||||
assert.ErrorIs(t, err, os.ErrPermission)
|
||||
_, err = client.RealPath(linkName)
|
||||
assert.ErrorIs(t, err, os.ErrPermission)
|
||||
_, err = client.ReadDir(linkName)
|
||||
assert.ErrorIs(t, err, os.ErrPermission)
|
||||
_, err = client.ReadDir(path.Join(dirName, linkName))
|
||||
|
@ -1233,7 +1235,7 @@ func TestRealPath(t *testing.T) {
|
|||
err = client.Mkdir(subdir)
|
||||
assert.NoError(t, err)
|
||||
linkName := testFileName + "_link"
|
||||
err = client.Symlink(testFileName, path.Join(subdir, linkName))
|
||||
err = client.Symlink(path.Join("/", testFileName), path.Join(subdir, linkName))
|
||||
assert.NoError(t, err)
|
||||
p, err = client.RealPath(path.Join(subdir, linkName))
|
||||
assert.NoError(t, err)
|
||||
|
@ -6890,13 +6892,13 @@ func TestVirtualFoldersLink(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath2, testDir, testFileName+".link"))
|
||||
assert.NoError(t, err)
|
||||
err = client.Symlink(testFileName, path.Join(vdirPath1, testFileName+".link1"))
|
||||
err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath1, testFileName+".link1"))
|
||||
assert.Error(t, err)
|
||||
err = client.Symlink(testFileName, path.Join(vdirPath1, testDir, testFileName+".link1"))
|
||||
err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath1, testDir, testFileName+".link1"))
|
||||
assert.Error(t, err)
|
||||
err = client.Symlink(testFileName, path.Join(vdirPath2, testFileName+".link1"))
|
||||
err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath2, testFileName+".link1"))
|
||||
assert.Error(t, err)
|
||||
err = client.Symlink(testFileName, path.Join(vdirPath2, testDir, testFileName+".link1"))
|
||||
err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath2, testDir, testFileName+".link1"))
|
||||
assert.Error(t, err)
|
||||
err = client.Symlink(path.Join(vdirPath1, testFileName), testFileName+".link1")
|
||||
assert.Error(t, err)
|
||||
|
@ -7355,7 +7357,7 @@ func TestPermList(t *testing.T) {
|
|||
}
|
||||
err = client.Mkdir("sub")
|
||||
assert.NoError(t, err)
|
||||
err = client.Symlink(testFileName, path.Join("/sub", testFileName))
|
||||
err = client.Symlink(path.Join("/", testFileName), path.Join("/sub", testFileName))
|
||||
assert.NoError(t, err)
|
||||
_, err = client.ReadLink(path.Join("/sub", testFileName))
|
||||
assert.Error(t, err, "read remote link without permission on targe dir should not succeed")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
NFPM_VERSION=2.19.1
|
||||
NFPM_VERSION=2.19.2
|
||||
NFPM_ARCH=${NFPM_ARCH:-amd64}
|
||||
if [ -z ${SFTPGO_VERSION} ]
|
||||
then
|
||||
|
|
Loading…
Reference in a new issue