2 Unix SMB/Netbios implementation.
4 Samba system utilities for ACL support.
5 Copyright (C) Jeremy Allison 2000.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file wraps all differing system ACL interfaces into a consistent
26 one based on the POSIX interface. It also returns the correct errors
27 for older UNIX systems that don't support ACLs.
29 The interfaces that each ACL implementation must support are as follows :
31 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
32 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
33 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p
34 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
35 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
36 SMB_ACL_T sys_acl_get_fd(int fd)
37 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset);
38 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
39 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
40 SMB_ACL_T sys_acl_init( int count)
41 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
42 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
43 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
44 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
45 int sys_acl_valid( SMB_ACL_T theacl )
46 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
47 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
48 int sys_acl_delete_def_file(const char *path)
50 This next one is not POSIX complient - but we *have* to have it !
51 More POSIX braindamage.
53 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
55 The generic POSIX free is the following call. We split this into
56 several different free functions as we may need to add tag info
57 to structures when emulating the POSIX interface.
59 int sys_acl_free( void *obj_p)
61 The calls we actually use are :
63 int sys_acl_free_text(char *text) - free acl_to_text
64 int sys_acl_free_acl(SMB_ACL_T posix_acl)
65 int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
69 #if defined(HAVE_POSIX_ACLS)
71 /* Identity mapping - easy. */
73 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
75 return acl_get_entry( the_acl, entry_id, entry_p);
78 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
80 return acl_get_tag_type( entry_d, tag_type_p);
83 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
85 return acl_get_permset( entry_d, permset_p);
88 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
90 return acl_get_qualifier( entry_d);
93 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
95 return acl_get_file( path_p, type);
98 SMB_ACL_T sys_acl_get_fd(int fd)
100 return acl_get_fd(fd);
103 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
105 return acl_clear_perms(permset);
108 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
110 return acl_add_perm(permset, perm);
113 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
115 #if defined(HAVE_ACL_GET_PERM_NP)
117 * Required for TrustedBSD-based ACL implementations where
118 * non-POSIX.1e functions are denoted by a _np (non-portable)
121 return acl_get_perm_np(permset, perm);
123 return acl_get_perm(permset, perm);
127 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
129 return acl_to_text( the_acl, plen);
132 SMB_ACL_T sys_acl_init( int count)
134 return acl_init(count);
137 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
139 return acl_create_entry(pacl, pentry);
142 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
144 return acl_set_tag_type(entry, tagtype);
147 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
149 return acl_set_qualifier(entry, qual);
152 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
154 return acl_set_permset(entry, permset);
157 int sys_acl_valid( SMB_ACL_T theacl )
159 return acl_valid(theacl);
162 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
164 return acl_set_file(name, acltype, theacl);
167 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
169 return acl_set_fd(fd, theacl);
172 int sys_acl_delete_def_file(const char *name)
174 return acl_delete_def_file(name);
177 int sys_acl_free_text(char *text)
179 return acl_free(text);
182 int sys_acl_free_acl(SMB_ACL_T the_acl)
184 return acl_free(the_acl);
187 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
189 return acl_free(qual);
192 #elif defined(HAVE_TRU64_ACLS)
194 * The interface to DEC/Compaq Tru64 UNIX ACLs
195 * is based on Draft 13 of the POSIX spec which is
196 * slightly different from the Draft 16 interface.
198 * Also, some of the permset manipulation functions
199 * such as acl_clear_perm() and acl_add_perm() appear
200 * to be broken on Tru64 so we have to manipulate
201 * the permission bits in the permset directly.
203 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
205 SMB_ACL_ENTRY_T entry;
207 if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
212 if ((entry = acl_get_entry(the_acl)) != NULL) {
217 return errno ? -1 : 0;
220 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
222 return acl_get_tag_type( entry_d, tag_type_p);
225 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
227 return acl_get_permset( entry_d, permset_p);
230 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
232 return acl_get_qualifier( entry_d);
235 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
237 return acl_get_file((char *)path_p, type);
240 SMB_ACL_T sys_acl_get_fd(int fd)
242 return acl_get_fd(fd, ACL_TYPE_ACCESS);
245 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
247 *permset = 0; /* acl_clear_perm() is broken on Tru64 */
252 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
254 if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) {
259 *permset |= perm; /* acl_add_perm() is broken on Tru64 */
264 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
266 return *permset & perm; /* Tru64 doesn't have acl_get_perm() */
269 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
271 return acl_to_text( the_acl, plen);
274 SMB_ACL_T sys_acl_init( int count)
276 return acl_init(count);
279 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
281 SMB_ACL_ENTRY_T entry;
283 if ((entry = acl_create_entry(pacl)) == NULL) {
291 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
293 return acl_set_tag_type(entry, tagtype);
296 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
298 return acl_set_qualifier(entry, qual);
301 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
303 return acl_set_permset(entry, permset);
306 int sys_acl_valid( SMB_ACL_T theacl )
310 return acl_valid(theacl, &entry);
313 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
315 return acl_set_file((char *)name, acltype, theacl);
318 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
320 return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
323 int sys_acl_delete_def_file(const char *name)
325 return acl_delete_def_file((char *)name);
328 int sys_acl_free_text(char *text)
331 * (void) cast and explicit return 0 are for DEC UNIX
332 * which just #defines acl_free_text() to be free()
334 (void) acl_free_text(text);
338 int sys_acl_free_acl(SMB_ACL_T the_acl)
340 return acl_free(the_acl);
343 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
345 return acl_free_qualifier(qual, tagtype);
348 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
351 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
352 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
356 * Note that while this code implements sufficient functionality
357 * to support the sys_acl_* interfaces it does not provide all
358 * of the semantics of the POSIX ACL interfaces.
360 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
361 * from a call to sys_acl_get_entry() should not be assumed to be
362 * valid after calling any of the following functions, which may
363 * reorder the entries in the ACL.
371 * The only difference between Solaris and UnixWare / OpenUNIX is
372 * that the #defines for the ACL operations have different names
374 #if defined(HAVE_UNIXWARE_ACLS)
376 #define SETACL ACL_SET
377 #define GETACL ACL_GET
378 #define GETACLCNT ACL_CNT
383 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
385 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
390 if (entry_p == NULL) {
395 if (entry_id == SMB_ACL_FIRST_ENTRY) {
399 if (acl_d->next < 0) {
404 if (acl_d->next >= acl_d->count) {
408 *entry_p = &acl_d->acl[acl_d->next++];
413 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
415 *type_p = entry_d->a_type;
420 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
422 *permset_p = &entry_d->a_perm;
427 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
429 if (entry_d->a_type != SMB_ACL_USER
430 && entry_d->a_type != SMB_ACL_GROUP) {
435 return &entry_d->a_id;
439 * There is no way of knowing what size the ACL returned by
440 * GETACL will be unless you first call GETACLCNT which means
441 * making an additional system call.
443 * In the hope of avoiding the cost of the additional system
444 * call in most cases, we initially allocate enough space for
445 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
446 * be too small then we use GETACLCNT to find out the actual
447 * size, reallocate the ACL buffer, and then call GETACL again.
450 #define INITIAL_ACL_SIZE 16
452 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
455 int count; /* # of ACL entries allocated */
456 int naccess; /* # of access ACL entries */
457 int ndefault; /* # of default ACL entries */
459 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
464 count = INITIAL_ACL_SIZE;
465 if ((acl_d = sys_acl_init(count)) == NULL) {
470 * If there isn't enough space for the ACL entries we use
471 * GETACLCNT to determine the actual number of ACL entries
472 * reallocate and try again. This is in a loop because it
473 * is possible that someone else could modify the ACL and
474 * increase the number of entries between the call to
475 * GETACLCNT and the call to GETACL.
477 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
478 && errno == ENOSPC) {
480 sys_acl_free_acl(acl_d);
482 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
486 if ((acl_d = sys_acl_init(count)) == NULL) {
492 sys_acl_free_acl(acl_d);
497 * calculate the number of access and default ACL entries
499 * Note: we assume that the acl() system call returned a
500 * well formed ACL which is sorted so that all of the
501 * access ACL entries preceed any default ACL entries
503 for (naccess = 0; naccess < count; naccess++) {
504 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
507 ndefault = count - naccess;
510 * if the caller wants the default ACL we have to copy
511 * the entries down to the start of the acl[] buffer
512 * and mask out the ACL_DEFAULT flag from the type field
514 if (type == SMB_ACL_TYPE_DEFAULT) {
517 for (i = 0, j = naccess; i < ndefault; i++, j++) {
518 acl_d->acl[i] = acl_d->acl[j];
519 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
522 acl_d->count = ndefault;
524 acl_d->count = naccess;
530 SMB_ACL_T sys_acl_get_fd(int fd)
533 int count; /* # of ACL entries allocated */
534 int naccess; /* # of access ACL entries */
536 count = INITIAL_ACL_SIZE;
537 if ((acl_d = sys_acl_init(count)) == NULL) {
541 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
542 && errno == ENOSPC) {
544 sys_acl_free_acl(acl_d);
546 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
550 if ((acl_d = sys_acl_init(count)) == NULL) {
556 sys_acl_free_acl(acl_d);
561 * calculate the number of access ACL entries
563 for (naccess = 0; naccess < count; naccess++) {
564 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
568 acl_d->count = naccess;
573 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
580 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
582 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
583 && perm != SMB_ACL_EXECUTE) {
588 if (permset_d == NULL) {
598 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
600 return *permset_d & perm;
603 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
610 * use an initial estimate of 20 bytes per ACL entry
611 * when allocating memory for the text representation
615 maxlen = 20 * acl_d->count;
616 if ((text = malloc(maxlen)) == NULL) {
621 for (i = 0; i < acl_d->count; i++) {
622 struct acl *ap = &acl_d->acl[i];
632 switch (ap->a_type) {
634 * for debugging purposes it's probably more
635 * useful to dump unknown tag types rather
636 * than just returning an error
639 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
642 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
648 if ((pw = sys_getpwuid(ap->a_id)) == NULL) {
649 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
655 case SMB_ACL_USER_OBJ:
660 if ((gr = getgrgid(ap->a_id)) == NULL) {
661 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
667 case SMB_ACL_GROUP_OBJ:
681 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
682 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
683 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
686 /* <tag> : <qualifier> : rwx \n \0 */
687 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
690 * If this entry would overflow the buffer
691 * allocate enough additional memory for this
692 * entry and an estimate of another 20 bytes
693 * for each entry still to be processed
695 if ((len + nbytes) > maxlen) {
696 char *oldtext = text;
698 maxlen += nbytes + 20 * (acl_d->count - i);
700 if ((text = Realloc(oldtext, maxlen)) == NULL) {
707 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
717 SMB_ACL_T sys_acl_init(int count)
727 * note that since the definition of the structure pointed
728 * to by the SMB_ACL_T includes the first element of the
729 * acl[] array, this actually allocates an ACL with room
730 * for (count+1) entries
732 if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) {
745 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
748 SMB_ACL_ENTRY_T entry_d;
750 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
755 if (acl_d->count >= acl_d->size) {
760 entry_d = &acl_d->acl[acl_d->count++];
769 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
773 case SMB_ACL_USER_OBJ:
775 case SMB_ACL_GROUP_OBJ:
778 entry_d->a_type = tag_type;
788 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
790 if (entry_d->a_type != SMB_ACL_GROUP
791 && entry_d->a_type != SMB_ACL_USER) {
796 entry_d->a_id = *((id_t *)qual_p);
801 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
803 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
807 entry_d->a_perm = *permset_d;
813 * sort the ACL and check it for validity
815 * if it's a minimal ACL with only 4 entries then we
816 * need to recalculate the mask permissions to make
817 * sure that they are the same as the GROUP_OBJ
818 * permissions as required by the UnixWare acl() system call.
820 * (note: since POSIX allows minimal ACLs which only contain
821 * 3 entries - ie there is no mask entry - we should, in theory,
822 * check for this and add a mask entry if necessary - however
823 * we "know" that the caller of this interface always specifies
824 * a mask so, in practice "this never happens" (tm) - if it *does*
825 * happen aclsort() will fail and return an error and someone will
826 * have to fix it ...)
829 static int acl_sort(SMB_ACL_T acl_d)
831 int fixmask = (acl_d->count <= 4);
833 if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
840 int sys_acl_valid(SMB_ACL_T acl_d)
842 return acl_sort(acl_d);
845 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
850 struct acl *acl_buf = NULL;
853 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
858 if (acl_sort(acl_d) != 0) {
862 acl_p = &acl_d->acl[0];
863 acl_count = acl_d->count;
866 * if it's a directory there is extra work to do
867 * since the acl() system call will replace both
868 * the access ACLs and the default ACLs (if any)
870 if (stat(name, &s) != 0) {
873 if (S_ISDIR(s.st_mode)) {
879 if (type == SMB_ACL_TYPE_ACCESS) {
881 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
885 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
888 if (tmp_acl == NULL) {
893 * allocate a temporary buffer for the complete ACL
895 acl_count = acc_acl->count + def_acl->count;
896 acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0]));
898 if (acl_buf == NULL) {
899 sys_acl_free_acl(tmp_acl);
905 * copy the access control and default entries into the buffer
907 memcpy(&acl_buf[0], &acc_acl->acl[0],
908 acc_acl->count * sizeof(acl_buf[0]));
910 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
911 def_acl->count * sizeof(acl_buf[0]));
914 * set the ACL_DEFAULT flag on the default entries
916 for (i = acc_acl->count; i < acl_count; i++) {
917 acl_buf[i].a_type |= ACL_DEFAULT;
920 sys_acl_free_acl(tmp_acl);
922 } else if (type != SMB_ACL_TYPE_ACCESS) {
927 ret = acl(name, SETACL, acl_count, acl_p);
934 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
936 if (acl_sort(acl_d) != 0) {
940 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
943 int sys_acl_delete_def_file(const char *path)
949 * fetching the access ACL and rewriting it has
950 * the effect of deleting the default ACL
952 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
956 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
958 sys_acl_free_acl(acl_d);
963 int sys_acl_free_text(char *text)
969 int sys_acl_free_acl(SMB_ACL_T acl_d)
975 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
980 #elif defined(HAVE_HPUX_ACLS)
984 * Based on the Solaris/SCO code - with modifications.
988 * Note that while this code implements sufficient functionality
989 * to support the sys_acl_* interfaces it does not provide all
990 * of the semantics of the POSIX ACL interfaces.
992 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
993 * from a call to sys_acl_get_entry() should not be assumed to be
994 * valid after calling any of the following functions, which may
995 * reorder the entries in the ACL.
1002 /* This checks if the POSIX ACL system call is defined */
1003 /* which basically corresponds to whether JFS 3.3 or */
1004 /* higher is installed. If acl() was called when it */
1005 /* isn't defined, it causes the process to core dump */
1006 /* so it is important to check this and avoid acl() */
1007 /* calls if it isn't there. */
1009 static BOOL hpux_acl_call_presence(void)
1012 shl_t handle = NULL;
1015 static BOOL already_checked=0;
1021 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
1024 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
1025 ret_val, errno, strerror(errno)));
1026 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
1030 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
1032 already_checked = True;
1036 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1038 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1043 if (entry_p == NULL) {
1048 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1052 if (acl_d->next < 0) {
1057 if (acl_d->next >= acl_d->count) {
1061 *entry_p = &acl_d->acl[acl_d->next++];
1066 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1068 *type_p = entry_d->a_type;
1073 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1075 *permset_p = &entry_d->a_perm;
1080 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1082 if (entry_d->a_type != SMB_ACL_USER
1083 && entry_d->a_type != SMB_ACL_GROUP) {
1088 return &entry_d->a_id;
1092 * There is no way of knowing what size the ACL returned by
1093 * ACL_GET will be unless you first call ACL_CNT which means
1094 * making an additional system call.
1096 * In the hope of avoiding the cost of the additional system
1097 * call in most cases, we initially allocate enough space for
1098 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
1099 * be too small then we use ACL_CNT to find out the actual
1100 * size, reallocate the ACL buffer, and then call ACL_GET again.
1103 #define INITIAL_ACL_SIZE 16
1105 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1108 int count; /* # of ACL entries allocated */
1109 int naccess; /* # of access ACL entries */
1110 int ndefault; /* # of default ACL entries */
1112 if(hpux_acl_call_presence() == False) {
1113 /* Looks like we don't have the acl() system call on HPUX.
1114 * May be the system doesn't have the latest version of JFS.
1119 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1124 count = INITIAL_ACL_SIZE;
1125 if ((acl_d = sys_acl_init(count)) == NULL) {
1130 * If there isn't enough space for the ACL entries we use
1131 * ACL_CNT to determine the actual number of ACL entries
1132 * reallocate and try again. This is in a loop because it
1133 * is possible that someone else could modify the ACL and
1134 * increase the number of entries between the call to
1135 * ACL_CNT and the call to ACL_GET.
1137 while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
1139 sys_acl_free_acl(acl_d);
1141 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
1145 if ((acl_d = sys_acl_init(count)) == NULL) {
1151 sys_acl_free_acl(acl_d);
1156 * calculate the number of access and default ACL entries
1158 * Note: we assume that the acl() system call returned a
1159 * well formed ACL which is sorted so that all of the
1160 * access ACL entries preceed any default ACL entries
1162 for (naccess = 0; naccess < count; naccess++) {
1163 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
1166 ndefault = count - naccess;
1169 * if the caller wants the default ACL we have to copy
1170 * the entries down to the start of the acl[] buffer
1171 * and mask out the ACL_DEFAULT flag from the type field
1173 if (type == SMB_ACL_TYPE_DEFAULT) {
1176 for (i = 0, j = naccess; i < ndefault; i++, j++) {
1177 acl_d->acl[i] = acl_d->acl[j];
1178 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
1181 acl_d->count = ndefault;
1183 acl_d->count = naccess;
1189 SMB_ACL_T sys_acl_get_fd(int fd)
1192 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1195 files_struct *fsp = file_find_fd(fd);
1203 * We know we're in the same conn context. So we
1204 * can use the relative path.
1207 return sys_acl_get_file(dos_to_unix(fsp->fsp_name,False), SMB_ACL_TYPE_ACCESS);
1210 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
1217 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1219 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
1220 && perm != SMB_ACL_EXECUTE) {
1225 if (permset_d == NULL) {
1235 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1237 return *permset_d & perm;
1240 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
1247 * use an initial estimate of 20 bytes per ACL entry
1248 * when allocating memory for the text representation
1252 maxlen = 20 * acl_d->count;
1253 if ((text = malloc(maxlen)) == NULL) {
1258 for (i = 0; i < acl_d->count; i++) {
1259 struct acl *ap = &acl_d->acl[i];
1269 switch (ap->a_type) {
1271 * for debugging purposes it's probably more
1272 * useful to dump unknown tag types rather
1273 * than just returning an error
1276 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
1279 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1285 if ((pw = sys_getpwuid(ap->a_id)) == NULL) {
1286 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1292 case SMB_ACL_USER_OBJ:
1297 if ((gr = getgrgid(ap->a_id)) == NULL) {
1298 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1304 case SMB_ACL_GROUP_OBJ:
1318 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
1319 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
1320 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
1323 /* <tag> : <qualifier> : rwx \n \0 */
1324 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
1327 * If this entry would overflow the buffer
1328 * allocate enough additional memory for this
1329 * entry and an estimate of another 20 bytes
1330 * for each entry still to be processed
1332 if ((len + nbytes) > maxlen) {
1333 char *oldtext = text;
1335 maxlen += nbytes + 20 * (acl_d->count - i);
1337 if ((text = Realloc(oldtext, maxlen)) == NULL) {
1344 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
1354 SMB_ACL_T sys_acl_init(int count)
1364 * note that since the definition of the structure pointed
1365 * to by the SMB_ACL_T includes the first element of the
1366 * acl[] array, this actually allocates an ACL with room
1367 * for (count+1) entries
1369 if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) {
1374 a->size = count + 1;
1382 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1385 SMB_ACL_ENTRY_T entry_d;
1387 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1392 if (acl_d->count >= acl_d->size) {
1397 entry_d = &acl_d->acl[acl_d->count++];
1398 entry_d->a_type = 0;
1400 entry_d->a_perm = 0;
1406 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1410 case SMB_ACL_USER_OBJ:
1412 case SMB_ACL_GROUP_OBJ:
1415 entry_d->a_type = tag_type;
1425 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1427 if (entry_d->a_type != SMB_ACL_GROUP
1428 && entry_d->a_type != SMB_ACL_USER) {
1433 entry_d->a_id = *((id_t *)qual_p);
1438 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1440 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1444 entry_d->a_perm = *permset_d;
1449 /* Structure to capture the count for each type of ACE. */
1451 struct hpux_acl_types {
1460 int n_def_group_obj;
1464 int n_def_other_obj;
1467 int n_def_class_obj;
1473 * Counts the different number of objects in a given array of ACL
1477 * acl_count - Count of ACLs in the array of ACL strucutres.
1478 * aclp - Array of ACL structures.
1479 * acl_type_count - Pointer to acl_types structure. Should already be
1483 * acl_type_count - This structure is filled up with counts of various
1487 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1491 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1493 for(i=0;i<acl_count;i++) {
1494 switch(aclp[i].a_type) {
1496 acl_type_count->n_user++;
1499 acl_type_count->n_user_obj++;
1502 acl_type_count->n_def_user_obj++;
1505 acl_type_count->n_group++;
1508 acl_type_count->n_group_obj++;
1511 acl_type_count->n_def_group_obj++;
1514 acl_type_count->n_other_obj++;
1517 acl_type_count->n_def_other_obj++;
1520 acl_type_count->n_class_obj++;
1523 acl_type_count->n_def_class_obj++;
1526 acl_type_count->n_def_user++;
1529 acl_type_count->n_def_group++;
1532 acl_type_count->n_illegal_obj++;
1538 /* swap_acl_entries: Swaps two ACL entries.
1540 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1543 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1545 struct acl temp_acl;
1547 temp_acl.a_type = aclp0->a_type;
1548 temp_acl.a_id = aclp0->a_id;
1549 temp_acl.a_perm = aclp0->a_perm;
1551 aclp0->a_type = aclp1->a_type;
1552 aclp0->a_id = aclp1->a_id;
1553 aclp0->a_perm = aclp1->a_perm;
1555 aclp1->a_type = temp_acl.a_type;
1556 aclp1->a_id = temp_acl.a_id;
1557 aclp1->a_perm = temp_acl.a_perm;
1560 /* prohibited_duplicate_type
1561 * Identifies if given ACL type can have duplicate entries or
1564 * Inputs: acl_type - ACL Type.
1570 * True - If the ACL type matches any of the prohibited types.
1571 * False - If the ACL type doesn't match any of the prohibited types.
1574 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1587 /* get_needed_class_perm
1588 * Returns the permissions of a ACL structure only if the ACL
1589 * type matches one of the pre-determined types for computing
1590 * CLASS_OBJ permissions.
1592 * Inputs: aclp - Pointer to ACL structure.
1595 static int hpux_get_needed_class_perm(struct acl *aclp)
1597 switch(aclp->a_type) {
1607 return aclp->a_perm;
1613 /* acl_sort for HPUX.
1614 * Sorts the array of ACL structures as per the description in
1615 * aclsort man page. Refer to aclsort man page for more details
1619 * acl_count - Count of ACLs in the array of ACL structures.
1620 * calclass - If this is not zero, then we compute the CLASS_OBJ
1622 * aclp - Array of ACL structures.
1626 * aclp - Sorted array of ACL structures.
1630 * Returns 0 for success -1 for failure. Prints a message to the Samba
1631 * debug log in case of failure.
1634 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1636 #if !defined(HAVE_HPUX_ACLSORT)
1638 * The aclsort() system call is availabe on the latest HPUX General
1639 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1640 * function. Because, we don't want to update to a new
1641 * HPUX GR bundle just for aclsort() call.
1644 struct hpux_acl_types acl_obj_count;
1645 int n_class_obj_perm = 0;
1649 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1654 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1658 /* Count different types of ACLs in the ACLs array */
1660 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1662 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1663 * CLASS_OBJ and OTHER_OBJ
1666 if( (acl_obj_count.n_user_obj != 1) ||
1667 (acl_obj_count.n_group_obj != 1) ||
1668 (acl_obj_count.n_class_obj != 1) ||
1669 (acl_obj_count.n_other_obj != 1)
1671 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1672 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1676 /* If any of the default objects are present, there should be only
1680 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1681 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1682 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1683 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1687 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1690 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1691 * same ACL type, sort by ACL id.
1693 * I am using the trival kind of sorting method here because, performance isn't
1694 * really effected by the ACLs feature. More over there aren't going to be more
1695 * than 17 entries on HPUX.
1698 for(i=0; i<acl_count;i++) {
1699 for (j=i+1; j<acl_count; j++) {
1700 if( aclp[i].a_type > aclp[j].a_type ) {
1701 /* ACL entries out of order, swap them */
1703 hpux_swap_acl_entries((aclp+i), (aclp+j));
1705 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1707 /* ACL entries of same type, sort by id */
1709 if(aclp[i].a_id > aclp[j].a_id) {
1710 hpux_swap_acl_entries((aclp+i), (aclp+j));
1711 } else if (aclp[i].a_id == aclp[j].a_id) {
1712 /* We have a duplicate entry. */
1713 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1714 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1715 aclp[i].a_type, aclp[i].a_id));
1724 /* set the class obj permissions to the computed one. */
1726 int n_class_obj_index = -1;
1728 for(i=0;i<acl_count;i++) {
1729 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1731 if(aclp[i].a_type == CLASS_OBJ)
1732 n_class_obj_index = i;
1734 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1739 return aclsort(acl_count, calclass, aclp);
1744 * sort the ACL and check it for validity
1746 * if it's a minimal ACL with only 4 entries then we
1747 * need to recalculate the mask permissions to make
1748 * sure that they are the same as the GROUP_OBJ
1749 * permissions as required by the UnixWare acl() system call.
1751 * (note: since POSIX allows minimal ACLs which only contain
1752 * 3 entries - ie there is no mask entry - we should, in theory,
1753 * check for this and add a mask entry if necessary - however
1754 * we "know" that the caller of this interface always specifies
1755 * a mask so, in practice "this never happens" (tm) - if it *does*
1756 * happen aclsort() will fail and return an error and someone will
1757 * have to fix it ...)
1760 static int acl_sort(SMB_ACL_T acl_d)
1762 int fixmask = (acl_d->count <= 4);
1764 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1771 int sys_acl_valid(SMB_ACL_T acl_d)
1773 return acl_sort(acl_d);
1776 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1781 struct acl *acl_buf = NULL;
1784 if(hpux_acl_call_presence() == False) {
1785 /* Looks like we don't have the acl() system call on HPUX.
1786 * May be the system doesn't have the latest version of JFS.
1792 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1797 if (acl_sort(acl_d) != 0) {
1801 acl_p = &acl_d->acl[0];
1802 acl_count = acl_d->count;
1805 * if it's a directory there is extra work to do
1806 * since the acl() system call will replace both
1807 * the access ACLs and the default ACLs (if any)
1809 if (stat(name, &s) != 0) {
1812 if (S_ISDIR(s.st_mode)) {
1818 if (type == SMB_ACL_TYPE_ACCESS) {
1820 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1824 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1827 if (tmp_acl == NULL) {
1832 * allocate a temporary buffer for the complete ACL
1834 acl_count = acc_acl->count + def_acl->count;
1835 acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0]));
1837 if (acl_buf == NULL) {
1838 sys_acl_free_acl(tmp_acl);
1844 * copy the access control and default entries into the buffer
1846 memcpy(&acl_buf[0], &acc_acl->acl[0],
1847 acc_acl->count * sizeof(acl_buf[0]));
1849 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1850 def_acl->count * sizeof(acl_buf[0]));
1853 * set the ACL_DEFAULT flag on the default entries
1855 for (i = acc_acl->count; i < acl_count; i++) {
1856 acl_buf[i].a_type |= ACL_DEFAULT;
1859 sys_acl_free_acl(tmp_acl);
1861 } else if (type != SMB_ACL_TYPE_ACCESS) {
1866 ret = acl(name, ACL_SET, acl_count, acl_p);
1875 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1878 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1881 files_struct *fsp = file_find_fd(fd);
1888 if (acl_sort(acl_d) != 0) {
1893 * We know we're in the same conn context. So we
1894 * can use the relative path.
1897 return sys_acl_set_file(dos_to_unix(fsp->fsp_name,False), SMB_ACL_TYPE_ACCESS, acl_d);
1900 int sys_acl_delete_def_file(const char *path)
1906 * fetching the access ACL and rewriting it has
1907 * the effect of deleting the default ACL
1909 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1913 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1915 sys_acl_free_acl(acl_d);
1920 int sys_acl_free_text(char *text)
1926 int sys_acl_free_acl(SMB_ACL_T acl_d)
1932 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1937 #elif defined(HAVE_IRIX_ACLS)
1939 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1941 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1946 if (entry_p == NULL) {
1951 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1955 if (acl_d->next < 0) {
1960 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1964 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1969 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1971 *type_p = entry_d->ae_tag;
1976 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1978 *permset_p = entry_d;
1983 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1985 if (entry_d->ae_tag != SMB_ACL_USER
1986 && entry_d->ae_tag != SMB_ACL_GROUP) {
1991 return &entry_d->ae_id;
1994 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1998 if ((a = malloc(sizeof(*a))) == NULL) {
2002 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
2011 SMB_ACL_T sys_acl_get_fd(int fd)
2015 if ((a = malloc(sizeof(*a))) == NULL) {
2019 if ((a->aclp = acl_get_fd(fd)) == NULL) {
2028 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
2030 permset_d->ae_perm = 0;
2035 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2037 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
2038 && perm != SMB_ACL_EXECUTE) {
2043 if (permset_d == NULL) {
2048 permset_d->ae_perm |= perm;
2053 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2055 return permset_d->ae_perm & perm;
2058 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
2060 return acl_to_text(acl_d->aclp, len_p);
2063 SMB_ACL_T sys_acl_init(int count)
2072 if ((a = malloc(sizeof(*a) + sizeof(struct acl))) == NULL) {
2078 a->freeaclp = False;
2079 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
2080 a->aclp->acl_cnt = 0;
2086 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
2089 SMB_ACL_ENTRY_T entry_d;
2091 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
2096 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
2101 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
2102 entry_d->ae_tag = 0;
2104 entry_d->ae_perm = 0;
2110 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
2114 case SMB_ACL_USER_OBJ:
2116 case SMB_ACL_GROUP_OBJ:
2119 entry_d->ae_tag = tag_type;
2129 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
2131 if (entry_d->ae_tag != SMB_ACL_GROUP
2132 && entry_d->ae_tag != SMB_ACL_USER) {
2137 entry_d->ae_id = *((id_t *)qual_p);
2142 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
2144 if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
2148 entry_d->ae_perm = permset_d->ae_perm;
2153 int sys_acl_valid(SMB_ACL_T acl_d)
2155 return acl_valid(acl_d->aclp);
2158 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
2160 return acl_set_file(name, type, acl_d->aclp);
2163 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
2165 return acl_set_fd(fd, acl_d->aclp);
2168 int sys_acl_delete_def_file(const char *name)
2170 return acl_delete_def_file(name);
2173 int sys_acl_free_text(char *text)
2175 return acl_free(text);
2178 int sys_acl_free_acl(SMB_ACL_T acl_d)
2180 if (acl_d->freeaclp) {
2181 acl_free(acl_d->aclp);
2187 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2192 #elif defined(HAVE_AIX_ACLS)
2194 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
2196 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2198 struct acl_entry_link *link;
2199 struct new_acl_entry *entry;
2202 DEBUG(10,("This is the count: %d\n",theacl->count));
2204 /* Check if count was previously set to -1. *
2205 * If it was, that means we reached the end *
2206 * of the acl last time. */
2207 if(theacl->count == -1)
2211 /* To get to the next acl, traverse linked list until index *
2212 * of acl matches the count we are keeping. This count is *
2213 * incremented each time we return an acl entry. */
2215 for(keep_going = 0; keep_going < theacl->count; keep_going++)
2218 entry = *entry_p = link->entryp;
2220 DEBUG(10,("*entry_p is %d\n",entry_p));
2221 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
2223 /* Increment count */
2225 if(link->nextp == NULL)
2231 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2233 /* Initialize tag type */
2236 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
2238 /* Depending on what type of entry we have, *
2239 * return tag type. */
2240 switch(entry_d->ace_id->id_type) {
2242 *tag_type_p = SMB_ACL_USER;
2245 *tag_type_p = SMB_ACL_GROUP;
2248 case SMB_ACL_USER_OBJ:
2249 case SMB_ACL_GROUP_OBJ:
2251 *tag_type_p = entry_d->ace_id->id_type;
2261 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2263 DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
2264 *permset_p = &entry_d->ace_access;
2265 DEBUG(10,("**permset_p is %d\n",**permset_p));
2266 if(!(**permset_p & S_IXUSR) &&
2267 !(**permset_p & S_IWUSR) &&
2268 !(**permset_p & S_IRUSR) &&
2272 DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
2276 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2278 return(entry_d->ace_id->id_data);
2281 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2283 struct acl *file_acl = (struct acl *)NULL;
2284 struct acl_entry *acl_entry;
2285 struct new_acl_entry *new_acl_entry;
2287 struct acl_entry_link *acl_entry_link;
2288 struct acl_entry_link *acl_entry_link_head;
2293 /* Get the acl using statacl */
2295 DEBUG(10,("Entering sys_acl_get_file\n"));
2296 DEBUG(10,("path_p is %s\n",path_p));
2298 file_acl = (struct acl *)malloc(BUFSIZ);
2300 if(file_acl == NULL) {
2302 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
2306 memset(file_acl,0,BUFSIZ);
2308 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
2310 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
2311 SAFE_FREE(file_acl);
2315 DEBUG(10,("Got facl and returned it\n"));
2317 /* Point to the first acl entry in the acl */
2318 acl_entry = file_acl->acl_ext;
2320 /* Begin setting up the head of the linked list *
2321 * that will be used for the storing the acl *
2322 * in a way that is useful for the posix_acls.c *
2325 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2326 if(acl_entry_link_head == NULL)
2329 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2330 if(acl_entry_link->entryp == NULL) {
2331 SAFE_FREE(file_acl);
2333 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2337 DEBUG(10,("acl_entry is %d\n",acl_entry));
2338 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2340 /* Check if the extended acl bit is on. *
2341 * If it isn't, do not show the *
2342 * contents of the acl since AIX intends *
2343 * the extended info to remain unused */
2345 if(file_acl->acl_mode & S_IXACL){
2346 /* while we are not pointing to the very end */
2347 while(acl_entry < acl_last(file_acl)) {
2348 /* before we malloc anything, make sure this is */
2349 /* a valid acl entry and one that we want to map */
2350 idp = id_nxt(acl_entry->ace_id);
2351 if((acl_entry->ace_type == ACC_SPECIFY ||
2352 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2353 acl_entry = acl_nxt(acl_entry);
2357 idp = acl_entry->ace_id;
2359 /* Check if this is the first entry in the linked list. *
2360 * The first entry needs to keep prevp pointing to NULL *
2361 * and already has entryp allocated. */
2363 if(acl_entry_link_head->count != 0) {
2364 acl_entry_link->nextp = (struct acl_entry_link *)
2365 malloc(sizeof(struct acl_entry_link));
2367 if(acl_entry_link->nextp == NULL) {
2368 SAFE_FREE(file_acl);
2370 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2374 acl_entry_link->nextp->prevp = acl_entry_link;
2375 acl_entry_link = acl_entry_link->nextp;
2376 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2377 if(acl_entry_link->entryp == NULL) {
2378 SAFE_FREE(file_acl);
2380 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2383 acl_entry_link->nextp = NULL;
2386 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2388 /* Don't really need this since all types are going *
2389 * to be specified but, it's better than leaving it 0 */
2391 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2393 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2395 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2397 /* The access in the acl entries must be left shifted by *
2398 * three bites, because they will ultimately be compared *
2399 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2401 switch(acl_entry->ace_type){
2404 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2405 acl_entry_link->entryp->ace_access <<= 6;
2406 acl_entry_link_head->count++;
2409 /* Since there is no way to return a DENY acl entry *
2410 * change to PERMIT and then shift. */
2411 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2412 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2413 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2414 acl_entry_link->entryp->ace_access <<= 6;
2415 acl_entry_link_head->count++;
2421 DEBUG(10,("acl_entry = %d\n",acl_entry));
2422 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2424 acl_entry = acl_nxt(acl_entry);
2426 } /* end of if enabled */
2428 /* Since owner, group, other acl entries are not *
2429 * part of the acl entries in an acl, they must *
2430 * be dummied up to become part of the list. */
2432 for( i = 1; i < 4; i++) {
2433 DEBUG(10,("i is %d\n",i));
2434 if(acl_entry_link_head->count != 0) {
2435 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
2436 if(acl_entry_link->nextp == NULL) {
2437 SAFE_FREE(file_acl);
2439 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2443 acl_entry_link->nextp->prevp = acl_entry_link;
2444 acl_entry_link = acl_entry_link->nextp;
2445 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2446 if(acl_entry_link->entryp == NULL) {
2447 SAFE_FREE(file_acl);
2449 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2454 acl_entry_link->nextp = NULL;
2456 new_acl_entry = acl_entry_link->entryp;
2457 idp = new_acl_entry->ace_id;
2459 new_acl_entry->ace_len = sizeof(struct acl_entry);
2460 new_acl_entry->ace_type = ACC_PERMIT;
2461 idp->id_len = sizeof(struct ace_id);
2462 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2463 memset(idp->id_data,0,sizeof(uid_t));
2467 new_acl_entry->ace_access = file_acl->g_access << 6;
2468 idp->id_type = SMB_ACL_GROUP_OBJ;
2472 new_acl_entry->ace_access = file_acl->o_access << 6;
2473 idp->id_type = SMB_ACL_OTHER;
2477 new_acl_entry->ace_access = file_acl->u_access << 6;
2478 idp->id_type = SMB_ACL_USER_OBJ;
2486 acl_entry_link_head->count++;
2487 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2490 acl_entry_link_head->count = 0;
2491 SAFE_FREE(file_acl);
2493 return(acl_entry_link_head);
2496 SMB_ACL_T sys_acl_get_fd(int fd)
2498 struct acl *file_acl = (struct acl *)NULL;
2499 struct acl_entry *acl_entry;
2500 struct new_acl_entry *new_acl_entry;
2502 struct acl_entry_link *acl_entry_link;
2503 struct acl_entry_link *acl_entry_link_head;
2508 /* Get the acl using fstatacl */
2510 DEBUG(10,("Entering sys_acl_get_fd\n"));
2511 DEBUG(10,("fd is %d\n",fd));
2512 file_acl = (struct acl *)malloc(BUFSIZ);
2514 if(file_acl == NULL) {
2516 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2520 memset(file_acl,0,BUFSIZ);
2522 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2524 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2525 SAFE_FREE(file_acl);
2529 DEBUG(10,("Got facl and returned it\n"));
2531 /* Point to the first acl entry in the acl */
2533 acl_entry = file_acl->acl_ext;
2534 /* Begin setting up the head of the linked list *
2535 * that will be used for the storing the acl *
2536 * in a way that is useful for the posix_acls.c *
2539 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2540 if(acl_entry_link_head == NULL){
2541 SAFE_FREE(file_acl);
2545 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2547 if(acl_entry_link->entryp == NULL) {
2549 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2550 SAFE_FREE(file_acl);
2554 DEBUG(10,("acl_entry is %d\n",acl_entry));
2555 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2557 /* Check if the extended acl bit is on. *
2558 * If it isn't, do not show the *
2559 * contents of the acl since AIX intends *
2560 * the extended info to remain unused */
2562 if(file_acl->acl_mode & S_IXACL){
2563 /* while we are not pointing to the very end */
2564 while(acl_entry < acl_last(file_acl)) {
2565 /* before we malloc anything, make sure this is */
2566 /* a valid acl entry and one that we want to map */
2568 idp = id_nxt(acl_entry->ace_id);
2569 if((acl_entry->ace_type == ACC_SPECIFY ||
2570 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2571 acl_entry = acl_nxt(acl_entry);
2575 idp = acl_entry->ace_id;
2577 /* Check if this is the first entry in the linked list. *
2578 * The first entry needs to keep prevp pointing to NULL *
2579 * and already has entryp allocated. */
2581 if(acl_entry_link_head->count != 0) {
2582 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
2583 if(acl_entry_link->nextp == NULL) {
2585 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2586 SAFE_FREE(file_acl);
2589 acl_entry_link->nextp->prevp = acl_entry_link;
2590 acl_entry_link = acl_entry_link->nextp;
2591 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2592 if(acl_entry_link->entryp == NULL) {
2594 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2595 SAFE_FREE(file_acl);
2599 acl_entry_link->nextp = NULL;
2602 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2604 /* Don't really need this since all types are going *
2605 * to be specified but, it's better than leaving it 0 */
2607 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2608 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2610 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2612 /* The access in the acl entries must be left shifted by *
2613 * three bites, because they will ultimately be compared *
2614 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2616 switch(acl_entry->ace_type){
2619 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2620 acl_entry_link->entryp->ace_access <<= 6;
2621 acl_entry_link_head->count++;
2624 /* Since there is no way to return a DENY acl entry *
2625 * change to PERMIT and then shift. */
2626 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2627 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2628 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2629 acl_entry_link->entryp->ace_access <<= 6;
2630 acl_entry_link_head->count++;
2636 DEBUG(10,("acl_entry = %d\n",acl_entry));
2637 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2639 acl_entry = acl_nxt(acl_entry);
2641 } /* end of if enabled */
2643 /* Since owner, group, other acl entries are not *
2644 * part of the acl entries in an acl, they must *
2645 * be dummied up to become part of the list. */
2647 for( i = 1; i < 4; i++) {
2648 DEBUG(10,("i is %d\n",i));
2649 if(acl_entry_link_head->count != 0){
2650 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
2651 if(acl_entry_link->nextp == NULL) {
2653 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2654 SAFE_FREE(file_acl);
2658 acl_entry_link->nextp->prevp = acl_entry_link;
2659 acl_entry_link = acl_entry_link->nextp;
2660 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2662 if(acl_entry_link->entryp == NULL) {
2663 SAFE_FREE(file_acl);
2665 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2670 acl_entry_link->nextp = NULL;
2672 new_acl_entry = acl_entry_link->entryp;
2673 idp = new_acl_entry->ace_id;
2675 new_acl_entry->ace_len = sizeof(struct acl_entry);
2676 new_acl_entry->ace_type = ACC_PERMIT;
2677 idp->id_len = sizeof(struct ace_id);
2678 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2679 memset(idp->id_data,0,sizeof(uid_t));
2683 new_acl_entry->ace_access = file_acl->g_access << 6;
2684 idp->id_type = SMB_ACL_GROUP_OBJ;
2688 new_acl_entry->ace_access = file_acl->o_access << 6;
2689 idp->id_type = SMB_ACL_OTHER;
2693 new_acl_entry->ace_access = file_acl->u_access << 6;
2694 idp->id_type = SMB_ACL_USER_OBJ;
2701 acl_entry_link_head->count++;
2702 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2705 acl_entry_link_head->count = 0;
2706 SAFE_FREE(file_acl);
2708 return(acl_entry_link_head);
2711 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2713 *permset = *permset & ~0777;
2717 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2720 (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
2724 DEBUG(10,("This is the permset now: %d\n",*permset));
2728 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
2733 SMB_ACL_T sys_acl_init( int count)
2735 struct acl_entry_link *theacl = NULL;
2737 DEBUG(10,("Entering sys_acl_init\n"));
2739 theacl = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
2740 if(theacl == NULL) {
2742 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2747 theacl->nextp = NULL;
2748 theacl->prevp = NULL;
2749 theacl->entryp = NULL;
2750 DEBUG(10,("Exiting sys_acl_init\n"));
2754 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2756 struct acl_entry_link *theacl;
2757 struct acl_entry_link *acl_entryp;
2758 struct acl_entry_link *temp_entry;
2761 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2763 theacl = acl_entryp = *pacl;
2765 /* Get to the end of the acl before adding entry */
2767 for(counting=0; counting < theacl->count; counting++){
2768 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2769 temp_entry = acl_entryp;
2770 acl_entryp = acl_entryp->nextp;
2773 if(theacl->count != 0){
2774 temp_entry->nextp = acl_entryp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
2775 if(acl_entryp == NULL) {
2777 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2781 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2782 acl_entryp->prevp = temp_entry;
2783 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2786 *pentry = acl_entryp->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2787 if(*pentry == NULL) {
2789 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2793 memset(*pentry,0,sizeof(struct new_acl_entry));
2794 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2795 acl_entryp->entryp->ace_type = ACC_PERMIT;
2796 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2797 acl_entryp->nextp = NULL;
2799 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2803 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2805 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2806 entry->ace_id->id_type = tagtype;
2807 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2808 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2811 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2813 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2814 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2815 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2819 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2821 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2822 if(!(*permset & S_IXUSR) &&
2823 !(*permset & S_IWUSR) &&
2824 !(*permset & S_IRUSR) &&
2828 entry->ace_access = *permset;
2829 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2830 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2834 int sys_acl_valid( SMB_ACL_T theacl )
2839 struct acl_entry_link *acl_entry;
2841 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2842 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2843 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2844 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2847 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2849 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2855 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2857 struct acl_entry_link *acl_entry_link = NULL;
2858 struct acl *file_acl = NULL;
2859 struct acl *file_acl_temp = NULL;
2860 struct acl_entry *acl_entry = NULL;
2861 struct ace_id *ace_id = NULL;
2868 DEBUG(10,("Entering sys_acl_set_file\n"));
2869 DEBUG(10,("File name is %s\n",name));
2871 /* AIX has no default ACL */
2872 if(acltype == SMB_ACL_TYPE_DEFAULT)
2875 acl_length = BUFSIZ;
2876 file_acl = (struct acl *)malloc(BUFSIZ);
2878 if(file_acl == NULL) {
2880 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2884 memset(file_acl,0,BUFSIZ);
2886 file_acl->acl_len = ACL_SIZ;
2887 file_acl->acl_mode = S_IXACL;
2889 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2890 acl_entry_link->entryp->ace_access >>= 6;
2891 id_type = acl_entry_link->entryp->ace_id->id_type;
2894 case SMB_ACL_USER_OBJ:
2895 file_acl->u_access = acl_entry_link->entryp->ace_access;
2897 case SMB_ACL_GROUP_OBJ:
2898 file_acl->g_access = acl_entry_link->entryp->ace_access;
2901 file_acl->o_access = acl_entry_link->entryp->ace_access;
2907 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2908 acl_length += sizeof(struct acl_entry);
2909 file_acl_temp = (struct acl *)malloc(acl_length);
2910 if(file_acl_temp == NULL) {
2911 SAFE_FREE(file_acl);
2913 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2917 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2918 SAFE_FREE(file_acl);
2919 file_acl = file_acl_temp;
2922 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2923 file_acl->acl_len += sizeof(struct acl_entry);
2924 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2925 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2927 /* In order to use this, we'll need to wait until we can get denies */
2928 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2929 acl_entry->ace_type = ACC_SPECIFY; */
2931 acl_entry->ace_type = ACC_SPECIFY;
2933 ace_id = acl_entry->ace_id;
2935 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2936 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2937 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2938 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2939 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2942 rc = chacl(name,file_acl,file_acl->acl_len);
2943 DEBUG(10,("errno is %d\n",errno));
2944 DEBUG(10,("return code is %d\n",rc));
2945 SAFE_FREE(file_acl);
2946 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2950 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2952 struct acl_entry_link *acl_entry_link = NULL;
2953 struct acl *file_acl = NULL;
2954 struct acl *file_acl_temp = NULL;
2955 struct acl_entry *acl_entry = NULL;
2956 struct ace_id *ace_id = NULL;
2962 DEBUG(10,("Entering sys_acl_set_fd\n"));
2963 acl_length = BUFSIZ;
2964 file_acl = (struct acl *)malloc(BUFSIZ);
2966 if(file_acl == NULL) {
2968 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2972 memset(file_acl,0,BUFSIZ);
2974 file_acl->acl_len = ACL_SIZ;
2975 file_acl->acl_mode = S_IXACL;
2977 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2978 acl_entry_link->entryp->ace_access >>= 6;
2979 id_type = acl_entry_link->entryp->ace_id->id_type;
2980 DEBUG(10,("The id_type is %d\n",id_type));
2983 case SMB_ACL_USER_OBJ:
2984 file_acl->u_access = acl_entry_link->entryp->ace_access;
2986 case SMB_ACL_GROUP_OBJ:
2987 file_acl->g_access = acl_entry_link->entryp->ace_access;
2990 file_acl->o_access = acl_entry_link->entryp->ace_access;
2996 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2997 acl_length += sizeof(struct acl_entry);
2998 file_acl_temp = (struct acl *)malloc(acl_length);
2999 if(file_acl_temp == NULL) {
3000 SAFE_FREE(file_acl);
3002 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
3006 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
3007 SAFE_FREE(file_acl);
3008 file_acl = file_acl_temp;
3011 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
3012 file_acl->acl_len += sizeof(struct acl_entry);
3013 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
3014 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
3016 /* In order to use this, we'll need to wait until we can get denies */
3017 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
3018 acl_entry->ace_type = ACC_SPECIFY; */
3020 acl_entry->ace_type = ACC_SPECIFY;
3022 ace_id = acl_entry->ace_id;
3024 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
3025 DEBUG(10,("The id type is %d\n",ace_id->id_type));
3026 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
3027 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
3028 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
3031 rc = fchacl(fd,file_acl,file_acl->acl_len);
3032 DEBUG(10,("errno is %d\n",errno));
3033 DEBUG(10,("return code is %d\n",rc));
3034 SAFE_FREE(file_acl);
3035 DEBUG(10,("Exiting sys_acl_set_fd\n"));
3039 int sys_acl_delete_def_file(const char *name)
3041 /* AIX has no default ACL */
3045 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3047 return(*permset & perm);
3050 int sys_acl_free_text(char *text)
3055 int sys_acl_free_acl(SMB_ACL_T posix_acl)
3057 struct acl_entry_link *acl_entry_link;
3059 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
3060 SAFE_FREE(acl_entry_link->prevp->entryp);
3061 SAFE_FREE(acl_entry_link->prevp);
3064 SAFE_FREE(acl_entry_link->prevp->entryp);
3065 SAFE_FREE(acl_entry_link->prevp);
3066 SAFE_FREE(acl_entry_link->entryp);
3067 SAFE_FREE(acl_entry_link);
3072 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3077 #else /* No ACLs. */
3079 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
3085 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
3091 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
3097 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
3103 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
3106 return (SMB_ACL_T)NULL;
3109 SMB_ACL_T sys_acl_get_fd(int fd)
3112 return (SMB_ACL_T)NULL;
3115 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
3121 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3127 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3130 return (permset & perm) ? 1 : 0;
3133 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
3139 int sys_acl_free_text(char *text)
3145 SMB_ACL_T sys_acl_init( int count)
3151 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
3157 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
3163 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
3169 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
3175 int sys_acl_valid( SMB_ACL_T theacl )
3181 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
3187 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
3193 int sys_acl_delete_def_file(const char *name)
3199 int sys_acl_free_acl(SMB_ACL_T the_acl)
3205 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3211 #endif /* No ACLs. */