2 * Unix SMB/CIFS implementation.
3 * Based on the Samba ACL support code.
4 * Copyright (C) Jeremy Allison 2000.
6 * The permission functions have been changed to get/set all bits via
7 * one call. Some functions that rsync doesn't need were also removed.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * with this program; if not, visit the http://fsf.org website.
33 void SAFE_FREE(void *mem
)
40 This file wraps all differing system ACL interfaces into a consistent
41 one based on the POSIX interface. It also returns the correct errors
42 for older UNIX systems that don't support ACLs.
44 The interfaces that each ACL implementation must support are as follows :
46 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
47 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
48 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)
49 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
50 SMB_ACL_T sys_acl_get_fd(int fd)
51 SMB_ACL_T sys_acl_init( int count)
52 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
53 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
54 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
55 int sys_acl_valid( SMB_ACL_T theacl )
56 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
57 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
58 int sys_acl_delete_def_file(const char *path)
59 int sys_acl_free_acl(SMB_ACL_T posix_acl)
63 #if defined(HAVE_POSIX_ACLS) /*--------------------------------------------*/
65 /* Identity mapping - easy. */
67 int sys_acl_get_entry( SMB_ACL_T the_acl
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
69 return acl_get_entry( the_acl
, entry_id
, entry_p
);
72 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T
*tag_type_p
)
74 return acl_get_tag_type( entry_d
, tag_type_p
);
77 SMB_ACL_T
sys_acl_get_file( const char *path_p
, SMB_ACL_TYPE_T type
)
79 return acl_get_file( path_p
, type
);
83 SMB_ACL_T
sys_acl_get_fd(int fd
)
85 return acl_get_fd(fd
);
89 #if defined(HAVE_ACL_GET_PERM_NP)
90 #define acl_get_perm(p, b) acl_get_perm_np(p, b)
93 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
)
95 acl_permset_t permset
;
97 if (acl_get_tag_type(entry
, tag_type_p
) != 0
98 || acl_get_permset(entry
, &permset
) != 0)
101 *bits_p
= (acl_get_perm(permset
, ACL_READ
) ? 4 : 0)
102 | (acl_get_perm(permset
, ACL_WRITE
) ? 2 : 0)
103 | (acl_get_perm(permset
, ACL_EXECUTE
) ? 1 : 0);
105 if (*tag_type_p
== SMB_ACL_USER
|| *tag_type_p
== SMB_ACL_GROUP
) {
107 if ((qual
= acl_get_qualifier(entry
)) == NULL
)
109 *u_g_id_p
= *(id_t
*)qual
;
116 SMB_ACL_T
sys_acl_init( int count
)
118 return acl_init(count
);
121 int sys_acl_create_entry( SMB_ACL_T
*pacl
, SMB_ACL_ENTRY_T
*pentry
)
123 return acl_create_entry(pacl
, pentry
);
126 int sys_acl_set_info(SMB_ACL_ENTRY_T entry
, SMB_ACL_TAG_T tag_type
, uint32 bits
, id_t u_g_id
)
128 if (acl_set_tag_type(entry
, tag_type
) != 0)
131 if (tag_type
== SMB_ACL_USER
|| tag_type
== SMB_ACL_GROUP
) {
132 if (acl_set_qualifier(entry
, (void*)&u_g_id
) != 0)
136 return sys_acl_set_access_bits(entry
, bits
);
139 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry
, uint32 bits
)
141 acl_permset_t permset
;
143 if ((rc
= acl_get_permset(entry
, &permset
)) != 0)
145 acl_clear_perms(permset
);
147 acl_add_perm(permset
, ACL_READ
);
149 acl_add_perm(permset
, ACL_WRITE
);
151 acl_add_perm(permset
, ACL_EXECUTE
);
152 return acl_set_permset(entry
, permset
);
155 int sys_acl_valid( SMB_ACL_T theacl
)
157 return acl_valid(theacl
);
160 int sys_acl_set_file(const char *name
, SMB_ACL_TYPE_T acltype
, SMB_ACL_T theacl
)
162 return acl_set_file(name
, acltype
, theacl
);
166 int sys_acl_set_fd( int fd
, SMB_ACL_T theacl
)
168 return acl_set_fd(fd
, theacl
);
172 int sys_acl_delete_def_file(const char *name
)
174 return acl_delete_def_file(name
);
177 int sys_acl_free_acl(SMB_ACL_T the_acl
)
179 return acl_free(the_acl
);
182 #elif defined(HAVE_TRU64_ACLS) /*--------------------------------------------*/
184 * The interface to DEC/Compaq Tru64 UNIX ACLs
185 * is based on Draft 13 of the POSIX spec which is
186 * slightly different from the Draft 16 interface.
188 * Also, some of the permset manipulation functions
189 * such as acl_clear_perm() and acl_add_perm() appear
190 * to be broken on Tru64 so we have to manipulate
191 * the permission bits in the permset directly.
193 int sys_acl_get_entry( SMB_ACL_T the_acl
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
195 SMB_ACL_ENTRY_T entry
;
197 if (entry_id
== SMB_ACL_FIRST_ENTRY
&& acl_first_entry(the_acl
) != 0) {
202 if ((entry
= acl_get_entry(the_acl
)) != NULL
) {
207 return errno
? -1 : 0;
210 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T
*tag_type_p
)
212 return acl_get_tag_type( entry_d
, tag_type_p
);
215 SMB_ACL_T
sys_acl_get_file( const char *path_p
, SMB_ACL_TYPE_T type
)
217 return acl_get_file((char *)path_p
, type
);
221 SMB_ACL_T
sys_acl_get_fd(int fd
)
223 return acl_get_fd(fd
, ACL_TYPE_ACCESS
);
227 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
)
229 acl_permset_t permset
;
231 if (acl_get_tag_type(entry
, tag_type_p
) != 0
232 || acl_get_permset(entry
, &permset
) != 0)
235 *bits_p
= *permset
& 7; /* Tru64 doesn't have acl_get_perm() */
237 if (*tag_type_p
== SMB_ACL_USER
|| *tag_type_p
== SMB_ACL_GROUP
) {
239 if ((qual
= acl_get_qualifier(entry
)) == NULL
)
241 *u_g_id_p
= *(id_t
*)qual
;
242 acl_free_qualifier(qual
, *tag_type_p
);
248 SMB_ACL_T
sys_acl_init( int count
)
250 return acl_init(count
);
253 int sys_acl_create_entry( SMB_ACL_T
*pacl
, SMB_ACL_ENTRY_T
*pentry
)
255 SMB_ACL_ENTRY_T entry
;
257 if ((entry
= acl_create_entry(pacl
)) == NULL
) {
265 int sys_acl_set_info(SMB_ACL_ENTRY_T entry
, SMB_ACL_TAG_T tag_type
, uint32 bits
, id_t u_g_id
)
267 if (acl_set_tag_type(entry
, tag_type
) != 0)
270 if (tag_type
== SMB_ACL_USER
|| tag_type
== SMB_ACL_GROUP
) {
271 if (acl_set_qualifier(entry
, (void*)&u_g_id
) != 0)
275 return sys_acl_set_access_bits(entry
, bits
);
278 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry
, uint32 bits
)
280 acl_permset_t permset
;
282 if ((rc
= acl_get_permset(entry
, &permset
)) != 0)
285 return acl_set_permset(entry
, permset
);
288 int sys_acl_valid( SMB_ACL_T theacl
)
292 return acl_valid(theacl
, &entry
);
295 int sys_acl_set_file( const char *name
, SMB_ACL_TYPE_T acltype
, SMB_ACL_T theacl
)
297 return acl_set_file((char *)name
, acltype
, theacl
);
301 int sys_acl_set_fd( int fd
, SMB_ACL_T theacl
)
303 return acl_set_fd(fd
, ACL_TYPE_ACCESS
, theacl
);
307 int sys_acl_delete_def_file(const char *name
)
309 return acl_delete_def_file((char *)name
);
312 int sys_acl_free_acl(SMB_ACL_T the_acl
)
314 return acl_free(the_acl
);
317 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS) /*-----------*/
320 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
321 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
325 * Note that while this code implements sufficient functionality
326 * to support the sys_acl_* interfaces it does not provide all
327 * of the semantics of the POSIX ACL interfaces.
329 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
330 * from a call to sys_acl_get_entry() should not be assumed to be
331 * valid after calling any of the following functions, which may
332 * reorder the entries in the ACL.
340 * The only difference between Solaris and UnixWare / OpenUNIX is
341 * that the #defines for the ACL operations have different names
343 #if defined(HAVE_UNIXWARE_ACLS)
345 #define SETACL ACL_SET
346 #define GETACL ACL_GET
347 #define GETACLCNT ACL_CNT
352 int sys_acl_get_entry(SMB_ACL_T acl_d
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
354 if (entry_id
!= SMB_ACL_FIRST_ENTRY
&& entry_id
!= SMB_ACL_NEXT_ENTRY
) {
359 if (entry_p
== NULL
) {
364 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
368 if (acl_d
->next
< 0) {
373 if (acl_d
->next
>= acl_d
->count
) {
377 *entry_p
= &acl_d
->acl
[acl_d
->next
++];
382 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T
*type_p
)
384 *type_p
= entry_d
->a_type
;
390 * There is no way of knowing what size the ACL returned by
391 * GETACL will be unless you first call GETACLCNT which means
392 * making an additional system call.
394 * In the hope of avoiding the cost of the additional system
395 * call in most cases, we initially allocate enough space for
396 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
397 * be too small then we use GETACLCNT to find out the actual
398 * size, reallocate the ACL buffer, and then call GETACL again.
401 #define INITIAL_ACL_SIZE 16
403 SMB_ACL_T
sys_acl_get_file(const char *path_p
, SMB_ACL_TYPE_T type
)
406 int count
; /* # of ACL entries allocated */
407 int naccess
; /* # of access ACL entries */
408 int ndefault
; /* # of default ACL entries */
410 if (type
!= SMB_ACL_TYPE_ACCESS
&& type
!= SMB_ACL_TYPE_DEFAULT
) {
415 count
= INITIAL_ACL_SIZE
;
416 if ((acl_d
= sys_acl_init(count
)) == NULL
) {
421 * If there isn't enough space for the ACL entries we use
422 * GETACLCNT to determine the actual number of ACL entries
423 * reallocate and try again. This is in a loop because it
424 * is possible that someone else could modify the ACL and
425 * increase the number of entries between the call to
426 * GETACLCNT and the call to GETACL.
428 while ((count
= acl(path_p
, GETACL
, count
, &acl_d
->acl
[0])) < 0
429 && errno
== ENOSPC
) {
431 sys_acl_free_acl(acl_d
);
433 if ((count
= acl(path_p
, GETACLCNT
, 0, NULL
)) < 0) {
437 if ((acl_d
= sys_acl_init(count
)) == NULL
) {
443 sys_acl_free_acl(acl_d
);
448 * calculate the number of access and default ACL entries
450 * Note: we assume that the acl() system call returned a
451 * well formed ACL which is sorted so that all of the
452 * access ACL entries preceed any default ACL entries
454 for (naccess
= 0; naccess
< count
; naccess
++) {
455 if (acl_d
->acl
[naccess
].a_type
& ACL_DEFAULT
)
458 ndefault
= count
- naccess
;
461 * if the caller wants the default ACL we have to copy
462 * the entries down to the start of the acl[] buffer
463 * and mask out the ACL_DEFAULT flag from the type field
465 if (type
== SMB_ACL_TYPE_DEFAULT
) {
468 for (i
= 0, j
= naccess
; i
< ndefault
; i
++, j
++) {
469 acl_d
->acl
[i
] = acl_d
->acl
[j
];
470 acl_d
->acl
[i
].a_type
&= ~ACL_DEFAULT
;
473 acl_d
->count
= ndefault
;
475 acl_d
->count
= naccess
;
482 SMB_ACL_T
sys_acl_get_fd(int fd
)
485 int count
; /* # of ACL entries allocated */
486 int naccess
; /* # of access ACL entries */
488 count
= INITIAL_ACL_SIZE
;
489 if ((acl_d
= sys_acl_init(count
)) == NULL
) {
493 while ((count
= facl(fd
, GETACL
, count
, &acl_d
->acl
[0])) < 0
494 && errno
== ENOSPC
) {
496 sys_acl_free_acl(acl_d
);
498 if ((count
= facl(fd
, GETACLCNT
, 0, NULL
)) < 0) {
502 if ((acl_d
= sys_acl_init(count
)) == NULL
) {
508 sys_acl_free_acl(acl_d
);
513 * calculate the number of access ACL entries
515 for (naccess
= 0; naccess
< count
; naccess
++) {
516 if (acl_d
->acl
[naccess
].a_type
& ACL_DEFAULT
)
520 acl_d
->count
= naccess
;
526 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
)
528 *tag_type_p
= entry
->a_type
;
530 *bits_p
= entry
->a_perm
;
532 if (*tag_type_p
== SMB_ACL_USER
|| *tag_type_p
== SMB_ACL_GROUP
)
533 *u_g_id_p
= entry
->a_id
;
538 SMB_ACL_T
sys_acl_init(int count
)
548 * note that since the definition of the structure pointed
549 * to by the SMB_ACL_T includes the first element of the
550 * acl[] array, this actually allocates an ACL with room
551 * for (count+1) entries
553 if ((a
= (SMB_ACL_T
)SMB_MALLOC(sizeof(struct SMB_ACL_T
) + count
* sizeof(struct acl
))) == NULL
) {
566 int sys_acl_create_entry(SMB_ACL_T
*acl_p
, SMB_ACL_ENTRY_T
*entry_p
)
569 SMB_ACL_ENTRY_T entry_d
;
571 if (acl_p
== NULL
|| entry_p
== NULL
|| (acl_d
= *acl_p
) == NULL
) {
576 if (acl_d
->count
>= acl_d
->size
) {
581 entry_d
= &acl_d
->acl
[acl_d
->count
++];
590 int sys_acl_set_info(SMB_ACL_ENTRY_T entry
, SMB_ACL_TAG_T tag_type
, uint32 bits
, id_t u_g_id
)
592 entry
->a_type
= tag_type
;
594 if (tag_type
== SMB_ACL_USER
|| tag_type
== SMB_ACL_GROUP
)
595 entry
->a_id
= u_g_id
;
597 entry
->a_perm
= bits
;
602 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d
, uint32 bits
)
604 entry_d
->a_perm
= bits
;
609 * sort the ACL and check it for validity
611 * if it's a minimal ACL with only 4 entries then we
612 * need to recalculate the mask permissions to make
613 * sure that they are the same as the GROUP_OBJ
614 * permissions as required by the UnixWare acl() system call.
616 * (note: since POSIX allows minimal ACLs which only contain
617 * 3 entries - ie there is no mask entry - we should, in theory,
618 * check for this and add a mask entry if necessary - however
619 * we "know" that the caller of this interface always specifies
620 * a mask so, in practice "this never happens" (tm) - if it *does*
621 * happen aclsort() will fail and return an error and someone will
622 * have to fix it ...)
625 static int acl_sort(SMB_ACL_T acl_d
)
627 int fixmask
= (acl_d
->count
<= 4);
629 if (aclsort(acl_d
->count
, fixmask
, acl_d
->acl
) != 0) {
636 int sys_acl_valid(SMB_ACL_T acl_d
)
638 return acl_sort(acl_d
);
641 int sys_acl_set_file(const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
646 struct acl
*acl_buf
= NULL
;
649 if (type
!= SMB_ACL_TYPE_ACCESS
&& type
!= SMB_ACL_TYPE_DEFAULT
) {
654 if (acl_sort(acl_d
) != 0) {
658 acl_p
= &acl_d
->acl
[0];
659 acl_count
= acl_d
->count
;
662 * if it's a directory there is extra work to do
663 * since the acl() system call will replace both
664 * the access ACLs and the default ACLs (if any)
666 if (stat(name
, &s
) != 0) {
669 if (S_ISDIR(s
.st_mode
)) {
675 if (type
== SMB_ACL_TYPE_ACCESS
) {
677 def_acl
= tmp_acl
= sys_acl_get_file(name
, SMB_ACL_TYPE_DEFAULT
);
681 acc_acl
= tmp_acl
= sys_acl_get_file(name
, SMB_ACL_TYPE_ACCESS
);
684 if (tmp_acl
== NULL
) {
689 * allocate a temporary buffer for the complete ACL
691 acl_count
= acc_acl
->count
+ def_acl
->count
;
692 acl_p
= acl_buf
= SMB_MALLOC_ARRAY(struct acl
, acl_count
);
694 if (acl_buf
== NULL
) {
695 sys_acl_free_acl(tmp_acl
);
701 * copy the access control and default entries into the buffer
703 memcpy(&acl_buf
[0], &acc_acl
->acl
[0],
704 acc_acl
->count
* sizeof(acl_buf
[0]));
706 memcpy(&acl_buf
[acc_acl
->count
], &def_acl
->acl
[0],
707 def_acl
->count
* sizeof(acl_buf
[0]));
710 * set the ACL_DEFAULT flag on the default entries
712 for (i
= acc_acl
->count
; i
< acl_count
; i
++) {
713 acl_buf
[i
].a_type
|= ACL_DEFAULT
;
716 sys_acl_free_acl(tmp_acl
);
718 } else if (type
!= SMB_ACL_TYPE_ACCESS
) {
723 ret
= acl(name
, SETACL
, acl_count
, acl_p
);
731 int sys_acl_set_fd(int fd
, SMB_ACL_T acl_d
)
733 if (acl_sort(acl_d
) != 0) {
737 return facl(fd
, SETACL
, acl_d
->count
, &acl_d
->acl
[0]);
741 int sys_acl_delete_def_file(const char *path
)
747 * fetching the access ACL and rewriting it has
748 * the effect of deleting the default ACL
750 if ((acl_d
= sys_acl_get_file(path
, SMB_ACL_TYPE_ACCESS
)) == NULL
) {
754 ret
= acl(path
, SETACL
, acl_d
->count
, acl_d
->acl
);
756 sys_acl_free_acl(acl_d
);
761 int sys_acl_free_acl(SMB_ACL_T acl_d
)
767 #elif defined(HAVE_HPUX_ACLS) /*---------------------------------------------*/
772 * Based on the Solaris/SCO code - with modifications.
776 * Note that while this code implements sufficient functionality
777 * to support the sys_acl_* interfaces it does not provide all
778 * of the semantics of the POSIX ACL interfaces.
780 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
781 * from a call to sys_acl_get_entry() should not be assumed to be
782 * valid after calling any of the following functions, which may
783 * reorder the entries in the ACL.
790 /* This checks if the POSIX ACL system call is defined */
791 /* which basically corresponds to whether JFS 3.3 or */
792 /* higher is installed. If acl() was called when it */
793 /* isn't defined, it causes the process to core dump */
794 /* so it is important to check this and avoid acl() */
795 /* calls if it isn't there. */
797 static BOOL
hpux_acl_call_presence(void)
803 static BOOL already_checked
=0;
809 ret_val
= shl_findsym(&handle
, "acl", TYPE_PROCEDURE
, &value
);
812 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
813 ret_val
, errno
, strerror(errno
)));
814 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
818 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
820 already_checked
= True
;
824 int sys_acl_get_entry(SMB_ACL_T acl_d
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
826 if (entry_id
!= SMB_ACL_FIRST_ENTRY
&& entry_id
!= SMB_ACL_NEXT_ENTRY
) {
831 if (entry_p
== NULL
) {
836 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
840 if (acl_d
->next
< 0) {
845 if (acl_d
->next
>= acl_d
->count
) {
849 *entry_p
= &acl_d
->acl
[acl_d
->next
++];
854 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T
*type_p
)
856 *type_p
= entry_d
->a_type
;
862 * There is no way of knowing what size the ACL returned by
863 * ACL_GET will be unless you first call ACL_CNT which means
864 * making an additional system call.
866 * In the hope of avoiding the cost of the additional system
867 * call in most cases, we initially allocate enough space for
868 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
869 * be too small then we use ACL_CNT to find out the actual
870 * size, reallocate the ACL buffer, and then call ACL_GET again.
873 #define INITIAL_ACL_SIZE 16
875 SMB_ACL_T
sys_acl_get_file(const char *path_p
, SMB_ACL_TYPE_T type
)
878 int count
; /* # of ACL entries allocated */
879 int naccess
; /* # of access ACL entries */
880 int ndefault
; /* # of default ACL entries */
882 if(hpux_acl_call_presence() == False
) {
883 /* Looks like we don't have the acl() system call on HPUX.
884 * May be the system doesn't have the latest version of JFS.
889 if (type
!= SMB_ACL_TYPE_ACCESS
&& type
!= SMB_ACL_TYPE_DEFAULT
) {
894 count
= INITIAL_ACL_SIZE
;
895 if ((acl_d
= sys_acl_init(count
)) == NULL
) {
900 * If there isn't enough space for the ACL entries we use
901 * ACL_CNT to determine the actual number of ACL entries
902 * reallocate and try again. This is in a loop because it
903 * is possible that someone else could modify the ACL and
904 * increase the number of entries between the call to
905 * ACL_CNT and the call to ACL_GET.
907 while ((count
= acl(path_p
, ACL_GET
, count
, &acl_d
->acl
[0])) < 0 && errno
== ENOSPC
) {
909 sys_acl_free_acl(acl_d
);
911 if ((count
= acl(path_p
, ACL_CNT
, 0, NULL
)) < 0) {
915 if ((acl_d
= sys_acl_init(count
)) == NULL
) {
921 sys_acl_free_acl(acl_d
);
926 * calculate the number of access and default ACL entries
928 * Note: we assume that the acl() system call returned a
929 * well formed ACL which is sorted so that all of the
930 * access ACL entries preceed any default ACL entries
932 for (naccess
= 0; naccess
< count
; naccess
++) {
933 if (acl_d
->acl
[naccess
].a_type
& ACL_DEFAULT
)
936 ndefault
= count
- naccess
;
939 * if the caller wants the default ACL we have to copy
940 * the entries down to the start of the acl[] buffer
941 * and mask out the ACL_DEFAULT flag from the type field
943 if (type
== SMB_ACL_TYPE_DEFAULT
) {
946 for (i
= 0, j
= naccess
; i
< ndefault
; i
++, j
++) {
947 acl_d
->acl
[i
] = acl_d
->acl
[j
];
948 acl_d
->acl
[i
].a_type
&= ~ACL_DEFAULT
;
951 acl_d
->count
= ndefault
;
953 acl_d
->count
= naccess
;
960 SMB_ACL_T
sys_acl_get_fd(int fd
)
963 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
966 files_struct
*fsp
= file_find_fd(fd
);
974 * We know we're in the same conn context. So we
975 * can use the relative path.
978 return sys_acl_get_file(fsp
->fsp_name
, SMB_ACL_TYPE_ACCESS
);
982 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
)
984 *tag_type_p
= entry
->a_type
;
986 *bits_p
= entry
->a_perm
;
988 if (*tag_type_p
== SMB_ACL_USER
|| *tag_type_p
== SMB_ACL_GROUP
)
989 *u_g_id_p
= entry
->a_id
;
994 SMB_ACL_T
sys_acl_init(int count
)
1004 * note that since the definition of the structure pointed
1005 * to by the SMB_ACL_T includes the first element of the
1006 * acl[] array, this actually allocates an ACL with room
1007 * for (count+1) entries
1009 if ((a
= SMB_MALLOC(sizeof(struct SMB_ACL_T
) + count
* sizeof(struct acl
))) == NULL
) {
1014 a
->size
= count
+ 1;
1022 int sys_acl_create_entry(SMB_ACL_T
*acl_p
, SMB_ACL_ENTRY_T
*entry_p
)
1025 SMB_ACL_ENTRY_T entry_d
;
1027 if (acl_p
== NULL
|| entry_p
== NULL
|| (acl_d
= *acl_p
) == NULL
) {
1032 if (acl_d
->count
>= acl_d
->size
) {
1037 entry_d
= &acl_d
->acl
[acl_d
->count
++];
1038 entry_d
->a_type
= 0;
1040 entry_d
->a_perm
= 0;
1046 int sys_acl_set_info(SMB_ACL_ENTRY_T entry
, SMB_ACL_TAG_T tag_type
, uint32 bits
, id_t u_g_id
)
1048 entry
->a_type
= tag_type
;
1050 if (tag_type
== SMB_ACL_USER
|| tag_type
== SMB_ACL_GROUP
)
1051 entry
->a_id
= u_g_id
;
1053 entry
->a_perm
= bits
;
1058 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d
, uint32 bits
)
1060 entry_d
->a_perm
= bits
;
1065 /* Structure to capture the count for each type of ACE. */
1067 struct hpux_acl_types
{
1076 int n_def_group_obj
;
1080 int n_def_other_obj
;
1083 int n_def_class_obj
;
1089 * Counts the different number of objects in a given array of ACL
1093 * acl_count - Count of ACLs in the array of ACL strucutres.
1094 * aclp - Array of ACL structures.
1095 * acl_type_count - Pointer to acl_types structure. Should already be
1099 * acl_type_count - This structure is filled up with counts of various
1103 static void hpux_count_obj(int acl_count
, struct acl
*aclp
, struct hpux_acl_types
*acl_type_count
)
1107 memset(acl_type_count
, 0, sizeof(struct hpux_acl_types
));
1109 for(i
=0;i
<acl_count
;i
++) {
1110 switch(aclp
[i
].a_type
) {
1112 acl_type_count
->n_user
++;
1115 acl_type_count
->n_user_obj
++;
1118 acl_type_count
->n_def_user_obj
++;
1121 acl_type_count
->n_group
++;
1124 acl_type_count
->n_group_obj
++;
1127 acl_type_count
->n_def_group_obj
++;
1130 acl_type_count
->n_other_obj
++;
1133 acl_type_count
->n_def_other_obj
++;
1136 acl_type_count
->n_class_obj
++;
1139 acl_type_count
->n_def_class_obj
++;
1142 acl_type_count
->n_def_user
++;
1145 acl_type_count
->n_def_group
++;
1148 acl_type_count
->n_illegal_obj
++;
1154 /* swap_acl_entries: Swaps two ACL entries.
1156 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1159 static void hpux_swap_acl_entries(struct acl
*aclp0
, struct acl
*aclp1
)
1161 struct acl temp_acl
;
1163 temp_acl
.a_type
= aclp0
->a_type
;
1164 temp_acl
.a_id
= aclp0
->a_id
;
1165 temp_acl
.a_perm
= aclp0
->a_perm
;
1167 aclp0
->a_type
= aclp1
->a_type
;
1168 aclp0
->a_id
= aclp1
->a_id
;
1169 aclp0
->a_perm
= aclp1
->a_perm
;
1171 aclp1
->a_type
= temp_acl
.a_type
;
1172 aclp1
->a_id
= temp_acl
.a_id
;
1173 aclp1
->a_perm
= temp_acl
.a_perm
;
1176 /* prohibited_duplicate_type
1177 * Identifies if given ACL type can have duplicate entries or
1180 * Inputs: acl_type - ACL Type.
1186 * True - If the ACL type matches any of the prohibited types.
1187 * False - If the ACL type doesn't match any of the prohibited types.
1190 static BOOL
hpux_prohibited_duplicate_type(int acl_type
)
1203 /* get_needed_class_perm
1204 * Returns the permissions of a ACL structure only if the ACL
1205 * type matches one of the pre-determined types for computing
1206 * CLASS_OBJ permissions.
1208 * Inputs: aclp - Pointer to ACL structure.
1211 static int hpux_get_needed_class_perm(struct acl
*aclp
)
1213 switch(aclp
->a_type
) {
1223 return aclp
->a_perm
;
1229 /* acl_sort for HPUX.
1230 * Sorts the array of ACL structures as per the description in
1231 * aclsort man page. Refer to aclsort man page for more details
1235 * acl_count - Count of ACLs in the array of ACL structures.
1236 * calclass - If this is not zero, then we compute the CLASS_OBJ
1238 * aclp - Array of ACL structures.
1242 * aclp - Sorted array of ACL structures.
1246 * Returns 0 for success -1 for failure. Prints a message to the Samba
1247 * debug log in case of failure.
1250 static int hpux_acl_sort(int acl_count
, int calclass
, struct acl
*aclp
)
1252 #if !defined(HAVE_HPUX_ACLSORT)
1254 * The aclsort() system call is availabe on the latest HPUX General
1255 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1256 * function. Because, we don't want to update to a new
1257 * HPUX GR bundle just for aclsort() call.
1260 struct hpux_acl_types acl_obj_count
;
1261 int n_class_obj_perm
= 0;
1265 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1270 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1274 /* Count different types of ACLs in the ACLs array */
1276 hpux_count_obj(acl_count
, aclp
, &acl_obj_count
);
1278 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1279 * CLASS_OBJ and OTHER_OBJ
1282 if( (acl_obj_count
.n_user_obj
!= 1) ||
1283 (acl_obj_count
.n_group_obj
!= 1) ||
1284 (acl_obj_count
.n_class_obj
!= 1) ||
1285 (acl_obj_count
.n_other_obj
!= 1)
1287 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1288 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1292 /* If any of the default objects are present, there should be only
1296 if( (acl_obj_count
.n_def_user_obj
> 1) || (acl_obj_count
.n_def_group_obj
> 1) ||
1297 (acl_obj_count
.n_def_other_obj
> 1) || (acl_obj_count
.n_def_class_obj
> 1) ) {
1298 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1299 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1303 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1306 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1307 * same ACL type, sort by ACL id.
1309 * I am using the trival kind of sorting method here because, performance isn't
1310 * really effected by the ACLs feature. More over there aren't going to be more
1311 * than 17 entries on HPUX.
1314 for(i
=0; i
<acl_count
;i
++) {
1315 for (j
=i
+1; j
<acl_count
; j
++) {
1316 if( aclp
[i
].a_type
> aclp
[j
].a_type
) {
1317 /* ACL entries out of order, swap them */
1319 hpux_swap_acl_entries((aclp
+i
), (aclp
+j
));
1321 } else if ( aclp
[i
].a_type
== aclp
[j
].a_type
) {
1323 /* ACL entries of same type, sort by id */
1325 if(aclp
[i
].a_id
> aclp
[j
].a_id
) {
1326 hpux_swap_acl_entries((aclp
+i
), (aclp
+j
));
1327 } else if (aclp
[i
].a_id
== aclp
[j
].a_id
) {
1328 /* We have a duplicate entry. */
1329 if(hpux_prohibited_duplicate_type(aclp
[i
].a_type
)) {
1330 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1331 aclp
[i
].a_type
, aclp
[i
].a_id
));
1340 /* set the class obj permissions to the computed one. */
1342 int n_class_obj_index
= -1;
1344 for(i
=0;i
<acl_count
;i
++) {
1345 n_class_obj_perm
|= hpux_get_needed_class_perm((aclp
+i
));
1347 if(aclp
[i
].a_type
== CLASS_OBJ
)
1348 n_class_obj_index
= i
;
1350 aclp
[n_class_obj_index
].a_perm
= n_class_obj_perm
;
1355 return aclsort(acl_count
, calclass
, aclp
);
1360 * sort the ACL and check it for validity
1362 * if it's a minimal ACL with only 4 entries then we
1363 * need to recalculate the mask permissions to make
1364 * sure that they are the same as the GROUP_OBJ
1365 * permissions as required by the UnixWare acl() system call.
1367 * (note: since POSIX allows minimal ACLs which only contain
1368 * 3 entries - ie there is no mask entry - we should, in theory,
1369 * check for this and add a mask entry if necessary - however
1370 * we "know" that the caller of this interface always specifies
1371 * a mask so, in practice "this never happens" (tm) - if it *does*
1372 * happen aclsort() will fail and return an error and someone will
1373 * have to fix it ...)
1376 static int acl_sort(SMB_ACL_T acl_d
)
1378 int fixmask
= (acl_d
->count
<= 4);
1380 if (hpux_acl_sort(acl_d
->count
, fixmask
, acl_d
->acl
) != 0) {
1387 int sys_acl_valid(SMB_ACL_T acl_d
)
1389 return acl_sort(acl_d
);
1392 int sys_acl_set_file(const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
1397 struct acl
*acl_buf
= NULL
;
1400 if(hpux_acl_call_presence() == False
) {
1401 /* Looks like we don't have the acl() system call on HPUX.
1402 * May be the system doesn't have the latest version of JFS.
1408 if (type
!= SMB_ACL_TYPE_ACCESS
&& type
!= SMB_ACL_TYPE_DEFAULT
) {
1413 if (acl_sort(acl_d
) != 0) {
1417 acl_p
= &acl_d
->acl
[0];
1418 acl_count
= acl_d
->count
;
1421 * if it's a directory there is extra work to do
1422 * since the acl() system call will replace both
1423 * the access ACLs and the default ACLs (if any)
1425 if (stat(name
, &s
) != 0) {
1428 if (S_ISDIR(s
.st_mode
)) {
1434 if (type
== SMB_ACL_TYPE_ACCESS
) {
1436 def_acl
= tmp_acl
= sys_acl_get_file(name
, SMB_ACL_TYPE_DEFAULT
);
1440 acc_acl
= tmp_acl
= sys_acl_get_file(name
, SMB_ACL_TYPE_ACCESS
);
1443 if (tmp_acl
== NULL
) {
1448 * allocate a temporary buffer for the complete ACL
1450 acl_count
= acc_acl
->count
+ def_acl
->count
;
1451 acl_p
= acl_buf
= SMB_MALLOC_ARRAY(struct acl
, acl_count
);
1453 if (acl_buf
== NULL
) {
1454 sys_acl_free_acl(tmp_acl
);
1460 * copy the access control and default entries into the buffer
1462 memcpy(&acl_buf
[0], &acc_acl
->acl
[0],
1463 acc_acl
->count
* sizeof(acl_buf
[0]));
1465 memcpy(&acl_buf
[acc_acl
->count
], &def_acl
->acl
[0],
1466 def_acl
->count
* sizeof(acl_buf
[0]));
1469 * set the ACL_DEFAULT flag on the default entries
1471 for (i
= acc_acl
->count
; i
< acl_count
; i
++) {
1472 acl_buf
[i
].a_type
|= ACL_DEFAULT
;
1475 sys_acl_free_acl(tmp_acl
);
1477 } else if (type
!= SMB_ACL_TYPE_ACCESS
) {
1482 ret
= acl(name
, ACL_SET
, acl_count
, acl_p
);
1492 int sys_acl_set_fd(int fd
, SMB_ACL_T acl_d
)
1495 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1498 files_struct
*fsp
= file_find_fd(fd
);
1505 if (acl_sort(acl_d
) != 0) {
1510 * We know we're in the same conn context. So we
1511 * can use the relative path.
1514 return sys_acl_set_file(fsp
->fsp_name
, SMB_ACL_TYPE_ACCESS
, acl_d
);
1518 int sys_acl_delete_def_file(const char *path
)
1524 * fetching the access ACL and rewriting it has
1525 * the effect of deleting the default ACL
1527 if ((acl_d
= sys_acl_get_file(path
, SMB_ACL_TYPE_ACCESS
)) == NULL
) {
1531 ret
= acl(path
, ACL_SET
, acl_d
->count
, acl_d
->acl
);
1533 sys_acl_free_acl(acl_d
);
1538 int sys_acl_free_acl(SMB_ACL_T acl_d
)
1544 #elif defined(HAVE_IRIX_ACLS) /*---------------------------------------------*/
1546 int sys_acl_get_entry(SMB_ACL_T acl_d
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
1548 if (entry_id
!= SMB_ACL_FIRST_ENTRY
&& entry_id
!= SMB_ACL_NEXT_ENTRY
) {
1553 if (entry_p
== NULL
) {
1558 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
1562 if (acl_d
->next
< 0) {
1567 if (acl_d
->next
>= acl_d
->aclp
->acl_cnt
) {
1571 *entry_p
= &acl_d
->aclp
->acl_entry
[acl_d
->next
++];
1576 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T
*type_p
)
1578 *type_p
= entry_d
->ae_tag
;
1583 SMB_ACL_T
sys_acl_get_file(const char *path_p
, SMB_ACL_TYPE_T type
)
1587 if ((a
= SMB_MALLOC_P(struct SMB_ACL_T
)) == NULL
) {
1591 if ((a
->aclp
= acl_get_file(path_p
, type
)) == NULL
) {
1601 SMB_ACL_T
sys_acl_get_fd(int fd
)
1605 if ((a
= SMB_MALLOC_P(struct SMB_ACL_T
)) == NULL
) {
1609 if ((a
->aclp
= acl_get_fd(fd
)) == NULL
) {
1619 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
)
1621 *tag_type_p
= entry
->ae_tag
;
1623 *bits_p
= entry
->ae_perm
;
1625 if (*tag_type_p
== SMB_ACL_USER
|| *tag_type_p
== SMB_ACL_GROUP
)
1626 *u_g_id_p
= entry
->ae_id
;
1631 SMB_ACL_T
sys_acl_init(int count
)
1640 if ((a
= SMB_MALLOC(sizeof(struct SMB_ACL_T
) + sizeof(struct acl
))) == NULL
) {
1646 a
->freeaclp
= False
;
1647 a
->aclp
= (struct acl
*)(&a
->aclp
+ sizeof(struct acl
*));
1648 a
->aclp
->acl_cnt
= 0;
1654 int sys_acl_create_entry(SMB_ACL_T
*acl_p
, SMB_ACL_ENTRY_T
*entry_p
)
1657 SMB_ACL_ENTRY_T entry_d
;
1659 if (acl_p
== NULL
|| entry_p
== NULL
|| (acl_d
= *acl_p
) == NULL
) {
1664 if (acl_d
->aclp
->acl_cnt
>= ACL_MAX_ENTRIES
) {
1669 entry_d
= &acl_d
->aclp
->acl_entry
[acl_d
->aclp
->acl_cnt
++];
1670 entry_d
->ae_tag
= 0;
1672 entry_d
->ae_perm
= 0;
1678 int sys_acl_set_info(SMB_ACL_ENTRY_T entry
, SMB_ACL_TAG_T tag_type
, uint32 bits
, id_t u_g_id
)
1680 entry
->ae_tag
= tag_type
;
1682 if (tag_type
== SMB_ACL_USER
|| tag_type
== SMB_ACL_GROUP
)
1683 entry
->ae_id
= u_g_id
;
1685 entry
->ae_perm
= bits
;
1690 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d
, uint32 bits
)
1692 entry_d
->ae_perm
= bits
;
1697 int sys_acl_valid(SMB_ACL_T acl_d
)
1699 return acl_valid(acl_d
->aclp
);
1702 int sys_acl_set_file(const char *name
, SMB_ACL_TYPE_T type
, SMB_ACL_T acl_d
)
1704 return acl_set_file(name
, type
, acl_d
->aclp
);
1708 int sys_acl_set_fd(int fd
, SMB_ACL_T acl_d
)
1710 return acl_set_fd(fd
, acl_d
->aclp
);
1714 int sys_acl_delete_def_file(const char *name
)
1716 return acl_delete_def_file(name
);
1719 int sys_acl_free_acl(SMB_ACL_T acl_d
)
1721 if (acl_d
->freeaclp
) {
1722 acl_free(acl_d
->aclp
);
1728 #elif defined(HAVE_AIX_ACLS) /*----------------------------------------------*/
1730 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1732 int sys_acl_get_entry( SMB_ACL_T theacl
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
1734 struct acl_entry_link
*link
;
1735 struct new_acl_entry
*entry
;
1738 if (entry_id
== SMB_ACL_FIRST_ENTRY
)
1740 else if (entry_id
!= SMB_ACL_NEXT_ENTRY
) {
1745 DEBUG(10,("This is the count: %d\n",theacl
->count
));
1747 /* Check if count was previously set to -1. *
1748 * If it was, that means we reached the end *
1749 * of the acl last time. */
1750 if(theacl
->count
== -1)
1754 /* To get to the next acl, traverse linked list until index *
1755 * of acl matches the count we are keeping. This count is *
1756 * incremented each time we return an acl entry. */
1758 for(keep_going
= 0; keep_going
< theacl
->count
; keep_going
++)
1761 entry
= *entry_p
= link
->entryp
;
1763 DEBUG(10,("*entry_p is %d\n",entry_p
));
1764 DEBUG(10,("*entry_p->ace_access is %d\n",entry
->ace_access
));
1766 /* Increment count */
1768 if(link
->nextp
== NULL
)
1774 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T
*tag_type_p
)
1776 /* Initialize tag type */
1779 DEBUG(10,("the tagtype is %d\n",entry_d
->ace_id
->id_type
));
1781 /* Depending on what type of entry we have, *
1782 * return tag type. */
1783 switch(entry_d
->ace_id
->id_type
) {
1785 *tag_type_p
= SMB_ACL_USER
;
1788 *tag_type_p
= SMB_ACL_GROUP
;
1791 case SMB_ACL_USER_OBJ
:
1792 case SMB_ACL_GROUP_OBJ
:
1794 *tag_type_p
= entry_d
->ace_id
->id_type
;
1804 SMB_ACL_T
sys_acl_get_file( const char *path_p
, SMB_ACL_TYPE_T type
)
1806 struct acl
*file_acl
= (struct acl
*)NULL
;
1807 struct acl_entry
*acl_entry
;
1808 struct new_acl_entry
*new_acl_entry
;
1810 struct acl_entry_link
*acl_entry_link
;
1811 struct acl_entry_link
*acl_entry_link_head
;
1815 /* AIX has no DEFAULT */
1816 if ( type
== SMB_ACL_TYPE_DEFAULT
) {
1821 /* Get the acl using statacl */
1823 DEBUG(10,("Entering sys_acl_get_file\n"));
1824 DEBUG(10,("path_p is %s\n",path_p
));
1826 file_acl
= (struct acl
*)SMB_MALLOC(BUFSIZ
);
1828 if(file_acl
== NULL
) {
1830 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno
));
1834 memset(file_acl
,0,BUFSIZ
);
1836 rc
= statacl((char *)path_p
,0,file_acl
,BUFSIZ
);
1838 DEBUG(0,("statacl returned %d with errno %d\n",rc
,errno
));
1839 SAFE_FREE(file_acl
);
1843 DEBUG(10,("Got facl and returned it\n"));
1845 /* Point to the first acl entry in the acl */
1846 acl_entry
= file_acl
->acl_ext
;
1848 /* Begin setting up the head of the linked list *
1849 * that will be used for the storing the acl *
1850 * in a way that is useful for the posix_acls.c *
1853 acl_entry_link_head
= acl_entry_link
= sys_acl_init(0);
1854 if(acl_entry_link_head
== NULL
)
1857 acl_entry_link
->entryp
= SMB_MALLOC_P(struct new_acl_entry
);
1858 if(acl_entry_link
->entryp
== NULL
) {
1859 SAFE_FREE(file_acl
);
1861 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno
));
1865 DEBUG(10,("acl_entry is %d\n",acl_entry
));
1866 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl
)));
1868 /* Check if the extended acl bit is on. *
1869 * If it isn't, do not show the *
1870 * contents of the acl since AIX intends *
1871 * the extended info to remain unused */
1873 if(file_acl
->acl_mode
& S_IXACL
){
1874 /* while we are not pointing to the very end */
1875 while(acl_entry
< acl_last(file_acl
)) {
1876 /* before we malloc anything, make sure this is */
1877 /* a valid acl entry and one that we want to map */
1878 idp
= id_nxt(acl_entry
->ace_id
);
1879 if((acl_entry
->ace_type
== ACC_SPECIFY
||
1880 (acl_entry
->ace_type
== ACC_PERMIT
)) && (idp
!= id_last(acl_entry
))) {
1881 acl_entry
= acl_nxt(acl_entry
);
1885 idp
= acl_entry
->ace_id
;
1887 /* Check if this is the first entry in the linked list. *
1888 * The first entry needs to keep prevp pointing to NULL *
1889 * and already has entryp allocated. */
1891 if(acl_entry_link_head
->count
!= 0) {
1892 acl_entry_link
->nextp
= SMB_MALLOC_P(struct acl_entry_link
);
1894 if(acl_entry_link
->nextp
== NULL
) {
1895 SAFE_FREE(file_acl
);
1897 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno
));
1901 acl_entry_link
->nextp
->prevp
= acl_entry_link
;
1902 acl_entry_link
= acl_entry_link
->nextp
;
1903 acl_entry_link
->entryp
= SMB_MALLOC_P(struct new_acl_entry
);
1904 if(acl_entry_link
->entryp
== NULL
) {
1905 SAFE_FREE(file_acl
);
1907 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno
));
1910 acl_entry_link
->nextp
= NULL
;
1913 acl_entry_link
->entryp
->ace_len
= acl_entry
->ace_len
;
1915 /* Don't really need this since all types are going *
1916 * to be specified but, it's better than leaving it 0 */
1918 acl_entry_link
->entryp
->ace_type
= acl_entry
->ace_type
;
1920 acl_entry_link
->entryp
->ace_access
= acl_entry
->ace_access
;
1922 memcpy(acl_entry_link
->entryp
->ace_id
,idp
,sizeof(struct ace_id
));
1924 /* The access in the acl entries must be left shifted by *
1925 * three bites, because they will ultimately be compared *
1926 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
1928 switch(acl_entry
->ace_type
){
1931 acl_entry_link
->entryp
->ace_access
= acl_entry
->ace_access
;
1932 acl_entry_link
->entryp
->ace_access
<<= 6;
1933 acl_entry_link_head
->count
++;
1936 /* Since there is no way to return a DENY acl entry *
1937 * change to PERMIT and then shift. */
1938 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry
->ace_access
));
1939 acl_entry_link
->entryp
->ace_access
= ~acl_entry
->ace_access
& 7;
1940 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link
->entryp
->ace_access
));
1941 acl_entry_link
->entryp
->ace_access
<<= 6;
1942 acl_entry_link_head
->count
++;
1948 DEBUG(10,("acl_entry = %d\n",acl_entry
));
1949 DEBUG(10,("The ace_type is %d\n",acl_entry
->ace_type
));
1951 acl_entry
= acl_nxt(acl_entry
);
1953 } /* end of if enabled */
1955 /* Since owner, group, other acl entries are not *
1956 * part of the acl entries in an acl, they must *
1957 * be dummied up to become part of the list. */
1959 for( i
= 1; i
< 4; i
++) {
1960 DEBUG(10,("i is %d\n",i
));
1961 if(acl_entry_link_head
->count
!= 0) {
1962 acl_entry_link
->nextp
= SMB_MALLOC_P(struct acl_entry_link
);
1963 if(acl_entry_link
->nextp
== NULL
) {
1964 SAFE_FREE(file_acl
);
1966 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno
));
1970 acl_entry_link
->nextp
->prevp
= acl_entry_link
;
1971 acl_entry_link
= acl_entry_link
->nextp
;
1972 acl_entry_link
->entryp
= SMB_MALLOC_P(struct new_acl_entry
);
1973 if(acl_entry_link
->entryp
== NULL
) {
1974 SAFE_FREE(file_acl
);
1976 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno
));
1981 acl_entry_link
->nextp
= NULL
;
1983 new_acl_entry
= acl_entry_link
->entryp
;
1984 idp
= new_acl_entry
->ace_id
;
1986 new_acl_entry
->ace_len
= sizeof(struct acl_entry
);
1987 new_acl_entry
->ace_type
= ACC_PERMIT
;
1988 idp
->id_len
= sizeof(struct ace_id
);
1989 DEBUG(10,("idp->id_len = %d\n",idp
->id_len
));
1990 memset(idp
->id_data
,0,sizeof(uid_t
));
1994 new_acl_entry
->ace_access
= file_acl
->g_access
<< 6;
1995 idp
->id_type
= SMB_ACL_GROUP_OBJ
;
1999 new_acl_entry
->ace_access
= file_acl
->o_access
<< 6;
2000 idp
->id_type
= SMB_ACL_OTHER
;
2004 new_acl_entry
->ace_access
= file_acl
->u_access
<< 6;
2005 idp
->id_type
= SMB_ACL_USER_OBJ
;
2013 acl_entry_link_head
->count
++;
2014 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry
->ace_access
));
2017 acl_entry_link_head
->count
= 0;
2018 SAFE_FREE(file_acl
);
2020 return(acl_entry_link_head
);
2024 SMB_ACL_T
sys_acl_get_fd(int fd
)
2026 struct acl
*file_acl
= (struct acl
*)NULL
;
2027 struct acl_entry
*acl_entry
;
2028 struct new_acl_entry
*new_acl_entry
;
2030 struct acl_entry_link
*acl_entry_link
;
2031 struct acl_entry_link
*acl_entry_link_head
;
2035 /* Get the acl using fstatacl */
2037 DEBUG(10,("Entering sys_acl_get_fd\n"));
2038 DEBUG(10,("fd is %d\n",fd
));
2039 file_acl
= (struct acl
*)SMB_MALLOC(BUFSIZ
);
2041 if(file_acl
== NULL
) {
2043 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno
));
2047 memset(file_acl
,0,BUFSIZ
);
2049 rc
= fstatacl(fd
,0,file_acl
,BUFSIZ
);
2051 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc
,errno
));
2052 SAFE_FREE(file_acl
);
2056 DEBUG(10,("Got facl and returned it\n"));
2058 /* Point to the first acl entry in the acl */
2060 acl_entry
= file_acl
->acl_ext
;
2061 /* Begin setting up the head of the linked list *
2062 * that will be used for the storing the acl *
2063 * in a way that is useful for the posix_acls.c *
2066 acl_entry_link_head
= acl_entry_link
= sys_acl_init(0);
2067 if(acl_entry_link_head
== NULL
){
2068 SAFE_FREE(file_acl
);
2072 acl_entry_link
->entryp
= SMB_MALLOC_P(struct new_acl_entry
);
2074 if(acl_entry_link
->entryp
== NULL
) {
2076 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno
));
2077 SAFE_FREE(file_acl
);
2081 DEBUG(10,("acl_entry is %d\n",acl_entry
));
2082 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl
)));
2084 /* Check if the extended acl bit is on. *
2085 * If it isn't, do not show the *
2086 * contents of the acl since AIX intends *
2087 * the extended info to remain unused */
2089 if(file_acl
->acl_mode
& S_IXACL
){
2090 /* while we are not pointing to the very end */
2091 while(acl_entry
< acl_last(file_acl
)) {
2092 /* before we malloc anything, make sure this is */
2093 /* a valid acl entry and one that we want to map */
2095 idp
= id_nxt(acl_entry
->ace_id
);
2096 if((acl_entry
->ace_type
== ACC_SPECIFY
||
2097 (acl_entry
->ace_type
== ACC_PERMIT
)) && (idp
!= id_last(acl_entry
))) {
2098 acl_entry
= acl_nxt(acl_entry
);
2102 idp
= acl_entry
->ace_id
;
2104 /* Check if this is the first entry in the linked list. *
2105 * The first entry needs to keep prevp pointing to NULL *
2106 * and already has entryp allocated. */
2108 if(acl_entry_link_head
->count
!= 0) {
2109 acl_entry_link
->nextp
= SMB_MALLOC_P(struct acl_entry_link
);
2110 if(acl_entry_link
->nextp
== NULL
) {
2112 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno
));
2113 SAFE_FREE(file_acl
);
2116 acl_entry_link
->nextp
->prevp
= acl_entry_link
;
2117 acl_entry_link
= acl_entry_link
->nextp
;
2118 acl_entry_link
->entryp
= SMB_MALLOC_P(struct new_acl_entry
);
2119 if(acl_entry_link
->entryp
== NULL
) {
2121 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno
));
2122 SAFE_FREE(file_acl
);
2126 acl_entry_link
->nextp
= NULL
;
2129 acl_entry_link
->entryp
->ace_len
= acl_entry
->ace_len
;
2131 /* Don't really need this since all types are going *
2132 * to be specified but, it's better than leaving it 0 */
2134 acl_entry_link
->entryp
->ace_type
= acl_entry
->ace_type
;
2135 acl_entry_link
->entryp
->ace_access
= acl_entry
->ace_access
;
2137 memcpy(acl_entry_link
->entryp
->ace_id
, idp
, sizeof(struct ace_id
));
2139 /* The access in the acl entries must be left shifted by *
2140 * three bites, because they will ultimately be compared *
2141 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2143 switch(acl_entry
->ace_type
){
2146 acl_entry_link
->entryp
->ace_access
= acl_entry
->ace_access
;
2147 acl_entry_link
->entryp
->ace_access
<<= 6;
2148 acl_entry_link_head
->count
++;
2151 /* Since there is no way to return a DENY acl entry *
2152 * change to PERMIT and then shift. */
2153 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry
->ace_access
));
2154 acl_entry_link
->entryp
->ace_access
= ~acl_entry
->ace_access
& 7;
2155 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link
->entryp
->ace_access
));
2156 acl_entry_link
->entryp
->ace_access
<<= 6;
2157 acl_entry_link_head
->count
++;
2163 DEBUG(10,("acl_entry = %d\n",acl_entry
));
2164 DEBUG(10,("The ace_type is %d\n",acl_entry
->ace_type
));
2166 acl_entry
= acl_nxt(acl_entry
);
2168 } /* end of if enabled */
2170 /* Since owner, group, other acl entries are not *
2171 * part of the acl entries in an acl, they must *
2172 * be dummied up to become part of the list. */
2174 for( i
= 1; i
< 4; i
++) {
2175 DEBUG(10,("i is %d\n",i
));
2176 if(acl_entry_link_head
->count
!= 0){
2177 acl_entry_link
->nextp
= SMB_MALLOC_P(struct acl_entry_link
);
2178 if(acl_entry_link
->nextp
== NULL
) {
2180 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno
));
2181 SAFE_FREE(file_acl
);
2185 acl_entry_link
->nextp
->prevp
= acl_entry_link
;
2186 acl_entry_link
= acl_entry_link
->nextp
;
2187 acl_entry_link
->entryp
= SMB_MALLOC_P(struct new_acl_entry
);
2189 if(acl_entry_link
->entryp
== NULL
) {
2190 SAFE_FREE(file_acl
);
2192 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno
));
2197 acl_entry_link
->nextp
= NULL
;
2199 new_acl_entry
= acl_entry_link
->entryp
;
2200 idp
= new_acl_entry
->ace_id
;
2202 new_acl_entry
->ace_len
= sizeof(struct acl_entry
);
2203 new_acl_entry
->ace_type
= ACC_PERMIT
;
2204 idp
->id_len
= sizeof(struct ace_id
);
2205 DEBUG(10,("idp->id_len = %d\n",idp
->id_len
));
2206 memset(idp
->id_data
,0,sizeof(uid_t
));
2210 new_acl_entry
->ace_access
= file_acl
->g_access
<< 6;
2211 idp
->id_type
= SMB_ACL_GROUP_OBJ
;
2215 new_acl_entry
->ace_access
= file_acl
->o_access
<< 6;
2216 idp
->id_type
= SMB_ACL_OTHER
;
2220 new_acl_entry
->ace_access
= file_acl
->u_access
<< 6;
2221 idp
->id_type
= SMB_ACL_USER_OBJ
;
2228 acl_entry_link_head
->count
++;
2229 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry
->ace_access
));
2232 acl_entry_link_head
->count
= 0;
2233 SAFE_FREE(file_acl
);
2235 return(acl_entry_link_head
);
2239 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
)
2243 if (sys_acl_get_tag_type(entry
, tag_type_p
) != 0)
2246 if (*tag_type_p
== SMB_ACL_USER
|| *tag_type_p
== SMB_ACL_GROUP
)
2247 memcpy(u_g_id_p
, entry
->ace_id
->id_data
, sizeof (id_t
));
2249 permset
= &entry
->ace_access
;
2251 DEBUG(10,("*permset is %d\n",*permset
));
2252 *bits_p
= (*permset
& S_IRUSR
? 4 : 0)
2253 | (*permset
& S_IWUSR
? 2 : 0)
2254 | (*permset
& S_IXUSR
? 1 : 0);
2259 SMB_ACL_T
sys_acl_init( int count
)
2261 struct acl_entry_link
*theacl
= NULL
;
2268 DEBUG(10,("Entering sys_acl_init\n"));
2270 theacl
= SMB_MALLOC_P(struct acl_entry_link
);
2271 if(theacl
== NULL
) {
2273 DEBUG(0,("Error in sys_acl_init is %d\n",errno
));
2278 theacl
->nextp
= NULL
;
2279 theacl
->prevp
= NULL
;
2280 theacl
->entryp
= NULL
;
2281 DEBUG(10,("Exiting sys_acl_init\n"));
2285 int sys_acl_create_entry( SMB_ACL_T
*pacl
, SMB_ACL_ENTRY_T
*pentry
)
2287 struct acl_entry_link
*theacl
;
2288 struct acl_entry_link
*acl_entryp
;
2289 struct acl_entry_link
*temp_entry
;
2292 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2294 theacl
= acl_entryp
= *pacl
;
2296 /* Get to the end of the acl before adding entry */
2298 for(counting
=0; counting
< theacl
->count
; counting
++){
2299 DEBUG(10,("The acl_entryp is %d\n",acl_entryp
));
2300 temp_entry
= acl_entryp
;
2301 acl_entryp
= acl_entryp
->nextp
;
2304 if(theacl
->count
!= 0){
2305 temp_entry
->nextp
= acl_entryp
= SMB_MALLOC_P(struct acl_entry_link
);
2306 if(acl_entryp
== NULL
) {
2308 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno
));
2312 DEBUG(10,("The acl_entryp is %d\n",acl_entryp
));
2313 acl_entryp
->prevp
= temp_entry
;
2314 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp
->prevp
));
2317 *pentry
= acl_entryp
->entryp
= SMB_MALLOC_P(struct new_acl_entry
);
2318 if(*pentry
== NULL
) {
2320 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno
));
2324 memset(*pentry
,0,sizeof(struct new_acl_entry
));
2325 acl_entryp
->entryp
->ace_len
= sizeof(struct acl_entry
);
2326 acl_entryp
->entryp
->ace_type
= ACC_PERMIT
;
2327 acl_entryp
->entryp
->ace_id
->id_len
= sizeof(struct ace_id
);
2328 acl_entryp
->nextp
= NULL
;
2330 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2334 int sys_acl_set_info(SMB_ACL_ENTRY_T entry
, SMB_ACL_TAG_T tag_type
, uint32 bits
, id_t u_g_id
)
2336 entry
->ace_id
->id_type
= tag_type
;
2337 DEBUG(10,("The tag type is %d\n",entry
->ace_id
->id_type
));
2339 if (tag_type
== SMB_ACL_USER
|| tag_type
== SMB_ACL_GROUP
)
2340 memcpy(entry
->ace_id
->id_data
, &u_g_id
, sizeof (id_t
));
2342 entry
->ace_access
= bits
;
2343 DEBUG(10,("entry->ace_access = %d\n",entry
->ace_access
));
2348 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry
, uint32 bits
)
2350 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2351 entry
->ace_access
= bits
;
2352 DEBUG(10,("entry->ace_access = %d\n",entry
->ace_access
));
2353 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2357 int sys_acl_valid( SMB_ACL_T theacl
)
2362 struct acl_entry_link
*acl_entry
;
2364 for(acl_entry
=theacl
; acl_entry
!= NULL
; acl_entry
= acl_entry
->nextp
) {
2365 user_obj
+= (acl_entry
->entryp
->ace_id
->id_type
== SMB_ACL_USER_OBJ
);
2366 group_obj
+= (acl_entry
->entryp
->ace_id
->id_type
== SMB_ACL_GROUP_OBJ
);
2367 other_obj
+= (acl_entry
->entryp
->ace_id
->id_type
== SMB_ACL_OTHER
);
2370 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj
,group_obj
,other_obj
));
2372 if(user_obj
!= 1 || group_obj
!= 1 || other_obj
!= 1)
2378 int sys_acl_set_file( const char *name
, SMB_ACL_TYPE_T acltype
, SMB_ACL_T theacl
)
2380 struct acl_entry_link
*acl_entry_link
= NULL
;
2381 struct acl
*file_acl
= NULL
;
2382 struct acl
*file_acl_temp
= NULL
;
2383 struct acl_entry
*acl_entry
= NULL
;
2384 struct ace_id
*ace_id
= NULL
;
2390 DEBUG(10,("Entering sys_acl_set_file\n"));
2391 DEBUG(10,("File name is %s\n",name
));
2393 /* AIX has no default ACL */
2394 if(acltype
== SMB_ACL_TYPE_DEFAULT
)
2397 acl_length
= BUFSIZ
;
2398 file_acl
= (struct acl
*)SMB_MALLOC(BUFSIZ
);
2400 if(file_acl
== NULL
) {
2402 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno
));
2406 memset(file_acl
,0,BUFSIZ
);
2408 file_acl
->acl_len
= ACL_SIZ
;
2409 file_acl
->acl_mode
= S_IXACL
;
2411 for(acl_entry_link
=theacl
; acl_entry_link
!= NULL
; acl_entry_link
= acl_entry_link
->nextp
) {
2412 acl_entry_link
->entryp
->ace_access
>>= 6;
2413 id_type
= acl_entry_link
->entryp
->ace_id
->id_type
;
2416 case SMB_ACL_USER_OBJ
:
2417 file_acl
->u_access
= acl_entry_link
->entryp
->ace_access
;
2419 case SMB_ACL_GROUP_OBJ
:
2420 file_acl
->g_access
= acl_entry_link
->entryp
->ace_access
;
2423 file_acl
->o_access
= acl_entry_link
->entryp
->ace_access
;
2429 if((file_acl
->acl_len
+ sizeof(struct acl_entry
)) > acl_length
) {
2430 acl_length
+= sizeof(struct acl_entry
);
2431 file_acl_temp
= (struct acl
*)SMB_MALLOC(acl_length
);
2432 if(file_acl_temp
== NULL
) {
2433 SAFE_FREE(file_acl
);
2435 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno
));
2439 memcpy(file_acl_temp
,file_acl
,file_acl
->acl_len
);
2440 SAFE_FREE(file_acl
);
2441 file_acl
= file_acl_temp
;
2444 acl_entry
= (struct acl_entry
*)((char *)file_acl
+ file_acl
->acl_len
);
2445 file_acl
->acl_len
+= sizeof(struct acl_entry
);
2446 acl_entry
->ace_len
= acl_entry_link
->entryp
->ace_len
;
2447 acl_entry
->ace_access
= acl_entry_link
->entryp
->ace_access
;
2449 /* In order to use this, we'll need to wait until we can get denies */
2450 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2451 acl_entry->ace_type = ACC_SPECIFY; */
2453 acl_entry
->ace_type
= ACC_SPECIFY
;
2455 ace_id
= acl_entry
->ace_id
;
2457 ace_id
->id_type
= acl_entry_link
->entryp
->ace_id
->id_type
;
2458 DEBUG(10,("The id type is %d\n",ace_id
->id_type
));
2459 ace_id
->id_len
= acl_entry_link
->entryp
->ace_id
->id_len
;
2460 memcpy(&user_id
, acl_entry_link
->entryp
->ace_id
->id_data
, sizeof(uid_t
));
2461 memcpy(acl_entry
->ace_id
->id_data
, &user_id
, sizeof(uid_t
));
2464 rc
= chacl((char*)name
,file_acl
,file_acl
->acl_len
);
2465 DEBUG(10,("errno is %d\n",errno
));
2466 DEBUG(10,("return code is %d\n",rc
));
2467 SAFE_FREE(file_acl
);
2468 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2473 int sys_acl_set_fd( int fd
, SMB_ACL_T theacl
)
2475 struct acl_entry_link
*acl_entry_link
= NULL
;
2476 struct acl
*file_acl
= NULL
;
2477 struct acl
*file_acl_temp
= NULL
;
2478 struct acl_entry
*acl_entry
= NULL
;
2479 struct ace_id
*ace_id
= NULL
;
2485 DEBUG(10,("Entering sys_acl_set_fd\n"));
2486 acl_length
= BUFSIZ
;
2487 file_acl
= (struct acl
*)SMB_MALLOC(BUFSIZ
);
2489 if(file_acl
== NULL
) {
2491 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno
));
2495 memset(file_acl
,0,BUFSIZ
);
2497 file_acl
->acl_len
= ACL_SIZ
;
2498 file_acl
->acl_mode
= S_IXACL
;
2500 for(acl_entry_link
=theacl
; acl_entry_link
!= NULL
; acl_entry_link
= acl_entry_link
->nextp
) {
2501 acl_entry_link
->entryp
->ace_access
>>= 6;
2502 id_type
= acl_entry_link
->entryp
->ace_id
->id_type
;
2503 DEBUG(10,("The id_type is %d\n",id_type
));
2506 case SMB_ACL_USER_OBJ
:
2507 file_acl
->u_access
= acl_entry_link
->entryp
->ace_access
;
2509 case SMB_ACL_GROUP_OBJ
:
2510 file_acl
->g_access
= acl_entry_link
->entryp
->ace_access
;
2513 file_acl
->o_access
= acl_entry_link
->entryp
->ace_access
;
2519 if((file_acl
->acl_len
+ sizeof(struct acl_entry
)) > acl_length
) {
2520 acl_length
+= sizeof(struct acl_entry
);
2521 file_acl_temp
= (struct acl
*)SMB_MALLOC(acl_length
);
2522 if(file_acl_temp
== NULL
) {
2523 SAFE_FREE(file_acl
);
2525 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno
));
2529 memcpy(file_acl_temp
,file_acl
,file_acl
->acl_len
);
2530 SAFE_FREE(file_acl
);
2531 file_acl
= file_acl_temp
;
2534 acl_entry
= (struct acl_entry
*)((char *)file_acl
+ file_acl
->acl_len
);
2535 file_acl
->acl_len
+= sizeof(struct acl_entry
);
2536 acl_entry
->ace_len
= acl_entry_link
->entryp
->ace_len
;
2537 acl_entry
->ace_access
= acl_entry_link
->entryp
->ace_access
;
2539 /* In order to use this, we'll need to wait until we can get denies */
2540 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2541 acl_entry->ace_type = ACC_SPECIFY; */
2543 acl_entry
->ace_type
= ACC_SPECIFY
;
2545 ace_id
= acl_entry
->ace_id
;
2547 ace_id
->id_type
= acl_entry_link
->entryp
->ace_id
->id_type
;
2548 DEBUG(10,("The id type is %d\n",ace_id
->id_type
));
2549 ace_id
->id_len
= acl_entry_link
->entryp
->ace_id
->id_len
;
2550 memcpy(&user_id
, acl_entry_link
->entryp
->ace_id
->id_data
, sizeof(uid_t
));
2551 memcpy(ace_id
->id_data
, &user_id
, sizeof(uid_t
));
2554 rc
= fchacl(fd
,file_acl
,file_acl
->acl_len
);
2555 DEBUG(10,("errno is %d\n",errno
));
2556 DEBUG(10,("return code is %d\n",rc
));
2557 SAFE_FREE(file_acl
);
2558 DEBUG(10,("Exiting sys_acl_set_fd\n"));
2563 int sys_acl_delete_def_file(UNUSED(const char *name
))
2565 /* AIX has no default ACL */
2569 int sys_acl_free_acl(SMB_ACL_T posix_acl
)
2571 struct acl_entry_link
*acl_entry_link
;
2573 for(acl_entry_link
= posix_acl
->nextp
; acl_entry_link
->nextp
!= NULL
; acl_entry_link
= acl_entry_link
->nextp
) {
2574 SAFE_FREE(acl_entry_link
->prevp
->entryp
);
2575 SAFE_FREE(acl_entry_link
->prevp
);
2578 SAFE_FREE(acl_entry_link
->prevp
->entryp
);
2579 SAFE_FREE(acl_entry_link
->prevp
);
2580 SAFE_FREE(acl_entry_link
->entryp
);
2581 SAFE_FREE(acl_entry_link
);
2586 #elif defined(HAVE_OSX_ACLS) /*----------------------------------------------*/
2588 #define OSX_BROKEN_GETENTRY /* returns 0 instead of 1 */
2590 #include <membership.h>
2592 int sys_acl_get_entry(SMB_ACL_T the_acl
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
2594 int ret
= acl_get_entry(the_acl
, entry_id
, entry_p
);
2595 #ifdef OSX_BROKEN_GETENTRY
2598 else if (ret
== -1 && errno
== 22)
2604 SMB_ACL_T
sys_acl_get_file(const char *path_p
, SMB_ACL_TYPE_T type
)
2606 if (type
== ACL_TYPE_DEFAULT
) {
2611 return acl_get_file(path_p
, type
);
2615 SMB_ACL_T
sys_acl_get_fd(int fd
)
2617 return acl_get_fd(fd
);
2621 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
)
2625 acl_flagset_t flagset
;
2626 acl_permset_t permset
;
2627 uint32 bits
, fb
, bb
, pb
;
2631 if (acl_get_tag_type(entry
, &tag
) != 0
2632 || acl_get_flagset_np(entry
, &flagset
) != 0
2633 || acl_get_permset(entry
, &permset
) != 0
2634 || (uup
= acl_get_qualifier(entry
)) == NULL
)
2637 rc
= mbr_uuid_to_id(*uup
, u_g_id_p
, &id_type
);
2642 if (id_type
== ID_TYPE_UID
)
2643 *tag_type_p
= SMB_ACL_USER
;
2645 *tag_type_p
= SMB_ACL_GROUP
;
2647 bits
= tag
== ACL_EXTENDED_ALLOW
? 1 : 0;
2649 for (fb
= (1u<<4), bb
= (1u<<1); bb
< (1u<<12); fb
*= 2, bb
*= 2) {
2650 if (acl_get_flag_np(flagset
, fb
) == 1)
2654 for (pb
= (1u<<1), bb
= (1u<<12); bb
< (1u<<25); pb
*= 2, bb
*= 2) {
2655 if (acl_get_perm_np(permset
, pb
) == 1)
2664 SMB_ACL_T
sys_acl_init(int count
)
2666 return acl_init(count
);
2669 int sys_acl_create_entry(SMB_ACL_T
*pacl
, SMB_ACL_ENTRY_T
*pentry
)
2671 return acl_create_entry(pacl
, pentry
);
2674 int sys_acl_set_info(SMB_ACL_ENTRY_T entry
, SMB_ACL_TAG_T tag_type
, uint32 bits
, id_t u_g_id
)
2676 acl_flagset_t flagset
;
2677 acl_permset_t permset
;
2679 int is_user
= tag_type
== SMB_ACL_USER
;
2683 tag_type
= bits
& 1 ? ACL_EXTENDED_ALLOW
: ACL_EXTENDED_DENY
;
2685 if (acl_get_flagset_np(entry
, &flagset
) != 0
2686 || acl_get_permset(entry
, &permset
) != 0)
2689 acl_clear_flags_np(flagset
);
2690 acl_clear_perms(permset
);
2692 for (fb
= (1u<<4), bb
= (1u<<1); bb
< (1u<<12); fb
*= 2, bb
*= 2) {
2694 acl_add_flag_np(flagset
, fb
);
2697 for (pb
= (1u<<1), bb
= (1u<<12); bb
< (1u<<25); pb
*= 2, bb
*= 2) {
2699 acl_add_perm(permset
, pb
);
2703 rc
= mbr_uid_to_uuid(u_g_id
, uu
);
2705 rc
= mbr_gid_to_uuid(u_g_id
, uu
);
2707 if (acl_set_tag_type(entry
, tag_type
) != 0
2708 || acl_set_qualifier(entry
, &uu
) != 0
2709 || acl_set_permset(entry
, permset
) != 0
2710 || acl_set_flagset_np(entry
, flagset
) != 0)
2717 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry
, uint32 bits
)
2719 return -1; /* Not needed for OS X. */
2723 int sys_acl_valid(SMB_ACL_T theacl
)
2725 return acl_valid(theacl
);
2728 int sys_acl_set_file(const char *name
, SMB_ACL_TYPE_T acltype
, SMB_ACL_T theacl
)
2730 return acl_set_file(name
, acltype
, theacl
);
2734 int sys_acl_set_fd(int fd
, SMB_ACL_T theacl
)
2736 return acl_set_fd(fd
, theacl
);
2740 int sys_acl_delete_def_file(const char *name
)
2742 return acl_delete_def_file(name
);
2745 int sys_acl_free_acl(SMB_ACL_T the_acl
)
2747 return acl_free(the_acl
);
2750 #else /* No ACLs. */
2752 #error No ACL functions defined for this platform!
2756 /************************************************************************
2757 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
2759 ************************************************************************/
2761 int no_acl_syscall_error(int err
)
2763 #ifdef HAVE_OSX_ACLS
2765 return 1; /* Weird problem with directory ACLs. */
2768 if (err
== ENOSYS
) {
2772 #if defined(ENOTSUP)
2773 if (err
== ENOTSUP
) {
2780 #endif /* SUPPORT_ACLS */