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 2 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 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 void SAFE_FREE(void *mem)
41 This file wraps all differing system ACL interfaces into a consistent
42 one based on the POSIX interface. It also returns the correct errors
43 for older UNIX systems that don't support ACLs.
45 The interfaces that each ACL implementation must support are as follows :
47 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
48 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
49 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
50 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
51 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
52 SMB_ACL_T sys_acl_get_fd(int fd)
53 SMB_ACL_T sys_acl_init( int count)
54 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
55 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
56 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
57 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
58 int sys_acl_valid( SMB_ACL_T theacl )
59 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
60 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
61 int sys_acl_delete_def_file(const char *path)
63 The generic POSIX free is the following call. We split this into
64 several different free functions as we may need to add tag info
65 to structures when emulating the POSIX interface.
67 int sys_acl_free( void *obj_p)
69 The calls we actually use are :
71 int sys_acl_free_acl(SMB_ACL_T posix_acl)
72 int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
76 #if defined(HAVE_POSIX_ACLS)
78 /* Identity mapping - easy. */
80 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
82 return acl_get_entry( the_acl, entry_id, entry_p);
85 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
87 return acl_get_tag_type( entry_d, tag_type_p);
90 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
92 return acl_get_qualifier( entry_d);
95 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
97 return acl_get_file( path_p, type);
101 SMB_ACL_T sys_acl_get_fd(int fd)
103 return acl_get_fd(fd);
107 #if defined(HAVE_ACL_GET_PERM_NP)
108 #define acl_get_perm(p, b) acl_get_perm_np(p, b)
111 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
113 SMB_ACL_PERMSET_T permset;
115 if ((rc = acl_get_permset(entry_d, &permset)) != 0)
117 *bits = (acl_get_perm(permset, ACL_READ) ? 4 : 0)
118 | (acl_get_perm(permset, ACL_WRITE) ? 2 : 0)
119 | (acl_get_perm(permset, ACL_EXECUTE) ? 1 : 0);
123 SMB_ACL_T sys_acl_init( int count)
125 return acl_init(count);
128 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
130 return acl_create_entry(pacl, pentry);
133 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
135 return acl_set_tag_type(entry, tagtype);
138 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
140 return acl_set_qualifier(entry, qual);
143 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
145 SMB_ACL_PERMSET_T permset;
147 if ((rc = acl_get_permset(entry, &permset)) != 0)
149 acl_clear_perms(permset);
151 acl_add_perm(permset, ACL_READ);
153 acl_add_perm(permset, ACL_WRITE);
155 acl_add_perm(permset, ACL_EXECUTE);
156 return acl_set_permset(entry, permset);
159 int sys_acl_valid( SMB_ACL_T theacl )
161 return acl_valid(theacl);
164 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
166 return acl_set_file(name, acltype, theacl);
169 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
171 return acl_set_fd(fd, theacl);
174 int sys_acl_delete_def_file(const char *name)
176 return acl_delete_def_file(name);
179 int sys_acl_free_acl(SMB_ACL_T the_acl)
181 return acl_free(the_acl);
184 int sys_acl_free_qualifier(void *qual, UNUSED(SMB_ACL_TAG_T tagtype))
186 return acl_free(qual);
189 #elif defined(HAVE_TRU64_ACLS)
191 * The interface to DEC/Compaq Tru64 UNIX ACLs
192 * is based on Draft 13 of the POSIX spec which is
193 * slightly different from the Draft 16 interface.
195 * Also, some of the permset manipulation functions
196 * such as acl_clear_perm() and acl_add_perm() appear
197 * to be broken on Tru64 so we have to manipulate
198 * the permission bits in the permset directly.
200 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
202 SMB_ACL_ENTRY_T entry;
204 if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
209 if ((entry = acl_get_entry(the_acl)) != NULL) {
214 return errno ? -1 : 0;
217 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
219 return acl_get_tag_type( entry_d, tag_type_p);
222 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
224 return acl_get_qualifier( entry_d);
227 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
229 return acl_get_file((char *)path_p, type);
233 SMB_ACL_T sys_acl_get_fd(int fd)
235 return acl_get_fd(fd, ACL_TYPE_ACCESS);
239 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
241 SMB_ACL_PERMSET_T permset;
243 if ((rc = acl_get_permset(entry_d, &permset)) != 0)
245 *bits = *permset & 7; /* Tru64 doesn't have acl_get_perm() */
249 SMB_ACL_T sys_acl_init( int count)
251 return acl_init(count);
254 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
256 SMB_ACL_ENTRY_T entry;
258 if ((entry = acl_create_entry(pacl)) == NULL) {
266 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
268 return acl_set_tag_type(entry, tagtype);
271 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
273 return acl_set_qualifier(entry, qual);
276 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
278 SMB_ACL_PERMSET_T permset;
280 if ((rc = acl_get_permset(entry, &permset)) != 0)
283 return acl_set_permset(entry, permset);
286 int sys_acl_valid( SMB_ACL_T theacl )
290 return acl_valid(theacl, &entry);
293 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
295 return acl_set_file((char *)name, acltype, theacl);
298 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
300 return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
303 int sys_acl_delete_def_file(const char *name)
305 return acl_delete_def_file((char *)name);
308 int sys_acl_free_acl(SMB_ACL_T the_acl)
310 return acl_free(the_acl);
313 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
315 return acl_free_qualifier(qual, tagtype);
318 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
321 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
322 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
326 * Note that while this code implements sufficient functionality
327 * to support the sys_acl_* interfaces it does not provide all
328 * of the semantics of the POSIX ACL interfaces.
330 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
331 * from a call to sys_acl_get_entry() should not be assumed to be
332 * valid after calling any of the following functions, which may
333 * reorder the entries in the ACL.
341 * The only difference between Solaris and UnixWare / OpenUNIX is
342 * that the #defines for the ACL operations have different names
344 #if defined(HAVE_UNIXWARE_ACLS)
346 #define SETACL ACL_SET
347 #define GETACL ACL_GET
348 #define GETACLCNT ACL_CNT
353 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
355 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
360 if (entry_p == NULL) {
365 if (entry_id == SMB_ACL_FIRST_ENTRY) {
369 if (acl_d->next < 0) {
374 if (acl_d->next >= acl_d->count) {
378 *entry_p = &acl_d->acl[acl_d->next++];
383 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
385 *type_p = entry_d->a_type;
390 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
392 if (entry_d->a_type != SMB_ACL_USER
393 && entry_d->a_type != SMB_ACL_GROUP) {
398 return &entry_d->a_id;
402 * There is no way of knowing what size the ACL returned by
403 * GETACL will be unless you first call GETACLCNT which means
404 * making an additional system call.
406 * In the hope of avoiding the cost of the additional system
407 * call in most cases, we initially allocate enough space for
408 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
409 * be too small then we use GETACLCNT to find out the actual
410 * size, reallocate the ACL buffer, and then call GETACL again.
413 #define INITIAL_ACL_SIZE 16
415 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
418 int count; /* # of ACL entries allocated */
419 int naccess; /* # of access ACL entries */
420 int ndefault; /* # of default ACL entries */
422 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
427 count = INITIAL_ACL_SIZE;
428 if ((acl_d = sys_acl_init(count)) == NULL) {
433 * If there isn't enough space for the ACL entries we use
434 * GETACLCNT to determine the actual number of ACL entries
435 * reallocate and try again. This is in a loop because it
436 * is possible that someone else could modify the ACL and
437 * increase the number of entries between the call to
438 * GETACLCNT and the call to GETACL.
440 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
441 && errno == ENOSPC) {
443 sys_acl_free_acl(acl_d);
445 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
449 if ((acl_d = sys_acl_init(count)) == NULL) {
455 sys_acl_free_acl(acl_d);
460 * calculate the number of access and default ACL entries
462 * Note: we assume that the acl() system call returned a
463 * well formed ACL which is sorted so that all of the
464 * access ACL entries preceed any default ACL entries
466 for (naccess = 0; naccess < count; naccess++) {
467 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
470 ndefault = count - naccess;
473 * if the caller wants the default ACL we have to copy
474 * the entries down to the start of the acl[] buffer
475 * and mask out the ACL_DEFAULT flag from the type field
477 if (type == SMB_ACL_TYPE_DEFAULT) {
480 for (i = 0, j = naccess; i < ndefault; i++, j++) {
481 acl_d->acl[i] = acl_d->acl[j];
482 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
485 acl_d->count = ndefault;
487 acl_d->count = naccess;
494 SMB_ACL_T sys_acl_get_fd(int fd)
497 int count; /* # of ACL entries allocated */
498 int naccess; /* # of access ACL entries */
500 count = INITIAL_ACL_SIZE;
501 if ((acl_d = sys_acl_init(count)) == NULL) {
505 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
506 && errno == ENOSPC) {
508 sys_acl_free_acl(acl_d);
510 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
514 if ((acl_d = sys_acl_init(count)) == NULL) {
520 sys_acl_free_acl(acl_d);
525 * calculate the number of access ACL entries
527 for (naccess = 0; naccess < count; naccess++) {
528 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
532 acl_d->count = naccess;
538 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
540 *bits = entry_d->a_perm;
544 SMB_ACL_T sys_acl_init(int count)
554 * note that since the definition of the structure pointed
555 * to by the SMB_ACL_T includes the first element of the
556 * acl[] array, this actually allocates an ACL with room
557 * for (count+1) entries
559 if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
572 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
575 SMB_ACL_ENTRY_T entry_d;
577 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
582 if (acl_d->count >= acl_d->size) {
587 entry_d = &acl_d->acl[acl_d->count++];
596 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
600 case SMB_ACL_USER_OBJ:
602 case SMB_ACL_GROUP_OBJ:
605 entry_d->a_type = tag_type;
615 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
617 if (entry_d->a_type != SMB_ACL_GROUP
618 && entry_d->a_type != SMB_ACL_USER) {
623 entry_d->a_id = *((id_t *)qual_p);
628 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
630 entry_d->a_perm = bits;
635 * sort the ACL and check it for validity
637 * if it's a minimal ACL with only 4 entries then we
638 * need to recalculate the mask permissions to make
639 * sure that they are the same as the GROUP_OBJ
640 * permissions as required by the UnixWare acl() system call.
642 * (note: since POSIX allows minimal ACLs which only contain
643 * 3 entries - ie there is no mask entry - we should, in theory,
644 * check for this and add a mask entry if necessary - however
645 * we "know" that the caller of this interface always specifies
646 * a mask so, in practice "this never happens" (tm) - if it *does*
647 * happen aclsort() will fail and return an error and someone will
648 * have to fix it ...)
651 static int acl_sort(SMB_ACL_T acl_d)
653 int fixmask = (acl_d->count <= 4);
655 if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
662 int sys_acl_valid(SMB_ACL_T acl_d)
664 return acl_sort(acl_d);
667 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
672 struct acl *acl_buf = NULL;
675 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
680 if (acl_sort(acl_d) != 0) {
684 acl_p = &acl_d->acl[0];
685 acl_count = acl_d->count;
688 * if it's a directory there is extra work to do
689 * since the acl() system call will replace both
690 * the access ACLs and the default ACLs (if any)
692 if (stat(name, &s) != 0) {
695 if (S_ISDIR(s.st_mode)) {
701 if (type == SMB_ACL_TYPE_ACCESS) {
703 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
707 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
710 if (tmp_acl == NULL) {
715 * allocate a temporary buffer for the complete ACL
717 acl_count = acc_acl->count + def_acl->count;
718 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
720 if (acl_buf == NULL) {
721 sys_acl_free_acl(tmp_acl);
727 * copy the access control and default entries into the buffer
729 memcpy(&acl_buf[0], &acc_acl->acl[0],
730 acc_acl->count * sizeof(acl_buf[0]));
732 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
733 def_acl->count * sizeof(acl_buf[0]));
736 * set the ACL_DEFAULT flag on the default entries
738 for (i = acc_acl->count; i < acl_count; i++) {
739 acl_buf[i].a_type |= ACL_DEFAULT;
742 sys_acl_free_acl(tmp_acl);
744 } else if (type != SMB_ACL_TYPE_ACCESS) {
749 ret = acl(name, SETACL, acl_count, acl_p);
756 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
758 if (acl_sort(acl_d) != 0) {
762 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
765 int sys_acl_delete_def_file(const char *path)
771 * fetching the access ACL and rewriting it has
772 * the effect of deleting the default ACL
774 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
778 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
780 sys_acl_free_acl(acl_d);
785 int sys_acl_free_acl(SMB_ACL_T acl_d)
791 int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
796 #elif defined(HAVE_HPUX_ACLS)
800 * Based on the Solaris/SCO code - with modifications.
804 * Note that while this code implements sufficient functionality
805 * to support the sys_acl_* interfaces it does not provide all
806 * of the semantics of the POSIX ACL interfaces.
808 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
809 * from a call to sys_acl_get_entry() should not be assumed to be
810 * valid after calling any of the following functions, which may
811 * reorder the entries in the ACL.
818 /* This checks if the POSIX ACL system call is defined */
819 /* which basically corresponds to whether JFS 3.3 or */
820 /* higher is installed. If acl() was called when it */
821 /* isn't defined, it causes the process to core dump */
822 /* so it is important to check this and avoid acl() */
823 /* calls if it isn't there. */
825 static BOOL hpux_acl_call_presence(void)
831 static BOOL already_checked=0;
837 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
840 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
841 ret_val, errno, strerror(errno)));
842 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
846 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
848 already_checked = True;
852 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
854 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
859 if (entry_p == NULL) {
864 if (entry_id == SMB_ACL_FIRST_ENTRY) {
868 if (acl_d->next < 0) {
873 if (acl_d->next >= acl_d->count) {
877 *entry_p = &acl_d->acl[acl_d->next++];
882 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
884 *type_p = entry_d->a_type;
889 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
891 if (entry_d->a_type != SMB_ACL_USER
892 && entry_d->a_type != SMB_ACL_GROUP) {
897 return &entry_d->a_id;
901 * There is no way of knowing what size the ACL returned by
902 * ACL_GET will be unless you first call ACL_CNT which means
903 * making an additional system call.
905 * In the hope of avoiding the cost of the additional system
906 * call in most cases, we initially allocate enough space for
907 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
908 * be too small then we use ACL_CNT to find out the actual
909 * size, reallocate the ACL buffer, and then call ACL_GET again.
912 #define INITIAL_ACL_SIZE 16
914 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
917 int count; /* # of ACL entries allocated */
918 int naccess; /* # of access ACL entries */
919 int ndefault; /* # of default ACL entries */
921 if(hpux_acl_call_presence() == False) {
922 /* Looks like we don't have the acl() system call on HPUX.
923 * May be the system doesn't have the latest version of JFS.
928 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
933 count = INITIAL_ACL_SIZE;
934 if ((acl_d = sys_acl_init(count)) == NULL) {
939 * If there isn't enough space for the ACL entries we use
940 * ACL_CNT to determine the actual number of ACL entries
941 * reallocate and try again. This is in a loop because it
942 * is possible that someone else could modify the ACL and
943 * increase the number of entries between the call to
944 * ACL_CNT and the call to ACL_GET.
946 while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
948 sys_acl_free_acl(acl_d);
950 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
954 if ((acl_d = sys_acl_init(count)) == NULL) {
960 sys_acl_free_acl(acl_d);
965 * calculate the number of access and default ACL entries
967 * Note: we assume that the acl() system call returned a
968 * well formed ACL which is sorted so that all of the
969 * access ACL entries preceed any default ACL entries
971 for (naccess = 0; naccess < count; naccess++) {
972 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
975 ndefault = count - naccess;
978 * if the caller wants the default ACL we have to copy
979 * the entries down to the start of the acl[] buffer
980 * and mask out the ACL_DEFAULT flag from the type field
982 if (type == SMB_ACL_TYPE_DEFAULT) {
985 for (i = 0, j = naccess; i < ndefault; i++, j++) {
986 acl_d->acl[i] = acl_d->acl[j];
987 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
990 acl_d->count = ndefault;
992 acl_d->count = naccess;
999 SMB_ACL_T sys_acl_get_fd(int fd)
1002 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1005 files_struct *fsp = file_find_fd(fd);
1013 * We know we're in the same conn context. So we
1014 * can use the relative path.
1017 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
1021 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1023 *bits = entry_d->a_perm;
1028 SMB_ACL_T sys_acl_init(int count)
1038 * note that since the definition of the structure pointed
1039 * to by the SMB_ACL_T includes the first element of the
1040 * acl[] array, this actually allocates an ACL with room
1041 * for (count+1) entries
1043 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
1048 a->size = count + 1;
1056 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1059 SMB_ACL_ENTRY_T entry_d;
1061 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1066 if (acl_d->count >= acl_d->size) {
1071 entry_d = &acl_d->acl[acl_d->count++];
1072 entry_d->a_type = 0;
1074 entry_d->a_perm = 0;
1080 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1084 case SMB_ACL_USER_OBJ:
1086 case SMB_ACL_GROUP_OBJ:
1089 entry_d->a_type = tag_type;
1099 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1101 if (entry_d->a_type != SMB_ACL_GROUP
1102 && entry_d->a_type != SMB_ACL_USER) {
1107 entry_d->a_id = *((id_t *)qual_p);
1112 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1114 entry_d->a_perm = bits;
1119 /* Structure to capture the count for each type of ACE. */
1121 struct hpux_acl_types {
1130 int n_def_group_obj;
1134 int n_def_other_obj;
1137 int n_def_class_obj;
1143 * Counts the different number of objects in a given array of ACL
1147 * acl_count - Count of ACLs in the array of ACL strucutres.
1148 * aclp - Array of ACL structures.
1149 * acl_type_count - Pointer to acl_types structure. Should already be
1153 * acl_type_count - This structure is filled up with counts of various
1157 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1161 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1163 for(i=0;i<acl_count;i++) {
1164 switch(aclp[i].a_type) {
1166 acl_type_count->n_user++;
1169 acl_type_count->n_user_obj++;
1172 acl_type_count->n_def_user_obj++;
1175 acl_type_count->n_group++;
1178 acl_type_count->n_group_obj++;
1181 acl_type_count->n_def_group_obj++;
1184 acl_type_count->n_other_obj++;
1187 acl_type_count->n_def_other_obj++;
1190 acl_type_count->n_class_obj++;
1193 acl_type_count->n_def_class_obj++;
1196 acl_type_count->n_def_user++;
1199 acl_type_count->n_def_group++;
1202 acl_type_count->n_illegal_obj++;
1208 /* swap_acl_entries: Swaps two ACL entries.
1210 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1213 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1215 struct acl temp_acl;
1217 temp_acl.a_type = aclp0->a_type;
1218 temp_acl.a_id = aclp0->a_id;
1219 temp_acl.a_perm = aclp0->a_perm;
1221 aclp0->a_type = aclp1->a_type;
1222 aclp0->a_id = aclp1->a_id;
1223 aclp0->a_perm = aclp1->a_perm;
1225 aclp1->a_type = temp_acl.a_type;
1226 aclp1->a_id = temp_acl.a_id;
1227 aclp1->a_perm = temp_acl.a_perm;
1230 /* prohibited_duplicate_type
1231 * Identifies if given ACL type can have duplicate entries or
1234 * Inputs: acl_type - ACL Type.
1240 * True - If the ACL type matches any of the prohibited types.
1241 * False - If the ACL type doesn't match any of the prohibited types.
1244 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1257 /* get_needed_class_perm
1258 * Returns the permissions of a ACL structure only if the ACL
1259 * type matches one of the pre-determined types for computing
1260 * CLASS_OBJ permissions.
1262 * Inputs: aclp - Pointer to ACL structure.
1265 static int hpux_get_needed_class_perm(struct acl *aclp)
1267 switch(aclp->a_type) {
1277 return aclp->a_perm;
1283 /* acl_sort for HPUX.
1284 * Sorts the array of ACL structures as per the description in
1285 * aclsort man page. Refer to aclsort man page for more details
1289 * acl_count - Count of ACLs in the array of ACL structures.
1290 * calclass - If this is not zero, then we compute the CLASS_OBJ
1292 * aclp - Array of ACL structures.
1296 * aclp - Sorted array of ACL structures.
1300 * Returns 0 for success -1 for failure. Prints a message to the Samba
1301 * debug log in case of failure.
1304 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1306 #if !defined(HAVE_HPUX_ACLSORT)
1308 * The aclsort() system call is availabe on the latest HPUX General
1309 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1310 * function. Because, we don't want to update to a new
1311 * HPUX GR bundle just for aclsort() call.
1314 struct hpux_acl_types acl_obj_count;
1315 int n_class_obj_perm = 0;
1319 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1324 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1328 /* Count different types of ACLs in the ACLs array */
1330 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1332 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1333 * CLASS_OBJ and OTHER_OBJ
1336 if( (acl_obj_count.n_user_obj != 1) ||
1337 (acl_obj_count.n_group_obj != 1) ||
1338 (acl_obj_count.n_class_obj != 1) ||
1339 (acl_obj_count.n_other_obj != 1)
1341 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1342 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1346 /* If any of the default objects are present, there should be only
1350 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1351 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1352 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1353 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1357 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1360 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1361 * same ACL type, sort by ACL id.
1363 * I am using the trival kind of sorting method here because, performance isn't
1364 * really effected by the ACLs feature. More over there aren't going to be more
1365 * than 17 entries on HPUX.
1368 for(i=0; i<acl_count;i++) {
1369 for (j=i+1; j<acl_count; j++) {
1370 if( aclp[i].a_type > aclp[j].a_type ) {
1371 /* ACL entries out of order, swap them */
1373 hpux_swap_acl_entries((aclp+i), (aclp+j));
1375 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1377 /* ACL entries of same type, sort by id */
1379 if(aclp[i].a_id > aclp[j].a_id) {
1380 hpux_swap_acl_entries((aclp+i), (aclp+j));
1381 } else if (aclp[i].a_id == aclp[j].a_id) {
1382 /* We have a duplicate entry. */
1383 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1384 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1385 aclp[i].a_type, aclp[i].a_id));
1394 /* set the class obj permissions to the computed one. */
1396 int n_class_obj_index = -1;
1398 for(i=0;i<acl_count;i++) {
1399 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1401 if(aclp[i].a_type == CLASS_OBJ)
1402 n_class_obj_index = i;
1404 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1409 return aclsort(acl_count, calclass, aclp);
1414 * sort the ACL and check it for validity
1416 * if it's a minimal ACL with only 4 entries then we
1417 * need to recalculate the mask permissions to make
1418 * sure that they are the same as the GROUP_OBJ
1419 * permissions as required by the UnixWare acl() system call.
1421 * (note: since POSIX allows minimal ACLs which only contain
1422 * 3 entries - ie there is no mask entry - we should, in theory,
1423 * check for this and add a mask entry if necessary - however
1424 * we "know" that the caller of this interface always specifies
1425 * a mask so, in practice "this never happens" (tm) - if it *does*
1426 * happen aclsort() will fail and return an error and someone will
1427 * have to fix it ...)
1430 static int acl_sort(SMB_ACL_T acl_d)
1432 int fixmask = (acl_d->count <= 4);
1434 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1441 int sys_acl_valid(SMB_ACL_T acl_d)
1443 return acl_sort(acl_d);
1446 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1451 struct acl *acl_buf = NULL;
1454 if(hpux_acl_call_presence() == False) {
1455 /* Looks like we don't have the acl() system call on HPUX.
1456 * May be the system doesn't have the latest version of JFS.
1462 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1467 if (acl_sort(acl_d) != 0) {
1471 acl_p = &acl_d->acl[0];
1472 acl_count = acl_d->count;
1475 * if it's a directory there is extra work to do
1476 * since the acl() system call will replace both
1477 * the access ACLs and the default ACLs (if any)
1479 if (stat(name, &s) != 0) {
1482 if (S_ISDIR(s.st_mode)) {
1488 if (type == SMB_ACL_TYPE_ACCESS) {
1490 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1494 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1497 if (tmp_acl == NULL) {
1502 * allocate a temporary buffer for the complete ACL
1504 acl_count = acc_acl->count + def_acl->count;
1505 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1507 if (acl_buf == NULL) {
1508 sys_acl_free_acl(tmp_acl);
1514 * copy the access control and default entries into the buffer
1516 memcpy(&acl_buf[0], &acc_acl->acl[0],
1517 acc_acl->count * sizeof(acl_buf[0]));
1519 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1520 def_acl->count * sizeof(acl_buf[0]));
1523 * set the ACL_DEFAULT flag on the default entries
1525 for (i = acc_acl->count; i < acl_count; i++) {
1526 acl_buf[i].a_type |= ACL_DEFAULT;
1529 sys_acl_free_acl(tmp_acl);
1531 } else if (type != SMB_ACL_TYPE_ACCESS) {
1536 ret = acl(name, ACL_SET, acl_count, acl_p);
1546 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1549 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1552 files_struct *fsp = file_find_fd(fd);
1559 if (acl_sort(acl_d) != 0) {
1564 * We know we're in the same conn context. So we
1565 * can use the relative path.
1568 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1572 int sys_acl_delete_def_file(const char *path)
1578 * fetching the access ACL and rewriting it has
1579 * the effect of deleting the default ACL
1581 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1585 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1587 sys_acl_free_acl(acl_d);
1592 int sys_acl_free_acl(SMB_ACL_T acl_d)
1598 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1603 #elif defined(HAVE_IRIX_ACLS)
1605 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1607 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1612 if (entry_p == NULL) {
1617 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1621 if (acl_d->next < 0) {
1626 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1630 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1635 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1637 *type_p = entry_d->ae_tag;
1642 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1644 if (entry_d->ae_tag != SMB_ACL_USER
1645 && entry_d->ae_tag != SMB_ACL_GROUP) {
1650 return &entry_d->ae_id;
1653 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1657 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1661 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1671 SMB_ACL_T sys_acl_get_fd(int fd)
1675 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1679 if ((a->aclp = acl_get_fd(fd)) == NULL) {
1689 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1691 *bits = entry_d->ae_perm;
1696 SMB_ACL_T sys_acl_init(int count)
1705 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
1711 a->freeaclp = False;
1712 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
1713 a->aclp->acl_cnt = 0;
1719 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1722 SMB_ACL_ENTRY_T entry_d;
1724 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1729 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
1734 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
1735 entry_d->ae_tag = 0;
1737 entry_d->ae_perm = 0;
1743 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1747 case SMB_ACL_USER_OBJ:
1749 case SMB_ACL_GROUP_OBJ:
1752 entry_d->ae_tag = tag_type;
1762 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1764 if (entry_d->ae_tag != SMB_ACL_GROUP
1765 && entry_d->ae_tag != SMB_ACL_USER) {
1770 entry_d->ae_id = *((id_t *)qual_p);
1775 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1777 entry_d->ae_perm = bits;
1782 int sys_acl_valid(SMB_ACL_T acl_d)
1784 return acl_valid(acl_d->aclp);
1787 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1789 return acl_set_file(name, type, acl_d->aclp);
1792 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1794 return acl_set_fd(fd, acl_d->aclp);
1797 int sys_acl_delete_def_file(const char *name)
1799 return acl_delete_def_file(name);
1802 int sys_acl_free_acl(SMB_ACL_T acl_d)
1804 if (acl_d->freeaclp) {
1805 acl_free(acl_d->aclp);
1811 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1816 #elif defined(HAVE_AIX_ACLS)
1818 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1820 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1822 struct acl_entry_link *link;
1823 struct new_acl_entry *entry;
1826 DEBUG(10,("This is the count: %d\n",theacl->count));
1828 /* Check if count was previously set to -1. *
1829 * If it was, that means we reached the end *
1830 * of the acl last time. */
1831 if(theacl->count == -1)
1835 /* To get to the next acl, traverse linked list until index *
1836 * of acl matches the count we are keeping. This count is *
1837 * incremented each time we return an acl entry. */
1839 for(keep_going = 0; keep_going < theacl->count; keep_going++)
1842 entry = *entry_p = link->entryp;
1844 DEBUG(10,("*entry_p is %d\n",entry_p));
1845 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1847 /* Increment count */
1849 if(link->nextp == NULL)
1855 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1857 /* Initialize tag type */
1860 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1862 /* Depending on what type of entry we have, *
1863 * return tag type. */
1864 switch(entry_d->ace_id->id_type) {
1866 *tag_type_p = SMB_ACL_USER;
1869 *tag_type_p = SMB_ACL_GROUP;
1872 case SMB_ACL_USER_OBJ:
1873 case SMB_ACL_GROUP_OBJ:
1875 *tag_type_p = entry_d->ace_id->id_type;
1885 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1887 SMB_ACL_PERMSET_T permset;
1888 DEBUG(10,("Starting AIX sys_acl_get_access_bits\n"));
1889 permset = &entry_d->ace_access;
1890 DEBUG(10,("*permset is %d\n",*permset));
1891 *bits = (*permset & S_IRUSR ? 4 : 0)
1892 | (*permset & S_IWUSR ? 2 : 0)
1893 | (*permset & S_IXUSR ? 1 : 0);
1894 DEBUG(10,("Ending AIX sys_acl_get_access_bits\n"));
1898 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1900 return(entry_d->ace_id->id_data);
1903 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1905 struct acl *file_acl = (struct acl *)NULL;
1906 struct acl_entry *acl_entry;
1907 struct new_acl_entry *new_acl_entry;
1909 struct acl_entry_link *acl_entry_link;
1910 struct acl_entry_link *acl_entry_link_head;
1915 /* AIX has no DEFAULT */
1916 if ( type == SMB_ACL_TYPE_DEFAULT ) {
1921 /* Get the acl using statacl */
1923 DEBUG(10,("Entering sys_acl_get_file\n"));
1924 DEBUG(10,("path_p is %s\n",path_p));
1926 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
1928 if(file_acl == NULL) {
1930 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1934 memset(file_acl,0,BUFSIZ);
1936 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1938 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1939 SAFE_FREE(file_acl);
1943 DEBUG(10,("Got facl and returned it\n"));
1945 /* Point to the first acl entry in the acl */
1946 acl_entry = file_acl->acl_ext;
1948 /* Begin setting up the head of the linked list *
1949 * that will be used for the storing the acl *
1950 * in a way that is useful for the posix_acls.c *
1953 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1954 if(acl_entry_link_head == NULL)
1957 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1958 if(acl_entry_link->entryp == NULL) {
1959 SAFE_FREE(file_acl);
1961 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1965 DEBUG(10,("acl_entry is %d\n",acl_entry));
1966 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1968 /* Check if the extended acl bit is on. *
1969 * If it isn't, do not show the *
1970 * contents of the acl since AIX intends *
1971 * the extended info to remain unused */
1973 if(file_acl->acl_mode & S_IXACL){
1974 /* while we are not pointing to the very end */
1975 while(acl_entry < acl_last(file_acl)) {
1976 /* before we malloc anything, make sure this is */
1977 /* a valid acl entry and one that we want to map */
1978 idp = id_nxt(acl_entry->ace_id);
1979 if((acl_entry->ace_type == ACC_SPECIFY ||
1980 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1981 acl_entry = acl_nxt(acl_entry);
1985 idp = acl_entry->ace_id;
1987 /* Check if this is the first entry in the linked list. *
1988 * The first entry needs to keep prevp pointing to NULL *
1989 * and already has entryp allocated. */
1991 if(acl_entry_link_head->count != 0) {
1992 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
1994 if(acl_entry_link->nextp == NULL) {
1995 SAFE_FREE(file_acl);
1997 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2001 acl_entry_link->nextp->prevp = acl_entry_link;
2002 acl_entry_link = acl_entry_link->nextp;
2003 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2004 if(acl_entry_link->entryp == NULL) {
2005 SAFE_FREE(file_acl);
2007 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2010 acl_entry_link->nextp = NULL;
2013 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2015 /* Don't really need this since all types are going *
2016 * to be specified but, it's better than leaving it 0 */
2018 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2020 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2022 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2024 /* The access in the acl entries must be left shifted by *
2025 * three bites, because they will ultimately be compared *
2026 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2028 switch(acl_entry->ace_type){
2031 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2032 acl_entry_link->entryp->ace_access <<= 6;
2033 acl_entry_link_head->count++;
2036 /* Since there is no way to return a DENY acl entry *
2037 * change to PERMIT and then shift. */
2038 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2039 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2040 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2041 acl_entry_link->entryp->ace_access <<= 6;
2042 acl_entry_link_head->count++;
2048 DEBUG(10,("acl_entry = %d\n",acl_entry));
2049 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2051 acl_entry = acl_nxt(acl_entry);
2053 } /* end of if enabled */
2055 /* Since owner, group, other acl entries are not *
2056 * part of the acl entries in an acl, they must *
2057 * be dummied up to become part of the list. */
2059 for( i = 1; i < 4; i++) {
2060 DEBUG(10,("i is %d\n",i));
2061 if(acl_entry_link_head->count != 0) {
2062 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2063 if(acl_entry_link->nextp == NULL) {
2064 SAFE_FREE(file_acl);
2066 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2070 acl_entry_link->nextp->prevp = acl_entry_link;
2071 acl_entry_link = acl_entry_link->nextp;
2072 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2073 if(acl_entry_link->entryp == NULL) {
2074 SAFE_FREE(file_acl);
2076 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2081 acl_entry_link->nextp = NULL;
2083 new_acl_entry = acl_entry_link->entryp;
2084 idp = new_acl_entry->ace_id;
2086 new_acl_entry->ace_len = sizeof(struct acl_entry);
2087 new_acl_entry->ace_type = ACC_PERMIT;
2088 idp->id_len = sizeof(struct ace_id);
2089 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2090 memset(idp->id_data,0,sizeof(uid_t));
2094 new_acl_entry->ace_access = file_acl->g_access << 6;
2095 idp->id_type = SMB_ACL_GROUP_OBJ;
2099 new_acl_entry->ace_access = file_acl->o_access << 6;
2100 idp->id_type = SMB_ACL_OTHER;
2104 new_acl_entry->ace_access = file_acl->u_access << 6;
2105 idp->id_type = SMB_ACL_USER_OBJ;
2113 acl_entry_link_head->count++;
2114 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2117 acl_entry_link_head->count = 0;
2118 SAFE_FREE(file_acl);
2120 return(acl_entry_link_head);
2124 SMB_ACL_T sys_acl_get_fd(int fd)
2126 struct acl *file_acl = (struct acl *)NULL;
2127 struct acl_entry *acl_entry;
2128 struct new_acl_entry *new_acl_entry;
2130 struct acl_entry_link *acl_entry_link;
2131 struct acl_entry_link *acl_entry_link_head;
2136 /* Get the acl using fstatacl */
2138 DEBUG(10,("Entering sys_acl_get_fd\n"));
2139 DEBUG(10,("fd is %d\n",fd));
2140 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2142 if(file_acl == NULL) {
2144 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2148 memset(file_acl,0,BUFSIZ);
2150 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2152 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2153 SAFE_FREE(file_acl);
2157 DEBUG(10,("Got facl and returned it\n"));
2159 /* Point to the first acl entry in the acl */
2161 acl_entry = file_acl->acl_ext;
2162 /* Begin setting up the head of the linked list *
2163 * that will be used for the storing the acl *
2164 * in a way that is useful for the posix_acls.c *
2167 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2168 if(acl_entry_link_head == NULL){
2169 SAFE_FREE(file_acl);
2173 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2175 if(acl_entry_link->entryp == NULL) {
2177 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2178 SAFE_FREE(file_acl);
2182 DEBUG(10,("acl_entry is %d\n",acl_entry));
2183 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2185 /* Check if the extended acl bit is on. *
2186 * If it isn't, do not show the *
2187 * contents of the acl since AIX intends *
2188 * the extended info to remain unused */
2190 if(file_acl->acl_mode & S_IXACL){
2191 /* while we are not pointing to the very end */
2192 while(acl_entry < acl_last(file_acl)) {
2193 /* before we malloc anything, make sure this is */
2194 /* a valid acl entry and one that we want to map */
2196 idp = id_nxt(acl_entry->ace_id);
2197 if((acl_entry->ace_type == ACC_SPECIFY ||
2198 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2199 acl_entry = acl_nxt(acl_entry);
2203 idp = acl_entry->ace_id;
2205 /* Check if this is the first entry in the linked list. *
2206 * The first entry needs to keep prevp pointing to NULL *
2207 * and already has entryp allocated. */
2209 if(acl_entry_link_head->count != 0) {
2210 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2211 if(acl_entry_link->nextp == NULL) {
2213 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2214 SAFE_FREE(file_acl);
2217 acl_entry_link->nextp->prevp = acl_entry_link;
2218 acl_entry_link = acl_entry_link->nextp;
2219 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2220 if(acl_entry_link->entryp == NULL) {
2222 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2223 SAFE_FREE(file_acl);
2227 acl_entry_link->nextp = NULL;
2230 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2232 /* Don't really need this since all types are going *
2233 * to be specified but, it's better than leaving it 0 */
2235 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2236 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2238 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2240 /* The access in the acl entries must be left shifted by *
2241 * three bites, because they will ultimately be compared *
2242 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2244 switch(acl_entry->ace_type){
2247 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2248 acl_entry_link->entryp->ace_access <<= 6;
2249 acl_entry_link_head->count++;
2252 /* Since there is no way to return a DENY acl entry *
2253 * change to PERMIT and then shift. */
2254 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2255 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2256 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2257 acl_entry_link->entryp->ace_access <<= 6;
2258 acl_entry_link_head->count++;
2264 DEBUG(10,("acl_entry = %d\n",acl_entry));
2265 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2267 acl_entry = acl_nxt(acl_entry);
2269 } /* end of if enabled */
2271 /* Since owner, group, other acl entries are not *
2272 * part of the acl entries in an acl, they must *
2273 * be dummied up to become part of the list. */
2275 for( i = 1; i < 4; i++) {
2276 DEBUG(10,("i is %d\n",i));
2277 if(acl_entry_link_head->count != 0){
2278 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2279 if(acl_entry_link->nextp == NULL) {
2281 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2282 SAFE_FREE(file_acl);
2286 acl_entry_link->nextp->prevp = acl_entry_link;
2287 acl_entry_link = acl_entry_link->nextp;
2288 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2290 if(acl_entry_link->entryp == NULL) {
2291 SAFE_FREE(file_acl);
2293 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2298 acl_entry_link->nextp = NULL;
2300 new_acl_entry = acl_entry_link->entryp;
2301 idp = new_acl_entry->ace_id;
2303 new_acl_entry->ace_len = sizeof(struct acl_entry);
2304 new_acl_entry->ace_type = ACC_PERMIT;
2305 idp->id_len = sizeof(struct ace_id);
2306 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2307 memset(idp->id_data,0,sizeof(uid_t));
2311 new_acl_entry->ace_access = file_acl->g_access << 6;
2312 idp->id_type = SMB_ACL_GROUP_OBJ;
2316 new_acl_entry->ace_access = file_acl->o_access << 6;
2317 idp->id_type = SMB_ACL_OTHER;
2321 new_acl_entry->ace_access = file_acl->u_access << 6;
2322 idp->id_type = SMB_ACL_USER_OBJ;
2329 acl_entry_link_head->count++;
2330 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2333 acl_entry_link_head->count = 0;
2334 SAFE_FREE(file_acl);
2336 return(acl_entry_link_head);
2340 SMB_ACL_T sys_acl_init( int count)
2342 struct acl_entry_link *theacl = NULL;
2344 DEBUG(10,("Entering sys_acl_init\n"));
2346 theacl = SMB_MALLOC_P(struct acl_entry_link);
2347 if(theacl == NULL) {
2349 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2354 theacl->nextp = NULL;
2355 theacl->prevp = NULL;
2356 theacl->entryp = NULL;
2357 DEBUG(10,("Exiting sys_acl_init\n"));
2361 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2363 struct acl_entry_link *theacl;
2364 struct acl_entry_link *acl_entryp;
2365 struct acl_entry_link *temp_entry;
2368 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2370 theacl = acl_entryp = *pacl;
2372 /* Get to the end of the acl before adding entry */
2374 for(counting=0; counting < theacl->count; counting++){
2375 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2376 temp_entry = acl_entryp;
2377 acl_entryp = acl_entryp->nextp;
2380 if(theacl->count != 0){
2381 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2382 if(acl_entryp == NULL) {
2384 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2388 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2389 acl_entryp->prevp = temp_entry;
2390 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2393 *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2394 if(*pentry == NULL) {
2396 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2400 memset(*pentry,0,sizeof(struct new_acl_entry));
2401 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2402 acl_entryp->entryp->ace_type = ACC_PERMIT;
2403 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2404 acl_entryp->nextp = NULL;
2406 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2410 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2412 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2413 entry->ace_id->id_type = tagtype;
2414 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2415 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2418 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2420 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2421 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2422 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2426 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
2428 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2429 entry->ace_access = bits;
2430 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2431 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2435 int sys_acl_valid( SMB_ACL_T theacl )
2440 struct acl_entry_link *acl_entry;
2442 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2443 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2444 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2445 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2448 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2450 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2456 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2458 struct acl_entry_link *acl_entry_link = NULL;
2459 struct acl *file_acl = NULL;
2460 struct acl *file_acl_temp = NULL;
2461 struct acl_entry *acl_entry = NULL;
2462 struct ace_id *ace_id = NULL;
2469 DEBUG(10,("Entering sys_acl_set_file\n"));
2470 DEBUG(10,("File name is %s\n",name));
2472 /* AIX has no default ACL */
2473 if(acltype == SMB_ACL_TYPE_DEFAULT)
2476 acl_length = BUFSIZ;
2477 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2479 if(file_acl == NULL) {
2481 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2485 memset(file_acl,0,BUFSIZ);
2487 file_acl->acl_len = ACL_SIZ;
2488 file_acl->acl_mode = S_IXACL;
2490 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2491 acl_entry_link->entryp->ace_access >>= 6;
2492 id_type = acl_entry_link->entryp->ace_id->id_type;
2495 case SMB_ACL_USER_OBJ:
2496 file_acl->u_access = acl_entry_link->entryp->ace_access;
2498 case SMB_ACL_GROUP_OBJ:
2499 file_acl->g_access = acl_entry_link->entryp->ace_access;
2502 file_acl->o_access = acl_entry_link->entryp->ace_access;
2508 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2509 acl_length += sizeof(struct acl_entry);
2510 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2511 if(file_acl_temp == NULL) {
2512 SAFE_FREE(file_acl);
2514 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2518 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2519 SAFE_FREE(file_acl);
2520 file_acl = file_acl_temp;
2523 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2524 file_acl->acl_len += sizeof(struct acl_entry);
2525 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2526 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2528 /* In order to use this, we'll need to wait until we can get denies */
2529 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2530 acl_entry->ace_type = ACC_SPECIFY; */
2532 acl_entry->ace_type = ACC_SPECIFY;
2534 ace_id = acl_entry->ace_id;
2536 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2537 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2538 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2539 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2540 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2543 rc = chacl(name,file_acl,file_acl->acl_len);
2544 DEBUG(10,("errno is %d\n",errno));
2545 DEBUG(10,("return code is %d\n",rc));
2546 SAFE_FREE(file_acl);
2547 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2551 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2553 struct acl_entry_link *acl_entry_link = NULL;
2554 struct acl *file_acl = NULL;
2555 struct acl *file_acl_temp = NULL;
2556 struct acl_entry *acl_entry = NULL;
2557 struct ace_id *ace_id = NULL;
2563 DEBUG(10,("Entering sys_acl_set_fd\n"));
2564 acl_length = BUFSIZ;
2565 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2567 if(file_acl == NULL) {
2569 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2573 memset(file_acl,0,BUFSIZ);
2575 file_acl->acl_len = ACL_SIZ;
2576 file_acl->acl_mode = S_IXACL;
2578 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2579 acl_entry_link->entryp->ace_access >>= 6;
2580 id_type = acl_entry_link->entryp->ace_id->id_type;
2581 DEBUG(10,("The id_type is %d\n",id_type));
2584 case SMB_ACL_USER_OBJ:
2585 file_acl->u_access = acl_entry_link->entryp->ace_access;
2587 case SMB_ACL_GROUP_OBJ:
2588 file_acl->g_access = acl_entry_link->entryp->ace_access;
2591 file_acl->o_access = acl_entry_link->entryp->ace_access;
2597 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2598 acl_length += sizeof(struct acl_entry);
2599 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2600 if(file_acl_temp == NULL) {
2601 SAFE_FREE(file_acl);
2603 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2607 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2608 SAFE_FREE(file_acl);
2609 file_acl = file_acl_temp;
2612 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2613 file_acl->acl_len += sizeof(struct acl_entry);
2614 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2615 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2617 /* In order to use this, we'll need to wait until we can get denies */
2618 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2619 acl_entry->ace_type = ACC_SPECIFY; */
2621 acl_entry->ace_type = ACC_SPECIFY;
2623 ace_id = acl_entry->ace_id;
2625 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2626 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2627 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2628 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2629 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2632 rc = fchacl(fd,file_acl,file_acl->acl_len);
2633 DEBUG(10,("errno is %d\n",errno));
2634 DEBUG(10,("return code is %d\n",rc));
2635 SAFE_FREE(file_acl);
2636 DEBUG(10,("Exiting sys_acl_set_fd\n"));
2640 int sys_acl_delete_def_file(const char *name)
2642 /* AIX has no default ACL */
2646 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2648 struct acl_entry_link *acl_entry_link;
2650 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2651 SAFE_FREE(acl_entry_link->prevp->entryp);
2652 SAFE_FREE(acl_entry_link->prevp);
2655 SAFE_FREE(acl_entry_link->prevp->entryp);
2656 SAFE_FREE(acl_entry_link->prevp);
2657 SAFE_FREE(acl_entry_link->entryp);
2658 SAFE_FREE(acl_entry_link);
2663 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2668 #else /* No ACLs. */
2670 #error No ACL functions defined for this platform!
2674 /************************************************************************
2675 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
2677 ************************************************************************/
2679 int no_acl_syscall_error(int err)
2682 if (err == ENOSYS) {
2686 #if defined(ENOTSUP)
2687 if (err == ENOTSUP) {
2694 #endif /* SUPPORT_ACLS */