r3773: more low-risk or critical changes from 3.0
[Samba.git] / source / lib / sysacls.c
blob9b5bef00e8acc1250112c63a6361cee850a34a03
1 /*
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.
21 #include "includes.h"
24 This file wraps all differing system ACL interfaces into a consistent
25 one based on the POSIX interface. It also returns the correct errors
26 for older UNIX systems that don't support ACLs.
28 The interfaces that each ACL implementation must support are as follows :
30 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
31 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
32 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p
33 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
34 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
35 SMB_ACL_T sys_acl_get_fd(int fd)
36 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset);
37 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
38 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
39 SMB_ACL_T sys_acl_init( int count)
40 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
41 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
42 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
43 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
44 int sys_acl_valid( SMB_ACL_T theacl )
45 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
46 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
47 int sys_acl_delete_def_file(const char *path)
49 This next one is not POSIX complient - but we *have* to have it !
50 More POSIX braindamage.
52 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
54 The generic POSIX free is the following call. We split this into
55 several different free functions as we may need to add tag info
56 to structures when emulating the POSIX interface.
58 int sys_acl_free( void *obj_p)
60 The calls we actually use are :
62 int sys_acl_free_text(char *text) - free acl_to_text
63 int sys_acl_free_acl(SMB_ACL_T posix_acl)
64 int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
68 #if defined(HAVE_POSIX_ACLS)
70 /* Identity mapping - easy. */
72 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
74 return acl_get_entry( the_acl, entry_id, entry_p);
77 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
79 return acl_get_tag_type( entry_d, tag_type_p);
82 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
84 return acl_get_permset( entry_d, permset_p);
87 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
89 return acl_get_qualifier( entry_d);
92 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
94 return acl_get_file( path_p, type);
97 SMB_ACL_T sys_acl_get_fd(int fd)
99 return acl_get_fd(fd);
102 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
104 return acl_clear_perms(permset);
107 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
109 return acl_add_perm(permset, perm);
112 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
114 #if defined(HAVE_ACL_GET_PERM_NP)
116 * Required for TrustedBSD-based ACL implementations where
117 * non-POSIX.1e functions are denoted by a _np (non-portable)
118 * suffix.
120 return acl_get_perm_np(permset, perm);
121 #else
122 return acl_get_perm(permset, perm);
123 #endif
126 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
128 return acl_to_text( the_acl, plen);
131 SMB_ACL_T sys_acl_init( int count)
133 return acl_init(count);
136 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
138 return acl_create_entry(pacl, pentry);
141 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
143 return acl_set_tag_type(entry, tagtype);
146 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
148 return acl_set_qualifier(entry, qual);
151 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
153 return acl_set_permset(entry, permset);
156 int sys_acl_valid( SMB_ACL_T theacl )
158 return acl_valid(theacl);
161 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
163 return acl_set_file(name, acltype, theacl);
166 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
168 return acl_set_fd(fd, theacl);
171 int sys_acl_delete_def_file(const char *name)
173 return acl_delete_def_file(name);
176 int sys_acl_free_text(char *text)
178 return acl_free(text);
181 int sys_acl_free_acl(SMB_ACL_T the_acl)
183 return acl_free(the_acl);
186 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
188 return acl_free(qual);
191 #elif defined(HAVE_TRU64_ACLS)
193 * The interface to DEC/Compaq Tru64 UNIX ACLs
194 * is based on Draft 13 of the POSIX spec which is
195 * slightly different from the Draft 16 interface.
197 * Also, some of the permset manipulation functions
198 * such as acl_clear_perm() and acl_add_perm() appear
199 * to be broken on Tru64 so we have to manipulate
200 * the permission bits in the permset directly.
202 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
204 SMB_ACL_ENTRY_T entry;
206 if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
207 return -1;
210 errno = 0;
211 if ((entry = acl_get_entry(the_acl)) != NULL) {
212 *entry_p = entry;
213 return 1;
216 return errno ? -1 : 0;
219 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
221 return acl_get_tag_type( entry_d, tag_type_p);
224 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
226 return acl_get_permset( entry_d, permset_p);
229 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
231 return acl_get_qualifier( entry_d);
234 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
236 return acl_get_file((char *)path_p, type);
239 SMB_ACL_T sys_acl_get_fd(int fd)
241 return acl_get_fd(fd, ACL_TYPE_ACCESS);
244 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
246 *permset = 0; /* acl_clear_perm() is broken on Tru64 */
248 return 0;
251 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
253 if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) {
254 errno = EINVAL;
255 return -1;
258 *permset |= perm; /* acl_add_perm() is broken on Tru64 */
260 return 0;
263 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
265 return *permset & perm; /* Tru64 doesn't have acl_get_perm() */
268 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
270 return acl_to_text( the_acl, plen);
273 SMB_ACL_T sys_acl_init( int count)
275 return acl_init(count);
278 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
280 SMB_ACL_ENTRY_T entry;
282 if ((entry = acl_create_entry(pacl)) == NULL) {
283 return -1;
286 *pentry = entry;
287 return 0;
290 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
292 return acl_set_tag_type(entry, tagtype);
295 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
297 return acl_set_qualifier(entry, qual);
300 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
302 return acl_set_permset(entry, permset);
305 int sys_acl_valid( SMB_ACL_T theacl )
307 acl_entry_t entry;
309 return acl_valid(theacl, &entry);
312 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
314 return acl_set_file((char *)name, acltype, theacl);
317 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
319 return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
322 int sys_acl_delete_def_file(const char *name)
324 return acl_delete_def_file((char *)name);
327 int sys_acl_free_text(char *text)
330 * (void) cast and explicit return 0 are for DEC UNIX
331 * which just #defines acl_free_text() to be free()
333 (void) acl_free_text(text);
334 return 0;
337 int sys_acl_free_acl(SMB_ACL_T the_acl)
339 return acl_free(the_acl);
342 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
344 return acl_free_qualifier(qual, tagtype);
347 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
350 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
351 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
355 * Note that while this code implements sufficient functionality
356 * to support the sys_acl_* interfaces it does not provide all
357 * of the semantics of the POSIX ACL interfaces.
359 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
360 * from a call to sys_acl_get_entry() should not be assumed to be
361 * valid after calling any of the following functions, which may
362 * reorder the entries in the ACL.
364 * sys_acl_valid()
365 * sys_acl_set_file()
366 * sys_acl_set_fd()
370 * The only difference between Solaris and UnixWare / OpenUNIX is
371 * that the #defines for the ACL operations have different names
373 #if defined(HAVE_UNIXWARE_ACLS)
375 #define SETACL ACL_SET
376 #define GETACL ACL_GET
377 #define GETACLCNT ACL_CNT
379 #endif
382 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
384 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
385 errno = EINVAL;
386 return -1;
389 if (entry_p == NULL) {
390 errno = EINVAL;
391 return -1;
394 if (entry_id == SMB_ACL_FIRST_ENTRY) {
395 acl_d->next = 0;
398 if (acl_d->next < 0) {
399 errno = EINVAL;
400 return -1;
403 if (acl_d->next >= acl_d->count) {
404 return 0;
407 *entry_p = &acl_d->acl[acl_d->next++];
409 return 1;
412 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
414 *type_p = entry_d->a_type;
416 return 0;
419 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
421 *permset_p = &entry_d->a_perm;
423 return 0;
426 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
428 if (entry_d->a_type != SMB_ACL_USER
429 && entry_d->a_type != SMB_ACL_GROUP) {
430 errno = EINVAL;
431 return NULL;
434 return &entry_d->a_id;
438 * There is no way of knowing what size the ACL returned by
439 * GETACL will be unless you first call GETACLCNT which means
440 * making an additional system call.
442 * In the hope of avoiding the cost of the additional system
443 * call in most cases, we initially allocate enough space for
444 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
445 * be too small then we use GETACLCNT to find out the actual
446 * size, reallocate the ACL buffer, and then call GETACL again.
449 #define INITIAL_ACL_SIZE 16
451 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
453 SMB_ACL_T acl_d;
454 int count; /* # of ACL entries allocated */
455 int naccess; /* # of access ACL entries */
456 int ndefault; /* # of default ACL entries */
458 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
459 errno = EINVAL;
460 return NULL;
463 count = INITIAL_ACL_SIZE;
464 if ((acl_d = sys_acl_init(count)) == NULL) {
465 return NULL;
469 * If there isn't enough space for the ACL entries we use
470 * GETACLCNT to determine the actual number of ACL entries
471 * reallocate and try again. This is in a loop because it
472 * is possible that someone else could modify the ACL and
473 * increase the number of entries between the call to
474 * GETACLCNT and the call to GETACL.
476 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
477 && errno == ENOSPC) {
479 sys_acl_free_acl(acl_d);
481 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
482 return NULL;
485 if ((acl_d = sys_acl_init(count)) == NULL) {
486 return NULL;
490 if (count < 0) {
491 sys_acl_free_acl(acl_d);
492 return NULL;
496 * calculate the number of access and default ACL entries
498 * Note: we assume that the acl() system call returned a
499 * well formed ACL which is sorted so that all of the
500 * access ACL entries preceed any default ACL entries
502 for (naccess = 0; naccess < count; naccess++) {
503 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
504 break;
506 ndefault = count - naccess;
509 * if the caller wants the default ACL we have to copy
510 * the entries down to the start of the acl[] buffer
511 * and mask out the ACL_DEFAULT flag from the type field
513 if (type == SMB_ACL_TYPE_DEFAULT) {
514 int i, j;
516 for (i = 0, j = naccess; i < ndefault; i++, j++) {
517 acl_d->acl[i] = acl_d->acl[j];
518 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
521 acl_d->count = ndefault;
522 } else {
523 acl_d->count = naccess;
526 return acl_d;
529 SMB_ACL_T sys_acl_get_fd(int fd)
531 SMB_ACL_T acl_d;
532 int count; /* # of ACL entries allocated */
533 int naccess; /* # of access ACL entries */
535 count = INITIAL_ACL_SIZE;
536 if ((acl_d = sys_acl_init(count)) == NULL) {
537 return NULL;
540 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
541 && errno == ENOSPC) {
543 sys_acl_free_acl(acl_d);
545 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
546 return NULL;
549 if ((acl_d = sys_acl_init(count)) == NULL) {
550 return NULL;
554 if (count < 0) {
555 sys_acl_free_acl(acl_d);
556 return NULL;
560 * calculate the number of access ACL entries
562 for (naccess = 0; naccess < count; naccess++) {
563 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
564 break;
567 acl_d->count = naccess;
569 return acl_d;
572 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
574 *permset_d = 0;
576 return 0;
579 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
581 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
582 && perm != SMB_ACL_EXECUTE) {
583 errno = EINVAL;
584 return -1;
587 if (permset_d == NULL) {
588 errno = EINVAL;
589 return -1;
592 *permset_d |= perm;
594 return 0;
597 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
599 return *permset_d & perm;
602 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
604 int i;
605 int len, maxlen;
606 char *text;
609 * use an initial estimate of 20 bytes per ACL entry
610 * when allocating memory for the text representation
611 * of the ACL
613 len = 0;
614 maxlen = 20 * acl_d->count;
615 if ((text = malloc(maxlen)) == NULL) {
616 errno = ENOMEM;
617 return NULL;
620 for (i = 0; i < acl_d->count; i++) {
621 struct acl *ap = &acl_d->acl[i];
622 struct passwd *pw;
623 struct group *gr;
624 char tagbuf[12];
625 char idbuf[12];
626 char *tag;
627 char *id = "";
628 char perms[4];
629 int nbytes;
631 switch (ap->a_type) {
633 * for debugging purposes it's probably more
634 * useful to dump unknown tag types rather
635 * than just returning an error
637 default:
638 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
639 ap->a_type);
640 tag = tagbuf;
641 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
642 (long)ap->a_id);
643 id = idbuf;
644 break;
646 case SMB_ACL_USER:
647 id = uidtoname(ap->a_id);
648 case SMB_ACL_USER_OBJ:
649 tag = "user";
650 break;
652 case SMB_ACL_GROUP:
653 if ((gr = getgrgid(ap->a_id)) == NULL) {
654 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
655 (long)ap->a_id);
656 id = idbuf;
657 } else {
658 id = gr->gr_name;
660 case SMB_ACL_GROUP_OBJ:
661 tag = "group";
662 break;
664 case SMB_ACL_OTHER:
665 tag = "other";
666 break;
668 case SMB_ACL_MASK:
669 tag = "mask";
670 break;
674 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
675 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
676 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
677 perms[3] = '\0';
679 /* <tag> : <qualifier> : rwx \n \0 */
680 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
683 * If this entry would overflow the buffer
684 * allocate enough additional memory for this
685 * entry and an estimate of another 20 bytes
686 * for each entry still to be processed
688 if ((len + nbytes) > maxlen) {
689 char *oldtext = text;
691 maxlen += nbytes + 20 * (acl_d->count - i);
693 if ((text = Realloc(oldtext, maxlen)) == NULL) {
694 SAFE_FREE(oldtext);
695 errno = ENOMEM;
696 return NULL;
700 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
701 len += nbytes - 1;
704 if (len_p)
705 *len_p = len;
707 return text;
710 SMB_ACL_T sys_acl_init(int count)
712 SMB_ACL_T a;
714 if (count < 0) {
715 errno = EINVAL;
716 return NULL;
720 * note that since the definition of the structure pointed
721 * to by the SMB_ACL_T includes the first element of the
722 * acl[] array, this actually allocates an ACL with room
723 * for (count+1) entries
725 if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) {
726 errno = ENOMEM;
727 return NULL;
730 a->size = count + 1;
731 a->count = 0;
732 a->next = -1;
734 return a;
738 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
740 SMB_ACL_T acl_d;
741 SMB_ACL_ENTRY_T entry_d;
743 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
744 errno = EINVAL;
745 return -1;
748 if (acl_d->count >= acl_d->size) {
749 errno = ENOSPC;
750 return -1;
753 entry_d = &acl_d->acl[acl_d->count++];
754 entry_d->a_type = 0;
755 entry_d->a_id = -1;
756 entry_d->a_perm = 0;
757 *entry_p = entry_d;
759 return 0;
762 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
764 switch (tag_type) {
765 case SMB_ACL_USER:
766 case SMB_ACL_USER_OBJ:
767 case SMB_ACL_GROUP:
768 case SMB_ACL_GROUP_OBJ:
769 case SMB_ACL_OTHER:
770 case SMB_ACL_MASK:
771 entry_d->a_type = tag_type;
772 break;
773 default:
774 errno = EINVAL;
775 return -1;
778 return 0;
781 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
783 if (entry_d->a_type != SMB_ACL_GROUP
784 && entry_d->a_type != SMB_ACL_USER) {
785 errno = EINVAL;
786 return -1;
789 entry_d->a_id = *((id_t *)qual_p);
791 return 0;
794 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
796 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
797 return EINVAL;
800 entry_d->a_perm = *permset_d;
802 return 0;
806 * sort the ACL and check it for validity
808 * if it's a minimal ACL with only 4 entries then we
809 * need to recalculate the mask permissions to make
810 * sure that they are the same as the GROUP_OBJ
811 * permissions as required by the UnixWare acl() system call.
813 * (note: since POSIX allows minimal ACLs which only contain
814 * 3 entries - ie there is no mask entry - we should, in theory,
815 * check for this and add a mask entry if necessary - however
816 * we "know" that the caller of this interface always specifies
817 * a mask so, in practice "this never happens" (tm) - if it *does*
818 * happen aclsort() will fail and return an error and someone will
819 * have to fix it ...)
822 static int acl_sort(SMB_ACL_T acl_d)
824 int fixmask = (acl_d->count <= 4);
826 if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
827 errno = EINVAL;
828 return -1;
830 return 0;
833 int sys_acl_valid(SMB_ACL_T acl_d)
835 return acl_sort(acl_d);
838 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
840 struct stat s;
841 struct acl *acl_p;
842 int acl_count;
843 struct acl *acl_buf = NULL;
844 int ret;
846 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
847 errno = EINVAL;
848 return -1;
851 if (acl_sort(acl_d) != 0) {
852 return -1;
855 acl_p = &acl_d->acl[0];
856 acl_count = acl_d->count;
859 * if it's a directory there is extra work to do
860 * since the acl() system call will replace both
861 * the access ACLs and the default ACLs (if any)
863 if (stat(name, &s) != 0) {
864 return -1;
866 if (S_ISDIR(s.st_mode)) {
867 SMB_ACL_T acc_acl;
868 SMB_ACL_T def_acl;
869 SMB_ACL_T tmp_acl;
870 int i;
872 if (type == SMB_ACL_TYPE_ACCESS) {
873 acc_acl = acl_d;
874 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
876 } else {
877 def_acl = acl_d;
878 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
881 if (tmp_acl == NULL) {
882 return -1;
886 * allocate a temporary buffer for the complete ACL
888 acl_count = acc_acl->count + def_acl->count;
889 acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0]));
891 if (acl_buf == NULL) {
892 sys_acl_free_acl(tmp_acl);
893 errno = ENOMEM;
894 return -1;
898 * copy the access control and default entries into the buffer
900 memcpy(&acl_buf[0], &acc_acl->acl[0],
901 acc_acl->count * sizeof(acl_buf[0]));
903 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
904 def_acl->count * sizeof(acl_buf[0]));
907 * set the ACL_DEFAULT flag on the default entries
909 for (i = acc_acl->count; i < acl_count; i++) {
910 acl_buf[i].a_type |= ACL_DEFAULT;
913 sys_acl_free_acl(tmp_acl);
915 } else if (type != SMB_ACL_TYPE_ACCESS) {
916 errno = EINVAL;
917 return -1;
920 ret = acl(name, SETACL, acl_count, acl_p);
922 SAFE_FREE(acl_buf);
924 return ret;
927 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
929 if (acl_sort(acl_d) != 0) {
930 return -1;
933 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
936 int sys_acl_delete_def_file(const char *path)
938 SMB_ACL_T acl_d;
939 int ret;
942 * fetching the access ACL and rewriting it has
943 * the effect of deleting the default ACL
945 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
946 return -1;
949 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
951 sys_acl_free_acl(acl_d);
953 return ret;
956 int sys_acl_free_text(char *text)
958 SAFE_FREE(text);
959 return 0;
962 int sys_acl_free_acl(SMB_ACL_T acl_d)
964 SAFE_FREE(acl_d);
965 return 0;
968 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
970 return 0;
973 #elif defined(HAVE_HPUX_ACLS)
974 #include <dl.h>
977 * Based on the Solaris/SCO code - with modifications.
981 * Note that while this code implements sufficient functionality
982 * to support the sys_acl_* interfaces it does not provide all
983 * of the semantics of the POSIX ACL interfaces.
985 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
986 * from a call to sys_acl_get_entry() should not be assumed to be
987 * valid after calling any of the following functions, which may
988 * reorder the entries in the ACL.
990 * sys_acl_valid()
991 * sys_acl_set_file()
992 * sys_acl_set_fd()
995 /* This checks if the POSIX ACL system call is defined */
996 /* which basically corresponds to whether JFS 3.3 or */
997 /* higher is installed. If acl() was called when it */
998 /* isn't defined, it causes the process to core dump */
999 /* so it is important to check this and avoid acl() */
1000 /* calls if it isn't there. */
1002 static BOOL hpux_acl_call_presence(void)
1005 shl_t handle = NULL;
1006 void *value;
1007 int ret_val=0;
1008 static BOOL already_checked=0;
1010 if(already_checked)
1011 return True;
1014 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
1016 if(ret_val != 0) {
1017 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
1018 ret_val, errno, strerror(errno)));
1019 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
1020 return False;
1023 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
1025 already_checked = True;
1026 return True;
1029 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1031 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1032 errno = EINVAL;
1033 return -1;
1036 if (entry_p == NULL) {
1037 errno = EINVAL;
1038 return -1;
1041 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1042 acl_d->next = 0;
1045 if (acl_d->next < 0) {
1046 errno = EINVAL;
1047 return -1;
1050 if (acl_d->next >= acl_d->count) {
1051 return 0;
1054 *entry_p = &acl_d->acl[acl_d->next++];
1056 return 1;
1059 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1061 *type_p = entry_d->a_type;
1063 return 0;
1066 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1068 *permset_p = &entry_d->a_perm;
1070 return 0;
1073 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1075 if (entry_d->a_type != SMB_ACL_USER
1076 && entry_d->a_type != SMB_ACL_GROUP) {
1077 errno = EINVAL;
1078 return NULL;
1081 return &entry_d->a_id;
1085 * There is no way of knowing what size the ACL returned by
1086 * ACL_GET will be unless you first call ACL_CNT which means
1087 * making an additional system call.
1089 * In the hope of avoiding the cost of the additional system
1090 * call in most cases, we initially allocate enough space for
1091 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
1092 * be too small then we use ACL_CNT to find out the actual
1093 * size, reallocate the ACL buffer, and then call ACL_GET again.
1096 #define INITIAL_ACL_SIZE 16
1098 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1100 SMB_ACL_T acl_d;
1101 int count; /* # of ACL entries allocated */
1102 int naccess; /* # of access ACL entries */
1103 int ndefault; /* # of default ACL entries */
1105 if(hpux_acl_call_presence() == False) {
1106 /* Looks like we don't have the acl() system call on HPUX.
1107 * May be the system doesn't have the latest version of JFS.
1109 return NULL;
1112 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1113 errno = EINVAL;
1114 return NULL;
1117 count = INITIAL_ACL_SIZE;
1118 if ((acl_d = sys_acl_init(count)) == NULL) {
1119 return NULL;
1123 * If there isn't enough space for the ACL entries we use
1124 * ACL_CNT to determine the actual number of ACL entries
1125 * reallocate and try again. This is in a loop because it
1126 * is possible that someone else could modify the ACL and
1127 * increase the number of entries between the call to
1128 * ACL_CNT and the call to ACL_GET.
1130 while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
1132 sys_acl_free_acl(acl_d);
1134 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
1135 return NULL;
1138 if ((acl_d = sys_acl_init(count)) == NULL) {
1139 return NULL;
1143 if (count < 0) {
1144 sys_acl_free_acl(acl_d);
1145 return NULL;
1149 * calculate the number of access and default ACL entries
1151 * Note: we assume that the acl() system call returned a
1152 * well formed ACL which is sorted so that all of the
1153 * access ACL entries preceed any default ACL entries
1155 for (naccess = 0; naccess < count; naccess++) {
1156 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
1157 break;
1159 ndefault = count - naccess;
1162 * if the caller wants the default ACL we have to copy
1163 * the entries down to the start of the acl[] buffer
1164 * and mask out the ACL_DEFAULT flag from the type field
1166 if (type == SMB_ACL_TYPE_DEFAULT) {
1167 int i, j;
1169 for (i = 0, j = naccess; i < ndefault; i++, j++) {
1170 acl_d->acl[i] = acl_d->acl[j];
1171 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
1174 acl_d->count = ndefault;
1175 } else {
1176 acl_d->count = naccess;
1179 return acl_d;
1182 SMB_ACL_T sys_acl_get_fd(int fd)
1185 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1188 files_struct *fsp = file_find_fd(fd);
1190 if (fsp == NULL) {
1191 errno = EBADF;
1192 return NULL;
1196 * We know we're in the same conn context. So we
1197 * can use the relative path.
1200 return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
1203 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
1205 *permset_d = 0;
1207 return 0;
1210 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1212 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
1213 && perm != SMB_ACL_EXECUTE) {
1214 errno = EINVAL;
1215 return -1;
1218 if (permset_d == NULL) {
1219 errno = EINVAL;
1220 return -1;
1223 *permset_d |= perm;
1225 return 0;
1228 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1230 return *permset_d & perm;
1233 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
1235 int i;
1236 int len, maxlen;
1237 char *text;
1240 * use an initial estimate of 20 bytes per ACL entry
1241 * when allocating memory for the text representation
1242 * of the ACL
1244 len = 0;
1245 maxlen = 20 * acl_d->count;
1246 if ((text = malloc(maxlen)) == NULL) {
1247 errno = ENOMEM;
1248 return NULL;
1251 for (i = 0; i < acl_d->count; i++) {
1252 struct acl *ap = &acl_d->acl[i];
1253 struct passwd *pw;
1254 struct group *gr;
1255 char tagbuf[12];
1256 char idbuf[12];
1257 char *tag;
1258 char *id = "";
1259 char perms[4];
1260 int nbytes;
1262 switch (ap->a_type) {
1264 * for debugging purposes it's probably more
1265 * useful to dump unknown tag types rather
1266 * than just returning an error
1268 default:
1269 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
1270 ap->a_type);
1271 tag = tagbuf;
1272 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1273 (long)ap->a_id);
1274 id = idbuf;
1275 break;
1277 case SMB_ACL_USER:
1278 id = uidtoname(ap->a_id);
1279 case SMB_ACL_USER_OBJ:
1280 tag = "user";
1281 break;
1283 case SMB_ACL_GROUP:
1284 if ((gr = getgrgid(ap->a_id)) == NULL) {
1285 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1286 (long)ap->a_id);
1287 id = idbuf;
1288 } else {
1289 id = gr->gr_name;
1291 case SMB_ACL_GROUP_OBJ:
1292 tag = "group";
1293 break;
1295 case SMB_ACL_OTHER:
1296 tag = "other";
1297 break;
1299 case SMB_ACL_MASK:
1300 tag = "mask";
1301 break;
1305 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
1306 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
1307 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
1308 perms[3] = '\0';
1310 /* <tag> : <qualifier> : rwx \n \0 */
1311 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
1314 * If this entry would overflow the buffer
1315 * allocate enough additional memory for this
1316 * entry and an estimate of another 20 bytes
1317 * for each entry still to be processed
1319 if ((len + nbytes) > maxlen) {
1320 char *oldtext = text;
1322 maxlen += nbytes + 20 * (acl_d->count - i);
1324 if ((text = Realloc(oldtext, maxlen)) == NULL) {
1325 free(oldtext);
1326 errno = ENOMEM;
1327 return NULL;
1331 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
1332 len += nbytes - 1;
1335 if (len_p)
1336 *len_p = len;
1338 return text;
1341 SMB_ACL_T sys_acl_init(int count)
1343 SMB_ACL_T a;
1345 if (count < 0) {
1346 errno = EINVAL;
1347 return NULL;
1351 * note that since the definition of the structure pointed
1352 * to by the SMB_ACL_T includes the first element of the
1353 * acl[] array, this actually allocates an ACL with room
1354 * for (count+1) entries
1356 if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) {
1357 errno = ENOMEM;
1358 return NULL;
1361 a->size = count + 1;
1362 a->count = 0;
1363 a->next = -1;
1365 return a;
1369 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1371 SMB_ACL_T acl_d;
1372 SMB_ACL_ENTRY_T entry_d;
1374 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1375 errno = EINVAL;
1376 return -1;
1379 if (acl_d->count >= acl_d->size) {
1380 errno = ENOSPC;
1381 return -1;
1384 entry_d = &acl_d->acl[acl_d->count++];
1385 entry_d->a_type = 0;
1386 entry_d->a_id = -1;
1387 entry_d->a_perm = 0;
1388 *entry_p = entry_d;
1390 return 0;
1393 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1395 switch (tag_type) {
1396 case SMB_ACL_USER:
1397 case SMB_ACL_USER_OBJ:
1398 case SMB_ACL_GROUP:
1399 case SMB_ACL_GROUP_OBJ:
1400 case SMB_ACL_OTHER:
1401 case SMB_ACL_MASK:
1402 entry_d->a_type = tag_type;
1403 break;
1404 default:
1405 errno = EINVAL;
1406 return -1;
1409 return 0;
1412 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1414 if (entry_d->a_type != SMB_ACL_GROUP
1415 && entry_d->a_type != SMB_ACL_USER) {
1416 errno = EINVAL;
1417 return -1;
1420 entry_d->a_id = *((id_t *)qual_p);
1422 return 0;
1425 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1427 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1428 return EINVAL;
1431 entry_d->a_perm = *permset_d;
1433 return 0;
1436 /* Structure to capture the count for each type of ACE. */
1438 struct hpux_acl_types {
1439 int n_user;
1440 int n_def_user;
1441 int n_user_obj;
1442 int n_def_user_obj;
1444 int n_group;
1445 int n_def_group;
1446 int n_group_obj;
1447 int n_def_group_obj;
1449 int n_other;
1450 int n_other_obj;
1451 int n_def_other_obj;
1453 int n_class_obj;
1454 int n_def_class_obj;
1456 int n_illegal_obj;
1459 /* count_obj:
1460 * Counts the different number of objects in a given array of ACL
1461 * structures.
1462 * Inputs:
1464 * acl_count - Count of ACLs in the array of ACL strucutres.
1465 * aclp - Array of ACL structures.
1466 * acl_type_count - Pointer to acl_types structure. Should already be
1467 * allocated.
1468 * Output:
1470 * acl_type_count - This structure is filled up with counts of various
1471 * acl types.
1474 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1476 int i;
1478 memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1480 for(i=0;i<acl_count;i++) {
1481 switch(aclp[i].a_type) {
1482 case USER:
1483 acl_type_count->n_user++;
1484 break;
1485 case USER_OBJ:
1486 acl_type_count->n_user_obj++;
1487 break;
1488 case DEF_USER_OBJ:
1489 acl_type_count->n_def_user_obj++;
1490 break;
1491 case GROUP:
1492 acl_type_count->n_group++;
1493 break;
1494 case GROUP_OBJ:
1495 acl_type_count->n_group_obj++;
1496 break;
1497 case DEF_GROUP_OBJ:
1498 acl_type_count->n_def_group_obj++;
1499 break;
1500 case OTHER_OBJ:
1501 acl_type_count->n_other_obj++;
1502 break;
1503 case DEF_OTHER_OBJ:
1504 acl_type_count->n_def_other_obj++;
1505 break;
1506 case CLASS_OBJ:
1507 acl_type_count->n_class_obj++;
1508 break;
1509 case DEF_CLASS_OBJ:
1510 acl_type_count->n_def_class_obj++;
1511 break;
1512 case DEF_USER:
1513 acl_type_count->n_def_user++;
1514 break;
1515 case DEF_GROUP:
1516 acl_type_count->n_def_group++;
1517 break;
1518 default:
1519 acl_type_count->n_illegal_obj++;
1520 break;
1525 /* swap_acl_entries: Swaps two ACL entries.
1527 * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1530 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1532 struct acl temp_acl;
1534 temp_acl.a_type = aclp0->a_type;
1535 temp_acl.a_id = aclp0->a_id;
1536 temp_acl.a_perm = aclp0->a_perm;
1538 aclp0->a_type = aclp1->a_type;
1539 aclp0->a_id = aclp1->a_id;
1540 aclp0->a_perm = aclp1->a_perm;
1542 aclp1->a_type = temp_acl.a_type;
1543 aclp1->a_id = temp_acl.a_id;
1544 aclp1->a_perm = temp_acl.a_perm;
1547 /* prohibited_duplicate_type
1548 * Identifies if given ACL type can have duplicate entries or
1549 * not.
1551 * Inputs: acl_type - ACL Type.
1553 * Outputs:
1555 * Return..
1557 * True - If the ACL type matches any of the prohibited types.
1558 * False - If the ACL type doesn't match any of the prohibited types.
1561 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1563 switch(acl_type) {
1564 case USER:
1565 case GROUP:
1566 case DEF_USER:
1567 case DEF_GROUP:
1568 return True;
1569 default:
1570 return False;
1574 /* get_needed_class_perm
1575 * Returns the permissions of a ACL structure only if the ACL
1576 * type matches one of the pre-determined types for computing
1577 * CLASS_OBJ permissions.
1579 * Inputs: aclp - Pointer to ACL structure.
1582 static int hpux_get_needed_class_perm(struct acl *aclp)
1584 switch(aclp->a_type) {
1585 case USER:
1586 case GROUP_OBJ:
1587 case GROUP:
1588 case DEF_USER_OBJ:
1589 case DEF_USER:
1590 case DEF_GROUP_OBJ:
1591 case DEF_GROUP:
1592 case DEF_CLASS_OBJ:
1593 case DEF_OTHER_OBJ:
1594 return aclp->a_perm;
1595 default:
1596 return 0;
1600 /* acl_sort for HPUX.
1601 * Sorts the array of ACL structures as per the description in
1602 * aclsort man page. Refer to aclsort man page for more details
1604 * Inputs:
1606 * acl_count - Count of ACLs in the array of ACL structures.
1607 * calclass - If this is not zero, then we compute the CLASS_OBJ
1608 * permissions.
1609 * aclp - Array of ACL structures.
1611 * Outputs:
1613 * aclp - Sorted array of ACL structures.
1615 * Outputs:
1617 * Returns 0 for success -1 for failure. Prints a message to the Samba
1618 * debug log in case of failure.
1621 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1623 #if !defined(HAVE_HPUX_ACLSORT)
1625 * The aclsort() system call is availabe on the latest HPUX General
1626 * Patch Bundles. So for HPUX, we developed our version of acl_sort
1627 * function. Because, we don't want to update to a new
1628 * HPUX GR bundle just for aclsort() call.
1631 struct hpux_acl_types acl_obj_count;
1632 int n_class_obj_perm = 0;
1633 int i, j;
1635 if(!acl_count) {
1636 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1637 return 0;
1640 if(aclp == NULL) {
1641 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1642 return -1;
1645 /* Count different types of ACLs in the ACLs array */
1647 hpux_count_obj(acl_count, aclp, &acl_obj_count);
1649 /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
1650 * CLASS_OBJ and OTHER_OBJ
1653 if( (acl_obj_count.n_user_obj != 1) ||
1654 (acl_obj_count.n_group_obj != 1) ||
1655 (acl_obj_count.n_class_obj != 1) ||
1656 (acl_obj_count.n_other_obj != 1)
1658 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1659 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1660 return -1;
1663 /* If any of the default objects are present, there should be only
1664 * one of them each.
1667 if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
1668 (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1669 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1670 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1671 return -1;
1674 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1675 * structures.
1677 * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1678 * same ACL type, sort by ACL id.
1680 * I am using the trival kind of sorting method here because, performance isn't
1681 * really effected by the ACLs feature. More over there aren't going to be more
1682 * than 17 entries on HPUX.
1685 for(i=0; i<acl_count;i++) {
1686 for (j=i+1; j<acl_count; j++) {
1687 if( aclp[i].a_type > aclp[j].a_type ) {
1688 /* ACL entries out of order, swap them */
1690 hpux_swap_acl_entries((aclp+i), (aclp+j));
1692 } else if ( aclp[i].a_type == aclp[j].a_type ) {
1694 /* ACL entries of same type, sort by id */
1696 if(aclp[i].a_id > aclp[j].a_id) {
1697 hpux_swap_acl_entries((aclp+i), (aclp+j));
1698 } else if (aclp[i].a_id == aclp[j].a_id) {
1699 /* We have a duplicate entry. */
1700 if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1701 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1702 aclp[i].a_type, aclp[i].a_id));
1703 return -1;
1711 /* set the class obj permissions to the computed one. */
1712 if(calclass) {
1713 int n_class_obj_index = -1;
1715 for(i=0;i<acl_count;i++) {
1716 n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1718 if(aclp[i].a_type == CLASS_OBJ)
1719 n_class_obj_index = i;
1721 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1724 return 0;
1725 #else
1726 return aclsort(acl_count, calclass, aclp);
1727 #endif
1731 * sort the ACL and check it for validity
1733 * if it's a minimal ACL with only 4 entries then we
1734 * need to recalculate the mask permissions to make
1735 * sure that they are the same as the GROUP_OBJ
1736 * permissions as required by the UnixWare acl() system call.
1738 * (note: since POSIX allows minimal ACLs which only contain
1739 * 3 entries - ie there is no mask entry - we should, in theory,
1740 * check for this and add a mask entry if necessary - however
1741 * we "know" that the caller of this interface always specifies
1742 * a mask so, in practice "this never happens" (tm) - if it *does*
1743 * happen aclsort() will fail and return an error and someone will
1744 * have to fix it ...)
1747 static int acl_sort(SMB_ACL_T acl_d)
1749 int fixmask = (acl_d->count <= 4);
1751 if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1752 errno = EINVAL;
1753 return -1;
1755 return 0;
1758 int sys_acl_valid(SMB_ACL_T acl_d)
1760 return acl_sort(acl_d);
1763 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1765 struct stat s;
1766 struct acl *acl_p;
1767 int acl_count;
1768 struct acl *acl_buf = NULL;
1769 int ret;
1771 if(hpux_acl_call_presence() == False) {
1772 /* Looks like we don't have the acl() system call on HPUX.
1773 * May be the system doesn't have the latest version of JFS.
1775 errno=ENOSYS;
1776 return -1;
1779 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1780 errno = EINVAL;
1781 return -1;
1784 if (acl_sort(acl_d) != 0) {
1785 return -1;
1788 acl_p = &acl_d->acl[0];
1789 acl_count = acl_d->count;
1792 * if it's a directory there is extra work to do
1793 * since the acl() system call will replace both
1794 * the access ACLs and the default ACLs (if any)
1796 if (stat(name, &s) != 0) {
1797 return -1;
1799 if (S_ISDIR(s.st_mode)) {
1800 SMB_ACL_T acc_acl;
1801 SMB_ACL_T def_acl;
1802 SMB_ACL_T tmp_acl;
1803 int i;
1805 if (type == SMB_ACL_TYPE_ACCESS) {
1806 acc_acl = acl_d;
1807 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1809 } else {
1810 def_acl = acl_d;
1811 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1814 if (tmp_acl == NULL) {
1815 return -1;
1819 * allocate a temporary buffer for the complete ACL
1821 acl_count = acc_acl->count + def_acl->count;
1822 acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0]));
1824 if (acl_buf == NULL) {
1825 sys_acl_free_acl(tmp_acl);
1826 errno = ENOMEM;
1827 return -1;
1831 * copy the access control and default entries into the buffer
1833 memcpy(&acl_buf[0], &acc_acl->acl[0],
1834 acc_acl->count * sizeof(acl_buf[0]));
1836 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1837 def_acl->count * sizeof(acl_buf[0]));
1840 * set the ACL_DEFAULT flag on the default entries
1842 for (i = acc_acl->count; i < acl_count; i++) {
1843 acl_buf[i].a_type |= ACL_DEFAULT;
1846 sys_acl_free_acl(tmp_acl);
1848 } else if (type != SMB_ACL_TYPE_ACCESS) {
1849 errno = EINVAL;
1850 return -1;
1853 ret = acl(name, ACL_SET, acl_count, acl_p);
1855 if (acl_buf) {
1856 free(acl_buf);
1859 return ret;
1862 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1865 * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1868 files_struct *fsp = file_find_fd(fd);
1870 if (fsp == NULL) {
1871 errno = EBADF;
1872 return NULL;
1875 if (acl_sort(acl_d) != 0) {
1876 return -1;
1880 * We know we're in the same conn context. So we
1881 * can use the relative path.
1884 return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1887 int sys_acl_delete_def_file(const char *path)
1889 SMB_ACL_T acl_d;
1890 int ret;
1893 * fetching the access ACL and rewriting it has
1894 * the effect of deleting the default ACL
1896 if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1897 return -1;
1900 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1902 sys_acl_free_acl(acl_d);
1904 return ret;
1907 int sys_acl_free_text(char *text)
1909 free(text);
1910 return 0;
1913 int sys_acl_free_acl(SMB_ACL_T acl_d)
1915 free(acl_d);
1916 return 0;
1919 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1921 return 0;
1924 #elif defined(HAVE_IRIX_ACLS)
1926 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1928 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1929 errno = EINVAL;
1930 return -1;
1933 if (entry_p == NULL) {
1934 errno = EINVAL;
1935 return -1;
1938 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1939 acl_d->next = 0;
1942 if (acl_d->next < 0) {
1943 errno = EINVAL;
1944 return -1;
1947 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1948 return 0;
1951 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1953 return 1;
1956 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1958 *type_p = entry_d->ae_tag;
1960 return 0;
1963 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1965 *permset_p = entry_d;
1967 return 0;
1970 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1972 if (entry_d->ae_tag != SMB_ACL_USER
1973 && entry_d->ae_tag != SMB_ACL_GROUP) {
1974 errno = EINVAL;
1975 return NULL;
1978 return &entry_d->ae_id;
1981 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1983 SMB_ACL_T a;
1985 if ((a = malloc(sizeof(*a))) == NULL) {
1986 errno = ENOMEM;
1987 return NULL;
1989 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1990 SAFE_FREE(a);
1991 return NULL;
1993 a->next = -1;
1994 a->freeaclp = True;
1995 return a;
1998 SMB_ACL_T sys_acl_get_fd(int fd)
2000 SMB_ACL_T a;
2002 if ((a = malloc(sizeof(*a))) == NULL) {
2003 errno = ENOMEM;
2004 return NULL;
2006 if ((a->aclp = acl_get_fd(fd)) == NULL) {
2007 SAFE_FREE(a);
2008 return NULL;
2010 a->next = -1;
2011 a->freeaclp = True;
2012 return a;
2015 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
2017 permset_d->ae_perm = 0;
2019 return 0;
2022 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2024 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
2025 && perm != SMB_ACL_EXECUTE) {
2026 errno = EINVAL;
2027 return -1;
2030 if (permset_d == NULL) {
2031 errno = EINVAL;
2032 return -1;
2035 permset_d->ae_perm |= perm;
2037 return 0;
2040 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
2042 return permset_d->ae_perm & perm;
2045 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
2047 return acl_to_text(acl_d->aclp, len_p);
2050 SMB_ACL_T sys_acl_init(int count)
2052 SMB_ACL_T a;
2054 if (count < 0) {
2055 errno = EINVAL;
2056 return NULL;
2059 if ((a = malloc(sizeof(*a) + sizeof(struct acl))) == NULL) {
2060 errno = ENOMEM;
2061 return NULL;
2064 a->next = -1;
2065 a->freeaclp = False;
2066 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
2067 a->aclp->acl_cnt = 0;
2069 return a;
2073 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
2075 SMB_ACL_T acl_d;
2076 SMB_ACL_ENTRY_T entry_d;
2078 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
2079 errno = EINVAL;
2080 return -1;
2083 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
2084 errno = ENOSPC;
2085 return -1;
2088 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
2089 entry_d->ae_tag = 0;
2090 entry_d->ae_id = 0;
2091 entry_d->ae_perm = 0;
2092 *entry_p = entry_d;
2094 return 0;
2097 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
2099 switch (tag_type) {
2100 case SMB_ACL_USER:
2101 case SMB_ACL_USER_OBJ:
2102 case SMB_ACL_GROUP:
2103 case SMB_ACL_GROUP_OBJ:
2104 case SMB_ACL_OTHER:
2105 case SMB_ACL_MASK:
2106 entry_d->ae_tag = tag_type;
2107 break;
2108 default:
2109 errno = EINVAL;
2110 return -1;
2113 return 0;
2116 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
2118 if (entry_d->ae_tag != SMB_ACL_GROUP
2119 && entry_d->ae_tag != SMB_ACL_USER) {
2120 errno = EINVAL;
2121 return -1;
2124 entry_d->ae_id = *((id_t *)qual_p);
2126 return 0;
2129 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
2131 if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
2132 return EINVAL;
2135 entry_d->ae_perm = permset_d->ae_perm;
2137 return 0;
2140 int sys_acl_valid(SMB_ACL_T acl_d)
2142 return acl_valid(acl_d->aclp);
2145 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
2147 return acl_set_file(name, type, acl_d->aclp);
2150 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
2152 return acl_set_fd(fd, acl_d->aclp);
2155 int sys_acl_delete_def_file(const char *name)
2157 return acl_delete_def_file(name);
2160 int sys_acl_free_text(char *text)
2162 return acl_free(text);
2165 int sys_acl_free_acl(SMB_ACL_T acl_d)
2167 if (acl_d->freeaclp) {
2168 acl_free(acl_d->aclp);
2170 acl_free(acl_d);
2171 return 0;
2174 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2176 return 0;
2179 #elif defined(HAVE_AIX_ACLS)
2181 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
2183 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2185 struct acl_entry_link *link;
2186 struct new_acl_entry *entry;
2187 int keep_going;
2189 DEBUG(10,("This is the count: %d\n",theacl->count));
2191 /* Check if count was previously set to -1. *
2192 * If it was, that means we reached the end *
2193 * of the acl last time. */
2194 if(theacl->count == -1)
2195 return(0);
2197 link = theacl;
2198 /* To get to the next acl, traverse linked list until index *
2199 * of acl matches the count we are keeping. This count is *
2200 * incremented each time we return an acl entry. */
2202 for(keep_going = 0; keep_going < theacl->count; keep_going++)
2203 link = link->nextp;
2205 entry = *entry_p = link->entryp;
2207 DEBUG(10,("*entry_p is %d\n",entry_p));
2208 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
2210 /* Increment count */
2211 theacl->count++;
2212 if(link->nextp == NULL)
2213 theacl->count = -1;
2215 return(1);
2218 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2220 /* Initialize tag type */
2222 *tag_type_p = -1;
2223 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
2225 /* Depending on what type of entry we have, *
2226 * return tag type. */
2227 switch(entry_d->ace_id->id_type) {
2228 case ACEID_USER:
2229 *tag_type_p = SMB_ACL_USER;
2230 break;
2231 case ACEID_GROUP:
2232 *tag_type_p = SMB_ACL_GROUP;
2233 break;
2235 case SMB_ACL_USER_OBJ:
2236 case SMB_ACL_GROUP_OBJ:
2237 case SMB_ACL_OTHER:
2238 *tag_type_p = entry_d->ace_id->id_type;
2239 break;
2241 default:
2242 return(-1);
2245 return(0);
2248 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2250 DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
2251 *permset_p = &entry_d->ace_access;
2252 DEBUG(10,("**permset_p is %d\n",**permset_p));
2253 if(!(**permset_p & S_IXUSR) &&
2254 !(**permset_p & S_IWUSR) &&
2255 !(**permset_p & S_IRUSR) &&
2256 (**permset_p != 0))
2257 return(-1);
2259 DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
2260 return(0);
2263 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2265 return(entry_d->ace_id->id_data);
2268 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2270 struct acl *file_acl = (struct acl *)NULL;
2271 struct acl_entry *acl_entry;
2272 struct new_acl_entry *new_acl_entry;
2273 struct ace_id *idp;
2274 struct acl_entry_link *acl_entry_link;
2275 struct acl_entry_link *acl_entry_link_head;
2276 int i;
2277 int rc = 0;
2278 uid_t user_id;
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 *)malloc(BUFSIZ);
2287 if(file_acl == NULL) {
2288 errno=ENOMEM;
2289 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
2290 return(NULL);
2293 memset(file_acl,0,BUFSIZ);
2295 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
2296 if(rc == -1) {
2297 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
2298 SAFE_FREE(file_acl);
2299 return(NULL);
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 *
2310 * code. */
2312 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2313 if(acl_entry_link_head == NULL)
2314 return(NULL);
2316 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2317 if(acl_entry_link->entryp == NULL) {
2318 SAFE_FREE(file_acl);
2319 errno = ENOMEM;
2320 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2321 return(NULL);
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);
2341 continue;
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 = (struct acl_entry_link *)
2352 malloc(sizeof(struct acl_entry_link));
2354 if(acl_entry_link->nextp == NULL) {
2355 SAFE_FREE(file_acl);
2356 errno = ENOMEM;
2357 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2358 return(NULL);
2361 acl_entry_link->nextp->prevp = acl_entry_link;
2362 acl_entry_link = acl_entry_link->nextp;
2363 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2364 if(acl_entry_link->entryp == NULL) {
2365 SAFE_FREE(file_acl);
2366 errno = ENOMEM;
2367 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2368 return(NULL);
2370 acl_entry_link->nextp = NULL;
2373 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2375 /* Don't really need this since all types are going *
2376 * to be specified but, it's better than leaving it 0 */
2378 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2380 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2382 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2384 /* The access in the acl entries must be left shifted by *
2385 * three bites, because they will ultimately be compared *
2386 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2388 switch(acl_entry->ace_type){
2389 case ACC_PERMIT:
2390 case ACC_SPECIFY:
2391 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2392 acl_entry_link->entryp->ace_access <<= 6;
2393 acl_entry_link_head->count++;
2394 break;
2395 case ACC_DENY:
2396 /* Since there is no way to return a DENY acl entry *
2397 * change to PERMIT and then shift. */
2398 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2399 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2400 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2401 acl_entry_link->entryp->ace_access <<= 6;
2402 acl_entry_link_head->count++;
2403 break;
2404 default:
2405 return(0);
2408 DEBUG(10,("acl_entry = %d\n",acl_entry));
2409 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2411 acl_entry = acl_nxt(acl_entry);
2413 } /* end of if enabled */
2415 /* Since owner, group, other acl entries are not *
2416 * part of the acl entries in an acl, they must *
2417 * be dummied up to become part of the list. */
2419 for( i = 1; i < 4; i++) {
2420 DEBUG(10,("i is %d\n",i));
2421 if(acl_entry_link_head->count != 0) {
2422 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
2423 if(acl_entry_link->nextp == NULL) {
2424 SAFE_FREE(file_acl);
2425 errno = ENOMEM;
2426 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2427 return(NULL);
2430 acl_entry_link->nextp->prevp = acl_entry_link;
2431 acl_entry_link = acl_entry_link->nextp;
2432 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2433 if(acl_entry_link->entryp == NULL) {
2434 SAFE_FREE(file_acl);
2435 errno = ENOMEM;
2436 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2437 return(NULL);
2441 acl_entry_link->nextp = NULL;
2443 new_acl_entry = acl_entry_link->entryp;
2444 idp = new_acl_entry->ace_id;
2446 new_acl_entry->ace_len = sizeof(struct acl_entry);
2447 new_acl_entry->ace_type = ACC_PERMIT;
2448 idp->id_len = sizeof(struct ace_id);
2449 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2450 memset(idp->id_data,0,sizeof(uid_t));
2452 switch(i) {
2453 case 2:
2454 new_acl_entry->ace_access = file_acl->g_access << 6;
2455 idp->id_type = SMB_ACL_GROUP_OBJ;
2456 break;
2458 case 3:
2459 new_acl_entry->ace_access = file_acl->o_access << 6;
2460 idp->id_type = SMB_ACL_OTHER;
2461 break;
2463 case 1:
2464 new_acl_entry->ace_access = file_acl->u_access << 6;
2465 idp->id_type = SMB_ACL_USER_OBJ;
2466 break;
2468 default:
2469 return(NULL);
2473 acl_entry_link_head->count++;
2474 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2477 acl_entry_link_head->count = 0;
2478 SAFE_FREE(file_acl);
2480 return(acl_entry_link_head);
2483 SMB_ACL_T sys_acl_get_fd(int fd)
2485 struct acl *file_acl = (struct acl *)NULL;
2486 struct acl_entry *acl_entry;
2487 struct new_acl_entry *new_acl_entry;
2488 struct ace_id *idp;
2489 struct acl_entry_link *acl_entry_link;
2490 struct acl_entry_link *acl_entry_link_head;
2491 int i;
2492 int rc = 0;
2493 uid_t user_id;
2495 /* Get the acl using fstatacl */
2497 DEBUG(10,("Entering sys_acl_get_fd\n"));
2498 DEBUG(10,("fd is %d\n",fd));
2499 file_acl = (struct acl *)malloc(BUFSIZ);
2501 if(file_acl == NULL) {
2502 errno=ENOMEM;
2503 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2504 return(NULL);
2507 memset(file_acl,0,BUFSIZ);
2509 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2510 if(rc == -1) {
2511 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2512 SAFE_FREE(file_acl);
2513 return(NULL);
2516 DEBUG(10,("Got facl and returned it\n"));
2518 /* Point to the first acl entry in the acl */
2520 acl_entry = file_acl->acl_ext;
2521 /* Begin setting up the head of the linked list *
2522 * that will be used for the storing the acl *
2523 * in a way that is useful for the posix_acls.c *
2524 * code. */
2526 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2527 if(acl_entry_link_head == NULL){
2528 SAFE_FREE(file_acl);
2529 return(NULL);
2532 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2534 if(acl_entry_link->entryp == NULL) {
2535 errno = ENOMEM;
2536 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2537 SAFE_FREE(file_acl);
2538 return(NULL);
2541 DEBUG(10,("acl_entry is %d\n",acl_entry));
2542 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2544 /* Check if the extended acl bit is on. *
2545 * If it isn't, do not show the *
2546 * contents of the acl since AIX intends *
2547 * the extended info to remain unused */
2549 if(file_acl->acl_mode & S_IXACL){
2550 /* while we are not pointing to the very end */
2551 while(acl_entry < acl_last(file_acl)) {
2552 /* before we malloc anything, make sure this is */
2553 /* a valid acl entry and one that we want to map */
2555 idp = id_nxt(acl_entry->ace_id);
2556 if((acl_entry->ace_type == ACC_SPECIFY ||
2557 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2558 acl_entry = acl_nxt(acl_entry);
2559 continue;
2562 idp = acl_entry->ace_id;
2564 /* Check if this is the first entry in the linked list. *
2565 * The first entry needs to keep prevp pointing to NULL *
2566 * and already has entryp allocated. */
2568 if(acl_entry_link_head->count != 0) {
2569 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
2570 if(acl_entry_link->nextp == NULL) {
2571 errno = ENOMEM;
2572 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2573 SAFE_FREE(file_acl);
2574 return(NULL);
2576 acl_entry_link->nextp->prevp = acl_entry_link;
2577 acl_entry_link = acl_entry_link->nextp;
2578 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2579 if(acl_entry_link->entryp == NULL) {
2580 errno = ENOMEM;
2581 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2582 SAFE_FREE(file_acl);
2583 return(NULL);
2586 acl_entry_link->nextp = NULL;
2589 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2591 /* Don't really need this since all types are going *
2592 * to be specified but, it's better than leaving it 0 */
2594 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2595 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2597 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2599 /* The access in the acl entries must be left shifted by *
2600 * three bites, because they will ultimately be compared *
2601 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
2603 switch(acl_entry->ace_type){
2604 case ACC_PERMIT:
2605 case ACC_SPECIFY:
2606 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2607 acl_entry_link->entryp->ace_access <<= 6;
2608 acl_entry_link_head->count++;
2609 break;
2610 case ACC_DENY:
2611 /* Since there is no way to return a DENY acl entry *
2612 * change to PERMIT and then shift. */
2613 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2614 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2615 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2616 acl_entry_link->entryp->ace_access <<= 6;
2617 acl_entry_link_head->count++;
2618 break;
2619 default:
2620 return(0);
2623 DEBUG(10,("acl_entry = %d\n",acl_entry));
2624 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2626 acl_entry = acl_nxt(acl_entry);
2628 } /* end of if enabled */
2630 /* Since owner, group, other acl entries are not *
2631 * part of the acl entries in an acl, they must *
2632 * be dummied up to become part of the list. */
2634 for( i = 1; i < 4; i++) {
2635 DEBUG(10,("i is %d\n",i));
2636 if(acl_entry_link_head->count != 0){
2637 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
2638 if(acl_entry_link->nextp == NULL) {
2639 errno = ENOMEM;
2640 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2641 SAFE_FREE(file_acl);
2642 return(NULL);
2645 acl_entry_link->nextp->prevp = acl_entry_link;
2646 acl_entry_link = acl_entry_link->nextp;
2647 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2649 if(acl_entry_link->entryp == NULL) {
2650 SAFE_FREE(file_acl);
2651 errno = ENOMEM;
2652 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2653 return(NULL);
2657 acl_entry_link->nextp = NULL;
2659 new_acl_entry = acl_entry_link->entryp;
2660 idp = new_acl_entry->ace_id;
2662 new_acl_entry->ace_len = sizeof(struct acl_entry);
2663 new_acl_entry->ace_type = ACC_PERMIT;
2664 idp->id_len = sizeof(struct ace_id);
2665 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2666 memset(idp->id_data,0,sizeof(uid_t));
2668 switch(i) {
2669 case 2:
2670 new_acl_entry->ace_access = file_acl->g_access << 6;
2671 idp->id_type = SMB_ACL_GROUP_OBJ;
2672 break;
2674 case 3:
2675 new_acl_entry->ace_access = file_acl->o_access << 6;
2676 idp->id_type = SMB_ACL_OTHER;
2677 break;
2679 case 1:
2680 new_acl_entry->ace_access = file_acl->u_access << 6;
2681 idp->id_type = SMB_ACL_USER_OBJ;
2682 break;
2684 default:
2685 return(NULL);
2688 acl_entry_link_head->count++;
2689 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2692 acl_entry_link_head->count = 0;
2693 SAFE_FREE(file_acl);
2695 return(acl_entry_link_head);
2698 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2700 *permset = *permset & ~0777;
2701 return(0);
2704 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2706 if((perm != 0) &&
2707 (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
2708 return(-1);
2710 *permset |= perm;
2711 DEBUG(10,("This is the permset now: %d\n",*permset));
2712 return(0);
2715 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
2717 return(NULL);
2720 SMB_ACL_T sys_acl_init( int count)
2722 struct acl_entry_link *theacl = NULL;
2724 DEBUG(10,("Entering sys_acl_init\n"));
2726 theacl = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
2727 if(theacl == NULL) {
2728 errno = ENOMEM;
2729 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2730 return(NULL);
2733 theacl->count = 0;
2734 theacl->nextp = NULL;
2735 theacl->prevp = NULL;
2736 theacl->entryp = NULL;
2737 DEBUG(10,("Exiting sys_acl_init\n"));
2738 return(theacl);
2741 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2743 struct acl_entry_link *theacl;
2744 struct acl_entry_link *acl_entryp;
2745 struct acl_entry_link *temp_entry;
2746 int counting;
2748 DEBUG(10,("Entering the sys_acl_create_entry\n"));
2750 theacl = acl_entryp = *pacl;
2752 /* Get to the end of the acl before adding entry */
2754 for(counting=0; counting < theacl->count; counting++){
2755 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2756 temp_entry = acl_entryp;
2757 acl_entryp = acl_entryp->nextp;
2760 if(theacl->count != 0){
2761 temp_entry->nextp = acl_entryp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
2762 if(acl_entryp == NULL) {
2763 errno = ENOMEM;
2764 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2765 return(-1);
2768 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2769 acl_entryp->prevp = temp_entry;
2770 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2773 *pentry = acl_entryp->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
2774 if(*pentry == NULL) {
2775 errno = ENOMEM;
2776 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2777 return(-1);
2780 memset(*pentry,0,sizeof(struct new_acl_entry));
2781 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2782 acl_entryp->entryp->ace_type = ACC_PERMIT;
2783 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2784 acl_entryp->nextp = NULL;
2785 theacl->count++;
2786 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2787 return(0);
2790 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2792 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2793 entry->ace_id->id_type = tagtype;
2794 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2795 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2798 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2800 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2801 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2802 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2803 return(0);
2806 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2808 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2809 if(!(*permset & S_IXUSR) &&
2810 !(*permset & S_IWUSR) &&
2811 !(*permset & S_IRUSR) &&
2812 (*permset != 0))
2813 return(-1);
2815 entry->ace_access = *permset;
2816 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2817 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2818 return(0);
2821 int sys_acl_valid( SMB_ACL_T theacl )
2823 int user_obj = 0;
2824 int group_obj = 0;
2825 int other_obj = 0;
2826 struct acl_entry_link *acl_entry;
2828 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2829 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2830 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2831 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2834 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2836 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2837 return(-1);
2839 return(0);
2842 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2844 struct acl_entry_link *acl_entry_link = NULL;
2845 struct acl *file_acl = NULL;
2846 struct acl *file_acl_temp = NULL;
2847 struct acl_entry *acl_entry = NULL;
2848 struct ace_id *ace_id = NULL;
2849 uint id_type;
2850 uint ace_access;
2851 uint user_id;
2852 uint acl_length;
2853 uint rc;
2855 DEBUG(10,("Entering sys_acl_set_file\n"));
2856 DEBUG(10,("File name is %s\n",name));
2858 /* AIX has no default ACL */
2859 if(acltype == SMB_ACL_TYPE_DEFAULT)
2860 return(0);
2862 acl_length = BUFSIZ;
2863 file_acl = (struct acl *)malloc(BUFSIZ);
2865 if(file_acl == NULL) {
2866 errno = ENOMEM;
2867 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2868 return(-1);
2871 memset(file_acl,0,BUFSIZ);
2873 file_acl->acl_len = ACL_SIZ;
2874 file_acl->acl_mode = S_IXACL;
2876 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2877 acl_entry_link->entryp->ace_access >>= 6;
2878 id_type = acl_entry_link->entryp->ace_id->id_type;
2880 switch(id_type) {
2881 case SMB_ACL_USER_OBJ:
2882 file_acl->u_access = acl_entry_link->entryp->ace_access;
2883 continue;
2884 case SMB_ACL_GROUP_OBJ:
2885 file_acl->g_access = acl_entry_link->entryp->ace_access;
2886 continue;
2887 case SMB_ACL_OTHER:
2888 file_acl->o_access = acl_entry_link->entryp->ace_access;
2889 continue;
2890 case SMB_ACL_MASK:
2891 continue;
2894 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2895 acl_length += sizeof(struct acl_entry);
2896 file_acl_temp = (struct acl *)malloc(acl_length);
2897 if(file_acl_temp == NULL) {
2898 SAFE_FREE(file_acl);
2899 errno = ENOMEM;
2900 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2901 return(-1);
2904 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2905 SAFE_FREE(file_acl);
2906 file_acl = file_acl_temp;
2909 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2910 file_acl->acl_len += sizeof(struct acl_entry);
2911 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2912 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2914 /* In order to use this, we'll need to wait until we can get denies */
2915 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2916 acl_entry->ace_type = ACC_SPECIFY; */
2918 acl_entry->ace_type = ACC_SPECIFY;
2920 ace_id = acl_entry->ace_id;
2922 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2923 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2924 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2925 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2926 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2929 rc = chacl(name,file_acl,file_acl->acl_len);
2930 DEBUG(10,("errno is %d\n",errno));
2931 DEBUG(10,("return code is %d\n",rc));
2932 SAFE_FREE(file_acl);
2933 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2934 return(rc);
2937 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2939 struct acl_entry_link *acl_entry_link = NULL;
2940 struct acl *file_acl = NULL;
2941 struct acl *file_acl_temp = NULL;
2942 struct acl_entry *acl_entry = NULL;
2943 struct ace_id *ace_id = NULL;
2944 uint id_type;
2945 uint user_id;
2946 uint acl_length;
2947 uint rc;
2949 DEBUG(10,("Entering sys_acl_set_fd\n"));
2950 acl_length = BUFSIZ;
2951 file_acl = (struct acl *)malloc(BUFSIZ);
2953 if(file_acl == NULL) {
2954 errno = ENOMEM;
2955 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2956 return(-1);
2959 memset(file_acl,0,BUFSIZ);
2961 file_acl->acl_len = ACL_SIZ;
2962 file_acl->acl_mode = S_IXACL;
2964 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2965 acl_entry_link->entryp->ace_access >>= 6;
2966 id_type = acl_entry_link->entryp->ace_id->id_type;
2967 DEBUG(10,("The id_type is %d\n",id_type));
2969 switch(id_type) {
2970 case SMB_ACL_USER_OBJ:
2971 file_acl->u_access = acl_entry_link->entryp->ace_access;
2972 continue;
2973 case SMB_ACL_GROUP_OBJ:
2974 file_acl->g_access = acl_entry_link->entryp->ace_access;
2975 continue;
2976 case SMB_ACL_OTHER:
2977 file_acl->o_access = acl_entry_link->entryp->ace_access;
2978 continue;
2979 case SMB_ACL_MASK:
2980 continue;
2983 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2984 acl_length += sizeof(struct acl_entry);
2985 file_acl_temp = (struct acl *)malloc(acl_length);
2986 if(file_acl_temp == NULL) {
2987 SAFE_FREE(file_acl);
2988 errno = ENOMEM;
2989 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2990 return(-1);
2993 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2994 SAFE_FREE(file_acl);
2995 file_acl = file_acl_temp;
2998 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2999 file_acl->acl_len += sizeof(struct acl_entry);
3000 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
3001 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
3003 /* In order to use this, we'll need to wait until we can get denies */
3004 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
3005 acl_entry->ace_type = ACC_SPECIFY; */
3007 acl_entry->ace_type = ACC_SPECIFY;
3009 ace_id = acl_entry->ace_id;
3011 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
3012 DEBUG(10,("The id type is %d\n",ace_id->id_type));
3013 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
3014 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
3015 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
3018 rc = fchacl(fd,file_acl,file_acl->acl_len);
3019 DEBUG(10,("errno is %d\n",errno));
3020 DEBUG(10,("return code is %d\n",rc));
3021 SAFE_FREE(file_acl);
3022 DEBUG(10,("Exiting sys_acl_set_fd\n"));
3023 return(rc);
3026 int sys_acl_delete_def_file(const char *name)
3028 /* AIX has no default ACL */
3029 return 0;
3032 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3034 return(*permset & perm);
3037 int sys_acl_free_text(char *text)
3039 return(0);
3042 int sys_acl_free_acl(SMB_ACL_T posix_acl)
3044 struct acl_entry_link *acl_entry_link;
3046 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
3047 SAFE_FREE(acl_entry_link->prevp->entryp);
3048 SAFE_FREE(acl_entry_link->prevp);
3051 SAFE_FREE(acl_entry_link->prevp->entryp);
3052 SAFE_FREE(acl_entry_link->prevp);
3053 SAFE_FREE(acl_entry_link->entryp);
3054 SAFE_FREE(acl_entry_link);
3056 return(0);
3059 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3061 return(0);
3064 #else /* No ACLs. */
3066 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
3068 errno = ENOSYS;
3069 return -1;
3072 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
3074 errno = ENOSYS;
3075 return -1;
3078 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
3080 errno = ENOSYS;
3081 return -1;
3084 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
3086 errno = ENOSYS;
3087 return NULL;
3090 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
3092 errno = ENOSYS;
3093 return (SMB_ACL_T)NULL;
3096 SMB_ACL_T sys_acl_get_fd(int fd)
3098 errno = ENOSYS;
3099 return (SMB_ACL_T)NULL;
3102 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
3104 errno = ENOSYS;
3105 return -1;
3108 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3110 errno = ENOSYS;
3111 return -1;
3114 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3116 errno = ENOSYS;
3117 return (permset & perm) ? 1 : 0;
3120 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
3122 errno = ENOSYS;
3123 return NULL;
3126 int sys_acl_free_text(char *text)
3128 errno = ENOSYS;
3129 return -1;
3132 SMB_ACL_T sys_acl_init( int count)
3134 errno = ENOSYS;
3135 return NULL;
3138 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
3140 errno = ENOSYS;
3141 return -1;
3144 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
3146 errno = ENOSYS;
3147 return -1;
3150 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
3152 errno = ENOSYS;
3153 return -1;
3156 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
3158 errno = ENOSYS;
3159 return -1;
3162 int sys_acl_valid( SMB_ACL_T theacl )
3164 errno = ENOSYS;
3165 return -1;
3168 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
3170 errno = ENOSYS;
3171 return -1;
3174 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
3176 errno = ENOSYS;
3177 return -1;
3180 int sys_acl_delete_def_file(const char *name)
3182 errno = ENOSYS;
3183 return -1;
3186 int sys_acl_free_acl(SMB_ACL_T the_acl)
3188 errno = ENOSYS;
3189 return -1;
3192 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3194 errno = ENOSYS;
3195 return -1;
3198 #endif /* No ACLs. */
3200 /************************************************************************
3201 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
3202 errno, 0 if not.
3203 ************************************************************************/
3205 int no_acl_syscall_error(int err)
3207 #if defined(ENOSYS)
3208 if (err == ENOSYS) {
3209 return 1;
3211 #endif
3212 #if defined(ENOTSUP)
3213 if (err == ENOTSUP) {
3214 return 1;
3216 #endif
3217 return 0;