Fix BasePathFs symlink

1. Support related path
2. Make ReadlinkIfPossible return path under basepath

Fixes #282
This commit is contained in:
ronyweng 2020-12-28 13:59:01 +08:00
parent 32b5faae5b
commit e597de429b
2 changed files with 55 additions and 4 deletions

View File

@ -185,10 +185,13 @@ func (b *BasePathFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
} }
func (b *BasePathFs) SymlinkIfPossible(oldname, newname string) error { func (b *BasePathFs) SymlinkIfPossible(oldname, newname string) error {
oldname, err := b.RealPath(oldname) var err error
if filepath.IsAbs(oldname) {
oldname, err = b.RealPath(oldname)
if err != nil { if err != nil {
return &os.LinkError{Op: "symlink", Old: oldname, New: newname, Err: err} return &os.LinkError{Op: "symlink", Old: oldname, New: newname, Err: err}
} }
}
newname, err = b.RealPath(newname) newname, err = b.RealPath(newname)
if err != nil { if err != nil {
return &os.LinkError{Op: "symlink", Old: oldname, New: newname, Err: err} return &os.LinkError{Op: "symlink", Old: oldname, New: newname, Err: err}
@ -205,7 +208,14 @@ func (b *BasePathFs) ReadlinkIfPossible(name string) (string, error) {
return "", &os.PathError{Op: "readlink", Path: name, Err: err} return "", &os.PathError{Op: "readlink", Path: name, Err: err}
} }
if reader, ok := b.source.(LinkReader); ok { if reader, ok := b.source.(LinkReader); ok {
return reader.ReadlinkIfPossible(name) linkpath, err := reader.ReadlinkIfPossible(name)
if err != nil {
return "", err
}
if filepath.IsAbs(linkpath) {
linkpath = strings.TrimPrefix(filepath.Clean(linkpath), filepath.Clean(b.path))
}
return linkpath, nil
} }
return "", &os.PathError{Op: "readlink", Path: name, Err: ErrNoReadlink} return "", &os.PathError{Op: "readlink", Path: name, Err: ErrNoReadlink}
} }

View File

@ -188,3 +188,44 @@ func TestBasePathTempFile(t *testing.T) {
t.Fatalf("TempFile realpath leaked: expected %s, got %s", expected, actual) t.Fatalf("TempFile realpath leaked: expected %s, got %s", expected, actual)
} }
} }
func TestBasePathSymlink(t *testing.T) {
type SymlinkTest struct {
Testcase, Link, Target string
}
symlinkTests := []SymlinkTest{
{Testcase: "Absolute path", Link: "/foo/baz/abs_link", Target: "/foo/file"},
{Testcase: "Relative path", Link: "/foo/baz/ref_link", Target: "../file"},
}
fs := NewOsFs()
baseDir, err := TempDir(fs, "", "base")
if err != nil {
t.Fatal("error creating tempDir", err)
}
defer fs.RemoveAll(baseDir)
var bp Fs = NewBasePathFs(fs, baseDir).(*BasePathFs)
bp.MkdirAll("/foo/baz", 0777)
bp.Create("/foo/file")
linker, _ := bp.(Linker)
lreader, _ := bp.(LinkReader)
for _, test := range symlinkTests {
err = linker.SymlinkIfPossible(test.Target, test.Link)
if err != nil {
t.Errorf("%s: error creating symlink %s", test.Testcase, err.Error())
}
linkpath, err := lreader.ReadlinkIfPossible(test.Link)
if err != nil {
t.Errorf("%s: error read symlink %s", test.Testcase, err.Error())
}
if linkpath != test.Target {
t.Errorf("%s: link not match %s != %s", test.Testcase, linkpath, test.Target)
}
_, err = bp.Stat(test.Link)
if err != nil {
t.Errorf("%s: error stat symlink %s", test.Testcase, err.Error())
}
}
}