test parent directory before making a symlink

This commit is contained in:
Cassondra Foesch 2020-09-17 14:48:19 +00:00
parent 5b7cbe6684
commit ffc579dce4
2 changed files with 42 additions and 27 deletions

View File

@ -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

View File

@ -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)
} }