mirror of https://github.com/pkg/sftp.git
test parent directory before making a symlink
This commit is contained in:
parent
5b7cbe6684
commit
ffc579dce4
|
|
@ -194,6 +194,15 @@ func (fs *root) Filecmd(r *Request) error {
|
||||||
return os.ErrExist
|
return os.ErrExist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dir, err := fs.fetch(path.Dir(r.Target))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !dir.isdir {
|
||||||
|
return syscall.ENOTDIR
|
||||||
|
}
|
||||||
|
|
||||||
link := newMemFile(r.Target, false)
|
link := newMemFile(r.Target, false)
|
||||||
link.symlink = r.Filepath
|
link.symlink = r.Filepath
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -143,6 +144,16 @@ func putTestFile(cli *Client, path, content string) (int, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTestFile(cli *Client, path string) ([]byte, error) {
|
||||||
|
r, err := cli.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
|
||||||
|
return ioutil.ReadAll(r)
|
||||||
|
}
|
||||||
|
|
||||||
func TestRequestWrite(t *testing.T) {
|
func TestRequestWrite(t *testing.T) {
|
||||||
p := clientRequestServerPair(t)
|
p := clientRequestServerPair(t)
|
||||||
defer p.Close()
|
defer p.Close()
|
||||||
|
|
@ -504,59 +515,54 @@ func TestRequestSymlink(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, fi.Mode()&os.ModeSymlink == os.ModeSymlink)
|
assert.True(t, fi.Mode()&os.ModeSymlink == os.ModeSymlink)
|
||||||
|
|
||||||
file, err := p.cli.Open("/baz")
|
content, err := getTestFile(p.cli, "/baz")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer file.Close()
|
assert.Equal(t, []byte("hello"), content)
|
||||||
|
|
||||||
buf := make([]byte, 4)
|
|
||||||
n, err := file.ReadAt(buf, 1)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, 4, n)
|
|
||||||
assert.Equal(t, []byte{'e', 'l', 'l', 'o'}, buf)
|
|
||||||
|
|
||||||
checkRequestServerAllocator(t, p)
|
checkRequestServerAllocator(t, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRequestSymlinkFail(t *testing.T) {
|
func TestRequestSymlinkDanglingFiles(t *testing.T) {
|
||||||
p := clientRequestServerPair(t)
|
p := clientRequestServerPair(t)
|
||||||
defer p.Close()
|
defer p.Close()
|
||||||
|
|
||||||
// dangling links are ok.
|
// dangling links are ok. We will use "/foo" later.
|
||||||
err := p.cli.Symlink("/foo", "/bar")
|
err := p.cli.Symlink("/foo", "/bar")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// creating a symlink in a non-existant directory should fail.
|
||||||
|
err = p.cli.Symlink("/dangle", "/foo/bar")
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// creating a symlink under a dangling symlink should fail.
|
||||||
|
err = p.cli.Symlink("/dangle", "/bar/bar")
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
// opening a dangling link without O_CREATE should fail with os.IsNotExist == true
|
// opening a dangling link without O_CREATE should fail with os.IsNotExist == true
|
||||||
_, err = p.cli.OpenFile("/bar", os.O_RDONLY)
|
_, err = p.cli.OpenFile("/bar", os.O_RDONLY)
|
||||||
require.True(t, os.IsNotExist(err))
|
require.True(t, os.IsNotExist(err))
|
||||||
|
|
||||||
// overwriting links is not allowed.
|
// overwriting a symlink is not allowed.
|
||||||
err = p.cli.Symlink("/foo2", "/bar")
|
err = p.cli.Symlink("/dangle", "/bar")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
// double symlink
|
// double symlink
|
||||||
err = p.cli.Symlink("/bar", "/baz")
|
err = p.cli.Symlink("/bar", "/baz")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// opening a dangling link with O_CREATE should not fail, and make the file.
|
// opening a dangling link with O_CREATE should work.
|
||||||
file, err := p.cli.OpenFile("/baz", os.O_RDWR|os.O_CREATE)
|
_, err = putTestFile(p.cli, "/baz", "hello")
|
||||||
require.NoError(t, err)
|
|
||||||
n, err := file.Write([]byte("hello"))
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 5, n)
|
|
||||||
file.Close()
|
|
||||||
|
|
||||||
// dangling link creation should be reflected in target file itself.
|
|
||||||
file, err = p.cli.OpenFile("/foo", os.O_RDONLY)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
content := make([]byte, 5)
|
// dangling link creation should create the target file itself.
|
||||||
n, err = file.Read(content)
|
content, err := getTestFile(p.cli, "/foo")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 5, n)
|
|
||||||
file.Close()
|
|
||||||
|
|
||||||
assert.Equal(t, []byte("hello"), content)
|
assert.Equal(t, []byte("hello"), content)
|
||||||
|
|
||||||
|
// creating a symlink under a non-directory file should fail.
|
||||||
|
err = p.cli.Symlink("/dangle", "/foo/bar")
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
checkRequestServerAllocator(t, p)
|
checkRequestServerAllocator(t, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue