github.com/olljanat/moby@v1.13.1/pkg/system/xattrs_linux.go (about)

     1  package system
     2  
     3  import (
     4  	"syscall"
     5  	"unsafe"
     6  )
     7  
     8  // Lgetxattr retrieves the value of the extended attribute identified by attr
     9  // and associated with the given path in the file system.
    10  // It will returns a nil slice and nil error if the xattr is not set.
    11  func Lgetxattr(path string, attr string) ([]byte, error) {
    12  	pathBytes, err := syscall.BytePtrFromString(path)
    13  	if err != nil {
    14  		return nil, err
    15  	}
    16  	attrBytes, err := syscall.BytePtrFromString(attr)
    17  	if err != nil {
    18  		return nil, err
    19  	}
    20  
    21  	dest := make([]byte, 128)
    22  	destBytes := unsafe.Pointer(&dest[0])
    23  	sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
    24  	if errno == syscall.ENODATA {
    25  		return nil, nil
    26  	}
    27  	if errno == syscall.ERANGE {
    28  		dest = make([]byte, sz)
    29  		destBytes := unsafe.Pointer(&dest[0])
    30  		sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
    31  	}
    32  	if errno != 0 {
    33  		return nil, errno
    34  	}
    35  
    36  	return dest[:sz], nil
    37  }
    38  
    39  var _zero uintptr
    40  
    41  // Lsetxattr sets the value of the extended attribute identified by attr
    42  // and associated with the given path in the file system.
    43  func Lsetxattr(path string, attr string, data []byte, flags int) error {
    44  	pathBytes, err := syscall.BytePtrFromString(path)
    45  	if err != nil {
    46  		return err
    47  	}
    48  	attrBytes, err := syscall.BytePtrFromString(attr)
    49  	if err != nil {
    50  		return err
    51  	}
    52  	var dataBytes unsafe.Pointer
    53  	if len(data) > 0 {
    54  		dataBytes = unsafe.Pointer(&data[0])
    55  	} else {
    56  		dataBytes = unsafe.Pointer(&_zero)
    57  	}
    58  	_, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0)
    59  	if errno != 0 {
    60  		return errno
    61  	}
    62  	return nil
    63  }