2 * Unix SMB/CIFS implementation.
3 * Based on the Samba ACL support code.
4 * Copyright (C) Jeremy Allison 2000.
5 * Copyright (C) 2007-2008 Wayne Davison
7 * The permission functions have been changed to get/set all bits via
8 * one call. Some functions that rsync doesn't need were also removed.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * with this program; if not, visit the http://fsf.org website.
34 void SAFE_FREE(void *mem)
41 This file wraps all differing system ACL interfaces into a consistent
42 one based on the POSIX interface. It also returns the correct errors
43 for older UNIX systems that don't support ACLs.
45 The interfaces that each ACL implementation must support are as follows :
47 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
48 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
49 int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
50 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
51 SMB_ACL_T sys_acl_get_fd(int fd)
52 SMB_ACL_T sys_acl_init( int count)
53 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
54 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
55 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
56 int sys_acl_valid( SMB_ACL_T theacl )
57 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
58 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
59 int sys_acl_delete_def_file(const char *path)
60 int sys_acl_free_acl(SMB_ACL_T posix_acl)
64 #if defined(HAVE_POSIX_ACLS) /*--------------------------------------------*/
66 /* Identity mapping - easy. */
68 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
70 return acl_get_entry( the_acl, entry_id, entry_p);
73 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
75 return acl_get_tag_type( entry_d, tag_type_p);
78 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
80 return acl_get_file( path_p, type);
84 SMB_ACL_T sys_acl_get_fd(int fd)
86 return acl_get_fd(fd);
90 #if defined(HAVE_ACL_GET_PERM_NP)
91 #define acl_get_perm(p, b) acl_get_perm_np(p, b)
94 int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
96 acl_permset_t permset;
98 if (acl_get_tag_type(entry, tag_type_p) != 0
99 || acl_get_permset(entry, &permset) != 0)
102 *bits_p = (acl_get_perm(permset, ACL_READ) ? 4 : 0)
103 | (acl_get_perm(permset, ACL_WRITE) ? 2 : 0)
104 | (acl_get_perm(permset, ACL_EXECUTE) ? 1 : 0);
106 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP) {
108 if ((qual = acl_get_qualifier(entry)) == NULL)
110 *u_g_id_p = *(id_t*)qual;
117 SMB_ACL_T sys_acl_init( int count)
119 return acl_init(count);
122 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
124 return acl_create_entry(pacl, pentry);
127 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
129 if (acl_set_tag_type(entry, tag_type) != 0)
132 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP) {
133 if (acl_set_qualifier(entry, (void*)&u_g_id) != 0)
137 return sys_acl_set_access_bits(entry, bits);
140 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
142 acl_permset_t permset;
144 if ((rc = acl_get_permset(entry, &permset)) != 0)
146 acl_clear_perms(permset);
148 acl_add_perm(permset, ACL_READ);
150 acl_add_perm(permset, ACL_WRITE);
152 acl_add_perm(permset, ACL_EXECUTE);
153 return acl_set_permset(entry, permset);
156 int sys_acl_valid( SMB_ACL_T theacl )
158 return acl_valid(theacl);
161 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
163 return acl_set_file(name, acltype, theacl);
167 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
169 return acl_set_fd(fd, theacl);
173 int sys_acl_delete_def_file(const char *name)
175 return acl_delete_def_file(name);
178 int sys_acl_free_acl(SMB_ACL_T the_acl)
180 return acl_free(the_acl);
183 #elif defined(HAVE_TRU64_ACLS) /*--------------------------------------------*/
185 * The interface to DEC/Compaq Tru64 UNIX ACLs
186 * is based on Draft 13 of the POSIX spec which is
187 * slightly different from the Draft 16 interface.
189 * Also, some of the permset manipulation functions
190 * such as acl_clear_perm() and acl_add_perm() appear
191 * to be broken on Tru64 so we have to manipulate
192 * the permission bits in the permset directly.
194 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
196 SMB_ACL_ENTRY_T entry;
198 if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
203 if ((entry = acl_get_entry(the_acl)) != NULL) {
208 return errno ? -1 : 0;
211 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
213 return acl_get_tag_type( entry_d, tag_type_p);
216 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
218 return acl_get_file((char *)path_p, type);
222 SMB_ACL_T sys_acl_get_fd(int fd)
224 return acl_get_fd(fd, ACL_TYPE_ACCESS);
228 int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
230 acl_permset_t permset;
232 if (acl_get_tag_type(entry, tag_type_p) != 0
233 || acl_get_permset(entry, &permset) != 0)
236 *bits_p = *permset & 7; /* Tru64 doesn't have acl_get_perm() */
238 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP) {
240 if ((qual = acl_get_qualifier(entry)) == NULL)
242 *u_g_id_p = *(id_t*)qual;
243 acl_free_qualifier(qual, *tag_type_p);
249 SMB_ACL_T sys_acl_init( int count)
251 return acl_init(count);
254 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
256 SMB_ACL_ENTRY_T entry;
258 if ((entry = acl_create_entry(pacl)) == NULL) {
266 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
268 if (acl_set_tag_type(entry, tag_type) != 0)
271 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP) {
272 if (acl_set_qualifier(entry, (void*)&u_g_id) != 0)
276 return sys_acl_set_access_bits(entry, bits);
279 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
281 acl_permset_t permset;
283 if ((rc = acl_get_permset(entry, &permset)) != 0)
286 return acl_set_permset(entry, permset);
289 int sys_acl_valid( SMB_ACL_T theacl )
293 return acl_valid(theacl, &entry);
296 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
298 return acl_set_file((char *)name, acltype, theacl);
302 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
304 return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
308 int sys_acl_delete_def_file(const char *name)
310 return acl_delete_def_file((char *)name);
313 int sys_acl_free_acl(SMB_ACL_T the_acl)
315 return acl_free(the_acl);
318 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS) /*-----------*/
321 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
322 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
326 * Note that while this code implements sufficient functionality
327 * to support the sys_acl_* interfaces it does not provide all
328 * of the semantics of the POSIX ACL interfaces.
330 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
331 * from a call to sys_acl_get_entry() should not be assumed to be
332 * valid after calling any of the following functions, which may
333 * reorder the entries in the ACL.
341 * The only difference between Solaris and UnixWare / OpenUNIX is
342 * that the #defines for the ACL operations have different names
344 #if defined(HAVE_UNIXWARE_ACLS)
346 #define SETACL ACL_SET
347 #define GETACL ACL_GET
348 #define GETACLCNT ACL_CNT
353 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
355 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
360 if (entry_p == NULL) {
365 if (entry_id == SMB_ACL_FIRST_ENTRY) {
369 if (acl_d->next < 0) {
374 if (acl_d->next >= acl_d->count) {
378 *entry_p = &acl_d->acl[acl_d->next++];
383 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
385 *type_p = entry_d->a_type;
391 * There is no way of knowing what size the ACL returned by
392 * GETACL will be unless you first call GETACLCNT which means
393 * making an additional system call.
395 * In the hope of avoiding the cost of the additional system
396 * call in most cases, we initially allocate enough space for
397 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
398 * be too small then we use GETACLCNT to find out the actual
399 * size, reallocate the ACL buffer, and then call GETACL again.
402 #define INITIAL_ACL_SIZE 16
404 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
407 int count; /* # of ACL entries allocated */
408 int naccess; /* # of access ACL entries */
409 int ndefault; /* # of default ACL entries */
411 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
416 count = INITIAL_ACL_SIZE;
417 if ((acl_d = sys_acl_init(count)) == NULL) {
422 * If there isn't enough space for the ACL entries we use
423 * GETACLCNT to determine the actual number of ACL entries
424 * reallocate and try again. This is in a loop because it
425 * is possible that someone else could modify the ACL and
426 * increase the number of entries between the call to
427 * GETACLCNT and the call to GETACL.
429 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
430 && errno == ENOSPC) {
432 sys_acl_free_acl(acl_d);
434 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
438 if ((acl_d = sys_acl_init(count)) == NULL) {
444 sys_acl_free_acl(acl_d);
449 * calculate the number of access and default ACL entries
451 * Note: we assume that the acl() system call returned a
452 * well formed ACL which is sorted so that all of the
453 * access ACL entries preceed any default ACL entries
455 for (naccess = 0; naccess < count; naccess++) {
456 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
459 ndefault = count - naccess;
462 * if the caller wants the default ACL we have to copy
463 * the entries down to the start of the acl[] buffer
464 * and mask out the ACL_DEFAULT flag from the type field
466 if (type == SMB_ACL_TYPE_DEFAULT) {
469 for (i = 0, j = naccess; i < ndefault; i++, j++) {
470 acl_d->acl[i] = acl_d->acl[j];
471 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
474 acl_d->count = ndefault;
476 acl_d->count = naccess;
483 SMB_ACL_T sys_acl_get_fd(int fd)
486 int count; /* # of ACL entries allocated */
487 int naccess; /* # of access ACL entries */
489 count = INITIAL_ACL_SIZE;
490 if ((acl_d = sys_acl_init(count)) == NULL) {
494 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
495 && errno == ENOSPC) {
497 sys_acl_free_acl(acl_d);
499 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
503 if ((acl_d = sys_acl_init(count)) == NULL) {
509 sys_acl_free_acl(acl_d);
514 * calculate the number of access ACL entries
516 for (naccess = 0; naccess < count; naccess++) {
517 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
521 acl_d->count = naccess;
527 int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
529 *tag_type_p = entry->a_type;
531 *bits_p = entry->a_perm;
533 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
534 *u_g_id_p = entry->a_id;
539 SMB_ACL_T sys_acl_init(int count)
549 * note that since the definition of the structure pointed
550 * to by the SMB_ACL_T includes the first element of the
551 * acl[] array, this actually allocates an ACL with room
552 * for (count+1) entries
554 if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + count * sizeof (struct acl))) == NULL) {
567 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
570 SMB_ACL_ENTRY_T entry_d;
572 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
577 if (acl_d->count >= acl_d->size) {
582 entry_d = &acl_d->acl[acl_d->count++];
591 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
593 entry->a_type = tag_type;
595 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
596 entry->a_id = u_g_id;
598 entry->a_perm = bits;
603 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
605 entry_d->a_perm = bits;
610 * sort the ACL and check it for validity
612 * if it's a minimal ACL with only 4 entries then we
613 * need to recalculate the mask permissions to make
614 * sure that they are the same as the GROUP_OBJ
615 * permissions as required by the UnixWare acl() system call.
617 * (note: since POSIX allows minimal ACLs which only contain
618 * 3 entries - ie there is no mask entry - we should, in theory,
619 * check for this and add a mask entry if necessary - however
620 * we "know" that the caller of this interface always specifies
621 * a mask so, in practice "this never happens" (tm) - if it *does*
622 * happen aclsort() will fail and return an error and someone will
623 * have to fix it ...)
626 static int acl_sort(SMB_ACL_T acl_d)
628 int fixmask = (acl_d->count <= 4);
630 if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
637 int sys_acl_valid(SMB_ACL_T acl_d)
639 return acl_sort(acl_d);
642 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
647 struct acl *acl_buf = NULL;
650 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
655 if (acl_sort(acl_d) != 0) {
659 acl_p = &acl_d->acl[0];
660 acl_count = acl_d->count;
663 * if it's a directory there is extra work to do
664 * since the acl() system call will replace both
665 * the access ACLs and the default ACLs (if any)
667 if (stat(name, &s) != 0) {
670 if (S_ISDIR(s.st_mode)) {
676 if (type == SMB_ACL_TYPE_ACCESS) {
678 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
682 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
685 if (tmp_acl == NULL) {
690 * allocate a temporary buffer for the complete ACL
692 acl_count = acc_acl->count + def_acl->count;
693 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
695 if (acl_buf == NULL) {
696 sys_acl_free_acl(tmp_acl);
702 * copy the access control and default entries into the buffer
704 memcpy(&acl_buf[0], &acc_acl->acl[0],
705 acc_acl->count * sizeof(acl_buf[0]));
707 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
708 def_acl->count * sizeof(acl_buf[0]));
711 * set the ACL_DEFAULT flag on the default entries
713 for (i = acc_acl->count; i < acl_count; i++) {
714 acl_buf[i].a_type |= ACL_DEFAULT;
717 sys_acl_free_acl(tmp_acl);
719 } else if (type != SMB_ACL_TYPE_ACCESS) {
724 ret = acl(name, SETACL, acl_count, acl_p);
732 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
734 if (acl_sort(acl_d) != 0) {
738 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
742 int sys_acl_delete_def_file(const char *path)
748 * fetching the access ACL and rewriting it has
749 * the effect of deleting the default ACL
751 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
755 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
757 sys_acl_free_acl(acl_d);
762 int sys_acl_free_acl(SMB_ACL_T acl_d)
768 #elif defined(HAVE_HPUX_ACLS) /*---------------------------------------------*/
773 * Based on the Solaris/SCO code - with modifications.
777 * Note that while this code implements sufficient functionality
778 * to support the sys_acl_* interfaces it does not provide all
779 * of the semantics of the POSIX ACL interfaces.
781 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
782 * from a call to sys_acl_get_entry() should not be assumed to be
783 * valid after calling any of the following functions, which may
784 * reorder the entries in the ACL.
791 /* This checks if the POSIX ACL system call is defined */
792 /* which basically corresponds to whether JFS 3.3 or */
793 /* higher is installed. If acl() was called when it */
794 /* isn't defined, it causes the process to core dump */
795 /* so it is important to check this and avoid acl() */
796 /* calls if it isn't there. */
798 static BOOL hpux_acl_call_presence(void)
804 static BOOL already_checked=0;
810 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
813 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
814 ret_val, errno, strerror(errno)));
815 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
819 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
821 already_checked = True;
825 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
827 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
832 if (entry_p == NULL) {
837 if (entry_id == SMB_ACL_FIRST_ENTRY) {
841 if (acl_d->next < 0) {
846 if (acl_d->next >= acl_d->count) {
850 *entry_p = &acl_d->acl[acl_d->next++];
855 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
857 *type_p = entry_d->a_type;
863 * There is no way of knowing what size the ACL returned by
864 * ACL_GET will be unless you first call ACL_CNT which means
865 * making an additional system call.
867 * In the hope of avoiding the cost of the additional system
868 * call in most cases, we initially allocate enough space for
869 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
870 * be too small then we use ACL_CNT to find out the actual
871 * size, reallocate the ACL buffer, and then call ACL_GET again.
874 #define INITIAL_ACL_SIZE 16
876 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
879 int count; /* # of ACL entries allocated */
880 int naccess; /* # of access ACL entries */
881 int ndefault; /* # of default ACL entries */
883 if(hpux_acl_call_presence() == False) {
884 /* Looks like we don't have the acl() system call on HPUX.
885 * May be the system doesn't have the latest version of JFS.
890 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
895 count = INITIAL_ACL_SIZE;
896 if ((acl_d = sys_acl_init(count)) == NULL) {
901 * If there isn't enough space for the ACL entries we use
902 * ACL_CNT to determine the actual number of ACL entries
903 * reallocate and try again. This is in a loop because it
904 * is possible that someone else could modify the ACL and
905 * increase the number of entries between the call to
906 * ACL_CNT and the call to ACL_GET.
908 while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
910 sys_acl_free_acl(acl_d);
912 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
916 if ((acl_d = sys_acl_init(count)) == NULL) {
922 sys_acl_free_acl(acl_d);
927 * calculate the number of access and default ACL entries
929 * Note: we assume that the acl() system call returned a
930 * well formed ACL which is sorted so that all of the
931 * access ACL entries preceed any default ACL entries
933 for (naccess = 0; naccess < count; naccess++) {
934 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
937 ndefault = count - naccess;
940 * if the caller wants the default ACL we have to copy
941 * the entries down to the start of the acl[] buffer
942 * and mask out the ACL_DEFAULT flag from the type field
944 if (type == SMB_ACL_TYPE_DEFAULT) {
947 for (i = 0, j = naccess; i < ndefault; i++, j++) {
948 acl_d->acl[i] = acl_d->acl[j];
949 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
952 acl_d->count = ndefault;
954 acl_d->count = naccess;
961 SMB_ACL_T sys_acl_get_fd(int fd)
964 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
967 files_struct *fsp = file_find_fd(fd);
975 * We know we're in the same conn context. So we
976 * can use the relative path.
979 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
983 int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
985 *tag_type_p = entry->a_type;
987 *bits_p = entry->a_perm;
989 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
990 *u_g_id_p = entry->a_id;
995 SMB_ACL_T sys_acl_init(int count)
1005 * note that since the definition of the structure pointed
1006 * to by the SMB_ACL_T includes the first element of the
1007 * acl[] array, this actually allocates an ACL with room
1008 * for (count+1) entries
1010 if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + count * sizeof(struct acl))) == NULL) {
1015 a->size = count + 1;
1023 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1026 SMB_ACL_ENTRY_T entry_d;
1028 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1033 if (acl_d->count >= acl_d->size) {
1038 entry_d = &acl_d->acl[acl_d->count++];
1039 entry_d->a_type = 0;
1041 entry_d->a_perm = 0;
1047 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
1049 entry->a_type = tag_type;
1051 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
1052 entry->a_id = u_g_id;
1054 entry->a_perm = bits;
1059 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1061 entry_d->a_perm = bits;
1066 /* Structure to capture the count for each type of ACE. */
1068 struct hpux_acl_types {
1077 int n_def_group_obj;
1081 int n_def_other_obj;
1084 int n_def_class_obj;
1090 * Counts the different number of objects in a given array of ACL
1094 * acl_count - Count of ACLs in the array of ACL strucutres.
1095 * aclp - Array of ACL structures.
1096 * acl_type_count - Pointer to acl_types structure. Should already be
1100 * acl_type_count - This structure is filled up with counts of various
1104 static void hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1108 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1110 for(i=0;i<acl_count;i++) {
1111 switch(aclp[i].a_type) {
1113 acl_type_count->n_user++;
1116 acl_type_count->n_user_obj++;
1119 acl_type_count->n_def_user_obj++;
1122 acl_type_count->n_group++;
1125 acl_type_count->n_group_obj++;
1128 acl_type_count->n_def_group_obj++;
1131 acl_type_count->n_other_obj++;
1134 acl_type_count->n_def_other_obj++;
1137 acl_type_count->n_class_obj++;
1140 acl_type_count->n_def_class_obj++;
1143 acl_type_count->n_def_user++;
1146 acl_type_count->n_def_group++;
1149 acl_type_count->n_illegal_obj++;
1155 /* swap_acl_entries: Swaps two ACL entries.
1157 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1160 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1162 struct acl temp_acl;
1164 temp_acl.a_type = aclp0->a_type;
1165 temp_acl.a_id = aclp0->a_id;
1166 temp_acl.a_perm = aclp0->a_perm;
1168 aclp0->a_type = aclp1->a_type;
1169 aclp0->a_id = aclp1->a_id;
1170 aclp0->a_perm = aclp1->a_perm;
1172 aclp1->a_type = temp_acl.a_type;
1173 aclp1->a_id = temp_acl.a_id;
1174 aclp1->a_perm = temp_acl.a_perm;
1177 /* prohibited_duplicate_type
1178 * Identifies if given ACL type can have duplicate entries or
1181 * Inputs: acl_type - ACL Type.
1187 * True - If the ACL type matches any of the prohibited types.
1188 * False - If the ACL type doesn't match any of the prohibited types.
1191 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1204 /* get_needed_class_perm
1205 * Returns the permissions of a ACL structure only if the ACL
1206 * type matches one of the pre-determined types for computing
1207 * CLASS_OBJ permissions.
1209 * Inputs: aclp - Pointer to ACL structure.
1212 static int hpux_get_needed_class_perm(struct acl *aclp)
1214 switch(aclp->a_type) {
1224 return aclp->a_perm;
1230 /* acl_sort for HPUX.
1231 * Sorts the array of ACL structures as per the description in
1232 * aclsort man page. Refer to aclsort man page for more details
1236 * acl_count - Count of ACLs in the array of ACL structures.
1237 * calclass - If this is not zero, then we compute the CLASS_OBJ
1239 * aclp - Array of ACL structures.
1243 * aclp - Sorted array of ACL structures.
1247 * Returns 0 for success -1 for failure. Prints a message to the Samba
1248 * debug log in case of failure.
1251 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1253 #if !defined(HAVE_HPUX_ACLSORT)
1255 * The aclsort() system call is availabe on the latest HPUX General
1256 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1257 * function. Because, we don't want to update to a new
1258 * HPUX GR bundle just for aclsort() call.
1261 struct hpux_acl_types acl_obj_count;
1262 int n_class_obj_perm = 0;
1266 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1271 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1275 /* Count different types of ACLs in the ACLs array */
1277 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1279 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1280 * CLASS_OBJ and OTHER_OBJ
1283 if( (acl_obj_count.n_user_obj != 1) ||
1284 (acl_obj_count.n_group_obj != 1) ||
1285 (acl_obj_count.n_class_obj != 1) ||
1286 (acl_obj_count.n_other_obj != 1)
1288 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1289 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1293 /* If any of the default objects are present, there should be only
1297 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1298 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1299 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1300 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1304 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1307 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1308 * same ACL type, sort by ACL id.
1310 * I am using the trival kind of sorting method here because, performance isn't
1311 * really effected by the ACLs feature. More over there aren't going to be more
1312 * than 17 entries on HPUX.
1315 for(i=0; i<acl_count;i++) {
1316 for (j=i+1; j<acl_count; j++) {
1317 if( aclp[i].a_type > aclp[j].a_type ) {
1318 /* ACL entries out of order, swap them */
1320 hpux_swap_acl_entries((aclp+i), (aclp+j));
1322 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1324 /* ACL entries of same type, sort by id */
1326 if(aclp[i].a_id > aclp[j].a_id) {
1327 hpux_swap_acl_entries((aclp+i), (aclp+j));
1328 } else if (aclp[i].a_id == aclp[j].a_id) {
1329 /* We have a duplicate entry. */
1330 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1331 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1332 aclp[i].a_type, aclp[i].a_id));
1341 /* set the class obj permissions to the computed one. */
1343 int n_class_obj_index = -1;
1345 for(i=0;i<acl_count;i++) {
1346 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1348 if(aclp[i].a_type == CLASS_OBJ)
1349 n_class_obj_index = i;
1351 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1356 return aclsort(acl_count, calclass, aclp);
1361 * sort the ACL and check it for validity
1363 * if it's a minimal ACL with only 4 entries then we
1364 * need to recalculate the mask permissions to make
1365 * sure that they are the same as the GROUP_OBJ
1366 * permissions as required by the UnixWare acl() system call.
1368 * (note: since POSIX allows minimal ACLs which only contain
1369 * 3 entries - ie there is no mask entry - we should, in theory,
1370 * check for this and add a mask entry if necessary - however
1371 * we "know" that the caller of this interface always specifies
1372 * a mask so, in practice "this never happens" (tm) - if it *does*
1373 * happen aclsort() will fail and return an error and someone will
1374 * have to fix it ...)
1377 static int acl_sort(SMB_ACL_T acl_d)
1379 int fixmask = (acl_d->count <= 4);
1381 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1388 int sys_acl_valid(SMB_ACL_T acl_d)
1390 return acl_sort(acl_d);
1393 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1398 struct acl *acl_buf = NULL;
1401 if(hpux_acl_call_presence() == False) {
1402 /* Looks like we don't have the acl() system call on HPUX.
1403 * May be the system doesn't have the latest version of JFS.
1409 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1414 if (acl_sort(acl_d) != 0) {
1418 acl_p = &acl_d->acl[0];
1419 acl_count = acl_d->count;
1422 * if it's a directory there is extra work to do
1423 * since the acl() system call will replace both
1424 * the access ACLs and the default ACLs (if any)
1426 if (stat(name, &s) != 0) {
1429 if (S_ISDIR(s.st_mode)) {
1435 if (type == SMB_ACL_TYPE_ACCESS) {
1437 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1441 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1444 if (tmp_acl == NULL) {
1449 * allocate a temporary buffer for the complete ACL
1451 acl_count = acc_acl->count + def_acl->count;
1452 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1454 if (acl_buf == NULL) {
1455 sys_acl_free_acl(tmp_acl);
1461 * copy the access control and default entries into the buffer
1463 memcpy(&acl_buf[0], &acc_acl->acl[0],
1464 acc_acl->count * sizeof(acl_buf[0]));
1466 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1467 def_acl->count * sizeof(acl_buf[0]));
1470 * set the ACL_DEFAULT flag on the default entries
1472 for (i = acc_acl->count; i < acl_count; i++) {
1473 acl_buf[i].a_type |= ACL_DEFAULT;
1476 sys_acl_free_acl(tmp_acl);
1478 } else if (type != SMB_ACL_TYPE_ACCESS) {
1483 ret = acl(name, ACL_SET, acl_count, acl_p);
1493 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1496 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1499 files_struct *fsp = file_find_fd(fd);
1506 if (acl_sort(acl_d) != 0) {
1511 * We know we're in the same conn context. So we
1512 * can use the relative path.
1515 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1519 int sys_acl_delete_def_file(const char *path)
1525 * fetching the access ACL and rewriting it has
1526 * the effect of deleting the default ACL
1528 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1532 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1534 sys_acl_free_acl(acl_d);
1539 int sys_acl_free_acl(SMB_ACL_T acl_d)
1545 #elif defined(HAVE_IRIX_ACLS) /*---------------------------------------------*/
1547 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1549 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1554 if (entry_p == NULL) {
1559 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1563 if (acl_d->next < 0) {
1568 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1572 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1577 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1579 *type_p = entry_d->ae_tag;
1584 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1588 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1592 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1602 SMB_ACL_T sys_acl_get_fd(int fd)
1606 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1610 if ((a->aclp = acl_get_fd(fd)) == NULL) {
1620 int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
1622 *tag_type_p = entry->ae_tag;
1624 *bits_p = entry->ae_perm;
1626 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
1627 *u_g_id_p = entry->ae_id;
1632 SMB_ACL_T sys_acl_init(int count)
1641 if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + sizeof (struct acl))) == NULL) {
1647 a->freeaclp = False;
1648 a->aclp = (struct acl *)((char *)a + sizeof a[0]);
1649 a->aclp->acl_cnt = 0;
1655 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1658 SMB_ACL_ENTRY_T entry_d;
1660 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1665 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
1670 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
1671 entry_d->ae_tag = 0;
1673 entry_d->ae_perm = 0;
1679 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
1681 entry->ae_tag = tag_type;
1683 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
1684 entry->ae_id = u_g_id;
1686 entry->ae_perm = bits;
1691 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1693 entry_d->ae_perm = bits;
1698 int sys_acl_valid(SMB_ACL_T acl_d)
1700 return acl_valid(acl_d->aclp);
1703 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1705 return acl_set_file(name, type, acl_d->aclp);
1709 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1711 return acl_set_fd(fd, acl_d->aclp);
1715 int sys_acl_delete_def_file(const char *name)
1717 return acl_delete_def_file(name);
1720 int sys_acl_free_acl(SMB_ACL_T acl_d)
1722 if (acl_d->freeaclp) {
1723 acl_free(acl_d->aclp);
1729 #elif defined(HAVE_AIX_ACLS) /*----------------------------------------------*/
1731 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1733 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1735 struct acl_entry_link *link;
1736 struct new_acl_entry *entry;
1739 if (entry_id == SMB_ACL_FIRST_ENTRY)
1741 else if (entry_id != SMB_ACL_NEXT_ENTRY) {
1746 DEBUG(10,("This is the count: %d\n",theacl->count));
1748 /* Check if count was previously set to -1. *
1749 * If it was, that means we reached the end *
1750 * of the acl last time. */
1751 if(theacl->count == -1)
1755 /* To get to the next acl, traverse linked list until index *
1756 * of acl matches the count we are keeping. This count is *
1757 * incremented each time we return an acl entry. */
1759 for(keep_going = 0; keep_going < theacl->count; keep_going++)
1762 entry = *entry_p = link->entryp;
1764 DEBUG(10,("*entry_p is %d\n",entry_p));
1765 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1767 /* Increment count */
1769 if(link->nextp == NULL)
1775 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1777 /* Initialize tag type */
1780 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1782 /* Depending on what type of entry we have, *
1783 * return tag type. */
1784 switch(entry_d->ace_id->id_type) {
1786 *tag_type_p = SMB_ACL_USER;
1789 *tag_type_p = SMB_ACL_GROUP;
1792 case SMB_ACL_USER_OBJ:
1793 case SMB_ACL_GROUP_OBJ:
1795 *tag_type_p = entry_d->ace_id->id_type;
1805 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1807 struct acl *file_acl = (struct acl *)NULL;
1808 struct acl_entry *acl_entry;
1809 struct new_acl_entry *new_acl_entry;
1811 struct acl_entry_link *acl_entry_link;
1812 struct acl_entry_link *acl_entry_link_head;
1816 /* AIX has no DEFAULT */
1817 if ( type == SMB_ACL_TYPE_DEFAULT ) {
1822 /* Get the acl using statacl */
1824 DEBUG(10,("Entering sys_acl_get_file\n"));
1825 DEBUG(10,("path_p is %s\n",path_p));
1827 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
1829 if(file_acl == NULL) {
1831 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1835 memset(file_acl,0,BUFSIZ);
1837 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1839 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1840 SAFE_FREE(file_acl);
1844 DEBUG(10,("Got facl and returned it\n"));
1846 /* Point to the first acl entry in the acl */
1847 acl_entry = file_acl->acl_ext;
1849 /* Begin setting up the head of the linked list *
1850 * that will be used for the storing the acl *
1851 * in a way that is useful for the posix_acls.c *
1854 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1855 if(acl_entry_link_head == NULL)
1858 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1859 if(acl_entry_link->entryp == NULL) {
1860 SAFE_FREE(file_acl);
1862 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1866 DEBUG(10,("acl_entry is %d\n",acl_entry));
1867 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1869 /* Check if the extended acl bit is on. *
1870 * If it isn't, do not show the *
1871 * contents of the acl since AIX intends *
1872 * the extended info to remain unused */
1874 if(file_acl->acl_mode & S_IXACL){
1875 /* while we are not pointing to the very end */
1876 while(acl_entry < acl_last(file_acl)) {
1877 /* before we malloc anything, make sure this is */
1878 /* a valid acl entry and one that we want to map */
1879 idp = id_nxt(acl_entry->ace_id);
1880 if((acl_entry->ace_type == ACC_SPECIFY ||
1881 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1882 acl_entry = acl_nxt(acl_entry);
1886 idp = acl_entry->ace_id;
1888 /* Check if this is the first entry in the linked list. *
1889 * The first entry needs to keep prevp pointing to NULL *
1890 * and already has entryp allocated. */
1892 if(acl_entry_link_head->count != 0) {
1893 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
1895 if(acl_entry_link->nextp == NULL) {
1896 SAFE_FREE(file_acl);
1898 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1902 acl_entry_link->nextp->prevp = acl_entry_link;
1903 acl_entry_link = acl_entry_link->nextp;
1904 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1905 if(acl_entry_link->entryp == NULL) {
1906 SAFE_FREE(file_acl);
1908 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1911 acl_entry_link->nextp = NULL;
1914 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1916 /* Don't really need this since all types are going *
1917 * to be specified but, it's better than leaving it 0 */
1919 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1921 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1923 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
1925 /* The access in the acl entries must be left shifted by *
1926 * three bites, because they will ultimately be compared *
1927 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
1929 switch(acl_entry->ace_type){
1932 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1933 acl_entry_link->entryp->ace_access <<= 6;
1934 acl_entry_link_head->count++;
1937 /* Since there is no way to return a DENY acl entry *
1938 * change to PERMIT and then shift. */
1939 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1940 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1941 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1942 acl_entry_link->entryp->ace_access <<= 6;
1943 acl_entry_link_head->count++;
1949 DEBUG(10,("acl_entry = %d\n",acl_entry));
1950 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1952 acl_entry = acl_nxt(acl_entry);
1954 } /* end of if enabled */
1956 /* Since owner, group, other acl entries are not *
1957 * part of the acl entries in an acl, they must *
1958 * be dummied up to become part of the list. */
1960 for( i = 1; i < 4; i++) {
1961 DEBUG(10,("i is %d\n",i));
1962 if(acl_entry_link_head->count != 0) {
1963 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
1964 if(acl_entry_link->nextp == NULL) {
1965 SAFE_FREE(file_acl);
1967 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1971 acl_entry_link->nextp->prevp = acl_entry_link;
1972 acl_entry_link = acl_entry_link->nextp;
1973 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1974 if(acl_entry_link->entryp == NULL) {
1975 SAFE_FREE(file_acl);
1977 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1982 acl_entry_link->nextp = NULL;
1984 new_acl_entry = acl_entry_link->entryp;
1985 idp = new_acl_entry->ace_id;
1987 new_acl_entry->ace_len = sizeof(struct acl_entry);
1988 new_acl_entry->ace_type = ACC_PERMIT;
1989 idp->id_len = sizeof(struct ace_id);
1990 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1991 memset(idp->id_data,0,sizeof(uid_t));
1995 new_acl_entry->ace_access = file_acl->g_access << 6;
1996 idp->id_type = SMB_ACL_GROUP_OBJ;
2000 new_acl_entry->ace_access = file_acl->o_access << 6;
2001 idp->id_type = SMB_ACL_OTHER;
2005 new_acl_entry->ace_access = file_acl->u_access << 6;
2006 idp->id_type = SMB_ACL_USER_OBJ;
2014 acl_entry_link_head->count++;
2015 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2018 acl_entry_link_head->count = 0;
2019 SAFE_FREE(file_acl);
2021 return(acl_entry_link_head);
2025 SMB_ACL_T sys_acl_get_fd(int fd)
2027 struct acl *file_acl = (struct acl *)NULL;
2028 struct acl_entry *acl_entry;
2029 struct new_acl_entry *new_acl_entry;
2031 struct acl_entry_link *acl_entry_link;
2032 struct acl_entry_link *acl_entry_link_head;
2036 /* Get the acl using fstatacl */
2038 DEBUG(10,("Entering sys_acl_get_fd\n"));
2039 DEBUG(10,("fd is %d\n",fd));
2040 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2042 if(file_acl == NULL) {
2044 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2048 memset(file_acl,0,BUFSIZ);
2050 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2052 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2053 SAFE_FREE(file_acl);
2057 DEBUG(10,("Got facl and returned it\n"));
2059 /* Point to the first acl entry in the acl */
2061 acl_entry = file_acl->acl_ext;
2062 /* Begin setting up the head of the linked list *
2063 * that will be used for the storing the acl *
2064 * in a way that is useful for the posix_acls.c *
2067 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2068 if(acl_entry_link_head == NULL){
2069 SAFE_FREE(file_acl);
2073 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2075 if(acl_entry_link->entryp == NULL) {
2077 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2078 SAFE_FREE(file_acl);
2082 DEBUG(10,("acl_entry is %d\n",acl_entry));
2083 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2085 /* Check if the extended acl bit is on. *
2086 * If it isn't, do not show the *
2087 * contents of the acl since AIX intends *
2088 * the extended info to remain unused */
2090 if(file_acl->acl_mode & S_IXACL){
2091 /* while we are not pointing to the very end */
2092 while(acl_entry < acl_last(file_acl)) {
2093 /* before we malloc anything, make sure this is */
2094 /* a valid acl entry and one that we want to map */
2096 idp = id_nxt(acl_entry->ace_id);
2097 if((acl_entry->ace_type == ACC_SPECIFY ||
2098 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2099 acl_entry = acl_nxt(acl_entry);
2103 idp = acl_entry->ace_id;
2105 /* Check if this is the first entry in the linked list. *
2106 * The first entry needs to keep prevp pointing to NULL *
2107 * and already has entryp allocated. */
2109 if(acl_entry_link_head->count != 0) {
2110 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2111 if(acl_entry_link->nextp == NULL) {
2113 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2114 SAFE_FREE(file_acl);
2117 acl_entry_link->nextp->prevp = acl_entry_link;
2118 acl_entry_link = acl_entry_link->nextp;
2119 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2120 if(acl_entry_link->entryp == NULL) {
2122 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2123 SAFE_FREE(file_acl);
2127 acl_entry_link->nextp = NULL;
2130 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2132 /* Don't really need this since all types are going *
2133 * to be specified but, it's better than leaving it 0 */
2135 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2136 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2138 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2140 /* The access in the acl entries must be left shifted by *
2141 * three bites, because they will ultimately be compared *
2142 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2144 switch(acl_entry->ace_type){
2147 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2148 acl_entry_link->entryp->ace_access <<= 6;
2149 acl_entry_link_head->count++;
2152 /* Since there is no way to return a DENY acl entry *
2153 * change to PERMIT and then shift. */
2154 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2155 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2156 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2157 acl_entry_link->entryp->ace_access <<= 6;
2158 acl_entry_link_head->count++;
2164 DEBUG(10,("acl_entry = %d\n",acl_entry));
2165 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2167 acl_entry = acl_nxt(acl_entry);
2169 } /* end of if enabled */
2171 /* Since owner, group, other acl entries are not *
2172 * part of the acl entries in an acl, they must *
2173 * be dummied up to become part of the list. */
2175 for( i = 1; i < 4; i++) {
2176 DEBUG(10,("i is %d\n",i));
2177 if(acl_entry_link_head->count != 0){
2178 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2179 if(acl_entry_link->nextp == NULL) {
2181 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2182 SAFE_FREE(file_acl);
2186 acl_entry_link->nextp->prevp = acl_entry_link;
2187 acl_entry_link = acl_entry_link->nextp;
2188 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2190 if(acl_entry_link->entryp == NULL) {
2191 SAFE_FREE(file_acl);
2193 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2198 acl_entry_link->nextp = NULL;
2200 new_acl_entry = acl_entry_link->entryp;
2201 idp = new_acl_entry->ace_id;
2203 new_acl_entry->ace_len = sizeof(struct acl_entry);
2204 new_acl_entry->ace_type = ACC_PERMIT;
2205 idp->id_len = sizeof(struct ace_id);
2206 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2207 memset(idp->id_data,0,sizeof(uid_t));
2211 new_acl_entry->ace_access = file_acl->g_access << 6;
2212 idp->id_type = SMB_ACL_GROUP_OBJ;
2216 new_acl_entry->ace_access = file_acl->o_access << 6;
2217 idp->id_type = SMB_ACL_OTHER;
2221 new_acl_entry->ace_access = file_acl->u_access << 6;
2222 idp->id_type = SMB_ACL_USER_OBJ;
2229 acl_entry_link_head->count++;
2230 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2233 acl_entry_link_head->count = 0;
2234 SAFE_FREE(file_acl);
2236 return(acl_entry_link_head);
2240 int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
2244 if (sys_acl_get_tag_type(entry, tag_type_p) != 0)
2247 if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
2248 memcpy(u_g_id_p, entry->ace_id->id_data, sizeof (id_t));
2250 permset = &entry->ace_access;
2252 DEBUG(10,("*permset is %d\n",*permset));
2253 *bits_p = (*permset & S_IRUSR ? 4 : 0)
2254 | (*permset & S_IWUSR ? 2 : 0)
2255 | (*permset & S_IXUSR ? 1 : 0);
2260 SMB_ACL_T sys_acl_init( int count)
2262 struct acl_entry_link *theacl = NULL;
2269 DEBUG(10,("Entering sys_acl_init\n"));
2271 theacl = SMB_MALLOC_P(struct acl_entry_link);
2272 if(theacl == NULL) {
2274 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2279 theacl->nextp = NULL;
2280 theacl->prevp = NULL;
2281 theacl->entryp = NULL;
2282 DEBUG(10,("Exiting sys_acl_init\n"));
2286 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2288 struct acl_entry_link *theacl;
2289 struct acl_entry_link *acl_entryp;
2290 struct acl_entry_link *temp_entry;
2293 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2295 theacl = acl_entryp = *pacl;
2297 /* Get to the end of the acl before adding entry */
2299 for(counting=0; counting < theacl->count; counting++){
2300 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2301 temp_entry = acl_entryp;
2302 acl_entryp = acl_entryp->nextp;
2305 if(theacl->count != 0){
2306 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2307 if(acl_entryp == NULL) {
2309 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2313 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2314 acl_entryp->prevp = temp_entry;
2315 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2318 *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2319 if(*pentry == NULL) {
2321 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2325 memset(*pentry,0,sizeof(struct new_acl_entry));
2326 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2327 acl_entryp->entryp->ace_type = ACC_PERMIT;
2328 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2329 acl_entryp->nextp = NULL;
2331 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2335 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
2337 entry->ace_id->id_type = tag_type;
2338 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2340 if (tag_type == SMB_ACL_USER || tag_type == SMB_ACL_GROUP)
2341 memcpy(entry->ace_id->id_data, &u_g_id, sizeof (id_t));
2343 entry->ace_access = bits;
2344 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2349 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
2351 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2352 entry->ace_access = bits;
2353 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2354 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2358 int sys_acl_valid( SMB_ACL_T theacl )
2363 struct acl_entry_link *acl_entry;
2365 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2366 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2367 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2368 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2371 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2373 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2379 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2381 struct acl_entry_link *acl_entry_link = NULL;
2382 struct acl *file_acl = NULL;
2383 struct acl *file_acl_temp = NULL;
2384 struct acl_entry *acl_entry = NULL;
2385 struct ace_id *ace_id = NULL;
2391 DEBUG(10,("Entering sys_acl_set_file\n"));
2392 DEBUG(10,("File name is %s\n",name));
2394 /* AIX has no default ACL */
2395 if(acltype == SMB_ACL_TYPE_DEFAULT)
2398 acl_length = BUFSIZ;
2399 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2401 if(file_acl == NULL) {
2403 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2407 memset(file_acl,0,BUFSIZ);
2409 file_acl->acl_len = ACL_SIZ;
2410 file_acl->acl_mode = S_IXACL;
2412 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2413 acl_entry_link->entryp->ace_access >>= 6;
2414 id_type = acl_entry_link->entryp->ace_id->id_type;
2417 case SMB_ACL_USER_OBJ:
2418 file_acl->u_access = acl_entry_link->entryp->ace_access;
2420 case SMB_ACL_GROUP_OBJ:
2421 file_acl->g_access = acl_entry_link->entryp->ace_access;
2424 file_acl->o_access = acl_entry_link->entryp->ace_access;
2430 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2431 acl_length += sizeof(struct acl_entry);
2432 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2433 if(file_acl_temp == NULL) {
2434 SAFE_FREE(file_acl);
2436 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2440 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2441 SAFE_FREE(file_acl);
2442 file_acl = file_acl_temp;
2445 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2446 file_acl->acl_len += sizeof(struct acl_entry);
2447 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2448 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2450 /* In order to use this, we'll need to wait until we can get denies */
2451 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2452 acl_entry->ace_type = ACC_SPECIFY; */
2454 acl_entry->ace_type = ACC_SPECIFY;
2456 ace_id = acl_entry->ace_id;
2458 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2459 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2460 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2461 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2462 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2465 rc = chacl((char*)name,file_acl,file_acl->acl_len);
2466 DEBUG(10,("errno is %d\n",errno));
2467 DEBUG(10,("return code is %d\n",rc));
2468 SAFE_FREE(file_acl);
2469 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2474 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2476 struct acl_entry_link *acl_entry_link = NULL;
2477 struct acl *file_acl = NULL;
2478 struct acl *file_acl_temp = NULL;
2479 struct acl_entry *acl_entry = NULL;
2480 struct ace_id *ace_id = NULL;
2486 DEBUG(10,("Entering sys_acl_set_fd\n"));
2487 acl_length = BUFSIZ;
2488 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2490 if(file_acl == NULL) {
2492 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2496 memset(file_acl,0,BUFSIZ);
2498 file_acl->acl_len = ACL_SIZ;
2499 file_acl->acl_mode = S_IXACL;
2501 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2502 acl_entry_link->entryp->ace_access >>= 6;
2503 id_type = acl_entry_link->entryp->ace_id->id_type;
2504 DEBUG(10,("The id_type is %d\n",id_type));
2507 case SMB_ACL_USER_OBJ:
2508 file_acl->u_access = acl_entry_link->entryp->ace_access;
2510 case SMB_ACL_GROUP_OBJ:
2511 file_acl->g_access = acl_entry_link->entryp->ace_access;
2514 file_acl->o_access = acl_entry_link->entryp->ace_access;
2520 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2521 acl_length += sizeof(struct acl_entry);
2522 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2523 if(file_acl_temp == NULL) {
2524 SAFE_FREE(file_acl);
2526 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2530 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2531 SAFE_FREE(file_acl);
2532 file_acl = file_acl_temp;
2535 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2536 file_acl->acl_len += sizeof(struct acl_entry);
2537 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2538 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2540 /* In order to use this, we'll need to wait until we can get denies */
2541 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2542 acl_entry->ace_type = ACC_SPECIFY; */
2544 acl_entry->ace_type = ACC_SPECIFY;
2546 ace_id = acl_entry->ace_id;
2548 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2549 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2550 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2551 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2552 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2555 rc = fchacl(fd,file_acl,file_acl->acl_len);
2556 DEBUG(10,("errno is %d\n",errno));
2557 DEBUG(10,("return code is %d\n",rc));
2558 SAFE_FREE(file_acl);
2559 DEBUG(10,("Exiting sys_acl_set_fd\n"));
2564 int sys_acl_delete_def_file(UNUSED(const char *name))
2566 /* AIX has no default ACL */
2570 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2572 struct acl_entry_link *acl_entry_link;
2574 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2575 SAFE_FREE(acl_entry_link->prevp->entryp);
2576 SAFE_FREE(acl_entry_link->prevp);
2579 SAFE_FREE(acl_entry_link->prevp->entryp);
2580 SAFE_FREE(acl_entry_link->prevp);
2581 SAFE_FREE(acl_entry_link->entryp);
2582 SAFE_FREE(acl_entry_link);
2587 #elif defined(HAVE_OSX_ACLS) /*----------------------------------------------*/
2589 #define OSX_BROKEN_GETENTRY /* returns 0 instead of 1 */
2591 #include <membership.h>
2593 int sys_acl_get_entry(SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2595 int ret = acl_get_entry(the_acl, entry_id, entry_p);
2596 #ifdef OSX_BROKEN_GETENTRY
2599 else if (ret == -1 && errno == 22)
2605 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
2607 if (type == ACL_TYPE_DEFAULT) {
2612 return acl_get_file(path_p, type);
2616 SMB_ACL_T sys_acl_get_fd(int fd)
2618 return acl_get_fd(fd);
2622 int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
2626 acl_flagset_t flagset;
2627 acl_permset_t permset;
2628 uint32 bits, fb, bb, pb;
2632 if (acl_get_tag_type(entry, &tag) != 0
2633 || acl_get_flagset_np(entry, &flagset) != 0
2634 || acl_get_permset(entry, &permset) != 0
2635 || (uup = acl_get_qualifier(entry)) == NULL)
2638 rc = mbr_uuid_to_id(*uup, u_g_id_p, &id_type);
2643 if (id_type == ID_TYPE_UID)
2644 *tag_type_p = SMB_ACL_USER;
2646 *tag_type_p = SMB_ACL_GROUP;
2648 bits = tag == ACL_EXTENDED_ALLOW ? 1 : 0;
2650 for (fb = (1u<<4), bb = (1u<<1); bb < (1u<<12); fb *= 2, bb *= 2) {
2651 if (acl_get_flag_np(flagset, fb) == 1)
2655 for (pb = (1u<<1), bb = (1u<<12); bb < (1u<<25); pb *= 2, bb *= 2) {
2656 if (acl_get_perm_np(permset, pb) == 1)
2665 SMB_ACL_T sys_acl_init(int count)
2667 return acl_init(count);
2670 int sys_acl_create_entry(SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2672 return acl_create_entry(pacl, pentry);
2675 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
2677 acl_flagset_t flagset;
2678 acl_permset_t permset;
2680 int is_user = tag_type == SMB_ACL_USER;
2684 tag_type = bits & 1 ? ACL_EXTENDED_ALLOW : ACL_EXTENDED_DENY;
2686 if (acl_get_flagset_np(entry, &flagset) != 0
2687 || acl_get_permset(entry, &permset) != 0)
2690 acl_clear_flags_np(flagset);
2691 acl_clear_perms(permset);
2693 for (fb = (1u<<4), bb = (1u<<1); bb < (1u<<12); fb *= 2, bb *= 2) {
2695 acl_add_flag_np(flagset, fb);
2698 for (pb = (1u<<1), bb = (1u<<12); bb < (1u<<25); pb *= 2, bb *= 2) {
2700 acl_add_perm(permset, pb);
2704 rc = mbr_uid_to_uuid(u_g_id, uu);
2706 rc = mbr_gid_to_uuid(u_g_id, uu);
2710 if (acl_set_tag_type(entry, tag_type) != 0
2711 || acl_set_qualifier(entry, &uu) != 0
2712 || acl_set_permset(entry, permset) != 0
2713 || acl_set_flagset_np(entry, flagset) != 0)
2720 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
2722 return -1; /* Not needed for OS X. */
2726 int sys_acl_valid(SMB_ACL_T theacl)
2728 return acl_valid(theacl);
2731 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2733 return acl_set_file(name, acltype, theacl);
2737 int sys_acl_set_fd(int fd, SMB_ACL_T theacl)
2739 return acl_set_fd(fd, theacl);
2743 int sys_acl_delete_def_file(const char *name)
2745 return acl_delete_def_file(name);
2748 int sys_acl_free_acl(SMB_ACL_T the_acl)
2750 return acl_free(the_acl);
2753 #else /* No ACLs. */
2755 #error No ACL functions defined for this platform!
2759 /************************************************************************
2760 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
2762 ************************************************************************/
2764 int no_acl_syscall_error(int err)
2766 #ifdef HAVE_OSX_ACLS
2768 return 1; /* Weird problem with directory ACLs. */
2771 if (err == ENOSYS) {
2775 #if defined(ENOTSUP)
2776 if (err == ENOTSUP) {
2783 #endif /* SUPPORT_ACLS */