Commit 5ee141ce authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Use XAttr functions provided by syscall package.

parent e41b8b68
...@@ -26,13 +26,14 @@ func (fs *loopbackFileSystem) StatFs(name string) *fuse.StatfsOut { ...@@ -26,13 +26,14 @@ func (fs *loopbackFileSystem) StatFs(name string) *fuse.StatfsOut {
} }
func (fs *loopbackFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) { func (fs *loopbackFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
data, errNo := ListXAttr(fs.GetPath(name)) data, err := listXAttr(fs.GetPath(name))
return data, fuse.Status(errNo) return data, fuse.ToStatus(err)
} }
func (fs *loopbackFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status { func (fs *loopbackFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
return fuse.Status(Removexattr(fs.GetPath(name), attr)) err := syscall.Removexattr(fs.GetPath(name), attr)
return fuse.ToStatus(err)
} }
func (fs *loopbackFileSystem) String() string { func (fs *loopbackFileSystem) String() string {
...@@ -41,7 +42,7 @@ func (fs *loopbackFileSystem) String() string { ...@@ -41,7 +42,7 @@ func (fs *loopbackFileSystem) String() string {
func (fs *loopbackFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) { func (fs *loopbackFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
data := make([]byte, 1024) data := make([]byte, 1024)
data, errNo := GetXAttr(fs.GetPath(name), attr, data) data, err := getXAttr(fs.GetPath(name), attr, data)
return data, fuse.Status(errNo) return data, fuse.ToStatus(err)
} }
...@@ -3,62 +3,32 @@ package pathfs ...@@ -3,62 +3,32 @@ package pathfs
import ( import (
"bytes" "bytes"
"syscall" "syscall"
"unsafe"
) )
func getxattr(path string, attr string, dest []byte) (sz int, errno int) { func getXAttr(path string, attr string, dest []byte) (value []byte, err error) {
pathBs := syscall.StringBytePtr(path) sz, err := syscall.Getxattr(path, attr, dest)
attrBs := syscall.StringBytePtr(attr) for sz > cap(dest) && err == nil {
size, _, errNo := syscall.Syscall6(
syscall.SYS_GETXATTR,
uintptr(unsafe.Pointer(pathBs)),
uintptr(unsafe.Pointer(attrBs)),
uintptr(unsafe.Pointer(&dest[0])),
uintptr(len(dest)),
0, 0)
return int(size), int(errNo)
}
func GetXAttr(path string, attr string, dest []byte) (value []byte, errno int) {
sz, errno := getxattr(path, attr, dest)
for sz > cap(dest) && errno == 0 {
dest = make([]byte, sz) dest = make([]byte, sz)
sz, errno = getxattr(path, attr, dest) sz, err = syscall.Getxattr(path, attr, dest)
} }
if errno != 0 { if err != nil {
return nil, errno return nil, err
} }
return dest[:sz], errno return dest[:sz], err
} }
func listxattr(path string, dest []byte) (sz int, errno int) { func listXAttr(path string) (attributes []string, err error) {
pathbs := syscall.StringBytePtr(path)
var destPointer unsafe.Pointer
if len(dest) > 0 {
destPointer = unsafe.Pointer(&dest[0])
}
size, _, errNo := syscall.Syscall(
syscall.SYS_LISTXATTR,
uintptr(unsafe.Pointer(pathbs)),
uintptr(destPointer),
uintptr(len(dest)))
return int(size), int(errNo)
}
func ListXAttr(path string) (attributes []string, errno int) {
dest := make([]byte, 0) dest := make([]byte, 0)
sz, errno := listxattr(path, dest) sz, err := syscall.Listxattr(path, dest)
if errno != 0 { if err != nil {
return nil, errno return nil, err
} }
for sz > cap(dest) && errno == 0 { for sz > cap(dest) && err == nil {
dest = make([]byte, sz) dest = make([]byte, sz)
sz, errno = listxattr(path, dest) sz, err = syscall.Listxattr(path, dest)
} }
// -1 to drop the final empty slice. // -1 to drop the final empty slice.
...@@ -68,29 +38,6 @@ func ListXAttr(path string) (attributes []string, errno int) { ...@@ -68,29 +38,6 @@ func ListXAttr(path string) (attributes []string, errno int) {
for i, v := range attributesBytes { for i, v := range attributesBytes {
attributes[i] = string(v) attributes[i] = string(v)
} }
return attributes, errno return attributes, err
} }
func Setxattr(path string, attr string, data []byte, flags int) (errno int) {
pathbs := syscall.StringBytePtr(path)
attrbs := syscall.StringBytePtr(attr)
_, _, errNo := syscall.Syscall6(
syscall.SYS_SETXATTR,
uintptr(unsafe.Pointer(pathbs)),
uintptr(unsafe.Pointer(attrbs)),
uintptr(unsafe.Pointer(&data[0])),
uintptr(len(data)),
uintptr(flags), 0)
return int(errNo)
}
func Removexattr(path string, attr string) (errno int) {
pathbs := syscall.StringBytePtr(path)
attrbs := syscall.StringBytePtr(attr)
_, _, errNo := syscall.Syscall(
syscall.SYS_REMOVEXATTR,
uintptr(unsafe.Pointer(pathbs)),
uintptr(unsafe.Pointer(attrbs)), 0)
return int(errNo)
}
...@@ -100,9 +100,9 @@ func (fs *XAttrTestFs) RemoveXAttr(name string, attr string, context *fuse.Conte ...@@ -100,9 +100,9 @@ func (fs *XAttrTestFs) RemoveXAttr(name string, attr string, context *fuse.Conte
return fuse.OK return fuse.OK
} }
func readXAttr(p, a string) (val []byte, errno int) { func readXAttr(p, a string) (val []byte, err error) {
val = make([]byte, 1024) val = make([]byte, 1024)
return GetXAttr(p, a, val) return getXAttr(p, a, val)
} }
func xattrTestCase(t *testing.T, nm string) (mountPoint string, cleanup func()) { func xattrTestCase(t *testing.T, nm string) (mountPoint string, cleanup func()) {
...@@ -138,8 +138,8 @@ func TestXAttrNoExist(t *testing.T) { ...@@ -138,8 +138,8 @@ func TestXAttrNoExist(t *testing.T) {
t.Error("Unexpected stat error", err) t.Error("Unexpected stat error", err)
} }
val, errno := readXAttr(mounted, "noexist") val, err := readXAttr(mounted, "noexist")
if errno == 0 { if err == nil {
t.Error("Expected GetXAttr error", val) t.Error("Expected GetXAttr error", val)
} }
} }
...@@ -150,15 +150,15 @@ func TestXAttrRead(t *testing.T) { ...@@ -150,15 +150,15 @@ func TestXAttrRead(t *testing.T) {
defer clean() defer clean()
mounted := filepath.Join(mountPoint, nm) mounted := filepath.Join(mountPoint, nm)
attrs, errno := ListXAttr(mounted) attrs, err := listXAttr(mounted)
readback := make(map[string][]byte) readback := make(map[string][]byte)
if errno != 0 { if err != nil {
t.Error("Unexpected ListXAttr error", errno) t.Error("Unexpected ListXAttr error", err)
} else { } else {
for _, a := range attrs { for _, a := range attrs {
val, errno := readXAttr(mounted, a) val, err := readXAttr(mounted, a)
if errno != 0 { if err != nil {
t.Errorf("GetXAttr(%q) failed: %v", a, syscall.Errno(errno)) t.Errorf("GetXAttr(%q) failed: %v", a, err)
} }
readback[a] = val readback[a] = val
} }
...@@ -174,18 +174,18 @@ func TestXAttrRead(t *testing.T) { ...@@ -174,18 +174,18 @@ func TestXAttrRead(t *testing.T) {
} }
} }
errno = Setxattr(mounted, "third", []byte("value"), 0) err = syscall.Setxattr(mounted, "third", []byte("value"), 0)
if errno != 0 { if err != nil {
t.Error("Setxattr error", errno) t.Error("Setxattr error", err)
} }
val, errno := readXAttr(mounted, "third") val, err := readXAttr(mounted, "third")
if errno != 0 || string(val) != "value" { if err != nil || string(val) != "value" {
t.Error("Read back set xattr:", errno, string(val)) t.Error("Read back set xattr:", err, string(val))
} }
Removexattr(mounted, "third") syscall.Removexattr(mounted, "third")
val, errno = readXAttr(mounted, "third") val, err = readXAttr(mounted, "third")
if errno != int(fuse.ENODATA) { if err != syscall.ENODATA {
t.Error("Data not removed?", errno, val) t.Error("Data not removed?", err, val)
} }
} }
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