diff --git a/archive/stat_linux.go b/archive/stat_linux.go index f87a99c55a..2910ce5bab 100644 --- a/archive/stat_linux.go +++ b/archive/stat_linux.go @@ -37,3 +37,56 @@ func UtimesNano(path string, ts []syscall.Timespec) error { } return nil } + +// Returns a nil slice and nil error if the xattr is not set +func Lgetxattr(path string, attr string) ([]byte, error) { + pathBytes, err := syscall.BytePtrFromString(path) + if err != nil { + return nil, err + } + attrBytes, err := syscall.BytePtrFromString(attr) + if err != nil { + return nil, err + } + + dest := make([]byte, 128) + destBytes := unsafe.Pointer(&dest[0]) + sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) + if errno == syscall.ENODATA { + return nil, nil + } + if errno == syscall.ERANGE { + dest = make([]byte, sz) + destBytes := unsafe.Pointer(&dest[0]) + sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) + } + if errno != 0 { + return nil, errno + } + + return dest[:sz], nil +} + +var _zero uintptr + +func Lsetxattr(path string, attr string, data []byte, flags int) error { + pathBytes, err := syscall.BytePtrFromString(path) + if err != nil { + return err + } + attrBytes, err := syscall.BytePtrFromString(attr) + if err != nil { + return err + } + var dataBytes unsafe.Pointer + if len(data) > 0 { + dataBytes = unsafe.Pointer(&data[0]) + } else { + dataBytes = unsafe.Pointer(&_zero) + } + _, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0) + if errno != 0 { + return errno + } + return nil +} diff --git a/archive/stat_unsupported.go b/archive/stat_unsupported.go index 50ca461867..99f1fbc7da 100644 --- a/archive/stat_unsupported.go +++ b/archive/stat_unsupported.go @@ -19,3 +19,11 @@ func LUtimesNano(path string, ts []syscall.Timespec) error { func UtimesNano(path string, ts []syscall.Timespec) error { return ErrNotImplemented } + +func Lgetxattr(path string, attr string) ([]byte, error) { + return nil, ErrNotImplemented +} + +func Lsetxattr(path string, attr string, data []byte, flags int) error { + return ErrNotImplemented +}