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 version 3 as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * with this program; if not, visit the http://fsf.org website.
32 void SAFE_FREE(void *mem)
39 This file wraps all differing system ACL interfaces into a consistent
40 one based on the POSIX interface. It also returns the correct errors
41 for older UNIX systems that don't support ACLs.
43 The interfaces that each ACL implementation must support are as follows :
45 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
46 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
47 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
48 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
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_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
54 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
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)
61 The generic POSIX free is the following call. We split this into
62 several different free functions as we may need to add tag info
63 to structures when emulating the POSIX interface.
65 int sys_acl_free( void *obj_p)
67 The calls we actually use are :
69 int sys_acl_free_acl(SMB_ACL_T posix_acl)
70 int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
74 #if defined(HAVE_POSIX_ACLS)
76 /* Identity mapping - easy. */
78 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
80 return acl_get_entry( the_acl, entry_id, entry_p);
83 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
85 return acl_get_tag_type( entry_d, tag_type_p);
88 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
90 return acl_get_qualifier( entry_d);
93 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
95 return acl_get_file( path_p, type);
99 SMB_ACL_T sys_acl_get_fd(int fd)
101 return acl_get_fd(fd);
105 #if defined(HAVE_ACL_GET_PERM_NP)
106 #define acl_get_perm(p, b) acl_get_perm_np(p, b)
109 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
111 SMB_ACL_PERMSET_T permset;
113 if ((rc = acl_get_permset(entry_d, &permset)) != 0)
115 *bits = (acl_get_perm(permset, ACL_READ) ? 4 : 0)
116 | (acl_get_perm(permset, ACL_WRITE) ? 2 : 0)
117 | (acl_get_perm(permset, ACL_EXECUTE) ? 1 : 0);
121 SMB_ACL_T sys_acl_init( int count)
123 return acl_init(count);
126 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
128 return acl_create_entry(pacl, pentry);
131 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
133 return acl_set_tag_type(entry, tagtype);
136 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
138 return acl_set_qualifier(entry, qual);
141 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
143 SMB_ACL_PERMSET_T permset;
145 if ((rc = acl_get_permset(entry, &permset)) != 0)
147 acl_clear_perms(permset);
149 acl_add_perm(permset, ACL_READ);
151 acl_add_perm(permset, ACL_WRITE);
153 acl_add_perm(permset, ACL_EXECUTE);
154 return acl_set_permset(entry, permset);
157 int sys_acl_valid( SMB_ACL_T theacl )
159 return acl_valid(theacl);
162 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
164 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);
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 int sys_acl_free_qualifier(void *qual, UNUSED(SMB_ACL_TAG_T tagtype))
184 return acl_free(qual);
187 #elif defined(HAVE_TRU64_ACLS)
189 * The interface to DEC/Compaq Tru64 UNIX ACLs
190 * is based on Draft 13 of the POSIX spec which is
191 * slightly different from the Draft 16 interface.
193 * Also, some of the permset manipulation functions
194 * such as acl_clear_perm() and acl_add_perm() appear
195 * to be broken on Tru64 so we have to manipulate
196 * the permission bits in the permset directly.
198 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
200 SMB_ACL_ENTRY_T entry;
202 if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
207 if ((entry = acl_get_entry(the_acl)) != NULL) {
212 return errno ? -1 : 0;
215 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
217 return acl_get_tag_type( entry_d, tag_type_p);
220 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
222 return acl_get_qualifier( entry_d);
225 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
227 return acl_get_file((char *)path_p, type);
231 SMB_ACL_T sys_acl_get_fd(int fd)
233 return acl_get_fd(fd, ACL_TYPE_ACCESS);
237 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
239 SMB_ACL_PERMSET_T permset;
241 if ((rc = acl_get_permset(entry_d, &permset)) != 0)
243 *bits = *permset & 7; /* Tru64 doesn't have acl_get_perm() */
247 SMB_ACL_T sys_acl_init( int count)
249 return acl_init(count);
252 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
254 SMB_ACL_ENTRY_T entry;
256 if ((entry = acl_create_entry(pacl)) == NULL) {
264 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
266 return acl_set_tag_type(entry, tagtype);
269 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
271 return acl_set_qualifier(entry, qual);
274 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
276 SMB_ACL_PERMSET_T permset;
278 if ((rc = acl_get_permset(entry, &permset)) != 0)
281 return acl_set_permset(entry, permset);
284 int sys_acl_valid( SMB_ACL_T theacl )
288 return acl_valid(theacl, &entry);
291 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
293 return acl_set_file((char *)name, acltype, theacl);
296 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
298 return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
301 int sys_acl_delete_def_file(const char *name)
303 return acl_delete_def_file((char *)name);
306 int sys_acl_free_acl(SMB_ACL_T the_acl)
308 return acl_free(the_acl);
311 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
313 return acl_free_qualifier(qual, tagtype);
316 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
319 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
320 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
324 * Note that while this code implements sufficient functionality
325 * to support the sys_acl_* interfaces it does not provide all
326 * of the semantics of the POSIX ACL interfaces.
328 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
329 * from a call to sys_acl_get_entry() should not be assumed to be
330 * valid after calling any of the following functions, which may
331 * reorder the entries in the ACL.
339 * The only difference between Solaris and UnixWare / OpenUNIX is
340 * that the #defines for the ACL operations have different names
342 #if defined(HAVE_UNIXWARE_ACLS)
344 #define SETACL ACL_SET
345 #define GETACL ACL_GET
346 #define GETACLCNT ACL_CNT
351 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
353 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
358 if (entry_p == NULL) {
363 if (entry_id == SMB_ACL_FIRST_ENTRY) {
367 if (acl_d->next < 0) {
372 if (acl_d->next >= acl_d->count) {
376 *entry_p = &acl_d->acl[acl_d->next++];
381 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
383 *type_p = entry_d->a_type;
388 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
390 if (entry_d->a_type != SMB_ACL_USER
391 && entry_d->a_type != SMB_ACL_GROUP) {
396 return &entry_d->a_id;
400 * There is no way of knowing what size the ACL returned by
401 * GETACL will be unless you first call GETACLCNT which means
402 * making an additional system call.
404 * In the hope of avoiding the cost of the additional system
405 * call in most cases, we initially allocate enough space for
406 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
407 * be too small then we use GETACLCNT to find out the actual
408 * size, reallocate the ACL buffer, and then call GETACL again.
411 #define INITIAL_ACL_SIZE 16
413 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
416 int count; /* # of ACL entries allocated */
417 int naccess; /* # of access ACL entries */
418 int ndefault; /* # of default ACL entries */
420 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
425 count = INITIAL_ACL_SIZE;
426 if ((acl_d = sys_acl_init(count)) == NULL) {
431 * If there isn't enough space for the ACL entries we use
432 * GETACLCNT to determine the actual number of ACL entries
433 * reallocate and try again. This is in a loop because it
434 * is possible that someone else could modify the ACL and
435 * increase the number of entries between the call to
436 * GETACLCNT and the call to GETACL.
438 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
439 && errno == ENOSPC) {
441 sys_acl_free_acl(acl_d);
443 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
447 if ((acl_d = sys_acl_init(count)) == NULL) {
453 sys_acl_free_acl(acl_d);
458 * calculate the number of access and default ACL entries
460 * Note: we assume that the acl() system call returned a
461 * well formed ACL which is sorted so that all of the
462 * access ACL entries preceed any default ACL entries
464 for (naccess = 0; naccess < count; naccess++) {
465 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
468 ndefault = count - naccess;
471 * if the caller wants the default ACL we have to copy
472 * the entries down to the start of the acl[] buffer
473 * and mask out the ACL_DEFAULT flag from the type field
475 if (type == SMB_ACL_TYPE_DEFAULT) {
478 for (i = 0, j = naccess; i < ndefault; i++, j++) {
479 acl_d->acl[i] = acl_d->acl[j];
480 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
483 acl_d->count = ndefault;
485 acl_d->count = naccess;
492 SMB_ACL_T sys_acl_get_fd(int fd)
495 int count; /* # of ACL entries allocated */
496 int naccess; /* # of access ACL entries */
498 count = INITIAL_ACL_SIZE;
499 if ((acl_d = sys_acl_init(count)) == NULL) {
503 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
504 && errno == ENOSPC) {
506 sys_acl_free_acl(acl_d);
508 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
512 if ((acl_d = sys_acl_init(count)) == NULL) {
518 sys_acl_free_acl(acl_d);
523 * calculate the number of access ACL entries
525 for (naccess = 0; naccess < count; naccess++) {
526 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
530 acl_d->count = naccess;
536 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
538 *bits = entry_d->a_perm;
542 SMB_ACL_T sys_acl_init(int count)
552 * note that since the definition of the structure pointed
553 * to by the SMB_ACL_T includes the first element of the
554 * acl[] array, this actually allocates an ACL with room
555 * for (count+1) entries
557 if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
570 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
573 SMB_ACL_ENTRY_T entry_d;
575 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
580 if (acl_d->count >= acl_d->size) {
585 entry_d = &acl_d->acl[acl_d->count++];
594 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
598 case SMB_ACL_USER_OBJ:
600 case SMB_ACL_GROUP_OBJ:
603 entry_d->a_type = tag_type;
613 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
615 if (entry_d->a_type != SMB_ACL_GROUP
616 && entry_d->a_type != SMB_ACL_USER) {
621 entry_d->a_id = *((id_t *)qual_p);
626 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
628 entry_d->a_perm = bits;
633 * sort the ACL and check it for validity
635 * if it's a minimal ACL with only 4 entries then we
636 * need to recalculate the mask permissions to make
637 * sure that they are the same as the GROUP_OBJ
638 * permissions as required by the UnixWare acl() system call.
640 * (note: since POSIX allows minimal ACLs which only contain
641 * 3 entries - ie there is no mask entry - we should, in theory,
642 * check for this and add a mask entry if necessary - however
643 * we "know" that the caller of this interface always specifies
644 * a mask so, in practice "this never happens" (tm) - if it *does*
645 * happen aclsort() will fail and return an error and someone will
646 * have to fix it ...)
649 static int acl_sort(SMB_ACL_T acl_d)
651 int fixmask = (acl_d->count <= 4);
653 if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
660 int sys_acl_valid(SMB_ACL_T acl_d)
662 return acl_sort(acl_d);
665 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
670 struct acl *acl_buf = NULL;
673 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
678 if (acl_sort(acl_d) != 0) {
682 acl_p = &acl_d->acl[0];
683 acl_count = acl_d->count;
686 * if it's a directory there is extra work to do
687 * since the acl() system call will replace both
688 * the access ACLs and the default ACLs (if any)
690 if (stat(name, &s) != 0) {
693 if (S_ISDIR(s.st_mode)) {
699 if (type == SMB_ACL_TYPE_ACCESS) {
701 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
705 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
708 if (tmp_acl == NULL) {
713 * allocate a temporary buffer for the complete ACL
715 acl_count = acc_acl->count + def_acl->count;
716 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
718 if (acl_buf == NULL) {
719 sys_acl_free_acl(tmp_acl);
725 * copy the access control and default entries into the buffer
727 memcpy(&acl_buf[0], &acc_acl->acl[0],
728 acc_acl->count * sizeof(acl_buf[0]));
730 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
731 def_acl->count * sizeof(acl_buf[0]));
734 * set the ACL_DEFAULT flag on the default entries
736 for (i = acc_acl->count; i < acl_count; i++) {
737 acl_buf[i].a_type |= ACL_DEFAULT;
740 sys_acl_free_acl(tmp_acl);
742 } else if (type != SMB_ACL_TYPE_ACCESS) {
747 ret = acl(name, SETACL, acl_count, acl_p);
754 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
756 if (acl_sort(acl_d) != 0) {
760 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
763 int sys_acl_delete_def_file(const char *path)
769 * fetching the access ACL and rewriting it has
770 * the effect of deleting the default ACL
772 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
776 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
778 sys_acl_free_acl(acl_d);
783 int sys_acl_free_acl(SMB_ACL_T acl_d)
789 int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
794 #elif defined(HAVE_HPUX_ACLS)
798 * Based on the Solaris/SCO code - with modifications.
802 * Note that while this code implements sufficient functionality
803 * to support the sys_acl_* interfaces it does not provide all
804 * of the semantics of the POSIX ACL interfaces.
806 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
807 * from a call to sys_acl_get_entry() should not be assumed to be
808 * valid after calling any of the following functions, which may
809 * reorder the entries in the ACL.
816 /* This checks if the POSIX ACL system call is defined */
817 /* which basically corresponds to whether JFS 3.3 or */
818 /* higher is installed. If acl() was called when it */
819 /* isn't defined, it causes the process to core dump */
820 /* so it is important to check this and avoid acl() */
821 /* calls if it isn't there. */
823 static BOOL hpux_acl_call_presence(void)
829 static BOOL already_checked=0;
835 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
838 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
839 ret_val, errno, strerror(errno)));
840 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
844 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
846 already_checked = True;
850 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
852 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
857 if (entry_p == NULL) {
862 if (entry_id == SMB_ACL_FIRST_ENTRY) {
866 if (acl_d->next < 0) {
871 if (acl_d->next >= acl_d->count) {
875 *entry_p = &acl_d->acl[acl_d->next++];
880 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
882 *type_p = entry_d->a_type;
887 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
889 if (entry_d->a_type != SMB_ACL_USER
890 && entry_d->a_type != SMB_ACL_GROUP) {
895 return &entry_d->a_id;
899 * There is no way of knowing what size the ACL returned by
900 * ACL_GET will be unless you first call ACL_CNT which means
901 * making an additional system call.
903 * In the hope of avoiding the cost of the additional system
904 * call in most cases, we initially allocate enough space for
905 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
906 * be too small then we use ACL_CNT to find out the actual
907 * size, reallocate the ACL buffer, and then call ACL_GET again.
910 #define INITIAL_ACL_SIZE 16
912 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
915 int count; /* # of ACL entries allocated */
916 int naccess; /* # of access ACL entries */
917 int ndefault; /* # of default ACL entries */
919 if(hpux_acl_call_presence() == False) {
920 /* Looks like we don't have the acl() system call on HPUX.
921 * May be the system doesn't have the latest version of JFS.
926 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
931 count = INITIAL_ACL_SIZE;
932 if ((acl_d = sys_acl_init(count)) == NULL) {
937 * If there isn't enough space for the ACL entries we use
938 * ACL_CNT to determine the actual number of ACL entries
939 * reallocate and try again. This is in a loop because it
940 * is possible that someone else could modify the ACL and
941 * increase the number of entries between the call to
942 * ACL_CNT and the call to ACL_GET.
944 while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
946 sys_acl_free_acl(acl_d);
948 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
952 if ((acl_d = sys_acl_init(count)) == NULL) {
958 sys_acl_free_acl(acl_d);
963 * calculate the number of access and default ACL entries
965 * Note: we assume that the acl() system call returned a
966 * well formed ACL which is sorted so that all of the
967 * access ACL entries preceed any default ACL entries
969 for (naccess = 0; naccess < count; naccess++) {
970 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
973 ndefault = count - naccess;
976 * if the caller wants the default ACL we have to copy
977 * the entries down to the start of the acl[] buffer
978 * and mask out the ACL_DEFAULT flag from the type field
980 if (type == SMB_ACL_TYPE_DEFAULT) {
983 for (i = 0, j = naccess; i < ndefault; i++, j++) {
984 acl_d->acl[i] = acl_d->acl[j];
985 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
988 acl_d->count = ndefault;
990 acl_d->count = naccess;
997 SMB_ACL_T sys_acl_get_fd(int fd)
1000 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1003 files_struct *fsp = file_find_fd(fd);
1011 * We know we're in the same conn context. So we
1012 * can use the relative path.
1015 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
1019 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1021 *bits = entry_d->a_perm;
1026 SMB_ACL_T sys_acl_init(int count)
1036 * note that since the definition of the structure pointed
1037 * to by the SMB_ACL_T includes the first element of the
1038 * acl[] array, this actually allocates an ACL with room
1039 * for (count+1) entries
1041 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
1046 a->size = count + 1;
1054 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1057 SMB_ACL_ENTRY_T entry_d;
1059 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1064 if (acl_d->count >= acl_d->size) {
1069 entry_d = &acl_d->acl[acl_d->count++];
1070 entry_d->a_type = 0;
1072 entry_d->a_perm = 0;
1078 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1082 case SMB_ACL_USER_OBJ:
1084 case SMB_ACL_GROUP_OBJ:
1087 entry_d->a_type = tag_type;
1097 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1099 if (entry_d->a_type != SMB_ACL_GROUP
1100 && entry_d->a_type != SMB_ACL_USER) {
1105 entry_d->a_id = *((id_t *)qual_p);
1110 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1112 entry_d->a_perm = bits;
1117 /* Structure to capture the count for each type of ACE. */
1119 struct hpux_acl_types {
1128 int n_def_group_obj;
1132 int n_def_other_obj;
1135 int n_def_class_obj;
1141 * Counts the different number of objects in a given array of ACL
1145 * acl_count - Count of ACLs in the array of ACL strucutres.
1146 * aclp - Array of ACL structures.
1147 * acl_type_count - Pointer to acl_types structure. Should already be
1151 * acl_type_count - This structure is filled up with counts of various
1155 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1159 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1161 for(i=0;i<acl_count;i++) {
1162 switch(aclp[i].a_type) {
1164 acl_type_count->n_user++;
1167 acl_type_count->n_user_obj++;
1170 acl_type_count->n_def_user_obj++;
1173 acl_type_count->n_group++;
1176 acl_type_count->n_group_obj++;
1179 acl_type_count->n_def_group_obj++;
1182 acl_type_count->n_other_obj++;
1185 acl_type_count->n_def_other_obj++;
1188 acl_type_count->n_class_obj++;
1191 acl_type_count->n_def_class_obj++;
1194 acl_type_count->n_def_user++;
1197 acl_type_count->n_def_group++;
1200 acl_type_count->n_illegal_obj++;
1206 /* swap_acl_entries: Swaps two ACL entries.
1208 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1211 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1213 struct acl temp_acl;
1215 temp_acl.a_type = aclp0->a_type;
1216 temp_acl.a_id = aclp0->a_id;
1217 temp_acl.a_perm = aclp0->a_perm;
1219 aclp0->a_type = aclp1->a_type;
1220 aclp0->a_id = aclp1->a_id;
1221 aclp0->a_perm = aclp1->a_perm;
1223 aclp1->a_type = temp_acl.a_type;
1224 aclp1->a_id = temp_acl.a_id;
1225 aclp1->a_perm = temp_acl.a_perm;
1228 /* prohibited_duplicate_type
1229 * Identifies if given ACL type can have duplicate entries or
1232 * Inputs: acl_type - ACL Type.
1238 * True - If the ACL type matches any of the prohibited types.
1239 * False - If the ACL type doesn't match any of the prohibited types.
1242 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1255 /* get_needed_class_perm
1256 * Returns the permissions of a ACL structure only if the ACL
1257 * type matches one of the pre-determined types for computing
1258 * CLASS_OBJ permissions.
1260 * Inputs: aclp - Pointer to ACL structure.
1263 static int hpux_get_needed_class_perm(struct acl *aclp)
1265 switch(aclp->a_type) {
1275 return aclp->a_perm;
1281 /* acl_sort for HPUX.
1282 * Sorts the array of ACL structures as per the description in
1283 * aclsort man page. Refer to aclsort man page for more details
1287 * acl_count - Count of ACLs in the array of ACL structures.
1288 * calclass - If this is not zero, then we compute the CLASS_OBJ
1290 * aclp - Array of ACL structures.
1294 * aclp - Sorted array of ACL structures.
1298 * Returns 0 for success -1 for failure. Prints a message to the Samba
1299 * debug log in case of failure.
1302 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1304 #if !defined(HAVE_HPUX_ACLSORT)
1306 * The aclsort() system call is availabe on the latest HPUX General
1307 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1308 * function. Because, we don't want to update to a new
1309 * HPUX GR bundle just for aclsort() call.
1312 struct hpux_acl_types acl_obj_count;
1313 int n_class_obj_perm = 0;
1317 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1322 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1326 /* Count different types of ACLs in the ACLs array */
1328 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1330 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1331 * CLASS_OBJ and OTHER_OBJ
1334 if( (acl_obj_count.n_user_obj != 1) ||
1335 (acl_obj_count.n_group_obj != 1) ||
1336 (acl_obj_count.n_class_obj != 1) ||
1337 (acl_obj_count.n_other_obj != 1)
1339 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1340 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1344 /* If any of the default objects are present, there should be only
1348 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1349 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1350 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1351 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1355 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1358 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1359 * same ACL type, sort by ACL id.
1361 * I am using the trival kind of sorting method here because, performance isn't
1362 * really effected by the ACLs feature. More over there aren't going to be more
1363 * than 17 entries on HPUX.
1366 for(i=0; i<acl_count;i++) {
1367 for (j=i+1; j<acl_count; j++) {
1368 if( aclp[i].a_type > aclp[j].a_type ) {
1369 /* ACL entries out of order, swap them */
1371 hpux_swap_acl_entries((aclp+i), (aclp+j));
1373 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1375 /* ACL entries of same type, sort by id */
1377 if(aclp[i].a_id > aclp[j].a_id) {
1378 hpux_swap_acl_entries((aclp+i), (aclp+j));
1379 } else if (aclp[i].a_id == aclp[j].a_id) {
1380 /* We have a duplicate entry. */
1381 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1382 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1383 aclp[i].a_type, aclp[i].a_id));
1392 /* set the class obj permissions to the computed one. */
1394 int n_class_obj_index = -1;
1396 for(i=0;i<acl_count;i++) {
1397 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1399 if(aclp[i].a_type == CLASS_OBJ)
1400 n_class_obj_index = i;
1402 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1407 return aclsort(acl_count, calclass, aclp);
1412 * sort the ACL and check it for validity
1414 * if it's a minimal ACL with only 4 entries then we
1415 * need to recalculate the mask permissions to make
1416 * sure that they are the same as the GROUP_OBJ
1417 * permissions as required by the UnixWare acl() system call.
1419 * (note: since POSIX allows minimal ACLs which only contain
1420 * 3 entries - ie there is no mask entry - we should, in theory,
1421 * check for this and add a mask entry if necessary - however
1422 * we "know" that the caller of this interface always specifies
1423 * a mask so, in practice "this never happens" (tm) - if it *does*
1424 * happen aclsort() will fail and return an error and someone will
1425 * have to fix it ...)
1428 static int acl_sort(SMB_ACL_T acl_d)
1430 int fixmask = (acl_d->count <= 4);
1432 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1439 int sys_acl_valid(SMB_ACL_T acl_d)
1441 return acl_sort(acl_d);
1444 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1449 struct acl *acl_buf = NULL;
1452 if(hpux_acl_call_presence() == False) {
1453 /* Looks like we don't have the acl() system call on HPUX.
1454 * May be the system doesn't have the latest version of JFS.
1460 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1465 if (acl_sort(acl_d) != 0) {
1469 acl_p = &acl_d->acl[0];
1470 acl_count = acl_d->count;
1473 * if it's a directory there is extra work to do
1474 * since the acl() system call will replace both
1475 * the access ACLs and the default ACLs (if any)
1477 if (stat(name, &s) != 0) {
1480 if (S_ISDIR(s.st_mode)) {
1486 if (type == SMB_ACL_TYPE_ACCESS) {
1488 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1492 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1495 if (tmp_acl == NULL) {
1500 * allocate a temporary buffer for the complete ACL
1502 acl_count = acc_acl->count + def_acl->count;
1503 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1505 if (acl_buf == NULL) {
1506 sys_acl_free_acl(tmp_acl);
1512 * copy the access control and default entries into the buffer
1514 memcpy(&acl_buf[0], &acc_acl->acl[0],
1515 acc_acl->count * sizeof(acl_buf[0]));
1517 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1518 def_acl->count * sizeof(acl_buf[0]));
1521 * set the ACL_DEFAULT flag on the default entries
1523 for (i = acc_acl->count; i < acl_count; i++) {
1524 acl_buf[i].a_type |= ACL_DEFAULT;
1527 sys_acl_free_acl(tmp_acl);
1529 } else if (type != SMB_ACL_TYPE_ACCESS) {
1534 ret = acl(name, ACL_SET, acl_count, acl_p);
1544 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1547 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1550 files_struct *fsp = file_find_fd(fd);
1557 if (acl_sort(acl_d) != 0) {
1562 * We know we're in the same conn context. So we
1563 * can use the relative path.
1566 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1570 int sys_acl_delete_def_file(const char *path)
1576 * fetching the access ACL and rewriting it has
1577 * the effect of deleting the default ACL
1579 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1583 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1585 sys_acl_free_acl(acl_d);
1590 int sys_acl_free_acl(SMB_ACL_T acl_d)
1596 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1601 #elif defined(HAVE_IRIX_ACLS)
1603 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1605 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1610 if (entry_p == NULL) {
1615 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1619 if (acl_d->next < 0) {
1624 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1628 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1633 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1635 *type_p = entry_d->ae_tag;
1640 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1642 if (entry_d->ae_tag != SMB_ACL_USER
1643 && entry_d->ae_tag != SMB_ACL_GROUP) {
1648 return &entry_d->ae_id;
1651 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1655 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1659 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1669 SMB_ACL_T sys_acl_get_fd(int fd)
1673 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1677 if ((a->aclp = acl_get_fd(fd)) == NULL) {
1687 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1689 *bits = entry_d->ae_perm;
1694 SMB_ACL_T sys_acl_init(int count)
1703 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
1709 a->freeaclp = False;
1710 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
1711 a->aclp->acl_cnt = 0;
1717 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1720 SMB_ACL_ENTRY_T entry_d;
1722 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1727 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
1732 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
1733 entry_d->ae_tag = 0;
1735 entry_d->ae_perm = 0;
1741 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1745 case SMB_ACL_USER_OBJ:
1747 case SMB_ACL_GROUP_OBJ:
1750 entry_d->ae_tag = tag_type;
1760 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1762 if (entry_d->ae_tag != SMB_ACL_GROUP
1763 && entry_d->ae_tag != SMB_ACL_USER) {
1768 entry_d->ae_id = *((id_t *)qual_p);
1773 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1775 entry_d->ae_perm = bits;
1780 int sys_acl_valid(SMB_ACL_T acl_d)
1782 return acl_valid(acl_d->aclp);
1785 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1787 return acl_set_file(name, type, acl_d->aclp);
1790 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1792 return acl_set_fd(fd, acl_d->aclp);
1795 int sys_acl_delete_def_file(const char *name)
1797 return acl_delete_def_file(name);
1800 int sys_acl_free_acl(SMB_ACL_T acl_d)
1802 if (acl_d->freeaclp) {
1803 acl_free(acl_d->aclp);
1809 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1814 #elif defined(HAVE_AIX_ACLS)
1816 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1818 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1820 struct acl_entry_link *link;
1821 struct new_acl_entry *entry;
1824 DEBUG(10,("This is the count: %d\n",theacl->count));
1826 /* Check if count was previously set to -1. *
1827 * If it was, that means we reached the end *
1828 * of the acl last time. */
1829 if(theacl->count == -1)
1833 /* To get to the next acl, traverse linked list until index *
1834 * of acl matches the count we are keeping. This count is *
1835 * incremented each time we return an acl entry. */
1837 for(keep_going = 0; keep_going < theacl->count; keep_going++)
1840 entry = *entry_p = link->entryp;
1842 DEBUG(10,("*entry_p is %d\n",entry_p));
1843 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1845 /* Increment count */
1847 if(link->nextp == NULL)
1853 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1855 /* Initialize tag type */
1858 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1860 /* Depending on what type of entry we have, *
1861 * return tag type. */
1862 switch(entry_d->ace_id->id_type) {
1864 *tag_type_p = SMB_ACL_USER;
1867 *tag_type_p = SMB_ACL_GROUP;
1870 case SMB_ACL_USER_OBJ:
1871 case SMB_ACL_GROUP_OBJ:
1873 *tag_type_p = entry_d->ace_id->id_type;
1883 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1885 SMB_ACL_PERMSET_T permset;
1886 DEBUG(10,("Starting AIX sys_acl_get_access_bits\n"));
1887 permset = &entry_d->ace_access;
1888 DEBUG(10,("*permset is %d\n",*permset));
1889 *bits = (*permset & S_IRUSR ? 4 : 0)
1890 | (*permset & S_IWUSR ? 2 : 0)
1891 | (*permset & S_IXUSR ? 1 : 0);
1892 DEBUG(10,("Ending AIX sys_acl_get_access_bits\n"));
1896 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1898 return(entry_d->ace_id->id_data);
1901 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1903 struct acl *file_acl = (struct acl *)NULL;
1904 struct acl_entry *acl_entry;
1905 struct new_acl_entry *new_acl_entry;
1907 struct acl_entry_link *acl_entry_link;
1908 struct acl_entry_link *acl_entry_link_head;
1913 /* AIX has no DEFAULT */
1914 if ( type == SMB_ACL_TYPE_DEFAULT ) {
1919 /* Get the acl using statacl */
1921 DEBUG(10,("Entering sys_acl_get_file\n"));
1922 DEBUG(10,("path_p is %s\n",path_p));
1924 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
1926 if(file_acl == NULL) {
1928 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1932 memset(file_acl,0,BUFSIZ);
1934 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1936 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1937 SAFE_FREE(file_acl);
1941 DEBUG(10,("Got facl and returned it\n"));
1943 /* Point to the first acl entry in the acl */
1944 acl_entry = file_acl->acl_ext;
1946 /* Begin setting up the head of the linked list *
1947 * that will be used for the storing the acl *
1948 * in a way that is useful for the posix_acls.c *
1951 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1952 if(acl_entry_link_head == NULL)
1955 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1956 if(acl_entry_link->entryp == NULL) {
1957 SAFE_FREE(file_acl);
1959 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1963 DEBUG(10,("acl_entry is %d\n",acl_entry));
1964 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1966 /* Check if the extended acl bit is on. *
1967 * If it isn't, do not show the *
1968 * contents of the acl since AIX intends *
1969 * the extended info to remain unused */
1971 if(file_acl->acl_mode & S_IXACL){
1972 /* while we are not pointing to the very end */
1973 while(acl_entry < acl_last(file_acl)) {
1974 /* before we malloc anything, make sure this is */
1975 /* a valid acl entry and one that we want to map */
1976 idp = id_nxt(acl_entry->ace_id);
1977 if((acl_entry->ace_type == ACC_SPECIFY ||
1978 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1979 acl_entry = acl_nxt(acl_entry);
1983 idp = acl_entry->ace_id;
1985 /* Check if this is the first entry in the linked list. *
1986 * The first entry needs to keep prevp pointing to NULL *
1987 * and already has entryp allocated. */
1989 if(acl_entry_link_head->count != 0) {
1990 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
1992 if(acl_entry_link->nextp == NULL) {
1993 SAFE_FREE(file_acl);
1995 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1999 acl_entry_link->nextp->prevp = acl_entry_link;
2000 acl_entry_link = acl_entry_link->nextp;
2001 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2002 if(acl_entry_link->entryp == NULL) {
2003 SAFE_FREE(file_acl);
2005 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2008 acl_entry_link->nextp = NULL;
2011 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2013 /* Don't really need this since all types are going *
2014 * to be specified but, it's better than leaving it 0 */
2016 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2018 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2020 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2022 /* The access in the acl entries must be left shifted by *
2023 * three bites, because they will ultimately be compared *
2024 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2026 switch(acl_entry->ace_type){
2029 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2030 acl_entry_link->entryp->ace_access <<= 6;
2031 acl_entry_link_head->count++;
2034 /* Since there is no way to return a DENY acl entry *
2035 * change to PERMIT and then shift. */
2036 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2037 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2038 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2039 acl_entry_link->entryp->ace_access <<= 6;
2040 acl_entry_link_head->count++;
2046 DEBUG(10,("acl_entry = %d\n",acl_entry));
2047 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2049 acl_entry = acl_nxt(acl_entry);
2051 } /* end of if enabled */
2053 /* Since owner, group, other acl entries are not *
2054 * part of the acl entries in an acl, they must *
2055 * be dummied up to become part of the list. */
2057 for( i = 1; i < 4; i++) {
2058 DEBUG(10,("i is %d\n",i));
2059 if(acl_entry_link_head->count != 0) {
2060 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2061 if(acl_entry_link->nextp == NULL) {
2062 SAFE_FREE(file_acl);
2064 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2068 acl_entry_link->nextp->prevp = acl_entry_link;
2069 acl_entry_link = acl_entry_link->nextp;
2070 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2071 if(acl_entry_link->entryp == NULL) {
2072 SAFE_FREE(file_acl);
2074 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2079 acl_entry_link->nextp = NULL;
2081 new_acl_entry = acl_entry_link->entryp;
2082 idp = new_acl_entry->ace_id;
2084 new_acl_entry->ace_len = sizeof(struct acl_entry);
2085 new_acl_entry->ace_type = ACC_PERMIT;
2086 idp->id_len = sizeof(struct ace_id);
2087 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2088 memset(idp->id_data,0,sizeof(uid_t));
2092 new_acl_entry->ace_access = file_acl->g_access << 6;
2093 idp->id_type = SMB_ACL_GROUP_OBJ;
2097 new_acl_entry->ace_access = file_acl->o_access << 6;
2098 idp->id_type = SMB_ACL_OTHER;
2102 new_acl_entry->ace_access = file_acl->u_access << 6;
2103 idp->id_type = SMB_ACL_USER_OBJ;
2111 acl_entry_link_head->count++;
2112 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2115 acl_entry_link_head->count = 0;
2116 SAFE_FREE(file_acl);
2118 return(acl_entry_link_head);
2122 SMB_ACL_T sys_acl_get_fd(int fd)
2124 struct acl *file_acl = (struct acl *)NULL;
2125 struct acl_entry *acl_entry;
2126 struct new_acl_entry *new_acl_entry;
2128 struct acl_entry_link *acl_entry_link;
2129 struct acl_entry_link *acl_entry_link_head;
2134 /* Get the acl using fstatacl */
2136 DEBUG(10,("Entering sys_acl_get_fd\n"));
2137 DEBUG(10,("fd is %d\n",fd));
2138 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2140 if(file_acl == NULL) {
2142 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2146 memset(file_acl,0,BUFSIZ);
2148 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2150 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2151 SAFE_FREE(file_acl);
2155 DEBUG(10,("Got facl and returned it\n"));
2157 /* Point to the first acl entry in the acl */
2159 acl_entry = file_acl->acl_ext;
2160 /* Begin setting up the head of the linked list *
2161 * that will be used for the storing the acl *
2162 * in a way that is useful for the posix_acls.c *
2165 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2166 if(acl_entry_link_head == NULL){
2167 SAFE_FREE(file_acl);
2171 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2173 if(acl_entry_link->entryp == NULL) {
2175 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2176 SAFE_FREE(file_acl);
2180 DEBUG(10,("acl_entry is %d\n",acl_entry));
2181 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2183 /* Check if the extended acl bit is on. *
2184 * If it isn't, do not show the *
2185 * contents of the acl since AIX intends *
2186 * the extended info to remain unused */
2188 if(file_acl->acl_mode & S_IXACL){
2189 /* while we are not pointing to the very end */
2190 while(acl_entry < acl_last(file_acl)) {
2191 /* before we malloc anything, make sure this is */
2192 /* a valid acl entry and one that we want to map */
2194 idp = id_nxt(acl_entry->ace_id);
2195 if((acl_entry->ace_type == ACC_SPECIFY ||
2196 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2197 acl_entry = acl_nxt(acl_entry);
2201 idp = acl_entry->ace_id;
2203 /* Check if this is the first entry in the linked list. *
2204 * The first entry needs to keep prevp pointing to NULL *
2205 * and already has entryp allocated. */
2207 if(acl_entry_link_head->count != 0) {
2208 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2209 if(acl_entry_link->nextp == NULL) {
2211 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2212 SAFE_FREE(file_acl);
2215 acl_entry_link->nextp->prevp = acl_entry_link;
2216 acl_entry_link = acl_entry_link->nextp;
2217 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2218 if(acl_entry_link->entryp == NULL) {
2220 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2221 SAFE_FREE(file_acl);
2225 acl_entry_link->nextp = NULL;
2228 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2230 /* Don't really need this since all types are going *
2231 * to be specified but, it's better than leaving it 0 */
2233 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2234 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2236 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2238 /* The access in the acl entries must be left shifted by *
2239 * three bites, because they will ultimately be compared *
2240 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2242 switch(acl_entry->ace_type){
2245 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2246 acl_entry_link->entryp->ace_access <<= 6;
2247 acl_entry_link_head->count++;
2250 /* Since there is no way to return a DENY acl entry *
2251 * change to PERMIT and then shift. */
2252 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2253 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2254 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2255 acl_entry_link->entryp->ace_access <<= 6;
2256 acl_entry_link_head->count++;
2262 DEBUG(10,("acl_entry = %d\n",acl_entry));
2263 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2265 acl_entry = acl_nxt(acl_entry);
2267 } /* end of if enabled */
2269 /* Since owner, group, other acl entries are not *
2270 * part of the acl entries in an acl, they must *
2271 * be dummied up to become part of the list. */
2273 for( i = 1; i < 4; i++) {
2274 DEBUG(10,("i is %d\n",i));
2275 if(acl_entry_link_head->count != 0){
2276 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2277 if(acl_entry_link->nextp == NULL) {
2279 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2280 SAFE_FREE(file_acl);
2284 acl_entry_link->nextp->prevp = acl_entry_link;
2285 acl_entry_link = acl_entry_link->nextp;
2286 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2288 if(acl_entry_link->entryp == NULL) {
2289 SAFE_FREE(file_acl);
2291 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2296 acl_entry_link->nextp = NULL;
2298 new_acl_entry = acl_entry_link->entryp;
2299 idp = new_acl_entry->ace_id;
2301 new_acl_entry->ace_len = sizeof(struct acl_entry);
2302 new_acl_entry->ace_type = ACC_PERMIT;
2303 idp->id_len = sizeof(struct ace_id);
2304 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2305 memset(idp->id_data,0,sizeof(uid_t));
2309 new_acl_entry->ace_access = file_acl->g_access << 6;
2310 idp->id_type = SMB_ACL_GROUP_OBJ;
2314 new_acl_entry->ace_access = file_acl->o_access << 6;
2315 idp->id_type = SMB_ACL_OTHER;
2319 new_acl_entry->ace_access = file_acl->u_access << 6;
2320 idp->id_type = SMB_ACL_USER_OBJ;
2327 acl_entry_link_head->count++;
2328 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2331 acl_entry_link_head->count = 0;
2332 SAFE_FREE(file_acl);
2334 return(acl_entry_link_head);
2338 SMB_ACL_T sys_acl_init( int count)
2340 struct acl_entry_link *theacl = NULL;
2342 DEBUG(10,("Entering sys_acl_init\n"));
2344 theacl = SMB_MALLOC_P(struct acl_entry_link);
2345 if(theacl == NULL) {
2347 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2352 theacl->nextp = NULL;
2353 theacl->prevp = NULL;
2354 theacl->entryp = NULL;
2355 DEBUG(10,("Exiting sys_acl_init\n"));
2359 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2361 struct acl_entry_link *theacl;
2362 struct acl_entry_link *acl_entryp;
2363 struct acl_entry_link *temp_entry;
2366 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2368 theacl = acl_entryp = *pacl;
2370 /* Get to the end of the acl before adding entry */
2372 for(counting=0; counting < theacl->count; counting++){
2373 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2374 temp_entry = acl_entryp;
2375 acl_entryp = acl_entryp->nextp;
2378 if(theacl->count != 0){
2379 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2380 if(acl_entryp == NULL) {
2382 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2386 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2387 acl_entryp->prevp = temp_entry;
2388 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2391 *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2392 if(*pentry == NULL) {
2394 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2398 memset(*pentry,0,sizeof(struct new_acl_entry));
2399 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2400 acl_entryp->entryp->ace_type = ACC_PERMIT;
2401 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2402 acl_entryp->nextp = NULL;
2404 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2408 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2410 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2411 entry->ace_id->id_type = tagtype;
2412 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2413 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2416 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2418 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2419 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2420 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2424 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
2426 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2427 entry->ace_access = bits;
2428 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2429 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2433 int sys_acl_valid( SMB_ACL_T theacl )
2438 struct acl_entry_link *acl_entry;
2440 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2441 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2442 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2443 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2446 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2448 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2454 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2456 struct acl_entry_link *acl_entry_link = NULL;
2457 struct acl *file_acl = NULL;
2458 struct acl *file_acl_temp = NULL;
2459 struct acl_entry *acl_entry = NULL;
2460 struct ace_id *ace_id = NULL;
2467 DEBUG(10,("Entering sys_acl_set_file\n"));
2468 DEBUG(10,("File name is %s\n",name));
2470 /* AIX has no default ACL */
2471 if(acltype == SMB_ACL_TYPE_DEFAULT)
2474 acl_length = BUFSIZ;
2475 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2477 if(file_acl == NULL) {
2479 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2483 memset(file_acl,0,BUFSIZ);
2485 file_acl->acl_len = ACL_SIZ;
2486 file_acl->acl_mode = S_IXACL;
2488 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2489 acl_entry_link->entryp->ace_access >>= 6;
2490 id_type = acl_entry_link->entryp->ace_id->id_type;
2493 case SMB_ACL_USER_OBJ:
2494 file_acl->u_access = acl_entry_link->entryp->ace_access;
2496 case SMB_ACL_GROUP_OBJ:
2497 file_acl->g_access = acl_entry_link->entryp->ace_access;
2500 file_acl->o_access = acl_entry_link->entryp->ace_access;
2506 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2507 acl_length += sizeof(struct acl_entry);
2508 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2509 if(file_acl_temp == NULL) {
2510 SAFE_FREE(file_acl);
2512 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2516 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2517 SAFE_FREE(file_acl);
2518 file_acl = file_acl_temp;
2521 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2522 file_acl->acl_len += sizeof(struct acl_entry);
2523 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2524 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2526 /* In order to use this, we'll need to wait until we can get denies */
2527 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2528 acl_entry->ace_type = ACC_SPECIFY; */
2530 acl_entry->ace_type = ACC_SPECIFY;
2532 ace_id = acl_entry->ace_id;
2534 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2535 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2536 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2537 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2538 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2541 rc = chacl(name,file_acl,file_acl->acl_len);
2542 DEBUG(10,("errno is %d\n",errno));
2543 DEBUG(10,("return code is %d\n",rc));
2544 SAFE_FREE(file_acl);
2545 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2549 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2551 struct acl_entry_link *acl_entry_link = NULL;
2552 struct acl *file_acl = NULL;
2553 struct acl *file_acl_temp = NULL;
2554 struct acl_entry *acl_entry = NULL;
2555 struct ace_id *ace_id = NULL;
2561 DEBUG(10,("Entering sys_acl_set_fd\n"));
2562 acl_length = BUFSIZ;
2563 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2565 if(file_acl == NULL) {
2567 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2571 memset(file_acl,0,BUFSIZ);
2573 file_acl->acl_len = ACL_SIZ;
2574 file_acl->acl_mode = S_IXACL;
2576 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2577 acl_entry_link->entryp->ace_access >>= 6;
2578 id_type = acl_entry_link->entryp->ace_id->id_type;
2579 DEBUG(10,("The id_type is %d\n",id_type));
2582 case SMB_ACL_USER_OBJ:
2583 file_acl->u_access = acl_entry_link->entryp->ace_access;
2585 case SMB_ACL_GROUP_OBJ:
2586 file_acl->g_access = acl_entry_link->entryp->ace_access;
2589 file_acl->o_access = acl_entry_link->entryp->ace_access;
2595 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2596 acl_length += sizeof(struct acl_entry);
2597 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2598 if(file_acl_temp == NULL) {
2599 SAFE_FREE(file_acl);
2601 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2605 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2606 SAFE_FREE(file_acl);
2607 file_acl = file_acl_temp;
2610 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2611 file_acl->acl_len += sizeof(struct acl_entry);
2612 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2613 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2615 /* In order to use this, we'll need to wait until we can get denies */
2616 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2617 acl_entry->ace_type = ACC_SPECIFY; */
2619 acl_entry->ace_type = ACC_SPECIFY;
2621 ace_id = acl_entry->ace_id;
2623 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2624 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2625 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2626 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2627 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2630 rc = fchacl(fd,file_acl,file_acl->acl_len);
2631 DEBUG(10,("errno is %d\n",errno));
2632 DEBUG(10,("return code is %d\n",rc));
2633 SAFE_FREE(file_acl);
2634 DEBUG(10,("Exiting sys_acl_set_fd\n"));
2638 int sys_acl_delete_def_file(const char *name)
2640 /* AIX has no default ACL */
2644 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2646 struct acl_entry_link *acl_entry_link;
2648 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2649 SAFE_FREE(acl_entry_link->prevp->entryp);
2650 SAFE_FREE(acl_entry_link->prevp);
2653 SAFE_FREE(acl_entry_link->prevp->entryp);
2654 SAFE_FREE(acl_entry_link->prevp);
2655 SAFE_FREE(acl_entry_link->entryp);
2656 SAFE_FREE(acl_entry_link);
2661 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2666 #else /* No ACLs. */
2668 #error No ACL functions defined for this platform!
2672 /************************************************************************
2673 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
2675 ************************************************************************/
2677 int no_acl_syscall_error(int err)
2680 if (err == ENOSYS) {
2684 #if defined(ENOTSUP)
2685 if (err == ENOTSUP) {
2692 #endif /* SUPPORT_ACLS */