106 lines
3.1 KiB
Go
106 lines
3.1 KiB
Go
// Copyright 2018 The gVisor Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package fs_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"gvisor.dev/gvisor/pkg/sentry/context"
|
|
"gvisor.dev/gvisor/pkg/sentry/fs"
|
|
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
|
|
"gvisor.dev/gvisor/pkg/sentry/fs/ramfs"
|
|
"gvisor.dev/gvisor/pkg/sentry/kernel/contexttest"
|
|
)
|
|
|
|
// Creates a new MountNamespace with filesystem:
|
|
// / (root dir)
|
|
// |-foo (dir)
|
|
// |-bar (file)
|
|
func createMountNamespace(ctx context.Context) (*fs.MountNamespace, error) {
|
|
perms := fs.FilePermsFromMode(0777)
|
|
m := fs.NewPseudoMountSource(ctx)
|
|
|
|
barFile := fsutil.NewSimpleFileInode(ctx, fs.RootOwner, perms, 0)
|
|
fooDir := ramfs.NewDir(ctx, map[string]*fs.Inode{
|
|
"bar": fs.NewInode(ctx, barFile, m, fs.StableAttr{Type: fs.RegularFile}),
|
|
}, fs.RootOwner, perms)
|
|
rootDir := ramfs.NewDir(ctx, map[string]*fs.Inode{
|
|
"foo": fs.NewInode(ctx, fooDir, m, fs.StableAttr{Type: fs.Directory}),
|
|
}, fs.RootOwner, perms)
|
|
|
|
return fs.NewMountNamespace(ctx, fs.NewInode(ctx, rootDir, m, fs.StableAttr{Type: fs.Directory}))
|
|
}
|
|
|
|
func TestFindLink(t *testing.T) {
|
|
ctx := contexttest.Context(t)
|
|
mm, err := createMountNamespace(ctx)
|
|
if err != nil {
|
|
t.Fatalf("createMountNamespace failed: %v", err)
|
|
}
|
|
|
|
root := mm.Root()
|
|
defer root.DecRef()
|
|
foo, err := root.Walk(ctx, root, "foo")
|
|
if err != nil {
|
|
t.Fatalf("Error walking to foo: %v", err)
|
|
}
|
|
|
|
// Positive cases.
|
|
for _, tc := range []struct {
|
|
findPath string
|
|
wd *fs.Dirent
|
|
wantPath string
|
|
}{
|
|
{".", root, "/"},
|
|
{".", foo, "/foo"},
|
|
{"..", foo, "/"},
|
|
{"../../..", foo, "/"},
|
|
{"///foo", foo, "/foo"},
|
|
{"/foo", foo, "/foo"},
|
|
{"/foo/bar", foo, "/foo/bar"},
|
|
{"/foo/.///./bar", foo, "/foo/bar"},
|
|
{"/foo///bar", foo, "/foo/bar"},
|
|
{"/foo/../foo/bar", foo, "/foo/bar"},
|
|
{"foo/bar", root, "/foo/bar"},
|
|
{"foo////bar", root, "/foo/bar"},
|
|
{"bar", foo, "/foo/bar"},
|
|
} {
|
|
wdPath, _ := tc.wd.FullName(root)
|
|
maxTraversals := uint(0)
|
|
if d, err := mm.FindLink(ctx, root, tc.wd, tc.findPath, &maxTraversals); err != nil {
|
|
t.Errorf("FindLink(%q, wd=%q) failed: %v", tc.findPath, wdPath, err)
|
|
} else if got, _ := d.FullName(root); got != tc.wantPath {
|
|
t.Errorf("FindLink(%q, wd=%q) got dirent %q, want %q", tc.findPath, wdPath, got, tc.wantPath)
|
|
}
|
|
}
|
|
|
|
// Negative cases.
|
|
for _, tc := range []struct {
|
|
findPath string
|
|
wd *fs.Dirent
|
|
}{
|
|
{"bar", root},
|
|
{"/bar", root},
|
|
{"/foo/../../bar", root},
|
|
{"foo", foo},
|
|
} {
|
|
wdPath, _ := tc.wd.FullName(root)
|
|
maxTraversals := uint(0)
|
|
if _, err := mm.FindLink(ctx, root, tc.wd, tc.findPath, &maxTraversals); err == nil {
|
|
t.Errorf("FindLink(%q, wd=%q) did not return error", tc.findPath, wdPath)
|
|
}
|
|
}
|
|
}
|