Fixed typo in Solaris and UnixWare ACLs.
[abartlet/samba.git/.git] / source / lib / sysacls.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.2.
4    Samba system utilities for ACL support.
5    Copyright (C) Jeremy Allison 2000.
6    
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.
11    
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.
16    
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.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26 /*
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.
30
31  The interfaces that each ACL implementation must support are as follows :
32
33  int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
34  int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
35  int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p
36  void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
37  SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
38  SMB_ACL_T sys_acl_get_fd(int fd)
39  int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset);
40  int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
41  char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
42  SMB_ACL_T sys_acl_init( int count)
43  int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
44  int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
45  int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
46  int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
47  int sys_acl_valid( SMB_ACL_T theacl )
48  int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
49  int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
50  int sys_acl_delete_def_file(const char *path)
51
52  This next one is not POSIX complient - but we *have* to have it !
53  More POSIX braindamage.
54
55  int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
56
57  The generic POSIX free is the following call. We split this into
58  several different free functions as we may need to add tag info
59  to structures when emulating the POSIX interface.
60
61  int sys_acl_free( void *obj_p)
62
63  The calls we actually use are :
64
65  int sys_acl_free_text(char *text) - free acl_to_text
66  int sys_acl_free_acl(SMB_ACL_T posix_acl)
67  int sys_acl_free_qualifier(SMB_ACL_T posix_acl)
68
69 */
70
71 #if defined(HAVE_POSIX_ACLS)
72
73 /* Identity mapping - easy. */
74
75 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
76 {
77         return acl_get_entry( the_acl, entry_id, entry_p);
78 }
79
80 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
81 {
82         return acl_get_tag_type( entry_d, tag_type_p);
83 }
84
85 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
86 {
87         return acl_get_permset( entry_d, permset_p);
88 }
89
90 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
91 {
92         return acl_get_qualifier( entry_d);
93 }
94
95 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
96 {
97         return acl_get_file( path_p, type);
98 }
99
100 SMB_ACL_T sys_acl_get_fd(int fd)
101 {
102         return acl_get_fd(fd);
103 }
104
105 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
106 {
107         return acl_clear_perms(permset);
108 }
109
110 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
111 {
112         return acl_add_perm(permset, perm);
113 }
114
115 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
116 {
117 #if defined(HAVE_ACL_GET_PERM_NP)
118         /*
119          * Required for TrustedBSD-based ACL implementations where
120          * non-POSIX.1e functions are denoted by a _np (non-portable)
121          * suffix.
122          */
123         return acl_get_perm_np(permset, perm);
124 #else
125         return acl_get_perm(permset, perm);
126 #endif
127 }
128
129 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
130 {
131         return acl_to_text( the_acl, plen);
132 }
133
134 SMB_ACL_T sys_acl_init( int count)
135 {
136         return acl_init(count);
137 }
138
139 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
140 {
141         return acl_create_entry(pacl, pentry);
142 }
143
144 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
145 {
146         return acl_set_tag_type(entry, tagtype);
147 }
148
149 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
150 {
151         return acl_set_qualifier(entry, qual);
152 }
153
154 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
155 {
156         return acl_set_permset(entry, permset);
157 }
158
159 int sys_acl_valid( SMB_ACL_T theacl )
160 {
161         return acl_valid(theacl);
162 }
163
164 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
165 {
166         return acl_set_file(name, acltype, theacl);
167 }
168
169 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
170 {
171         return acl_set_fd(fd, theacl);
172 }
173
174 int sys_acl_delete_def_file(const char *name)
175 {
176         return acl_delete_def_file(name);
177 }
178
179 int sys_acl_free_text(char *text)
180 {
181         return acl_free(text);
182 }
183
184 int sys_acl_free_acl(SMB_ACL_T the_acl) 
185 {
186         return acl_free(the_acl);
187 }
188
189 int sys_acl_free_qualifier(void *qual) 
190 {
191         return acl_free(qual);
192 }
193
194 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
195
196 /*
197  * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
198  * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
199  */
200
201 /*
202  * Note that while this code implements sufficient functionality
203  * to support the sys_acl_* interfaces it does not provide all
204  * of the semantics of the POSIX ACL interfaces.
205  *
206  * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
207  * from a call to sys_acl_get_entry() should not be assumed to be
208  * valid after calling any of the following functions, which may
209  * reorder the entries in the ACL.
210  *
211  *      sys_acl_valid()
212  *      sys_acl_set_file()
213  *      sys_acl_set_fd()
214  */
215
216 /*
217  * The only difference between Solaris and UnixWare / OpenUNIX is
218  * that the #defines for the ACL operations have different names
219  */
220 #if defined(HAVE_UNIXWARE_ACLS)
221
222 #define SETACL          ACL_SET
223 #define GETACL          ACL_GET
224 #define GETACLCNT       ACL_CNT
225
226 #endif
227
228
229 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
230 {
231         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
232                 errno = EINVAL;
233                 return -1;
234         }
235
236         if (entry_p == NULL) {
237                 errno = EINVAL;
238                 return -1;
239         }
240
241         if (entry_id == SMB_ACL_FIRST_ENTRY) {
242                 acl_d->next = 0;
243         }
244
245         if (acl_d->next < 0) {
246                 errno = EINVAL;
247                 return -1;
248         }
249
250         if (acl_d->next >= acl_d->count) {
251                 return 0;
252         }
253
254         *entry_p = &acl_d->acl[acl_d->next++];
255
256         return 1;
257 }
258
259 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
260 {
261         *type_p = entry_d->a_type;
262
263         return 0;
264 }
265
266 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
267 {
268         *permset_p = &entry_d->a_perm;
269
270         return 0;
271 }
272
273 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
274 {
275         if (entry_d->a_type != SMB_ACL_USER
276             && entry_d->a_type != SMB_ACL_GROUP) {
277                 errno = EINVAL;
278                 return NULL;
279         }
280
281         return &entry_d->a_id;
282 }
283
284 /*
285  * There is no way of knowing what size the ACL returned by
286  * GETACL will be unless you first call GETACLCNT which means
287  * making an additional system call.
288  *
289  * In the hope of avoiding the cost of the additional system
290  * call in most cases, we initially allocate enough space for
291  * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
292  * be too small then we use GETACLCNT to find out the actual
293  * size, reallocate the ACL buffer, and then call GETACL again.
294  */
295
296 #define INITIAL_ACL_SIZE        16
297
298 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
299 {
300         SMB_ACL_T       acl_d;
301         int             count;          /* # of ACL entries allocated   */
302         int             naccess;        /* # of access ACL entries      */
303         int             ndefault;       /* # of default ACL entries     */
304
305         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
306                 errno = EINVAL;
307                 return NULL;
308         }
309
310         count = INITIAL_ACL_SIZE;
311         if ((acl_d = sys_acl_init(count)) == NULL) {
312                 return NULL;
313         }
314
315         /*
316          * If there isn't enough space for the ACL entries we use
317          * GETACLCNT to determine the actual number of ACL entries
318          * reallocate and try again. This is in a loop because it
319          * is possible that someone else could modify the ACL and
320          * increase the number of entries between the call to
321          * GETACLCNT and the call to GETACL.
322          */
323         while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
324             && errno == ENOSPC) {
325
326                 sys_acl_free_acl(acl_d);
327
328                 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
329                         return NULL;
330                 }
331
332                 if ((acl_d = sys_acl_init(count)) == NULL) {
333                         return NULL;
334                 }
335         }
336
337         if (count < 0) {
338                 sys_acl_free_acl(acl_d);
339                 return NULL;
340         }
341
342         /*
343          * calculate the number of access and default ACL entries
344          *
345          * Note: we assume that the acl() system call returned a
346          * well formed ACL which is sorted so that all of the
347          * access ACL entries preceed any default ACL entries
348          */
349         for (naccess = 0; naccess < count; naccess++) {
350                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
351                         break;
352         }
353         ndefault = count - naccess;
354         
355         /*
356          * if the caller wants the default ACL we have to copy
357          * the entries down to the start of the acl[] buffer
358          * and mask out the ACL_DEFAULT flag from the type field
359          */
360         if (type == SMB_ACL_TYPE_DEFAULT) {
361                 int     i, j;
362
363                 for (i = 0, j = naccess; i < ndefault; i++, j++) {
364                         acl_d->acl[i] = acl_d->acl[j];
365                         acl_d->acl[i].a_type &= ~ACL_DEFAULT;
366                 }
367
368                 acl_d->count = ndefault;
369         } else {
370                 acl_d->count = naccess;
371         }
372
373         return acl_d;
374 }
375
376 SMB_ACL_T sys_acl_get_fd(int fd)
377 {
378         SMB_ACL_T       acl_d;
379         int             count;          /* # of ACL entries allocated   */
380         int             naccess;        /* # of access ACL entries      */
381
382         count = INITIAL_ACL_SIZE;
383         if ((acl_d = sys_acl_init(count)) == NULL) {
384                 return NULL;
385         }
386
387         while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
388             && errno == ENOSPC) {
389
390                 sys_acl_free_acl(acl_d);
391
392                 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
393                         return NULL;
394                 }
395
396                 if ((acl_d = sys_acl_init(count)) == NULL) {
397                         return NULL;
398                 }
399         }
400
401         if (count < 0) {
402                 sys_acl_free_acl(acl_d);
403                 return NULL;
404         }
405
406         /*
407          * calculate the number of access ACL entries
408          */
409         for (naccess = 0; naccess < count; naccess++) {
410                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
411                         break;
412         }
413         
414         acl_d->count = naccess;
415
416         return acl_d;
417 }
418
419 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
420 {
421         *permset_d = 0;
422
423         return 0;
424 }
425
426 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
427 {
428         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
429             && perm != SMB_ACL_EXECUTE) {
430                 errno = EINVAL;
431                 return -1;
432         }
433
434         if (permset_d == NULL) {
435                 errno = EINVAL;
436                 return -1;
437         }
438
439         *permset_d |= perm;
440
441         return 0;
442 }
443
444 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
445 {
446         return *permset_d & perm;
447 }
448
449 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
450 {
451         int     i;
452         int     len, maxlen;
453         char    *text;
454
455         /*
456          * use an initial estimate of 20 bytes per ACL entry
457          * when allocating memory for the text representation
458          * of the ACL
459          */
460         len     = 0;
461         maxlen  = 20 * acl_d->count;
462         if ((text = malloc(maxlen)) == NULL) {
463                 errno = ENOMEM;
464                 return NULL;
465         }
466
467         for (i = 0; i < acl_d->count; i++) {
468                 struct acl      *ap     = &acl_d->acl[i];
469                 struct passwd   *pw;
470                 struct group    *gr;
471                 char            tagbuf[12];
472                 char            idbuf[12];
473                 char            *tag;
474                 char            *id     = "";
475                 char            perms[4];
476                 int             nbytes;
477
478                 switch (ap->a_type) {
479                         /*
480                          * for debugging purposes it's probably more
481                          * useful to dump unknown tag types rather
482                          * than just returning an error
483                          */
484                         default:
485                                 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
486                                         ap->a_type);
487                                 tag = tagbuf;
488                                 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
489                                         (long)ap->a_id);
490                                 id = idbuf;
491                                 break;
492
493                         case SMB_ACL_USER:
494                                 if ((pw = sys_getpwuid(ap->a_id)) == NULL) {
495                                         slprintf(idbuf, sizeof(idbuf)-1, "%ld",
496                                                 (long)ap->a_id);
497                                         id = idbuf;
498                                 } else {
499                                         id = pw->pw_name;
500                                 }
501                         case SMB_ACL_USER_OBJ:
502                                 tag = "user";
503                                 break;
504
505                         case SMB_ACL_GROUP:
506                                 if ((gr = getgrgid(ap->a_id)) == NULL) {
507                                         slprintf(idbuf, sizeof(idbuf)-1, "%ld",
508                                                 (long)ap->a_id);
509                                         id = idbuf;
510                                 } else {
511                                         id = gr->gr_name;
512                                 }
513                         case SMB_ACL_GROUP_OBJ:
514                                 tag = "group";
515                                 break;
516
517                         case SMB_ACL_OTHER:
518                                 tag = "other";
519                                 break;
520
521                         case SMB_ACL_MASK:
522                                 tag = "mask";
523                                 break;
524
525                 }
526
527                 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
528                 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
529                 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
530                 perms[3] = '\0';
531
532                 /*          <tag>      :  <qualifier>   :  rwx \n  \0 */
533                 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
534
535                 /*
536                  * If this entry would overflow the buffer
537                  * allocate enough additional memory for this
538                  * entry and an estimate of another 20 bytes
539                  * for each entry still to be processed
540                  */
541                 if ((len + nbytes) > maxlen) {
542                         char *oldtext = text;
543
544                         maxlen += nbytes + 20 * (acl_d->count - i);
545
546                         if ((text = realloc(oldtext, maxlen)) == NULL) {
547                                 free(oldtext);
548                                 errno = ENOMEM;
549                                 return NULL;
550                         }
551                 }
552
553                 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
554                 len += nbytes - 1;
555         }
556
557         if (len_p)
558                 *len_p = len;
559
560         return text;
561 }
562
563 SMB_ACL_T sys_acl_init(int count)
564 {
565         SMB_ACL_T       a;
566
567         if (count < 0) {
568                 errno = EINVAL;
569                 return NULL;
570         }
571
572         /*
573          * note that since the definition of the structure pointed
574          * to by the SMB_ACL_T includes the first element of the
575          * acl[] array, this actually allocates an ACL with room
576          * for (count+1) entries
577          */
578         if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) {
579                 errno = ENOMEM;
580                 return NULL;
581         }
582
583         a->size = count + 1;
584         a->count = 0;
585         a->next = -1;
586
587         return a;
588 }
589
590
591 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
592 {
593         SMB_ACL_T       acl_d;
594         SMB_ACL_ENTRY_T entry_d;
595
596         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
597                 errno = EINVAL;
598                 return -1;
599         }
600
601         if (acl_d->count >= acl_d->size) {
602                 errno = ENOSPC;
603                 return -1;
604         }
605
606         entry_d         = &acl_d->acl[acl_d->count++];
607         entry_d->a_type = 0;
608         entry_d->a_id   = -1;
609         entry_d->a_perm = 0;
610         *entry_p        = entry_d;
611
612         return 0;
613 }
614
615 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
616 {
617         switch (tag_type) {
618                 case SMB_ACL_USER:
619                 case SMB_ACL_USER_OBJ:
620                 case SMB_ACL_GROUP:
621                 case SMB_ACL_GROUP_OBJ:
622                 case SMB_ACL_OTHER:
623                 case SMB_ACL_MASK:
624                         entry_d->a_type = tag_type;
625                         break;
626                 default:
627                         errno = EINVAL;
628                         return -1;
629         }
630
631         return 0;
632 }
633
634 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
635 {
636         if (entry_d->a_type != SMB_ACL_GROUP
637             && entry_d->a_type != SMB_ACL_USER) {
638                 errno = EINVAL;
639                 return -1;
640         }
641
642         entry_d->a_id = *((id_t *)qual_p);
643
644         return 0;
645 }
646
647 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
648 {
649         if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
650                 return EINVAL;
651         }
652
653         entry_d->a_perm = *permset_d;
654
655         return 0;
656 }
657
658 /*
659  * sort the ACL and check it for validity
660  *
661  * if it's a minimal ACL with only 4 entries then we
662  * need to recalculate the mask permissions to make
663  * sure that they are the same as the GROUP_OBJ
664  * permissions as required by the UnixWare acl() system call.
665  *
666  * (note: since POSIX allows minimal ACLs which only contain
667  * 3 entries - ie there is no mask entry - we should, in theory,
668  * check for this and add a mask entry if necessary - however
669  * we "know" that the caller of this interface always specifies
670  * a mask so, in practice "this never happens" (tm) - if it *does*
671  * happen aclsort() will fail and return an error and someone will
672  * have to fix it ...)
673  */
674
675 static int acl_sort(SMB_ACL_T acl_d)
676 {
677         int     fixmask = (acl_d->count <= 4);
678
679         if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
680                 errno = EINVAL;
681                 return -1;
682         }
683         return 0;
684 }
685  
686 int sys_acl_valid(SMB_ACL_T acl_d)
687 {
688         return acl_sort(acl_d);
689 }
690
691 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
692 {
693         struct stat     s;
694         struct acl      *acl_p;
695         int             acl_count;
696         struct acl      *acl_buf        = NULL;
697         int             ret;
698
699         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
700                 errno = EINVAL;
701                 return -1;
702         }
703
704         if (acl_sort(acl_d) != 0) {
705                 return -1;
706         }
707
708         acl_p           = &acl_d->acl[0];
709         acl_count       = acl_d->count;
710
711         /*
712          * if it's a directory there is extra work to do
713          * since the acl() system call will replace both
714          * the access ACLs and the default ACLs (if any)
715          */
716         if (stat(name, &s) != 0) {
717                 return -1;
718         }
719         if (S_ISDIR(s.st_mode)) {
720                 SMB_ACL_T       acc_acl;
721                 SMB_ACL_T       def_acl;
722                 SMB_ACL_T       tmp_acl;
723                 int             i;
724
725                 if (type == SMB_ACL_TYPE_ACCESS) {
726                         acc_acl = acl_d;
727                         def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
728
729                 } else {
730                         def_acl = acl_d;
731                         acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
732                 }
733
734                 if (tmp_acl == NULL) {
735                         return -1;
736                 }
737
738                 /*
739                  * allocate a temporary buffer for the complete ACL
740                  */
741                 acl_count = acc_acl->count + def_acl->count;
742                 acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0]));
743
744                 if (acl_buf == NULL) {
745                         sys_acl_free_acl(tmp_acl);
746                         errno = ENOMEM;
747                         return -1;
748                 }
749
750                 /*
751                  * copy the access control and default entries into the buffer
752                  */
753                 memcpy(&acl_buf[0], &acc_acl->acl[0],
754                         acc_acl->count * sizeof(acl_buf[0]));
755
756                 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
757                         def_acl->count * sizeof(acl_buf[0]));
758
759                 /*
760                  * set the ACL_DEFAULT flag on the default entries
761                  */
762                 for (i = acc_acl->count; i < acl_count; i++) {
763                         acl_buf[i].a_type |= ACL_DEFAULT;
764                 }
765
766                 sys_acl_free_acl(tmp_acl);
767
768         } else if (type != SMB_ACL_TYPE_ACCESS) {
769                 errno = EINVAL;
770                 return -1;
771         }
772
773         ret = acl(name, SETACL, acl_count, acl_p);
774
775         if (acl_buf) {
776                 free(acl_buf);
777         }
778
779         return ret;
780 }
781
782 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
783 {
784         if (acl_sort(acl_d) != 0) {
785                 return -1;
786         }
787
788         return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
789 }
790
791 int sys_acl_delete_def_file(const char *path)
792 {
793         SMB_ACL_T       acl_d;
794         int             ret;
795
796         /*
797          * fetching the access ACL and rewriting it has
798          * the effect of deleting the default ACL
799          */
800         if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
801                 return -1;
802         }
803
804         ret = acl(path, SETACL, acl_d->count, acl_d->acl);
805
806         sys_acl_free_acl(acl_d);
807         
808         return ret;
809 }
810
811 int sys_acl_free_text(char *text)
812 {
813         free(text);
814         return 0;
815 }
816
817 int sys_acl_free_acl(SMB_ACL_T acl_d) 
818 {
819         free(acl_d);
820         return 0;
821 }
822
823 int sys_acl_free_qualifier(void *qual) 
824 {
825         return 0;
826 }
827
828 #elif defined(HAVE_IRIX_ACLS)
829
830 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
831 {
832         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
833                 errno = EINVAL;
834                 return -1;
835         }
836
837         if (entry_p == NULL) {
838                 errno = EINVAL;
839                 return -1;
840         }
841
842         if (entry_id == SMB_ACL_FIRST_ENTRY) {
843                 acl_d->next = 0;
844         }
845
846         if (acl_d->next < 0) {
847                 errno = EINVAL;
848                 return -1;
849         }
850
851         if (acl_d->next >= acl_d->aclp->acl_cnt) {
852                 return 0;
853         }
854
855         *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
856
857         return 1;
858 }
859
860 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
861 {
862         *type_p = entry_d->ae_tag;
863
864         return 0;
865 }
866
867 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
868 {
869         *permset_p = entry_d;
870
871         return 0;
872 }
873
874 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
875 {
876         if (entry_d->ae_tag != SMB_ACL_USER
877             && entry_d->ae_tag != SMB_ACL_GROUP) {
878                 errno = EINVAL;
879                 return NULL;
880         }
881
882         return &entry_d->ae_id;
883 }
884
885 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
886 {
887         SMB_ACL_T       a;
888
889         if ((a = malloc(sizeof(*a))) == NULL) {
890                 errno = ENOMEM;
891                 return NULL;
892         }
893         if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
894                 free(a);
895                 return NULL;
896         }
897         a->next = -1;
898         a->freeaclp = True;
899         return a;
900 }
901
902 SMB_ACL_T sys_acl_get_fd(int fd)
903 {
904         SMB_ACL_T       a;
905
906         if ((a = malloc(sizeof(*a))) == NULL) {
907                 errno = ENOMEM;
908                 return NULL;
909         }
910         if ((a->aclp = acl_get_fd(fd)) == NULL) {
911                 free(a);
912                 return NULL;
913         }
914         a->next = -1;
915         a->freeaclp = True;
916         return a;
917 }
918
919 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
920 {
921         permset_d->ae_perm = 0;
922
923         return 0;
924 }
925
926 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
927 {
928         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
929             && perm != SMB_ACL_EXECUTE) {
930                 errno = EINVAL;
931                 return -1;
932         }
933
934         if (permset_d == NULL) {
935                 errno = EINVAL;
936                 return -1;
937         }
938
939         permset_d->ae_perm |= perm;
940
941         return 0;
942 }
943
944 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
945 {
946         return permset_d->ae_perm & perm;
947 }
948
949 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
950 {
951         return acl_to_text(acl_d->aclp, len_p);
952 }
953
954 SMB_ACL_T sys_acl_init(int count)
955 {
956         SMB_ACL_T       a;
957
958         if (count < 0) {
959                 errno = EINVAL;
960                 return NULL;
961         }
962
963         if ((a = malloc(sizeof(*a) + sizeof(struct acl))) == NULL) {
964                 errno = ENOMEM;
965                 return NULL;
966         }
967
968         a->next = -1;
969         a->freeaclp = False;
970         a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
971         a->aclp->acl_cnt = 0;
972
973         return a;
974 }
975
976
977 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
978 {
979         SMB_ACL_T       acl_d;
980         SMB_ACL_ENTRY_T entry_d;
981
982         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
983                 errno = EINVAL;
984                 return -1;
985         }
986
987         if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
988                 errno = ENOSPC;
989                 return -1;
990         }
991
992         entry_d         = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
993         entry_d->ae_tag = 0;
994         entry_d->ae_id  = 0;
995         entry_d->ae_perm        = 0;
996         *entry_p        = entry_d;
997
998         return 0;
999 }
1000
1001 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1002 {
1003         switch (tag_type) {
1004                 case SMB_ACL_USER:
1005                 case SMB_ACL_USER_OBJ:
1006                 case SMB_ACL_GROUP:
1007                 case SMB_ACL_GROUP_OBJ:
1008                 case SMB_ACL_OTHER:
1009                 case SMB_ACL_MASK:
1010                         entry_d->ae_tag = tag_type;
1011                         break;
1012                 default:
1013                         errno = EINVAL;
1014                         return -1;
1015         }
1016
1017         return 0;
1018 }
1019
1020 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1021 {
1022         if (entry_d->ae_tag != SMB_ACL_GROUP
1023             && entry_d->ae_tag != SMB_ACL_USER) {
1024                 errno = EINVAL;
1025                 return -1;
1026         }
1027
1028         entry_d->ae_id = *((id_t *)qual_p);
1029
1030         return 0;
1031 }
1032
1033 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1034 {
1035         if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1036                 return EINVAL;
1037         }
1038
1039         entry_d->ae_perm = permset_d->ae_perm;
1040
1041         return 0;
1042 }
1043
1044 int sys_acl_valid(SMB_ACL_T acl_d)
1045 {
1046         return acl_valid(acl_d->aclp);
1047 }
1048
1049 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1050 {
1051         return acl_set_file(name, type, acl_d->aclp);
1052 }
1053
1054 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1055 {
1056         return acl_set_fd(fd, acl_d->aclp);
1057 }
1058
1059 int sys_acl_delete_def_file(const char *name)
1060 {
1061         return acl_delete_def_file(name);
1062 }
1063
1064 int sys_acl_free_text(char *text)
1065 {
1066         return acl_free(text);
1067 }
1068
1069 int sys_acl_free_acl(SMB_ACL_T acl_d) 
1070 {
1071         if (acl_d->freeaclp) {
1072                 acl_free(acl_d->aclp);
1073         }
1074         acl_free(acl_d);
1075         return 0;
1076 }
1077
1078 int sys_acl_free_qualifier(void *qual) 
1079 {
1080         return 0;
1081 }
1082
1083 #elif defined(HAVE_XFS_ACLS)
1084 /* For Linux SGI/XFS Filesystems    
1085  * contributed by J Trostel, Connex 
1086  *                                  */
1087
1088 /* based on the implementation for Solaris by Toomas Soome.. which is 
1089  * based on the implementation  by Micheal Davidson for Unixware...
1090  *
1091  * Linux XFS is a 'work-in-progress'
1092  * This interface may change...  
1093  * You've been warned ;->           */
1094
1095 /* First, do the identity mapping */
1096
1097 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1098 {
1099         if( acl_get_entry( the_acl, entry_id, entry_p) >= 0) {
1100                 return 1;
1101         }
1102         else {
1103                 return -1;
1104         }
1105 }
1106
1107 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1108 {
1109         return acl_get_file( path_p, type);
1110 }
1111
1112 SMB_ACL_T sys_acl_get_fd(int fd)
1113 {
1114         return acl_get_fd(fd);
1115 }
1116
1117 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
1118 {
1119         return acl_to_text( the_acl, plen);
1120 }
1121
1122 int sys_acl_valid( SMB_ACL_T theacl )
1123 {
1124         return acl_valid(theacl);
1125 }
1126
1127 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1128 {
1129         return acl_set_file(name, acltype, theacl);
1130 }
1131
1132 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
1133 {
1134         return acl_set_fd(fd, theacl);
1135 }
1136
1137 /* Now the functions I need to define for XFS */
1138
1139 int sys_acl_create_entry( SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1140 {
1141         acl_t acl, newacl;
1142         acl_entry_t ace;
1143         int cnt;
1144
1145         acl = *acl_p;
1146         ace = *entry_p;
1147
1148         if((*acl_p == NULL) || (ace == NULL)){
1149                 errno = EINVAL;
1150                 return -1;
1151         }
1152         
1153         cnt = acl->acl_cnt;     
1154         if( (cnt + 1) > ACL_MAX_ENTRIES  ){
1155                 errno = ENOSPC;
1156                 return -1;
1157         }
1158
1159         newacl = (acl_t)malloc(sizeof(struct acl));
1160         if(newacl == NULL){
1161                 errno = ENOMEM;
1162                 return -1;
1163         }
1164         
1165         *newacl = *acl;
1166         newacl->acl_entry[cnt] = *ace;
1167         newacl->acl_cnt = cnt + 1;
1168
1169         acl_free(*acl_p);
1170         *acl_p = newacl;
1171         *entry_p = &newacl->acl_entry[cnt];
1172         return 0;
1173 }
1174
1175
1176 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1177 {
1178         *tag_type_p = entry_d->ae_tag;
1179         return 0;
1180 }
1181
1182 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1183 {
1184         *permset_p = &entry_d->ae_perm;
1185         return 0;
1186 }
1187
1188 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1189 {
1190         if (entry_d->ae_tag != SMB_ACL_USER
1191                 && entry_d->ae_tag != SMB_ACL_GROUP) {
1192                 errno = EINVAL;
1193                 return NULL;
1194         }       
1195         return &entry_d->ae_id;
1196 }
1197
1198 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1199 {
1200         *permset = 0;
1201         return 0;
1202 }
1203
1204 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1205 {
1206         return (*permset & perm);
1207 }
1208
1209 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1210 {
1211
1212         /* TO DO: Add in ALL possible permissions here */
1213         /* TO DO: Include extended ones!! */
1214
1215         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE && perm != SMB_ACL_EXECUTE) {
1216                 errno = EINVAL;
1217                 return -1;
1218         }
1219         
1220         if(permset == NULL) {
1221                 errno = EINVAL;
1222                 return -1;
1223         }
1224         
1225         *permset |= perm;
1226         
1227         return 0;
1228 }
1229
1230 SMB_ACL_T sys_acl_init( int count)
1231 {
1232         SMB_ACL_T a;
1233         if((count > ACL_MAX_ENTRIES) || (count < 0)) {
1234                 errno = EINVAL;
1235                 return NULL;
1236         }
1237         else {
1238                 a = (struct acl *)malloc(sizeof(struct acl)); /* where is this memory freed? */
1239                 a->acl_cnt = 0;
1240                 return a;
1241         }
1242 }
1243
1244 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1245 {
1246         
1247         switch (tag_type) {
1248                 case SMB_ACL_USER:
1249                 case SMB_ACL_USER_OBJ:
1250                 case SMB_ACL_GROUP:
1251                 case SMB_ACL_GROUP_OBJ:
1252                 case SMB_ACL_OTHER:
1253                 case SMB_ACL_MASK:
1254                         entry_d->ae_tag = tag_type;
1255                         break;
1256                 default:
1257                         errno = EINVAL;
1258                         return -1;
1259         }
1260         return 0;
1261 }
1262
1263 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry_d, void *qual_p)
1264 {
1265         if(entry_d->ae_tag != SMB_ACL_GROUP &&
1266                 entry_d->ae_tag != SMB_ACL_USER) {
1267                 errno = EINVAL;
1268                 return -1;
1269         }
1270         
1271         entry_d->ae_id = *((uid_t *)qual_p);
1272
1273         return 0;
1274 }
1275
1276 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1277 {
1278   /* TO DO: expand to extended permissions eventually! */
1279
1280         if(*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1281                 return EINVAL;
1282         }
1283
1284         return 0;
1285 }
1286
1287 int sys_acl_free_text(char *text)
1288 {
1289         return acl_free(text);
1290 }
1291
1292 int sys_acl_free_acl(SMB_ACL_T the_acl) 
1293 {
1294         return acl_free(the_acl);
1295 }
1296
1297 int sys_acl_free_qualifier(void *qual) 
1298 {
1299         return 0;
1300 }
1301
1302 #elif defined(HAVE_AIX_ACLS)
1303
1304 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1305
1306 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1307 {
1308         struct acl_entry_link *link;
1309         struct new_acl_entry *entry;
1310         int keep_going;
1311
1312         DEBUG(10,("This is the count: %d\n",theacl->count));
1313
1314         /* Check if count was previously set to -1. *
1315          * If it was, that means we reached the end *
1316          * of the acl last time.                    */
1317         if(theacl->count == -1)
1318                 return(0);
1319
1320         link = theacl;
1321         /* To get to the next acl, traverse linked list until index *
1322          * of acl matches the count we are keeping.  This count is  *
1323          * incremented each time we return an acl entry.            */
1324
1325         for(keep_going = 0; keep_going < theacl->count; keep_going++)
1326                 link = link->nextp;
1327
1328         entry = *entry_p =  link->entryp;
1329
1330         DEBUG(10,("*entry_p is %d\n",entry_p));
1331         DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1332
1333         /* Increment count */
1334         theacl->count++;
1335         if(link->nextp == NULL)
1336                 theacl->count = -1;
1337
1338         return(1);
1339 }
1340
1341 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1342 {
1343         /* Initialize tag type */
1344
1345         *tag_type_p = -1;
1346         DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1347
1348         /* Depending on what type of entry we have, *
1349          * return tag type.                         */
1350         switch(entry_d->ace_id->id_type) {
1351         case ACEID_USER:
1352                 *tag_type_p = SMB_ACL_USER;
1353                 break;
1354         case ACEID_GROUP:
1355                 *tag_type_p = SMB_ACL_GROUP;
1356                 break;
1357
1358         case SMB_ACL_USER_OBJ:
1359         case SMB_ACL_GROUP_OBJ:
1360         case SMB_ACL_OTHER:
1361                 *tag_type_p = entry_d->ace_id->id_type;
1362                 break;
1363  
1364         default:
1365                 return(-1);
1366         }
1367
1368         return(0);
1369 }
1370
1371 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1372 {
1373         DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
1374         *permset_p = &entry_d->ace_access;
1375         DEBUG(10,("**permset_p is %d\n",**permset_p));
1376         if(!(**permset_p & S_IXUSR) &&
1377                 !(**permset_p & S_IWUSR) &&
1378                 !(**permset_p & S_IRUSR) &&
1379                 (**permset_p != 0))
1380                         return(-1);
1381
1382         DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
1383         return(0);
1384 }
1385
1386 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1387 {
1388         return(entry_d->ace_id->id_data);
1389 }
1390
1391 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1392 {
1393         struct acl *file_acl = (struct acl *)NULL;
1394         struct acl_entry *acl_entry;
1395         struct new_acl_entry *new_acl_entry;
1396         struct ace_id *idp;
1397         struct acl_entry_link *acl_entry_link;
1398         struct acl_entry_link *acl_entry_link_head;
1399         int i;
1400         int rc = 0;
1401         uid_t user_id;
1402
1403         /* Get the acl using statacl */
1404  
1405         DEBUG(10,("Entering sys_acl_get_file\n"));
1406         DEBUG(10,("path_p is %s\n",path_p));
1407
1408         file_acl = (struct acl *)malloc(BUFSIZ);
1409  
1410         if(file_acl == NULL) {
1411                 errno=ENOMEM;
1412                 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1413                 return(NULL);
1414         }
1415
1416         memset(file_acl,0,BUFSIZ);
1417
1418         rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1419         if(rc == -1) {
1420                 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1421                 free(file_acl);
1422                 return(NULL);
1423         }
1424
1425         DEBUG(10,("Got facl and returned it\n"));
1426
1427         /* Point to the first acl entry in the acl */
1428         acl_entry =  file_acl->acl_ext;
1429
1430         /* Begin setting up the head of the linked list *
1431          * that will be used for the storing the acl    *
1432          * in a way that is useful for the posix_acls.c *
1433          * code.                                          */
1434
1435         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1436         if(acl_entry_link_head == NULL)
1437                 return(NULL);
1438
1439         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1440         if(acl_entry_link->entryp == NULL) {
1441                 free(file_acl);
1442                 errno = ENOMEM;
1443                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1444                 return(NULL);
1445         }
1446
1447         DEBUG(10,("acl_entry is %d\n",acl_entry));
1448         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1449
1450         /* Check if the extended acl bit is on.   *
1451          * If it isn't, do not show the           *
1452          * contents of the acl since AIX intends *
1453          * the extended info to remain unused     */
1454
1455         if(file_acl->acl_mode & S_IXACL){
1456                 /* while we are not pointing to the very end */
1457                 while(acl_entry < acl_last(file_acl)) {
1458                         /* before we malloc anything, make sure this is  */
1459                         /* a valid acl entry and one that we want to map */
1460                         idp = id_nxt(acl_entry->ace_id);
1461                         if((acl_entry->ace_type == ACC_SPECIFY ||
1462                                 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1463                                         acl_entry = acl_nxt(acl_entry);
1464                                         continue;
1465                         }
1466
1467                         idp = acl_entry->ace_id;
1468
1469                         /* Check if this is the first entry in the linked list. *
1470                          * The first entry needs to keep prevp pointing to NULL *
1471                          * and already has entryp allocated.                  */
1472
1473                         if(acl_entry_link_head->count != 0) {
1474                                 acl_entry_link->nextp = (struct acl_entry_link *)
1475                                                                                         malloc(sizeof(struct acl_entry_link));
1476
1477                                 if(acl_entry_link->nextp == NULL) {
1478                                         free(file_acl);
1479                                         errno = ENOMEM;
1480                                         DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1481                                         return(NULL);
1482                                 }
1483
1484                                 acl_entry_link->nextp->prevp = acl_entry_link;
1485                                 acl_entry_link = acl_entry_link->nextp;
1486                                 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1487                                 if(acl_entry_link->entryp == NULL) {
1488                                         free(file_acl);
1489                                         errno = ENOMEM;
1490                                         DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1491                                         return(NULL);
1492                                 }
1493                                 acl_entry_link->nextp = NULL;
1494                         }
1495
1496                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1497
1498                         /* Don't really need this since all types are going *
1499                          * to be specified but, it's better than leaving it 0 */
1500
1501                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1502  
1503                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1504  
1505                         memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
1506
1507                         /* The access in the acl entries must be left shifted by *
1508                          * three bites, because they will ultimately be compared *
1509                          * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
1510
1511                         switch(acl_entry->ace_type){
1512                         case ACC_PERMIT:
1513                         case ACC_SPECIFY:
1514                                 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1515                                 acl_entry_link->entryp->ace_access <<= 6;
1516                                 acl_entry_link_head->count++;
1517                                 break;
1518                         case ACC_DENY:
1519                                 /* Since there is no way to return a DENY acl entry *
1520                                  * change to PERMIT and then shift.                 */
1521                                 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1522                                 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1523                                 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1524                                 acl_entry_link->entryp->ace_access <<= 6;
1525                                 acl_entry_link_head->count++;
1526                                 break;
1527                         default:
1528                                 return(0);
1529                         }
1530
1531                         DEBUG(10,("acl_entry = %d\n",acl_entry));
1532                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1533  
1534                         acl_entry = acl_nxt(acl_entry);
1535                 }
1536         } /* end of if enabled */
1537
1538         /* Since owner, group, other acl entries are not *
1539          * part of the acl entries in an acl, they must  *
1540          * be dummied up to become part of the list.     */
1541
1542         for( i = 1; i < 4; i++) {
1543                 DEBUG(10,("i is %d\n",i));
1544                 if(acl_entry_link_head->count != 0) {
1545                         acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1546                         if(acl_entry_link->nextp == NULL) {
1547                                 free(file_acl);
1548                                 errno = ENOMEM;
1549                                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1550                                 return(NULL);
1551                         }
1552
1553                         acl_entry_link->nextp->prevp = acl_entry_link;
1554                         acl_entry_link = acl_entry_link->nextp;
1555                         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1556                         if(acl_entry_link->entryp == NULL) {
1557                                 free(file_acl);
1558                                 errno = ENOMEM;
1559                                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1560                                 return(NULL);
1561                         }
1562                 }
1563
1564                 acl_entry_link->nextp = NULL;
1565
1566                 new_acl_entry = acl_entry_link->entryp;
1567                 idp = new_acl_entry->ace_id;
1568
1569                 new_acl_entry->ace_len = sizeof(struct acl_entry);
1570                 new_acl_entry->ace_type = ACC_PERMIT;
1571                 idp->id_len = sizeof(struct ace_id);
1572                 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1573                 memset(idp->id_data,0,sizeof(uid_t));
1574
1575                 switch(i) {
1576                 case 2:
1577                         new_acl_entry->ace_access = file_acl->g_access << 6;
1578                         idp->id_type = SMB_ACL_GROUP_OBJ;
1579                         break;
1580
1581                 case 3:
1582                         new_acl_entry->ace_access = file_acl->o_access << 6;
1583                         idp->id_type = SMB_ACL_OTHER;
1584                         break;
1585  
1586                 case 1:
1587                         new_acl_entry->ace_access = file_acl->u_access << 6;
1588                         idp->id_type = SMB_ACL_USER_OBJ;
1589                         break;
1590  
1591                 default:
1592                         return(NULL);
1593
1594                 }
1595
1596                 acl_entry_link_head->count++;
1597                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1598         }
1599
1600         acl_entry_link_head->count = 0;
1601         free(file_acl);
1602
1603         return(acl_entry_link_head);
1604 }
1605
1606 SMB_ACL_T sys_acl_get_fd(int fd)
1607 {
1608         struct acl *file_acl = (struct acl *)NULL;
1609         struct acl_entry *acl_entry;
1610         struct new_acl_entry *new_acl_entry;
1611         struct ace_id *idp;
1612         struct acl_entry_link *acl_entry_link;
1613         struct acl_entry_link *acl_entry_link_head;
1614         int i;
1615         int rc = 0;
1616         uid_t user_id;
1617
1618         /* Get the acl using fstatacl */
1619    
1620         DEBUG(10,("Entering sys_acl_get_fd\n"));
1621         DEBUG(10,("fd is %d\n",fd));
1622         file_acl = (struct acl *)malloc(BUFSIZ);
1623
1624         if(file_acl == NULL) {
1625                 errno=ENOMEM;
1626                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1627                 return(NULL);
1628         }
1629
1630         memset(file_acl,0,BUFSIZ);
1631
1632         rc = fstatacl(fd,0,file_acl,BUFSIZ);
1633         if(rc == -1) {
1634                 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
1635                 free(file_acl);
1636                 return(NULL);
1637         }
1638
1639         DEBUG(10,("Got facl and returned it\n"));
1640
1641         /* Point to the first acl entry in the acl */
1642
1643         acl_entry =  file_acl->acl_ext;
1644         /* Begin setting up the head of the linked list *
1645          * that will be used for the storing the acl    *
1646          * in a way that is useful for the posix_acls.c *
1647          * code.                                        */
1648
1649         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1650         if(acl_entry_link_head == NULL){
1651                 free(file_acl);
1652                 return(NULL);
1653         }
1654
1655         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1656
1657         if(acl_entry_link->entryp == NULL) {
1658                 errno = ENOMEM;
1659                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1660                 free(file_acl);
1661                 return(NULL);
1662         }
1663
1664         DEBUG(10,("acl_entry is %d\n",acl_entry));
1665         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1666  
1667         /* Check if the extended acl bit is on.   *
1668          * If it isn't, do not show the           *
1669          * contents of the acl since AIX intends  *
1670          * the extended info to remain unused     */
1671  
1672         if(file_acl->acl_mode & S_IXACL){
1673                 /* while we are not pointing to the very end */
1674                 while(acl_entry < acl_last(file_acl)) {
1675                         /* before we malloc anything, make sure this is  */
1676                         /* a valid acl entry and one that we want to map */
1677
1678                         idp = id_nxt(acl_entry->ace_id);
1679                         if((acl_entry->ace_type == ACC_SPECIFY ||
1680                                 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1681                                         acl_entry = acl_nxt(acl_entry);
1682                                         continue;
1683                         }
1684
1685                         idp = acl_entry->ace_id;
1686  
1687                         /* Check if this is the first entry in the linked list. *
1688                          * The first entry needs to keep prevp pointing to NULL *
1689                          * and already has entryp allocated.                 */
1690
1691                         if(acl_entry_link_head->count != 0) {
1692                                 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1693                                 if(acl_entry_link->nextp == NULL) {
1694                                         errno = ENOMEM;
1695                                         DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1696                                         free(file_acl);
1697                                         return(NULL);
1698                                 }
1699                                 acl_entry_link->nextp->prevp = acl_entry_link;
1700                                 acl_entry_link = acl_entry_link->nextp;
1701                                 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1702                                 if(acl_entry_link->entryp == NULL) {
1703                                         errno = ENOMEM;
1704                                         DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1705                                         free(file_acl);
1706                                         return(NULL);
1707                                 }
1708
1709                                 acl_entry_link->nextp = NULL;
1710                         }
1711
1712                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1713
1714                         /* Don't really need this since all types are going *
1715                          * to be specified but, it's better than leaving it 0 */
1716
1717                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1718                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1719
1720                         memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
1721
1722                         /* The access in the acl entries must be left shifted by *
1723                          * three bites, because they will ultimately be compared *
1724                          * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
1725
1726                         switch(acl_entry->ace_type){
1727                         case ACC_PERMIT:
1728                         case ACC_SPECIFY:
1729                                 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1730                                 acl_entry_link->entryp->ace_access <<= 6;
1731                                 acl_entry_link_head->count++;
1732                                 break;
1733                         case ACC_DENY:
1734                                 /* Since there is no way to return a DENY acl entry *
1735                                  * change to PERMIT and then shift.                 */
1736                                 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1737                                 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1738                                 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1739                                 acl_entry_link->entryp->ace_access <<= 6;
1740                                 acl_entry_link_head->count++;
1741                                 break;
1742                         default:
1743                                 return(0);
1744                         }
1745
1746                         DEBUG(10,("acl_entry = %d\n",acl_entry));
1747                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1748  
1749                         acl_entry = acl_nxt(acl_entry);
1750                 }
1751         } /* end of if enabled */
1752
1753         /* Since owner, group, other acl entries are not *
1754          * part of the acl entries in an acl, they must  *
1755          * be dummied up to become part of the list.     */
1756
1757         for( i = 1; i < 4; i++) {
1758                 DEBUG(10,("i is %d\n",i));
1759                 if(acl_entry_link_head->count != 0){
1760                         acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1761                         if(acl_entry_link->nextp == NULL) {
1762                                 errno = ENOMEM;
1763                                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1764                                 free(file_acl);
1765                                 return(NULL);
1766                         }
1767
1768                         acl_entry_link->nextp->prevp = acl_entry_link;
1769                         acl_entry_link = acl_entry_link->nextp;
1770                         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1771
1772                         if(acl_entry_link->entryp == NULL) {
1773                                 free(file_acl);
1774                                 errno = ENOMEM;
1775                                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1776                                 return(NULL);
1777                         }
1778                 }
1779
1780                 acl_entry_link->nextp = NULL;
1781  
1782                 new_acl_entry = acl_entry_link->entryp;
1783                 idp = new_acl_entry->ace_id;
1784  
1785                 new_acl_entry->ace_len = sizeof(struct acl_entry);
1786                 new_acl_entry->ace_type = ACC_PERMIT;
1787                 idp->id_len = sizeof(struct ace_id);
1788                 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1789                 memset(idp->id_data,0,sizeof(uid_t));
1790  
1791                 switch(i) {
1792                 case 2:
1793                         new_acl_entry->ace_access = file_acl->g_access << 6;
1794                         idp->id_type = SMB_ACL_GROUP_OBJ;
1795                         break;
1796  
1797                 case 3:
1798                         new_acl_entry->ace_access = file_acl->o_access << 6;
1799                         idp->id_type = SMB_ACL_OTHER;
1800                         break;
1801  
1802                 case 1:
1803                         new_acl_entry->ace_access = file_acl->u_access << 6;
1804                         idp->id_type = SMB_ACL_USER_OBJ;
1805                         break;
1806  
1807                 default:
1808                         return(NULL);
1809                 }
1810  
1811                 acl_entry_link_head->count++;
1812                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1813         }
1814
1815         acl_entry_link_head->count = 0;
1816         free(file_acl);
1817  
1818         return(acl_entry_link_head);
1819 }
1820
1821 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1822 {
1823         *permset = *permset & ~0777;
1824         return(0);
1825 }
1826
1827 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1828 {
1829         if((perm != 0) &&
1830                         (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
1831                 return(-1);
1832
1833         *permset |= perm;
1834         DEBUG(10,("This is the permset now: %d\n",*permset));
1835         return(0);
1836 }
1837
1838 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
1839 {
1840         return(NULL);
1841 }
1842
1843 SMB_ACL_T sys_acl_init( int count)
1844 {
1845         struct acl_entry_link *theacl = NULL;
1846  
1847         DEBUG(10,("Entering sys_acl_init\n"));
1848
1849         theacl = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1850         if(theacl == NULL) {
1851                 errno = ENOMEM;
1852                 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
1853                 return(NULL);
1854         }
1855
1856         theacl->count = 0;
1857         theacl->nextp = NULL;
1858         theacl->prevp = NULL;
1859         theacl->entryp = NULL;
1860         DEBUG(10,("Exiting sys_acl_init\n"));
1861         return(theacl);
1862 }
1863
1864 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1865 {
1866         struct acl_entry_link *theacl;
1867         struct acl_entry_link *acl_entryp;
1868         struct acl_entry_link *temp_entry;
1869         int counting;
1870
1871         DEBUG(10,("Entering the sys_acl_create_entry\n"));
1872
1873         theacl = acl_entryp = *pacl;
1874
1875         /* Get to the end of the acl before adding entry */
1876
1877         for(counting=0; counting < theacl->count; counting++){
1878                 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
1879                 temp_entry = acl_entryp;
1880                 acl_entryp = acl_entryp->nextp;
1881         }
1882
1883         if(theacl->count != 0){
1884                 temp_entry->nextp = acl_entryp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1885                 if(acl_entryp == NULL) {
1886                         errno = ENOMEM;
1887                         DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
1888                         return(-1);
1889                 }
1890
1891                 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
1892                 acl_entryp->prevp = temp_entry;
1893                 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
1894         }
1895
1896         *pentry = acl_entryp->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1897         if(*pentry == NULL) {
1898                 errno = ENOMEM;
1899                 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
1900                 return(-1);
1901         }
1902
1903         memset(*pentry,0,sizeof(struct new_acl_entry));
1904         acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
1905         acl_entryp->entryp->ace_type = ACC_PERMIT;
1906         acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
1907         acl_entryp->nextp = NULL;
1908         theacl->count++;
1909         DEBUG(10,("Exiting sys_acl_create_entry\n"));
1910         return(0);
1911 }
1912
1913 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1914 {
1915         DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
1916         entry->ace_id->id_type = tagtype;
1917         DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
1918         DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
1919 }
1920
1921 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
1922 {
1923         DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
1924         memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
1925         DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
1926         return(0);
1927 }
1928
1929 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1930 {
1931         DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
1932         if(!(*permset & S_IXUSR) &&
1933                 !(*permset & S_IWUSR) &&
1934                 !(*permset & S_IRUSR) &&
1935                 (*permset != 0))
1936                         return(-1);
1937
1938         entry->ace_access = *permset;
1939         DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
1940         DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
1941         return(0);
1942 }
1943
1944 int sys_acl_valid( SMB_ACL_T theacl )
1945 {
1946         int user_obj = 0;
1947         int group_obj = 0;
1948         int other_obj = 0;
1949         struct acl_entry_link *acl_entry;
1950
1951         for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
1952                 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
1953                 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
1954                 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
1955         }
1956
1957         DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
1958  
1959         if(user_obj != 1 || group_obj != 1 || other_obj != 1)
1960                 return(-1); 
1961
1962         return(0);
1963 }
1964
1965 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1966 {
1967         struct acl_entry_link *acl_entry_link = NULL;
1968         struct acl *file_acl = NULL;
1969         struct acl *file_acl_temp = NULL;
1970         struct acl_entry *acl_entry = NULL;
1971         struct ace_id *ace_id = NULL;
1972         uint id_type;
1973         uint ace_access;
1974         uint user_id;
1975         uint acl_length;
1976         uint rc;
1977
1978         DEBUG(10,("Entering sys_acl_set_file\n"));
1979         DEBUG(10,("File name is %s\n",name));
1980  
1981         /* AIX has no default ACL */
1982         if(acltype == SMB_ACL_TYPE_DEFAULT)
1983                 return(0);
1984
1985         acl_length = BUFSIZ;
1986         file_acl = (struct acl *)malloc(BUFSIZ);
1987
1988         if(file_acl == NULL) {
1989                 errno = ENOMEM;
1990                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
1991                 return(-1);
1992         }
1993
1994         memset(file_acl,0,BUFSIZ);
1995
1996         file_acl->acl_len = ACL_SIZ;
1997         file_acl->acl_mode = S_IXACL;
1998
1999         for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2000                 acl_entry_link->entryp->ace_access >>= 6;
2001                 id_type = acl_entry_link->entryp->ace_id->id_type;
2002
2003                 switch(id_type) {
2004                 case SMB_ACL_USER_OBJ:
2005                         file_acl->u_access = acl_entry_link->entryp->ace_access;
2006                         continue;
2007                 case SMB_ACL_GROUP_OBJ:
2008                         file_acl->g_access = acl_entry_link->entryp->ace_access;
2009                         continue;
2010                 case SMB_ACL_OTHER:
2011                         file_acl->o_access = acl_entry_link->entryp->ace_access;
2012                         continue;
2013                 case SMB_ACL_MASK:
2014                         continue;
2015                 }
2016
2017                 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2018                         acl_length += sizeof(struct acl_entry);
2019                         file_acl_temp = (struct acl *)malloc(acl_length);
2020                         if(file_acl_temp == NULL) {
2021                                 free(file_acl);
2022                                 errno = ENOMEM;
2023                                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2024                                 return(-1);
2025                         }  
2026
2027                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2028                         free(file_acl);
2029                         file_acl = file_acl_temp;
2030                 }
2031
2032                 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2033                 file_acl->acl_len += sizeof(struct acl_entry);
2034                 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2035                 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2036  
2037                 /* In order to use this, we'll need to wait until we can get denies */
2038                 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2039                 acl_entry->ace_type = ACC_SPECIFY; */
2040
2041                 acl_entry->ace_type = ACC_SPECIFY;
2042  
2043                 ace_id = acl_entry->ace_id;
2044  
2045                 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2046                 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2047                 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2048                 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2049                 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2050         }
2051
2052         rc = chacl(name,file_acl,file_acl->acl_len);
2053         DEBUG(10,("errno is %d\n",errno));
2054         DEBUG(10,("return code is %d\n",rc));
2055         free(file_acl);
2056         DEBUG(10,("Exiting the sys_acl_set_file\n"));
2057         return(rc);
2058 }
2059
2060 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2061 {
2062         struct acl_entry_link *acl_entry_link = NULL;
2063         struct acl *file_acl = NULL;
2064         struct acl *file_acl_temp = NULL;
2065         struct acl_entry *acl_entry = NULL;
2066         struct ace_id *ace_id = NULL;
2067         uint id_type;
2068         uint user_id;
2069         uint acl_length;
2070         uint rc;
2071  
2072         DEBUG(10,("Entering sys_acl_set_fd\n"));
2073         acl_length = BUFSIZ;
2074         file_acl = (struct acl *)malloc(BUFSIZ);
2075
2076         if(file_acl == NULL) {
2077                 errno = ENOMEM;
2078                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2079                 return(-1);
2080         }
2081
2082         memset(file_acl,0,BUFSIZ);
2083  
2084         file_acl->acl_len = ACL_SIZ;
2085         file_acl->acl_mode = S_IXACL;
2086
2087         for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2088                 acl_entry_link->entryp->ace_access >>= 6;
2089                 id_type = acl_entry_link->entryp->ace_id->id_type;
2090                 DEBUG(10,("The id_type is %d\n",id_type));
2091
2092                 switch(id_type) {
2093                 case SMB_ACL_USER_OBJ:
2094                         file_acl->u_access = acl_entry_link->entryp->ace_access;
2095                         continue;
2096                 case SMB_ACL_GROUP_OBJ:
2097                         file_acl->g_access = acl_entry_link->entryp->ace_access;
2098                         continue;
2099                 case SMB_ACL_OTHER:
2100                         file_acl->o_access = acl_entry_link->entryp->ace_access;
2101                         continue;
2102                 case SMB_ACL_MASK:
2103                         continue;
2104                 }
2105
2106                 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2107                         acl_length += sizeof(struct acl_entry);
2108                         file_acl_temp = (struct acl *)malloc(acl_length);
2109                         if(file_acl_temp == NULL) {
2110                                 free(file_acl);
2111                                 errno = ENOMEM;
2112                                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2113                                 return(-1);
2114                         }
2115
2116                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2117                         free(file_acl);
2118                         file_acl = file_acl_temp;
2119                 }
2120
2121                 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2122                 file_acl->acl_len += sizeof(struct acl_entry);
2123                 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2124                 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2125  
2126                 /* In order to use this, we'll need to wait until we can get denies */
2127                 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2128                         acl_entry->ace_type = ACC_SPECIFY; */
2129  
2130                 acl_entry->ace_type = ACC_SPECIFY;
2131  
2132                 ace_id = acl_entry->ace_id;
2133  
2134                 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2135                 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2136                 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2137                 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2138                 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2139         }
2140  
2141         rc = fchacl(fd,file_acl,file_acl->acl_len);
2142         DEBUG(10,("errno is %d\n",errno));
2143         DEBUG(10,("return code is %d\n",rc));
2144         free(file_acl);
2145         DEBUG(10,("Exiting sys_acl_set_fd\n"));
2146         return(rc);
2147 }
2148
2149 int sys_acl_delete_def_file(const char *name)
2150 {
2151         /* AIX has no default ACL */
2152         return 0;
2153 }
2154
2155 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2156 {
2157         return(*permset & perm);
2158 }
2159
2160 int sys_acl_free_text(char *text)
2161 {
2162         return(0);
2163 }
2164
2165 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2166 {
2167         struct acl_entry_link *acl_entry_link;
2168
2169         for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2170                 free(acl_entry_link->prevp->entryp);
2171                 free(acl_entry_link->prevp);
2172         }
2173
2174         free(acl_entry_link->prevp->entryp);
2175         free(acl_entry_link->prevp);
2176         free(acl_entry_link->entryp);
2177         free(acl_entry_link);
2178  
2179         return(0);
2180 }
2181
2182 int sys_acl_free_qualifier(void *qual)
2183 {
2184         return(0);
2185 }
2186
2187 #else /* No ACLs. */
2188
2189 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2190 {
2191         errno = ENOSYS;
2192         return -1;
2193 }
2194
2195 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2196 {
2197         errno = ENOSYS;
2198         return -1;
2199 }
2200
2201 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2202 {
2203         errno = ENOSYS;
2204         return -1;
2205 }
2206
2207 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2208 {
2209         errno = ENOSYS;
2210         return NULL;
2211 }
2212
2213 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2214 {
2215         errno = ENOSYS;
2216         return (SMB_ACL_T)NULL;
2217 }
2218
2219 SMB_ACL_T sys_acl_get_fd(int fd)
2220 {
2221         errno = ENOSYS;
2222         return (SMB_ACL_T)NULL;
2223 }
2224
2225 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2226 {
2227         errno = ENOSYS;
2228         return -1;
2229 }
2230
2231 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2232 {
2233         errno = ENOSYS;
2234         return -1;
2235 }
2236
2237 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2238 {
2239         errno = ENOSYS;
2240         return (permset & perm) ? 1 : 0;
2241 }
2242
2243 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
2244 {
2245         errno = ENOSYS;
2246         return NULL;
2247 }
2248
2249 int sys_acl_free_text(char *text)
2250 {
2251         errno = ENOSYS;
2252         return -1;
2253 }
2254
2255 SMB_ACL_T sys_acl_init( int count)
2256 {
2257         errno = ENOSYS;
2258         return NULL;
2259 }
2260
2261 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2262 {
2263         errno = ENOSYS;
2264         return -1;
2265 }
2266
2267 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2268 {
2269         errno = ENOSYS;
2270         return -1;
2271 }
2272
2273 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2274 {
2275         errno = ENOSYS;
2276         return -1;
2277 }
2278
2279 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2280 {
2281         errno = ENOSYS;
2282         return -1;
2283 }
2284
2285 int sys_acl_valid( SMB_ACL_T theacl )
2286 {
2287         errno = ENOSYS;
2288         return -1;
2289 }
2290
2291 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2292 {
2293         errno = ENOSYS;
2294         return -1;
2295 }
2296
2297 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2298 {
2299         errno = ENOSYS;
2300         return -1;
2301 }
2302
2303 int sys_acl_delete_def_file(const char *name)
2304 {
2305         errno = ENOSYS;
2306         return -1;
2307 }
2308
2309 int sys_acl_free_acl(SMB_ACL_T the_acl) 
2310 {
2311         errno = ENOSYS;
2312         return -1;
2313 }
2314
2315 int sys_acl_free_qualifier(void *qual) 
2316 {
2317         errno = ENOSYS;
2318         return -1;
2319 }
2320
2321 #endif /* No ACLs. */