r15152: Fix a case when target is offline. Jerry, this needs to be in 3.0.23pre1
[Samba.git] / source / lib / sysacls.c
blob61975264fd6b9c57c9b430aaf1e95a3150cb0353
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"
23 #undef DBGC_CLASS
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)
121 * suffix.
123 return acl_get_perm_np(permset, perm);
124 #else
125 return acl_get_perm(permset, perm);
126 #endif
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) {
210 return -1;
213 errno = 0;
214 if ((entry = acl_get_entry(the_acl)) != NULL) {
215 *entry_p = entry;
216 return 1;
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 */
251 return 0;
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)) {
257 errno = EINVAL;
258 return -1;
261 *permset |= perm; /* acl_add_perm() is broken on Tru64 */
263 return 0;
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) {
286 return -1;
289 *pentry = entry;
290 return 0;
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 )
310 acl_entry_t entry;
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);
337 return 0;
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.
367 * sys_acl_valid()
368 * sys_acl_set_file()
369 * sys_acl_set_fd()
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
382 #endif
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) {
388 errno = EINVAL;
389 return -1;
392 if (entry_p == NULL) {
393 errno = EINVAL;
394 return -1;
397 if (entry_id == SMB_ACL_FIRST_ENTRY) {
398 acl_d->next = 0;
401 if (acl_d->next < 0) {
402 errno = EINVAL;
403 return -1;
406 if (acl_d->next >= acl_d->count) {
407 return 0;
410 *entry_p = &acl_d->acl[acl_d->next++];
412 return 1;
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;
419 return 0;
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;
426 return 0;
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) {
433 errno = EINVAL;
434 return NULL;
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)
456 SMB_ACL_T acl_d;
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) {
462 errno = EINVAL;
463 return NULL;
466 count = INITIAL_ACL_SIZE;
467 if ((acl_d = sys_acl_init(count)) == NULL) {
468 return 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) {
485 return NULL;
488 if ((acl_d = sys_acl_init(count)) == NULL) {
489 return NULL;
493 if (count < 0) {
494 sys_acl_free_acl(acl_d);
495 return NULL;
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)
507 break;
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) {
517 int i, j;
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;
525 } else {
526 acl_d->count = naccess;
529 return acl_d;
532 SMB_ACL_T sys_acl_get_fd(int fd)
534 SMB_ACL_T acl_d;
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) {
540 return 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) {
549 return NULL;
552 if ((acl_d = sys_acl_init(count)) == NULL) {
553 return NULL;
557 if (count < 0) {
558 sys_acl_free_acl(acl_d);
559 return NULL;
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)
567 break;
570 acl_d->count = naccess;
572 return acl_d;
575 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
577 *permset_d = 0;
579 return 0;
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) {
586 errno = EINVAL;
587 return -1;
590 if (permset_d == NULL) {
591 errno = EINVAL;
592 return -1;
595 *permset_d |= perm;
597 return 0;
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)
607 int i;
608 int len, maxlen;
609 char *text;
612 * use an initial estimate of 20 bytes per ACL entry
613 * when allocating memory for the text representation
614 * of the ACL
616 len = 0;
617 maxlen = 20 * acl_d->count;
618 if ((text = SMB_MALLOC(maxlen)) == NULL) {
619 errno = ENOMEM;
620 return NULL;
623 for (i = 0; i < acl_d->count; i++) {
624 struct acl *ap = &acl_d->acl[i];
625 struct passwd *pw;
626 struct group *gr;
627 char tagbuf[12];
628 char idbuf[12];
629 char *tag;
630 char *id = "";
631 char perms[4];
632 int nbytes;
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
640 default:
641 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
642 ap->a_type);
643 tag = tagbuf;
644 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
645 (long)ap->a_id);
646 id = idbuf;
647 break;
649 case SMB_ACL_USER:
650 id = uidtoname(ap->a_id);
651 case SMB_ACL_USER_OBJ:
652 tag = "user";
653 break;
655 case SMB_ACL_GROUP:
656 if ((gr = getgrgid(ap->a_id)) == NULL) {
657 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
658 (long)ap->a_id);
659 id = idbuf;
660 } else {
661 id = gr->gr_name;
663 case SMB_ACL_GROUP_OBJ:
664 tag = "group";
665 break;
667 case SMB_ACL_OTHER:
668 tag = "other";
669 break;
671 case SMB_ACL_MASK:
672 tag = "mask";
673 break;
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' : '-';
680 perms[3] = '\0';
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) {
694 errno = ENOMEM;
695 return NULL;
699 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
700 len += nbytes - 1;
703 if (len_p)
704 *len_p = len;
706 return text;
709 SMB_ACL_T sys_acl_init(int count)
711 SMB_ACL_T a;
713 if (count < 0) {
714 errno = EINVAL;
715 return NULL;
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) {
725 errno = ENOMEM;
726 return NULL;
729 a->size = count + 1;
730 a->count = 0;
731 a->next = -1;
733 return a;
737 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
739 SMB_ACL_T acl_d;
740 SMB_ACL_ENTRY_T entry_d;
742 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
743 errno = EINVAL;
744 return -1;
747 if (acl_d->count >= acl_d->size) {
748 errno = ENOSPC;
749 return -1;
752 entry_d = &acl_d->acl[acl_d->count++];
753 entry_d->a_type = 0;
754 entry_d->a_id = -1;
755 entry_d->a_perm = 0;
756 *entry_p = entry_d;
758 return 0;
761 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
763 switch (tag_type) {
764 case SMB_ACL_USER:
765 case SMB_ACL_USER_OBJ:
766 case SMB_ACL_GROUP:
767 case SMB_ACL_GROUP_OBJ:
768 case SMB_ACL_OTHER:
769 case SMB_ACL_MASK:
770 entry_d->a_type = tag_type;
771 break;
772 default:
773 errno = EINVAL;
774 return -1;
777 return 0;
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) {
784 errno = EINVAL;
785 return -1;
788 entry_d->a_id = *((id_t *)qual_p);
790 return 0;
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)) {
796 return EINVAL;
799 entry_d->a_perm = *permset_d;
801 return 0;
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) {
826 errno = EINVAL;
827 return -1;
829 return 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)
839 struct stat s;
840 struct acl *acl_p;
841 int acl_count;
842 struct acl *acl_buf = NULL;
843 int ret;
845 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
846 errno = EINVAL;
847 return -1;
850 if (acl_sort(acl_d) != 0) {
851 return -1;
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) {
863 return -1;
865 if (S_ISDIR(s.st_mode)) {
866 SMB_ACL_T acc_acl;
867 SMB_ACL_T def_acl;
868 SMB_ACL_T tmp_acl;
869 int i;
871 if (type == SMB_ACL_TYPE_ACCESS) {
872 acc_acl = acl_d;
873 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
875 } else {
876 def_acl = acl_d;
877 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
880 if (tmp_acl == NULL) {
881 return -1;
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);
892 errno = ENOMEM;
893 return -1;
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) {
915 errno = EINVAL;
916 return -1;
919 ret = acl(name, SETACL, acl_count, acl_p);
921 SAFE_FREE(acl_buf);
923 return ret;
926 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
928 if (acl_sort(acl_d) != 0) {
929 return -1;
932 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
935 int sys_acl_delete_def_file(const char *path)
937 SMB_ACL_T acl_d;
938 int ret;
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) {
945 return -1;
948 ret = acl(path, SETACL, acl_d->count, acl_d->acl);
950 sys_acl_free_acl(acl_d);
952 return ret;
955 int sys_acl_free_text(char *text)
957 SAFE_FREE(text);
958 return 0;
961 int sys_acl_free_acl(SMB_ACL_T acl_d)
963 SAFE_FREE(acl_d);
964 return 0;
967 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
969 return 0;
972 #elif defined(HAVE_HPUX_ACLS)
973 #include <dl.h>
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.
989 * sys_acl_valid()
990 * sys_acl_set_file()
991 * sys_acl_set_fd()
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;
1005 void *value;
1006 int ret_val=0;
1007 static BOOL already_checked=0;
1009 if(already_checked)
1010 return True;
1013 ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
1015 if(ret_val != 0) {
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"));
1019 return False;
1022 DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
1024 already_checked = True;
1025 return 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) {
1031 errno = EINVAL;
1032 return -1;
1035 if (entry_p == NULL) {
1036 errno = EINVAL;
1037 return -1;
1040 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1041 acl_d->next = 0;
1044 if (acl_d->next < 0) {
1045 errno = EINVAL;
1046 return -1;
1049 if (acl_d->next >= acl_d->count) {
1050 return 0;
1053 *entry_p = &acl_d->acl[acl_d->next++];
1055 return 1;
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;
1062 return 0;
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;
1069 return 0;
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) {
1076 errno = EINVAL;
1077 return NULL;
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)
1099 SMB_ACL_T acl_d;
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.
1108 return NULL;
1111 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1112 errno = EINVAL;
1113 return NULL;
1116 count = INITIAL_ACL_SIZE;
1117 if ((acl_d = sys_acl_init(count)) == NULL) {
1118 return 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) {
1134 return NULL;
1137 if ((acl_d = sys_acl_init(count)) == NULL) {
1138 return NULL;
1142 if (count < 0) {
1143 sys_acl_free_acl(acl_d);
1144 return NULL;
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)
1156 break;
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) {
1166 int i, j;
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;
1174 } else {
1175 acl_d->count = naccess;
1178 return acl_d;
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);
1189 if (fsp == NULL) {
1190 errno = EBADF;
1191 return NULL;
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)
1204 *permset_d = 0;
1206 return 0;
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) {
1213 errno = EINVAL;
1214 return -1;
1217 if (permset_d == NULL) {
1218 errno = EINVAL;
1219 return -1;
1222 *permset_d |= perm;
1224 return 0;
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)
1234 int i;
1235 int len, maxlen;
1236 char *text;
1239 * use an initial estimate of 20 bytes per ACL entry
1240 * when allocating memory for the text representation
1241 * of the ACL
1243 len = 0;
1244 maxlen = 20 * acl_d->count;
1245 if ((text = SMB_MALLOC(maxlen)) == NULL) {
1246 errno = ENOMEM;
1247 return NULL;
1250 for (i = 0; i < acl_d->count; i++) {
1251 struct acl *ap = &acl_d->acl[i];
1252 struct passwd *pw;
1253 struct group *gr;
1254 char tagbuf[12];
1255 char idbuf[12];
1256 char *tag;
1257 char *id = "";
1258 char perms[4];
1259 int nbytes;
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
1267 default:
1268 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
1269 ap->a_type);
1270 tag = tagbuf;
1271 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1272 (long)ap->a_id);
1273 id = idbuf;
1274 break;
1276 case SMB_ACL_USER:
1277 id = uidtoname(ap->a_id);
1278 case SMB_ACL_USER_OBJ:
1279 tag = "user";
1280 break;
1282 case SMB_ACL_GROUP:
1283 if ((gr = getgrgid(ap->a_id)) == NULL) {
1284 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
1285 (long)ap->a_id);
1286 id = idbuf;
1287 } else {
1288 id = gr->gr_name;
1290 case SMB_ACL_GROUP_OBJ:
1291 tag = "group";
1292 break;
1294 case SMB_ACL_OTHER:
1295 tag = "other";
1296 break;
1298 case SMB_ACL_MASK:
1299 tag = "mask";
1300 break;
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' : '-';
1307 perms[3] = '\0';
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) {
1321 free(oldtext);
1322 errno = ENOMEM;
1323 return NULL;
1327 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
1328 len += nbytes - 1;
1331 if (len_p)
1332 *len_p = len;
1334 return text;
1337 SMB_ACL_T sys_acl_init(int count)
1339 SMB_ACL_T a;
1341 if (count < 0) {
1342 errno = EINVAL;
1343 return NULL;
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) {
1353 errno = ENOMEM;
1354 return NULL;
1357 a->size = count + 1;
1358 a->count = 0;
1359 a->next = -1;
1361 return a;
1365 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1367 SMB_ACL_T acl_d;
1368 SMB_ACL_ENTRY_T entry_d;
1370 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1371 errno = EINVAL;
1372 return -1;
1375 if (acl_d->count >= acl_d->size) {
1376 errno = ENOSPC;
1377 return -1;
1380 entry_d = &acl_d->acl[acl_d->count++];
1381 entry_d->a_type = 0;
1382 entry_d->a_id = -1;
1383 entry_d->a_perm = 0;
1384 *entry_p = entry_d;
1386 return 0;
1389 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1391 switch (tag_type) {
1392 case SMB_ACL_USER:
1393 case SMB_ACL_USER_OBJ:
1394 case SMB_ACL_GROUP:
1395 case SMB_ACL_GROUP_OBJ:
1396 case SMB_ACL_OTHER:
1397 case SMB_ACL_MASK:
1398 entry_d->a_type = tag_type;
1399 break;
1400 default:
1401 errno = EINVAL;
1402 return -1;
1405 return 0;
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) {
1412 errno = EINVAL;
1413 return -1;
1416 entry_d->a_id = *((id_t *)qual_p);
1418 return 0;
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)) {
1424 return EINVAL;
1427 entry_d->a_perm = *permset_d;
1429 return 0;
1432 /* Structure to capture the count for each type of ACE. */
1434 struct hpux_acl_types {
1435 int n_user;
1436 int n_def_user;
1437 int n_user_obj;
1438 int n_def_user_obj;
1440 int n_group;
1441 int n_def_group;
1442 int n_group_obj;
1443 int n_def_group_obj;
1445 int n_other;
1446 int n_other_obj;
1447 int n_def_other_obj;
1449 int n_class_obj;
1450 int n_def_class_obj;
1452 int n_illegal_obj;
1455 /* count_obj:
1456 * Counts the different number of objects in a given array of ACL
1457 * structures.
1458 * Inputs:
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
1463 * allocated.
1464 * Output:
1466 * acl_type_count - This structure is filled up with counts of various
1467 * acl types.
1470 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1472 int i;
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) {
1478 case USER:
1479 acl_type_count->n_user++;
1480 break;
1481 case USER_OBJ:
1482 acl_type_count->n_user_obj++;
1483 break;
1484 case DEF_USER_OBJ:
1485 acl_type_count->n_def_user_obj++;
1486 break;
1487 case GROUP:
1488 acl_type_count->n_group++;
1489 break;
1490 case GROUP_OBJ:
1491 acl_type_count->n_group_obj++;
1492 break;
1493 case DEF_GROUP_OBJ:
1494 acl_type_count->n_def_group_obj++;
1495 break;
1496 case OTHER_OBJ:
1497 acl_type_count->n_other_obj++;
1498 break;
1499 case DEF_OTHER_OBJ:
1500 acl_type_count->n_def_other_obj++;
1501 break;
1502 case CLASS_OBJ:
1503 acl_type_count->n_class_obj++;
1504 break;
1505 case DEF_CLASS_OBJ:
1506 acl_type_count->n_def_class_obj++;
1507 break;
1508 case DEF_USER:
1509 acl_type_count->n_def_user++;
1510 break;
1511 case DEF_GROUP:
1512 acl_type_count->n_def_group++;
1513 break;
1514 default:
1515 acl_type_count->n_illegal_obj++;
1516 break;
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
1545 * not.
1547 * Inputs: acl_type - ACL Type.
1549 * Outputs:
1551 * Return..
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)
1559 switch(acl_type) {
1560 case USER:
1561 case GROUP:
1562 case DEF_USER:
1563 case DEF_GROUP:
1564 return True;
1565 default:
1566 return False;
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) {
1581 case USER:
1582 case GROUP_OBJ:
1583 case GROUP:
1584 case DEF_USER_OBJ:
1585 case DEF_USER:
1586 case DEF_GROUP_OBJ:
1587 case DEF_GROUP:
1588 case DEF_CLASS_OBJ:
1589 case DEF_OTHER_OBJ:
1590 return aclp->a_perm;
1591 default:
1592 return 0;
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
1600 * Inputs:
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
1604 * permissions.
1605 * aclp - Array of ACL structures.
1607 * Outputs:
1609 * aclp - Sorted array of ACL structures.
1611 * Outputs:
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;
1629 int i, j;
1631 if(!acl_count) {
1632 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1633 return 0;
1636 if(aclp == NULL) {
1637 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1638 return -1;
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"));
1656 return -1;
1659 /* If any of the default objects are present, there should be only
1660 * one of them each.
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"));
1667 return -1;
1670 /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
1671 * structures.
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));
1699 return -1;
1707 /* set the class obj permissions to the computed one. */
1708 if(calclass) {
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;
1720 return 0;
1721 #else
1722 return aclsort(acl_count, calclass, aclp);
1723 #endif
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) {
1748 errno = EINVAL;
1749 return -1;
1751 return 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)
1761 struct stat s;
1762 struct acl *acl_p;
1763 int acl_count;
1764 struct acl *acl_buf = NULL;
1765 int ret;
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.
1771 errno=ENOSYS;
1772 return -1;
1775 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1776 errno = EINVAL;
1777 return -1;
1780 if (acl_sort(acl_d) != 0) {
1781 return -1;
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) {
1793 return -1;
1795 if (S_ISDIR(s.st_mode)) {
1796 SMB_ACL_T acc_acl;
1797 SMB_ACL_T def_acl;
1798 SMB_ACL_T tmp_acl;
1799 int i;
1801 if (type == SMB_ACL_TYPE_ACCESS) {
1802 acc_acl = acl_d;
1803 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1805 } else {
1806 def_acl = acl_d;
1807 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1810 if (tmp_acl == NULL) {
1811 return -1;
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);
1822 errno = ENOMEM;
1823 return -1;
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) {
1845 errno = EINVAL;
1846 return -1;
1849 ret = acl(name, ACL_SET, acl_count, acl_p);
1851 if (acl_buf) {
1852 free(acl_buf);
1855 return ret;
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);
1866 if (fsp == NULL) {
1867 errno = EBADF;
1868 return NULL;
1871 if (acl_sort(acl_d) != 0) {
1872 return -1;
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)
1885 SMB_ACL_T acl_d;
1886 int ret;
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) {
1893 return -1;
1896 ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1898 sys_acl_free_acl(acl_d);
1900 return ret;
1903 int sys_acl_free_text(char *text)
1905 free(text);
1906 return 0;
1909 int sys_acl_free_acl(SMB_ACL_T acl_d)
1911 free(acl_d);
1912 return 0;
1915 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1917 return 0;
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) {
1925 errno = EINVAL;
1926 return -1;
1929 if (entry_p == NULL) {
1930 errno = EINVAL;
1931 return -1;
1934 if (entry_id == SMB_ACL_FIRST_ENTRY) {
1935 acl_d->next = 0;
1938 if (acl_d->next < 0) {
1939 errno = EINVAL;
1940 return -1;
1943 if (acl_d->next >= acl_d->aclp->acl_cnt) {
1944 return 0;
1947 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1949 return 1;
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;
1956 return 0;
1959 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1961 *permset_p = entry_d;
1963 return 0;
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) {
1970 errno = EINVAL;
1971 return NULL;
1974 return &entry_d->ae_id;
1977 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1979 SMB_ACL_T a;
1981 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1982 errno = ENOMEM;
1983 return NULL;
1985 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1986 SAFE_FREE(a);
1987 return NULL;
1989 a->next = -1;
1990 a->freeaclp = True;
1991 return a;
1994 SMB_ACL_T sys_acl_get_fd(int fd)
1996 SMB_ACL_T a;
1998 if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1999 errno = ENOMEM;
2000 return NULL;
2002 if ((a->aclp = acl_get_fd(fd)) == NULL) {
2003 SAFE_FREE(a);
2004 return NULL;
2006 a->next = -1;
2007 a->freeaclp = True;
2008 return a;
2011 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
2013 permset_d->ae_perm = 0;
2015 return 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) {
2022 errno = EINVAL;
2023 return -1;
2026 if (permset_d == NULL) {
2027 errno = EINVAL;
2028 return -1;
2031 permset_d->ae_perm |= perm;
2033 return 0;
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)
2048 SMB_ACL_T a;
2050 if (count < 0) {
2051 errno = EINVAL;
2052 return NULL;
2055 if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
2056 errno = ENOMEM;
2057 return NULL;
2060 a->next = -1;
2061 a->freeaclp = False;
2062 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
2063 a->aclp->acl_cnt = 0;
2065 return a;
2069 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
2071 SMB_ACL_T acl_d;
2072 SMB_ACL_ENTRY_T entry_d;
2074 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
2075 errno = EINVAL;
2076 return -1;
2079 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
2080 errno = ENOSPC;
2081 return -1;
2084 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
2085 entry_d->ae_tag = 0;
2086 entry_d->ae_id = 0;
2087 entry_d->ae_perm = 0;
2088 *entry_p = entry_d;
2090 return 0;
2093 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
2095 switch (tag_type) {
2096 case SMB_ACL_USER:
2097 case SMB_ACL_USER_OBJ:
2098 case SMB_ACL_GROUP:
2099 case SMB_ACL_GROUP_OBJ:
2100 case SMB_ACL_OTHER:
2101 case SMB_ACL_MASK:
2102 entry_d->ae_tag = tag_type;
2103 break;
2104 default:
2105 errno = EINVAL;
2106 return -1;
2109 return 0;
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) {
2116 errno = EINVAL;
2117 return -1;
2120 entry_d->ae_id = *((id_t *)qual_p);
2122 return 0;
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)) {
2128 return EINVAL;
2131 entry_d->ae_perm = permset_d->ae_perm;
2133 return 0;
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);
2166 acl_free(acl_d);
2167 return 0;
2170 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2172 return 0;
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;
2183 int keep_going;
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)
2191 return(0);
2193 link = theacl;
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++)
2199 link = link->nextp;
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 */
2207 theacl->count++;
2208 if(link->nextp == NULL)
2209 theacl->count = -1;
2211 return(1);
2214 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2216 /* Initialize tag type */
2218 *tag_type_p = -1;
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) {
2224 case ACEID_USER:
2225 *tag_type_p = SMB_ACL_USER;
2226 break;
2227 case ACEID_GROUP:
2228 *tag_type_p = SMB_ACL_GROUP;
2229 break;
2231 case SMB_ACL_USER_OBJ:
2232 case SMB_ACL_GROUP_OBJ:
2233 case SMB_ACL_OTHER:
2234 *tag_type_p = entry_d->ace_id->id_type;
2235 break;
2237 default:
2238 return(-1);
2241 return(0);
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) &&
2252 (**permset_p != 0))
2253 return(-1);
2255 DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
2256 return(0);
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;
2269 struct ace_id *idp;
2270 struct acl_entry_link *acl_entry_link;
2271 struct acl_entry_link *acl_entry_link_head;
2272 int i;
2273 int rc = 0;
2274 uid_t user_id;
2276 /* AIX has no DEFAULT */
2277 if ( type == SMB_ACL_TYPE_DEFAULT )
2278 return NULL;
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) {
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 = SMB_MALLOC_P(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 = SMB_MALLOC_P(struct acl_entry_link);
2353 if(acl_entry_link->nextp == NULL) {
2354 SAFE_FREE(file_acl);
2355 errno = ENOMEM;
2356 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2357 return(NULL);
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);
2365 errno = ENOMEM;
2366 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2367 return(NULL);
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){
2388 case ACC_PERMIT:
2389 case ACC_SPECIFY:
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++;
2393 break;
2394 case ACC_DENY:
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++;
2402 break;
2403 default:
2404 return(0);
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);
2424 errno = ENOMEM;
2425 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2426 return(NULL);
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);
2434 errno = ENOMEM;
2435 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2436 return(NULL);
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));
2451 switch(i) {
2452 case 2:
2453 new_acl_entry->ace_access = file_acl->g_access << 6;
2454 idp->id_type = SMB_ACL_GROUP_OBJ;
2455 break;
2457 case 3:
2458 new_acl_entry->ace_access = file_acl->o_access << 6;
2459 idp->id_type = SMB_ACL_OTHER;
2460 break;
2462 case 1:
2463 new_acl_entry->ace_access = file_acl->u_access << 6;
2464 idp->id_type = SMB_ACL_USER_OBJ;
2465 break;
2467 default:
2468 return(NULL);
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;
2487 struct ace_id *idp;
2488 struct acl_entry_link *acl_entry_link;
2489 struct acl_entry_link *acl_entry_link_head;
2490 int i;
2491 int rc = 0;
2492 uid_t user_id;
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) {
2501 errno=ENOMEM;
2502 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2503 return(NULL);
2506 memset(file_acl,0,BUFSIZ);
2508 rc = fstatacl(fd,0,file_acl,BUFSIZ);
2509 if(rc == -1) {
2510 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2511 SAFE_FREE(file_acl);
2512 return(NULL);
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 *
2523 * code. */
2525 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2526 if(acl_entry_link_head == NULL){
2527 SAFE_FREE(file_acl);
2528 return(NULL);
2531 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2533 if(acl_entry_link->entryp == NULL) {
2534 errno = ENOMEM;
2535 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2536 SAFE_FREE(file_acl);
2537 return(NULL);
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);
2558 continue;
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) {
2570 errno = ENOMEM;
2571 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2572 SAFE_FREE(file_acl);
2573 return(NULL);
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) {
2579 errno = ENOMEM;
2580 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2581 SAFE_FREE(file_acl);
2582 return(NULL);
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){
2603 case ACC_PERMIT:
2604 case ACC_SPECIFY:
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++;
2608 break;
2609 case ACC_DENY:
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++;
2617 break;
2618 default:
2619 return(0);
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) {
2638 errno = ENOMEM;
2639 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2640 SAFE_FREE(file_acl);
2641 return(NULL);
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);
2650 errno = ENOMEM;
2651 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2652 return(NULL);
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));
2667 switch(i) {
2668 case 2:
2669 new_acl_entry->ace_access = file_acl->g_access << 6;
2670 idp->id_type = SMB_ACL_GROUP_OBJ;
2671 break;
2673 case 3:
2674 new_acl_entry->ace_access = file_acl->o_access << 6;
2675 idp->id_type = SMB_ACL_OTHER;
2676 break;
2678 case 1:
2679 new_acl_entry->ace_access = file_acl->u_access << 6;
2680 idp->id_type = SMB_ACL_USER_OBJ;
2681 break;
2683 default:
2684 return(NULL);
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;
2700 return(0);
2703 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2705 if((perm != 0) &&
2706 (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
2707 return(-1);
2709 *permset |= perm;
2710 DEBUG(10,("This is the permset now: %d\n",*permset));
2711 return(0);
2714 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
2716 return(NULL);
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) {
2727 errno = ENOMEM;
2728 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2729 return(NULL);
2732 theacl->count = 0;
2733 theacl->nextp = NULL;
2734 theacl->prevp = NULL;
2735 theacl->entryp = NULL;
2736 DEBUG(10,("Exiting sys_acl_init\n"));
2737 return(theacl);
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;
2745 int counting;
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) {
2762 errno = ENOMEM;
2763 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2764 return(-1);
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) {
2774 errno = ENOMEM;
2775 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2776 return(-1);
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;
2784 theacl->count++;
2785 DEBUG(10,("Exiting sys_acl_create_entry\n"));
2786 return(0);
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"));
2802 return(0);
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) &&
2811 (*permset != 0))
2812 return(-1);
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"));
2817 return(0);
2820 int sys_acl_valid( SMB_ACL_T theacl )
2822 int user_obj = 0;
2823 int group_obj = 0;
2824 int other_obj = 0;
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)
2836 return(-1);
2838 return(0);
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;
2848 uint id_type;
2849 uint ace_access;
2850 uint user_id;
2851 uint acl_length;
2852 uint rc;
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)
2859 return(0);
2861 acl_length = BUFSIZ;
2862 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2864 if(file_acl == NULL) {
2865 errno = ENOMEM;
2866 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2867 return(-1);
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;
2879 switch(id_type) {
2880 case SMB_ACL_USER_OBJ:
2881 file_acl->u_access = acl_entry_link->entryp->ace_access;
2882 continue;
2883 case SMB_ACL_GROUP_OBJ:
2884 file_acl->g_access = acl_entry_link->entryp->ace_access;
2885 continue;
2886 case SMB_ACL_OTHER:
2887 file_acl->o_access = acl_entry_link->entryp->ace_access;
2888 continue;
2889 case SMB_ACL_MASK:
2890 continue;
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);
2898 errno = ENOMEM;
2899 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2900 return(-1);
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"));
2933 return(rc);
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;
2943 uint id_type;
2944 uint user_id;
2945 uint acl_length;
2946 uint rc;
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) {
2953 errno = ENOMEM;
2954 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2955 return(-1);
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));
2968 switch(id_type) {
2969 case SMB_ACL_USER_OBJ:
2970 file_acl->u_access = acl_entry_link->entryp->ace_access;
2971 continue;
2972 case SMB_ACL_GROUP_OBJ:
2973 file_acl->g_access = acl_entry_link->entryp->ace_access;
2974 continue;
2975 case SMB_ACL_OTHER:
2976 file_acl->o_access = acl_entry_link->entryp->ace_access;
2977 continue;
2978 case SMB_ACL_MASK:
2979 continue;
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);
2987 errno = ENOMEM;
2988 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2989 return(-1);
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"));
3022 return(rc);
3025 int sys_acl_delete_def_file(const char *name)
3027 /* AIX has no default ACL */
3028 return 0;
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)
3038 return(0);
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);
3055 return(0);
3058 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3060 return(0);
3063 #else /* No ACLs. */
3065 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
3067 errno = ENOSYS;
3068 return -1;
3071 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
3073 errno = ENOSYS;
3074 return -1;
3077 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
3079 errno = ENOSYS;
3080 return -1;
3083 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
3085 errno = ENOSYS;
3086 return NULL;
3089 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
3091 errno = ENOSYS;
3092 return (SMB_ACL_T)NULL;
3095 SMB_ACL_T sys_acl_get_fd(int fd)
3097 errno = ENOSYS;
3098 return (SMB_ACL_T)NULL;
3101 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
3103 errno = ENOSYS;
3104 return -1;
3107 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3109 errno = ENOSYS;
3110 return -1;
3113 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
3115 errno = ENOSYS;
3116 return (permset & perm) ? 1 : 0;
3119 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
3121 errno = ENOSYS;
3122 return NULL;
3125 int sys_acl_free_text(char *text)
3127 errno = ENOSYS;
3128 return -1;
3131 SMB_ACL_T sys_acl_init( int count)
3133 errno = ENOSYS;
3134 return NULL;
3137 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
3139 errno = ENOSYS;
3140 return -1;
3143 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
3145 errno = ENOSYS;
3146 return -1;
3149 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
3151 errno = ENOSYS;
3152 return -1;
3155 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
3157 errno = ENOSYS;
3158 return -1;
3161 int sys_acl_valid( SMB_ACL_T theacl )
3163 errno = ENOSYS;
3164 return -1;
3167 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
3169 errno = ENOSYS;
3170 return -1;
3173 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
3175 errno = ENOSYS;
3176 return -1;
3179 int sys_acl_delete_def_file(const char *name)
3181 errno = ENOSYS;
3182 return -1;
3185 int sys_acl_free_acl(SMB_ACL_T the_acl)
3187 errno = ENOSYS;
3188 return -1;
3191 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
3193 errno = ENOSYS;
3194 return -1;
3197 #endif /* No ACLs. */
3199 /************************************************************************
3200 Deliberately outside the ACL defines. Return 1 if this is a "no acls"
3201 errno, 0 if not.
3202 ************************************************************************/
3204 int no_acl_syscall_error(int err)
3206 #if defined(ENOSYS)
3207 if (err == ENOSYS) {
3208 return 1;
3210 #endif
3211 #if defined(ENOTSUP)
3212 if (err == ENOTSUP) {
3213 return 1;
3215 #endif
3216 return 0;