xattrs_linux.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package selinux
  2. import (
  3. "golang.org/x/sys/unix"
  4. )
  5. // lgetxattr returns a []byte slice containing the value of
  6. // an extended attribute attr set for path.
  7. func lgetxattr(path, attr string) ([]byte, error) {
  8. // Start with a 128 length byte array
  9. dest := make([]byte, 128)
  10. sz, errno := doLgetxattr(path, attr, dest)
  11. for errno == unix.ERANGE { //nolint:errorlint // unix errors are bare
  12. // Buffer too small, use zero-sized buffer to get the actual size
  13. sz, errno = doLgetxattr(path, attr, []byte{})
  14. if errno != nil {
  15. return nil, errno
  16. }
  17. dest = make([]byte, sz)
  18. sz, errno = doLgetxattr(path, attr, dest)
  19. }
  20. if errno != nil {
  21. return nil, errno
  22. }
  23. return dest[:sz], nil
  24. }
  25. // doLgetxattr is a wrapper that retries on EINTR
  26. func doLgetxattr(path, attr string, dest []byte) (int, error) {
  27. for {
  28. sz, err := unix.Lgetxattr(path, attr, dest)
  29. if err != unix.EINTR { //nolint:errorlint // unix errors are bare
  30. return sz, err
  31. }
  32. }
  33. }
  34. // getxattr returns a []byte slice containing the value of
  35. // an extended attribute attr set for path.
  36. func getxattr(path, attr string) ([]byte, error) {
  37. // Start with a 128 length byte array
  38. dest := make([]byte, 128)
  39. sz, errno := dogetxattr(path, attr, dest)
  40. for errno == unix.ERANGE { //nolint:errorlint // unix errors are bare
  41. // Buffer too small, use zero-sized buffer to get the actual size
  42. sz, errno = dogetxattr(path, attr, []byte{})
  43. if errno != nil {
  44. return nil, errno
  45. }
  46. dest = make([]byte, sz)
  47. sz, errno = dogetxattr(path, attr, dest)
  48. }
  49. if errno != nil {
  50. return nil, errno
  51. }
  52. return dest[:sz], nil
  53. }
  54. // dogetxattr is a wrapper that retries on EINTR
  55. func dogetxattr(path, attr string, dest []byte) (int, error) {
  56. for {
  57. sz, err := unix.Getxattr(path, attr, dest)
  58. if err != unix.EINTR { //nolint:errorlint // unix errors are bare
  59. return sz, err
  60. }
  61. }
  62. }