fix for Solaris ACL support. The sys_acl_set_file was writing out
[Samba.git] / source / lib / sysacls.c
blob5df67596ac6ba21550fac254f52b15601f1110e7
1 /*
2 Unix SMB/Netbios implementation.
3 Version 2.2.
4 Samba system utilities for ACL support.
5 Copyright (C) Jeremy Allison 2000.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 extern int DEBUGLEVEL;
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( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
49 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
51 This next one is not POSIX complient - but we *have* to have it !
52 More POSIX braindamage.
54 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
56 The generic POSIX free is the following call. We split this into
57 several different free functions as we may need to add tag info
58 to structures when emulating the POSIX interface.
60 int sys_acl_free( void *obj_p)
62 The calls we actually use are :
64 int sys_acl_free_text(char *text) - free acl_to_text
65 int sys_acl_free_acl(SMB_ACL_T posix_acl)
66 int sys_acl_free_qualifier(SMB_ACL_T posix_acl)
70 #if defined(HAVE_POSIX_ACLS)
72 /* Identity mapping - easy. */
74 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
76 return acl_get_entry( the_acl, entry_id, entry_p);
79 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
81 return acl_get_tag_type( entry_d, tag_type_p);
84 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
86 return acl_get_permset( entry_d, permset_p);
89 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
91 return acl_get_qualifier( entry_d);
94 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
96 return acl_get_file( path_p, type);
99 SMB_ACL_T sys_acl_get_fd(int fd)
101 return acl_get_fd(fd);
104 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
106 return acl_clear_perms(permset);
109 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
111 return acl_add_perm(permset, perm);
114 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
116 #if defined(HAVE_ACL_GET_PERM_NP)
118 * Required for TrustedBSD-based ACL implementations where
119 * non-POSIX.1e functions are denoted by a _np (non-portable)
120 * suffix.
122 return acl_get_perm_np(permset, perm);
123 #else
124 return acl_get_perm(permset, perm);
125 #endif
128 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
130 return acl_to_text( the_acl, plen);
133 SMB_ACL_T sys_acl_init( int count)
135 return acl_init(count);
138 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
140 return acl_create_entry(pacl, pentry);
143 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
145 return acl_set_tag_type(entry, tagtype);
148 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
150 return acl_set_qualifier(entry, qual);
153 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
155 return acl_set_permset(entry, permset);
158 int sys_acl_valid( SMB_ACL_T theacl )
160 return acl_valid(theacl);
163 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
165 return acl_set_file(name, acltype, theacl);
168 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
170 return acl_set_fd(fd, theacl);
173 int sys_acl_free_text(char *text)
175 return acl_free(text);
178 int sys_acl_free_acl(SMB_ACL_T the_acl)
180 return acl_free(the_acl);
183 int sys_acl_free_qualifier(void *qual)
185 return acl_free(qual);
188 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
191 * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
192 * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
196 * Note that while this code implements sufficient functionality
197 * to support the sys_acl_* interfaces it does not provide all
198 * of the semantics of the POSIX ACL interfaces.
200 * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
201 * from a call to sys_acl_get_entry() should not be assumed to be
202 * valid after calling any of the following functions, which may
203 * reorder the entries in the ACL.
205 * sys_acl_valid()
206 * sys_acl_set_file()
207 * sys_acl_set_fd()
211 * The only difference between Solaris and UnixWare / OpenUNIX is
212 * that the #defines for the ACL operations have different names
214 #if defined(HAVE_UNIXWARE_ACLS)
216 #define SETACL ACL_SET
217 #define GETACL ACL_GET
218 #define GETACLCNT ACL_CNT
220 #endif
223 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
225 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
226 errno = EINVAL;
227 return -1;
230 if (entry_p == NULL) {
231 errno = EINVAL;
232 return -1;
235 if (entry_id == SMB_ACL_FIRST_ENTRY) {
236 acl_d->next = 0;
239 if (acl_d->next < 0) {
240 errno = EINVAL;
241 return -1;
244 if (acl_d->next >= acl_d->count) {
245 return 0;
248 *entry_p = &acl_d->acl[acl_d->next++];
250 return 1;
253 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
255 *type_p = entry_d->a_type;
257 return 0;
260 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
262 *permset_p = &entry_d->a_perm;
264 return 0;
267 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
269 if (entry_d->a_type != SMB_ACL_USER
270 && entry_d->a_type != SMB_ACL_GROUP) {
271 errno = EINVAL;
272 return NULL;
275 return &entry_d->a_id;
279 * There is no way of knowing what size the ACL returned by
280 * GETACL will be unless you first call GETACLCNT which means
281 * making an additional system call.
283 * In the hope of avoiding the cost of the additional system
284 * call in most cases, we initially allocate enough space for
285 * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
286 * be too small then we use GETACLCNT to find out the actual
287 * size, reallocate the ACL buffer, and then call GETACL again.
290 #define INITIAL_ACL_SIZE 16
292 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
294 SMB_ACL_T acl_d;
295 int count; /* # of ACL entries allocated */
296 int naccess; /* # of access ACL entries */
297 int ndefault; /* # of default ACL entries */
299 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
300 errno = EINVAL;
301 return NULL;
304 count = INITIAL_ACL_SIZE;
305 if ((acl_d = sys_acl_init(count)) == NULL) {
306 return NULL;
310 * If there isn't enough space for the ACL entries we use
311 * GETACLCNT to determine the actual number of ACL entries
312 * reallocate and try again. This is in a loop because it
313 * is possible that someone else could modify the ACL and
314 * increase the number of entries between the call to
315 * GETACLCNT and the call to GETACL.
317 while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
318 && errno == ENOSPC) {
320 sys_acl_free_acl(acl_d);
322 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
323 return NULL;
326 if ((acl_d = sys_acl_init(count)) == NULL) {
327 return NULL;
331 if (count < 0) {
332 sys_acl_free_acl(acl_d);
333 return NULL;
337 * calculate the number of access and default ACL entries
339 * Note: we assume that the acl() system call returned a
340 * well formed ACL which is sorted so that all of the
341 * access ACL entries preceed any default ACL entries
343 for (naccess = 0; naccess < count; naccess++) {
344 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
345 break;
347 ndefault = count - naccess;
350 * if the caller wants the default ACL we have to copy
351 * the entries down to the start of the acl[] buffer
352 * and mask out the ACL_DEFAULT flag from the type field
354 if (type == SMB_ACL_TYPE_DEFAULT) {
355 int i, j;
357 for (i = 0, j = naccess; i < ndefault; i++, j++) {
358 acl_d->acl[i] = acl_d->acl[j];
359 acl_d->acl[i].a_type &= ~ACL_DEFAULT;
362 acl_d->count = ndefault;
363 } else {
364 acl_d->count = naccess;
367 return acl_d;
370 SMB_ACL_T sys_acl_get_fd(int fd)
372 SMB_ACL_T acl_d;
373 int count; /* # of ACL entries allocated */
374 int naccess; /* # of access ACL entries */
376 count = INITIAL_ACL_SIZE;
377 if ((acl_d = sys_acl_init(count)) == NULL) {
378 return NULL;
381 while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
382 && errno == ENOSPC) {
384 sys_acl_free_acl(acl_d);
386 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
387 return NULL;
390 if ((acl_d = sys_acl_init(count)) == NULL) {
391 return NULL;
395 if (count < 0) {
396 sys_acl_free_acl(acl_d);
397 return NULL;
401 * calculate the number of access ACL entries
403 for (naccess = 0; naccess < count; naccess++) {
404 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
405 break;
408 acl_d->count = naccess;
410 return acl_d;
413 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
415 *permset_d = 0;
417 return 0;
420 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
422 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
423 && perm != SMB_ACL_EXECUTE) {
424 errno = EINVAL;
425 return -1;
428 if (permset_d == NULL) {
429 errno = EINVAL;
430 return -1;
433 *permset_d |= perm;
435 return 0;
438 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
440 return *permset_d & perm;
443 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
445 int i;
446 int len, maxlen;
447 char *text;
450 * use an initial estimate of 20 bytes per ACL entry
451 * when allocating memory for the text representation
452 * of the ACL
454 len = 0;
455 maxlen = 20 * acl_d->count;
456 if ((text = malloc(maxlen)) == NULL) {
457 errno = ENOMEM;
458 return NULL;
461 for (i = 0; i < acl_d->count; i++) {
462 struct acl *ap = &acl_d->acl[i];
463 struct passwd *pw;
464 struct group *gr;
465 char tagbuf[12];
466 char idbuf[12];
467 char *tag;
468 char *id = "";
469 char perms[4];
470 int nbytes;
472 switch (ap->a_type) {
474 * for debugging purposes it's probably more
475 * useful to dump unknown tag types rather
476 * than just returning an error
478 default:
479 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
480 ap->a_type);
481 tag = tagbuf;
482 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
483 (long)ap->a_id);
484 id = idbuf;
485 break;
487 case SMB_ACL_USER:
488 if ((pw = sys_getpwuid(ap->a_id)) == NULL) {
489 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
490 (long)ap->a_id);
491 id = idbuf;
492 } else {
493 id = pw->pw_name;
495 case SMB_ACL_USER_OBJ:
496 tag = "user";
497 break;
499 case SMB_ACL_GROUP:
500 if ((gr = getgrgid(ap->a_id)) == NULL) {
501 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
502 (long)ap->a_id);
503 id = idbuf;
504 } else {
505 id = gr->gr_name;
507 case SMB_ACL_GROUP_OBJ:
508 tag = "group";
509 break;
511 case SMB_ACL_OTHER:
512 tag = "other";
513 break;
515 case SMB_ACL_MASK:
516 tag = "mask";
517 break;
521 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
522 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
523 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
524 perms[3] = '\0';
526 /* <tag> : <qualifier> : rwx \n \0 */
527 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
530 * If this entry would overflow the buffer
531 * allocate enough additional memory for this
532 * entry and an estimate of another 20 bytes
533 * for each entry still to be processed
535 if ((len + nbytes) > maxlen) {
536 char *oldtext = text;
538 maxlen += nbytes + 20 * (acl_d->count - i);
540 if ((text = realloc(oldtext, maxlen)) == NULL) {
541 free(oldtext);
542 errno = ENOMEM;
543 return NULL;
547 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
548 len += nbytes - 1;
551 if (len_p)
552 *len_p = len;
554 return text;
557 SMB_ACL_T sys_acl_init(int count)
559 SMB_ACL_T a;
561 if (count < 0) {
562 errno = EINVAL;
563 return NULL;
567 * note that since the definition of the structure pointed
568 * to by the SMB_ACL_T includes the first element of the
569 * acl[] array, this actually allocates an ACL with room
570 * for (count+1) entries
572 if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) {
573 errno = ENOMEM;
574 return NULL;
577 a->size = count + 1;
578 a->count = 0;
579 a->next = -1;
581 return a;
585 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
587 SMB_ACL_T acl_d;
588 SMB_ACL_ENTRY_T entry_d;
590 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
591 errno = EINVAL;
592 return -1;
595 if (acl_d->count >= acl_d->size) {
596 errno = ENOSPC;
597 return -1;
600 entry_d = &acl_d->acl[acl_d->count++];
601 entry_d->a_type = 0;
602 entry_d->a_id = -1;
603 entry_d->a_perm = 0;
604 *entry_p = entry_d;
606 return 0;
609 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
611 switch (tag_type) {
612 case SMB_ACL_USER:
613 case SMB_ACL_USER_OBJ:
614 case SMB_ACL_GROUP:
615 case SMB_ACL_GROUP_OBJ:
616 case SMB_ACL_OTHER:
617 case SMB_ACL_MASK:
618 entry_d->a_type = tag_type;
619 break;
620 default:
621 errno = EINVAL;
622 return -1;
625 return 0;
628 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
630 if (entry_d->a_type != SMB_ACL_GROUP
631 && entry_d->a_type != SMB_ACL_USER) {
632 errno = EINVAL;
633 return -1;
636 entry_d->a_id = *((id_t *)qual_p);
638 return 0;
641 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
643 if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
644 return EINVAL;
647 entry_d->a_perm = *permset_d;
649 return 0;
652 int sys_acl_valid(SMB_ACL_T acl_d)
654 if (aclsort(acl_d->count, 0, acl_d->acl) != 0) {
655 errno = EINVAL;
656 return -1;
659 return 0;
662 int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
664 struct stat s;
665 struct acl *acl_p;
666 int acl_count;
667 struct acl *acl_buf = NULL;
668 int ret;
670 if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
671 errno = EINVAL;
672 return -1;
675 if (stat(name, &s) != 0) {
676 return -1;
679 acl_p = &acl_d->acl[0];
680 acl_count = acl_d->count;
683 * if it's a directory there is extra work to do
684 * since the acl() system call will replace both
685 * the access ACLs and the default ACLs (if any)
687 if (S_ISDIR(s.st_mode)) {
688 SMB_ACL_T acc_acl;
689 SMB_ACL_T def_acl;
690 SMB_ACL_T tmp_acl;
691 int i;
693 if (type == SMB_ACL_TYPE_ACCESS) {
694 acc_acl = acl_d;
695 def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
697 } else {
698 def_acl = acl_d;
699 acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
702 if (tmp_acl == NULL) {
703 return -1;
707 * allocate a temporary buffer for the complete ACL
709 acl_count = acc_acl->count + def_acl->count;
710 acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0]));
712 if (acl_buf == NULL) {
713 sys_acl_free_acl(tmp_acl);
714 errno = ENOMEM;
715 return -1;
719 * copy the access control and default entries into the buffer
721 memcpy(&acl_buf[0], &acc_acl->acl[0],
722 acc_acl->count * sizeof(acl_buf[0]));
724 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
725 def_acl->count * sizeof(acl_buf[0]));
728 * set the ACL_DEFAULT flag on the default entries
730 for (i = acc_acl->count; i < acl_count; i++) {
731 acl_buf[i].a_type |= ACL_DEFAULT;
734 sys_acl_free_acl(tmp_acl);
736 } else if (type != SMB_ACL_TYPE_ACCESS) {
737 errno = EINVAL;
738 return -1;
741 if (aclsort(acl_count, 0, acl_p) != 0) {
742 errno = EINVAL;
743 ret = -1;
744 } else {
745 ret = acl(name, SETACL, acl_count, acl_p);
748 if (acl_buf) {
749 free(acl_buf);
752 return ret;
755 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
757 if (aclsort(acl_d->count, 0, acl_d->acl) != 0) {
758 errno = EINVAL;
759 return -1;
762 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
765 int sys_acl_free_text(char *text)
767 free(text);
768 return 0;
771 int sys_acl_free_acl(SMB_ACL_T acl_d)
773 free(acl_d);
774 return 0;
777 int sys_acl_free_qualifier(void *qual)
779 return 0;
782 #elif defined(HAVE_IRIX_ACLS)
784 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
786 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
787 errno = EINVAL;
788 return -1;
791 if (entry_p == NULL) {
792 errno = EINVAL;
793 return -1;
796 if (entry_id == SMB_ACL_FIRST_ENTRY) {
797 acl_d->next = 0;
800 if (acl_d->next < 0) {
801 errno = EINVAL;
802 return -1;
805 if (acl_d->next >= acl_d->aclp->acl_cnt) {
806 return 0;
809 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
811 return 1;
814 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
816 *type_p = entry_d->ae_tag;
818 return 0;
821 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
823 *permset_p = entry_d;
825 return 0;
828 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
830 if (entry_d->ae_tag != SMB_ACL_USER
831 && entry_d->ae_tag != SMB_ACL_GROUP) {
832 errno = EINVAL;
833 return NULL;
836 return &entry_d->ae_id;
839 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
841 SMB_ACL_T a;
843 if ((a = malloc(sizeof(*a))) == NULL) {
844 errno = ENOMEM;
845 return NULL;
847 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
848 free(a);
849 return NULL;
851 a->next = -1;
852 a->freeaclp = True;
853 return a;
856 SMB_ACL_T sys_acl_get_fd(int fd)
858 SMB_ACL_T a;
860 if ((a = malloc(sizeof(*a))) == NULL) {
861 errno = ENOMEM;
862 return NULL;
864 if ((a->aclp = acl_get_fd(fd)) == NULL) {
865 free(a);
866 return NULL;
868 a->next = -1;
869 a->freeaclp = True;
870 return a;
873 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
875 permset_d->ae_perm = 0;
877 return 0;
880 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
882 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
883 && perm != SMB_ACL_EXECUTE) {
884 errno = EINVAL;
885 return -1;
888 if (permset_d == NULL) {
889 errno = EINVAL;
890 return -1;
893 permset_d->ae_perm |= perm;
895 return 0;
898 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
900 return permset_d->ae_perm & perm;
903 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
905 return acl_to_text(acl_d->aclp, len_p);
908 SMB_ACL_T sys_acl_init(int count)
910 SMB_ACL_T a;
912 if (count < 0) {
913 errno = EINVAL;
914 return NULL;
917 if ((a = malloc(sizeof(*a) + sizeof(struct acl))) == NULL) {
918 errno = ENOMEM;
919 return NULL;
922 a->next = -1;
923 a->freeaclp = False;
924 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
925 a->aclp->acl_cnt = 0;
927 return a;
931 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
933 SMB_ACL_T acl_d;
934 SMB_ACL_ENTRY_T entry_d;
936 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
937 errno = EINVAL;
938 return -1;
941 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
942 errno = ENOSPC;
943 return -1;
946 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
947 entry_d->ae_tag = 0;
948 entry_d->ae_id = 0;
949 entry_d->ae_perm = 0;
950 *entry_p = entry_d;
952 return 0;
955 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
957 switch (tag_type) {
958 case SMB_ACL_USER:
959 case SMB_ACL_USER_OBJ:
960 case SMB_ACL_GROUP:
961 case SMB_ACL_GROUP_OBJ:
962 case SMB_ACL_OTHER:
963 case SMB_ACL_MASK:
964 entry_d->ae_tag = tag_type;
965 break;
966 default:
967 errno = EINVAL;
968 return -1;
971 return 0;
974 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
976 if (entry_d->ae_tag != SMB_ACL_GROUP
977 && entry_d->ae_tag != SMB_ACL_USER) {
978 errno = EINVAL;
979 return -1;
982 entry_d->ae_id = *((id_t *)qual_p);
984 return 0;
987 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
989 if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
990 return EINVAL;
993 entry_d->ae_perm = permset_d->ae_perm;
995 return 0;
998 int sys_acl_valid(SMB_ACL_T acl_d)
1000 return acl_valid(acl_d->aclp);
1003 int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1005 return acl_set_file(name, type, acl_d->aclp);
1008 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1010 return acl_set_fd(fd, acl_d->aclp);
1013 int sys_acl_free_text(char *text)
1015 return acl_free(text);
1018 int sys_acl_free_acl(SMB_ACL_T acl_d)
1020 if (acl_d->freeaclp) {
1021 acl_free(acl_d->aclp);
1023 acl_free(acl_d);
1024 return 0;
1027 int sys_acl_free_qualifier(void *qual)
1029 return 0;
1032 #elif defined(HAVE_XFS_ACLS)
1033 /* For Linux SGI/XFS Filesystems
1034 * contributed by J Trostel, Connex
1035 * */
1037 /* based on the implementation for Solaris by Toomas Soome.. which is
1038 * based on the implementation by Micheal Davidson for Unixware...
1040 * Linux XFS is a 'work-in-progress'
1041 * This interface may change...
1042 * You've been warned ;-> */
1044 /* First, do the identity mapping */
1046 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1048 if( acl_get_entry( the_acl, entry_id, entry_p) >= 0) {
1049 return 1;
1051 else {
1052 return -1;
1056 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1058 return acl_get_file( path_p, type);
1061 SMB_ACL_T sys_acl_get_fd(int fd)
1063 return acl_get_fd(fd);
1066 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
1068 return acl_to_text( the_acl, plen);
1071 int sys_acl_valid( SMB_ACL_T theacl )
1073 return acl_valid(theacl);
1076 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1078 return acl_set_file(name, acltype, theacl);
1081 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
1083 return acl_set_fd(fd, theacl);
1086 /* Now the functions I need to define for XFS */
1088 int sys_acl_create_entry( SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1090 acl_t acl, newacl;
1091 acl_entry_t ace;
1092 int cnt;
1094 acl = *acl_p;
1095 ace = *entry_p;
1097 if((*acl_p == NULL) || (ace == NULL)){
1098 errno = EINVAL;
1099 return -1;
1102 cnt = acl->acl_cnt;
1103 if( (cnt + 1) > ACL_MAX_ENTRIES ){
1104 errno = ENOSPC;
1105 return -1;
1108 newacl = (acl_t)malloc(sizeof(struct acl));
1109 if(newacl == NULL){
1110 errno = ENOMEM;
1111 return -1;
1114 *newacl = *acl;
1115 newacl->acl_entry[cnt] = *ace;
1116 newacl->acl_cnt = cnt + 1;
1118 acl_free(*acl_p);
1119 *acl_p = newacl;
1120 *entry_p = &newacl->acl_entry[cnt];
1121 return 0;
1125 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1127 *tag_type_p = entry_d->ae_tag;
1128 return 0;
1131 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1133 *permset_p = &entry_d->ae_perm;
1134 return 0;
1137 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1139 if (entry_d->ae_tag != SMB_ACL_USER
1140 && entry_d->ae_tag != SMB_ACL_GROUP) {
1141 errno = EINVAL;
1142 return NULL;
1144 return &entry_d->ae_id;
1147 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1149 *permset = 0;
1150 return 0;
1153 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1155 return (*permset & perm);
1158 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1161 /* TO DO: Add in ALL possible permissions here */
1162 /* TO DO: Include extended ones!! */
1164 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE && perm != SMB_ACL_EXECUTE) {
1165 errno = EINVAL;
1166 return -1;
1169 if(permset == NULL) {
1170 errno = EINVAL;
1171 return -1;
1174 *permset |= perm;
1176 return 0;
1179 SMB_ACL_T sys_acl_init( int count)
1181 SMB_ACL_T a;
1182 if((count > ACL_MAX_ENTRIES) || (count < 0)) {
1183 errno = EINVAL;
1184 return NULL;
1186 else {
1187 a = (struct acl *)malloc(sizeof(struct acl)); /* where is this memory freed? */
1188 a->acl_cnt = 0;
1189 return a;
1193 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1196 switch (tag_type) {
1197 case SMB_ACL_USER:
1198 case SMB_ACL_USER_OBJ:
1199 case SMB_ACL_GROUP:
1200 case SMB_ACL_GROUP_OBJ:
1201 case SMB_ACL_OTHER:
1202 case SMB_ACL_MASK:
1203 entry_d->ae_tag = tag_type;
1204 break;
1205 default:
1206 errno = EINVAL;
1207 return -1;
1209 return 0;
1212 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry_d, void *qual_p)
1214 if(entry_d->ae_tag != SMB_ACL_GROUP &&
1215 entry_d->ae_tag != SMB_ACL_USER) {
1216 errno = EINVAL;
1217 return -1;
1220 entry_d->ae_id = *((uid_t *)qual_p);
1222 return 0;
1225 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1227 /* TO DO: expand to extended permissions eventually! */
1229 if(*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1230 return EINVAL;
1233 return 0;
1236 int sys_acl_free_text(char *text)
1238 return acl_free(text);
1241 int sys_acl_free_acl(SMB_ACL_T the_acl)
1243 return acl_free(the_acl);
1246 int sys_acl_free_qualifier(void *qual)
1248 return 0;
1251 #elif defined(HAVE_AIX_ACLS)
1253 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1255 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1257 struct acl_entry_link *link;
1258 struct new_acl_entry *entry;
1259 int keep_going;
1261 DEBUG(10,("This is the count: %d\n",theacl->count));
1263 /* Check if count was previously set to -1. *
1264 * If it was, that means we reached the end *
1265 * of the acl last time. */
1266 if(theacl->count == -1)
1267 return(0);
1269 link = theacl;
1270 /* To get to the next acl, traverse linked list until index *
1271 * of acl matches the count we are keeping. This count is *
1272 * incremented each time we return an acl entry. */
1274 for(keep_going = 0; keep_going < theacl->count; keep_going++)
1275 link = link->nextp;
1277 entry = *entry_p = link->entryp;
1279 DEBUG(10,("*entry_p is %d\n",entry_p));
1280 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1282 /* Increment count */
1283 theacl->count++;
1284 if(link->nextp == NULL)
1285 theacl->count = -1;
1287 return(1);
1290 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1292 /* Initialize tag type */
1294 *tag_type_p = -1;
1295 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1297 /* Depending on what type of entry we have, *
1298 * return tag type. */
1299 switch(entry_d->ace_id->id_type) {
1300 case ACEID_USER:
1301 *tag_type_p = SMB_ACL_USER;
1302 break;
1303 case ACEID_GROUP:
1304 *tag_type_p = SMB_ACL_GROUP;
1305 break;
1307 case SMB_ACL_USER_OBJ:
1308 case SMB_ACL_GROUP_OBJ:
1309 case SMB_ACL_OTHER:
1310 *tag_type_p = entry_d->ace_id->id_type;
1311 break;
1313 default:
1314 return(-1);
1317 return(0);
1320 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1322 DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
1323 *permset_p = &entry_d->ace_access;
1324 DEBUG(10,("**permset_p is %d\n",**permset_p));
1325 if(!(**permset_p & S_IXUSR) &&
1326 !(**permset_p & S_IWUSR) &&
1327 !(**permset_p & S_IRUSR) &&
1328 (**permset_p != 0))
1329 return(-1);
1331 DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
1332 return(0);
1335 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1337 return(entry_d->ace_id->id_data);
1340 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1342 struct acl *file_acl = (struct acl *)NULL;
1343 struct acl_entry *acl_entry;
1344 struct new_acl_entry *new_acl_entry;
1345 struct ace_id *idp;
1346 struct acl_entry_link *acl_entry_link;
1347 struct acl_entry_link *acl_entry_link_head;
1348 int i;
1349 int rc = 0;
1350 uid_t user_id;
1352 /* Get the acl using statacl */
1354 DEBUG(10,("Entering sys_acl_get_file\n"));
1355 DEBUG(10,("path_p is %s\n",path_p));
1357 file_acl = (struct acl *)malloc(BUFSIZ);
1359 if(file_acl == NULL) {
1360 errno=ENOMEM;
1361 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1362 return(NULL);
1365 memset(file_acl,0,BUFSIZ);
1367 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1368 if(rc == -1) {
1369 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1370 free(file_acl);
1371 return(NULL);
1374 DEBUG(10,("Got facl and returned it\n"));
1376 /* Point to the first acl entry in the acl */
1377 acl_entry = file_acl->acl_ext;
1379 /* Begin setting up the head of the linked list *
1380 * that will be used for the storing the acl *
1381 * in a way that is useful for the posix_acls.c *
1382 * code. */
1384 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1385 if(acl_entry_link_head == NULL)
1386 return(NULL);
1388 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1389 if(acl_entry_link->entryp == NULL) {
1390 free(file_acl);
1391 errno = ENOMEM;
1392 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1393 return(NULL);
1396 DEBUG(10,("acl_entry is %d\n",acl_entry));
1397 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1399 /* Check if the extended acl bit is on. *
1400 * If it isn't, do not show the *
1401 * contents of the acl since AIX intends *
1402 * the extended info to remain unused */
1404 if(file_acl->acl_mode & S_IXACL){
1405 /* while we are not pointing to the very end */
1406 while(acl_entry < acl_last(file_acl)) {
1407 /* before we malloc anything, make sure this is */
1408 /* a valid acl entry and one that we want to map */
1409 idp = id_nxt(acl_entry->ace_id);
1410 if((acl_entry->ace_type == ACC_SPECIFY ||
1411 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1412 acl_entry = acl_nxt(acl_entry);
1413 continue;
1416 idp = acl_entry->ace_id;
1418 /* Check if this is the first entry in the linked list. *
1419 * The first entry needs to keep prevp pointing to NULL *
1420 * and already has entryp allocated. */
1422 if(acl_entry_link_head->count != 0) {
1423 acl_entry_link->nextp = (struct acl_entry_link *)
1424 malloc(sizeof(struct acl_entry_link));
1426 if(acl_entry_link->nextp == NULL) {
1427 free(file_acl);
1428 errno = ENOMEM;
1429 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1430 return(NULL);
1433 acl_entry_link->nextp->prevp = acl_entry_link;
1434 acl_entry_link = acl_entry_link->nextp;
1435 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1436 if(acl_entry_link->entryp == NULL) {
1437 free(file_acl);
1438 errno = ENOMEM;
1439 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1440 return(NULL);
1442 acl_entry_link->nextp = NULL;
1445 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1447 /* Don't really need this since all types are going *
1448 * to be specified but, it's better than leaving it 0 */
1450 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1452 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1454 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
1456 /* The access in the acl entries must be left shifted by *
1457 * three bites, because they will ultimately be compared *
1458 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
1460 switch(acl_entry->ace_type){
1461 case ACC_PERMIT:
1462 case ACC_SPECIFY:
1463 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1464 acl_entry_link->entryp->ace_access <<= 6;
1465 acl_entry_link_head->count++;
1466 break;
1467 case ACC_DENY:
1468 /* Since there is no way to return a DENY acl entry *
1469 * change to PERMIT and then shift. */
1470 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1471 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1472 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1473 acl_entry_link->entryp->ace_access <<= 6;
1474 acl_entry_link_head->count++;
1475 break;
1476 default:
1477 return(0);
1480 DEBUG(10,("acl_entry = %d\n",acl_entry));
1481 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1483 acl_entry = acl_nxt(acl_entry);
1485 } /* end of if enabled */
1487 /* Since owner, group, other acl entries are not *
1488 * part of the acl entries in an acl, they must *
1489 * be dummied up to become part of the list. */
1491 for( i = 1; i < 4; i++) {
1492 DEBUG(10,("i is %d\n",i));
1493 if(acl_entry_link_head->count != 0) {
1494 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1495 if(acl_entry_link->nextp == NULL) {
1496 free(file_acl);
1497 errno = ENOMEM;
1498 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1499 return(NULL);
1502 acl_entry_link->nextp->prevp = acl_entry_link;
1503 acl_entry_link = acl_entry_link->nextp;
1504 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1505 if(acl_entry_link->entryp == NULL) {
1506 free(file_acl);
1507 errno = ENOMEM;
1508 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1509 return(NULL);
1513 acl_entry_link->nextp = NULL;
1515 new_acl_entry = acl_entry_link->entryp;
1516 idp = new_acl_entry->ace_id;
1518 new_acl_entry->ace_len = sizeof(struct acl_entry);
1519 new_acl_entry->ace_type = ACC_PERMIT;
1520 idp->id_len = sizeof(struct ace_id);
1521 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1522 memset(idp->id_data,0,sizeof(uid_t));
1524 switch(i) {
1525 case 2:
1526 new_acl_entry->ace_access = file_acl->g_access << 6;
1527 idp->id_type = SMB_ACL_GROUP_OBJ;
1528 break;
1530 case 3:
1531 new_acl_entry->ace_access = file_acl->o_access << 6;
1532 idp->id_type = SMB_ACL_OTHER;
1533 break;
1535 case 1:
1536 new_acl_entry->ace_access = file_acl->u_access << 6;
1537 idp->id_type = SMB_ACL_USER_OBJ;
1538 break;
1540 default:
1541 return(NULL);
1545 acl_entry_link_head->count++;
1546 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1549 acl_entry_link_head->count = 0;
1550 free(file_acl);
1552 return(acl_entry_link_head);
1555 SMB_ACL_T sys_acl_get_fd(int fd)
1557 struct acl *file_acl = (struct acl *)NULL;
1558 struct acl_entry *acl_entry;
1559 struct new_acl_entry *new_acl_entry;
1560 struct ace_id *idp;
1561 struct acl_entry_link *acl_entry_link;
1562 struct acl_entry_link *acl_entry_link_head;
1563 int i;
1564 int rc = 0;
1565 uid_t user_id;
1567 /* Get the acl using fstatacl */
1569 DEBUG(10,("Entering sys_acl_get_fd\n"));
1570 DEBUG(10,("fd is %d\n",fd));
1571 file_acl = (struct acl *)malloc(BUFSIZ);
1573 if(file_acl == NULL) {
1574 errno=ENOMEM;
1575 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1576 return(NULL);
1579 memset(file_acl,0,BUFSIZ);
1581 rc = fstatacl(fd,0,file_acl,BUFSIZ);
1582 if(rc == -1) {
1583 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
1584 free(file_acl);
1585 return(NULL);
1588 DEBUG(10,("Got facl and returned it\n"));
1590 /* Point to the first acl entry in the acl */
1592 acl_entry = file_acl->acl_ext;
1593 /* Begin setting up the head of the linked list *
1594 * that will be used for the storing the acl *
1595 * in a way that is useful for the posix_acls.c *
1596 * code. */
1598 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1599 if(acl_entry_link_head == NULL){
1600 free(file_acl);
1601 return(NULL);
1604 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1606 if(acl_entry_link->entryp == NULL) {
1607 errno = ENOMEM;
1608 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1609 free(file_acl);
1610 return(NULL);
1613 DEBUG(10,("acl_entry is %d\n",acl_entry));
1614 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1616 /* Check if the extended acl bit is on. *
1617 * If it isn't, do not show the *
1618 * contents of the acl since AIX intends *
1619 * the extended info to remain unused */
1621 if(file_acl->acl_mode & S_IXACL){
1622 /* while we are not pointing to the very end */
1623 while(acl_entry < acl_last(file_acl)) {
1624 /* before we malloc anything, make sure this is */
1625 /* a valid acl entry and one that we want to map */
1627 idp = id_nxt(acl_entry->ace_id);
1628 if((acl_entry->ace_type == ACC_SPECIFY ||
1629 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1630 acl_entry = acl_nxt(acl_entry);
1631 continue;
1634 idp = acl_entry->ace_id;
1636 /* Check if this is the first entry in the linked list. *
1637 * The first entry needs to keep prevp pointing to NULL *
1638 * and already has entryp allocated. */
1640 if(acl_entry_link_head->count != 0) {
1641 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1642 if(acl_entry_link->nextp == NULL) {
1643 errno = ENOMEM;
1644 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1645 free(file_acl);
1646 return(NULL);
1648 acl_entry_link->nextp->prevp = acl_entry_link;
1649 acl_entry_link = acl_entry_link->nextp;
1650 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1651 if(acl_entry_link->entryp == NULL) {
1652 errno = ENOMEM;
1653 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1654 free(file_acl);
1655 return(NULL);
1658 acl_entry_link->nextp = NULL;
1661 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1663 /* Don't really need this since all types are going *
1664 * to be specified but, it's better than leaving it 0 */
1666 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1667 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1669 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
1671 /* The access in the acl entries must be left shifted by *
1672 * three bites, because they will ultimately be compared *
1673 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
1675 switch(acl_entry->ace_type){
1676 case ACC_PERMIT:
1677 case ACC_SPECIFY:
1678 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1679 acl_entry_link->entryp->ace_access <<= 6;
1680 acl_entry_link_head->count++;
1681 break;
1682 case ACC_DENY:
1683 /* Since there is no way to return a DENY acl entry *
1684 * change to PERMIT and then shift. */
1685 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1686 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1687 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1688 acl_entry_link->entryp->ace_access <<= 6;
1689 acl_entry_link_head->count++;
1690 break;
1691 default:
1692 return(0);
1695 DEBUG(10,("acl_entry = %d\n",acl_entry));
1696 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1698 acl_entry = acl_nxt(acl_entry);
1700 } /* end of if enabled */
1702 /* Since owner, group, other acl entries are not *
1703 * part of the acl entries in an acl, they must *
1704 * be dummied up to become part of the list. */
1706 for( i = 1; i < 4; i++) {
1707 DEBUG(10,("i is %d\n",i));
1708 if(acl_entry_link_head->count != 0){
1709 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1710 if(acl_entry_link->nextp == NULL) {
1711 errno = ENOMEM;
1712 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1713 free(file_acl);
1714 return(NULL);
1717 acl_entry_link->nextp->prevp = acl_entry_link;
1718 acl_entry_link = acl_entry_link->nextp;
1719 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1721 if(acl_entry_link->entryp == NULL) {
1722 free(file_acl);
1723 errno = ENOMEM;
1724 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1725 return(NULL);
1729 acl_entry_link->nextp = NULL;
1731 new_acl_entry = acl_entry_link->entryp;
1732 idp = new_acl_entry->ace_id;
1734 new_acl_entry->ace_len = sizeof(struct acl_entry);
1735 new_acl_entry->ace_type = ACC_PERMIT;
1736 idp->id_len = sizeof(struct ace_id);
1737 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1738 memset(idp->id_data,0,sizeof(uid_t));
1740 switch(i) {
1741 case 2:
1742 new_acl_entry->ace_access = file_acl->g_access << 6;
1743 idp->id_type = SMB_ACL_GROUP_OBJ;
1744 break;
1746 case 3:
1747 new_acl_entry->ace_access = file_acl->o_access << 6;
1748 idp->id_type = SMB_ACL_OTHER;
1749 break;
1751 case 1:
1752 new_acl_entry->ace_access = file_acl->u_access << 6;
1753 idp->id_type = SMB_ACL_USER_OBJ;
1754 break;
1756 default:
1757 return(NULL);
1760 acl_entry_link_head->count++;
1761 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1764 acl_entry_link_head->count = 0;
1765 free(file_acl);
1767 return(acl_entry_link_head);
1770 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1772 *permset = *permset & ~0777;
1773 return(0);
1776 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1778 if((perm != 0) &&
1779 (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
1780 return(-1);
1782 *permset |= perm;
1783 DEBUG(10,("This is the permset now: %d\n",*permset));
1784 return(0);
1787 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
1789 return(NULL);
1792 SMB_ACL_T sys_acl_init( int count)
1794 struct acl_entry_link *theacl = NULL;
1796 DEBUG(10,("Entering sys_acl_init\n"));
1798 theacl = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1799 if(theacl == NULL) {
1800 errno = ENOMEM;
1801 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
1802 return(NULL);
1805 theacl->count = 0;
1806 theacl->nextp = NULL;
1807 theacl->prevp = NULL;
1808 theacl->entryp = NULL;
1809 DEBUG(10,("Exiting sys_acl_init\n"));
1810 return(theacl);
1813 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1815 struct acl_entry_link *theacl;
1816 struct acl_entry_link *acl_entryp;
1817 struct acl_entry_link *temp_entry;
1818 int counting;
1820 DEBUG(10,("Entering the sys_acl_create_entry\n"));
1822 theacl = acl_entryp = *pacl;
1824 /* Get to the end of the acl before adding entry */
1826 for(counting=0; counting < theacl->count; counting++){
1827 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
1828 temp_entry = acl_entryp;
1829 acl_entryp = acl_entryp->nextp;
1832 if(theacl->count != 0){
1833 temp_entry->nextp = acl_entryp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1834 if(acl_entryp == NULL) {
1835 errno = ENOMEM;
1836 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
1837 return(-1);
1840 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
1841 acl_entryp->prevp = temp_entry;
1842 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
1845 *pentry = acl_entryp->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1846 if(*pentry == NULL) {
1847 errno = ENOMEM;
1848 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
1849 return(-1);
1852 memset(*pentry,0,sizeof(struct new_acl_entry));
1853 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
1854 acl_entryp->entryp->ace_type = ACC_PERMIT;
1855 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
1856 acl_entryp->nextp = NULL;
1857 theacl->count++;
1858 DEBUG(10,("Exiting sys_acl_create_entry\n"));
1859 return(0);
1862 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1864 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
1865 entry->ace_id->id_type = tagtype;
1866 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
1867 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
1870 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
1872 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
1873 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
1874 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
1875 return(0);
1878 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1880 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
1881 if(!(*permset & S_IXUSR) &&
1882 !(*permset & S_IWUSR) &&
1883 !(*permset & S_IRUSR) &&
1884 (*permset != 0))
1885 return(-1);
1887 entry->ace_access = *permset;
1888 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
1889 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
1890 return(0);
1893 int sys_acl_valid( SMB_ACL_T theacl )
1895 int user_obj = 0;
1896 int group_obj = 0;
1897 int other_obj = 0;
1898 struct acl_entry_link *acl_entry;
1900 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
1901 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
1902 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
1903 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
1906 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
1908 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
1909 return(-1);
1911 return(0);
1914 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1916 struct acl_entry_link *acl_entry_link = NULL;
1917 struct acl *file_acl = NULL;
1918 struct acl *file_acl_temp = NULL;
1919 struct acl_entry *acl_entry = NULL;
1920 struct ace_id *ace_id = NULL;
1921 uint id_type;
1922 uint ace_access;
1923 uint user_id;
1924 uint acl_length;
1925 uint rc;
1927 DEBUG(10,("Entering sys_acl_set_file\n"));
1928 DEBUG(10,("File name is %s\n",name));
1930 /* AIX has no default ACL */
1931 if(acltype == SMB_ACL_TYPE_DEFAULT)
1932 return(0);
1934 acl_length = BUFSIZ;
1935 file_acl = (struct acl *)malloc(BUFSIZ);
1937 if(file_acl == NULL) {
1938 errno = ENOMEM;
1939 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
1940 return(-1);
1943 memset(file_acl,0,BUFSIZ);
1945 file_acl->acl_len = ACL_SIZ;
1946 file_acl->acl_mode = S_IXACL;
1948 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
1949 acl_entry_link->entryp->ace_access >>= 6;
1950 id_type = acl_entry_link->entryp->ace_id->id_type;
1952 switch(id_type) {
1953 case SMB_ACL_USER_OBJ:
1954 file_acl->u_access = acl_entry_link->entryp->ace_access;
1955 continue;
1956 case SMB_ACL_GROUP_OBJ:
1957 file_acl->g_access = acl_entry_link->entryp->ace_access;
1958 continue;
1959 case SMB_ACL_OTHER:
1960 file_acl->o_access = acl_entry_link->entryp->ace_access;
1961 continue;
1962 case SMB_ACL_MASK:
1963 continue;
1966 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
1967 acl_length += sizeof(struct acl_entry);
1968 file_acl_temp = (struct acl *)malloc(acl_length);
1969 if(file_acl_temp == NULL) {
1970 free(file_acl);
1971 errno = ENOMEM;
1972 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
1973 return(-1);
1976 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
1977 free(file_acl);
1978 file_acl = file_acl_temp;
1981 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
1982 file_acl->acl_len += sizeof(struct acl_entry);
1983 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
1984 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
1986 /* In order to use this, we'll need to wait until we can get denies */
1987 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
1988 acl_entry->ace_type = ACC_SPECIFY; */
1990 acl_entry->ace_type = ACC_SPECIFY;
1992 ace_id = acl_entry->ace_id;
1994 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
1995 DEBUG(10,("The id type is %d\n",ace_id->id_type));
1996 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
1997 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
1998 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2001 rc = chacl(name,file_acl,file_acl->acl_len);
2002 DEBUG(10,("errno is %d\n",errno));
2003 DEBUG(10,("return code is %d\n",rc));
2004 free(file_acl);
2005 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2006 return(rc);
2009 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2011 struct acl_entry_link *acl_entry_link = NULL;
2012 struct acl *file_acl = NULL;
2013 struct acl *file_acl_temp = NULL;
2014 struct acl_entry *acl_entry = NULL;
2015 struct ace_id *ace_id = NULL;
2016 uint id_type;
2017 uint user_id;
2018 uint acl_length;
2019 uint rc;
2021 DEBUG(10,("Entering sys_acl_set_fd\n"));
2022 acl_length = BUFSIZ;
2023 file_acl = (struct acl *)malloc(BUFSIZ);
2025 if(file_acl == NULL) {
2026 errno = ENOMEM;
2027 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2028 return(-1);
2031 memset(file_acl,0,BUFSIZ);
2033 file_acl->acl_len = ACL_SIZ;
2034 file_acl->acl_mode = S_IXACL;
2036 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2037 acl_entry_link->entryp->ace_access >>= 6;
2038 id_type = acl_entry_link->entryp->ace_id->id_type;
2039 DEBUG(10,("The id_type is %d\n",id_type));
2041 switch(id_type) {
2042 case SMB_ACL_USER_OBJ:
2043 file_acl->u_access = acl_entry_link->entryp->ace_access;
2044 continue;
2045 case SMB_ACL_GROUP_OBJ:
2046 file_acl->g_access = acl_entry_link->entryp->ace_access;
2047 continue;
2048 case SMB_ACL_OTHER:
2049 file_acl->o_access = acl_entry_link->entryp->ace_access;
2050 continue;
2051 case SMB_ACL_MASK:
2052 continue;
2055 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2056 acl_length += sizeof(struct acl_entry);
2057 file_acl_temp = (struct acl *)malloc(acl_length);
2058 if(file_acl_temp == NULL) {
2059 free(file_acl);
2060 errno = ENOMEM;
2061 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2062 return(-1);
2065 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2066 free(file_acl);
2067 file_acl = file_acl_temp;
2070 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2071 file_acl->acl_len += sizeof(struct acl_entry);
2072 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2073 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2075 /* In order to use this, we'll need to wait until we can get denies */
2076 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2077 acl_entry->ace_type = ACC_SPECIFY; */
2079 acl_entry->ace_type = ACC_SPECIFY;
2081 ace_id = acl_entry->ace_id;
2083 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2084 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2085 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2086 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2087 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2090 rc = fchacl(fd,file_acl,file_acl->acl_len);
2091 DEBUG(10,("errno is %d\n",errno));
2092 DEBUG(10,("return code is %d\n",rc));
2093 free(file_acl);
2094 DEBUG(10,("Exiting sys_acl_set_fd\n"));
2095 return(rc);
2098 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2100 return(*permset & perm);
2103 int sys_acl_free_text(char *text)
2105 return(0);
2108 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2110 struct acl_entry_link *acl_entry_link;
2112 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2113 free(acl_entry_link->prevp->entryp);
2114 free(acl_entry_link->prevp);
2117 free(acl_entry_link->prevp->entryp);
2118 free(acl_entry_link->prevp);
2119 free(acl_entry_link->entryp);
2120 free(acl_entry_link);
2122 return(0);
2125 int sys_acl_free_qualifier(void *qual)
2127 return(0);
2130 #else /* No ACLs. */
2132 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2134 errno = ENOSYS;
2135 return -1;
2138 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2140 errno = ENOSYS;
2141 return -1;
2144 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2146 errno = ENOSYS;
2147 return -1;
2150 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2152 errno = ENOSYS;
2153 return NULL;
2156 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2158 errno = ENOSYS;
2159 return (SMB_ACL_T)NULL;
2162 SMB_ACL_T sys_acl_get_fd(int fd)
2164 errno = ENOSYS;
2165 return (SMB_ACL_T)NULL;
2168 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2170 errno = ENOSYS;
2171 return -1;
2174 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2176 errno = ENOSYS;
2177 return -1;
2180 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2182 errno = ENOSYS;
2183 return (permset & perm) ? 1 : 0;
2186 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
2188 errno = ENOSYS;
2189 return NULL;
2192 int sys_acl_free_text(char *text)
2194 errno = ENOSYS;
2195 return -1;
2198 SMB_ACL_T sys_acl_init( int count)
2200 errno = ENOSYS;
2201 return NULL;
2204 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2206 errno = ENOSYS;
2207 return -1;
2210 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2212 errno = ENOSYS;
2213 return -1;
2216 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2218 errno = ENOSYS;
2219 return -1;
2222 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2224 errno = ENOSYS;
2225 return -1;
2228 int sys_acl_valid( SMB_ACL_T theacl )
2230 errno = ENOSYS;
2231 return -1;
2234 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2236 errno = ENOSYS;
2237 return -1;
2240 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2242 errno = ENOSYS;
2243 return -1;
2246 int sys_acl_free_acl(SMB_ACL_T the_acl)
2248 errno = ENOSYS;
2249 return -1;
2252 int sys_acl_free_qualifier(void *qual)
2254 errno = ENOSYS;
2255 return -1;
2258 #endif /* No ACLs. */