xattrs.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // +build linux
  2. package selinux
  3. import (
  4. "syscall"
  5. "unsafe"
  6. )
  7. var _zero uintptr
  8. // Returns a []byte slice if the xattr is set and nil otherwise
  9. // Requires path and its attribute as arguments
  10. func lgetxattr(path string, attr string) ([]byte, error) {
  11. var sz int
  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. // Start with a 128 length byte array
  21. sz = 128
  22. dest := make([]byte, sz)
  23. destBytes := unsafe.Pointer(&dest[0])
  24. _sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
  25. switch {
  26. case errno == syscall.ENODATA:
  27. return nil, errno
  28. case errno == syscall.ENOTSUP:
  29. return nil, errno
  30. case errno == syscall.ERANGE:
  31. // 128 byte array might just not be good enough,
  32. // A dummy buffer is used ``uintptr(0)`` to get real size
  33. // of the xattrs on disk
  34. _sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(unsafe.Pointer(nil)), uintptr(0), 0, 0)
  35. sz = int(_sz)
  36. if sz < 0 {
  37. return nil, errno
  38. }
  39. dest = make([]byte, sz)
  40. destBytes := unsafe.Pointer(&dest[0])
  41. _sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
  42. if errno != 0 {
  43. return nil, errno
  44. }
  45. case errno != 0:
  46. return nil, errno
  47. }
  48. sz = int(_sz)
  49. return dest[:sz], nil
  50. }
  51. func lsetxattr(path string, attr string, data []byte, flags int) error {
  52. pathBytes, err := syscall.BytePtrFromString(path)
  53. if err != nil {
  54. return err
  55. }
  56. attrBytes, err := syscall.BytePtrFromString(attr)
  57. if err != nil {
  58. return err
  59. }
  60. var dataBytes unsafe.Pointer
  61. if len(data) > 0 {
  62. dataBytes = unsafe.Pointer(&data[0])
  63. } else {
  64. dataBytes = unsafe.Pointer(&_zero)
  65. }
  66. _, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0)
  67. if errno != 0 {
  68. return errno
  69. }
  70. return nil
  71. }