123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- // +build linux darwin
- package sysx
- import (
- "bytes"
- "syscall"
- "golang.org/x/sys/unix"
- )
- // Listxattr calls syscall listxattr and reads all content
- // and returns a string array
- func Listxattr(path string) ([]string, error) {
- return listxattrAll(path, unix.Listxattr)
- }
- // Removexattr calls syscall removexattr
- func Removexattr(path string, attr string) (err error) {
- return unix.Removexattr(path, attr)
- }
- // Setxattr calls syscall setxattr
- func Setxattr(path string, attr string, data []byte, flags int) (err error) {
- return unix.Setxattr(path, attr, data, flags)
- }
- // Getxattr calls syscall getxattr
- func Getxattr(path, attr string) ([]byte, error) {
- return getxattrAll(path, attr, unix.Getxattr)
- }
- // LListxattr lists xattrs, not following symlinks
- func LListxattr(path string) ([]string, error) {
- return listxattrAll(path, unix.Llistxattr)
- }
- // LRemovexattr removes an xattr, not following symlinks
- func LRemovexattr(path string, attr string) (err error) {
- return unix.Lremovexattr(path, attr)
- }
- // LSetxattr sets an xattr, not following symlinks
- func LSetxattr(path string, attr string, data []byte, flags int) (err error) {
- return unix.Lsetxattr(path, attr, data, flags)
- }
- // LGetxattr gets an xattr, not following symlinks
- func LGetxattr(path, attr string) ([]byte, error) {
- return getxattrAll(path, attr, unix.Lgetxattr)
- }
- const defaultXattrBufferSize = 5
- type listxattrFunc func(path string, dest []byte) (int, error)
- func listxattrAll(path string, listFunc listxattrFunc) ([]string, error) {
- var p []byte // nil on first execution
- for {
- n, err := listFunc(path, p) // first call gets buffer size.
- if err != nil {
- return nil, err
- }
- if n > len(p) {
- p = make([]byte, n)
- continue
- }
- p = p[:n]
- ps := bytes.Split(bytes.TrimSuffix(p, []byte{0}), []byte{0})
- var entries []string
- for _, p := range ps {
- s := string(p)
- if s != "" {
- entries = append(entries, s)
- }
- }
- return entries, nil
- }
- }
- type getxattrFunc func(string, string, []byte) (int, error)
- func getxattrAll(path, attr string, getFunc getxattrFunc) ([]byte, error) {
- p := make([]byte, defaultXattrBufferSize)
- for {
- n, err := getFunc(path, attr, p)
- if err != nil {
- if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERANGE {
- p = make([]byte, len(p)*2) // this can't be ideal.
- continue // try again!
- }
- return nil, err
- }
- // realloc to correct size and repeat
- if n > len(p) {
- p = make([]byte, n)
- continue
- }
- return p[:n], nil
- }
- }
|