Added sys_acl_delete_def_file for UnixWare and Solaris from
[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) {
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_free_text(char *text)
1060 {
1061         return acl_free(text);
1062 }
1063
1064 int sys_acl_free_acl(SMB_ACL_T acl_d) 
1065 {
1066         if (acl_d->freeaclp) {
1067                 acl_free(acl_d->aclp);
1068         }
1069         acl_free(acl_d);
1070         return 0;
1071 }
1072
1073 int sys_acl_free_qualifier(void *qual) 
1074 {
1075         return 0;
1076 }
1077
1078 #elif defined(HAVE_XFS_ACLS)
1079 /* For Linux SGI/XFS Filesystems    
1080  * contributed by J Trostel, Connex 
1081  *                                  */
1082
1083 /* based on the implementation for Solaris by Toomas Soome.. which is 
1084  * based on the implementation  by Micheal Davidson for Unixware...
1085  *
1086  * Linux XFS is a 'work-in-progress'
1087  * This interface may change...  
1088  * You've been warned ;->           */
1089
1090 /* First, do the identity mapping */
1091
1092 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1093 {
1094         if( acl_get_entry( the_acl, entry_id, entry_p) >= 0) {
1095                 return 1;
1096         }
1097         else {
1098                 return -1;
1099         }
1100 }
1101
1102 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1103 {
1104         return acl_get_file( path_p, type);
1105 }
1106
1107 SMB_ACL_T sys_acl_get_fd(int fd)
1108 {
1109         return acl_get_fd(fd);
1110 }
1111
1112 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
1113 {
1114         return acl_to_text( the_acl, plen);
1115 }
1116
1117 int sys_acl_valid( SMB_ACL_T theacl )
1118 {
1119         return acl_valid(theacl);
1120 }
1121
1122 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1123 {
1124         return acl_set_file(name, acltype, theacl);
1125 }
1126
1127 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
1128 {
1129         return acl_set_fd(fd, theacl);
1130 }
1131
1132 /* Now the functions I need to define for XFS */
1133
1134 int sys_acl_create_entry( SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1135 {
1136         acl_t acl, newacl;
1137         acl_entry_t ace;
1138         int cnt;
1139
1140         acl = *acl_p;
1141         ace = *entry_p;
1142
1143         if((*acl_p == NULL) || (ace == NULL)){
1144                 errno = EINVAL;
1145                 return -1;
1146         }
1147         
1148         cnt = acl->acl_cnt;     
1149         if( (cnt + 1) > ACL_MAX_ENTRIES  ){
1150                 errno = ENOSPC;
1151                 return -1;
1152         }
1153
1154         newacl = (acl_t)malloc(sizeof(struct acl));
1155         if(newacl == NULL){
1156                 errno = ENOMEM;
1157                 return -1;
1158         }
1159         
1160         *newacl = *acl;
1161         newacl->acl_entry[cnt] = *ace;
1162         newacl->acl_cnt = cnt + 1;
1163
1164         acl_free(*acl_p);
1165         *acl_p = newacl;
1166         *entry_p = &newacl->acl_entry[cnt];
1167         return 0;
1168 }
1169
1170
1171 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1172 {
1173         *tag_type_p = entry_d->ae_tag;
1174         return 0;
1175 }
1176
1177 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1178 {
1179         *permset_p = &entry_d->ae_perm;
1180         return 0;
1181 }
1182
1183 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1184 {
1185         if (entry_d->ae_tag != SMB_ACL_USER
1186                 && entry_d->ae_tag != SMB_ACL_GROUP) {
1187                 errno = EINVAL;
1188                 return NULL;
1189         }       
1190         return &entry_d->ae_id;
1191 }
1192
1193 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1194 {
1195         *permset = 0;
1196         return 0;
1197 }
1198
1199 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1200 {
1201         return (*permset & perm);
1202 }
1203
1204 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1205 {
1206
1207         /* TO DO: Add in ALL possible permissions here */
1208         /* TO DO: Include extended ones!! */
1209
1210         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE && perm != SMB_ACL_EXECUTE) {
1211                 errno = EINVAL;
1212                 return -1;
1213         }
1214         
1215         if(permset == NULL) {
1216                 errno = EINVAL;
1217                 return -1;
1218         }
1219         
1220         *permset |= perm;
1221         
1222         return 0;
1223 }
1224
1225 SMB_ACL_T sys_acl_init( int count)
1226 {
1227         SMB_ACL_T a;
1228         if((count > ACL_MAX_ENTRIES) || (count < 0)) {
1229                 errno = EINVAL;
1230                 return NULL;
1231         }
1232         else {
1233                 a = (struct acl *)malloc(sizeof(struct acl)); /* where is this memory freed? */
1234                 a->acl_cnt = 0;
1235                 return a;
1236         }
1237 }
1238
1239 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1240 {
1241         
1242         switch (tag_type) {
1243                 case SMB_ACL_USER:
1244                 case SMB_ACL_USER_OBJ:
1245                 case SMB_ACL_GROUP:
1246                 case SMB_ACL_GROUP_OBJ:
1247                 case SMB_ACL_OTHER:
1248                 case SMB_ACL_MASK:
1249                         entry_d->ae_tag = tag_type;
1250                         break;
1251                 default:
1252                         errno = EINVAL;
1253                         return -1;
1254         }
1255         return 0;
1256 }
1257
1258 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry_d, void *qual_p)
1259 {
1260         if(entry_d->ae_tag != SMB_ACL_GROUP &&
1261                 entry_d->ae_tag != SMB_ACL_USER) {
1262                 errno = EINVAL;
1263                 return -1;
1264         }
1265         
1266         entry_d->ae_id = *((uid_t *)qual_p);
1267
1268         return 0;
1269 }
1270
1271 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1272 {
1273   /* TO DO: expand to extended permissions eventually! */
1274
1275         if(*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1276                 return EINVAL;
1277         }
1278
1279         return 0;
1280 }
1281
1282 int sys_acl_free_text(char *text)
1283 {
1284         return acl_free(text);
1285 }
1286
1287 int sys_acl_free_acl(SMB_ACL_T the_acl) 
1288 {
1289         return acl_free(the_acl);
1290 }
1291
1292 int sys_acl_free_qualifier(void *qual) 
1293 {
1294         return 0;
1295 }
1296
1297 #elif defined(HAVE_AIX_ACLS)
1298
1299 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1300
1301 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1302 {
1303         struct acl_entry_link *link;
1304         struct new_acl_entry *entry;
1305         int keep_going;
1306
1307         DEBUG(10,("This is the count: %d\n",theacl->count));
1308
1309         /* Check if count was previously set to -1. *
1310          * If it was, that means we reached the end *
1311          * of the acl last time.                    */
1312         if(theacl->count == -1)
1313                 return(0);
1314
1315         link = theacl;
1316         /* To get to the next acl, traverse linked list until index *
1317          * of acl matches the count we are keeping.  This count is  *
1318          * incremented each time we return an acl entry.            */
1319
1320         for(keep_going = 0; keep_going < theacl->count; keep_going++)
1321                 link = link->nextp;
1322
1323         entry = *entry_p =  link->entryp;
1324
1325         DEBUG(10,("*entry_p is %d\n",entry_p));
1326         DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1327
1328         /* Increment count */
1329         theacl->count++;
1330         if(link->nextp == NULL)
1331                 theacl->count = -1;
1332
1333         return(1);
1334 }
1335
1336 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1337 {
1338         /* Initialize tag type */
1339
1340         *tag_type_p = -1;
1341         DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1342
1343         /* Depending on what type of entry we have, *
1344          * return tag type.                         */
1345         switch(entry_d->ace_id->id_type) {
1346         case ACEID_USER:
1347                 *tag_type_p = SMB_ACL_USER;
1348                 break;
1349         case ACEID_GROUP:
1350                 *tag_type_p = SMB_ACL_GROUP;
1351                 break;
1352
1353         case SMB_ACL_USER_OBJ:
1354         case SMB_ACL_GROUP_OBJ:
1355         case SMB_ACL_OTHER:
1356                 *tag_type_p = entry_d->ace_id->id_type;
1357                 break;
1358  
1359         default:
1360                 return(-1);
1361         }
1362
1363         return(0);
1364 }
1365
1366 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1367 {
1368         DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
1369         *permset_p = &entry_d->ace_access;
1370         DEBUG(10,("**permset_p is %d\n",**permset_p));
1371         if(!(**permset_p & S_IXUSR) &&
1372                 !(**permset_p & S_IWUSR) &&
1373                 !(**permset_p & S_IRUSR) &&
1374                 (**permset_p != 0))
1375                         return(-1);
1376
1377         DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
1378         return(0);
1379 }
1380
1381 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1382 {
1383         return(entry_d->ace_id->id_data);
1384 }
1385
1386 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1387 {
1388         struct acl *file_acl = (struct acl *)NULL;
1389         struct acl_entry *acl_entry;
1390         struct new_acl_entry *new_acl_entry;
1391         struct ace_id *idp;
1392         struct acl_entry_link *acl_entry_link;
1393         struct acl_entry_link *acl_entry_link_head;
1394         int i;
1395         int rc = 0;
1396         uid_t user_id;
1397
1398         /* Get the acl using statacl */
1399  
1400         DEBUG(10,("Entering sys_acl_get_file\n"));
1401         DEBUG(10,("path_p is %s\n",path_p));
1402
1403         file_acl = (struct acl *)malloc(BUFSIZ);
1404  
1405         if(file_acl == NULL) {
1406                 errno=ENOMEM;
1407                 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1408                 return(NULL);
1409         }
1410
1411         memset(file_acl,0,BUFSIZ);
1412
1413         rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1414         if(rc == -1) {
1415                 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1416                 free(file_acl);
1417                 return(NULL);
1418         }
1419
1420         DEBUG(10,("Got facl and returned it\n"));
1421
1422         /* Point to the first acl entry in the acl */
1423         acl_entry =  file_acl->acl_ext;
1424
1425         /* Begin setting up the head of the linked list *
1426          * that will be used for the storing the acl    *
1427          * in a way that is useful for the posix_acls.c *
1428          * code.                                          */
1429
1430         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1431         if(acl_entry_link_head == NULL)
1432                 return(NULL);
1433
1434         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1435         if(acl_entry_link->entryp == NULL) {
1436                 free(file_acl);
1437                 errno = ENOMEM;
1438                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1439                 return(NULL);
1440         }
1441
1442         DEBUG(10,("acl_entry is %d\n",acl_entry));
1443         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1444
1445         /* Check if the extended acl bit is on.   *
1446          * If it isn't, do not show the           *
1447          * contents of the acl since AIX intends *
1448          * the extended info to remain unused     */
1449
1450         if(file_acl->acl_mode & S_IXACL){
1451                 /* while we are not pointing to the very end */
1452                 while(acl_entry < acl_last(file_acl)) {
1453                         /* before we malloc anything, make sure this is  */
1454                         /* a valid acl entry and one that we want to map */
1455                         idp = id_nxt(acl_entry->ace_id);
1456                         if((acl_entry->ace_type == ACC_SPECIFY ||
1457                                 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1458                                         acl_entry = acl_nxt(acl_entry);
1459                                         continue;
1460                         }
1461
1462                         idp = acl_entry->ace_id;
1463
1464                         /* Check if this is the first entry in the linked list. *
1465                          * The first entry needs to keep prevp pointing to NULL *
1466                          * and already has entryp allocated.                  */
1467
1468                         if(acl_entry_link_head->count != 0) {
1469                                 acl_entry_link->nextp = (struct acl_entry_link *)
1470                                                                                         malloc(sizeof(struct acl_entry_link));
1471
1472                                 if(acl_entry_link->nextp == NULL) {
1473                                         free(file_acl);
1474                                         errno = ENOMEM;
1475                                         DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1476                                         return(NULL);
1477                                 }
1478
1479                                 acl_entry_link->nextp->prevp = acl_entry_link;
1480                                 acl_entry_link = acl_entry_link->nextp;
1481                                 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1482                                 if(acl_entry_link->entryp == NULL) {
1483                                         free(file_acl);
1484                                         errno = ENOMEM;
1485                                         DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1486                                         return(NULL);
1487                                 }
1488                                 acl_entry_link->nextp = NULL;
1489                         }
1490
1491                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1492
1493                         /* Don't really need this since all types are going *
1494                          * to be specified but, it's better than leaving it 0 */
1495
1496                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1497  
1498                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1499  
1500                         memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
1501
1502                         /* The access in the acl entries must be left shifted by *
1503                          * three bites, because they will ultimately be compared *
1504                          * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
1505
1506                         switch(acl_entry->ace_type){
1507                         case ACC_PERMIT:
1508                         case ACC_SPECIFY:
1509                                 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1510                                 acl_entry_link->entryp->ace_access <<= 6;
1511                                 acl_entry_link_head->count++;
1512                                 break;
1513                         case ACC_DENY:
1514                                 /* Since there is no way to return a DENY acl entry *
1515                                  * change to PERMIT and then shift.                 */
1516                                 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1517                                 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1518                                 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1519                                 acl_entry_link->entryp->ace_access <<= 6;
1520                                 acl_entry_link_head->count++;
1521                                 break;
1522                         default:
1523                                 return(0);
1524                         }
1525
1526                         DEBUG(10,("acl_entry = %d\n",acl_entry));
1527                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1528  
1529                         acl_entry = acl_nxt(acl_entry);
1530                 }
1531         } /* end of if enabled */
1532
1533         /* Since owner, group, other acl entries are not *
1534          * part of the acl entries in an acl, they must  *
1535          * be dummied up to become part of the list.     */
1536
1537         for( i = 1; i < 4; i++) {
1538                 DEBUG(10,("i is %d\n",i));
1539                 if(acl_entry_link_head->count != 0) {
1540                         acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1541                         if(acl_entry_link->nextp == NULL) {
1542                                 free(file_acl);
1543                                 errno = ENOMEM;
1544                                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1545                                 return(NULL);
1546                         }
1547
1548                         acl_entry_link->nextp->prevp = acl_entry_link;
1549                         acl_entry_link = acl_entry_link->nextp;
1550                         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1551                         if(acl_entry_link->entryp == NULL) {
1552                                 free(file_acl);
1553                                 errno = ENOMEM;
1554                                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1555                                 return(NULL);
1556                         }
1557                 }
1558
1559                 acl_entry_link->nextp = NULL;
1560
1561                 new_acl_entry = acl_entry_link->entryp;
1562                 idp = new_acl_entry->ace_id;
1563
1564                 new_acl_entry->ace_len = sizeof(struct acl_entry);
1565                 new_acl_entry->ace_type = ACC_PERMIT;
1566                 idp->id_len = sizeof(struct ace_id);
1567                 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1568                 memset(idp->id_data,0,sizeof(uid_t));
1569
1570                 switch(i) {
1571                 case 2:
1572                         new_acl_entry->ace_access = file_acl->g_access << 6;
1573                         idp->id_type = SMB_ACL_GROUP_OBJ;
1574                         break;
1575
1576                 case 3:
1577                         new_acl_entry->ace_access = file_acl->o_access << 6;
1578                         idp->id_type = SMB_ACL_OTHER;
1579                         break;
1580  
1581                 case 1:
1582                         new_acl_entry->ace_access = file_acl->u_access << 6;
1583                         idp->id_type = SMB_ACL_USER_OBJ;
1584                         break;
1585  
1586                 default:
1587                         return(NULL);
1588
1589                 }
1590
1591                 acl_entry_link_head->count++;
1592                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1593         }
1594
1595         acl_entry_link_head->count = 0;
1596         free(file_acl);
1597
1598         return(acl_entry_link_head);
1599 }
1600
1601 SMB_ACL_T sys_acl_get_fd(int fd)
1602 {
1603         struct acl *file_acl = (struct acl *)NULL;
1604         struct acl_entry *acl_entry;
1605         struct new_acl_entry *new_acl_entry;
1606         struct ace_id *idp;
1607         struct acl_entry_link *acl_entry_link;
1608         struct acl_entry_link *acl_entry_link_head;
1609         int i;
1610         int rc = 0;
1611         uid_t user_id;
1612
1613         /* Get the acl using fstatacl */
1614    
1615         DEBUG(10,("Entering sys_acl_get_fd\n"));
1616         DEBUG(10,("fd is %d\n",fd));
1617         file_acl = (struct acl *)malloc(BUFSIZ);
1618
1619         if(file_acl == NULL) {
1620                 errno=ENOMEM;
1621                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1622                 return(NULL);
1623         }
1624
1625         memset(file_acl,0,BUFSIZ);
1626
1627         rc = fstatacl(fd,0,file_acl,BUFSIZ);
1628         if(rc == -1) {
1629                 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
1630                 free(file_acl);
1631                 return(NULL);
1632         }
1633
1634         DEBUG(10,("Got facl and returned it\n"));
1635
1636         /* Point to the first acl entry in the acl */
1637
1638         acl_entry =  file_acl->acl_ext;
1639         /* Begin setting up the head of the linked list *
1640          * that will be used for the storing the acl    *
1641          * in a way that is useful for the posix_acls.c *
1642          * code.                                        */
1643
1644         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1645         if(acl_entry_link_head == NULL){
1646                 free(file_acl);
1647                 return(NULL);
1648         }
1649
1650         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1651
1652         if(acl_entry_link->entryp == NULL) {
1653                 errno = ENOMEM;
1654                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1655                 free(file_acl);
1656                 return(NULL);
1657         }
1658
1659         DEBUG(10,("acl_entry is %d\n",acl_entry));
1660         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1661  
1662         /* Check if the extended acl bit is on.   *
1663          * If it isn't, do not show the           *
1664          * contents of the acl since AIX intends  *
1665          * the extended info to remain unused     */
1666  
1667         if(file_acl->acl_mode & S_IXACL){
1668                 /* while we are not pointing to the very end */
1669                 while(acl_entry < acl_last(file_acl)) {
1670                         /* before we malloc anything, make sure this is  */
1671                         /* a valid acl entry and one that we want to map */
1672
1673                         idp = id_nxt(acl_entry->ace_id);
1674                         if((acl_entry->ace_type == ACC_SPECIFY ||
1675                                 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1676                                         acl_entry = acl_nxt(acl_entry);
1677                                         continue;
1678                         }
1679
1680                         idp = acl_entry->ace_id;
1681  
1682                         /* Check if this is the first entry in the linked list. *
1683                          * The first entry needs to keep prevp pointing to NULL *
1684                          * and already has entryp allocated.                 */
1685
1686                         if(acl_entry_link_head->count != 0) {
1687                                 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1688                                 if(acl_entry_link->nextp == NULL) {
1689                                         errno = ENOMEM;
1690                                         DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1691                                         free(file_acl);
1692                                         return(NULL);
1693                                 }
1694                                 acl_entry_link->nextp->prevp = acl_entry_link;
1695                                 acl_entry_link = acl_entry_link->nextp;
1696                                 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1697                                 if(acl_entry_link->entryp == NULL) {
1698                                         errno = ENOMEM;
1699                                         DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1700                                         free(file_acl);
1701                                         return(NULL);
1702                                 }
1703
1704                                 acl_entry_link->nextp = NULL;
1705                         }
1706
1707                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1708
1709                         /* Don't really need this since all types are going *
1710                          * to be specified but, it's better than leaving it 0 */
1711
1712                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1713                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1714
1715                         memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
1716
1717                         /* The access in the acl entries must be left shifted by *
1718                          * three bites, because they will ultimately be compared *
1719                          * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
1720
1721                         switch(acl_entry->ace_type){
1722                         case ACC_PERMIT:
1723                         case ACC_SPECIFY:
1724                                 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1725                                 acl_entry_link->entryp->ace_access <<= 6;
1726                                 acl_entry_link_head->count++;
1727                                 break;
1728                         case ACC_DENY:
1729                                 /* Since there is no way to return a DENY acl entry *
1730                                  * change to PERMIT and then shift.                 */
1731                                 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1732                                 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1733                                 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1734                                 acl_entry_link->entryp->ace_access <<= 6;
1735                                 acl_entry_link_head->count++;
1736                                 break;
1737                         default:
1738                                 return(0);
1739                         }
1740
1741                         DEBUG(10,("acl_entry = %d\n",acl_entry));
1742                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1743  
1744                         acl_entry = acl_nxt(acl_entry);
1745                 }
1746         } /* end of if enabled */
1747
1748         /* Since owner, group, other acl entries are not *
1749          * part of the acl entries in an acl, they must  *
1750          * be dummied up to become part of the list.     */
1751
1752         for( i = 1; i < 4; i++) {
1753                 DEBUG(10,("i is %d\n",i));
1754                 if(acl_entry_link_head->count != 0){
1755                         acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1756                         if(acl_entry_link->nextp == NULL) {
1757                                 errno = ENOMEM;
1758                                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1759                                 free(file_acl);
1760                                 return(NULL);
1761                         }
1762
1763                         acl_entry_link->nextp->prevp = acl_entry_link;
1764                         acl_entry_link = acl_entry_link->nextp;
1765                         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1766
1767                         if(acl_entry_link->entryp == NULL) {
1768                                 free(file_acl);
1769                                 errno = ENOMEM;
1770                                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1771                                 return(NULL);
1772                         }
1773                 }
1774
1775                 acl_entry_link->nextp = NULL;
1776  
1777                 new_acl_entry = acl_entry_link->entryp;
1778                 idp = new_acl_entry->ace_id;
1779  
1780                 new_acl_entry->ace_len = sizeof(struct acl_entry);
1781                 new_acl_entry->ace_type = ACC_PERMIT;
1782                 idp->id_len = sizeof(struct ace_id);
1783                 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1784                 memset(idp->id_data,0,sizeof(uid_t));
1785  
1786                 switch(i) {
1787                 case 2:
1788                         new_acl_entry->ace_access = file_acl->g_access << 6;
1789                         idp->id_type = SMB_ACL_GROUP_OBJ;
1790                         break;
1791  
1792                 case 3:
1793                         new_acl_entry->ace_access = file_acl->o_access << 6;
1794                         idp->id_type = SMB_ACL_OTHER;
1795                         break;
1796  
1797                 case 1:
1798                         new_acl_entry->ace_access = file_acl->u_access << 6;
1799                         idp->id_type = SMB_ACL_USER_OBJ;
1800                         break;
1801  
1802                 default:
1803                         return(NULL);
1804                 }
1805  
1806                 acl_entry_link_head->count++;
1807                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1808         }
1809
1810         acl_entry_link_head->count = 0;
1811         free(file_acl);
1812  
1813         return(acl_entry_link_head);
1814 }
1815
1816 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1817 {
1818         *permset = *permset & ~0777;
1819         return(0);
1820 }
1821
1822 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1823 {
1824         if((perm != 0) &&
1825                         (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
1826                 return(-1);
1827
1828         *permset |= perm;
1829         DEBUG(10,("This is the permset now: %d\n",*permset));
1830         return(0);
1831 }
1832
1833 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
1834 {
1835         return(NULL);
1836 }
1837
1838 SMB_ACL_T sys_acl_init( int count)
1839 {
1840         struct acl_entry_link *theacl = NULL;
1841  
1842         DEBUG(10,("Entering sys_acl_init\n"));
1843
1844         theacl = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1845         if(theacl == NULL) {
1846                 errno = ENOMEM;
1847                 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
1848                 return(NULL);
1849         }
1850
1851         theacl->count = 0;
1852         theacl->nextp = NULL;
1853         theacl->prevp = NULL;
1854         theacl->entryp = NULL;
1855         DEBUG(10,("Exiting sys_acl_init\n"));
1856         return(theacl);
1857 }
1858
1859 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1860 {
1861         struct acl_entry_link *theacl;
1862         struct acl_entry_link *acl_entryp;
1863         struct acl_entry_link *temp_entry;
1864         int counting;
1865
1866         DEBUG(10,("Entering the sys_acl_create_entry\n"));
1867
1868         theacl = acl_entryp = *pacl;
1869
1870         /* Get to the end of the acl before adding entry */
1871
1872         for(counting=0; counting < theacl->count; counting++){
1873                 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
1874                 temp_entry = acl_entryp;
1875                 acl_entryp = acl_entryp->nextp;
1876         }
1877
1878         if(theacl->count != 0){
1879                 temp_entry->nextp = acl_entryp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1880                 if(acl_entryp == NULL) {
1881                         errno = ENOMEM;
1882                         DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
1883                         return(-1);
1884                 }
1885
1886                 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
1887                 acl_entryp->prevp = temp_entry;
1888                 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
1889         }
1890
1891         *pentry = acl_entryp->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1892         if(*pentry == NULL) {
1893                 errno = ENOMEM;
1894                 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
1895                 return(-1);
1896         }
1897
1898         memset(*pentry,0,sizeof(struct new_acl_entry));
1899         acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
1900         acl_entryp->entryp->ace_type = ACC_PERMIT;
1901         acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
1902         acl_entryp->nextp = NULL;
1903         theacl->count++;
1904         DEBUG(10,("Exiting sys_acl_create_entry\n"));
1905         return(0);
1906 }
1907
1908 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1909 {
1910         DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
1911         entry->ace_id->id_type = tagtype;
1912         DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
1913         DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
1914 }
1915
1916 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
1917 {
1918         DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
1919         memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
1920         DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
1921         return(0);
1922 }
1923
1924 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1925 {
1926         DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
1927         if(!(*permset & S_IXUSR) &&
1928                 !(*permset & S_IWUSR) &&
1929                 !(*permset & S_IRUSR) &&
1930                 (*permset != 0))
1931                         return(-1);
1932
1933         entry->ace_access = *permset;
1934         DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
1935         DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
1936         return(0);
1937 }
1938
1939 int sys_acl_valid( SMB_ACL_T theacl )
1940 {
1941         int user_obj = 0;
1942         int group_obj = 0;
1943         int other_obj = 0;
1944         struct acl_entry_link *acl_entry;
1945
1946         for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
1947                 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
1948                 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
1949                 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
1950         }
1951
1952         DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
1953  
1954         if(user_obj != 1 || group_obj != 1 || other_obj != 1)
1955                 return(-1); 
1956
1957         return(0);
1958 }
1959
1960 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1961 {
1962         struct acl_entry_link *acl_entry_link = NULL;
1963         struct acl *file_acl = NULL;
1964         struct acl *file_acl_temp = NULL;
1965         struct acl_entry *acl_entry = NULL;
1966         struct ace_id *ace_id = NULL;
1967         uint id_type;
1968         uint ace_access;
1969         uint user_id;
1970         uint acl_length;
1971         uint rc;
1972
1973         DEBUG(10,("Entering sys_acl_set_file\n"));
1974         DEBUG(10,("File name is %s\n",name));
1975  
1976         /* AIX has no default ACL */
1977         if(acltype == SMB_ACL_TYPE_DEFAULT)
1978                 return(0);
1979
1980         acl_length = BUFSIZ;
1981         file_acl = (struct acl *)malloc(BUFSIZ);
1982
1983         if(file_acl == NULL) {
1984                 errno = ENOMEM;
1985                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
1986                 return(-1);
1987         }
1988
1989         memset(file_acl,0,BUFSIZ);
1990
1991         file_acl->acl_len = ACL_SIZ;
1992         file_acl->acl_mode = S_IXACL;
1993
1994         for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
1995                 acl_entry_link->entryp->ace_access >>= 6;
1996                 id_type = acl_entry_link->entryp->ace_id->id_type;
1997
1998                 switch(id_type) {
1999                 case SMB_ACL_USER_OBJ:
2000                         file_acl->u_access = acl_entry_link->entryp->ace_access;
2001                         continue;
2002                 case SMB_ACL_GROUP_OBJ:
2003                         file_acl->g_access = acl_entry_link->entryp->ace_access;
2004                         continue;
2005                 case SMB_ACL_OTHER:
2006                         file_acl->o_access = acl_entry_link->entryp->ace_access;
2007                         continue;
2008                 case SMB_ACL_MASK:
2009                         continue;
2010                 }
2011
2012                 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2013                         acl_length += sizeof(struct acl_entry);
2014                         file_acl_temp = (struct acl *)malloc(acl_length);
2015                         if(file_acl_temp == NULL) {
2016                                 free(file_acl);
2017                                 errno = ENOMEM;
2018                                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2019                                 return(-1);
2020                         }  
2021
2022                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2023                         free(file_acl);
2024                         file_acl = file_acl_temp;
2025                 }
2026
2027                 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2028                 file_acl->acl_len += sizeof(struct acl_entry);
2029                 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2030                 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2031  
2032                 /* In order to use this, we'll need to wait until we can get denies */
2033                 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2034                 acl_entry->ace_type = ACC_SPECIFY; */
2035
2036                 acl_entry->ace_type = ACC_SPECIFY;
2037  
2038                 ace_id = acl_entry->ace_id;
2039  
2040                 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2041                 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2042                 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2043                 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2044                 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2045         }
2046
2047         rc = chacl(name,file_acl,file_acl->acl_len);
2048         DEBUG(10,("errno is %d\n",errno));
2049         DEBUG(10,("return code is %d\n",rc));
2050         free(file_acl);
2051         DEBUG(10,("Exiting the sys_acl_set_file\n"));
2052         return(rc);
2053 }
2054
2055 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2056 {
2057         struct acl_entry_link *acl_entry_link = NULL;
2058         struct acl *file_acl = NULL;
2059         struct acl *file_acl_temp = NULL;
2060         struct acl_entry *acl_entry = NULL;
2061         struct ace_id *ace_id = NULL;
2062         uint id_type;
2063         uint user_id;
2064         uint acl_length;
2065         uint rc;
2066  
2067         DEBUG(10,("Entering sys_acl_set_fd\n"));
2068         acl_length = BUFSIZ;
2069         file_acl = (struct acl *)malloc(BUFSIZ);
2070
2071         if(file_acl == NULL) {
2072                 errno = ENOMEM;
2073                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2074                 return(-1);
2075         }
2076
2077         memset(file_acl,0,BUFSIZ);
2078  
2079         file_acl->acl_len = ACL_SIZ;
2080         file_acl->acl_mode = S_IXACL;
2081
2082         for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2083                 acl_entry_link->entryp->ace_access >>= 6;
2084                 id_type = acl_entry_link->entryp->ace_id->id_type;
2085                 DEBUG(10,("The id_type is %d\n",id_type));
2086
2087                 switch(id_type) {
2088                 case SMB_ACL_USER_OBJ:
2089                         file_acl->u_access = acl_entry_link->entryp->ace_access;
2090                         continue;
2091                 case SMB_ACL_GROUP_OBJ:
2092                         file_acl->g_access = acl_entry_link->entryp->ace_access;
2093                         continue;
2094                 case SMB_ACL_OTHER:
2095                         file_acl->o_access = acl_entry_link->entryp->ace_access;
2096                         continue;
2097                 case SMB_ACL_MASK:
2098                         continue;
2099                 }
2100
2101                 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2102                         acl_length += sizeof(struct acl_entry);
2103                         file_acl_temp = (struct acl *)malloc(acl_length);
2104                         if(file_acl_temp == NULL) {
2105                                 free(file_acl);
2106                                 errno = ENOMEM;
2107                                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2108                                 return(-1);
2109                         }
2110
2111                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2112                         free(file_acl);
2113                         file_acl = file_acl_temp;
2114                 }
2115
2116                 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2117                 file_acl->acl_len += sizeof(struct acl_entry);
2118                 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2119                 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2120  
2121                 /* In order to use this, we'll need to wait until we can get denies */
2122                 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2123                         acl_entry->ace_type = ACC_SPECIFY; */
2124  
2125                 acl_entry->ace_type = ACC_SPECIFY;
2126  
2127                 ace_id = acl_entry->ace_id;
2128  
2129                 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2130                 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2131                 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2132                 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2133                 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2134         }
2135  
2136         rc = fchacl(fd,file_acl,file_acl->acl_len);
2137         DEBUG(10,("errno is %d\n",errno));
2138         DEBUG(10,("return code is %d\n",rc));
2139         free(file_acl);
2140         DEBUG(10,("Exiting sys_acl_set_fd\n"));
2141         return(rc);
2142 }
2143
2144 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2145 {
2146         return(*permset & perm);
2147 }
2148
2149 int sys_acl_free_text(char *text)
2150 {
2151         return(0);
2152 }
2153
2154 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2155 {
2156         struct acl_entry_link *acl_entry_link;
2157
2158         for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2159                 free(acl_entry_link->prevp->entryp);
2160                 free(acl_entry_link->prevp);
2161         }
2162
2163         free(acl_entry_link->prevp->entryp);
2164         free(acl_entry_link->prevp);
2165         free(acl_entry_link->entryp);
2166         free(acl_entry_link);
2167  
2168         return(0);
2169 }
2170
2171 int sys_acl_free_qualifier(void *qual)
2172 {
2173         return(0);
2174 }
2175
2176 #else /* No ACLs. */
2177
2178 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2179 {
2180         errno = ENOSYS;
2181         return -1;
2182 }
2183
2184 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2185 {
2186         errno = ENOSYS;
2187         return -1;
2188 }
2189
2190 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2191 {
2192         errno = ENOSYS;
2193         return -1;
2194 }
2195
2196 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2197 {
2198         errno = ENOSYS;
2199         return NULL;
2200 }
2201
2202 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2203 {
2204         errno = ENOSYS;
2205         return (SMB_ACL_T)NULL;
2206 }
2207
2208 SMB_ACL_T sys_acl_get_fd(int fd)
2209 {
2210         errno = ENOSYS;
2211         return (SMB_ACL_T)NULL;
2212 }
2213
2214 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2215 {
2216         errno = ENOSYS;
2217         return -1;
2218 }
2219
2220 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2221 {
2222         errno = ENOSYS;
2223         return -1;
2224 }
2225
2226 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2227 {
2228         errno = ENOSYS;
2229         return (permset & perm) ? 1 : 0;
2230 }
2231
2232 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
2233 {
2234         errno = ENOSYS;
2235         return NULL;
2236 }
2237
2238 int sys_acl_free_text(char *text)
2239 {
2240         errno = ENOSYS;
2241         return -1;
2242 }
2243
2244 SMB_ACL_T sys_acl_init( int count)
2245 {
2246         errno = ENOSYS;
2247         return NULL;
2248 }
2249
2250 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2251 {
2252         errno = ENOSYS;
2253         return -1;
2254 }
2255
2256 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2257 {
2258         errno = ENOSYS;
2259         return -1;
2260 }
2261
2262 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2263 {
2264         errno = ENOSYS;
2265         return -1;
2266 }
2267
2268 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2269 {
2270         errno = ENOSYS;
2271         return -1;
2272 }
2273
2274 int sys_acl_valid( SMB_ACL_T theacl )
2275 {
2276         errno = ENOSYS;
2277         return -1;
2278 }
2279
2280 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2281 {
2282         errno = ENOSYS;
2283         return -1;
2284 }
2285
2286 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2287 {
2288         errno = ENOSYS;
2289         return -1;
2290 }
2291
2292 int sys_acl_delete_def_file(const char *name)
2293 {
2294         errno = ENOSYS;
2295         return -1;
2296 }
2297
2298 int sys_acl_free_acl(SMB_ACL_T the_acl) 
2299 {
2300         errno = ENOSYS;
2301         return -1;
2302 }
2303
2304 int sys_acl_free_qualifier(void *qual) 
2305 {
2306         errno = ENOSYS;
2307         return -1;
2308 }
2309
2310 #endif /* No ACLs. */