Commit f28fbbf1 authored by Jakob Unterwurzacher's avatar Jakob Unterwurzacher Committed by Han-Wen Nienhuys

loopback: use Lgetxattr and friends

Stop following symlinks when working with extended
attributes, and add a test for it.

Problem found by xfstests generic/062.

Change-Id: I67f94451322cdfebdcbcc3af21679ccd4e2800d7
parent 25660c21
...@@ -14,22 +14,22 @@ import ( ...@@ -14,22 +14,22 @@ import (
) )
func (n *loopbackNode) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) { func (n *loopbackNode) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
sz, err := syscall.Getxattr(n.path(), attr, dest) sz, err := unix.Lgetxattr(n.path(), attr, dest)
return uint32(sz), ToErrno(err) return uint32(sz), ToErrno(err)
} }
func (n *loopbackNode) Setxattr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno { func (n *loopbackNode) Setxattr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno {
err := syscall.Setxattr(n.path(), attr, data, int(flags)) err := unix.Lsetxattr(n.path(), attr, data, int(flags))
return ToErrno(err) return ToErrno(err)
} }
func (n *loopbackNode) Removexattr(ctx context.Context, attr string) syscall.Errno { func (n *loopbackNode) Removexattr(ctx context.Context, attr string) syscall.Errno {
err := syscall.Removexattr(n.path(), attr) err := unix.Lremovexattr(n.path(), attr)
return ToErrno(err) return ToErrno(err)
} }
func (n *loopbackNode) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) { func (n *loopbackNode) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
sz, err := syscall.Listxattr(n.path(), dest) sz, err := unix.Llistxattr(n.path(), dest)
return uint32(sz), ToErrno(err) return uint32(sz), ToErrno(err)
} }
......
...@@ -163,6 +163,28 @@ func TestXAttr(t *testing.T) { ...@@ -163,6 +163,28 @@ func TestXAttr(t *testing.T) {
} }
} }
// TestXAttrSymlink verifies that we did not forget to use Lgetxattr instead
// of Getxattr. This test is Linux-specific because it depends on the behavoir
// of the `security` namespace.
//
// On Linux, symlinks can not have xattrs in the `user` namespace, so we
// try to read something from `security`. Writing would need root rights,
// so don't even bother. See `man 7 xattr` for more info.
func TestXAttrSymlink(t *testing.T) {
tc := newTestCase(t, nil)
defer tc.Clean()
path := tc.mntDir + "/symlink"
if err := syscall.Symlink("target/does/not/exist", path); err != nil {
t.Fatal(err)
}
buf := make([]byte, 10)
_, err := unix.Lgetxattr(path, "security.foo", buf)
if err != unix.ENODATA {
t.Errorf("want %d=ENODATA, got error %d=%q instead", unix.ENODATA, err, err)
}
}
func TestCopyFileRange(t *testing.T) { func TestCopyFileRange(t *testing.T) {
tc := newTestCase(t, &testOptions{attrCache: true, entryCache: true}) tc := newTestCase(t, &testOptions{attrCache: true, entryCache: true})
defer tc.Clean() defer tc.Clean()
......
...@@ -32,6 +32,7 @@ type testCase struct { ...@@ -32,6 +32,7 @@ type testCase struct {
server *fuse.Server server *fuse.Server
} }
// writeOrig writes a file into the backing directory of the loopback mount
func (tc *testCase) writeOrig(path, content string, mode os.FileMode) { func (tc *testCase) writeOrig(path, content string, mode os.FileMode) {
if err := ioutil.WriteFile(filepath.Join(tc.origDir, path), []byte(content), mode); err != nil { if err := ioutil.WriteFile(filepath.Join(tc.origDir, path), []byte(content), mode); err != nil {
tc.Fatal(err) tc.Fatal(err)
...@@ -54,6 +55,8 @@ type testOptions struct { ...@@ -54,6 +55,8 @@ type testOptions struct {
testDir string testDir string
} }
// newTestCase creates the directories `orig` and `mnt` inside a temporary
// directory and mounts a loopback filesystem, backed by `orig`, on `mnt`.
func newTestCase(t *testing.T, opts *testOptions) *testCase { func newTestCase(t *testing.T, opts *testOptions) *testCase {
if opts == nil { if opts == nil {
opts = &testOptions{} opts = &testOptions{}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment