Kaynağa Gözat

unix: add F*xattr on Darwin

Add Fgetxattr, Flistxattr, Fremovexattr and Fsetxattr on Darwin. Also
add a corresponding test.

Updates golang/go#26832

Change-Id: Id75bfce90ccc024b567a7b066a9188a615b9eec4
Reviewed-on: https://go-review.googlesource.com/128537
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Tobias Klauser 7 yıl önce
ebeveyn
işleme
904bdc2570

+ 26 - 6
unix/syscall_darwin.go

@@ -199,7 +199,13 @@ func Lgetxattr(link string, attr string, dest []byte) (sz int, err error) {
 	return getxattr(link, attr, xattrPointer(dest), len(dest), 0, XATTR_NOFOLLOW)
 }
 
-//sys  setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error)
+//sys	fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error)
+
+func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) {
+	return fgetxattr(fd, attr, xattrPointer(dest), len(dest), 0, 0)
+}
+
+//sys	setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error)
 
 func Setxattr(path string, attr string, data []byte, flags int) (err error) {
 	// The parameters for the OS X implementation vary slightly compared to the
@@ -235,7 +241,13 @@ func Lsetxattr(link string, attr string, data []byte, flags int) (err error) {
 	return setxattr(link, attr, xattrPointer(data), len(data), 0, flags|XATTR_NOFOLLOW)
 }
 
-//sys removexattr(path string, attr string, options int) (err error)
+//sys	fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error)
+
+func Fsetxattr(fd int, attr string, data []byte, flags int) (err error) {
+	return fsetxattr(fd, attr, xattrPointer(data), len(data), 0, 0)
+}
+
+//sys	removexattr(path string, attr string, options int) (err error)
 
 func Removexattr(path string, attr string) (err error) {
 	// We wrap around and explicitly zero out the options provided to the OS X
@@ -248,6 +260,12 @@ func Lremovexattr(link string, attr string) (err error) {
 	return removexattr(link, attr, XATTR_NOFOLLOW)
 }
 
+//sys	fremovexattr(fd int, attr string, options int) (err error)
+
+func Fremovexattr(fd int, attr string) (err error) {
+	return fremovexattr(fd, attr, 0)
+}
+
 //sys	listxattr(path string, dest *byte, size int, options int) (sz int, err error)
 
 func Listxattr(path string, dest []byte) (sz int, err error) {
@@ -258,6 +276,12 @@ func Llistxattr(link string, dest []byte) (sz int, err error) {
 	return listxattr(link, xattrPointer(dest), len(dest), XATTR_NOFOLLOW)
 }
 
+//sys	flistxattr(fd int, dest *byte, size int, options int) (sz int, err error)
+
+func Flistxattr(fd int, dest []byte) (sz int, err error) {
+	return flistxattr(fd, xattrPointer(dest), len(dest), 0)
+}
+
 func setattrlistTimes(path string, times []Timespec, flags int) error {
 	_p0, err := BytePtrFromString(path)
 	if err != nil {
@@ -529,10 +553,6 @@ func Uname(uname *Utsname) error {
 // Watchevent
 // Waitevent
 // Modwatch
-// Fgetxattr
-// Fsetxattr
-// Fremovexattr
-// Flistxattr
 // Fsctl
 // Initgroups
 // Posix_spawn

+ 82 - 0
unix/xattr_test.go

@@ -7,6 +7,7 @@
 package unix_test
 
 import (
+	"io/ioutil"
 	"os"
 	"runtime"
 	"strings"
@@ -117,3 +118,84 @@ func TestXattr(t *testing.T) {
 		}
 	}
 }
+
+func TestFdXattr(t *testing.T) {
+	file, err := ioutil.TempFile("", "TestFdXattr")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.Remove(file.Name())
+	defer file.Close()
+
+	fd := int(file.Fd())
+	xattrName := "user.test"
+	xattrDataSet := "gopher"
+
+	err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0)
+	if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
+		t.Skip("filesystem does not support extended attributes, skipping test")
+	} else if err != nil {
+		t.Fatalf("Fsetxattr: %v", err)
+	}
+
+	// find size
+	size, err := unix.Flistxattr(fd, nil)
+	if err != nil {
+		t.Fatalf("Flistxattr: %v", err)
+	}
+
+	if size <= 0 {
+		t.Fatalf("Flistxattr returned an empty list of attributes")
+	}
+
+	buf := make([]byte, size)
+	read, err := unix.Flistxattr(fd, buf)
+	if err != nil {
+		t.Fatalf("Flistxattr: %v", err)
+	}
+
+	xattrs := stringsFromByteSlice(buf[:read])
+
+	xattrWant := xattrName
+	if runtime.GOOS == "freebsd" {
+		// On FreeBSD, the namespace is stored separately from the xattr
+		// name and Listxattr doesn't return the namespace prefix.
+		xattrWant = strings.TrimPrefix(xattrWant, "user.")
+	}
+	found := false
+	for _, name := range xattrs {
+		if name == xattrWant {
+			found = true
+		}
+	}
+
+	if !found {
+		t.Errorf("Flistxattr did not return previously set attribute '%s'", xattrName)
+	}
+
+	// find size
+	size, err = unix.Fgetxattr(fd, xattrName, nil)
+	if err != nil {
+		t.Fatalf("Fgetxattr: %v", err)
+	}
+
+	if size <= 0 {
+		t.Fatalf("Fgetxattr returned an empty attribute")
+	}
+
+	xattrDataGet := make([]byte, size)
+	_, err = unix.Fgetxattr(fd, xattrName, xattrDataGet)
+	if err != nil {
+		t.Fatalf("Fgetxattr: %v", err)
+	}
+
+	got := string(xattrDataGet)
+	if got != xattrDataSet {
+		t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got)
+	}
+
+	err = unix.Fremovexattr(fd, xattrName)
+	if err != nil {
+		t.Fatalf("Fremovexattr: %v", err)
+	}
+}

+ 57 - 0
unix/zsyscall_darwin_386.go

@@ -420,6 +420,22 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options))
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -440,6 +456,21 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func removexattr(path string, attr string, options int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -460,6 +491,21 @@ func removexattr(path string, attr string, options int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fremovexattr(fd int, attr string, options int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func listxattr(path string, dest *byte, size int, options int) (sz int, err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -476,6 +522,17 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) {
+	r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0)
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func kill(pid int, signum int, posix int) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix))
 	if e1 != 0 {

+ 57 - 0
unix/zsyscall_darwin_amd64.go

@@ -420,6 +420,22 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options))
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -440,6 +456,21 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func removexattr(path string, attr string, options int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -460,6 +491,21 @@ func removexattr(path string, attr string, options int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fremovexattr(fd int, attr string, options int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func listxattr(path string, dest *byte, size int, options int) (sz int, err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -476,6 +522,17 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) {
+	r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0)
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func kill(pid int, signum int, posix int) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix))
 	if e1 != 0 {

+ 57 - 0
unix/zsyscall_darwin_arm.go

@@ -420,6 +420,22 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options))
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -440,6 +456,21 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func removexattr(path string, attr string, options int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -460,6 +491,21 @@ func removexattr(path string, attr string, options int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fremovexattr(fd int, attr string, options int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func listxattr(path string, dest *byte, size int, options int) (sz int, err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -476,6 +522,17 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) {
+	r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0)
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func kill(pid int, signum int, posix int) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix))
 	if e1 != 0 {

+ 57 - 0
unix/zsyscall_darwin_arm64.go

@@ -420,6 +420,22 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options))
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -440,6 +456,21 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func removexattr(path string, attr string, options int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -460,6 +491,21 @@ func removexattr(path string, attr string, options int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func fremovexattr(fd int, attr string, options int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func listxattr(path string, dest *byte, size int, options int) (sz int, err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -476,6 +522,17 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) {
+	r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0)
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func kill(pid int, signum int, posix int) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix))
 	if e1 != 0 {