platform_darwin.pyx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import os
  2. from .helpers import user2uid, group2gid, safe_decode, safe_encode
  3. from .platform_posix import swidth
  4. API_VERSION = 3
  5. cdef extern from "sys/acl.h":
  6. ctypedef struct _acl_t:
  7. pass
  8. ctypedef _acl_t *acl_t
  9. int acl_free(void *obj)
  10. acl_t acl_get_link_np(const char *path, int type)
  11. acl_t acl_set_link_np(const char *path, int type, acl_t acl)
  12. acl_t acl_from_text(const char *buf)
  13. char *acl_to_text(acl_t acl, ssize_t *len_p)
  14. int ACL_TYPE_EXTENDED
  15. def _remove_numeric_id_if_possible(acl):
  16. """Replace the user/group field with the local uid/gid if possible
  17. """
  18. entries = []
  19. for entry in safe_decode(acl).split('\n'):
  20. if entry:
  21. fields = entry.split(':')
  22. if fields[0] == 'user':
  23. if user2uid(fields[2]) is not None:
  24. fields[1] = fields[3] = ''
  25. elif fields[0] == 'group':
  26. if group2gid(fields[2]) is not None:
  27. fields[1] = fields[3] = ''
  28. entries.append(':'.join(fields))
  29. return safe_encode('\n'.join(entries))
  30. def _remove_non_numeric_identifier(acl):
  31. """Remove user and group names from the acl
  32. """
  33. entries = []
  34. for entry in safe_decode(acl).split('\n'):
  35. if entry:
  36. fields = entry.split(':')
  37. if fields[0] in ('user', 'group'):
  38. fields[2] = ''
  39. entries.append(':'.join(fields))
  40. else:
  41. entries.append(entry)
  42. return safe_encode('\n'.join(entries))
  43. def acl_get(path, item, st, numeric_owner=False):
  44. cdef acl_t acl = NULL
  45. cdef char *text = NULL
  46. try:
  47. acl = acl_get_link_np(<bytes>os.fsencode(path), ACL_TYPE_EXTENDED)
  48. if acl == NULL:
  49. return
  50. text = acl_to_text(acl, NULL)
  51. if text == NULL:
  52. return
  53. if numeric_owner:
  54. item[b'acl_extended'] = _remove_non_numeric_identifier(text)
  55. else:
  56. item[b'acl_extended'] = text
  57. finally:
  58. acl_free(text)
  59. acl_free(acl)
  60. def acl_set(path, item, numeric_owner=False):
  61. cdef acl_t acl = NULL
  62. try:
  63. try:
  64. if numeric_owner:
  65. acl = acl_from_text(item[b'acl_extended'])
  66. else:
  67. acl = acl_from_text(<bytes>_remove_numeric_id_if_possible(item[b'acl_extended']))
  68. except KeyError:
  69. return
  70. if acl == NULL:
  71. return
  72. if acl_set_link_np(<bytes>os.fsencode(path), ACL_TYPE_EXTENDED, acl):
  73. return
  74. finally:
  75. acl_free(acl)