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