this now works as a add|delete share command :-)
[Samba.git] / source / lib / sysacls.c
blobd1b6e58b409c52fcde0a57f214701681b871d0a1
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, 1, 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 =
696 tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
698 } else {
699 def_acl = acl_d;
700 acc_acl =
701 tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
704 if (tmp_acl == NULL) {
705 return -1;
709 * allocate a temporary buffer for the complete ACL
711 acl_count = acc_acl->count + def_acl->count;
712 acl_p =
713 acl_buf = malloc(acl_count * sizeof(acl_buf[0]));
715 if (acl_buf == NULL) {
716 sys_acl_free_acl(tmp_acl);
717 errno = ENOMEM;
718 return -1;
722 * copy the access control and default entries into the buffer
724 memcpy(&acl_buf[0], &acc_acl->acl[0],
725 acc_acl->count * sizeof(acl_buf[0]));
727 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
728 def_acl->count * sizeof(acl_buf[0]));
731 * set the ACL_DEFAULT flag on the default entries
733 for (i = acc_acl->count; i < acl_count; i++) {
734 acl_buf[i].a_type |= ACL_DEFAULT;
737 sys_acl_free_acl(tmp_acl);
739 } else if (type != SMB_ACL_TYPE_ACCESS) {
740 errno = EINVAL;
741 return -1;
744 if (aclsort(acl_count, 1, acl_p) != 0) {
745 errno = EINVAL;
746 ret = -1;
747 } else {
748 ret = acl(name, SETACL, acl_count, acl_p);
751 if (acl_buf) {
752 free(acl_buf);
755 return ret;
758 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
760 if (aclsort(acl_d->count, 1, acl_d->acl) != 0) {
761 errno = EINVAL;
762 return -1;
765 return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
768 int sys_acl_free_text(char *text)
770 free(text);
771 return 0;
774 int sys_acl_free_acl(SMB_ACL_T acl_d)
776 free(acl_d);
777 return 0;
780 int sys_acl_free_qualifier(void *qual)
782 return 0;
785 #elif defined(HAVE_IRIX_ACLS)
787 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
789 if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
790 errno = EINVAL;
791 return -1;
794 if (entry_p == NULL) {
795 errno = EINVAL;
796 return -1;
799 if (entry_id == SMB_ACL_FIRST_ENTRY) {
800 acl_d->next = 0;
803 if (acl_d->next < 0) {
804 errno = EINVAL;
805 return -1;
808 if (acl_d->next >= acl_d->aclp->acl_cnt) {
809 return 0;
812 *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
814 return 1;
817 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
819 *type_p = entry_d->ae_tag;
821 return 0;
824 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
826 *permset_p = entry_d;
828 return 0;
831 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
833 if (entry_d->ae_tag != SMB_ACL_USER
834 && entry_d->ae_tag != SMB_ACL_GROUP) {
835 errno = EINVAL;
836 return NULL;
839 return &entry_d->ae_id;
842 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
844 SMB_ACL_T a;
846 if ((a = malloc(sizeof(*a))) == NULL) {
847 errno = ENOMEM;
848 return NULL;
850 if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
851 free(a);
852 return NULL;
854 a->next = -1;
855 a->freeaclp = True;
856 return a;
859 SMB_ACL_T sys_acl_get_fd(int fd)
861 SMB_ACL_T a;
863 if ((a = malloc(sizeof(*a))) == NULL) {
864 errno = ENOMEM;
865 return NULL;
867 if ((a->aclp = acl_get_fd(fd)) == NULL) {
868 free(a);
869 return NULL;
871 a->next = -1;
872 a->freeaclp = True;
873 return a;
876 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
878 permset_d->ae_perm = 0;
880 return 0;
883 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
885 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
886 && perm != SMB_ACL_EXECUTE) {
887 errno = EINVAL;
888 return -1;
891 if (permset_d == NULL) {
892 errno = EINVAL;
893 return -1;
896 permset_d->ae_perm |= perm;
898 return 0;
901 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
903 return permset_d->ae_perm & perm;
906 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
908 return acl_to_text(acl_d->aclp, len_p);
911 SMB_ACL_T sys_acl_init(int count)
913 SMB_ACL_T a;
915 if (count < 0) {
916 errno = EINVAL;
917 return NULL;
920 if ((a = malloc(sizeof(*a) + sizeof(struct acl))) == NULL) {
921 errno = ENOMEM;
922 return NULL;
925 a->next = -1;
926 a->freeaclp = False;
927 a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
928 a->aclp->acl_cnt = 0;
930 return a;
934 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
936 SMB_ACL_T acl_d;
937 SMB_ACL_ENTRY_T entry_d;
939 if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
940 errno = EINVAL;
941 return -1;
944 if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
945 errno = ENOSPC;
946 return -1;
949 entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
950 entry_d->ae_tag = 0;
951 entry_d->ae_id = 0;
952 entry_d->ae_perm = 0;
953 *entry_p = entry_d;
955 return 0;
958 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
960 switch (tag_type) {
961 case SMB_ACL_USER:
962 case SMB_ACL_USER_OBJ:
963 case SMB_ACL_GROUP:
964 case SMB_ACL_GROUP_OBJ:
965 case SMB_ACL_OTHER:
966 case SMB_ACL_MASK:
967 entry_d->ae_tag = tag_type;
968 break;
969 default:
970 errno = EINVAL;
971 return -1;
974 return 0;
977 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
979 if (entry_d->ae_tag != SMB_ACL_GROUP
980 && entry_d->ae_tag != SMB_ACL_USER) {
981 errno = EINVAL;
982 return -1;
985 entry_d->ae_id = *((id_t *)qual_p);
987 return 0;
990 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
992 if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
993 return EINVAL;
996 entry_d->ae_perm = permset_d->ae_perm;
998 return 0;
1001 int sys_acl_valid(SMB_ACL_T acl_d)
1003 return acl_valid(acl_d->aclp);
1006 int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1008 return acl_set_file(name, type, acl_d->aclp);
1011 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1013 return acl_set_fd(fd, acl_d->aclp);
1016 int sys_acl_free_text(char *text)
1018 return acl_free(text);
1021 int sys_acl_free_acl(SMB_ACL_T acl_d)
1023 if (acl_d->freeaclp) {
1024 acl_free(acl_d->aclp);
1026 acl_free(acl_d);
1027 return 0;
1030 int sys_acl_free_qualifier(void *qual)
1032 return 0;
1035 #elif defined(HAVE_XFS_ACLS)
1036 /* For Linux SGI/XFS Filesystems
1037 * contributed by J Trostel, Connex
1038 * */
1040 /* based on the implementation for Solaris by Toomas Soome.. which is
1041 * based on the implementation by Micheal Davidson for Unixware...
1043 * Linux XFS is a 'work-in-progress'
1044 * This interface may change...
1045 * You've been warned ;-> */
1047 /* First, do the identity mapping */
1049 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1051 if( acl_get_entry( the_acl, entry_id, entry_p) >= 0) {
1052 return 1;
1054 else {
1055 return -1;
1059 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1061 return acl_get_file( path_p, type);
1064 SMB_ACL_T sys_acl_get_fd(int fd)
1066 return acl_get_fd(fd);
1069 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
1071 return acl_to_text( the_acl, plen);
1074 int sys_acl_valid( SMB_ACL_T theacl )
1076 return acl_valid(theacl);
1079 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1081 return acl_set_file(name, acltype, theacl);
1084 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
1086 return acl_set_fd(fd, theacl);
1089 /* Now the functions I need to define for XFS */
1091 int sys_acl_create_entry( SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1093 acl_t acl, newacl;
1094 acl_entry_t ace;
1095 int cnt;
1097 acl = *acl_p;
1098 ace = *entry_p;
1100 if((*acl_p == NULL) || (ace == NULL)){
1101 errno = EINVAL;
1102 return -1;
1105 cnt = acl->acl_cnt;
1106 if( (cnt + 1) > ACL_MAX_ENTRIES ){
1107 errno = ENOSPC;
1108 return -1;
1111 newacl = (acl_t)malloc(sizeof(struct acl));
1112 if(newacl == NULL){
1113 errno = ENOMEM;
1114 return -1;
1117 *newacl = *acl;
1118 newacl->acl_entry[cnt] = *ace;
1119 newacl->acl_cnt = cnt + 1;
1121 acl_free(*acl_p);
1122 *acl_p = newacl;
1123 *entry_p = &newacl->acl_entry[cnt];
1124 return 0;
1128 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1130 *tag_type_p = entry_d->ae_tag;
1131 return 0;
1134 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1136 *permset_p = &entry_d->ae_perm;
1137 return 0;
1140 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1142 if (entry_d->ae_tag != SMB_ACL_USER
1143 && entry_d->ae_tag != SMB_ACL_GROUP) {
1144 errno = EINVAL;
1145 return NULL;
1147 return &entry_d->ae_id;
1150 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1152 *permset = 0;
1153 return 0;
1156 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1158 return (*permset & perm);
1161 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1164 /* TO DO: Add in ALL possible permissions here */
1165 /* TO DO: Include extended ones!! */
1167 if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE && perm != SMB_ACL_EXECUTE) {
1168 errno = EINVAL;
1169 return -1;
1172 if(permset == NULL) {
1173 errno = EINVAL;
1174 return -1;
1177 *permset |= perm;
1179 return 0;
1182 SMB_ACL_T sys_acl_init( int count)
1184 SMB_ACL_T a;
1185 if((count > ACL_MAX_ENTRIES) || (count < 0)) {
1186 errno = EINVAL;
1187 return NULL;
1189 else {
1190 a = (struct acl *)malloc(sizeof(struct acl)); /* where is this memory freed? */
1191 a->acl_cnt = 0;
1192 return a;
1196 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1199 switch (tag_type) {
1200 case SMB_ACL_USER:
1201 case SMB_ACL_USER_OBJ:
1202 case SMB_ACL_GROUP:
1203 case SMB_ACL_GROUP_OBJ:
1204 case SMB_ACL_OTHER:
1205 case SMB_ACL_MASK:
1206 entry_d->ae_tag = tag_type;
1207 break;
1208 default:
1209 errno = EINVAL;
1210 return -1;
1212 return 0;
1215 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry_d, void *qual_p)
1217 if(entry_d->ae_tag != SMB_ACL_GROUP &&
1218 entry_d->ae_tag != SMB_ACL_USER) {
1219 errno = EINVAL;
1220 return -1;
1223 entry_d->ae_id = *((uid_t *)qual_p);
1225 return 0;
1228 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1230 /* TO DO: expand to extended permissions eventually! */
1232 if(*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1233 return EINVAL;
1236 return 0;
1239 int sys_acl_free_text(char *text)
1241 return acl_free(text);
1244 int sys_acl_free_acl(SMB_ACL_T the_acl)
1246 return acl_free(the_acl);
1249 int sys_acl_free_qualifier(void *qual)
1251 return 0;
1254 #elif defined(HAVE_AIX_ACLS)
1256 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1258 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1260 struct acl_entry_link *link;
1261 struct new_acl_entry *entry;
1262 int keep_going;
1264 DEBUG(10,("This is the count: %d\n",theacl->count));
1266 /* Check if count was previously set to -1. *
1267 * If it was, that means we reached the end *
1268 * of the acl last time. */
1269 if(theacl->count == -1)
1270 return(0);
1272 link = theacl;
1273 /* To get to the next acl, traverse linked list until index *
1274 * of acl matches the count we are keeping. This count is *
1275 * incremented each time we return an acl entry. */
1277 for(keep_going = 0; keep_going < theacl->count; keep_going++)
1278 link = link->nextp;
1280 entry = *entry_p = link->entryp;
1282 DEBUG(10,("*entry_p is %d\n",entry_p));
1283 DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1285 /* Increment count */
1286 theacl->count++;
1287 if(link->nextp == NULL)
1288 theacl->count = -1;
1290 return(1);
1293 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1295 /* Initialize tag type */
1297 *tag_type_p = -1;
1298 DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1300 /* Depending on what type of entry we have, *
1301 * return tag type. */
1302 switch(entry_d->ace_id->id_type) {
1303 case ACEID_USER:
1304 *tag_type_p = SMB_ACL_USER;
1305 break;
1306 case ACEID_GROUP:
1307 *tag_type_p = SMB_ACL_GROUP;
1308 break;
1310 case SMB_ACL_USER_OBJ:
1311 case SMB_ACL_GROUP_OBJ:
1312 case SMB_ACL_OTHER:
1313 *tag_type_p = entry_d->ace_id->id_type;
1314 break;
1316 default:
1317 return(-1);
1320 return(0);
1323 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1325 DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
1326 *permset_p = &entry_d->ace_access;
1327 DEBUG(10,("**permset_p is %d\n",**permset_p));
1328 if(!(**permset_p & S_IXUSR) &&
1329 !(**permset_p & S_IWUSR) &&
1330 !(**permset_p & S_IRUSR) &&
1331 (**permset_p != 0))
1332 return(-1);
1334 DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
1335 return(0);
1338 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1340 return(entry_d->ace_id->id_data);
1343 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1345 struct acl *file_acl = (struct acl *)NULL;
1346 struct acl_entry *acl_entry;
1347 struct new_acl_entry *new_acl_entry;
1348 struct ace_id *idp;
1349 struct acl_entry_link *acl_entry_link;
1350 struct acl_entry_link *acl_entry_link_head;
1351 int i;
1352 int rc = 0;
1353 uid_t user_id;
1355 /* Get the acl using statacl */
1357 DEBUG(10,("Entering sys_acl_get_file\n"));
1358 DEBUG(10,("path_p is %s\n",path_p));
1360 file_acl = (struct acl *)malloc(BUFSIZ);
1362 if(file_acl == NULL) {
1363 errno=ENOMEM;
1364 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1365 return(NULL);
1368 memset(file_acl,0,BUFSIZ);
1370 rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1371 if(rc == -1) {
1372 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1373 free(file_acl);
1374 return(NULL);
1377 DEBUG(10,("Got facl and returned it\n"));
1379 /* Point to the first acl entry in the acl */
1380 acl_entry = file_acl->acl_ext;
1382 /* Begin setting up the head of the linked list *
1383 * that will be used for the storing the acl *
1384 * in a way that is useful for the posix_acls.c *
1385 * code. */
1387 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1388 if(acl_entry_link_head == NULL)
1389 return(NULL);
1391 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1392 if(acl_entry_link->entryp == NULL) {
1393 free(file_acl);
1394 errno = ENOMEM;
1395 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1396 return(NULL);
1399 DEBUG(10,("acl_entry is %d\n",acl_entry));
1400 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1402 /* Check if the extended acl bit is on. *
1403 * If it isn't, do not show the *
1404 * contents of the acl since AIX intends *
1405 * the extended info to remain unused */
1407 if(file_acl->acl_mode & S_IXACL){
1408 /* while we are not pointing to the very end */
1409 while(acl_entry < acl_last(file_acl)) {
1410 /* before we malloc anything, make sure this is */
1411 /* a valid acl entry and one that we want to map */
1412 idp = id_nxt(acl_entry->ace_id);
1413 if((acl_entry->ace_type == ACC_SPECIFY ||
1414 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1415 acl_entry = acl_nxt(acl_entry);
1416 continue;
1419 idp = acl_entry->ace_id;
1421 /* Check if this is the first entry in the linked list. *
1422 * The first entry needs to keep prevp pointing to NULL *
1423 * and already has entryp allocated. */
1425 if(acl_entry_link_head->count != 0) {
1426 acl_entry_link->nextp = (struct acl_entry_link *)
1427 malloc(sizeof(struct acl_entry_link));
1429 if(acl_entry_link->nextp == NULL) {
1430 free(file_acl);
1431 errno = ENOMEM;
1432 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1433 return(NULL);
1436 acl_entry_link->nextp->prevp = acl_entry_link;
1437 acl_entry_link = acl_entry_link->nextp;
1438 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1439 if(acl_entry_link->entryp == NULL) {
1440 free(file_acl);
1441 errno = ENOMEM;
1442 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1443 return(NULL);
1445 acl_entry_link->nextp = NULL;
1448 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1450 /* Don't really need this since all types are going *
1451 * to be specified but, it's better than leaving it 0 */
1453 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1455 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1457 memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
1459 /* The access in the acl entries must be left shifted by *
1460 * three bites, because they will ultimately be compared *
1461 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
1463 switch(acl_entry->ace_type){
1464 case ACC_PERMIT:
1465 case ACC_SPECIFY:
1466 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1467 acl_entry_link->entryp->ace_access <<= 6;
1468 acl_entry_link_head->count++;
1469 break;
1470 case ACC_DENY:
1471 /* Since there is no way to return a DENY acl entry *
1472 * change to PERMIT and then shift. */
1473 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1474 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1475 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1476 acl_entry_link->entryp->ace_access <<= 6;
1477 acl_entry_link_head->count++;
1478 break;
1479 default:
1480 return(0);
1483 DEBUG(10,("acl_entry = %d\n",acl_entry));
1484 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1486 acl_entry = acl_nxt(acl_entry);
1488 } /* end of if enabled */
1490 /* Since owner, group, other acl entries are not *
1491 * part of the acl entries in an acl, they must *
1492 * be dummied up to become part of the list. */
1494 for( i = 1; i < 4; i++) {
1495 DEBUG(10,("i is %d\n",i));
1496 if(acl_entry_link_head->count != 0) {
1497 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1498 if(acl_entry_link->nextp == NULL) {
1499 free(file_acl);
1500 errno = ENOMEM;
1501 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1502 return(NULL);
1505 acl_entry_link->nextp->prevp = acl_entry_link;
1506 acl_entry_link = acl_entry_link->nextp;
1507 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1508 if(acl_entry_link->entryp == NULL) {
1509 free(file_acl);
1510 errno = ENOMEM;
1511 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1512 return(NULL);
1516 acl_entry_link->nextp = NULL;
1518 new_acl_entry = acl_entry_link->entryp;
1519 idp = new_acl_entry->ace_id;
1521 new_acl_entry->ace_len = sizeof(struct acl_entry);
1522 new_acl_entry->ace_type = ACC_PERMIT;
1523 idp->id_len = sizeof(struct ace_id);
1524 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1525 memset(idp->id_data,0,sizeof(uid_t));
1527 switch(i) {
1528 case 2:
1529 new_acl_entry->ace_access = file_acl->g_access << 6;
1530 idp->id_type = SMB_ACL_GROUP_OBJ;
1531 break;
1533 case 3:
1534 new_acl_entry->ace_access = file_acl->o_access << 6;
1535 idp->id_type = SMB_ACL_OTHER;
1536 break;
1538 case 1:
1539 new_acl_entry->ace_access = file_acl->u_access << 6;
1540 idp->id_type = SMB_ACL_USER_OBJ;
1541 break;
1543 default:
1544 return(NULL);
1548 acl_entry_link_head->count++;
1549 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1552 acl_entry_link_head->count = 0;
1553 free(file_acl);
1555 return(acl_entry_link_head);
1558 SMB_ACL_T sys_acl_get_fd(int fd)
1560 struct acl *file_acl = (struct acl *)NULL;
1561 struct acl_entry *acl_entry;
1562 struct new_acl_entry *new_acl_entry;
1563 struct ace_id *idp;
1564 struct acl_entry_link *acl_entry_link;
1565 struct acl_entry_link *acl_entry_link_head;
1566 int i;
1567 int rc = 0;
1568 uid_t user_id;
1570 /* Get the acl using fstatacl */
1572 DEBUG(10,("Entering sys_acl_get_fd\n"));
1573 DEBUG(10,("fd is %d\n",fd));
1574 file_acl = (struct acl *)malloc(BUFSIZ);
1576 if(file_acl == NULL) {
1577 errno=ENOMEM;
1578 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1579 return(NULL);
1582 memset(file_acl,0,BUFSIZ);
1584 rc = fstatacl(fd,0,file_acl,BUFSIZ);
1585 if(rc == -1) {
1586 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
1587 free(file_acl);
1588 return(NULL);
1591 DEBUG(10,("Got facl and returned it\n"));
1593 /* Point to the first acl entry in the acl */
1595 acl_entry = file_acl->acl_ext;
1596 /* Begin setting up the head of the linked list *
1597 * that will be used for the storing the acl *
1598 * in a way that is useful for the posix_acls.c *
1599 * code. */
1601 acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1602 if(acl_entry_link_head == NULL){
1603 free(file_acl);
1604 return(NULL);
1607 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1609 if(acl_entry_link->entryp == NULL) {
1610 errno = ENOMEM;
1611 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1612 free(file_acl);
1613 return(NULL);
1616 DEBUG(10,("acl_entry is %d\n",acl_entry));
1617 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1619 /* Check if the extended acl bit is on. *
1620 * If it isn't, do not show the *
1621 * contents of the acl since AIX intends *
1622 * the extended info to remain unused */
1624 if(file_acl->acl_mode & S_IXACL){
1625 /* while we are not pointing to the very end */
1626 while(acl_entry < acl_last(file_acl)) {
1627 /* before we malloc anything, make sure this is */
1628 /* a valid acl entry and one that we want to map */
1630 idp = id_nxt(acl_entry->ace_id);
1631 if((acl_entry->ace_type == ACC_SPECIFY ||
1632 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1633 acl_entry = acl_nxt(acl_entry);
1634 continue;
1637 idp = acl_entry->ace_id;
1639 /* Check if this is the first entry in the linked list. *
1640 * The first entry needs to keep prevp pointing to NULL *
1641 * and already has entryp allocated. */
1643 if(acl_entry_link_head->count != 0) {
1644 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1645 if(acl_entry_link->nextp == NULL) {
1646 errno = ENOMEM;
1647 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1648 free(file_acl);
1649 return(NULL);
1651 acl_entry_link->nextp->prevp = acl_entry_link;
1652 acl_entry_link = acl_entry_link->nextp;
1653 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1654 if(acl_entry_link->entryp == NULL) {
1655 errno = ENOMEM;
1656 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1657 free(file_acl);
1658 return(NULL);
1661 acl_entry_link->nextp = NULL;
1664 acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1666 /* Don't really need this since all types are going *
1667 * to be specified but, it's better than leaving it 0 */
1669 acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1670 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1672 memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
1674 /* The access in the acl entries must be left shifted by *
1675 * three bites, because they will ultimately be compared *
1676 * to S_IRUSR, S_IWUSR, and S_IXUSR. */
1678 switch(acl_entry->ace_type){
1679 case ACC_PERMIT:
1680 case ACC_SPECIFY:
1681 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1682 acl_entry_link->entryp->ace_access <<= 6;
1683 acl_entry_link_head->count++;
1684 break;
1685 case ACC_DENY:
1686 /* Since there is no way to return a DENY acl entry *
1687 * change to PERMIT and then shift. */
1688 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1689 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1690 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1691 acl_entry_link->entryp->ace_access <<= 6;
1692 acl_entry_link_head->count++;
1693 break;
1694 default:
1695 return(0);
1698 DEBUG(10,("acl_entry = %d\n",acl_entry));
1699 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1701 acl_entry = acl_nxt(acl_entry);
1703 } /* end of if enabled */
1705 /* Since owner, group, other acl entries are not *
1706 * part of the acl entries in an acl, they must *
1707 * be dummied up to become part of the list. */
1709 for( i = 1; i < 4; i++) {
1710 DEBUG(10,("i is %d\n",i));
1711 if(acl_entry_link_head->count != 0){
1712 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1713 if(acl_entry_link->nextp == NULL) {
1714 errno = ENOMEM;
1715 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1716 free(file_acl);
1717 return(NULL);
1720 acl_entry_link->nextp->prevp = acl_entry_link;
1721 acl_entry_link = acl_entry_link->nextp;
1722 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1724 if(acl_entry_link->entryp == NULL) {
1725 free(file_acl);
1726 errno = ENOMEM;
1727 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1728 return(NULL);
1732 acl_entry_link->nextp = NULL;
1734 new_acl_entry = acl_entry_link->entryp;
1735 idp = new_acl_entry->ace_id;
1737 new_acl_entry->ace_len = sizeof(struct acl_entry);
1738 new_acl_entry->ace_type = ACC_PERMIT;
1739 idp->id_len = sizeof(struct ace_id);
1740 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1741 memset(idp->id_data,0,sizeof(uid_t));
1743 switch(i) {
1744 case 2:
1745 new_acl_entry->ace_access = file_acl->g_access << 6;
1746 idp->id_type = SMB_ACL_GROUP_OBJ;
1747 break;
1749 case 3:
1750 new_acl_entry->ace_access = file_acl->o_access << 6;
1751 idp->id_type = SMB_ACL_OTHER;
1752 break;
1754 case 1:
1755 new_acl_entry->ace_access = file_acl->u_access << 6;
1756 idp->id_type = SMB_ACL_USER_OBJ;
1757 break;
1759 default:
1760 return(NULL);
1763 acl_entry_link_head->count++;
1764 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1767 acl_entry_link_head->count = 0;
1768 free(file_acl);
1770 return(acl_entry_link_head);
1773 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1775 *permset = *permset & ~0777;
1776 return(0);
1779 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1781 if((perm != 0) &&
1782 (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
1783 return(-1);
1785 *permset |= perm;
1786 DEBUG(10,("This is the permset now: %d\n",*permset));
1787 return(0);
1790 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
1792 return(NULL);
1795 SMB_ACL_T sys_acl_init( int count)
1797 struct acl_entry_link *theacl = NULL;
1799 DEBUG(10,("Entering sys_acl_init\n"));
1801 theacl = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1802 if(theacl == NULL) {
1803 errno = ENOMEM;
1804 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
1805 return(NULL);
1808 theacl->count = 0;
1809 theacl->nextp = NULL;
1810 theacl->prevp = NULL;
1811 theacl->entryp = NULL;
1812 DEBUG(10,("Exiting sys_acl_init\n"));
1813 return(theacl);
1816 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1818 struct acl_entry_link *theacl;
1819 struct acl_entry_link *acl_entryp;
1820 struct acl_entry_link *temp_entry;
1821 int counting;
1823 DEBUG(10,("Entering the sys_acl_create_entry\n"));
1825 theacl = acl_entryp = *pacl;
1827 /* Get to the end of the acl before adding entry */
1829 for(counting=0; counting < theacl->count; counting++){
1830 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
1831 temp_entry = acl_entryp;
1832 acl_entryp = acl_entryp->nextp;
1835 if(theacl->count != 0){
1836 temp_entry->nextp = acl_entryp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1837 if(acl_entryp == NULL) {
1838 errno = ENOMEM;
1839 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
1840 return(-1);
1843 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
1844 acl_entryp->prevp = temp_entry;
1845 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
1848 *pentry = acl_entryp->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1849 if(*pentry == NULL) {
1850 errno = ENOMEM;
1851 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
1852 return(-1);
1855 memset(*pentry,0,sizeof(struct new_acl_entry));
1856 acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
1857 acl_entryp->entryp->ace_type = ACC_PERMIT;
1858 acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
1859 acl_entryp->nextp = NULL;
1860 theacl->count++;
1861 DEBUG(10,("Exiting sys_acl_create_entry\n"));
1862 return(0);
1865 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1867 DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
1868 entry->ace_id->id_type = tagtype;
1869 DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
1870 DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
1873 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
1875 DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
1876 memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
1877 DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
1878 return(0);
1881 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1883 DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
1884 if(!(*permset & S_IXUSR) &&
1885 !(*permset & S_IWUSR) &&
1886 !(*permset & S_IRUSR) &&
1887 (*permset != 0))
1888 return(-1);
1890 entry->ace_access = *permset;
1891 DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
1892 DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
1893 return(0);
1896 int sys_acl_valid( SMB_ACL_T theacl )
1898 int user_obj = 0;
1899 int group_obj = 0;
1900 int other_obj = 0;
1901 struct acl_entry_link *acl_entry;
1903 for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
1904 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
1905 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
1906 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
1909 DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
1911 if(user_obj != 1 || group_obj != 1 || other_obj != 1)
1912 return(-1);
1914 return(0);
1917 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1919 struct acl_entry_link *acl_entry_link = NULL;
1920 struct acl *file_acl = NULL;
1921 struct acl *file_acl_temp = NULL;
1922 struct acl_entry *acl_entry = NULL;
1923 struct ace_id *ace_id = NULL;
1924 uint id_type;
1925 uint ace_access;
1926 uint user_id;
1927 uint acl_length;
1928 uint rc;
1930 DEBUG(10,("Entering sys_acl_set_file\n"));
1931 DEBUG(10,("File name is %s\n",name));
1933 /* AIX has no default ACL */
1934 if(acltype == SMB_ACL_TYPE_DEFAULT)
1935 return(0);
1937 acl_length = BUFSIZ;
1938 file_acl = (struct acl *)malloc(BUFSIZ);
1940 if(file_acl == NULL) {
1941 errno = ENOMEM;
1942 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
1943 return(-1);
1946 memset(file_acl,0,BUFSIZ);
1948 file_acl->acl_len = ACL_SIZ;
1949 file_acl->acl_mode = S_IXACL;
1951 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
1952 acl_entry_link->entryp->ace_access >>= 6;
1953 id_type = acl_entry_link->entryp->ace_id->id_type;
1955 switch(id_type) {
1956 case SMB_ACL_USER_OBJ:
1957 file_acl->u_access = acl_entry_link->entryp->ace_access;
1958 continue;
1959 case SMB_ACL_GROUP_OBJ:
1960 file_acl->g_access = acl_entry_link->entryp->ace_access;
1961 continue;
1962 case SMB_ACL_OTHER:
1963 file_acl->o_access = acl_entry_link->entryp->ace_access;
1964 continue;
1965 case SMB_ACL_MASK:
1966 continue;
1969 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
1970 acl_length += sizeof(struct acl_entry);
1971 file_acl_temp = (struct acl *)malloc(acl_length);
1972 if(file_acl_temp == NULL) {
1973 free(file_acl);
1974 errno = ENOMEM;
1975 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
1976 return(-1);
1979 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
1980 free(file_acl);
1981 file_acl = file_acl_temp;
1984 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
1985 file_acl->acl_len += sizeof(struct acl_entry);
1986 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
1987 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
1989 /* In order to use this, we'll need to wait until we can get denies */
1990 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
1991 acl_entry->ace_type = ACC_SPECIFY; */
1993 acl_entry->ace_type = ACC_SPECIFY;
1995 ace_id = acl_entry->ace_id;
1997 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
1998 DEBUG(10,("The id type is %d\n",ace_id->id_type));
1999 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2000 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2001 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2004 rc = chacl(name,file_acl,file_acl->acl_len);
2005 DEBUG(10,("errno is %d\n",errno));
2006 DEBUG(10,("return code is %d\n",rc));
2007 free(file_acl);
2008 DEBUG(10,("Exiting the sys_acl_set_file\n"));
2009 return(rc);
2012 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2014 struct acl_entry_link *acl_entry_link = NULL;
2015 struct acl *file_acl = NULL;
2016 struct acl *file_acl_temp = NULL;
2017 struct acl_entry *acl_entry = NULL;
2018 struct ace_id *ace_id = NULL;
2019 uint id_type;
2020 uint user_id;
2021 uint acl_length;
2022 uint rc;
2024 DEBUG(10,("Entering sys_acl_set_fd\n"));
2025 acl_length = BUFSIZ;
2026 file_acl = (struct acl *)malloc(BUFSIZ);
2028 if(file_acl == NULL) {
2029 errno = ENOMEM;
2030 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2031 return(-1);
2034 memset(file_acl,0,BUFSIZ);
2036 file_acl->acl_len = ACL_SIZ;
2037 file_acl->acl_mode = S_IXACL;
2039 for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2040 acl_entry_link->entryp->ace_access >>= 6;
2041 id_type = acl_entry_link->entryp->ace_id->id_type;
2042 DEBUG(10,("The id_type is %d\n",id_type));
2044 switch(id_type) {
2045 case SMB_ACL_USER_OBJ:
2046 file_acl->u_access = acl_entry_link->entryp->ace_access;
2047 continue;
2048 case SMB_ACL_GROUP_OBJ:
2049 file_acl->g_access = acl_entry_link->entryp->ace_access;
2050 continue;
2051 case SMB_ACL_OTHER:
2052 file_acl->o_access = acl_entry_link->entryp->ace_access;
2053 continue;
2054 case SMB_ACL_MASK:
2055 continue;
2058 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2059 acl_length += sizeof(struct acl_entry);
2060 file_acl_temp = (struct acl *)malloc(acl_length);
2061 if(file_acl_temp == NULL) {
2062 free(file_acl);
2063 errno = ENOMEM;
2064 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2065 return(-1);
2068 memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2069 free(file_acl);
2070 file_acl = file_acl_temp;
2073 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2074 file_acl->acl_len += sizeof(struct acl_entry);
2075 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2076 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2078 /* In order to use this, we'll need to wait until we can get denies */
2079 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2080 acl_entry->ace_type = ACC_SPECIFY; */
2082 acl_entry->ace_type = ACC_SPECIFY;
2084 ace_id = acl_entry->ace_id;
2086 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2087 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2088 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2089 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2090 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2093 rc = fchacl(fd,file_acl,file_acl->acl_len);
2094 DEBUG(10,("errno is %d\n",errno));
2095 DEBUG(10,("return code is %d\n",rc));
2096 free(file_acl);
2097 DEBUG(10,("Exiting sys_acl_set_fd\n"));
2098 return(rc);
2101 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2103 return(*permset & perm);
2106 int sys_acl_free_text(char *text)
2108 return(0);
2111 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2113 struct acl_entry_link *acl_entry_link;
2115 for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2116 free(acl_entry_link->prevp->entryp);
2117 free(acl_entry_link->prevp);
2120 free(acl_entry_link->prevp->entryp);
2121 free(acl_entry_link->prevp);
2122 free(acl_entry_link->entryp);
2123 free(acl_entry_link);
2125 return(0);
2128 int sys_acl_free_qualifier(void *qual)
2130 return(0);
2133 #else /* No ACLs. */
2135 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2137 errno = ENOSYS;
2138 return -1;
2141 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2143 errno = ENOSYS;
2144 return -1;
2147 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2149 errno = ENOSYS;
2150 return -1;
2153 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2155 errno = ENOSYS;
2156 return NULL;
2159 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2161 errno = ENOSYS;
2162 return (SMB_ACL_T)NULL;
2165 SMB_ACL_T sys_acl_get_fd(int fd)
2167 errno = ENOSYS;
2168 return (SMB_ACL_T)NULL;
2171 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2173 errno = ENOSYS;
2174 return -1;
2177 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2179 errno = ENOSYS;
2180 return -1;
2183 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2185 errno = ENOSYS;
2186 return (permset & perm) ? 1 : 0;
2189 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
2191 errno = ENOSYS;
2192 return NULL;
2195 int sys_acl_free_text(char *text)
2197 errno = ENOSYS;
2198 return -1;
2201 SMB_ACL_T sys_acl_init( int count)
2203 errno = ENOSYS;
2204 return NULL;
2207 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2209 errno = ENOSYS;
2210 return -1;
2213 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2215 errno = ENOSYS;
2216 return -1;
2219 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2221 errno = ENOSYS;
2222 return -1;
2225 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2227 errno = ENOSYS;
2228 return -1;
2231 int sys_acl_valid( SMB_ACL_T theacl )
2233 errno = ENOSYS;
2234 return -1;
2237 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2239 errno = ENOSYS;
2240 return -1;
2243 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2245 errno = ENOSYS;
2246 return -1;
2249 int sys_acl_free_acl(SMB_ACL_T the_acl)
2251 errno = ENOSYS;
2252 return -1;
2255 int sys_acl_free_qualifier(void *qual)
2257 errno = ENOSYS;
2258 return -1;
2261 #endif /* No ACLs. */