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;
1210 SMB_ACL_T sys_acl_get_fd(int fd)
1213 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1216 files_struct *fsp = file_find_fd(fd);
1224 * We know we're in the same conn context. So we
1225 * can use the relative path.
1228 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
1232 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
1239 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1241 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
1242 && perm != SMB_ACL_EXECUTE) {
1247 if (permset_d == NULL) {
1257 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1259 return *permset_d & perm;
1262 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
1269 * use an initial estimate of 20 bytes per ACL entry
1270 * when allocating memory for the text representation
1274 maxlen = 20 * acl_d->count;
1275 if ((text = SMB_MALLOC(maxlen)) == NULL) {
1280 for (i = 0; i < acl_d->count; i++) {
1281 struct acl *ap = &acl_d->acl[i];
1290 switch (ap->a_type) {
1292 * for debugging purposes it's probably more
1293 * useful to dump unknown tag types rather
1294 * than just returning an error
1297 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
1300 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1306 id = uidtoname(ap->a_id);
1307 case SMB_ACL_USER_OBJ:
1312 if ((gr = getgrgid(ap->a_id)) == NULL) {
1313 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1319 case SMB_ACL_GROUP_OBJ:
1333 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
1334 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
1335 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
1338 /* <tag> : <qualifier> : rwx \n \0 */
1339 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
1342 * If this entry would overflow the buffer
1343 * allocate enough additional memory for this
1344 * entry and an estimate of another 20 bytes
1345 * for each entry still to be processed
1347 if ((len + nbytes) > maxlen) {
1348 char *oldtext = text;
1350 maxlen += nbytes + 20 * (acl_d->count - i);
1352 if ((text = SMB_REALLOC(oldtext, maxlen)) == NULL) {
1359 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
1369 SMB_ACL_T sys_acl_init(int count)
1379 * note that since the definition of the structure pointed
1380 * to by the SMB_ACL_T includes the first element of the
1381 * acl[] array, this actually allocates an ACL with room
1382 * for (count+1) entries
1384 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
1389 a->size = count + 1;
1397 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1400 SMB_ACL_ENTRY_T entry_d;
1402 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1407 if (acl_d->count >= acl_d->size) {
1412 entry_d = &acl_d->acl[acl_d->count++];
1413 entry_d->a_type = 0;
1415 entry_d->a_perm = 0;
1421 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1425 case SMB_ACL_USER_OBJ:
1427 case SMB_ACL_GROUP_OBJ:
1430 entry_d->a_type = tag_type;
1440 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1442 if (entry_d->a_type != SMB_ACL_GROUP
1443 && entry_d->a_type != SMB_ACL_USER) {
1448 entry_d->a_id = *((id_t *)qual_p);
1453 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1455 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1459 entry_d->a_perm = *permset_d;
1464 /* Structure to capture the count for each type of ACE. */
1466 struct hpux_acl_types {
1475 int n_def_group_obj;
1479 int n_def_other_obj;
1482 int n_def_class_obj;
1488 * Counts the different number of objects in a given array of ACL
1492 * acl_count - Count of ACLs in the array of ACL strucutres.
1493 * aclp - Array of ACL structures.
1494 * acl_type_count - Pointer to acl_types structure. Should already be
1498 * acl_type_count - This structure is filled up with counts of various
1502 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1506 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1508 for(i=0;i<acl_count;i++) {
1509 switch(aclp[i].a_type) {
1511 acl_type_count->n_user++;
1514 acl_type_count->n_user_obj++;
1517 acl_type_count->n_def_user_obj++;
1520 acl_type_count->n_group++;
1523 acl_type_count->n_group_obj++;
1526 acl_type_count->n_def_group_obj++;
1529 acl_type_count->n_other_obj++;
1532 acl_type_count->n_def_other_obj++;
1535 acl_type_count->n_class_obj++;
1538 acl_type_count->n_def_class_obj++;
1541 acl_type_count->n_def_user++;
1544 acl_type_count->n_def_group++;
1547 acl_type_count->n_illegal_obj++;
1553 /* swap_acl_entries: Swaps two ACL entries.
1555 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1558 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1560 struct acl temp_acl;
1562 temp_acl.a_type = aclp0->a_type;
1563 temp_acl.a_id = aclp0->a_id;
1564 temp_acl.a_perm = aclp0->a_perm;
1566 aclp0->a_type = aclp1->a_type;
1567 aclp0->a_id = aclp1->a_id;
1568 aclp0->a_perm = aclp1->a_perm;
1570 aclp1->a_type = temp_acl.a_type;
1571 aclp1->a_id = temp_acl.a_id;
1572 aclp1->a_perm = temp_acl.a_perm;
1575 /* prohibited_duplicate_type
1576 * Identifies if given ACL type can have duplicate entries or
1579 * Inputs: acl_type - ACL Type.
1585 * True - If the ACL type matches any of the prohibited types.
1586 * False - If the ACL type doesn't match any of the prohibited types.
1589 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1602 /* get_needed_class_perm
1603 * Returns the permissions of a ACL structure only if the ACL
1604 * type matches one of the pre-determined types for computing
1605 * CLASS_OBJ permissions.
1607 * Inputs: aclp - Pointer to ACL structure.
1610 static int hpux_get_needed_class_perm(struct acl *aclp)
1612 switch(aclp->a_type) {
1622 return aclp->a_perm;
1628 /* acl_sort for HPUX.
1629 * Sorts the array of ACL structures as per the description in
1630 * aclsort man page. Refer to aclsort man page for more details
1634 * acl_count - Count of ACLs in the array of ACL structures.
1635 * calclass - If this is not zero, then we compute the CLASS_OBJ
1637 * aclp - Array of ACL structures.
1641 * aclp - Sorted array of ACL structures.
1645 * Returns 0 for success -1 for failure. Prints a message to the Samba
1646 * debug log in case of failure.
1649 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1651 #if !defined(HAVE_HPUX_ACLSORT)
1653 * The aclsort() system call is availabe on the latest HPUX General
1654 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1655 * function. Because, we don't want to update to a new
1656 * HPUX GR bundle just for aclsort() call.
1659 struct hpux_acl_types acl_obj_count;
1660 int n_class_obj_perm = 0;
1664 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1669 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1673 /* Count different types of ACLs in the ACLs array */
1675 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1677 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1678 * CLASS_OBJ and OTHER_OBJ
1681 if( (acl_obj_count.n_user_obj != 1) ||
1682 (acl_obj_count.n_group_obj != 1) ||
1683 (acl_obj_count.n_class_obj != 1) ||
1684 (acl_obj_count.n_other_obj != 1)
1686 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1687 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1691 /* If any of the default objects are present, there should be only
1695 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1696 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1697 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1698 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1702 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1705 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1706 * same ACL type, sort by ACL id.
1708 * I am using the trival kind of sorting method here because, performance isn't
1709 * really effected by the ACLs feature. More over there aren't going to be more
1710 * than 17 entries on HPUX.
1713 for(i=0; i<acl_count;i++) {
1714 for (j=i+1; j<acl_count; j++) {
1715 if( aclp[i].a_type > aclp[j].a_type ) {
1716 /* ACL entries out of order, swap them */
1718 hpux_swap_acl_entries((aclp+i), (aclp+j));
1720 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1722 /* ACL entries of same type, sort by id */
1724 if(aclp[i].a_id > aclp[j].a_id) {
1725 hpux_swap_acl_entries((aclp+i), (aclp+j));
1726 } else if (aclp[i].a_id == aclp[j].a_id) {
1727 /* We have a duplicate entry. */
1728 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1729 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1730 aclp[i].a_type, aclp[i].a_id));
1739 /* set the class obj permissions to the computed one. */
1741 int n_class_obj_index = -1;
1743 for(i=0;i<acl_count;i++) {
1744 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1746 if(aclp[i].a_type == CLASS_OBJ)
1747 n_class_obj_index = i;
1749 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1754 return aclsort(acl_count, calclass, aclp);
1759 * sort the ACL and check it for validity
1761 * if it's a minimal ACL with only 4 entries then we
1762 * need to recalculate the mask permissions to make
1763 * sure that they are the same as the GROUP_OBJ
1764 * permissions as required by the UnixWare acl() system call.
1766 * (note: since POSIX allows minimal ACLs which only contain
1767 * 3 entries - ie there is no mask entry - we should, in theory,
1768 * check for this and add a mask entry if necessary - however
1769 * we "know" that the caller of this interface always specifies
1770 * a mask so, in practice "this never happens" (tm) - if it *does*
1771 * happen aclsort() will fail and return an error and someone will
1772 * have to fix it ...)
1775 static int acl_sort(SMB_ACL_T acl_d)
1777 int fixmask = (acl_d->count <= 4);
1779 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1786 int sys_acl_valid(SMB_ACL_T acl_d)
1788 return acl_sort(acl_d);
1791 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1796 struct acl *acl_buf = NULL;
1799 if(hpux_acl_call_presence() == False) {
1800 /* Looks like we don't have the acl() system call on HPUX.
1801 * May be the system doesn't have the latest version of JFS.
1807 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1812 if (acl_sort(acl_d) != 0) {
1816 acl_p = &acl_d->acl[0];
1817 acl_count = acl_d->count;
1820 * if it's a directory there is extra work to do
1821 * since the acl() system call will replace both
1822 * the access ACLs and the default ACLs (if any)
1824 if (stat(name, &s) != 0) {
1827 if (S_ISDIR(s.st_mode)) {
1833 if (type == SMB_ACL_TYPE_ACCESS) {
1835 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1839 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1842 if (tmp_acl == NULL) {
1847 * allocate a temporary buffer for the complete ACL
1849 acl_count = acc_acl->count + def_acl->count;
1850 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1852 if (acl_buf == NULL) {
1853 sys_acl_free_acl(tmp_acl);
1859 * copy the access control and default entries into the buffer
1861 memcpy(&acl_buf[0], &acc_acl->acl[0],
1862 acc_acl->count * sizeof(acl_buf[0]));
1864 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1865 def_acl->count * sizeof(acl_buf[0]));
1868 * set the ACL_DEFAULT flag on the default entries
1870 for (i = acc_acl->count; i < acl_count; i++) {
1871 acl_buf[i].a_type |= ACL_DEFAULT;
1874 sys_acl_free_acl(tmp_acl);
1876 } else if (type != SMB_ACL_TYPE_ACCESS) {
1881 ret = acl(name, ACL_SET, acl_count, acl_p);
1891 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1894 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1897 files_struct *fsp = file_find_fd(fd);
1904 if (acl_sort(acl_d) != 0) {
1909 * We know we're in the same conn context. So we
1910 * can use the relative path.
1913 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1917 int sys_acl_delete_def_file(const char *path)
1923 * fetching the access ACL and rewriting it has
1924 * the effect of deleting the default ACL
1926 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1930 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1932 sys_acl_free_acl(acl_d);
1937 int sys_acl_free_text(char *text)
1943 int sys_acl_free_acl(SMB_ACL_T acl_d)
1949 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1954 #elif defined(HAVE_IRIX_ACLS)
1956 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1958 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1963 if (entry_p == NULL) {
1968 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1972 if (acl_d->next < 0) {
1977 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1981 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1986 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1988 *type_p = entry_d->ae_tag;
1993 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1995 *permset_p = entry_d;
2000 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
2002 if (entry_d->ae_tag != SMB_ACL_USER
2003 && entry_d->ae_tag != SMB_ACL_GROUP) {
2008 return &entry_d->ae_id;
2011 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
2015 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
2019 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
2028 SMB_ACL_T sys_acl_get_fd(int fd)
2032 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
2036 if ((a->aclp = acl_get_fd(fd)) == NULL) {
2045 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
2047 permset_d->ae_perm = 0;
2052 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2054 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
2055 && perm != SMB_ACL_EXECUTE) {
2060 if (permset_d == NULL) {
2065 permset_d->ae_perm |= perm;
2070 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2072 return permset_d->ae_perm & perm;
2075 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
2077 return acl_to_text(acl_d->aclp, len_p);
2080 SMB_ACL_T sys_acl_init(int count)
2089 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
2095 a->freeaclp = False;
2096 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
2097 a->aclp->acl_cnt = 0;
2103 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
2106 SMB_ACL_ENTRY_T entry_d;
2108 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
2113 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
2118 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
2119 entry_d->ae_tag = 0;
2121 entry_d->ae_perm = 0;
2127 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
2131 case SMB_ACL_USER_OBJ:
2133 case SMB_ACL_GROUP_OBJ:
2136 entry_d->ae_tag = tag_type;
2146 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
2148 if (entry_d->ae_tag != SMB_ACL_GROUP
2149 && entry_d->ae_tag != SMB_ACL_USER) {
2154 entry_d->ae_id = *((id_t *)qual_p);
2159 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
2161 if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
2165 entry_d->ae_perm = permset_d->ae_perm;
2170 int sys_acl_valid(SMB_ACL_T acl_d)
2172 return acl_valid(acl_d->aclp);
2175 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
2177 return acl_set_file(name, type, acl_d->aclp);
2180 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
2182 return acl_set_fd(fd, acl_d->aclp);
2185 int sys_acl_delete_def_file(const char *name)
2187 return acl_delete_def_file(name);
2190 int sys_acl_free_text(char *text)
2192 return acl_free(text);
2195 int sys_acl_free_acl(SMB_ACL_T acl_d)
2197 if (acl_d->freeaclp) {
2198 acl_free(acl_d->aclp);
2204 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2209 #elif defined(HAVE_AIX_ACLS)
2211 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
2213 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2215 struct acl_entry_link *link;
2216 struct new_acl_entry *entry;
2219 DEBUG(10,("This is the count: %d\n",theacl->count));
2221 /* Check if count was previously set to -1. *
2222 * If it was, that means we reached the end *
2223 * of the acl last time. */
2224 if(theacl->count == -1)
2228 /* To get to the next acl, traverse linked list until index *
2229 * of acl matches the count we are keeping. This count is *
2230 * incremented each time we return an acl entry. */
2232 for(keep_going = 0; keep_going < theacl->count; keep_going++)
2235 entry = *entry_p = link->entryp;
2237 DEBUG(10,("*entry_p is %d\n",entry_p));
2238 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
2240 /* Increment count */
2242 if(link->nextp == NULL)
2248 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2250 /* Initialize tag type */
2253 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
2255 /* Depending on what type of entry we have, *
2256 * return tag type. */
2257 switch(entry_d->ace_id->id_type) {
2259 *tag_type_p = SMB_ACL_USER;
2262 *tag_type_p = SMB_ACL_GROUP;
2265 case SMB_ACL_USER_OBJ:
2266 case SMB_ACL_GROUP_OBJ:
2268 *tag_type_p = entry_d->ace_id->id_type;
2278 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2280 DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
2281 *permset_p = &entry_d->ace_access;
2282 DEBUG(10,("**permset_p is %d\n",**permset_p));
2283 if(!(**permset_p & S_IXUSR) &&
2284 !(**permset_p & S_IWUSR) &&
2285 !(**permset_p & S_IRUSR) &&
2289 DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
2293 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2295 return(entry_d->ace_id->id_data);
2298 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2300 struct acl *file_acl = (struct acl *)NULL;
2301 struct acl_entry *acl_entry;
2302 struct new_acl_entry *new_acl_entry;
2304 struct acl_entry_link *acl_entry_link;
2305 struct acl_entry_link *acl_entry_link_head;
2310 /* AIX has no DEFAULT */
2311 if ( type == SMB_ACL_TYPE_DEFAULT ) {
2316 /* Get the acl using statacl */
2318 DEBUG(10,("Entering sys_acl_get_file\n"));
2319 DEBUG(10,("path_p is %s\n",path_p));
2321 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2323 if(file_acl == NULL) {
2325 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
2329 memset(file_acl,0,BUFSIZ);
2331 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
2333 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
2334 SAFE_FREE(file_acl);
2338 DEBUG(10,("Got facl and returned it\n"));
2340 /* Point to the first acl entry in the acl */
2341 acl_entry = file_acl->acl_ext;
2343 /* Begin setting up the head of the linked list *
2344 * that will be used for the storing the acl *
2345 * in a way that is useful for the posix_acls.c *
2348 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2349 if(acl_entry_link_head == NULL)
2352 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2353 if(acl_entry_link->entryp == NULL) {
2354 SAFE_FREE(file_acl);
2356 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2360 DEBUG(10,("acl_entry is %d\n",acl_entry));
2361 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2363 /* Check if the extended acl bit is on. *
2364 * If it isn't, do not show the *
2365 * contents of the acl since AIX intends *
2366 * the extended info to remain unused */
2368 if(file_acl->acl_mode & S_IXACL){
2369 /* while we are not pointing to the very end */
2370 while(acl_entry < acl_last(file_acl)) {
2371 /* before we malloc anything, make sure this is */
2372 /* a valid acl entry and one that we want to map */
2373 idp = id_nxt(acl_entry->ace_id);
2374 if((acl_entry->ace_type == ACC_SPECIFY ||
2375 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2376 acl_entry = acl_nxt(acl_entry);
2380 idp = acl_entry->ace_id;
2382 /* Check if this is the first entry in the linked list. *
2383 * The first entry needs to keep prevp pointing to NULL *
2384 * and already has entryp allocated. */
2386 if(acl_entry_link_head->count != 0) {
2387 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2389 if(acl_entry_link->nextp == NULL) {
2390 SAFE_FREE(file_acl);
2392 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2396 acl_entry_link->nextp->prevp = acl_entry_link;
2397 acl_entry_link = acl_entry_link->nextp;
2398 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2399 if(acl_entry_link->entryp == NULL) {
2400 SAFE_FREE(file_acl);
2402 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2405 acl_entry_link->nextp = NULL;
2408 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2410 /* Don't really need this since all types are going *
2411 * to be specified but, it's better than leaving it 0 */
2413 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2415 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2417 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2419 /* The access in the acl entries must be left shifted by *
2420 * three bites, because they will ultimately be compared *
2421 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2423 switch(acl_entry->ace_type){
2426 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2427 acl_entry_link->entryp->ace_access <<= 6;
2428 acl_entry_link_head->count++;
2431 /* Since there is no way to return a DENY acl entry *
2432 * change to PERMIT and then shift. */
2433 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2434 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2435 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2436 acl_entry_link->entryp->ace_access <<= 6;
2437 acl_entry_link_head->count++;
2443 DEBUG(10,("acl_entry = %d\n",acl_entry));
2444 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2446 acl_entry = acl_nxt(acl_entry);
2448 } /* end of if enabled */
2450 /* Since owner, group, other acl entries are not *
2451 * part of the acl entries in an acl, they must *
2452 * be dummied up to become part of the list. */
2454 for( i = 1; i < 4; i++) {
2455 DEBUG(10,("i is %d\n",i));
2456 if(acl_entry_link_head->count != 0) {
2457 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2458 if(acl_entry_link->nextp == NULL) {
2459 SAFE_FREE(file_acl);
2461 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2465 acl_entry_link->nextp->prevp = acl_entry_link;
2466 acl_entry_link = acl_entry_link->nextp;
2467 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2468 if(acl_entry_link->entryp == NULL) {
2469 SAFE_FREE(file_acl);
2471 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2476 acl_entry_link->nextp = NULL;
2478 new_acl_entry = acl_entry_link->entryp;
2479 idp = new_acl_entry->ace_id;
2481 new_acl_entry->ace_len = sizeof(struct acl_entry);
2482 new_acl_entry->ace_type = ACC_PERMIT;
2483 idp->id_len = sizeof(struct ace_id);
2484 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2485 memset(idp->id_data,0,sizeof(uid_t));
2489 new_acl_entry->ace_access = file_acl->g_access << 6;
2490 idp->id_type = SMB_ACL_GROUP_OBJ;
2494 new_acl_entry->ace_access = file_acl->o_access << 6;
2495 idp->id_type = SMB_ACL_OTHER;
2499 new_acl_entry->ace_access = file_acl->u_access << 6;
2500 idp->id_type = SMB_ACL_USER_OBJ;
2508 acl_entry_link_head->count++;
2509 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2512 acl_entry_link_head->count = 0;
2513 SAFE_FREE(file_acl);
2515 return(acl_entry_link_head);
2518 SMB_ACL_T sys_acl_get_fd(int fd)
2520 struct acl *file_acl = (struct acl *)NULL;
2521 struct acl_entry *acl_entry;
2522 struct new_acl_entry *new_acl_entry;
2524 struct acl_entry_link *acl_entry_link;
2525 struct acl_entry_link *acl_entry_link_head;
2530 /* Get the acl using fstatacl */
2532 DEBUG(10,("Entering sys_acl_get_fd\n"));
2533 DEBUG(10,("fd is %d\n",fd));
2534 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2536 if(file_acl == NULL) {
2538 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2542 memset(file_acl,0,BUFSIZ);
2544 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2546 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2547 SAFE_FREE(file_acl);
2551 DEBUG(10,("Got facl and returned it\n"));
2553 /* Point to the first acl entry in the acl */
2555 acl_entry = file_acl->acl_ext;
2556 /* Begin setting up the head of the linked list *
2557 * that will be used for the storing the acl *
2558 * in a way that is useful for the posix_acls.c *
2561 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2562 if(acl_entry_link_head == NULL){
2563 SAFE_FREE(file_acl);
2567 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2569 if(acl_entry_link->entryp == NULL) {
2571 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2572 SAFE_FREE(file_acl);
2576 DEBUG(10,("acl_entry is %d\n",acl_entry));
2577 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2579 /* Check if the extended acl bit is on. *
2580 * If it isn't, do not show the *
2581 * contents of the acl since AIX intends *
2582 * the extended info to remain unused */
2584 if(file_acl->acl_mode & S_IXACL){
2585 /* while we are not pointing to the very end */
2586 while(acl_entry < acl_last(file_acl)) {
2587 /* before we malloc anything, make sure this is */
2588 /* a valid acl entry and one that we want to map */
2590 idp = id_nxt(acl_entry->ace_id);
2591 if((acl_entry->ace_type == ACC_SPECIFY ||
2592 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2593 acl_entry = acl_nxt(acl_entry);
2597 idp = acl_entry->ace_id;
2599 /* Check if this is the first entry in the linked list. *
2600 * The first entry needs to keep prevp pointing to NULL *
2601 * and already has entryp allocated. */
2603 if(acl_entry_link_head->count != 0) {
2604 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2605 if(acl_entry_link->nextp == NULL) {
2607 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2608 SAFE_FREE(file_acl);
2611 acl_entry_link->nextp->prevp = acl_entry_link;
2612 acl_entry_link = acl_entry_link->nextp;
2613 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2614 if(acl_entry_link->entryp == NULL) {
2616 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2617 SAFE_FREE(file_acl);
2621 acl_entry_link->nextp = NULL;
2624 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2626 /* Don't really need this since all types are going *
2627 * to be specified but, it's better than leaving it 0 */
2629 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2630 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2632 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2634 /* The access in the acl entries must be left shifted by *
2635 * three bites, because they will ultimately be compared *
2636 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2638 switch(acl_entry->ace_type){
2641 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2642 acl_entry_link->entryp->ace_access <<= 6;
2643 acl_entry_link_head->count++;
2646 /* Since there is no way to return a DENY acl entry *
2647 * change to PERMIT and then shift. */
2648 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2649 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2650 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2651 acl_entry_link->entryp->ace_access <<= 6;
2652 acl_entry_link_head->count++;
2658 DEBUG(10,("acl_entry = %d\n",acl_entry));
2659 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2661 acl_entry = acl_nxt(acl_entry);
2663 } /* end of if enabled */
2665 /* Since owner, group, other acl entries are not *
2666 * part of the acl entries in an acl, they must *
2667 * be dummied up to become part of the list. */
2669 for( i = 1; i < 4; i++) {
2670 DEBUG(10,("i is %d\n",i));
2671 if(acl_entry_link_head->count != 0){
2672 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2673 if(acl_entry_link->nextp == NULL) {
2675 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2676 SAFE_FREE(file_acl);
2680 acl_entry_link->nextp->prevp = acl_entry_link;
2681 acl_entry_link = acl_entry_link->nextp;
2682 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2684 if(acl_entry_link->entryp == NULL) {
2685 SAFE_FREE(file_acl);
2687 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2692 acl_entry_link->nextp = NULL;
2694 new_acl_entry = acl_entry_link->entryp;
2695 idp = new_acl_entry->ace_id;
2697 new_acl_entry->ace_len = sizeof(struct acl_entry);
2698 new_acl_entry->ace_type = ACC_PERMIT;
2699 idp->id_len = sizeof(struct ace_id);
2700 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2701 memset(idp->id_data,0,sizeof(uid_t));
2705 new_acl_entry->ace_access = file_acl->g_access << 6;
2706 idp->id_type = SMB_ACL_GROUP_OBJ;
2710 new_acl_entry->ace_access = file_acl->o_access << 6;
2711 idp->id_type = SMB_ACL_OTHER;
2715 new_acl_entry->ace_access = file_acl->u_access << 6;
2716 idp->id_type = SMB_ACL_USER_OBJ;
2723 acl_entry_link_head->count++;
2724 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2727 acl_entry_link_head->count = 0;
2728 SAFE_FREE(file_acl);
2730 return(acl_entry_link_head);
2733 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2735 *permset = *permset & ~0777;
2739 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2742 (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
2746 DEBUG(10,("This is the permset now: %d\n",*permset));
2750 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
2755 SMB_ACL_T sys_acl_init( int count)
2757 struct acl_entry_link *theacl = NULL;
2759 DEBUG(10,("Entering sys_acl_init\n"));
2761 theacl = SMB_MALLOC_P(struct acl_entry_link);
2762 if(theacl == NULL) {
2764 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2769 theacl->nextp = NULL;
2770 theacl->prevp = NULL;
2771 theacl->entryp = NULL;
2772 DEBUG(10,("Exiting sys_acl_init\n"));
2776 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2778 struct acl_entry_link *theacl;
2779 struct acl_entry_link *acl_entryp;
2780 struct acl_entry_link *temp_entry;
2783 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2785 theacl = acl_entryp = *pacl;
2787 /* Get to the end of the acl before adding entry */
2789 for(counting=0; counting < theacl->count; counting++){
2790 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2791 temp_entry = acl_entryp;
2792 acl_entryp = acl_entryp->nextp;
2795 if(theacl->count != 0){
2796 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2797 if(acl_entryp == NULL) {
2799 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2803 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2804 acl_entryp->prevp = temp_entry;
2805 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2808 *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2809 if(*pentry == NULL) {
2811 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2815 memset(*pentry,0,sizeof(struct new_acl_entry));
2816 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2817 acl_entryp->entryp->ace_type = ACC_PERMIT;
2818 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2819 acl_entryp->nextp = NULL;
2821 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2825 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2827 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2828 entry->ace_id->id_type = tagtype;
2829 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2830 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2833 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2835 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2836 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2837 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2841 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2843 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2844 if(!(*permset & S_IXUSR) &&
2845 !(*permset & S_IWUSR) &&
2846 !(*permset & S_IRUSR) &&
2850 entry->ace_access = *permset;
2851 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2852 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2856 int sys_acl_valid( SMB_ACL_T theacl )
2861 struct acl_entry_link *acl_entry;
2863 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2864 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2865 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2866 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2869 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2871 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2877 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2879 struct acl_entry_link *acl_entry_link = NULL;
2880 struct acl *file_acl = NULL;
2881 struct acl *file_acl_temp = NULL;
2882 struct acl_entry *acl_entry = NULL;
2883 struct ace_id *ace_id = NULL;
2890 DEBUG(10,("Entering sys_acl_set_file\n"));
2891 DEBUG(10,("File name is %s\n",name));
2893 /* AIX has no default ACL */
2894 if(acltype == SMB_ACL_TYPE_DEFAULT)
2897 acl_length = BUFSIZ;
2898 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2900 if(file_acl == NULL) {
2902 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2906 memset(file_acl,0,BUFSIZ);
2908 file_acl->acl_len = ACL_SIZ;
2909 file_acl->acl_mode = S_IXACL;
2911 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2912 acl_entry_link->entryp->ace_access >>= 6;
2913 id_type = acl_entry_link->entryp->ace_id->id_type;
2916 case SMB_ACL_USER_OBJ:
2917 file_acl->u_access = acl_entry_link->entryp->ace_access;
2919 case SMB_ACL_GROUP_OBJ:
2920 file_acl->g_access = acl_entry_link->entryp->ace_access;
2923 file_acl->o_access = acl_entry_link->entryp->ace_access;
2929 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2930 acl_length += sizeof(struct acl_entry);
2931 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2932 if(file_acl_temp == NULL) {
2933 SAFE_FREE(file_acl);
2935 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2939 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2940 SAFE_FREE(file_acl);
2941 file_acl = file_acl_temp;
2944 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2945 file_acl->acl_len += sizeof(struct acl_entry);
2946 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2947 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2949 /* In order to use this, we'll need to wait until we can get denies */
2950 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2951 acl_entry->ace_type = ACC_SPECIFY; */
2953 acl_entry->ace_type = ACC_SPECIFY;
2955 ace_id = acl_entry->ace_id;
2957 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2958 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2959 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2960 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2961 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2964 rc = chacl(name,file_acl,file_acl->acl_len);
2965 DEBUG(10,("errno is %d\n",errno));
2966 DEBUG(10,("return code is %d\n",rc));
2967 SAFE_FREE(file_acl);
2968 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2972 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2974 struct acl_entry_link *acl_entry_link = NULL;
2975 struct acl *file_acl = NULL;
2976 struct acl *file_acl_temp = NULL;
2977 struct acl_entry *acl_entry = NULL;
2978 struct ace_id *ace_id = NULL;
2984 DEBUG(10,("Entering sys_acl_set_fd\n"));
2985 acl_length = BUFSIZ;
2986 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2988 if(file_acl == NULL) {
2990 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2994 memset(file_acl,0,BUFSIZ);
2996 file_acl->acl_len = ACL_SIZ;
2997 file_acl->acl_mode = S_IXACL;
2999 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
3000 acl_entry_link->entryp->ace_access >>= 6;
3001 id_type = acl_entry_link->entryp->ace_id->id_type;
3002 DEBUG(10,("The id_type is %d\n",id_type));
3005 case SMB_ACL_USER_OBJ:
3006 file_acl->u_access = acl_entry_link->entryp->ace_access;
3008 case SMB_ACL_GROUP_OBJ:
3009 file_acl->g_access = acl_entry_link->entryp->ace_access;
3012 file_acl->o_access = acl_entry_link->entryp->ace_access;
3018 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
3019 acl_length += sizeof(struct acl_entry);
3020 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
3021 if(file_acl_temp == NULL) {
3022 SAFE_FREE(file_acl);
3024 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
3028 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
3029 SAFE_FREE(file_acl);
3030 file_acl = file_acl_temp;
3033 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
3034 file_acl->acl_len += sizeof(struct acl_entry);
3035 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
3036 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
3038 /* In order to use this, we'll need to wait until we can get denies */
3039 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
3040 acl_entry->ace_type = ACC_SPECIFY; */
3042 acl_entry->ace_type = ACC_SPECIFY;
3044 ace_id = acl_entry->ace_id;
3046 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
3047 DEBUG(10,("The id type is %d\n",ace_id->id_type));
3048 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
3049 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
3050 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
3053 rc = fchacl(fd,file_acl,file_acl->acl_len);
3054 DEBUG(10,("errno is %d\n",errno));
3055 DEBUG(10,("return code is %d\n",rc));
3056 SAFE_FREE(file_acl);
3057 DEBUG(10,("Exiting sys_acl_set_fd\n"));
3061 int sys_acl_delete_def_file(const char *name)
3063 /* AIX has no default ACL */
3067 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3069 return(*permset & perm);
3072 int sys_acl_free_text(char *text)
3077 int sys_acl_free_acl(SMB_ACL_T posix_acl)
3079 struct acl_entry_link *acl_entry_link;
3081 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
3082 SAFE_FREE(acl_entry_link->prevp->entryp);
3083 SAFE_FREE(acl_entry_link->prevp);
3086 SAFE_FREE(acl_entry_link->prevp->entryp);
3087 SAFE_FREE(acl_entry_link->prevp);
3088 SAFE_FREE(acl_entry_link->entryp);
3089 SAFE_FREE(acl_entry_link);
3094 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3099 #else /* No ACLs. */
3101 int sys_acl_get_entry(UNUSED(SMB_ACL_T the_acl), UNUSED(int entry_id), UNUSED(SMB_ACL_ENTRY_T *entry_p))
3107 int sys_acl_get_tag_type(UNUSED(SMB_ACL_ENTRY_T entry_d), UNUSED(SMB_ACL_TAG_T *tag_type_p))
3113 int sys_acl_get_permset(UNUSED(SMB_ACL_ENTRY_T entry_d), UNUSED(SMB_ACL_PERMSET_T *permset_p))
3119 void *sys_acl_get_qualifier(UNUSED(SMB_ACL_ENTRY_T entry_d))
3125 SMB_ACL_T sys_acl_get_file(UNUSED(const char *path_p), UNUSED(SMB_ACL_TYPE_T type))
3128 return (SMB_ACL_T)NULL;
3131 SMB_ACL_T sys_acl_get_fd(UNUSED(int fd))
3134 return (SMB_ACL_T)NULL;
3137 int sys_acl_clear_perms(UNUSED(SMB_ACL_PERMSET_T permset))
3143 int sys_acl_add_perm( UNUSED(SMB_ACL_PERMSET_T permset), UNUSED(SMB_ACL_PERM_T perm))
3149 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3152 return (permset & perm) ? 1 : 0;
3155 char *sys_acl_to_text(UNUSED(SMB_ACL_T the_acl), UNUSED(ssize_t *plen))
3161 int sys_acl_free_text(UNUSED(char *text))
3167 SMB_ACL_T sys_acl_init(UNUSED(int count))
3173 int sys_acl_create_entry(UNUSED(SMB_ACL_T *pacl), UNUSED(SMB_ACL_ENTRY_T *pentry))
3179 int sys_acl_set_tag_type(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(SMB_ACL_TAG_T tagtype))
3185 int sys_acl_set_qualifier(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(void *qual))
3191 int sys_acl_set_permset(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(SMB_ACL_PERMSET_T permset))
3197 int sys_acl_valid(UNUSED(SMB_ACL_T theacl))
3203 int sys_acl_set_file(UNUSED(const char *name), UNUSED(SMB_ACL_TYPE_T acltype), UNUSED(SMB_ACL_T theacl))
3209 int sys_acl_set_fd(UNUSED(int fd), UNUSED(SMB_ACL_T theacl))
3215 int sys_acl_delete_def_file(UNUSED(const char *name))
3221 int sys_acl_free_acl(UNUSED(SMB_ACL_T the_acl))
3227 int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
3233 #endif /* No ACLs. */
3235 /************************************************************************
3236 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
3238 ************************************************************************/
3240 int no_acl_syscall_error(int err)
3243 if (err == ENOSYS) {
3247 #if defined(ENOTSUP)
3248 if (err == ENOTSUP) {
3255 #endif /* SUPPORT_ACLS */