2 Unix SMB/CIFS implementation.
3 Samba system utilities for ACL support.
4 Copyright (C) Jeremy Allison 2000.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "sysacls.h" /****** ADDED ******/
26 /****** EXTRAS -- THESE ITEMS ARE NOT FROM THE SAMBA SOURCE ******/
32 void SAFE_FREE(void *mem)
38 char *uidtoname(uid_t uid)
40 static char idbuf[12];
43 if ((pw = getpwuid(uid)) == NULL) {
44 slprintf(idbuf, sizeof(idbuf)-1, "%ld", (long)uid);
49 /****** EXTRAS -- END ******/
52 This file wraps all differing system ACL interfaces into a consistent
53 one based on the POSIX interface. It also returns the correct errors
54 for older UNIX systems that don't support ACLs.
56 The interfaces that each ACL implementation must support are as follows :
58 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
59 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
60 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p
61 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
62 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
63 SMB_ACL_T sys_acl_get_fd(int fd)
64 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset);
65 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
66 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
67 SMB_ACL_T sys_acl_init( int count)
68 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
69 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
70 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
71 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
72 int sys_acl_valid( SMB_ACL_T theacl )
73 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
74 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
75 int sys_acl_delete_def_file(const char *path)
77 This next one is not POSIX complient - but we *have* to have it !
78 More POSIX braindamage.
80 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
82 The generic POSIX free is the following call. We split this into
83 several different free functions as we may need to add tag info
84 to structures when emulating the POSIX interface.
86 int sys_acl_free( void *obj_p)
88 The calls we actually use are :
90 int sys_acl_free_text(char *text) - free acl_to_text
91 int sys_acl_free_acl(SMB_ACL_T posix_acl)
92 int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
96 #if defined(HAVE_POSIX_ACLS)
98 /* Identity mapping - easy. */
100 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
102 return acl_get_entry( the_acl, entry_id, entry_p);
105 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
107 return acl_get_tag_type( entry_d, tag_type_p);
110 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
112 return acl_get_permset( entry_d, permset_p);
115 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
117 return acl_get_qualifier( entry_d);
120 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
122 return acl_get_file( path_p, type);
125 SMB_ACL_T sys_acl_get_fd(int fd)
127 return acl_get_fd(fd);
130 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
132 return acl_clear_perms(permset);
135 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
137 return acl_add_perm(permset, perm);
140 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
142 #if defined(HAVE_ACL_GET_PERM_NP)
144 * Required for TrustedBSD-based ACL implementations where
145 * non-POSIX.1e functions are denoted by a _np (non-portable)
148 return acl_get_perm_np(permset, perm);
150 return acl_get_perm(permset, perm);
154 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
156 return acl_to_text( the_acl, plen);
159 SMB_ACL_T sys_acl_init( int count)
161 return acl_init(count);
164 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
166 return acl_create_entry(pacl, pentry);
169 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
171 return acl_set_tag_type(entry, tagtype);
174 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
176 return acl_set_qualifier(entry, qual);
179 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
181 return acl_set_permset(entry, permset);
184 int sys_acl_valid( SMB_ACL_T theacl )
186 return acl_valid(theacl);
189 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
191 return acl_set_file(name, acltype, theacl);
194 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
196 return acl_set_fd(fd, theacl);
199 int sys_acl_delete_def_file(const char *name)
201 return acl_delete_def_file(name);
204 int sys_acl_free_text(char *text)
206 return acl_free(text);
209 int sys_acl_free_acl(SMB_ACL_T the_acl)
211 return acl_free(the_acl);
214 int sys_acl_free_qualifier(void *qual, UNUSED(SMB_ACL_TAG_T tagtype))
216 return acl_free(qual);
219 #elif defined(HAVE_TRU64_ACLS)
221 * The interface to DEC/Compaq Tru64 UNIX ACLs
222 * is based on Draft 13 of the POSIX spec which is
223 * slightly different from the Draft 16 interface.
225 * Also, some of the permset manipulation functions
226 * such as acl_clear_perm() and acl_add_perm() appear
227 * to be broken on Tru64 so we have to manipulate
228 * the permission bits in the permset directly.
230 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
232 SMB_ACL_ENTRY_T entry;
234 if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
239 if ((entry = acl_get_entry(the_acl)) != NULL) {
244 return errno ? -1 : 0;
247 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
249 return acl_get_tag_type( entry_d, tag_type_p);
252 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
254 return acl_get_permset( entry_d, permset_p);
257 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
259 return acl_get_qualifier( entry_d);
262 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
264 return acl_get_file((char *)path_p, type);
267 SMB_ACL_T sys_acl_get_fd(int fd)
269 return acl_get_fd(fd, ACL_TYPE_ACCESS);
272 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
274 *permset = 0; /* acl_clear_perm() is broken on Tru64 */
279 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
281 if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) {
286 *permset |= perm; /* acl_add_perm() is broken on Tru64 */
291 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
293 return *permset & perm; /* Tru64 doesn't have acl_get_perm() */
296 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
298 return acl_to_text( the_acl, plen);
301 SMB_ACL_T sys_acl_init( int count)
303 return acl_init(count);
306 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
308 SMB_ACL_ENTRY_T entry;
310 if ((entry = acl_create_entry(pacl)) == NULL) {
318 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
320 return acl_set_tag_type(entry, tagtype);
323 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
325 return acl_set_qualifier(entry, qual);
328 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
330 return acl_set_permset(entry, permset);
333 int sys_acl_valid( SMB_ACL_T theacl )
337 return acl_valid(theacl, &entry);
340 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
342 return acl_set_file((char *)name, acltype, theacl);
345 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
347 return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
350 int sys_acl_delete_def_file(const char *name)
352 return acl_delete_def_file((char *)name);
355 int sys_acl_free_text(char *text)
358 * (void) cast and explicit return 0 are for DEC UNIX
359 * which just #defines acl_free_text() to be free()
361 (void) acl_free_text(text);
365 int sys_acl_free_acl(SMB_ACL_T the_acl)
367 return acl_free(the_acl);
370 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
372 return acl_free_qualifier(qual, tagtype);
375 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
378 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
379 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
383 * Note that while this code implements sufficient functionality
384 * to support the sys_acl_* interfaces it does not provide all
385 * of the semantics of the POSIX ACL interfaces.
387 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
388 * from a call to sys_acl_get_entry() should not be assumed to be
389 * valid after calling any of the following functions, which may
390 * reorder the entries in the ACL.
398 * The only difference between Solaris and UnixWare / OpenUNIX is
399 * that the #defines for the ACL operations have different names
401 #if defined(HAVE_UNIXWARE_ACLS)
403 #define SETACL ACL_SET
404 #define GETACL ACL_GET
405 #define GETACLCNT ACL_CNT
410 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
412 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
417 if (entry_p == NULL) {
422 if (entry_id == SMB_ACL_FIRST_ENTRY) {
426 if (acl_d->next < 0) {
431 if (acl_d->next >= acl_d->count) {
435 *entry_p = &acl_d->acl[acl_d->next++];
440 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
442 *type_p = entry_d->a_type;
447 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
449 *permset_p = &entry_d->a_perm;
454 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
456 if (entry_d->a_type != SMB_ACL_USER
457 && entry_d->a_type != SMB_ACL_GROUP) {
462 return &entry_d->a_id;
466 * There is no way of knowing what size the ACL returned by
467 * GETACL will be unless you first call GETACLCNT which means
468 * making an additional system call.
470 * In the hope of avoiding the cost of the additional system
471 * call in most cases, we initially allocate enough space for
472 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
473 * be too small then we use GETACLCNT to find out the actual
474 * size, reallocate the ACL buffer, and then call GETACL again.
477 #define INITIAL_ACL_SIZE 16
479 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
482 int count; /* # of ACL entries allocated */
483 int naccess; /* # of access ACL entries */
484 int ndefault; /* # of default ACL entries */
486 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
491 count = INITIAL_ACL_SIZE;
492 if ((acl_d = sys_acl_init(count)) == NULL) {
497 * If there isn't enough space for the ACL entries we use
498 * GETACLCNT to determine the actual number of ACL entries
499 * reallocate and try again. This is in a loop because it
500 * is possible that someone else could modify the ACL and
501 * increase the number of entries between the call to
502 * GETACLCNT and the call to GETACL.
504 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
505 && errno == ENOSPC) {
507 sys_acl_free_acl(acl_d);
509 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
513 if ((acl_d = sys_acl_init(count)) == NULL) {
519 sys_acl_free_acl(acl_d);
524 * calculate the number of access and default ACL entries
526 * Note: we assume that the acl() system call returned a
527 * well formed ACL which is sorted so that all of the
528 * access ACL entries preceed any default ACL entries
530 for (naccess = 0; naccess < count; naccess++) {
531 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
534 ndefault = count - naccess;
537 * if the caller wants the default ACL we have to copy
538 * the entries down to the start of the acl[] buffer
539 * and mask out the ACL_DEFAULT flag from the type field
541 if (type == SMB_ACL_TYPE_DEFAULT) {
544 for (i = 0, j = naccess; i < ndefault; i++, j++) {
545 acl_d->acl[i] = acl_d->acl[j];
546 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
549 acl_d->count = ndefault;
551 acl_d->count = naccess;
557 SMB_ACL_T sys_acl_get_fd(int fd)
560 int count; /* # of ACL entries allocated */
561 int naccess; /* # of access ACL entries */
563 count = INITIAL_ACL_SIZE;
564 if ((acl_d = sys_acl_init(count)) == NULL) {
568 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
569 && errno == ENOSPC) {
571 sys_acl_free_acl(acl_d);
573 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
577 if ((acl_d = sys_acl_init(count)) == NULL) {
583 sys_acl_free_acl(acl_d);
588 * calculate the number of access ACL entries
590 for (naccess = 0; naccess < count; naccess++) {
591 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
595 acl_d->count = naccess;
600 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
607 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
609 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
610 && perm != SMB_ACL_EXECUTE) {
615 if (permset_d == NULL) {
625 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
627 return *permset_d & perm;
630 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
637 * use an initial estimate of 20 bytes per ACL entry
638 * when allocating memory for the text representation
642 maxlen = 20 * acl_d->count;
643 if ((text = SMB_MALLOC(maxlen)) == NULL) {
648 for (i = 0; i < acl_d->count; i++) {
649 struct acl *ap = &acl_d->acl[i];
658 switch (ap->a_type) {
660 * for debugging purposes it's probably more
661 * useful to dump unknown tag types rather
662 * than just returning an error
665 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
668 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
674 id = uidtoname(ap->a_id);
675 case SMB_ACL_USER_OBJ:
680 if ((gr = getgrgid(ap->a_id)) == NULL) {
681 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
687 case SMB_ACL_GROUP_OBJ:
701 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
702 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
703 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
706 /* <tag> : <qualifier> : rwx \n \0 */
707 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
710 * If this entry would overflow the buffer
711 * allocate enough additional memory for this
712 * entry and an estimate of another 20 bytes
713 * for each entry still to be processed
715 if ((len + nbytes) > maxlen) {
716 char *oldtext = text;
718 maxlen += nbytes + 20 * (acl_d->count - i);
720 if ((text = SMB_REALLOC(oldtext, maxlen)) == NULL) {
727 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
737 SMB_ACL_T sys_acl_init(int count)
747 * note that since the definition of the structure pointed
748 * to by the SMB_ACL_T includes the first element of the
749 * acl[] array, this actually allocates an ACL with room
750 * for (count+1) entries
752 if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
765 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
768 SMB_ACL_ENTRY_T entry_d;
770 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
775 if (acl_d->count >= acl_d->size) {
780 entry_d = &acl_d->acl[acl_d->count++];
789 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
793 case SMB_ACL_USER_OBJ:
795 case SMB_ACL_GROUP_OBJ:
798 entry_d->a_type = tag_type;
808 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
810 if (entry_d->a_type != SMB_ACL_GROUP
811 && entry_d->a_type != SMB_ACL_USER) {
816 entry_d->a_id = *((id_t *)qual_p);
821 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
823 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
827 entry_d->a_perm = *permset_d;
833 * sort the ACL and check it for validity
835 * if it's a minimal ACL with only 4 entries then we
836 * need to recalculate the mask permissions to make
837 * sure that they are the same as the GROUP_OBJ
838 * permissions as required by the UnixWare acl() system call.
840 * (note: since POSIX allows minimal ACLs which only contain
841 * 3 entries - ie there is no mask entry - we should, in theory,
842 * check for this and add a mask entry if necessary - however
843 * we "know" that the caller of this interface always specifies
844 * a mask so, in practice "this never happens" (tm) - if it *does*
845 * happen aclsort() will fail and return an error and someone will
846 * have to fix it ...)
849 static int acl_sort(SMB_ACL_T acl_d)
851 int fixmask = (acl_d->count <= 4);
853 if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
860 int sys_acl_valid(SMB_ACL_T acl_d)
862 return acl_sort(acl_d);
865 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
870 struct acl *acl_buf = NULL;
873 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
878 if (acl_sort(acl_d) != 0) {
882 acl_p = &acl_d->acl[0];
883 acl_count = acl_d->count;
886 * if it's a directory there is extra work to do
887 * since the acl() system call will replace both
888 * the access ACLs and the default ACLs (if any)
890 if (stat(name, &s) != 0) {
893 if (S_ISDIR(s.st_mode)) {
899 if (type == SMB_ACL_TYPE_ACCESS) {
901 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
905 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
908 if (tmp_acl == NULL) {
913 * allocate a temporary buffer for the complete ACL
915 acl_count = acc_acl->count + def_acl->count;
916 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
918 if (acl_buf == NULL) {
919 sys_acl_free_acl(tmp_acl);
925 * copy the access control and default entries into the buffer
927 memcpy(&acl_buf[0], &acc_acl->acl[0],
928 acc_acl->count * sizeof(acl_buf[0]));
930 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
931 def_acl->count * sizeof(acl_buf[0]));
934 * set the ACL_DEFAULT flag on the default entries
936 for (i = acc_acl->count; i < acl_count; i++) {
937 acl_buf[i].a_type |= ACL_DEFAULT;
940 sys_acl_free_acl(tmp_acl);
942 } else if (type != SMB_ACL_TYPE_ACCESS) {
947 ret = acl(name, SETACL, acl_count, acl_p);
954 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
956 if (acl_sort(acl_d) != 0) {
960 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
963 int sys_acl_delete_def_file(const char *path)
969 * fetching the access ACL and rewriting it has
970 * the effect of deleting the default ACL
972 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
976 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
978 sys_acl_free_acl(acl_d);
983 int sys_acl_free_text(char *text)
989 int sys_acl_free_acl(SMB_ACL_T acl_d)
995 int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
1000 #elif defined(HAVE_HPUX_ACLS)
1004 * Based on the Solaris/SCO code - with modifications.
1008 * Note that while this code implements sufficient functionality
1009 * to support the sys_acl_* interfaces it does not provide all
1010 * of the semantics of the POSIX ACL interfaces.
1012 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
1013 * from a call to sys_acl_get_entry() should not be assumed to be
1014 * valid after calling any of the following functions, which may
1015 * reorder the entries in the ACL.
1018 * sys_acl_set_file()
1022 /* This checks if the POSIX ACL system call is defined */
1023 /* which basically corresponds to whether JFS 3.3 or */
1024 /* higher is installed. If acl() was called when it */
1025 /* isn't defined, it causes the process to core dump */
1026 /* so it is important to check this and avoid acl() */
1027 /* calls if it isn't there. */
1029 static BOOL hpux_acl_call_presence(void)
1032 shl_t handle = NULL;
1035 static BOOL already_checked=0;
1041 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
1044 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
1045 ret_val, errno, strerror(errno)));
1046 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
1050 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
1052 already_checked = True;
1056 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1058 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1063 if (entry_p == NULL) {
1068 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1072 if (acl_d->next < 0) {
1077 if (acl_d->next >= acl_d->count) {
1081 *entry_p = &acl_d->acl[acl_d->next++];
1086 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1088 *type_p = entry_d->a_type;
1093 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1095 *permset_p = &entry_d->a_perm;
1100 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1102 if (entry_d->a_type != SMB_ACL_USER
1103 && entry_d->a_type != SMB_ACL_GROUP) {
1108 return &entry_d->a_id;
1112 * There is no way of knowing what size the ACL returned by
1113 * ACL_GET will be unless you first call ACL_CNT which means
1114 * making an additional system call.
1116 * In the hope of avoiding the cost of the additional system
1117 * call in most cases, we initially allocate enough space for
1118 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
1119 * be too small then we use ACL_CNT to find out the actual
1120 * size, reallocate the ACL buffer, and then call ACL_GET again.
1123 #define INITIAL_ACL_SIZE 16
1125 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1128 int count; /* # of ACL entries allocated */
1129 int naccess; /* # of access ACL entries */
1130 int ndefault; /* # of default ACL entries */
1132 if(hpux_acl_call_presence() == False) {
1133 /* Looks like we don't have the acl() system call on HPUX.
1134 * May be the system doesn't have the latest version of JFS.
1139 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1144 count = INITIAL_ACL_SIZE;
1145 if ((acl_d = sys_acl_init(count)) == NULL) {
1150 * If there isn't enough space for the ACL entries we use
1151 * ACL_CNT to determine the actual number of ACL entries
1152 * reallocate and try again. This is in a loop because it
1153 * is possible that someone else could modify the ACL and
1154 * increase the number of entries between the call to
1155 * ACL_CNT and the call to ACL_GET.
1157 while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
1159 sys_acl_free_acl(acl_d);
1161 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
1165 if ((acl_d = sys_acl_init(count)) == NULL) {
1171 sys_acl_free_acl(acl_d);
1176 * calculate the number of access and default ACL entries
1178 * Note: we assume that the acl() system call returned a
1179 * well formed ACL which is sorted so that all of the
1180 * access ACL entries preceed any default ACL entries
1182 for (naccess = 0; naccess < count; naccess++) {
1183 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
1186 ndefault = count - naccess;
1189 * if the caller wants the default ACL we have to copy
1190 * the entries down to the start of the acl[] buffer
1191 * and mask out the ACL_DEFAULT flag from the type field
1193 if (type == SMB_ACL_TYPE_DEFAULT) {
1196 for (i = 0, j = naccess; i < ndefault; i++, j++) {
1197 acl_d->acl[i] = acl_d->acl[j];
1198 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
1201 acl_d->count = ndefault;
1203 acl_d->count = naccess;
1209 SMB_ACL_T sys_acl_get_fd(int fd)
1212 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1215 files_struct *fsp = file_find_fd(fd);
1223 * We know we're in the same conn context. So we
1224 * can use the relative path.
1227 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
1230 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
1237 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1239 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
1240 && perm != SMB_ACL_EXECUTE) {
1245 if (permset_d == NULL) {
1255 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1257 return *permset_d & perm;
1260 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
1267 * use an initial estimate of 20 bytes per ACL entry
1268 * when allocating memory for the text representation
1272 maxlen = 20 * acl_d->count;
1273 if ((text = SMB_MALLOC(maxlen)) == NULL) {
1278 for (i = 0; i < acl_d->count; i++) {
1279 struct acl *ap = &acl_d->acl[i];
1288 switch (ap->a_type) {
1290 * for debugging purposes it's probably more
1291 * useful to dump unknown tag types rather
1292 * than just returning an error
1295 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
1298 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1304 id = uidtoname(ap->a_id);
1305 case SMB_ACL_USER_OBJ:
1310 if ((gr = getgrgid(ap->a_id)) == NULL) {
1311 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1317 case SMB_ACL_GROUP_OBJ:
1331 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
1332 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
1333 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
1336 /* <tag> : <qualifier> : rwx \n \0 */
1337 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
1340 * If this entry would overflow the buffer
1341 * allocate enough additional memory for this
1342 * entry and an estimate of another 20 bytes
1343 * for each entry still to be processed
1345 if ((len + nbytes) > maxlen) {
1346 char *oldtext = text;
1348 maxlen += nbytes + 20 * (acl_d->count - i);
1350 if ((text = SMB_REALLOC(oldtext, maxlen)) == NULL) {
1357 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
1367 SMB_ACL_T sys_acl_init(int count)
1377 * note that since the definition of the structure pointed
1378 * to by the SMB_ACL_T includes the first element of the
1379 * acl[] array, this actually allocates an ACL with room
1380 * for (count+1) entries
1382 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
1387 a->size = count + 1;
1395 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1398 SMB_ACL_ENTRY_T entry_d;
1400 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1405 if (acl_d->count >= acl_d->size) {
1410 entry_d = &acl_d->acl[acl_d->count++];
1411 entry_d->a_type = 0;
1413 entry_d->a_perm = 0;
1419 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1423 case SMB_ACL_USER_OBJ:
1425 case SMB_ACL_GROUP_OBJ:
1428 entry_d->a_type = tag_type;
1438 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1440 if (entry_d->a_type != SMB_ACL_GROUP
1441 && entry_d->a_type != SMB_ACL_USER) {
1446 entry_d->a_id = *((id_t *)qual_p);
1451 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1453 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1457 entry_d->a_perm = *permset_d;
1462 /* Structure to capture the count for each type of ACE. */
1464 struct hpux_acl_types {
1473 int n_def_group_obj;
1477 int n_def_other_obj;
1480 int n_def_class_obj;
1486 * Counts the different number of objects in a given array of ACL
1490 * acl_count - Count of ACLs in the array of ACL strucutres.
1491 * aclp - Array of ACL structures.
1492 * acl_type_count - Pointer to acl_types structure. Should already be
1496 * acl_type_count - This structure is filled up with counts of various
1500 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1504 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1506 for(i=0;i<acl_count;i++) {
1507 switch(aclp[i].a_type) {
1509 acl_type_count->n_user++;
1512 acl_type_count->n_user_obj++;
1515 acl_type_count->n_def_user_obj++;
1518 acl_type_count->n_group++;
1521 acl_type_count->n_group_obj++;
1524 acl_type_count->n_def_group_obj++;
1527 acl_type_count->n_other_obj++;
1530 acl_type_count->n_def_other_obj++;
1533 acl_type_count->n_class_obj++;
1536 acl_type_count->n_def_class_obj++;
1539 acl_type_count->n_def_user++;
1542 acl_type_count->n_def_group++;
1545 acl_type_count->n_illegal_obj++;
1551 /* swap_acl_entries: Swaps two ACL entries.
1553 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1556 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1558 struct acl temp_acl;
1560 temp_acl.a_type = aclp0->a_type;
1561 temp_acl.a_id = aclp0->a_id;
1562 temp_acl.a_perm = aclp0->a_perm;
1564 aclp0->a_type = aclp1->a_type;
1565 aclp0->a_id = aclp1->a_id;
1566 aclp0->a_perm = aclp1->a_perm;
1568 aclp1->a_type = temp_acl.a_type;
1569 aclp1->a_id = temp_acl.a_id;
1570 aclp1->a_perm = temp_acl.a_perm;
1573 /* prohibited_duplicate_type
1574 * Identifies if given ACL type can have duplicate entries or
1577 * Inputs: acl_type - ACL Type.
1583 * True - If the ACL type matches any of the prohibited types.
1584 * False - If the ACL type doesn't match any of the prohibited types.
1587 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1600 /* get_needed_class_perm
1601 * Returns the permissions of a ACL structure only if the ACL
1602 * type matches one of the pre-determined types for computing
1603 * CLASS_OBJ permissions.
1605 * Inputs: aclp - Pointer to ACL structure.
1608 static int hpux_get_needed_class_perm(struct acl *aclp)
1610 switch(aclp->a_type) {
1620 return aclp->a_perm;
1626 /* acl_sort for HPUX.
1627 * Sorts the array of ACL structures as per the description in
1628 * aclsort man page. Refer to aclsort man page for more details
1632 * acl_count - Count of ACLs in the array of ACL structures.
1633 * calclass - If this is not zero, then we compute the CLASS_OBJ
1635 * aclp - Array of ACL structures.
1639 * aclp - Sorted array of ACL structures.
1643 * Returns 0 for success -1 for failure. Prints a message to the Samba
1644 * debug log in case of failure.
1647 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1649 #if !defined(HAVE_HPUX_ACLSORT)
1651 * The aclsort() system call is availabe on the latest HPUX General
1652 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1653 * function. Because, we don't want to update to a new
1654 * HPUX GR bundle just for aclsort() call.
1657 struct hpux_acl_types acl_obj_count;
1658 int n_class_obj_perm = 0;
1662 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1667 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1671 /* Count different types of ACLs in the ACLs array */
1673 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1675 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1676 * CLASS_OBJ and OTHER_OBJ
1679 if( (acl_obj_count.n_user_obj != 1) ||
1680 (acl_obj_count.n_group_obj != 1) ||
1681 (acl_obj_count.n_class_obj != 1) ||
1682 (acl_obj_count.n_other_obj != 1)
1684 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1685 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1689 /* If any of the default objects are present, there should be only
1693 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1694 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1695 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1696 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1700 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1703 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1704 * same ACL type, sort by ACL id.
1706 * I am using the trival kind of sorting method here because, performance isn't
1707 * really effected by the ACLs feature. More over there aren't going to be more
1708 * than 17 entries on HPUX.
1711 for(i=0; i<acl_count;i++) {
1712 for (j=i+1; j<acl_count; j++) {
1713 if( aclp[i].a_type > aclp[j].a_type ) {
1714 /* ACL entries out of order, swap them */
1716 hpux_swap_acl_entries((aclp+i), (aclp+j));
1718 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1720 /* ACL entries of same type, sort by id */
1722 if(aclp[i].a_id > aclp[j].a_id) {
1723 hpux_swap_acl_entries((aclp+i), (aclp+j));
1724 } else if (aclp[i].a_id == aclp[j].a_id) {
1725 /* We have a duplicate entry. */
1726 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1727 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1728 aclp[i].a_type, aclp[i].a_id));
1737 /* set the class obj permissions to the computed one. */
1739 int n_class_obj_index = -1;
1741 for(i=0;i<acl_count;i++) {
1742 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1744 if(aclp[i].a_type == CLASS_OBJ)
1745 n_class_obj_index = i;
1747 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1752 return aclsort(acl_count, calclass, aclp);
1757 * sort the ACL and check it for validity
1759 * if it's a minimal ACL with only 4 entries then we
1760 * need to recalculate the mask permissions to make
1761 * sure that they are the same as the GROUP_OBJ
1762 * permissions as required by the UnixWare acl() system call.
1764 * (note: since POSIX allows minimal ACLs which only contain
1765 * 3 entries - ie there is no mask entry - we should, in theory,
1766 * check for this and add a mask entry if necessary - however
1767 * we "know" that the caller of this interface always specifies
1768 * a mask so, in practice "this never happens" (tm) - if it *does*
1769 * happen aclsort() will fail and return an error and someone will
1770 * have to fix it ...)
1773 static int acl_sort(SMB_ACL_T acl_d)
1775 int fixmask = (acl_d->count <= 4);
1777 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1784 int sys_acl_valid(SMB_ACL_T acl_d)
1786 return acl_sort(acl_d);
1789 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1794 struct acl *acl_buf = NULL;
1797 if(hpux_acl_call_presence() == False) {
1798 /* Looks like we don't have the acl() system call on HPUX.
1799 * May be the system doesn't have the latest version of JFS.
1805 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1810 if (acl_sort(acl_d) != 0) {
1814 acl_p = &acl_d->acl[0];
1815 acl_count = acl_d->count;
1818 * if it's a directory there is extra work to do
1819 * since the acl() system call will replace both
1820 * the access ACLs and the default ACLs (if any)
1822 if (stat(name, &s) != 0) {
1825 if (S_ISDIR(s.st_mode)) {
1831 if (type == SMB_ACL_TYPE_ACCESS) {
1833 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1837 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1840 if (tmp_acl == NULL) {
1845 * allocate a temporary buffer for the complete ACL
1847 acl_count = acc_acl->count + def_acl->count;
1848 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1850 if (acl_buf == NULL) {
1851 sys_acl_free_acl(tmp_acl);
1857 * copy the access control and default entries into the buffer
1859 memcpy(&acl_buf[0], &acc_acl->acl[0],
1860 acc_acl->count * sizeof(acl_buf[0]));
1862 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1863 def_acl->count * sizeof(acl_buf[0]));
1866 * set the ACL_DEFAULT flag on the default entries
1868 for (i = acc_acl->count; i < acl_count; i++) {
1869 acl_buf[i].a_type |= ACL_DEFAULT;
1872 sys_acl_free_acl(tmp_acl);
1874 } else if (type != SMB_ACL_TYPE_ACCESS) {
1879 ret = acl(name, ACL_SET, acl_count, acl_p);
1888 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1891 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1894 files_struct *fsp = file_find_fd(fd);
1901 if (acl_sort(acl_d) != 0) {
1906 * We know we're in the same conn context. So we
1907 * can use the relative path.
1910 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1913 int sys_acl_delete_def_file(const char *path)
1919 * fetching the access ACL and rewriting it has
1920 * the effect of deleting the default ACL
1922 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1926 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1928 sys_acl_free_acl(acl_d);
1933 int sys_acl_free_text(char *text)
1939 int sys_acl_free_acl(SMB_ACL_T acl_d)
1945 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1950 #elif defined(HAVE_IRIX_ACLS)
1952 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1954 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1959 if (entry_p == NULL) {
1964 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1968 if (acl_d->next < 0) {
1973 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1977 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1982 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1984 *type_p = entry_d->ae_tag;
1989 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1991 *permset_p = entry_d;
1996 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1998 if (entry_d->ae_tag != SMB_ACL_USER
1999 && entry_d->ae_tag != SMB_ACL_GROUP) {
2004 return &entry_d->ae_id;
2007 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
2011 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
2015 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
2024 SMB_ACL_T sys_acl_get_fd(int fd)
2028 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
2032 if ((a->aclp = acl_get_fd(fd)) == NULL) {
2041 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
2043 permset_d->ae_perm = 0;
2048 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2050 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
2051 && perm != SMB_ACL_EXECUTE) {
2056 if (permset_d == NULL) {
2061 permset_d->ae_perm |= perm;
2066 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2068 return permset_d->ae_perm & perm;
2071 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
2073 return acl_to_text(acl_d->aclp, len_p);
2076 SMB_ACL_T sys_acl_init(int count)
2085 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
2091 a->freeaclp = False;
2092 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
2093 a->aclp->acl_cnt = 0;
2099 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
2102 SMB_ACL_ENTRY_T entry_d;
2104 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
2109 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
2114 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
2115 entry_d->ae_tag = 0;
2117 entry_d->ae_perm = 0;
2123 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
2127 case SMB_ACL_USER_OBJ:
2129 case SMB_ACL_GROUP_OBJ:
2132 entry_d->ae_tag = tag_type;
2142 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
2144 if (entry_d->ae_tag != SMB_ACL_GROUP
2145 && entry_d->ae_tag != SMB_ACL_USER) {
2150 entry_d->ae_id = *((id_t *)qual_p);
2155 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
2157 if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
2161 entry_d->ae_perm = permset_d->ae_perm;
2166 int sys_acl_valid(SMB_ACL_T acl_d)
2168 return acl_valid(acl_d->aclp);
2171 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
2173 return acl_set_file(name, type, acl_d->aclp);
2176 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
2178 return acl_set_fd(fd, acl_d->aclp);
2181 int sys_acl_delete_def_file(const char *name)
2183 return acl_delete_def_file(name);
2186 int sys_acl_free_text(char *text)
2188 return acl_free(text);
2191 int sys_acl_free_acl(SMB_ACL_T acl_d)
2193 if (acl_d->freeaclp) {
2194 acl_free(acl_d->aclp);
2200 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2205 #elif defined(HAVE_AIX_ACLS)
2207 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
2209 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2211 struct acl_entry_link *link;
2212 struct new_acl_entry *entry;
2215 DEBUG(10,("This is the count: %d\n",theacl->count));
2217 /* Check if count was previously set to -1. *
2218 * If it was, that means we reached the end *
2219 * of the acl last time. */
2220 if(theacl->count == -1)
2224 /* To get to the next acl, traverse linked list until index *
2225 * of acl matches the count we are keeping. This count is *
2226 * incremented each time we return an acl entry. */
2228 for(keep_going = 0; keep_going < theacl->count; keep_going++)
2231 entry = *entry_p = link->entryp;
2233 DEBUG(10,("*entry_p is %d\n",entry_p));
2234 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
2236 /* Increment count */
2238 if(link->nextp == NULL)
2244 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2246 /* Initialize tag type */
2249 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
2251 /* Depending on what type of entry we have, *
2252 * return tag type. */
2253 switch(entry_d->ace_id->id_type) {
2255 *tag_type_p = SMB_ACL_USER;
2258 *tag_type_p = SMB_ACL_GROUP;
2261 case SMB_ACL_USER_OBJ:
2262 case SMB_ACL_GROUP_OBJ:
2264 *tag_type_p = entry_d->ace_id->id_type;
2274 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2276 DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
2277 *permset_p = &entry_d->ace_access;
2278 DEBUG(10,("**permset_p is %d\n",**permset_p));
2279 if(!(**permset_p & S_IXUSR) &&
2280 !(**permset_p & S_IWUSR) &&
2281 !(**permset_p & S_IRUSR) &&
2285 DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
2289 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2291 return(entry_d->ace_id->id_data);
2294 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2296 struct acl *file_acl = (struct acl *)NULL;
2297 struct acl_entry *acl_entry;
2298 struct new_acl_entry *new_acl_entry;
2300 struct acl_entry_link *acl_entry_link;
2301 struct acl_entry_link *acl_entry_link_head;
2306 /* AIX has no DEFAULT */
2307 if ( type == SMB_ACL_TYPE_DEFAULT ) {
2312 /* Get the acl using statacl */
2314 DEBUG(10,("Entering sys_acl_get_file\n"));
2315 DEBUG(10,("path_p is %s\n",path_p));
2317 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2319 if(file_acl == NULL) {
2321 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
2325 memset(file_acl,0,BUFSIZ);
2327 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
2329 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
2330 SAFE_FREE(file_acl);
2334 DEBUG(10,("Got facl and returned it\n"));
2336 /* Point to the first acl entry in the acl */
2337 acl_entry = file_acl->acl_ext;
2339 /* Begin setting up the head of the linked list *
2340 * that will be used for the storing the acl *
2341 * in a way that is useful for the posix_acls.c *
2344 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2345 if(acl_entry_link_head == NULL)
2348 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2349 if(acl_entry_link->entryp == NULL) {
2350 SAFE_FREE(file_acl);
2352 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2356 DEBUG(10,("acl_entry is %d\n",acl_entry));
2357 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2359 /* Check if the extended acl bit is on. *
2360 * If it isn't, do not show the *
2361 * contents of the acl since AIX intends *
2362 * the extended info to remain unused */
2364 if(file_acl->acl_mode & S_IXACL){
2365 /* while we are not pointing to the very end */
2366 while(acl_entry < acl_last(file_acl)) {
2367 /* before we malloc anything, make sure this is */
2368 /* a valid acl entry and one that we want to map */
2369 idp = id_nxt(acl_entry->ace_id);
2370 if((acl_entry->ace_type == ACC_SPECIFY ||
2371 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2372 acl_entry = acl_nxt(acl_entry);
2376 idp = acl_entry->ace_id;
2378 /* Check if this is the first entry in the linked list. *
2379 * The first entry needs to keep prevp pointing to NULL *
2380 * and already has entryp allocated. */
2382 if(acl_entry_link_head->count != 0) {
2383 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2385 if(acl_entry_link->nextp == NULL) {
2386 SAFE_FREE(file_acl);
2388 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2392 acl_entry_link->nextp->prevp = acl_entry_link;
2393 acl_entry_link = acl_entry_link->nextp;
2394 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2395 if(acl_entry_link->entryp == NULL) {
2396 SAFE_FREE(file_acl);
2398 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2401 acl_entry_link->nextp = NULL;
2404 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2406 /* Don't really need this since all types are going *
2407 * to be specified but, it's better than leaving it 0 */
2409 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2411 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2413 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2415 /* The access in the acl entries must be left shifted by *
2416 * three bites, because they will ultimately be compared *
2417 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2419 switch(acl_entry->ace_type){
2422 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2423 acl_entry_link->entryp->ace_access <<= 6;
2424 acl_entry_link_head->count++;
2427 /* Since there is no way to return a DENY acl entry *
2428 * change to PERMIT and then shift. */
2429 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2430 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2431 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2432 acl_entry_link->entryp->ace_access <<= 6;
2433 acl_entry_link_head->count++;
2439 DEBUG(10,("acl_entry = %d\n",acl_entry));
2440 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2442 acl_entry = acl_nxt(acl_entry);
2444 } /* end of if enabled */
2446 /* Since owner, group, other acl entries are not *
2447 * part of the acl entries in an acl, they must *
2448 * be dummied up to become part of the list. */
2450 for( i = 1; i < 4; i++) {
2451 DEBUG(10,("i is %d\n",i));
2452 if(acl_entry_link_head->count != 0) {
2453 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2454 if(acl_entry_link->nextp == NULL) {
2455 SAFE_FREE(file_acl);
2457 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2461 acl_entry_link->nextp->prevp = acl_entry_link;
2462 acl_entry_link = acl_entry_link->nextp;
2463 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2464 if(acl_entry_link->entryp == NULL) {
2465 SAFE_FREE(file_acl);
2467 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2472 acl_entry_link->nextp = NULL;
2474 new_acl_entry = acl_entry_link->entryp;
2475 idp = new_acl_entry->ace_id;
2477 new_acl_entry->ace_len = sizeof(struct acl_entry);
2478 new_acl_entry->ace_type = ACC_PERMIT;
2479 idp->id_len = sizeof(struct ace_id);
2480 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2481 memset(idp->id_data,0,sizeof(uid_t));
2485 new_acl_entry->ace_access = file_acl->g_access << 6;
2486 idp->id_type = SMB_ACL_GROUP_OBJ;
2490 new_acl_entry->ace_access = file_acl->o_access << 6;
2491 idp->id_type = SMB_ACL_OTHER;
2495 new_acl_entry->ace_access = file_acl->u_access << 6;
2496 idp->id_type = SMB_ACL_USER_OBJ;
2504 acl_entry_link_head->count++;
2505 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2508 acl_entry_link_head->count = 0;
2509 SAFE_FREE(file_acl);
2511 return(acl_entry_link_head);
2514 SMB_ACL_T sys_acl_get_fd(int fd)
2516 struct acl *file_acl = (struct acl *)NULL;
2517 struct acl_entry *acl_entry;
2518 struct new_acl_entry *new_acl_entry;
2520 struct acl_entry_link *acl_entry_link;
2521 struct acl_entry_link *acl_entry_link_head;
2526 /* Get the acl using fstatacl */
2528 DEBUG(10,("Entering sys_acl_get_fd\n"));
2529 DEBUG(10,("fd is %d\n",fd));
2530 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2532 if(file_acl == NULL) {
2534 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2538 memset(file_acl,0,BUFSIZ);
2540 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2542 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2543 SAFE_FREE(file_acl);
2547 DEBUG(10,("Got facl and returned it\n"));
2549 /* Point to the first acl entry in the acl */
2551 acl_entry = file_acl->acl_ext;
2552 /* Begin setting up the head of the linked list *
2553 * that will be used for the storing the acl *
2554 * in a way that is useful for the posix_acls.c *
2557 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2558 if(acl_entry_link_head == NULL){
2559 SAFE_FREE(file_acl);
2563 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2565 if(acl_entry_link->entryp == NULL) {
2567 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2568 SAFE_FREE(file_acl);
2572 DEBUG(10,("acl_entry is %d\n",acl_entry));
2573 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2575 /* Check if the extended acl bit is on. *
2576 * If it isn't, do not show the *
2577 * contents of the acl since AIX intends *
2578 * the extended info to remain unused */
2580 if(file_acl->acl_mode & S_IXACL){
2581 /* while we are not pointing to the very end */
2582 while(acl_entry < acl_last(file_acl)) {
2583 /* before we malloc anything, make sure this is */
2584 /* a valid acl entry and one that we want to map */
2586 idp = id_nxt(acl_entry->ace_id);
2587 if((acl_entry->ace_type == ACC_SPECIFY ||
2588 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2589 acl_entry = acl_nxt(acl_entry);
2593 idp = acl_entry->ace_id;
2595 /* Check if this is the first entry in the linked list. *
2596 * The first entry needs to keep prevp pointing to NULL *
2597 * and already has entryp allocated. */
2599 if(acl_entry_link_head->count != 0) {
2600 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2601 if(acl_entry_link->nextp == NULL) {
2603 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2604 SAFE_FREE(file_acl);
2607 acl_entry_link->nextp->prevp = acl_entry_link;
2608 acl_entry_link = acl_entry_link->nextp;
2609 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2610 if(acl_entry_link->entryp == NULL) {
2612 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2613 SAFE_FREE(file_acl);
2617 acl_entry_link->nextp = NULL;
2620 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2622 /* Don't really need this since all types are going *
2623 * to be specified but, it's better than leaving it 0 */
2625 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2626 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2628 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2630 /* The access in the acl entries must be left shifted by *
2631 * three bites, because they will ultimately be compared *
2632 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2634 switch(acl_entry->ace_type){
2637 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2638 acl_entry_link->entryp->ace_access <<= 6;
2639 acl_entry_link_head->count++;
2642 /* Since there is no way to return a DENY acl entry *
2643 * change to PERMIT and then shift. */
2644 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2645 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2646 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2647 acl_entry_link->entryp->ace_access <<= 6;
2648 acl_entry_link_head->count++;
2654 DEBUG(10,("acl_entry = %d\n",acl_entry));
2655 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2657 acl_entry = acl_nxt(acl_entry);
2659 } /* end of if enabled */
2661 /* Since owner, group, other acl entries are not *
2662 * part of the acl entries in an acl, they must *
2663 * be dummied up to become part of the list. */
2665 for( i = 1; i < 4; i++) {
2666 DEBUG(10,("i is %d\n",i));
2667 if(acl_entry_link_head->count != 0){
2668 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2669 if(acl_entry_link->nextp == NULL) {
2671 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2672 SAFE_FREE(file_acl);
2676 acl_entry_link->nextp->prevp = acl_entry_link;
2677 acl_entry_link = acl_entry_link->nextp;
2678 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2680 if(acl_entry_link->entryp == NULL) {
2681 SAFE_FREE(file_acl);
2683 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2688 acl_entry_link->nextp = NULL;
2690 new_acl_entry = acl_entry_link->entryp;
2691 idp = new_acl_entry->ace_id;
2693 new_acl_entry->ace_len = sizeof(struct acl_entry);
2694 new_acl_entry->ace_type = ACC_PERMIT;
2695 idp->id_len = sizeof(struct ace_id);
2696 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2697 memset(idp->id_data,0,sizeof(uid_t));
2701 new_acl_entry->ace_access = file_acl->g_access << 6;
2702 idp->id_type = SMB_ACL_GROUP_OBJ;
2706 new_acl_entry->ace_access = file_acl->o_access << 6;
2707 idp->id_type = SMB_ACL_OTHER;
2711 new_acl_entry->ace_access = file_acl->u_access << 6;
2712 idp->id_type = SMB_ACL_USER_OBJ;
2719 acl_entry_link_head->count++;
2720 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2723 acl_entry_link_head->count = 0;
2724 SAFE_FREE(file_acl);
2726 return(acl_entry_link_head);
2729 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2731 *permset = *permset & ~0777;
2735 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2738 (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
2742 DEBUG(10,("This is the permset now: %d\n",*permset));
2746 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
2751 SMB_ACL_T sys_acl_init( int count)
2753 struct acl_entry_link *theacl = NULL;
2755 DEBUG(10,("Entering sys_acl_init\n"));
2757 theacl = SMB_MALLOC_P(struct acl_entry_link);
2758 if(theacl == NULL) {
2760 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2765 theacl->nextp = NULL;
2766 theacl->prevp = NULL;
2767 theacl->entryp = NULL;
2768 DEBUG(10,("Exiting sys_acl_init\n"));
2772 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2774 struct acl_entry_link *theacl;
2775 struct acl_entry_link *acl_entryp;
2776 struct acl_entry_link *temp_entry;
2779 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2781 theacl = acl_entryp = *pacl;
2783 /* Get to the end of the acl before adding entry */
2785 for(counting=0; counting < theacl->count; counting++){
2786 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2787 temp_entry = acl_entryp;
2788 acl_entryp = acl_entryp->nextp;
2791 if(theacl->count != 0){
2792 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2793 if(acl_entryp == NULL) {
2795 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2799 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2800 acl_entryp->prevp = temp_entry;
2801 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2804 *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2805 if(*pentry == NULL) {
2807 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2811 memset(*pentry,0,sizeof(struct new_acl_entry));
2812 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2813 acl_entryp->entryp->ace_type = ACC_PERMIT;
2814 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2815 acl_entryp->nextp = NULL;
2817 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2821 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2823 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2824 entry->ace_id->id_type = tagtype;
2825 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2826 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2829 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2831 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2832 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2833 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2837 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2839 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2840 if(!(*permset & S_IXUSR) &&
2841 !(*permset & S_IWUSR) &&
2842 !(*permset & S_IRUSR) &&
2846 entry->ace_access = *permset;
2847 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2848 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2852 int sys_acl_valid( SMB_ACL_T theacl )
2857 struct acl_entry_link *acl_entry;
2859 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2860 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2861 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2862 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2865 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2867 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2873 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2875 struct acl_entry_link *acl_entry_link = NULL;
2876 struct acl *file_acl = NULL;
2877 struct acl *file_acl_temp = NULL;
2878 struct acl_entry *acl_entry = NULL;
2879 struct ace_id *ace_id = NULL;
2886 DEBUG(10,("Entering sys_acl_set_file\n"));
2887 DEBUG(10,("File name is %s\n",name));
2889 /* AIX has no default ACL */
2890 if(acltype == SMB_ACL_TYPE_DEFAULT)
2893 acl_length = BUFSIZ;
2894 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2896 if(file_acl == NULL) {
2898 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2902 memset(file_acl,0,BUFSIZ);
2904 file_acl->acl_len = ACL_SIZ;
2905 file_acl->acl_mode = S_IXACL;
2907 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2908 acl_entry_link->entryp->ace_access >>= 6;
2909 id_type = acl_entry_link->entryp->ace_id->id_type;
2912 case SMB_ACL_USER_OBJ:
2913 file_acl->u_access = acl_entry_link->entryp->ace_access;
2915 case SMB_ACL_GROUP_OBJ:
2916 file_acl->g_access = acl_entry_link->entryp->ace_access;
2919 file_acl->o_access = acl_entry_link->entryp->ace_access;
2925 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2926 acl_length += sizeof(struct acl_entry);
2927 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2928 if(file_acl_temp == NULL) {
2929 SAFE_FREE(file_acl);
2931 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2935 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2936 SAFE_FREE(file_acl);
2937 file_acl = file_acl_temp;
2940 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2941 file_acl->acl_len += sizeof(struct acl_entry);
2942 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2943 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2945 /* In order to use this, we'll need to wait until we can get denies */
2946 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2947 acl_entry->ace_type = ACC_SPECIFY; */
2949 acl_entry->ace_type = ACC_SPECIFY;
2951 ace_id = acl_entry->ace_id;
2953 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2954 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2955 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2956 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2957 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2960 rc = chacl(name,file_acl,file_acl->acl_len);
2961 DEBUG(10,("errno is %d\n",errno));
2962 DEBUG(10,("return code is %d\n",rc));
2963 SAFE_FREE(file_acl);
2964 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2968 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2970 struct acl_entry_link *acl_entry_link = NULL;
2971 struct acl *file_acl = NULL;
2972 struct acl *file_acl_temp = NULL;
2973 struct acl_entry *acl_entry = NULL;
2974 struct ace_id *ace_id = NULL;
2980 DEBUG(10,("Entering sys_acl_set_fd\n"));
2981 acl_length = BUFSIZ;
2982 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2984 if(file_acl == NULL) {
2986 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2990 memset(file_acl,0,BUFSIZ);
2992 file_acl->acl_len = ACL_SIZ;
2993 file_acl->acl_mode = S_IXACL;
2995 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2996 acl_entry_link->entryp->ace_access >>= 6;
2997 id_type = acl_entry_link->entryp->ace_id->id_type;
2998 DEBUG(10,("The id_type is %d\n",id_type));
3001 case SMB_ACL_USER_OBJ:
3002 file_acl->u_access = acl_entry_link->entryp->ace_access;
3004 case SMB_ACL_GROUP_OBJ:
3005 file_acl->g_access = acl_entry_link->entryp->ace_access;
3008 file_acl->o_access = acl_entry_link->entryp->ace_access;
3014 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
3015 acl_length += sizeof(struct acl_entry);
3016 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
3017 if(file_acl_temp == NULL) {
3018 SAFE_FREE(file_acl);
3020 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
3024 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
3025 SAFE_FREE(file_acl);
3026 file_acl = file_acl_temp;
3029 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
3030 file_acl->acl_len += sizeof(struct acl_entry);
3031 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
3032 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
3034 /* In order to use this, we'll need to wait until we can get denies */
3035 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
3036 acl_entry->ace_type = ACC_SPECIFY; */
3038 acl_entry->ace_type = ACC_SPECIFY;
3040 ace_id = acl_entry->ace_id;
3042 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
3043 DEBUG(10,("The id type is %d\n",ace_id->id_type));
3044 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
3045 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
3046 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
3049 rc = fchacl(fd,file_acl,file_acl->acl_len);
3050 DEBUG(10,("errno is %d\n",errno));
3051 DEBUG(10,("return code is %d\n",rc));
3052 SAFE_FREE(file_acl);
3053 DEBUG(10,("Exiting sys_acl_set_fd\n"));
3057 int sys_acl_delete_def_file(const char *name)
3059 /* AIX has no default ACL */
3063 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3065 return(*permset & perm);
3068 int sys_acl_free_text(char *text)
3073 int sys_acl_free_acl(SMB_ACL_T posix_acl)
3075 struct acl_entry_link *acl_entry_link;
3077 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
3078 SAFE_FREE(acl_entry_link->prevp->entryp);
3079 SAFE_FREE(acl_entry_link->prevp);
3082 SAFE_FREE(acl_entry_link->prevp->entryp);
3083 SAFE_FREE(acl_entry_link->prevp);
3084 SAFE_FREE(acl_entry_link->entryp);
3085 SAFE_FREE(acl_entry_link);
3090 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3095 #else /* No ACLs. */
3097 int sys_acl_get_entry(UNUSED(SMB_ACL_T the_acl), UNUSED(int entry_id), UNUSED(SMB_ACL_ENTRY_T *entry_p))
3103 int sys_acl_get_tag_type(UNUSED(SMB_ACL_ENTRY_T entry_d), UNUSED(SMB_ACL_TAG_T *tag_type_p))
3109 int sys_acl_get_permset(UNUSED(SMB_ACL_ENTRY_T entry_d), UNUSED(SMB_ACL_PERMSET_T *permset_p))
3115 void *sys_acl_get_qualifier(UNUSED(SMB_ACL_ENTRY_T entry_d))
3121 SMB_ACL_T sys_acl_get_file(UNUSED(const char *path_p), UNUSED(SMB_ACL_TYPE_T type))
3124 return (SMB_ACL_T)NULL;
3127 SMB_ACL_T sys_acl_get_fd(UNUSED(int fd))
3130 return (SMB_ACL_T)NULL;
3133 int sys_acl_clear_perms(UNUSED(SMB_ACL_PERMSET_T permset))
3139 int sys_acl_add_perm( UNUSED(SMB_ACL_PERMSET_T permset), UNUSED(SMB_ACL_PERM_T perm))
3145 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3148 return (permset & perm) ? 1 : 0;
3151 char *sys_acl_to_text(UNUSED(SMB_ACL_T the_acl), UNUSED(ssize_t *plen))
3157 int sys_acl_free_text(UNUSED(char *text))
3163 SMB_ACL_T sys_acl_init(UNUSED(int count))
3169 int sys_acl_create_entry(UNUSED(SMB_ACL_T *pacl), UNUSED(SMB_ACL_ENTRY_T *pentry))
3175 int sys_acl_set_tag_type(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(SMB_ACL_TAG_T tagtype))
3181 int sys_acl_set_qualifier(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(void *qual))
3187 int sys_acl_set_permset(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(SMB_ACL_PERMSET_T permset))
3193 int sys_acl_valid(UNUSED(SMB_ACL_T theacl))
3199 int sys_acl_set_file(UNUSED(const char *name), UNUSED(SMB_ACL_TYPE_T acltype), UNUSED(SMB_ACL_T theacl))
3205 int sys_acl_set_fd(UNUSED(int fd), UNUSED(SMB_ACL_T theacl))
3211 int sys_acl_delete_def_file(UNUSED(const char *name))
3217 int sys_acl_free_acl(UNUSED(SMB_ACL_T the_acl))
3223 int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
3229 #endif /* No ACLs. */
3231 /************************************************************************
3232 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
3234 ************************************************************************/
3236 int no_acl_syscall_error(int err)
3239 if (err == ENOSYS) {
3243 #if defined(ENOTSUP)
3244 if (err == ENOTSUP) {
3251 #endif /* SUPPORT_ACLS */