AIX ACLs donated by IBM.
[kai/samba.git] / source3 / 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( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
49  int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
50
51  This next one is not POSIX complient - but we *have* to have it !
52  More POSIX braindamage.
53
54  int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
55
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.
59
60  int sys_acl_free( void *obj_p)
61
62  The calls we actually use are :
63
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)
67
68 */
69
70 #if defined(HAVE_POSIX_ACLS)
71
72 /* Identity mapping - easy. */
73
74 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
75 {
76         return acl_get_entry( the_acl, entry_id, entry_p);
77 }
78
79 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
80 {
81         return acl_get_tag_type( entry_d, tag_type_p);
82 }
83
84 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
85 {
86         return acl_get_permset( entry_d, permset_p);
87 }
88
89 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
90 {
91         return acl_get_qualifier( entry_d);
92 }
93
94 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
95 {
96         return acl_get_file( path_p, type);
97 }
98
99 SMB_ACL_T sys_acl_get_fd(int fd)
100 {
101         return acl_get_fd(fd);
102 }
103
104 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
105 {
106         return acl_clear_perms(permset);
107 }
108
109 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
110 {
111         return acl_add_perm(permset, perm);
112 }
113
114 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
115 {
116 #if defined(HAVE_ACL_GET_PERM_NP)
117         /*
118          * Required for TrustedBSD-based ACL implementations where
119          * non-POSIX.1e functions are denoted by a _np (non-portable)
120          * suffix.
121          */
122         return acl_get_perm_np(permset, perm);
123 #else
124         return acl_get_perm(permset, perm);
125 #endif
126 }
127
128 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
129 {
130         return acl_to_text( the_acl, plen);
131 }
132
133 SMB_ACL_T sys_acl_init( int count)
134 {
135         return acl_init(count);
136 }
137
138 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
139 {
140         return acl_create_entry(pacl, pentry);
141 }
142
143 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
144 {
145         return acl_set_tag_type(entry, tagtype);
146 }
147
148 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
149 {
150         return acl_set_qualifier(entry, qual);
151 }
152
153 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
154 {
155         return acl_set_permset(entry, permset);
156 }
157
158 int sys_acl_valid( SMB_ACL_T theacl )
159 {
160         return acl_valid(theacl);
161 }
162
163 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
164 {
165         return acl_set_file(name, acltype, theacl);
166 }
167
168 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
169 {
170         return acl_set_fd(fd, theacl);
171 }
172
173 int sys_acl_free_text(char *text)
174 {
175         return acl_free(text);
176 }
177
178 int sys_acl_free_acl(SMB_ACL_T the_acl) 
179 {
180         return acl_free(the_acl);
181 }
182
183 int sys_acl_free_qualifier(void *qual) 
184 {
185         return acl_free(qual);
186 }
187
188 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
189
190 /*
191  * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
192  * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
193  */
194
195 /*
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.
199  *
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.
204  *
205  *      sys_acl_valid()
206  *      sys_acl_set_file()
207  *      sys_acl_set_fd()
208  */
209
210 /*
211  * The only difference between Solaris and UnixWare / OpenUNIX is
212  * that the #defines for the ACL operations have different names
213  */
214 #if defined(HAVE_UNIXWARE_ACLS)
215
216 #define SETACL          ACL_SET
217 #define GETACL          ACL_GET
218 #define GETACLCNT       ACL_CNT
219
220 #endif
221
222
223 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
224 {
225         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
226                 errno = EINVAL;
227                 return -1;
228         }
229
230         if (entry_p == NULL) {
231                 errno = EINVAL;
232                 return -1;
233         }
234
235         if (entry_id == SMB_ACL_FIRST_ENTRY) {
236                 acl_d->next = 0;
237         }
238
239         if (acl_d->next < 0) {
240                 errno = EINVAL;
241                 return -1;
242         }
243
244         if (acl_d->next >= acl_d->count) {
245                 return 0;
246         }
247
248         *entry_p = &acl_d->acl[acl_d->next++];
249
250         return 1;
251 }
252
253 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
254 {
255         *type_p = entry_d->a_type;
256
257         return 0;
258 }
259
260 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
261 {
262         *permset_p = &entry_d->a_perm;
263
264         return 0;
265 }
266
267 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
268 {
269         if (entry_d->a_type != SMB_ACL_USER
270             && entry_d->a_type != SMB_ACL_GROUP) {
271                 errno = EINVAL;
272                 return NULL;
273         }
274
275         return &entry_d->a_id;
276 }
277
278 /*
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.
282  *
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.
288  */
289
290 #define INITIAL_ACL_SIZE        16
291
292 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
293 {
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     */
298
299         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
300                 errno = EINVAL;
301                 return NULL;
302         }
303
304         count = INITIAL_ACL_SIZE;
305         if ((acl_d = sys_acl_init(count)) == NULL) {
306                 return NULL;
307         }
308
309         /*
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.
316          */
317         while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
318             && errno == ENOSPC) {
319
320                 sys_acl_free_acl(acl_d);
321
322                 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
323                         return NULL;
324                 }
325
326                 if ((acl_d = sys_acl_init(count)) == NULL) {
327                         return NULL;
328                 }
329         }
330
331         if (count < 0) {
332                 sys_acl_free_acl(acl_d);
333                 return NULL;
334         }
335
336         /*
337          * calculate the number of access and default ACL entries
338          *
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
342          */
343         for (naccess = 0; naccess < count; naccess++) {
344                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
345                         break;
346         }
347         ndefault = count - naccess;
348         
349         /*
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
353          */
354         if (type == SMB_ACL_TYPE_DEFAULT) {
355                 int     i, j;
356
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;
360                 }
361
362                 acl_d->count = ndefault;
363         } else {
364                 acl_d->count = naccess;
365         }
366
367         return acl_d;
368 }
369
370 SMB_ACL_T sys_acl_get_fd(int fd)
371 {
372         SMB_ACL_T       acl_d;
373         int             count;          /* # of ACL entries allocated   */
374         int             naccess;        /* # of access ACL entries      */
375
376         count = INITIAL_ACL_SIZE;
377         if ((acl_d = sys_acl_init(count)) == NULL) {
378                 return NULL;
379         }
380
381         while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
382             && errno == ENOSPC) {
383
384                 sys_acl_free_acl(acl_d);
385
386                 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
387                         return NULL;
388                 }
389
390                 if ((acl_d = sys_acl_init(count)) == NULL) {
391                         return NULL;
392                 }
393         }
394
395         if (count < 0) {
396                 sys_acl_free_acl(acl_d);
397                 return NULL;
398         }
399
400         /*
401          * calculate the number of access ACL entries
402          */
403         for (naccess = 0; naccess < count; naccess++) {
404                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
405                         break;
406         }
407         
408         acl_d->count = naccess;
409
410         return acl_d;
411 }
412
413 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
414 {
415         *permset_d = 0;
416
417         return 0;
418 }
419
420 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
421 {
422         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
423             && perm != SMB_ACL_EXECUTE) {
424                 errno = EINVAL;
425                 return -1;
426         }
427
428         if (permset_d == NULL) {
429                 errno = EINVAL;
430                 return -1;
431         }
432
433         *permset_d |= perm;
434
435         return 0;
436 }
437
438 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
439 {
440         return *permset_d & perm;
441 }
442
443 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
444 {
445         int     i;
446         int     len, maxlen;
447         char    *text;
448
449         /*
450          * use an initial estimate of 20 bytes per ACL entry
451          * when allocating memory for the text representation
452          * of the ACL
453          */
454         len     = 0;
455         maxlen  = 20 * acl_d->count;
456         if ((text = malloc(maxlen)) == NULL) {
457                 errno = ENOMEM;
458                 return NULL;
459         }
460
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;
471
472                 switch (ap->a_type) {
473                         /*
474                          * for debugging purposes it's probably more
475                          * useful to dump unknown tag types rather
476                          * than just returning an error
477                          */
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;
486
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;
494                                 }
495                         case SMB_ACL_USER_OBJ:
496                                 tag = "user";
497                                 break;
498
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;
506                                 }
507                         case SMB_ACL_GROUP_OBJ:
508                                 tag = "group";
509                                 break;
510
511                         case SMB_ACL_OTHER:
512                                 tag = "other";
513                                 break;
514
515                         case SMB_ACL_MASK:
516                                 tag = "mask";
517                                 break;
518
519                 }
520
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';
525
526                 /*          <tag>      :  <qualifier>   :  rwx \n  \0 */
527                 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
528
529                 /*
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
534                  */
535                 if ((len + nbytes) > maxlen) {
536                         char *oldtext = text;
537
538                         maxlen += nbytes + 20 * (acl_d->count - i);
539
540                         if ((text = realloc(oldtext, maxlen)) == NULL) {
541                                 free(oldtext);
542                                 errno = ENOMEM;
543                                 return NULL;
544                         }
545                 }
546
547                 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
548                 len += nbytes - 1;
549         }
550
551         if (len_p)
552                 *len_p = len;
553
554         return text;
555 }
556
557 SMB_ACL_T sys_acl_init(int count)
558 {
559         SMB_ACL_T       a;
560
561         if (count < 0) {
562                 errno = EINVAL;
563                 return NULL;
564         }
565
566         /*
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
571          */
572         if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) {
573                 errno = ENOMEM;
574                 return NULL;
575         }
576
577         a->size = count + 1;
578         a->count = 0;
579         a->next = -1;
580
581         return a;
582 }
583
584
585 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
586 {
587         SMB_ACL_T       acl_d;
588         SMB_ACL_ENTRY_T entry_d;
589
590         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
591                 errno = EINVAL;
592                 return -1;
593         }
594
595         if (acl_d->count >= acl_d->size) {
596                 errno = ENOSPC;
597                 return -1;
598         }
599
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;
605
606         return 0;
607 }
608
609 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
610 {
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;
623         }
624
625         return 0;
626 }
627
628 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
629 {
630         if (entry_d->a_type != SMB_ACL_GROUP
631             && entry_d->a_type != SMB_ACL_USER) {
632                 errno = EINVAL;
633                 return -1;
634         }
635
636         entry_d->a_id = *((id_t *)qual_p);
637
638         return 0;
639 }
640
641 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
642 {
643         if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
644                 return EINVAL;
645         }
646
647         entry_d->a_perm = *permset_d;
648
649         return 0;
650 }
651
652 int sys_acl_valid(SMB_ACL_T acl_d)
653 {
654         if (aclsort(acl_d->count, 1, acl_d->acl) != 0) {
655                 errno = EINVAL;
656                 return -1;
657         }
658
659         return 0;
660 }
661
662 int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
663 {
664         struct stat     s;
665         struct acl      *acl_p;
666         int             acl_count;
667         struct acl      *acl_buf        = NULL;
668         int             ret;
669
670         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
671                 errno = EINVAL;
672                 return -1;
673         }
674
675         if (stat(name, &s) != 0) {
676                 return -1;
677         }
678
679         acl_p           = &acl_d->acl[0];
680         acl_count       = acl_d->count;
681
682         /*
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)
686          */
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;
692
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);
697
698                 } else {
699                         def_acl = acl_d;
700                         acc_acl = 
701                         tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
702                 }
703
704                 if (tmp_acl == NULL) {
705                         return -1;
706                 }
707
708                 /*
709                  * allocate a temporary buffer for the complete ACL
710                  */
711                 acl_count       = acc_acl->count + def_acl->count;
712                 acl_p           =
713                 acl_buf         = malloc(acl_count * sizeof(acl_buf[0]));
714
715                 if (acl_buf == NULL) {
716                         sys_acl_free_acl(tmp_acl);
717                         errno = ENOMEM;
718                         return -1;
719                 }
720
721                 /*
722                  * copy the access control and default entries into the buffer
723                  */
724                 memcpy(&acl_buf[0], &acc_acl->acl[0],
725                         acc_acl->count * sizeof(acl_buf[0]));
726
727                 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
728                         def_acl->count * sizeof(acl_buf[0]));
729
730                 /*
731                  * set the ACL_DEFAULT flag on the default entries
732                  */
733                 for (i = acc_acl->count; i < acl_count; i++) {
734                         acl_buf[i].a_type |= ACL_DEFAULT;
735                 }
736
737                 sys_acl_free_acl(tmp_acl);
738
739         } else if (type != SMB_ACL_TYPE_ACCESS) {
740                 errno = EINVAL;
741                 return -1;
742         }
743
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);
749         }
750
751         if (acl_buf) {
752                 free(acl_buf);
753         }
754
755         return ret;
756 }
757
758 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
759 {
760         if (aclsort(acl_d->count, 1, acl_d->acl) != 0) {
761                 errno = EINVAL;
762                 return -1;
763         }
764
765         return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
766 }
767
768 int sys_acl_free_text(char *text)
769 {
770         free(text);
771         return 0;
772 }
773
774 int sys_acl_free_acl(SMB_ACL_T acl_d) 
775 {
776         free(acl_d);
777         return 0;
778 }
779
780 int sys_acl_free_qualifier(void *qual) 
781 {
782         return 0;
783 }
784
785 #elif defined(HAVE_IRIX_ACLS)
786
787 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
788 {
789         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
790                 errno = EINVAL;
791                 return -1;
792         }
793
794         if (entry_p == NULL) {
795                 errno = EINVAL;
796                 return -1;
797         }
798
799         if (entry_id == SMB_ACL_FIRST_ENTRY) {
800                 acl_d->next = 0;
801         }
802
803         if (acl_d->next < 0) {
804                 errno = EINVAL;
805                 return -1;
806         }
807
808         if (acl_d->next >= acl_d->aclp->acl_cnt) {
809                 return 0;
810         }
811
812         *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
813
814         return 1;
815 }
816
817 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
818 {
819         *type_p = entry_d->ae_tag;
820
821         return 0;
822 }
823
824 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
825 {
826         *permset_p = entry_d;
827
828         return 0;
829 }
830
831 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
832 {
833         if (entry_d->ae_tag != SMB_ACL_USER
834             && entry_d->ae_tag != SMB_ACL_GROUP) {
835                 errno = EINVAL;
836                 return NULL;
837         }
838
839         return &entry_d->ae_id;
840 }
841
842 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
843 {
844         SMB_ACL_T       a;
845
846         if ((a = malloc(sizeof(*a))) == NULL) {
847                 errno = ENOMEM;
848                 return NULL;
849         }
850         if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
851                 free(a);
852                 return NULL;
853         }
854         a->next = -1;
855         a->freeaclp = True;
856         return a;
857 }
858
859 SMB_ACL_T sys_acl_get_fd(int fd)
860 {
861         SMB_ACL_T       a;
862
863         if ((a = malloc(sizeof(*a))) == NULL) {
864                 errno = ENOMEM;
865                 return NULL;
866         }
867         if ((a->aclp = acl_get_fd(fd)) == NULL) {
868                 free(a);
869                 return NULL;
870         }
871         a->next = -1;
872         a->freeaclp = True;
873         return a;
874 }
875
876 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
877 {
878         permset_d->ae_perm = 0;
879
880         return 0;
881 }
882
883 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
884 {
885         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
886             && perm != SMB_ACL_EXECUTE) {
887                 errno = EINVAL;
888                 return -1;
889         }
890
891         if (permset_d == NULL) {
892                 errno = EINVAL;
893                 return -1;
894         }
895
896         permset_d->ae_perm |= perm;
897
898         return 0;
899 }
900
901 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
902 {
903         return permset_d->ae_perm & perm;
904 }
905
906 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
907 {
908         return acl_to_text(acl_d->aclp, len_p);
909 }
910
911 SMB_ACL_T sys_acl_init(int count)
912 {
913         SMB_ACL_T       a;
914
915         if (count < 0) {
916                 errno = EINVAL;
917                 return NULL;
918         }
919
920         if ((a = malloc(sizeof(*a) + sizeof(struct acl))) == NULL) {
921                 errno = ENOMEM;
922                 return NULL;
923         }
924
925         a->next = -1;
926         a->freeaclp = False;
927         a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
928         a->aclp->acl_cnt = 0;
929
930         return a;
931 }
932
933
934 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
935 {
936         SMB_ACL_T       acl_d;
937         SMB_ACL_ENTRY_T entry_d;
938
939         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
940                 errno = EINVAL;
941                 return -1;
942         }
943
944         if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
945                 errno = ENOSPC;
946                 return -1;
947         }
948
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;
954
955         return 0;
956 }
957
958 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
959 {
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;
972         }
973
974         return 0;
975 }
976
977 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
978 {
979         if (entry_d->ae_tag != SMB_ACL_GROUP
980             && entry_d->ae_tag != SMB_ACL_USER) {
981                 errno = EINVAL;
982                 return -1;
983         }
984
985         entry_d->ae_id = *((id_t *)qual_p);
986
987         return 0;
988 }
989
990 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
991 {
992         if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
993                 return EINVAL;
994         }
995
996         entry_d->ae_perm = permset_d->ae_perm;
997
998         return 0;
999 }
1000
1001 int sys_acl_valid(SMB_ACL_T acl_d)
1002 {
1003         return acl_valid(acl_d->aclp);
1004 }
1005
1006 int sys_acl_set_file(char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1007 {
1008         return acl_set_file(name, type, acl_d->aclp);
1009 }
1010
1011 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1012 {
1013         return acl_set_fd(fd, acl_d->aclp);
1014 }
1015
1016 int sys_acl_free_text(char *text)
1017 {
1018         return acl_free(text);
1019 }
1020
1021 int sys_acl_free_acl(SMB_ACL_T acl_d) 
1022 {
1023         if (acl_d->freeaclp) {
1024                 acl_free(acl_d->aclp);
1025         }
1026         acl_free(acl_d);
1027         return 0;
1028 }
1029
1030 int sys_acl_free_qualifier(void *qual) 
1031 {
1032         return 0;
1033 }
1034
1035 #elif defined(HAVE_XFS_ACLS)
1036 /* For Linux SGI/XFS Filesystems    
1037  * contributed by J Trostel, Connex 
1038  *                                  */
1039
1040 /* based on the implementation for Solaris by Toomas Soome.. which is 
1041  * based on the implementation  by Micheal Davidson for Unixware...
1042  *
1043  * Linux XFS is a 'work-in-progress'
1044  * This interface may change...  
1045  * You've been warned ;->           */
1046
1047 /* First, do the identity mapping */
1048
1049 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1050 {
1051         if( acl_get_entry( the_acl, entry_id, entry_p) >= 0) {
1052                 return 1;
1053         }
1054         else {
1055                 return -1;
1056         }
1057 }
1058
1059 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1060 {
1061         return acl_get_file( path_p, type);
1062 }
1063
1064 SMB_ACL_T sys_acl_get_fd(int fd)
1065 {
1066         return acl_get_fd(fd);
1067 }
1068
1069 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
1070 {
1071         return acl_to_text( the_acl, plen);
1072 }
1073
1074 int sys_acl_valid( SMB_ACL_T theacl )
1075 {
1076         return acl_valid(theacl);
1077 }
1078
1079 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1080 {
1081         return acl_set_file(name, acltype, theacl);
1082 }
1083
1084 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
1085 {
1086         return acl_set_fd(fd, theacl);
1087 }
1088
1089 /* Now the functions I need to define for XFS */
1090
1091 int sys_acl_create_entry( SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1092 {
1093         acl_t acl, newacl;
1094         acl_entry_t ace;
1095         int cnt;
1096
1097         acl = *acl_p;
1098         ace = *entry_p;
1099
1100         if((*acl_p == NULL) || (ace == NULL)){
1101                 errno = EINVAL;
1102                 return -1;
1103         }
1104         
1105         cnt = acl->acl_cnt;     
1106         if( (cnt + 1) > ACL_MAX_ENTRIES  ){
1107                 errno = ENOSPC;
1108                 return -1;
1109         }
1110
1111         newacl = (acl_t)malloc(sizeof(struct acl));
1112         if(newacl == NULL){
1113                 errno = ENOMEM;
1114                 return -1;
1115         }
1116         
1117         *newacl = *acl;
1118         newacl->acl_entry[cnt] = *ace;
1119         newacl->acl_cnt = cnt + 1;
1120
1121         acl_free(*acl_p);
1122         *acl_p = newacl;
1123         *entry_p = &newacl->acl_entry[cnt];
1124         return 0;
1125 }
1126
1127
1128 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1129 {
1130         *tag_type_p = entry_d->ae_tag;
1131         return 0;
1132 }
1133
1134 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1135 {
1136         *permset_p = &entry_d->ae_perm;
1137         return 0;
1138 }
1139
1140 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1141 {
1142         if (entry_d->ae_tag != SMB_ACL_USER
1143                 && entry_d->ae_tag != SMB_ACL_GROUP) {
1144                 errno = EINVAL;
1145                 return NULL;
1146         }       
1147         return &entry_d->ae_id;
1148 }
1149
1150 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1151 {
1152         *permset = 0;
1153         return 0;
1154 }
1155
1156 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1157 {
1158         return (*permset & perm);
1159 }
1160
1161 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1162 {
1163
1164         /* TO DO: Add in ALL possible permissions here */
1165         /* TO DO: Include extended ones!! */
1166
1167         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE && perm != SMB_ACL_EXECUTE) {
1168                 errno = EINVAL;
1169                 return -1;
1170         }
1171         
1172         if(permset == NULL) {
1173                 errno = EINVAL;
1174                 return -1;
1175         }
1176         
1177         *permset |= perm;
1178         
1179         return 0;
1180 }
1181
1182 SMB_ACL_T sys_acl_init( int count)
1183 {
1184         SMB_ACL_T a;
1185         if((count > ACL_MAX_ENTRIES) || (count < 0)) {
1186                 errno = EINVAL;
1187                 return NULL;
1188         }
1189         else {
1190                 a = (struct acl *)malloc(sizeof(struct acl)); /* where is this memory freed? */
1191                 a->acl_cnt = 0;
1192                 return a;
1193         }
1194 }
1195
1196 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1197 {
1198         
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;
1211         }
1212         return 0;
1213 }
1214
1215 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry_d, void *qual_p)
1216 {
1217         if(entry_d->ae_tag != SMB_ACL_GROUP &&
1218                 entry_d->ae_tag != SMB_ACL_USER) {
1219                 errno = EINVAL;
1220                 return -1;
1221         }
1222         
1223         entry_d->ae_id = *((uid_t *)qual_p);
1224
1225         return 0;
1226 }
1227
1228 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1229 {
1230   /* TO DO: expand to extended permissions eventually! */
1231
1232         if(*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1233                 return EINVAL;
1234         }
1235
1236         return 0;
1237 }
1238
1239 int sys_acl_free_text(char *text)
1240 {
1241         return acl_free(text);
1242 }
1243
1244 int sys_acl_free_acl(SMB_ACL_T the_acl) 
1245 {
1246         return acl_free(the_acl);
1247 }
1248
1249 int sys_acl_free_qualifier(void *qual) 
1250 {
1251         return 0;
1252 }
1253
1254 #elif defined(HAVE_AIX_ACLS)
1255
1256 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1257
1258 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1259 {
1260         struct acl_entry_link *link;
1261         struct new_acl_entry *entry;
1262         int keep_going;
1263
1264         DEBUG(10,("This is the count: %d\n",theacl->count));
1265
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);
1271
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.            */
1276
1277         for(keep_going = 0; keep_going < theacl->count; keep_going++)
1278                 link = link->nextp;
1279
1280         entry = *entry_p =  link->entryp;
1281
1282         DEBUG(10,("*entry_p is %d\n",entry_p));
1283         DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1284
1285         /* Increment count */
1286         theacl->count++;
1287         if(link->nextp == NULL)
1288                 theacl->count = -1;
1289
1290         return(1);
1291 }
1292
1293 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1294 {
1295         /* Initialize tag type */
1296
1297         *tag_type_p = -1;
1298         DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1299
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;
1309
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;
1315  
1316         default:
1317                 return(-1);
1318         }
1319
1320         return(0);
1321 }
1322
1323 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1324 {
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);
1333
1334         DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
1335         return(0);
1336 }
1337
1338 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1339 {
1340         return(entry_d->ace_id->id_data);
1341 }
1342
1343 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1344 {
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;
1354
1355         /* Get the acl using statacl */
1356  
1357         DEBUG(10,("Entering sys_acl_get_file\n"));
1358         DEBUG(10,("path_p is %s\n",path_p));
1359
1360         file_acl = (struct acl *)malloc(BUFSIZ);
1361  
1362         if(file_acl == NULL) {
1363                 errno=ENOMEM;
1364                 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1365                 return(NULL);
1366         }
1367
1368         memset(file_acl,0,BUFSIZ);
1369
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);
1375         }
1376
1377         DEBUG(10,("Got facl and returned it\n"));
1378
1379         /* Point to the first acl entry in the acl */
1380         acl_entry =  file_acl->acl_ext;
1381
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.                                          */
1386
1387         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1388         if(acl_entry_link_head == NULL)
1389                 return(NULL);
1390
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);
1397         }
1398
1399         DEBUG(10,("acl_entry is %d\n",acl_entry));
1400         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1401
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     */
1406
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;
1417                         }
1418
1419                         idp = acl_entry->ace_id;
1420
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.                  */
1424
1425                         if(acl_entry_link_head->count != 0) {
1426                                 acl_entry_link->nextp = (struct acl_entry_link *)
1427                                                                                         malloc(sizeof(struct acl_entry_link));
1428
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);
1434                                 }
1435
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);
1444                                 }
1445                                 acl_entry_link->nextp = NULL;
1446                         }
1447
1448                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1449
1450                         /* Don't really need this since all types are going *
1451                          * to be specified but, it's better than leaving it 0 */
1452
1453                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1454  
1455                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1456  
1457                         memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
1458
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.                  */
1462
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);
1481                         }
1482
1483                         DEBUG(10,("acl_entry = %d\n",acl_entry));
1484                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1485  
1486                         acl_entry = acl_nxt(acl_entry);
1487                 }
1488         } /* end of if enabled */
1489
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.     */
1493
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);
1503                         }
1504
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);
1513                         }
1514                 }
1515
1516                 acl_entry_link->nextp = NULL;
1517
1518                 new_acl_entry = acl_entry_link->entryp;
1519                 idp = new_acl_entry->ace_id;
1520
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));
1526
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;
1532
1533                 case 3:
1534                         new_acl_entry->ace_access = file_acl->o_access << 6;
1535                         idp->id_type = SMB_ACL_OTHER;
1536                         break;
1537  
1538                 case 1:
1539                         new_acl_entry->ace_access = file_acl->u_access << 6;
1540                         idp->id_type = SMB_ACL_USER_OBJ;
1541                         break;
1542  
1543                 default:
1544                         return(NULL);
1545
1546                 }
1547
1548                 acl_entry_link_head->count++;
1549                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1550         }
1551
1552         acl_entry_link_head->count = 0;
1553         free(file_acl);
1554
1555         return(acl_entry_link_head);
1556 }
1557
1558 SMB_ACL_T sys_acl_get_fd(int fd)
1559 {
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;
1569
1570         /* Get the acl using fstatacl */
1571    
1572         DEBUG(10,("Entering sys_acl_get_fd\n"));
1573         DEBUG(10,("fd is %d\n",fd));
1574         file_acl = (struct acl *)malloc(BUFSIZ);
1575
1576         if(file_acl == NULL) {
1577                 errno=ENOMEM;
1578                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1579                 return(NULL);
1580         }
1581
1582         memset(file_acl,0,BUFSIZ);
1583
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);
1589         }
1590
1591         DEBUG(10,("Got facl and returned it\n"));
1592
1593         /* Point to the first acl entry in the acl */
1594
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.                                        */
1600
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);
1605         }
1606
1607         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1608
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);
1614         }
1615
1616         DEBUG(10,("acl_entry is %d\n",acl_entry));
1617         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1618  
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     */
1623  
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 */
1629
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;
1635                         }
1636
1637                         idp = acl_entry->ace_id;
1638  
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.                 */
1642
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);
1650                                 }
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);
1659                                 }
1660
1661                                 acl_entry_link->nextp = NULL;
1662                         }
1663
1664                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1665
1666                         /* Don't really need this since all types are going *
1667                          * to be specified but, it's better than leaving it 0 */
1668
1669                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1670                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1671
1672                         memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
1673
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.                  */
1677
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);
1696                         }
1697
1698                         DEBUG(10,("acl_entry = %d\n",acl_entry));
1699                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1700  
1701                         acl_entry = acl_nxt(acl_entry);
1702                 }
1703         } /* end of if enabled */
1704
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.     */
1708
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);
1718                         }
1719
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));
1723
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);
1729                         }
1730                 }
1731
1732                 acl_entry_link->nextp = NULL;
1733  
1734                 new_acl_entry = acl_entry_link->entryp;
1735                 idp = new_acl_entry->ace_id;
1736  
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));
1742  
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;
1748  
1749                 case 3:
1750                         new_acl_entry->ace_access = file_acl->o_access << 6;
1751                         idp->id_type = SMB_ACL_OTHER;
1752                         break;
1753  
1754                 case 1:
1755                         new_acl_entry->ace_access = file_acl->u_access << 6;
1756                         idp->id_type = SMB_ACL_USER_OBJ;
1757                         break;
1758  
1759                 default:
1760                         return(NULL);
1761                 }
1762  
1763                 acl_entry_link_head->count++;
1764                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1765         }
1766
1767         acl_entry_link_head->count = 0;
1768         free(file_acl);
1769  
1770         return(acl_entry_link_head);
1771 }
1772
1773 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1774 {
1775         *permset = *permset & ~0777;
1776         return(0);
1777 }
1778
1779 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1780 {
1781         if((perm != 0) &&
1782                         (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
1783                 return(-1);
1784
1785         *permset |= perm;
1786         DEBUG(10,("This is the permset now: %d\n",*permset));
1787         return(0);
1788 }
1789
1790 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
1791 {
1792         return(NULL);
1793 }
1794
1795 SMB_ACL_T sys_acl_init( int count)
1796 {
1797         struct acl_entry_link *theacl = NULL;
1798  
1799         DEBUG(10,("Entering sys_acl_init\n"));
1800
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);
1806         }
1807
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);
1814 }
1815
1816 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1817 {
1818         struct acl_entry_link *theacl;
1819         struct acl_entry_link *acl_entryp;
1820         struct acl_entry_link *temp_entry;
1821         int counting;
1822
1823         DEBUG(10,("Entering the sys_acl_create_entry\n"));
1824
1825         theacl = acl_entryp = *pacl;
1826
1827         /* Get to the end of the acl before adding entry */
1828
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;
1833         }
1834
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);
1841                 }
1842
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));
1846         }
1847
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);
1853         }
1854
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);
1863 }
1864
1865 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1866 {
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"));
1871 }
1872
1873 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
1874 {
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);
1879 }
1880
1881 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1882 {
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);
1889
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);
1894 }
1895
1896 int sys_acl_valid( SMB_ACL_T theacl )
1897 {
1898         int user_obj = 0;
1899         int group_obj = 0;
1900         int other_obj = 0;
1901         struct acl_entry_link *acl_entry;
1902
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);
1907         }
1908
1909         DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
1910  
1911         if(user_obj != 1 || group_obj != 1 || other_obj != 1)
1912                 return(-1); 
1913
1914         return(0);
1915 }
1916
1917 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1918 {
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;
1929
1930         DEBUG(10,("Entering sys_acl_set_file\n"));
1931         DEBUG(10,("File name is %s\n",name));
1932  
1933         /* AIX has no default ACL */
1934         if(acltype == SMB_ACL_TYPE_DEFAULT)
1935                 return(0);
1936
1937         acl_length = BUFSIZ;
1938         file_acl = (struct acl *)malloc(BUFSIZ);
1939
1940         if(file_acl == NULL) {
1941                 errno = ENOMEM;
1942                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
1943                 return(-1);
1944         }
1945
1946         memset(file_acl,0,BUFSIZ);
1947
1948         file_acl->acl_len = ACL_SIZ;
1949         file_acl->acl_mode = S_IXACL;
1950
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;
1954
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;
1967                 }
1968
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);
1977                         }  
1978
1979                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
1980                         free(file_acl);
1981                         file_acl = file_acl_temp;
1982                 }
1983
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;
1988  
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; */
1992
1993                 acl_entry->ace_type = ACC_SPECIFY;
1994  
1995                 ace_id = acl_entry->ace_id;
1996  
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));
2002         }
2003
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);
2010 }
2011
2012 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2013 {
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;
2023  
2024         DEBUG(10,("Entering sys_acl_set_fd\n"));
2025         acl_length = BUFSIZ;
2026         file_acl = (struct acl *)malloc(BUFSIZ);
2027
2028         if(file_acl == NULL) {
2029                 errno = ENOMEM;
2030                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2031                 return(-1);
2032         }
2033
2034         memset(file_acl,0,BUFSIZ);
2035  
2036         file_acl->acl_len = ACL_SIZ;
2037         file_acl->acl_mode = S_IXACL;
2038
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));
2043
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;
2056                 }
2057
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);
2066                         }
2067
2068                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2069                         free(file_acl);
2070                         file_acl = file_acl_temp;
2071                 }
2072
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;
2077  
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; */
2081  
2082                 acl_entry->ace_type = ACC_SPECIFY;
2083  
2084                 ace_id = acl_entry->ace_id;
2085  
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));
2091         }
2092  
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);
2099 }
2100
2101 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2102 {
2103         return(*permset & perm);
2104 }
2105
2106 int sys_acl_free_text(char *text)
2107 {
2108         return(0);
2109 }
2110
2111 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2112 {
2113         struct acl_entry_link *acl_entry_link;
2114
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);
2118         }
2119
2120         free(acl_entry_link->prevp->entryp);
2121         free(acl_entry_link->prevp);
2122         free(acl_entry_link->entryp);
2123         free(acl_entry_link);
2124  
2125         return(0);
2126 }
2127
2128 int sys_acl_free_qualifier(void *qual)
2129 {
2130         return(0);
2131 }
2132
2133 #else /* No ACLs. */
2134
2135 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2136 {
2137         errno = ENOSYS;
2138         return -1;
2139 }
2140
2141 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2142 {
2143         errno = ENOSYS;
2144         return -1;
2145 }
2146
2147 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2148 {
2149         errno = ENOSYS;
2150         return -1;
2151 }
2152
2153 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2154 {
2155         errno = ENOSYS;
2156         return NULL;
2157 }
2158
2159 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2160 {
2161         errno = ENOSYS;
2162         return (SMB_ACL_T)NULL;
2163 }
2164
2165 SMB_ACL_T sys_acl_get_fd(int fd)
2166 {
2167         errno = ENOSYS;
2168         return (SMB_ACL_T)NULL;
2169 }
2170
2171 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2172 {
2173         errno = ENOSYS;
2174         return -1;
2175 }
2176
2177 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2178 {
2179         errno = ENOSYS;
2180         return -1;
2181 }
2182
2183 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2184 {
2185         errno = ENOSYS;
2186         return (permset & perm) ? 1 : 0;
2187 }
2188
2189 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
2190 {
2191         errno = ENOSYS;
2192         return NULL;
2193 }
2194
2195 int sys_acl_free_text(char *text)
2196 {
2197         errno = ENOSYS;
2198         return -1;
2199 }
2200
2201 SMB_ACL_T sys_acl_init( int count)
2202 {
2203         errno = ENOSYS;
2204         return NULL;
2205 }
2206
2207 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2208 {
2209         errno = ENOSYS;
2210         return -1;
2211 }
2212
2213 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2214 {
2215         errno = ENOSYS;
2216         return -1;
2217 }
2218
2219 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2220 {
2221         errno = ENOSYS;
2222         return -1;
2223 }
2224
2225 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2226 {
2227         errno = ENOSYS;
2228         return -1;
2229 }
2230
2231 int sys_acl_valid( SMB_ACL_T theacl )
2232 {
2233         errno = ENOSYS;
2234         return -1;
2235 }
2236
2237 int sys_acl_set_file( char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2238 {
2239         errno = ENOSYS;
2240         return -1;
2241 }
2242
2243 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2244 {
2245         errno = ENOSYS;
2246         return -1;
2247 }
2248
2249 int sys_acl_free_acl(SMB_ACL_T the_acl) 
2250 {
2251         errno = ENOSYS;
2252         return -1;
2253 }
2254
2255 int sys_acl_free_qualifier(void *qual) 
2256 {
2257         errno = ENOSYS;
2258         return -1;
2259 }
2260
2261 #endif /* No ACLs. */