From eb9be4e8841bfd477e768f9f513fd5693408dfde Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Thu, 16 Feb 2017 14:25:47 +0100 Subject: [PATCH] Use github.com/pkg/xattr for extended attributes --- vendor/manifest | 12 +- .../src/github.com/ivaxer/go-xattr/README.md | 10 - .../ivaxer/go-xattr/syscall_darwin.go | 156 ---------------- .../ivaxer/go-xattr/syscall_linux.go | 21 --- .../src/github.com/ivaxer/go-xattr/xattr.go | 171 ------------------ .../ivaxer/go-xattr/xattr_darwin.go | 9 - .../github.com/ivaxer/go-xattr/xattr_linux.go | 9 - .../github.com/ivaxer/go-xattr/xattr_test.go | 153 ---------------- .../go-xattr/LICENCE => pkg/xattr/LICENSE} | 2 +- vendor/src/github.com/pkg/xattr/README.md | 21 +++ .../github.com/pkg/xattr/syscall_darwin.go | 39 ++++ .../github.com/pkg/xattr/syscall_freebsd.go | 91 ++++++++++ vendor/src/github.com/pkg/xattr/xattr.go | 26 +++ .../src/github.com/pkg/xattr/xattr_darwin.go | 56 ++++++ .../src/github.com/pkg/xattr/xattr_freebsd.go | 79 ++++++++ .../src/github.com/pkg/xattr/xattr_linux.go | 54 ++++++ vendor/src/github.com/pkg/xattr/xattr_test.go | 57 ++++++ 17 files changed, 430 insertions(+), 536 deletions(-) delete mode 100644 vendor/src/github.com/ivaxer/go-xattr/README.md delete mode 100644 vendor/src/github.com/ivaxer/go-xattr/syscall_darwin.go delete mode 100644 vendor/src/github.com/ivaxer/go-xattr/syscall_linux.go delete mode 100644 vendor/src/github.com/ivaxer/go-xattr/xattr.go delete mode 100644 vendor/src/github.com/ivaxer/go-xattr/xattr_darwin.go delete mode 100644 vendor/src/github.com/ivaxer/go-xattr/xattr_linux.go delete mode 100644 vendor/src/github.com/ivaxer/go-xattr/xattr_test.go rename vendor/src/github.com/{ivaxer/go-xattr/LICENCE => pkg/xattr/LICENSE} (95%) create mode 100644 vendor/src/github.com/pkg/xattr/README.md create mode 100644 vendor/src/github.com/pkg/xattr/syscall_darwin.go create mode 100644 vendor/src/github.com/pkg/xattr/syscall_freebsd.go create mode 100644 vendor/src/github.com/pkg/xattr/xattr.go create mode 100644 vendor/src/github.com/pkg/xattr/xattr_darwin.go create mode 100644 vendor/src/github.com/pkg/xattr/xattr_freebsd.go create mode 100644 vendor/src/github.com/pkg/xattr/xattr_linux.go create mode 100644 vendor/src/github.com/pkg/xattr/xattr_test.go diff --git a/vendor/manifest b/vendor/manifest index bbefc5d0b..53d94c88d 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -19,12 +19,6 @@ "revision": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75", "branch": "master" }, - { - "importpath": "github.com/ivaxer/go-xattr", - "repository": "https://github.com/ivaxer/go-xattr", - "revision": "1a541654d8e447148cf23d472c948f9f0078ac50", - "branch": "master" - }, { "importpath": "github.com/kr/fs", "repository": "https://github.com/kr/fs", @@ -55,6 +49,12 @@ "revision": "8197a2e580736b78d704be0fc47b2324c0591a32", "branch": "master" }, + { + "importpath": "github.com/pkg/xattr", + "repository": "https://github.com/pkg/xattr", + "revision": "1d40b70a947cd8e8457e4715e1123f8e99f5f241", + "branch": "master" + }, { "importpath": "github.com/restic/chunker", "repository": "https://github.com/restic/chunker", diff --git a/vendor/src/github.com/ivaxer/go-xattr/README.md b/vendor/src/github.com/ivaxer/go-xattr/README.md deleted file mode 100644 index 9f3a71b56..000000000 --- a/vendor/src/github.com/ivaxer/go-xattr/README.md +++ /dev/null @@ -1,10 +0,0 @@ -xattr -===== - -Package xattr provides a simple interface to user extended attributes on Linux and OSX. - -Install it: `go get github.com/ivaxer/go-xattr` - -Documentation is available on [godoc.org](http://godoc.org/github.com/ivaxer/go-xattr). - -License: Simplified BSD License (see LICENSE). diff --git a/vendor/src/github.com/ivaxer/go-xattr/syscall_darwin.go b/vendor/src/github.com/ivaxer/go-xattr/syscall_darwin.go deleted file mode 100644 index eee8c9a54..000000000 --- a/vendor/src/github.com/ivaxer/go-xattr/syscall_darwin.go +++ /dev/null @@ -1,156 +0,0 @@ -package xattr - -import ( - "syscall" - "unsafe" -) - -func get(path, attr string, buf []byte) (rs int, err error) { - return getxattr(path, attr, buf, 0, 0) -} - -// getxattr retrieves value of the extended attribute identified by attr -// associated with given path in filesystem into buffer buf. -// -// options specify options for retrieving extended attributes: -// - syscall.XATTR_NOFOLLOW -// - syscall.XATTR_SHOWCOMPRESSION -// -// position should be zero. For advanded usage see getxattr(2). -// -// On success, buf contains data associated with attr, retrieved value size sz -// and nil error returned. -// -// On error, non-nil error returned. It returns error if buf was to small. -// -// A nil slice can be passed as buf to get current size of attribute value, -// which can be used to estimate buf length for value associated with attr. -// -// See getxattr(2) for more details. -// -// ssize_t getxattr(const char *path, const char *name, void *value, size_t size, u_int32_t position, int options); -func getxattr(path, name string, buf []byte, position, options int) (sz int, err error) { - p, err := syscall.BytePtrFromString(path) - if err != nil { - return - } - - n, err := syscall.BytePtrFromString(name) - if err != nil { - return - } - - var b *byte - if len(buf) > 0 { - b = &buf[0] - } - - r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, - uintptr(unsafe.Pointer(p)), - uintptr(unsafe.Pointer(n)), - uintptr(unsafe.Pointer(b)), - uintptr(len(buf)), - uintptr(position), - uintptr(options)) - - sz = int(r0) - if e1 != 0 { - err = e1 - } - - return -} - -func list(path string, dest []byte) (sz int, err error) { - return listxattr(path, dest, 0) -} - -// ssize_t listxattr(const char *path, char *namebuf, size_t size, int options); -func listxattr(path string, buf []byte, options int) (sz int, err error) { - p, err := syscall.BytePtrFromString(path) - if err != nil { - return - } - - var b *byte - if len(buf) > 0 { - b = &buf[0] - } - - r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, - uintptr(unsafe.Pointer(p)), - uintptr(unsafe.Pointer(b)), - uintptr(len(buf)), - uintptr(options), 0, 0) - - sz = int(r0) - if e1 != 0 { - err = e1 - } - - return -} - -func set(path, attr string, data []byte, flags int) error { - return setxattr(path, attr, data, 0, flags) -} - -// int setxattr(const char *path, const char *name, void *value, size_t size, u_int32_t position, int options); -func setxattr(path string, name string, data []byte, position, options int) (err error) { - p, err := syscall.BytePtrFromString(path) - if err != nil { - return - } - - n, err := syscall.BytePtrFromString(name) - if err != nil { - return - } - - var b *byte - if len(data) > 0 { - b = &data[0] - } - - _, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, - uintptr(unsafe.Pointer(p)), - uintptr(unsafe.Pointer(n)), - uintptr(unsafe.Pointer(b)), - uintptr(len(data)), - uintptr(position), - uintptr(options)) - - if e1 != 0 { - err = e1 - } - - return -} - -func remove(path, attr string) error { - return removexattr(path, attr, 0) -} - -// int removexattr(const char *path, const char *name, int options); -func removexattr(path string, name string, options int) (err error) { - p, err := syscall.BytePtrFromString(path) - if err != nil { - return - } - - n, err := syscall.BytePtrFromString(name) - if err != nil { - return - } - - _, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, - uintptr(unsafe.Pointer(p)), - uintptr(unsafe.Pointer(n)), - uintptr(options)) - - if e1 != 0 { - err = e1 - } - - return -} diff --git a/vendor/src/github.com/ivaxer/go-xattr/syscall_linux.go b/vendor/src/github.com/ivaxer/go-xattr/syscall_linux.go deleted file mode 100644 index 4aa5380ec..000000000 --- a/vendor/src/github.com/ivaxer/go-xattr/syscall_linux.go +++ /dev/null @@ -1,21 +0,0 @@ -package xattr - -import ( - "syscall" -) - -func get(path, attr string, dest []byte) (sz int, err error) { - return syscall.Getxattr(path, attr, dest) -} - -func list(path string, dest []byte) (sz int, err error) { - return syscall.Listxattr(path, dest) -} - -func set(path, attr string, data []byte, flags int) error { - return syscall.Setxattr(path, attr, data, flags) -} - -func remove(path, attr string) error { - return syscall.Removexattr(path, attr) -} diff --git a/vendor/src/github.com/ivaxer/go-xattr/xattr.go b/vendor/src/github.com/ivaxer/go-xattr/xattr.go deleted file mode 100644 index 8de7b4278..000000000 --- a/vendor/src/github.com/ivaxer/go-xattr/xattr.go +++ /dev/null @@ -1,171 +0,0 @@ -// Package xattr provides a simple interface to user extended attributes on -// Linux and OSX. Support for xattrs is filesystem dependant, so not a given -// even if you are running one of those operating systems. -// -// On Linux you have to edit /etc/fstab to include "user_xattr". Also, on Linux -// user's extended attributes have a manditory prefix of "user.". -package xattr - -import ( - "os" -) - -// IsNotExist returns a boolean indicating whether the error is known to report -// that an extended attribute does not exist. -func IsNotExist(err error) bool { - if e, ok := err.(*os.PathError); ok { - err = e.Err - } - - return isNotExist(err) -} - -// Converts an array of NUL terminated UTF-8 strings -// to a []string. -func nullTermToStrings(buf []byte) (result []string) { - offset := 0 - for index, b := range buf { - if b == 0 { - result = append(result, string(buf[offset:index])) - offset = index + 1 - } - } - return -} - -// Getxattr retrieves value of the extended attribute identified by attr -// associated with given path in filesystem into buffer dest. -// -// On success, dest contains data associated with attr, retrieved value size sz -// and nil error are returned. -// -// On error, non-nil error is returned. Getxattr returns error if dest was too -// small for attribute value. -// -// A nil slice can be passed as dest to get current size of attribute value, -// which can be used to estimate dest length for value associated with attr. -// -// See getxattr(2) for more information. -// -// Get is high-level function on top of Getxattr. Getxattr more efficient, -// because it issues one syscall per call, doesn't allocate memory for -// attribute data (caller can reuse buffer). -func Getxattr(path, attr string, dest []byte) (sz int, err error) { - return get(path, attr, dest) -} - -// Get retrieves extended attribute data associated with path. If there is an -// error, it will be of type *os.PathError. -// -// See Getxattr for low-level usage. -func Get(path, attr string) ([]byte, error) { - // find size - size, err := Getxattr(path, attr, nil) - if err != nil { - return nil, &os.PathError{"getxattr", path, err} - } - if size == 0 { - return []byte{}, nil - } - - // read into buffer of that size - buf := make([]byte, size) - size, err = Getxattr(path, attr, buf) - if err != nil { - return nil, &os.PathError{"getxattr", path, err} - } - return buf[:size], nil -} - -// Listxattr retrieves the list of extended attribute names associated with -// path. The list is set of NULL-terminated names. -// -// On success, dest containes list of NULL-terminated names, the length of the -// extended attribute list and nil error are returned. -// -// On error, non nil error is returned. Listxattr returns error if dest buffer -// was too small for extended attribute list. -// -// The list of names is returned as an unordered array of NULL-terminated -// character strings (attribute names are separated by NULL characters), like -// this: -// user.name1\0system.name1\0user.name2\0 -// -// A nil slice can be passed as dest to get the current size of the list of -// extended attribute names, which can be used to estimate dest length for -// the list of names. -// -// See listxattr(2) for more information. -// -// List is high-level function on top of Listxattr. -func Listxattr(path string, dest []byte) (sz int, err error) { - return list(path, dest) -} - -// List retrieves a list of names of extended attributes associated with path. -// If there is an error, it will be of type *os.PathError. -// -// See Listxattr for low-level usage. -func List(path string) ([]string, error) { - // find size - size, err := Listxattr(path, nil) - if err != nil { - return nil, &os.PathError{"listxattr", path, err} - } - if size == 0 { - return []string{}, nil - } - - // read into buffer of that size - buf := make([]byte, size) - size, err = Listxattr(path, buf) - if err != nil { - return nil, &os.PathError{"listxattr", path, err} - } - return nullTermToStrings(buf[:size]), nil -} - -// Setxattr sets value in data of extended attribute attr and accosiated with -// path. -// -// The flags refine the semantic of the operation. XATTR_CREATE specifies pure -// create, which fails if attr already exists. XATTR_REPLACE specifies a pure -// replace operation, which fails if the attr does not already exist. By -// default (no flags), the attr will be created if need be, or will simply -// replace the value if attr exists. -// -// On error, non nil error is returned. -// -// See setxattr(2) for more information. -func Setxattr(path, attr string, data []byte, flags int) error { - return set(path, attr, data, flags) -} - -// Set associates data as an extended attribute of path. If there is an error, -// it will be of type *os.PathError. -// -// See Setxattr for low-level usage. -func Set(path, attr string, data []byte) error { - if err := Setxattr(path, attr, data, 0); err != nil { - return &os.PathError{"setxattr", path, err} - } - return nil -} - -// Removexattr removes the extended attribute attr accosiated with path. -// -// On error, non-nil error is returned. -// -// See removexattr(2) for more information. -func Removexattr(path, attr string) error { - return remove(path, attr) -} - -// Remove removes the extended attribute. If there is an error, it will be of -// type *os.PathError. -func Remove(path, attr string) error { - if err := Removexattr(path, attr); err != nil { - return &os.PathError{"removexattr", path, err} - } - return nil -} diff --git a/vendor/src/github.com/ivaxer/go-xattr/xattr_darwin.go b/vendor/src/github.com/ivaxer/go-xattr/xattr_darwin.go deleted file mode 100644 index ff19634bd..000000000 --- a/vendor/src/github.com/ivaxer/go-xattr/xattr_darwin.go +++ /dev/null @@ -1,9 +0,0 @@ -package xattr - -import ( - "syscall" -) - -func isNotExist(err error) bool { - return err == syscall.ENOATTR -} diff --git a/vendor/src/github.com/ivaxer/go-xattr/xattr_linux.go b/vendor/src/github.com/ivaxer/go-xattr/xattr_linux.go deleted file mode 100644 index 60b4d5a79..000000000 --- a/vendor/src/github.com/ivaxer/go-xattr/xattr_linux.go +++ /dev/null @@ -1,9 +0,0 @@ -package xattr - -import ( - "syscall" -) - -func isNotExist(err error) bool { - return err == syscall.ENODATA -} diff --git a/vendor/src/github.com/ivaxer/go-xattr/xattr_test.go b/vendor/src/github.com/ivaxer/go-xattr/xattr_test.go deleted file mode 100644 index 12d01926a..000000000 --- a/vendor/src/github.com/ivaxer/go-xattr/xattr_test.go +++ /dev/null @@ -1,153 +0,0 @@ -package xattr - -import ( - "bytes" - "io/ioutil" - "os" - "sort" - "testing" -) - -var tmpdir = os.Getenv("TEST_XATTR_PATH") - -func mktemp(t *testing.T) *os.File { - file, err := ioutil.TempFile(tmpdir, "test_xattr_") - if err != nil { - t.Fatalf("TempFile() failed: %v", err) - } - - return file -} - -func stringsEqual(got, expected []string) bool { - if len(got) != len(expected) { - return false - } - - for i := range got { - if got[i] != expected[i] { - return false - } - } - - return true -} - -// expected must be sorted slice of attribute names. -func checkList(t *testing.T, path string, expected []string) { - got, err := List(path) - if err != nil { - t.Fatalf("List(%q) failed: %v", path, err) - } - - sort.Strings(got) - - if !stringsEqual(got, expected) { - t.Errorf("List(%q): expected %v, got %v", path, got, expected) - } -} - -func checkListError(t *testing.T, path string, f func(error) bool) { - got, err := List(path) - if !f(err) { - t.Errorf("List(%q): unexpected error value: %v", path, err) - } - - if got != nil { - t.Error("List(): expected nil slice on error") - } -} - -func checkSet(t *testing.T, path, attr string, data []byte) { - if err := Set(path, attr, data); err != nil { - t.Fatalf("Set(%q, %q, %v) failed: %v", path, attr, data, err) - } -} - -func checkSetError(t *testing.T, path, attr string, data []byte, f func(error) bool) { - if err := Set(path, attr, data); !f(err) { - t.Fatalf("Set(%q, %q, %v): unexpected error value: %v", path, attr, data, err) - } -} - -func checkGet(t *testing.T, path, attr string, expected []byte) { - got, err := Get(path, attr) - if err != nil { - t.Fatalf("Get(%q, %q) failed: %v", path, attr, err) - } - - if !bytes.Equal(got, expected) { - t.Errorf("Get(%q, %q): got %v, expected %v", path, attr, got, expected) - } -} - -func checkGetError(t *testing.T, path, attr string, f func(error) bool) { - got, err := Get(path, attr) - if !f(err) { - t.Errorf("Get(%q, %q): unexpected error value: %v", path, attr, err) - } - - if got != nil { - t.Error("Get(): expected nil slice on error") - } -} - -func checkRemove(t *testing.T, path, attr string) { - if err := Remove(path, attr); err != nil { - t.Fatalf("Remove(%q, %q) failed: %v", path, attr, err) - } -} - -func checkRemoveError(t *testing.T, path, attr string, f func(error) bool) { - if err := Remove(path, attr); !f(err) { - t.Errorf("Remove(%q, %q): unexpected error value: %v", path, attr, err) - } -} - -func TestFlow(t *testing.T) { - f := mktemp(t) - defer func() { f.Close(); os.Remove(f.Name()) }() - - path := f.Name() - data := []byte("test xattr data") - attr := "user.test xattr" - attr2 := "user.text xattr 2" - - checkList(t, path, []string{}) - checkSet(t, path, attr, data) - checkList(t, path, []string{attr}) - checkSet(t, path, attr2, data) - checkList(t, path, []string{attr, attr2}) - checkGet(t, path, attr, data) - checkGetError(t, path, "user.unknown attr", IsNotExist) - checkRemove(t, path, attr) - checkList(t, path, []string{attr2}) - checkRemove(t, path, attr2) - checkList(t, path, []string{}) -} - -func TestEmptyAttr(t *testing.T) { - f := mktemp(t) - defer func() { f.Close(); os.Remove(f.Name()) }() - - path := f.Name() - attr := "user.test xattr" - data := []byte{} - - checkSet(t, path, attr, data) - checkList(t, path, []string{attr}) - checkGet(t, path, attr, []byte{}) - checkRemove(t, path, attr) - checkList(t, path, []string{}) -} - -func TestNoFile(t *testing.T) { - path := "no-such-file" - attr := "user.test xattr" - data := []byte("test_xattr data") - - checkListError(t, path, os.IsNotExist) - checkSetError(t, path, attr, data, os.IsNotExist) - checkGetError(t, path, attr, os.IsNotExist) - checkRemoveError(t, path, attr, os.IsNotExist) -} diff --git a/vendor/src/github.com/ivaxer/go-xattr/LICENCE b/vendor/src/github.com/pkg/xattr/LICENSE similarity index 95% rename from vendor/src/github.com/ivaxer/go-xattr/LICENCE rename to vendor/src/github.com/pkg/xattr/LICENSE index 75451ac03..99d2e9dc8 100644 --- a/vendor/src/github.com/ivaxer/go-xattr/LICENCE +++ b/vendor/src/github.com/pkg/xattr/LICENSE @@ -1,5 +1,5 @@ Copyright (c) 2012 Dave Cheney. All rights reserved. -Copyright (c) 2013 Alexey Palazhchenko. All rights reserved. +Copyright (c) 2014 Kuba Podgórski. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/src/github.com/pkg/xattr/README.md b/vendor/src/github.com/pkg/xattr/README.md new file mode 100644 index 000000000..9fb2e0d00 --- /dev/null +++ b/vendor/src/github.com/pkg/xattr/README.md @@ -0,0 +1,21 @@ +xattr +===== +Extended attribute support for Go (linux + darwin + freebsd). + +"Extended attributes are name:value pairs associated permanently with files and directories, similar to the environment strings associated with a process. An attribute may be defined or undefined. If it is defined, its value may be empty or non-empty." [See more...](https://en.wikipedia.org/wiki/Extended_file_attributes) + + +### Example +``` + const path = "/tmp/myfile" + const prefix = "user." + + if err = Setxattr(path, prefix+"test", []byte("test-attr-value")); err != nil { + t.Fatal(err) + } + + var data []byte + data, err = Getxattr(path, prefix+"test"); err != nil { + t.Fatal(err) + } +``` diff --git a/vendor/src/github.com/pkg/xattr/syscall_darwin.go b/vendor/src/github.com/pkg/xattr/syscall_darwin.go new file mode 100644 index 000000000..6fe1f6c10 --- /dev/null +++ b/vendor/src/github.com/pkg/xattr/syscall_darwin.go @@ -0,0 +1,39 @@ +// +build darwin + +package xattr + +import ( + "syscall" + "unsafe" +) + +func getxattr(path string, name string, value *byte, size int, pos int, options int) (int, error) { + + r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(syscall.StringBytePtr(path))), uintptr(unsafe.Pointer(syscall.StringBytePtr(name))), uintptr(unsafe.Pointer(value)), uintptr(size), uintptr(pos), uintptr(options)) + if e1 != syscall.Errno(0) { + return int(r0), e1 + } + return int(r0), nil +} + +func listxattr(path string, namebuf *byte, size int, options int) (int, error) { + r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(syscall.StringBytePtr(path))), uintptr(unsafe.Pointer(namebuf)), uintptr(size), uintptr(options), 0, 0) + if e1 != syscall.Errno(0) { + return int(r0), e1 + } + return int(r0), nil +} + +func setxattr(path string, name string, value *byte, size int, pos int, options int) error { + if _, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(syscall.StringBytePtr(path))), uintptr(unsafe.Pointer(syscall.StringBytePtr(name))), uintptr(unsafe.Pointer(value)), uintptr(size), uintptr(pos), uintptr(options)); e1 != syscall.Errno(0) { + return e1 + } + return nil +} + +func removexattr(path string, name string, options int) error { + if _, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(syscall.StringBytePtr(path))), uintptr(unsafe.Pointer(syscall.StringBytePtr(name))), uintptr(options)); e1 != syscall.Errno(0) { + return e1 + } + return nil +} diff --git a/vendor/src/github.com/pkg/xattr/syscall_freebsd.go b/vendor/src/github.com/pkg/xattr/syscall_freebsd.go new file mode 100644 index 000000000..fda12c2b8 --- /dev/null +++ b/vendor/src/github.com/pkg/xattr/syscall_freebsd.go @@ -0,0 +1,91 @@ +// +build freebsd + +package xattr + +import ( + "syscall" + "unsafe" +) + +/* + ssize_t + extattr_get_file(const char *path, int attrnamespace, + const char *attrname, void *data, size_t nbytes); + + ssize_t + extattr_set_file(const char *path, int attrnamespace, + const char *attrname, const void *data, size_t nbytes); + + int + extattr_delete_file(const char *path, int attrnamespace, + const char *attrname); + + ssize_t + extattr_list_file(const char *path, int attrnamespace, void *data, + size_t nbytes); +*/ + +func extattr_get_file(path string, attrnamespace int, attrname string, data *byte, nbytes int) (int, error) { + r, _, e := syscall.Syscall6( + syscall.SYS_EXTATTR_GET_FILE, + uintptr(unsafe.Pointer(syscall.StringBytePtr(path))), + uintptr(attrnamespace), + uintptr(unsafe.Pointer(syscall.StringBytePtr(attrname))), + uintptr(unsafe.Pointer(data)), + uintptr(nbytes), + 0, + ) + var err error + if e != 0 { + err = e + } + return int(r), err +} + +func extattr_set_file(path string, attrnamespace int, attrname string, data *byte, nbytes int) (int, error) { + r, _, e := syscall.Syscall6( + syscall.SYS_EXTATTR_SET_FILE, + uintptr(unsafe.Pointer(syscall.StringBytePtr(path))), + uintptr(attrnamespace), + uintptr(unsafe.Pointer(syscall.StringBytePtr(attrname))), + uintptr(unsafe.Pointer(data)), + uintptr(nbytes), + 0, + ) + var err error + if e != 0 { + err = e + } + return int(r), err +} + +func extattr_delete_file(path string, attrnamespace int, attrname string) error { + _, _, e := syscall.Syscall( + syscall.SYS_EXTATTR_DELETE_FILE, + uintptr(unsafe.Pointer(syscall.StringBytePtr(path))), + uintptr(attrnamespace), + uintptr(unsafe.Pointer(syscall.StringBytePtr(attrname))), + ) + var err error + if e != 0 { + err = e + } + return err +} + +func extattr_list_file(path string, attrnamespace int, data *byte, nbytes int) (int, error) { + r, _, e := syscall.Syscall6( + syscall.SYS_EXTATTR_LIST_FILE, + uintptr(unsafe.Pointer(syscall.StringBytePtr(path))), + uintptr(attrnamespace), + uintptr(unsafe.Pointer(data)), + uintptr(nbytes), + 0, + 0, + ) + var err error + if e != 0 { + err = e + } + return int(r), err +} diff --git a/vendor/src/github.com/pkg/xattr/xattr.go b/vendor/src/github.com/pkg/xattr/xattr.go new file mode 100644 index 000000000..a13007f8b --- /dev/null +++ b/vendor/src/github.com/pkg/xattr/xattr.go @@ -0,0 +1,26 @@ +package xattr + +// XAttrError records an error and the operation, file path and attribute that caused it. +type XAttrError struct { + Op string + Path string + Name string + Err error +} + +func (e *XAttrError) Error() string { + return e.Op + " " + e.Path + " " + e.Name + ": " + e.Err.Error() +} + +// Convert an array of NULL terminated UTF-8 strings +// to a []string. +func nullTermToStrings(buf []byte) (result []string) { + offset := 0 + for index, b := range buf { + if b == 0 { + result = append(result, string(buf[offset:index])) + offset = index + 1 + } + } + return +} diff --git a/vendor/src/github.com/pkg/xattr/xattr_darwin.go b/vendor/src/github.com/pkg/xattr/xattr_darwin.go new file mode 100644 index 000000000..443d049f2 --- /dev/null +++ b/vendor/src/github.com/pkg/xattr/xattr_darwin.go @@ -0,0 +1,56 @@ +// +build darwin + +package xattr + +// Retrieve extended attribute data associated with path. +func Getxattr(path, name string) ([]byte, error) { + // find size. + size, err := getxattr(path, name, nil, 0, 0, 0) + if err != nil { + return nil, &XAttrError{"getxattr", path, name, err} + } + buf := make([]byte, size) + // Read into buffer of that size. + read, err := getxattr(path, name, &buf[0], size, 0, 0) + if err != nil { + return nil, &XAttrError{"getxattr", path, name, err} + } + return buf[:read], nil +} + +// Retrieves a list of names of extended attributes associated with the +// given path in the file system. +func Listxattr(path string) ([]string, error) { + // find size. + size, err := listxattr(path, nil, 0, 0) + if err != nil { + return nil, &XAttrError{"listxattr", path, "", err} + } + if size == 0 { + return []string{}, nil + } + + buf := make([]byte, size) + // Read into buffer of that size. + read, err := listxattr(path, &buf[0], size, 0) + if err != nil { + return nil, &XAttrError{"listxattr", path, "", err} + } + return nullTermToStrings(buf[:read]), nil +} + +// Associates name and data together as an attribute of path. +func Setxattr(path, name string, data []byte) error { + if err := setxattr(path, name, &data[0], len(data), 0, 0); err != nil { + return &XAttrError{"setxattr", path, name, err} + } + return nil +} + +// Remove the attribute. +func Removexattr(path, name string) error { + if err := removexattr(path, name, 0); err != nil { + return &XAttrError{"removexattr", path, name, err} + } + return nil +} diff --git a/vendor/src/github.com/pkg/xattr/xattr_freebsd.go b/vendor/src/github.com/pkg/xattr/xattr_freebsd.go new file mode 100644 index 000000000..66cf0066b --- /dev/null +++ b/vendor/src/github.com/pkg/xattr/xattr_freebsd.go @@ -0,0 +1,79 @@ +// +build freebsd + +package xattr + +import ( + "syscall" +) + +const ( + EXTATTR_NAMESPACE_USER = 1 +) + +// Retrieve extended attribute data associated with path. +func Getxattr(path, name string) ([]byte, error) { + // find size. + size, err := extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, nil, 0) + if err != nil { + return nil, &XAttrError{"extattr_get_file", path, name, err} + } + buf := make([]byte, size) + // Read into buffer of that size. + read, err := extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, &buf[0], size) + if err != nil { + return nil, &XAttrError{"extattr_get_file", path, name, err} + } + return buf[:read], nil +} + +// Retrieves a list of names of extended attributes associated with the +// given path in the file system. +func Listxattr(path string) ([]string, error) { + // find size. + size, err := extattr_list_file(path, EXTATTR_NAMESPACE_USER, nil, 0) + if err != nil { + return nil, &XAttrError{"extattr_list_file", path, "", err} + } + buf := make([]byte, size) + // Read into buffer of that size. + read, err := extattr_list_file(path, EXTATTR_NAMESPACE_USER, &buf[0], size) + if err != nil { + return nil, &XAttrError{"extattr_list_file", path, "", err} + } + return attrListToStrings(buf[:read]), nil +} + +// Associates name and data together as an attribute of path. +func Setxattr(path, name string, data []byte) error { + written, err := extattr_set_file(path, EXTATTR_NAMESPACE_USER, name, &data[0], len(data)) + if err != nil { + return &XAttrError{"extattr_set_file", path, name, err} + } + if written != len(data) { + return &XAttrError{"extattr_set_file", path, name, syscall.E2BIG} + } + return nil +} + +// Remove the attribute. +func Removexattr(path, name string) error { + if err := extattr_delete_file(path, EXTATTR_NAMESPACE_USER, name); err != nil { + return &XAttrError{"extattr_delete_file", path, name, err} + } + return nil +} + +// Convert a sequnce of attribute name entries to a []string. +// Each entry consists of a single byte containing the length +// of the attribute name, followed by the attribute name. +// The name is _not_ terminated by NUL. +func attrListToStrings(buf []byte) []string { + var result []string + index := 0 + for index < len(buf) { + next := index + 1 + int(buf[index]) + result = append(result, string(buf[index+1:next])) + index = next + } + return result +} diff --git a/vendor/src/github.com/pkg/xattr/xattr_linux.go b/vendor/src/github.com/pkg/xattr/xattr_linux.go new file mode 100644 index 000000000..b180d12ab --- /dev/null +++ b/vendor/src/github.com/pkg/xattr/xattr_linux.go @@ -0,0 +1,54 @@ +// +build linux + +package xattr + +import "syscall" + +// Retrieve extended attribute data associated with path. +func Getxattr(path, name string) ([]byte, error) { + // find size. + size, err := syscall.Getxattr(path, name, nil) + if err != nil { + return nil, &XAttrError{"getxattr", path, name, err} + } + data := make([]byte, size) + // Read into buffer of that size. + read, err := syscall.Getxattr(path, name, data) + if err != nil { + return nil, &XAttrError{"getxattr", path, name, err} + } + return data[:read], nil +} + +// Retrieves a list of names of extended attributes associated with the +// given path in the file system. +func Listxattr(path string) ([]string, error) { + // find size. + size, err := syscall.Listxattr(path, nil) + if err != nil { + return nil, &XAttrError{"listxattr", path, "", err} + } + buf := make([]byte, size) + // Read into buffer of that size. + read, err := syscall.Listxattr(path, buf) + if err != nil { + return nil, &XAttrError{"listxattr", path, "", err} + } + return nullTermToStrings(buf[:read]), nil +} + +// Associates name and data together as an attribute of path. +func Setxattr(path, name string, data []byte) error { + if err := syscall.Setxattr(path, name, data, 0); err != nil { + return &XAttrError{"setxattr", path, name, err} + } + return nil +} + +// Remove the attribute. +func Removexattr(path, name string) error { + if err := syscall.Removexattr(path, name); err != nil { + return &XAttrError{"removexattr", path, name, err} + } + return nil +} diff --git a/vendor/src/github.com/pkg/xattr/xattr_test.go b/vendor/src/github.com/pkg/xattr/xattr_test.go new file mode 100644 index 000000000..2ea9fa53f --- /dev/null +++ b/vendor/src/github.com/pkg/xattr/xattr_test.go @@ -0,0 +1,57 @@ +// +build linux darwin freebsd + +package xattr + +import ( + "io/ioutil" + "os" + "testing" +) + +const UserPrefix = "user." + +func Test_setxattr(t *testing.T) { + tmp, err := ioutil.TempFile("", "") + + if err != nil { + t.Fatal(err) + } + defer os.Remove(tmp.Name()) + + err = Setxattr(tmp.Name(), UserPrefix+"test", []byte("test-attr-value")) + if err != nil { + t.Fatal(err) + } + + list, err := Listxattr(tmp.Name()) + if err != nil { + t.Fatal(err) + } + + found := false + for _, name := range list { + if name == UserPrefix+"test" { + found = true + } + } + + if !found { + t.Fatal("Listxattr did not return test attribute") + } + + var data []byte + data, err = Getxattr(tmp.Name(), UserPrefix+"test") + if err != nil { + t.Fatal(err) + } + value := string(data) + t.Log(value) + if "test-attr-value" != value { + t.Fail() + } + + err = Removexattr(tmp.Name(), UserPrefix+"test") + if err != nil { + t.Fatal(err) + } +}