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.
24 #define DBGC_CLASS DBGC_ACLS
27 This file wraps all differing system ACL interfaces into a consistent
28 one based on the POSIX interface. It also returns the correct errors
29 for older UNIX systems that don't support ACLs.
31 The interfaces that each ACL implementation must support are as follows :
33 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
34 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
35 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p
36 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
37 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
38 SMB_ACL_T sys_acl_get_fd(int fd)
39 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset);
40 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
41 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
42 SMB_ACL_T sys_acl_init( int count)
43 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
44 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
45 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
46 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
47 int sys_acl_valid( SMB_ACL_T theacl )
48 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
49 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
50 int sys_acl_delete_def_file(const char *path)
52 This next one is not POSIX complient - but we *have* to have it !
53 More POSIX braindamage.
55 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
57 The generic POSIX free is the following call. We split this into
58 several different free functions as we may need to add tag info
59 to structures when emulating the POSIX interface.
61 int sys_acl_free( void *obj_p)
63 The calls we actually use are :
65 int sys_acl_free_text(char *text) - free acl_to_text
66 int sys_acl_free_acl(SMB_ACL_T posix_acl)
67 int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
71 #if defined(HAVE_POSIX_ACLS)
73 /* Identity mapping - easy. */
75 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
77 return acl_get_entry( the_acl, entry_id, entry_p);
80 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
82 return acl_get_tag_type( entry_d, tag_type_p);
85 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
87 return acl_get_permset( entry_d, permset_p);
90 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
92 return acl_get_qualifier( entry_d);
95 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
97 return acl_get_file( path_p, type);
100 SMB_ACL_T sys_acl_get_fd(int fd)
102 return acl_get_fd(fd);
105 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
107 return acl_clear_perms(permset);
110 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
112 return acl_add_perm(permset, perm);
115 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
117 #if defined(HAVE_ACL_GET_PERM_NP)
119 * Required for TrustedBSD-based ACL implementations where
120 * non-POSIX.1e functions are denoted by a _np (non-portable)
123 return acl_get_perm_np(permset, perm);
125 return acl_get_perm(permset, perm);
129 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
131 return acl_to_text( the_acl, plen);
134 SMB_ACL_T sys_acl_init( int count)
136 return acl_init(count);
139 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
141 return acl_create_entry(pacl, pentry);
144 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
146 return acl_set_tag_type(entry, tagtype);
149 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
151 return acl_set_qualifier(entry, qual);
154 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
156 return acl_set_permset(entry, permset);
159 int sys_acl_valid( SMB_ACL_T theacl )
161 return acl_valid(theacl);
164 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
166 return acl_set_file(name, acltype, theacl);
169 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
171 return acl_set_fd(fd, theacl);
174 int sys_acl_delete_def_file(const char *name)
176 return acl_delete_def_file(name);
179 int sys_acl_free_text(char *text)
181 return acl_free(text);
184 int sys_acl_free_acl(SMB_ACL_T the_acl)
186 return acl_free(the_acl);
189 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
191 return acl_free(qual);
194 #elif defined(HAVE_TRU64_ACLS)
196 * The interface to DEC/Compaq Tru64 UNIX ACLs
197 * is based on Draft 13 of the POSIX spec which is
198 * slightly different from the Draft 16 interface.
200 * Also, some of the permset manipulation functions
201 * such as acl_clear_perm() and acl_add_perm() appear
202 * to be broken on Tru64 so we have to manipulate
203 * the permission bits in the permset directly.
205 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
207 SMB_ACL_ENTRY_T entry;
209 if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
214 if ((entry = acl_get_entry(the_acl)) != NULL) {
219 return errno ? -1 : 0;
222 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
224 return acl_get_tag_type( entry_d, tag_type_p);
227 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
229 return acl_get_permset( entry_d, permset_p);
232 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
234 return acl_get_qualifier( entry_d);
237 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
239 return acl_get_file((char *)path_p, type);
242 SMB_ACL_T sys_acl_get_fd(int fd)
244 return acl_get_fd(fd, ACL_TYPE_ACCESS);
247 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
249 *permset = 0; /* acl_clear_perm() is broken on Tru64 */
254 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
256 if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) {
261 *permset |= perm; /* acl_add_perm() is broken on Tru64 */
266 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
268 return *permset & perm; /* Tru64 doesn't have acl_get_perm() */
271 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
273 return acl_to_text( the_acl, plen);
276 SMB_ACL_T sys_acl_init( int count)
278 return acl_init(count);
281 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
283 SMB_ACL_ENTRY_T entry;
285 if ((entry = acl_create_entry(pacl)) == NULL) {
293 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
295 return acl_set_tag_type(entry, tagtype);
298 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
300 return acl_set_qualifier(entry, qual);
303 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
305 return acl_set_permset(entry, permset);
308 int sys_acl_valid( SMB_ACL_T theacl )
312 return acl_valid(theacl, &entry);
315 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
317 return acl_set_file((char *)name, acltype, theacl);
320 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
322 return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
325 int sys_acl_delete_def_file(const char *name)
327 return acl_delete_def_file((char *)name);
330 int sys_acl_free_text(char *text)
333 * (void) cast and explicit return 0 are for DEC UNIX
334 * which just #defines acl_free_text() to be free()
336 (void) acl_free_text(text);
340 int sys_acl_free_acl(SMB_ACL_T the_acl)
342 return acl_free(the_acl);
345 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
347 return acl_free_qualifier(qual, tagtype);
350 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
353 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
354 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
358 * Note that while this code implements sufficient functionality
359 * to support the sys_acl_* interfaces it does not provide all
360 * of the semantics of the POSIX ACL interfaces.
362 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
363 * from a call to sys_acl_get_entry() should not be assumed to be
364 * valid after calling any of the following functions, which may
365 * reorder the entries in the ACL.
373 * The only difference between Solaris and UnixWare / OpenUNIX is
374 * that the #defines for the ACL operations have different names
376 #if defined(HAVE_UNIXWARE_ACLS)
378 #define SETACL ACL_SET
379 #define GETACL ACL_GET
380 #define GETACLCNT ACL_CNT
385 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
387 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
392 if (entry_p == NULL) {
397 if (entry_id == SMB_ACL_FIRST_ENTRY) {
401 if (acl_d->next < 0) {
406 if (acl_d->next >= acl_d->count) {
410 *entry_p = &acl_d->acl[acl_d->next++];
415 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
417 *type_p = entry_d->a_type;
422 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
424 *permset_p = &entry_d->a_perm;
429 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
431 if (entry_d->a_type != SMB_ACL_USER
432 && entry_d->a_type != SMB_ACL_GROUP) {
437 return &entry_d->a_id;
441 * There is no way of knowing what size the ACL returned by
442 * GETACL will be unless you first call GETACLCNT which means
443 * making an additional system call.
445 * In the hope of avoiding the cost of the additional system
446 * call in most cases, we initially allocate enough space for
447 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
448 * be too small then we use GETACLCNT to find out the actual
449 * size, reallocate the ACL buffer, and then call GETACL again.
452 #define INITIAL_ACL_SIZE 16
454 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
457 int count; /* # of ACL entries allocated */
458 int naccess; /* # of access ACL entries */
459 int ndefault; /* # of default ACL entries */
461 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
466 count = INITIAL_ACL_SIZE;
467 if ((acl_d = sys_acl_init(count)) == NULL) {
472 * If there isn't enough space for the ACL entries we use
473 * GETACLCNT to determine the actual number of ACL entries
474 * reallocate and try again. This is in a loop because it
475 * is possible that someone else could modify the ACL and
476 * increase the number of entries between the call to
477 * GETACLCNT and the call to GETACL.
479 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
480 && errno == ENOSPC) {
482 sys_acl_free_acl(acl_d);
484 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
488 if ((acl_d = sys_acl_init(count)) == NULL) {
494 sys_acl_free_acl(acl_d);
499 * calculate the number of access and default ACL entries
501 * Note: we assume that the acl() system call returned a
502 * well formed ACL which is sorted so that all of the
503 * access ACL entries preceed any default ACL entries
505 for (naccess = 0; naccess < count; naccess++) {
506 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
509 ndefault = count - naccess;
512 * if the caller wants the default ACL we have to copy
513 * the entries down to the start of the acl[] buffer
514 * and mask out the ACL_DEFAULT flag from the type field
516 if (type == SMB_ACL_TYPE_DEFAULT) {
519 for (i = 0, j = naccess; i < ndefault; i++, j++) {
520 acl_d->acl[i] = acl_d->acl[j];
521 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
524 acl_d->count = ndefault;
526 acl_d->count = naccess;
532 SMB_ACL_T sys_acl_get_fd(int fd)
535 int count; /* # of ACL entries allocated */
536 int naccess; /* # of access ACL entries */
538 count = INITIAL_ACL_SIZE;
539 if ((acl_d = sys_acl_init(count)) == NULL) {
543 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
544 && errno == ENOSPC) {
546 sys_acl_free_acl(acl_d);
548 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
552 if ((acl_d = sys_acl_init(count)) == NULL) {
558 sys_acl_free_acl(acl_d);
563 * calculate the number of access ACL entries
565 for (naccess = 0; naccess < count; naccess++) {
566 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
570 acl_d->count = naccess;
575 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
582 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
584 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
585 && perm != SMB_ACL_EXECUTE) {
590 if (permset_d == NULL) {
600 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
602 return *permset_d & perm;
605 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
612 * use an initial estimate of 20 bytes per ACL entry
613 * when allocating memory for the text representation
617 maxlen = 20 * acl_d->count;
618 if ((text = SMB_MALLOC(maxlen)) == NULL) {
623 for (i = 0; i < acl_d->count; i++) {
624 struct acl *ap = &acl_d->acl[i];
634 switch (ap->a_type) {
636 * for debugging purposes it's probably more
637 * useful to dump unknown tag types rather
638 * than just returning an error
641 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
644 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
650 id = uidtoname(ap->a_id);
651 case SMB_ACL_USER_OBJ:
656 if ((gr = getgrgid(ap->a_id)) == NULL) {
657 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
663 case SMB_ACL_GROUP_OBJ:
677 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
678 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
679 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
682 /* <tag> : <qualifier> : rwx \n \0 */
683 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
686 * If this entry would overflow the buffer
687 * allocate enough additional memory for this
688 * entry and an estimate of another 20 bytes
689 * for each entry still to be processed
691 if ((len + nbytes) > maxlen) {
692 maxlen += nbytes + 20 * (acl_d->count - i);
693 if ((text = SMB_REALLOC(text, maxlen)) == NULL) {
699 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
709 SMB_ACL_T sys_acl_init(int count)
719 * note that since the definition of the structure pointed
720 * to by the SMB_ACL_T includes the first element of the
721 * acl[] array, this actually allocates an ACL with room
722 * for (count+1) entries
724 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
737 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
740 SMB_ACL_ENTRY_T entry_d;
742 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
747 if (acl_d->count >= acl_d->size) {
752 entry_d = &acl_d->acl[acl_d->count++];
761 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
765 case SMB_ACL_USER_OBJ:
767 case SMB_ACL_GROUP_OBJ:
770 entry_d->a_type = tag_type;
780 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
782 if (entry_d->a_type != SMB_ACL_GROUP
783 && entry_d->a_type != SMB_ACL_USER) {
788 entry_d->a_id = *((id_t *)qual_p);
793 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
795 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
799 entry_d->a_perm = *permset_d;
805 * sort the ACL and check it for validity
807 * if it's a minimal ACL with only 4 entries then we
808 * need to recalculate the mask permissions to make
809 * sure that they are the same as the GROUP_OBJ
810 * permissions as required by the UnixWare acl() system call.
812 * (note: since POSIX allows minimal ACLs which only contain
813 * 3 entries - ie there is no mask entry - we should, in theory,
814 * check for this and add a mask entry if necessary - however
815 * we "know" that the caller of this interface always specifies
816 * a mask so, in practice "this never happens" (tm) - if it *does*
817 * happen aclsort() will fail and return an error and someone will
818 * have to fix it ...)
821 static int acl_sort(SMB_ACL_T acl_d)
823 int fixmask = (acl_d->count <= 4);
825 if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
832 int sys_acl_valid(SMB_ACL_T acl_d)
834 return acl_sort(acl_d);
837 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
842 struct acl *acl_buf = NULL;
845 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
850 if (acl_sort(acl_d) != 0) {
854 acl_p = &acl_d->acl[0];
855 acl_count = acl_d->count;
858 * if it's a directory there is extra work to do
859 * since the acl() system call will replace both
860 * the access ACLs and the default ACLs (if any)
862 if (stat(name, &s) != 0) {
865 if (S_ISDIR(s.st_mode)) {
871 if (type == SMB_ACL_TYPE_ACCESS) {
873 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
877 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
880 if (tmp_acl == NULL) {
885 * allocate a temporary buffer for the complete ACL
887 acl_count = acc_acl->count + def_acl->count;
888 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
890 if (acl_buf == NULL) {
891 sys_acl_free_acl(tmp_acl);
897 * copy the access control and default entries into the buffer
899 memcpy(&acl_buf[0], &acc_acl->acl[0],
900 acc_acl->count * sizeof(acl_buf[0]));
902 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
903 def_acl->count * sizeof(acl_buf[0]));
906 * set the ACL_DEFAULT flag on the default entries
908 for (i = acc_acl->count; i < acl_count; i++) {
909 acl_buf[i].a_type |= ACL_DEFAULT;
912 sys_acl_free_acl(tmp_acl);
914 } else if (type != SMB_ACL_TYPE_ACCESS) {
919 ret = acl(name, SETACL, acl_count, acl_p);
926 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
928 if (acl_sort(acl_d) != 0) {
932 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
935 int sys_acl_delete_def_file(const char *path)
941 * fetching the access ACL and rewriting it has
942 * the effect of deleting the default ACL
944 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
948 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
950 sys_acl_free_acl(acl_d);
955 int sys_acl_free_text(char *text)
961 int sys_acl_free_acl(SMB_ACL_T acl_d)
967 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
972 #elif defined(HAVE_HPUX_ACLS)
976 * Based on the Solaris/SCO code - with modifications.
980 * Note that while this code implements sufficient functionality
981 * to support the sys_acl_* interfaces it does not provide all
982 * of the semantics of the POSIX ACL interfaces.
984 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
985 * from a call to sys_acl_get_entry() should not be assumed to be
986 * valid after calling any of the following functions, which may
987 * reorder the entries in the ACL.
994 /* This checks if the POSIX ACL system call is defined */
995 /* which basically corresponds to whether JFS 3.3 or */
996 /* higher is installed. If acl() was called when it */
997 /* isn't defined, it causes the process to core dump */
998 /* so it is important to check this and avoid acl() */
999 /* calls if it isn't there. */
1001 static BOOL hpux_acl_call_presence(void)
1004 shl_t handle = NULL;
1007 static BOOL already_checked=0;
1013 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
1016 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
1017 ret_val, errno, strerror(errno)));
1018 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
1022 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
1024 already_checked = True;
1028 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1030 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1035 if (entry_p == NULL) {
1040 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1044 if (acl_d->next < 0) {
1049 if (acl_d->next >= acl_d->count) {
1053 *entry_p = &acl_d->acl[acl_d->next++];
1058 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1060 *type_p = entry_d->a_type;
1065 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1067 *permset_p = &entry_d->a_perm;
1072 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1074 if (entry_d->a_type != SMB_ACL_USER
1075 && entry_d->a_type != SMB_ACL_GROUP) {
1080 return &entry_d->a_id;
1084 * There is no way of knowing what size the ACL returned by
1085 * ACL_GET will be unless you first call ACL_CNT which means
1086 * making an additional system call.
1088 * In the hope of avoiding the cost of the additional system
1089 * call in most cases, we initially allocate enough space for
1090 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
1091 * be too small then we use ACL_CNT to find out the actual
1092 * size, reallocate the ACL buffer, and then call ACL_GET again.
1095 #define INITIAL_ACL_SIZE 16
1097 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1100 int count; /* # of ACL entries allocated */
1101 int naccess; /* # of access ACL entries */
1102 int ndefault; /* # of default ACL entries */
1104 if(hpux_acl_call_presence() == False) {
1105 /* Looks like we don't have the acl() system call on HPUX.
1106 * May be the system doesn't have the latest version of JFS.
1111 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1116 count = INITIAL_ACL_SIZE;
1117 if ((acl_d = sys_acl_init(count)) == NULL) {
1122 * If there isn't enough space for the ACL entries we use
1123 * ACL_CNT to determine the actual number of ACL entries
1124 * reallocate and try again. This is in a loop because it
1125 * is possible that someone else could modify the ACL and
1126 * increase the number of entries between the call to
1127 * ACL_CNT and the call to ACL_GET.
1129 while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
1131 sys_acl_free_acl(acl_d);
1133 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
1137 if ((acl_d = sys_acl_init(count)) == NULL) {
1143 sys_acl_free_acl(acl_d);
1148 * calculate the number of access and default ACL entries
1150 * Note: we assume that the acl() system call returned a
1151 * well formed ACL which is sorted so that all of the
1152 * access ACL entries preceed any default ACL entries
1154 for (naccess = 0; naccess < count; naccess++) {
1155 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
1158 ndefault = count - naccess;
1161 * if the caller wants the default ACL we have to copy
1162 * the entries down to the start of the acl[] buffer
1163 * and mask out the ACL_DEFAULT flag from the type field
1165 if (type == SMB_ACL_TYPE_DEFAULT) {
1168 for (i = 0, j = naccess; i < ndefault; i++, j++) {
1169 acl_d->acl[i] = acl_d->acl[j];
1170 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
1173 acl_d->count = ndefault;
1175 acl_d->count = naccess;
1181 SMB_ACL_T sys_acl_get_fd(int fd)
1184 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1187 files_struct *fsp = file_find_fd(fd);
1195 * We know we're in the same conn context. So we
1196 * can use the relative path.
1199 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
1202 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
1209 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1211 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
1212 && perm != SMB_ACL_EXECUTE) {
1217 if (permset_d == NULL) {
1227 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1229 return *permset_d & perm;
1232 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
1239 * use an initial estimate of 20 bytes per ACL entry
1240 * when allocating memory for the text representation
1244 maxlen = 20 * acl_d->count;
1245 if ((text = SMB_MALLOC(maxlen)) == NULL) {
1250 for (i = 0; i < acl_d->count; i++) {
1251 struct acl *ap = &acl_d->acl[i];
1261 switch (ap->a_type) {
1263 * for debugging purposes it's probably more
1264 * useful to dump unknown tag types rather
1265 * than just returning an error
1268 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
1271 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1277 id = uidtoname(ap->a_id);
1278 case SMB_ACL_USER_OBJ:
1283 if ((gr = getgrgid(ap->a_id)) == NULL) {
1284 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1290 case SMB_ACL_GROUP_OBJ:
1304 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
1305 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
1306 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
1309 /* <tag> : <qualifier> : rwx \n \0 */
1310 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
1313 * If this entry would overflow the buffer
1314 * allocate enough additional memory for this
1315 * entry and an estimate of another 20 bytes
1316 * for each entry still to be processed
1318 if ((len + nbytes) > maxlen) {
1319 maxlen += nbytes + 20 * (acl_d->count - i);
1320 if ((text = SMB_REALLOC(text, maxlen)) == NULL) {
1327 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
1337 SMB_ACL_T sys_acl_init(int count)
1347 * note that since the definition of the structure pointed
1348 * to by the SMB_ACL_T includes the first element of the
1349 * acl[] array, this actually allocates an ACL with room
1350 * for (count+1) entries
1352 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
1357 a->size = count + 1;
1365 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1368 SMB_ACL_ENTRY_T entry_d;
1370 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1375 if (acl_d->count >= acl_d->size) {
1380 entry_d = &acl_d->acl[acl_d->count++];
1381 entry_d->a_type = 0;
1383 entry_d->a_perm = 0;
1389 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1393 case SMB_ACL_USER_OBJ:
1395 case SMB_ACL_GROUP_OBJ:
1398 entry_d->a_type = tag_type;
1408 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1410 if (entry_d->a_type != SMB_ACL_GROUP
1411 && entry_d->a_type != SMB_ACL_USER) {
1416 entry_d->a_id = *((id_t *)qual_p);
1421 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1423 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1427 entry_d->a_perm = *permset_d;
1432 /* Structure to capture the count for each type of ACE. */
1434 struct hpux_acl_types {
1443 int n_def_group_obj;
1447 int n_def_other_obj;
1450 int n_def_class_obj;
1456 * Counts the different number of objects in a given array of ACL
1460 * acl_count - Count of ACLs in the array of ACL strucutres.
1461 * aclp - Array of ACL structures.
1462 * acl_type_count - Pointer to acl_types structure. Should already be
1466 * acl_type_count - This structure is filled up with counts of various
1470 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1474 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1476 for(i=0;i<acl_count;i++) {
1477 switch(aclp[i].a_type) {
1479 acl_type_count->n_user++;
1482 acl_type_count->n_user_obj++;
1485 acl_type_count->n_def_user_obj++;
1488 acl_type_count->n_group++;
1491 acl_type_count->n_group_obj++;
1494 acl_type_count->n_def_group_obj++;
1497 acl_type_count->n_other_obj++;
1500 acl_type_count->n_def_other_obj++;
1503 acl_type_count->n_class_obj++;
1506 acl_type_count->n_def_class_obj++;
1509 acl_type_count->n_def_user++;
1512 acl_type_count->n_def_group++;
1515 acl_type_count->n_illegal_obj++;
1521 /* swap_acl_entries: Swaps two ACL entries.
1523 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1526 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1528 struct acl temp_acl;
1530 temp_acl.a_type = aclp0->a_type;
1531 temp_acl.a_id = aclp0->a_id;
1532 temp_acl.a_perm = aclp0->a_perm;
1534 aclp0->a_type = aclp1->a_type;
1535 aclp0->a_id = aclp1->a_id;
1536 aclp0->a_perm = aclp1->a_perm;
1538 aclp1->a_type = temp_acl.a_type;
1539 aclp1->a_id = temp_acl.a_id;
1540 aclp1->a_perm = temp_acl.a_perm;
1543 /* prohibited_duplicate_type
1544 * Identifies if given ACL type can have duplicate entries or
1547 * Inputs: acl_type - ACL Type.
1553 * True - If the ACL type matches any of the prohibited types.
1554 * False - If the ACL type doesn't match any of the prohibited types.
1557 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1570 /* get_needed_class_perm
1571 * Returns the permissions of a ACL structure only if the ACL
1572 * type matches one of the pre-determined types for computing
1573 * CLASS_OBJ permissions.
1575 * Inputs: aclp - Pointer to ACL structure.
1578 static int hpux_get_needed_class_perm(struct acl *aclp)
1580 switch(aclp->a_type) {
1590 return aclp->a_perm;
1596 /* acl_sort for HPUX.
1597 * Sorts the array of ACL structures as per the description in
1598 * aclsort man page. Refer to aclsort man page for more details
1602 * acl_count - Count of ACLs in the array of ACL structures.
1603 * calclass - If this is not zero, then we compute the CLASS_OBJ
1605 * aclp - Array of ACL structures.
1609 * aclp - Sorted array of ACL structures.
1613 * Returns 0 for success -1 for failure. Prints a message to the Samba
1614 * debug log in case of failure.
1617 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1619 #if !defined(HAVE_HPUX_ACLSORT)
1621 * The aclsort() system call is availabe on the latest HPUX General
1622 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1623 * function. Because, we don't want to update to a new
1624 * HPUX GR bundle just for aclsort() call.
1627 struct hpux_acl_types acl_obj_count;
1628 int n_class_obj_perm = 0;
1632 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1637 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1641 /* Count different types of ACLs in the ACLs array */
1643 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1645 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1646 * CLASS_OBJ and OTHER_OBJ
1649 if( (acl_obj_count.n_user_obj != 1) ||
1650 (acl_obj_count.n_group_obj != 1) ||
1651 (acl_obj_count.n_class_obj != 1) ||
1652 (acl_obj_count.n_other_obj != 1)
1654 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1655 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1659 /* If any of the default objects are present, there should be only
1663 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1664 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1665 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1666 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1670 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1673 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1674 * same ACL type, sort by ACL id.
1676 * I am using the trival kind of sorting method here because, performance isn't
1677 * really effected by the ACLs feature. More over there aren't going to be more
1678 * than 17 entries on HPUX.
1681 for(i=0; i<acl_count;i++) {
1682 for (j=i+1; j<acl_count; j++) {
1683 if( aclp[i].a_type > aclp[j].a_type ) {
1684 /* ACL entries out of order, swap them */
1686 hpux_swap_acl_entries((aclp+i), (aclp+j));
1688 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1690 /* ACL entries of same type, sort by id */
1692 if(aclp[i].a_id > aclp[j].a_id) {
1693 hpux_swap_acl_entries((aclp+i), (aclp+j));
1694 } else if (aclp[i].a_id == aclp[j].a_id) {
1695 /* We have a duplicate entry. */
1696 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1697 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1698 aclp[i].a_type, aclp[i].a_id));
1707 /* set the class obj permissions to the computed one. */
1709 int n_class_obj_index = -1;
1711 for(i=0;i<acl_count;i++) {
1712 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1714 if(aclp[i].a_type == CLASS_OBJ)
1715 n_class_obj_index = i;
1717 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1722 return aclsort(acl_count, calclass, aclp);
1727 * sort the ACL and check it for validity
1729 * if it's a minimal ACL with only 4 entries then we
1730 * need to recalculate the mask permissions to make
1731 * sure that they are the same as the GROUP_OBJ
1732 * permissions as required by the UnixWare acl() system call.
1734 * (note: since POSIX allows minimal ACLs which only contain
1735 * 3 entries - ie there is no mask entry - we should, in theory,
1736 * check for this and add a mask entry if necessary - however
1737 * we "know" that the caller of this interface always specifies
1738 * a mask so, in practice "this never happens" (tm) - if it *does*
1739 * happen aclsort() will fail and return an error and someone will
1740 * have to fix it ...)
1743 static int acl_sort(SMB_ACL_T acl_d)
1745 int fixmask = (acl_d->count <= 4);
1747 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1754 int sys_acl_valid(SMB_ACL_T acl_d)
1756 return acl_sort(acl_d);
1759 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1764 struct acl *acl_buf = NULL;
1767 if(hpux_acl_call_presence() == False) {
1768 /* Looks like we don't have the acl() system call on HPUX.
1769 * May be the system doesn't have the latest version of JFS.
1775 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1780 if (acl_sort(acl_d) != 0) {
1784 acl_p = &acl_d->acl[0];
1785 acl_count = acl_d->count;
1788 * if it's a directory there is extra work to do
1789 * since the acl() system call will replace both
1790 * the access ACLs and the default ACLs (if any)
1792 if (stat(name, &s) != 0) {
1795 if (S_ISDIR(s.st_mode)) {
1801 if (type == SMB_ACL_TYPE_ACCESS) {
1803 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1807 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1810 if (tmp_acl == NULL) {
1815 * allocate a temporary buffer for the complete ACL
1817 acl_count = acc_acl->count + def_acl->count;
1818 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1820 if (acl_buf == NULL) {
1821 sys_acl_free_acl(tmp_acl);
1827 * copy the access control and default entries into the buffer
1829 memcpy(&acl_buf[0], &acc_acl->acl[0],
1830 acc_acl->count * sizeof(acl_buf[0]));
1832 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1833 def_acl->count * sizeof(acl_buf[0]));
1836 * set the ACL_DEFAULT flag on the default entries
1838 for (i = acc_acl->count; i < acl_count; i++) {
1839 acl_buf[i].a_type |= ACL_DEFAULT;
1842 sys_acl_free_acl(tmp_acl);
1844 } else if (type != SMB_ACL_TYPE_ACCESS) {
1849 ret = acl(name, ACL_SET, acl_count, acl_p);
1858 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1861 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1864 files_struct *fsp = file_find_fd(fd);
1871 if (acl_sort(acl_d) != 0) {
1876 * We know we're in the same conn context. So we
1877 * can use the relative path.
1880 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1883 int sys_acl_delete_def_file(const char *path)
1889 * fetching the access ACL and rewriting it has
1890 * the effect of deleting the default ACL
1892 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1896 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1898 sys_acl_free_acl(acl_d);
1903 int sys_acl_free_text(char *text)
1909 int sys_acl_free_acl(SMB_ACL_T acl_d)
1915 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1920 #elif defined(HAVE_IRIX_ACLS)
1922 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1924 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1929 if (entry_p == NULL) {
1934 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1938 if (acl_d->next < 0) {
1943 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1947 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1952 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1954 *type_p = entry_d->ae_tag;
1959 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1961 *permset_p = entry_d;
1966 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1968 if (entry_d->ae_tag != SMB_ACL_USER
1969 && entry_d->ae_tag != SMB_ACL_GROUP) {
1974 return &entry_d->ae_id;
1977 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1981 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1985 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1994 SMB_ACL_T sys_acl_get_fd(int fd)
1998 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
2002 if ((a->aclp = acl_get_fd(fd)) == NULL) {
2011 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
2013 permset_d->ae_perm = 0;
2018 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2020 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
2021 && perm != SMB_ACL_EXECUTE) {
2026 if (permset_d == NULL) {
2031 permset_d->ae_perm |= perm;
2036 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2038 return permset_d->ae_perm & perm;
2041 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
2043 return acl_to_text(acl_d->aclp, len_p);
2046 SMB_ACL_T sys_acl_init(int count)
2055 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
2061 a->freeaclp = False;
2062 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
2063 a->aclp->acl_cnt = 0;
2069 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
2072 SMB_ACL_ENTRY_T entry_d;
2074 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
2079 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
2084 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
2085 entry_d->ae_tag = 0;
2087 entry_d->ae_perm = 0;
2093 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
2097 case SMB_ACL_USER_OBJ:
2099 case SMB_ACL_GROUP_OBJ:
2102 entry_d->ae_tag = tag_type;
2112 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
2114 if (entry_d->ae_tag != SMB_ACL_GROUP
2115 && entry_d->ae_tag != SMB_ACL_USER) {
2120 entry_d->ae_id = *((id_t *)qual_p);
2125 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
2127 if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
2131 entry_d->ae_perm = permset_d->ae_perm;
2136 int sys_acl_valid(SMB_ACL_T acl_d)
2138 return acl_valid(acl_d->aclp);
2141 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
2143 return acl_set_file(name, type, acl_d->aclp);
2146 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
2148 return acl_set_fd(fd, acl_d->aclp);
2151 int sys_acl_delete_def_file(const char *name)
2153 return acl_delete_def_file(name);
2156 int sys_acl_free_text(char *text)
2158 return acl_free(text);
2161 int sys_acl_free_acl(SMB_ACL_T acl_d)
2163 if (acl_d->freeaclp) {
2164 acl_free(acl_d->aclp);
2170 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2175 #elif defined(HAVE_AIX_ACLS)
2177 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
2179 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2181 struct acl_entry_link *link;
2182 struct new_acl_entry *entry;
2185 DEBUG(10,("This is the count: %d\n",theacl->count));
2187 /* Check if count was previously set to -1. *
2188 * If it was, that means we reached the end *
2189 * of the acl last time. */
2190 if(theacl->count == -1)
2194 /* To get to the next acl, traverse linked list until index *
2195 * of acl matches the count we are keeping. This count is *
2196 * incremented each time we return an acl entry. */
2198 for(keep_going = 0; keep_going < theacl->count; keep_going++)
2201 entry = *entry_p = link->entryp;
2203 DEBUG(10,("*entry_p is %d\n",entry_p));
2204 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
2206 /* Increment count */
2208 if(link->nextp == NULL)
2214 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2216 /* Initialize tag type */
2219 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
2221 /* Depending on what type of entry we have, *
2222 * return tag type. */
2223 switch(entry_d->ace_id->id_type) {
2225 *tag_type_p = SMB_ACL_USER;
2228 *tag_type_p = SMB_ACL_GROUP;
2231 case SMB_ACL_USER_OBJ:
2232 case SMB_ACL_GROUP_OBJ:
2234 *tag_type_p = entry_d->ace_id->id_type;
2244 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2246 DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
2247 *permset_p = &entry_d->ace_access;
2248 DEBUG(10,("**permset_p is %d\n",**permset_p));
2249 if(!(**permset_p & S_IXUSR) &&
2250 !(**permset_p & S_IWUSR) &&
2251 !(**permset_p & S_IRUSR) &&
2255 DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
2259 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2261 return(entry_d->ace_id->id_data);
2264 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2266 struct acl *file_acl = (struct acl *)NULL;
2267 struct acl_entry *acl_entry;
2268 struct new_acl_entry *new_acl_entry;
2270 struct acl_entry_link *acl_entry_link;
2271 struct acl_entry_link *acl_entry_link_head;
2276 /* AIX has no DEFAULT */
2277 if ( type == SMB_ACL_TYPE_DEFAULT )
2280 /* Get the acl using statacl */
2282 DEBUG(10,("Entering sys_acl_get_file\n"));
2283 DEBUG(10,("path_p is %s\n",path_p));
2285 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2287 if(file_acl == NULL) {
2289 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
2293 memset(file_acl,0,BUFSIZ);
2295 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
2297 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
2298 SAFE_FREE(file_acl);
2302 DEBUG(10,("Got facl and returned it\n"));
2304 /* Point to the first acl entry in the acl */
2305 acl_entry = file_acl->acl_ext;
2307 /* Begin setting up the head of the linked list *
2308 * that will be used for the storing the acl *
2309 * in a way that is useful for the posix_acls.c *
2312 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2313 if(acl_entry_link_head == NULL)
2316 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2317 if(acl_entry_link->entryp == NULL) {
2318 SAFE_FREE(file_acl);
2320 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2324 DEBUG(10,("acl_entry is %d\n",acl_entry));
2325 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2327 /* Check if the extended acl bit is on. *
2328 * If it isn't, do not show the *
2329 * contents of the acl since AIX intends *
2330 * the extended info to remain unused */
2332 if(file_acl->acl_mode & S_IXACL){
2333 /* while we are not pointing to the very end */
2334 while(acl_entry < acl_last(file_acl)) {
2335 /* before we malloc anything, make sure this is */
2336 /* a valid acl entry and one that we want to map */
2337 idp = id_nxt(acl_entry->ace_id);
2338 if((acl_entry->ace_type == ACC_SPECIFY ||
2339 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2340 acl_entry = acl_nxt(acl_entry);
2344 idp = acl_entry->ace_id;
2346 /* Check if this is the first entry in the linked list. *
2347 * The first entry needs to keep prevp pointing to NULL *
2348 * and already has entryp allocated. */
2350 if(acl_entry_link_head->count != 0) {
2351 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2353 if(acl_entry_link->nextp == NULL) {
2354 SAFE_FREE(file_acl);
2356 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2360 acl_entry_link->nextp->prevp = acl_entry_link;
2361 acl_entry_link = acl_entry_link->nextp;
2362 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2363 if(acl_entry_link->entryp == NULL) {
2364 SAFE_FREE(file_acl);
2366 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2369 acl_entry_link->nextp = NULL;
2372 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2374 /* Don't really need this since all types are going *
2375 * to be specified but, it's better than leaving it 0 */
2377 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2379 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2381 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2383 /* The access in the acl entries must be left shifted by *
2384 * three bites, because they will ultimately be compared *
2385 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2387 switch(acl_entry->ace_type){
2390 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2391 acl_entry_link->entryp->ace_access <<= 6;
2392 acl_entry_link_head->count++;
2395 /* Since there is no way to return a DENY acl entry *
2396 * change to PERMIT and then shift. */
2397 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2398 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2399 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2400 acl_entry_link->entryp->ace_access <<= 6;
2401 acl_entry_link_head->count++;
2407 DEBUG(10,("acl_entry = %d\n",acl_entry));
2408 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2410 acl_entry = acl_nxt(acl_entry);
2412 } /* end of if enabled */
2414 /* Since owner, group, other acl entries are not *
2415 * part of the acl entries in an acl, they must *
2416 * be dummied up to become part of the list. */
2418 for( i = 1; i < 4; i++) {
2419 DEBUG(10,("i is %d\n",i));
2420 if(acl_entry_link_head->count != 0) {
2421 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2422 if(acl_entry_link->nextp == NULL) {
2423 SAFE_FREE(file_acl);
2425 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2429 acl_entry_link->nextp->prevp = acl_entry_link;
2430 acl_entry_link = acl_entry_link->nextp;
2431 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2432 if(acl_entry_link->entryp == NULL) {
2433 SAFE_FREE(file_acl);
2435 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2440 acl_entry_link->nextp = NULL;
2442 new_acl_entry = acl_entry_link->entryp;
2443 idp = new_acl_entry->ace_id;
2445 new_acl_entry->ace_len = sizeof(struct acl_entry);
2446 new_acl_entry->ace_type = ACC_PERMIT;
2447 idp->id_len = sizeof(struct ace_id);
2448 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2449 memset(idp->id_data,0,sizeof(uid_t));
2453 new_acl_entry->ace_access = file_acl->g_access << 6;
2454 idp->id_type = SMB_ACL_GROUP_OBJ;
2458 new_acl_entry->ace_access = file_acl->o_access << 6;
2459 idp->id_type = SMB_ACL_OTHER;
2463 new_acl_entry->ace_access = file_acl->u_access << 6;
2464 idp->id_type = SMB_ACL_USER_OBJ;
2472 acl_entry_link_head->count++;
2473 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2476 acl_entry_link_head->count = 0;
2477 SAFE_FREE(file_acl);
2479 return(acl_entry_link_head);
2482 SMB_ACL_T sys_acl_get_fd(int fd)
2484 struct acl *file_acl = (struct acl *)NULL;
2485 struct acl_entry *acl_entry;
2486 struct new_acl_entry *new_acl_entry;
2488 struct acl_entry_link *acl_entry_link;
2489 struct acl_entry_link *acl_entry_link_head;
2494 /* Get the acl using fstatacl */
2496 DEBUG(10,("Entering sys_acl_get_fd\n"));
2497 DEBUG(10,("fd is %d\n",fd));
2498 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2500 if(file_acl == NULL) {
2502 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2506 memset(file_acl,0,BUFSIZ);
2508 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2510 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2511 SAFE_FREE(file_acl);
2515 DEBUG(10,("Got facl and returned it\n"));
2517 /* Point to the first acl entry in the acl */
2519 acl_entry = file_acl->acl_ext;
2520 /* Begin setting up the head of the linked list *
2521 * that will be used for the storing the acl *
2522 * in a way that is useful for the posix_acls.c *
2525 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2526 if(acl_entry_link_head == NULL){
2527 SAFE_FREE(file_acl);
2531 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2533 if(acl_entry_link->entryp == NULL) {
2535 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2536 SAFE_FREE(file_acl);
2540 DEBUG(10,("acl_entry is %d\n",acl_entry));
2541 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2543 /* Check if the extended acl bit is on. *
2544 * If it isn't, do not show the *
2545 * contents of the acl since AIX intends *
2546 * the extended info to remain unused */
2548 if(file_acl->acl_mode & S_IXACL){
2549 /* while we are not pointing to the very end */
2550 while(acl_entry < acl_last(file_acl)) {
2551 /* before we malloc anything, make sure this is */
2552 /* a valid acl entry and one that we want to map */
2554 idp = id_nxt(acl_entry->ace_id);
2555 if((acl_entry->ace_type == ACC_SPECIFY ||
2556 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2557 acl_entry = acl_nxt(acl_entry);
2561 idp = acl_entry->ace_id;
2563 /* Check if this is the first entry in the linked list. *
2564 * The first entry needs to keep prevp pointing to NULL *
2565 * and already has entryp allocated. */
2567 if(acl_entry_link_head->count != 0) {
2568 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2569 if(acl_entry_link->nextp == NULL) {
2571 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2572 SAFE_FREE(file_acl);
2575 acl_entry_link->nextp->prevp = acl_entry_link;
2576 acl_entry_link = acl_entry_link->nextp;
2577 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2578 if(acl_entry_link->entryp == NULL) {
2580 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2581 SAFE_FREE(file_acl);
2585 acl_entry_link->nextp = NULL;
2588 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2590 /* Don't really need this since all types are going *
2591 * to be specified but, it's better than leaving it 0 */
2593 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2594 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2596 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2598 /* The access in the acl entries must be left shifted by *
2599 * three bites, because they will ultimately be compared *
2600 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2602 switch(acl_entry->ace_type){
2605 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2606 acl_entry_link->entryp->ace_access <<= 6;
2607 acl_entry_link_head->count++;
2610 /* Since there is no way to return a DENY acl entry *
2611 * change to PERMIT and then shift. */
2612 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2613 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2614 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2615 acl_entry_link->entryp->ace_access <<= 6;
2616 acl_entry_link_head->count++;
2622 DEBUG(10,("acl_entry = %d\n",acl_entry));
2623 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2625 acl_entry = acl_nxt(acl_entry);
2627 } /* end of if enabled */
2629 /* Since owner, group, other acl entries are not *
2630 * part of the acl entries in an acl, they must *
2631 * be dummied up to become part of the list. */
2633 for( i = 1; i < 4; i++) {
2634 DEBUG(10,("i is %d\n",i));
2635 if(acl_entry_link_head->count != 0){
2636 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2637 if(acl_entry_link->nextp == NULL) {
2639 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2640 SAFE_FREE(file_acl);
2644 acl_entry_link->nextp->prevp = acl_entry_link;
2645 acl_entry_link = acl_entry_link->nextp;
2646 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2648 if(acl_entry_link->entryp == NULL) {
2649 SAFE_FREE(file_acl);
2651 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2656 acl_entry_link->nextp = NULL;
2658 new_acl_entry = acl_entry_link->entryp;
2659 idp = new_acl_entry->ace_id;
2661 new_acl_entry->ace_len = sizeof(struct acl_entry);
2662 new_acl_entry->ace_type = ACC_PERMIT;
2663 idp->id_len = sizeof(struct ace_id);
2664 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2665 memset(idp->id_data,0,sizeof(uid_t));
2669 new_acl_entry->ace_access = file_acl->g_access << 6;
2670 idp->id_type = SMB_ACL_GROUP_OBJ;
2674 new_acl_entry->ace_access = file_acl->o_access << 6;
2675 idp->id_type = SMB_ACL_OTHER;
2679 new_acl_entry->ace_access = file_acl->u_access << 6;
2680 idp->id_type = SMB_ACL_USER_OBJ;
2687 acl_entry_link_head->count++;
2688 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2691 acl_entry_link_head->count = 0;
2692 SAFE_FREE(file_acl);
2694 return(acl_entry_link_head);
2697 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2699 *permset = *permset & ~0777;
2703 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2706 (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
2710 DEBUG(10,("This is the permset now: %d\n",*permset));
2714 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
2719 SMB_ACL_T sys_acl_init( int count)
2721 struct acl_entry_link *theacl = NULL;
2723 DEBUG(10,("Entering sys_acl_init\n"));
2725 theacl = SMB_MALLOC_P(struct acl_entry_link);
2726 if(theacl == NULL) {
2728 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2733 theacl->nextp = NULL;
2734 theacl->prevp = NULL;
2735 theacl->entryp = NULL;
2736 DEBUG(10,("Exiting sys_acl_init\n"));
2740 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2742 struct acl_entry_link *theacl;
2743 struct acl_entry_link *acl_entryp;
2744 struct acl_entry_link *temp_entry;
2747 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2749 theacl = acl_entryp = *pacl;
2751 /* Get to the end of the acl before adding entry */
2753 for(counting=0; counting < theacl->count; counting++){
2754 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2755 temp_entry = acl_entryp;
2756 acl_entryp = acl_entryp->nextp;
2759 if(theacl->count != 0){
2760 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2761 if(acl_entryp == NULL) {
2763 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2767 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2768 acl_entryp->prevp = temp_entry;
2769 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2772 *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2773 if(*pentry == NULL) {
2775 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2779 memset(*pentry,0,sizeof(struct new_acl_entry));
2780 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2781 acl_entryp->entryp->ace_type = ACC_PERMIT;
2782 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2783 acl_entryp->nextp = NULL;
2785 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2789 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2791 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2792 entry->ace_id->id_type = tagtype;
2793 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2794 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2797 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2799 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2800 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2801 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2805 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2807 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2808 if(!(*permset & S_IXUSR) &&
2809 !(*permset & S_IWUSR) &&
2810 !(*permset & S_IRUSR) &&
2814 entry->ace_access = *permset;
2815 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2816 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2820 int sys_acl_valid( SMB_ACL_T theacl )
2825 struct acl_entry_link *acl_entry;
2827 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2828 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2829 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2830 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2833 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2835 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2841 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2843 struct acl_entry_link *acl_entry_link = NULL;
2844 struct acl *file_acl = NULL;
2845 struct acl *file_acl_temp = NULL;
2846 struct acl_entry *acl_entry = NULL;
2847 struct ace_id *ace_id = NULL;
2854 DEBUG(10,("Entering sys_acl_set_file\n"));
2855 DEBUG(10,("File name is %s\n",name));
2857 /* AIX has no default ACL */
2858 if(acltype == SMB_ACL_TYPE_DEFAULT)
2861 acl_length = BUFSIZ;
2862 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2864 if(file_acl == NULL) {
2866 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2870 memset(file_acl,0,BUFSIZ);
2872 file_acl->acl_len = ACL_SIZ;
2873 file_acl->acl_mode = S_IXACL;
2875 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2876 acl_entry_link->entryp->ace_access >>= 6;
2877 id_type = acl_entry_link->entryp->ace_id->id_type;
2880 case SMB_ACL_USER_OBJ:
2881 file_acl->u_access = acl_entry_link->entryp->ace_access;
2883 case SMB_ACL_GROUP_OBJ:
2884 file_acl->g_access = acl_entry_link->entryp->ace_access;
2887 file_acl->o_access = acl_entry_link->entryp->ace_access;
2893 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2894 acl_length += sizeof(struct acl_entry);
2895 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2896 if(file_acl_temp == NULL) {
2897 SAFE_FREE(file_acl);
2899 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2903 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2904 SAFE_FREE(file_acl);
2905 file_acl = file_acl_temp;
2908 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2909 file_acl->acl_len += sizeof(struct acl_entry);
2910 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2911 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2913 /* In order to use this, we'll need to wait until we can get denies */
2914 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2915 acl_entry->ace_type = ACC_SPECIFY; */
2917 acl_entry->ace_type = ACC_SPECIFY;
2919 ace_id = acl_entry->ace_id;
2921 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2922 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2923 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2924 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2925 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2928 rc = chacl(name,file_acl,file_acl->acl_len);
2929 DEBUG(10,("errno is %d\n",errno));
2930 DEBUG(10,("return code is %d\n",rc));
2931 SAFE_FREE(file_acl);
2932 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2936 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2938 struct acl_entry_link *acl_entry_link = NULL;
2939 struct acl *file_acl = NULL;
2940 struct acl *file_acl_temp = NULL;
2941 struct acl_entry *acl_entry = NULL;
2942 struct ace_id *ace_id = NULL;
2948 DEBUG(10,("Entering sys_acl_set_fd\n"));
2949 acl_length = BUFSIZ;
2950 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2952 if(file_acl == NULL) {
2954 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2958 memset(file_acl,0,BUFSIZ);
2960 file_acl->acl_len = ACL_SIZ;
2961 file_acl->acl_mode = S_IXACL;
2963 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2964 acl_entry_link->entryp->ace_access >>= 6;
2965 id_type = acl_entry_link->entryp->ace_id->id_type;
2966 DEBUG(10,("The id_type is %d\n",id_type));
2969 case SMB_ACL_USER_OBJ:
2970 file_acl->u_access = acl_entry_link->entryp->ace_access;
2972 case SMB_ACL_GROUP_OBJ:
2973 file_acl->g_access = acl_entry_link->entryp->ace_access;
2976 file_acl->o_access = acl_entry_link->entryp->ace_access;
2982 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2983 acl_length += sizeof(struct acl_entry);
2984 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2985 if(file_acl_temp == NULL) {
2986 SAFE_FREE(file_acl);
2988 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2992 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2993 SAFE_FREE(file_acl);
2994 file_acl = file_acl_temp;
2997 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2998 file_acl->acl_len += sizeof(struct acl_entry);
2999 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
3000 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
3002 /* In order to use this, we'll need to wait until we can get denies */
3003 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
3004 acl_entry->ace_type = ACC_SPECIFY; */
3006 acl_entry->ace_type = ACC_SPECIFY;
3008 ace_id = acl_entry->ace_id;
3010 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
3011 DEBUG(10,("The id type is %d\n",ace_id->id_type));
3012 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
3013 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
3014 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
3017 rc = fchacl(fd,file_acl,file_acl->acl_len);
3018 DEBUG(10,("errno is %d\n",errno));
3019 DEBUG(10,("return code is %d\n",rc));
3020 SAFE_FREE(file_acl);
3021 DEBUG(10,("Exiting sys_acl_set_fd\n"));
3025 int sys_acl_delete_def_file(const char *name)
3027 /* AIX has no default ACL */
3031 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3033 return(*permset & perm);
3036 int sys_acl_free_text(char *text)
3041 int sys_acl_free_acl(SMB_ACL_T posix_acl)
3043 struct acl_entry_link *acl_entry_link;
3045 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
3046 SAFE_FREE(acl_entry_link->prevp->entryp);
3047 SAFE_FREE(acl_entry_link->prevp);
3050 SAFE_FREE(acl_entry_link->prevp->entryp);
3051 SAFE_FREE(acl_entry_link->prevp);
3052 SAFE_FREE(acl_entry_link->entryp);
3053 SAFE_FREE(acl_entry_link);
3058 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3063 #else /* No ACLs. */
3065 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
3071 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
3077 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
3083 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
3089 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
3092 return (SMB_ACL_T)NULL;
3095 SMB_ACL_T sys_acl_get_fd(int fd)
3098 return (SMB_ACL_T)NULL;
3101 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
3107 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3113 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3116 return (permset & perm) ? 1 : 0;
3119 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
3125 int sys_acl_free_text(char *text)
3131 SMB_ACL_T sys_acl_init( int count)
3137 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
3143 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
3149 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
3155 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
3161 int sys_acl_valid( SMB_ACL_T theacl )
3167 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
3173 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
3179 int sys_acl_delete_def_file(const char *name)
3185 int sys_acl_free_acl(SMB_ACL_T the_acl)
3191 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3197 #endif /* No ACLs. */
3199 /************************************************************************
3200 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
3202 ************************************************************************/
3204 int no_acl_syscall_error(int err)
3207 if (err == ENOSYS) {
3211 #if defined(ENOTSUP)
3212 if (err == ENOTSUP) {