From 77b0e4315053a57ed2962443614bdb28db152054 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 22 May 2018 15:00:26 +0200 Subject: [PATCH] unix: add symlink-safe *xattr functions on darwin Updates golang/go#14456 Change-Id: I04632ef1d302e938a2cc373eb90f600f01404380 Reviewed-on: https://go-review.googlesource.com/114198 Run-TryBot: Tobias Klauser TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- unix/mkerrors.sh | 3 ++- unix/syscall_darwin.go | 41 +++++++++++++++++++++++------------- unix/xattr_test.go | 26 +++++++++++++++++++++++ unix/zerrors_darwin_386.go | 6 ++++++ unix/zerrors_darwin_amd64.go | 6 ++++++ unix/zerrors_darwin_arm.go | 6 ++++++ unix/zerrors_darwin_arm64.go | 6 ++++++ 7 files changed, 78 insertions(+), 16 deletions(-) diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh index e88bee07..3b7d6235 100755 --- a/unix/mkerrors.sh +++ b/unix/mkerrors.sh @@ -50,6 +50,7 @@ includes_Darwin=' #include #include #include +#include #include #include #include @@ -437,7 +438,7 @@ ccflags="$@" $2 ~ /^GENL_/ || $2 ~ /^STATX_/ || $2 ~ /^UTIME_/ || - $2 ~ /^XATTR_(CREATE|REPLACE)/ || + $2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ || $2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ || $2 ~ /^FSOPT_/ || $2 ~ /^WDIOC_/ || diff --git a/unix/syscall_darwin.go b/unix/syscall_darwin.go index 279cae16..79e94767 100644 --- a/unix/syscall_darwin.go +++ b/unix/syscall_darwin.go @@ -176,9 +176,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { return } -//sys getxattr(path string, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) - -func Getxattr(path string, attr string, dest []byte) (sz int, err error) { +func xattrPointer(dest []byte) *byte { // It's only when dest is set to NULL that the OS X implementations of // getxattr() and listxattr() return the current sizes of the named attributes. // An empty byte array is not sufficient. To maintain the same behaviour as the @@ -188,7 +186,17 @@ func Getxattr(path string, attr string, dest []byte) (sz int, err error) { if len(dest) > 0 { destp = &dest[0] } - return getxattr(path, attr, destp, len(dest), 0, 0) + return destp +} + +//sys getxattr(path string, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) + +func Getxattr(path string, attr string, dest []byte) (sz int, err error) { + return getxattr(path, attr, xattrPointer(dest), len(dest), 0, 0) +} + +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) @@ -220,11 +228,11 @@ func Setxattr(path string, attr string, data []byte, flags int) (err error) { // current implementation, only the resource fork extended attribute makes // use of this argument. For all others, position is reserved. We simply // default to setting it to zero. - var datap *byte - if len(data) > 0 { - datap = &data[0] - } - return setxattr(path, attr, datap, len(data), 0, flags) + return setxattr(path, attr, xattrPointer(data), len(data), 0, flags) +} + +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) @@ -236,15 +244,18 @@ func Removexattr(path string, attr string) (err error) { return removexattr(path, attr, 0) } +func Lremovexattr(link string, attr string) (err error) { + return removexattr(link, attr, XATTR_NOFOLLOW) +} + //sys listxattr(path string, dest *byte, size int, options int) (sz int, err error) func Listxattr(path string, dest []byte) (sz int, err error) { - // See comment in Getxattr for as to why Listxattr is implemented as such. - var destp *byte - if len(dest) > 0 { - destp = &dest[0] - } - return listxattr(path, destp, len(dest), 0) + return listxattr(path, xattrPointer(dest), len(dest), 0) +} + +func Llistxattr(link string, dest []byte) (sz int, err error) { + return listxattr(link, xattrPointer(dest), len(dest), XATTR_NOFOLLOW) } func setattrlistTimes(path string, times []Timespec, flags int) error { diff --git a/unix/xattr_test.go b/unix/xattr_test.go index 78cf9224..fb846a7b 100644 --- a/unix/xattr_test.go +++ b/unix/xattr_test.go @@ -7,6 +7,7 @@ package unix_test import ( + "os" "runtime" "strings" "testing" @@ -89,4 +90,29 @@ func TestXattr(t *testing.T) { if err != nil { t.Fatalf("Removexattr: %v", err) } + + n := "nonexistent" + err = unix.Lsetxattr(n, xattrName, []byte(xattrDataSet), 0) + if err != unix.ENOENT { + t.Errorf("Lsetxattr: expected %v on non-existent file, got %v", unix.ENOENT, err) + } + + _, err = unix.Lgetxattr(n, xattrName, nil) + if err != unix.ENOENT { + t.Errorf("Lgetxattr: %v", err) + } + + s := "symlink1" + err = os.Symlink(n, s) + if err != nil { + t.Fatal(err) + } + + // Linux doesn't support xattrs on symlink according to xattr(7), so + // just test that we get the proper errors. + + err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0) + if err != nil && (runtime.GOOS != "linux" || err != unix.EPERM) { + t.Fatalf("Lsetxattr: %v", err) + } } diff --git a/unix/zerrors_darwin_386.go b/unix/zerrors_darwin_386.go index c5a9b73d..3b39d740 100644 --- a/unix/zerrors_darwin_386.go +++ b/unix/zerrors_darwin_386.go @@ -1473,6 +1473,12 @@ const ( WORDSIZE = 0x20 WSTOPPED = 0x8 WUNTRACED = 0x2 + XATTR_CREATE = 0x2 + XATTR_NODEFAULT = 0x10 + XATTR_NOFOLLOW = 0x1 + XATTR_NOSECURITY = 0x8 + XATTR_REPLACE = 0x4 + XATTR_SHOWCOMPRESSION = 0x20 ) // Errors diff --git a/unix/zerrors_darwin_amd64.go b/unix/zerrors_darwin_amd64.go index 7de222b6..8fe55477 100644 --- a/unix/zerrors_darwin_amd64.go +++ b/unix/zerrors_darwin_amd64.go @@ -1473,6 +1473,12 @@ const ( WORDSIZE = 0x40 WSTOPPED = 0x8 WUNTRACED = 0x2 + XATTR_CREATE = 0x2 + XATTR_NODEFAULT = 0x10 + XATTR_NOFOLLOW = 0x1 + XATTR_NOSECURITY = 0x8 + XATTR_REPLACE = 0x4 + XATTR_SHOWCOMPRESSION = 0x20 ) // Errors diff --git a/unix/zerrors_darwin_arm.go b/unix/zerrors_darwin_arm.go index 33a42e78..7a977770 100644 --- a/unix/zerrors_darwin_arm.go +++ b/unix/zerrors_darwin_arm.go @@ -1473,6 +1473,12 @@ const ( WORDSIZE = 0x40 WSTOPPED = 0x8 WUNTRACED = 0x2 + XATTR_CREATE = 0x2 + XATTR_NODEFAULT = 0x10 + XATTR_NOFOLLOW = 0x1 + XATTR_NOSECURITY = 0x8 + XATTR_REPLACE = 0x4 + XATTR_SHOWCOMPRESSION = 0x20 ) // Errors diff --git a/unix/zerrors_darwin_arm64.go b/unix/zerrors_darwin_arm64.go index 71805155..6d56d8a0 100644 --- a/unix/zerrors_darwin_arm64.go +++ b/unix/zerrors_darwin_arm64.go @@ -1473,6 +1473,12 @@ const ( WORDSIZE = 0x40 WSTOPPED = 0x8 WUNTRACED = 0x2 + XATTR_CREATE = 0x2 + XATTR_NODEFAULT = 0x10 + XATTR_NOFOLLOW = 0x1 + XATTR_NOSECURITY = 0x8 + XATTR_REPLACE = 0x4 + XATTR_SHOWCOMPRESSION = 0x20 ) // Errors