platform_freebsd.pyx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import os
  2. from attic.helpers import posix_acl_use_stored_uid_gid
  3. API_VERSION = 2
  4. cdef extern from "errno.h":
  5. int errno
  6. int EINVAL
  7. cdef extern from "sys/types.h":
  8. int ACL_TYPE_ACCESS
  9. int ACL_TYPE_DEFAULT
  10. int ACL_TYPE_NFS4
  11. cdef extern from "sys/acl.h":
  12. ctypedef struct _acl_t:
  13. pass
  14. ctypedef _acl_t *acl_t
  15. int acl_free(void *obj)
  16. acl_t acl_get_link_np(const char *path, int type)
  17. acl_t acl_set_link_np(const char *path, int type, acl_t acl)
  18. acl_t acl_from_text(const char *buf)
  19. char *acl_to_text_np(acl_t acl, ssize_t *len, int flags)
  20. int ACL_TEXT_NUMERIC_IDS
  21. int ACL_TEXT_APPEND_ID
  22. cdef extern from "unistd.h":
  23. long lpathconf(const char *path, int name)
  24. int _PC_ACL_NFS4
  25. cdef _get_acl(p, type, item, attribute, int flags):
  26. cdef acl_t acl
  27. cdef char *text
  28. acl = acl_get_link_np(p, type)
  29. if acl:
  30. text = acl_to_text_np(acl, NULL, flags)
  31. if text:
  32. item[attribute] = text
  33. acl_free(text)
  34. acl_free(acl)
  35. def acl_get(path, item, st, numeric_owner=False):
  36. """Saves ACL Entries
  37. If `numeric_owner` is True the user/group field is not preserved only uid/gid
  38. """
  39. cdef int flags = ACL_TEXT_APPEND_ID
  40. p = os.fsencode(path)
  41. ret = lpathconf(p, _PC_ACL_NFS4)
  42. if ret < 0 and errno == EINVAL:
  43. return
  44. flags |= ACL_TEXT_NUMERIC_IDS if numeric_owner else 0
  45. if ret > 0:
  46. _get_acl(p, ACL_TYPE_NFS4, item, b'acl_nfs4', flags)
  47. else:
  48. _get_acl(p, ACL_TYPE_ACCESS, item, b'acl_access', flags)
  49. _get_acl(p, ACL_TYPE_DEFAULT, item, b'acl_default', flags)
  50. cdef _set_acl(p, type, item, attribute, numeric_owner=False):
  51. cdef acl_t acl
  52. text = item.get(attribute)
  53. if text:
  54. if numeric_owner and type == ACL_TYPE_NFS4:
  55. text = _nfs4_use_stored_uid_gid(text)
  56. elif numeric_owner and type in(ACL_TYPE_ACCESS, ACL_TYPE_DEFAULT):
  57. text = posix_acl_use_stored_uid_gid(text)
  58. acl = acl_from_text(<bytes>text)
  59. if acl:
  60. acl_set_link_np(p, type, acl)
  61. acl_free(acl)
  62. cdef _nfs4_use_stored_uid_gid(acl):
  63. """Replace the user/group field with the stored uid/gid
  64. """
  65. entries = []
  66. for entry in acl.decode('ascii').split('\n'):
  67. if entry:
  68. if entry.startswith('user:') or entry.startswith('group:'):
  69. fields = entry.split(':')
  70. entries.append(':'.join(fields[0], fields[5], *fields[2:-1]))
  71. else:
  72. entries.append(entry)
  73. return ('\n'.join(entries)).encode('ascii')
  74. def acl_set(path, item, numeric_owner=False):
  75. """Restore ACL Entries
  76. If `numeric_owner` is True the stored uid/gid is used instead
  77. of the user/group names
  78. """
  79. p = os.fsencode(path)
  80. _set_acl(p, ACL_TYPE_NFS4, item, b'acl_nfs4', numeric_owner)
  81. _set_acl(p, ACL_TYPE_ACCESS, item, b'acl_access', numeric_owner)
  82. _set_acl(p, ACL_TYPE_DEFAULT, item, b'acl_default', numeric_owner)