Decided against the last change.
[rsync/rsync.git] / lib / sysacls.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Based on the Samba ACL support code.
4    Copyright (C) Jeremy Allison 2000.
5
6    The permission functions have been changed to get/set all bits via
7    one call.  Some functions that rsync doesn't need were also removed.
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "rsync.h"
25 #include "sysacls.h"
26
27 #ifdef SUPPORT_ACLS
28
29 #ifdef DEBUG
30 #undef DEBUG
31 #endif
32 #define DEBUG(x,y)
33
34 void SAFE_FREE(void *mem)
35 {
36         if (mem)
37                 free(mem);
38 }
39
40 /*
41  This file wraps all differing system ACL interfaces into a consistent
42  one based on the POSIX interface. It also returns the correct errors
43  for older UNIX systems that don't support ACLs.
44
45  The interfaces that each ACL implementation must support are as follows :
46
47  int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
48  int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
49  int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
50  void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
51  SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
52  SMB_ACL_T sys_acl_get_fd(int fd)
53  SMB_ACL_T sys_acl_init( int count)
54  int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
55  int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
56  int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
57  int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
58  int sys_acl_valid( SMB_ACL_T theacl )
59  int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
60  int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
61  int sys_acl_delete_def_file(const char *path)
62
63  The generic POSIX free is the following call. We split this into
64  several different free functions as we may need to add tag info
65  to structures when emulating the POSIX interface.
66
67  int sys_acl_free( void *obj_p)
68
69  The calls we actually use are :
70
71  int sys_acl_free_acl(SMB_ACL_T posix_acl)
72  int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
73
74 */
75
76 #if defined(HAVE_POSIX_ACLS)
77
78 /* Identity mapping - easy. */
79
80 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
81 {
82         return acl_get_entry( the_acl, entry_id, entry_p);
83 }
84
85 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
86 {
87         return acl_get_tag_type( entry_d, tag_type_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 #if 0
101 SMB_ACL_T sys_acl_get_fd(int fd)
102 {
103         return acl_get_fd(fd);
104 }
105 #endif
106
107 #if defined(HAVE_ACL_GET_PERM_NP)
108 #define acl_get_perm(p, b) acl_get_perm_np(p, b)
109 #endif
110
111 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
112 {
113         SMB_ACL_PERMSET_T permset;
114         int rc;
115         if ((rc = acl_get_permset(entry_d, &permset)) != 0)
116                 return rc;
117         *bits = (acl_get_perm(permset, ACL_READ) ? 4 : 0)
118               | (acl_get_perm(permset, ACL_WRITE) ? 2 : 0)
119               | (acl_get_perm(permset, ACL_EXECUTE) ? 1 : 0);
120         return 0;
121 }
122
123 SMB_ACL_T sys_acl_init( int count)
124 {
125         return acl_init(count);
126 }
127
128 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
129 {
130         return acl_create_entry(pacl, pentry);
131 }
132
133 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
134 {
135         return acl_set_tag_type(entry, tagtype);
136 }
137
138 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
139 {
140         return acl_set_qualifier(entry, qual);
141 }
142
143 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
144 {
145         SMB_ACL_PERMSET_T permset;
146         int rc;
147         if ((rc = acl_get_permset(entry, &permset)) != 0)
148                 return rc;
149         acl_clear_perms(permset);
150         if (bits & 4)
151                 acl_add_perm(permset, ACL_READ);
152         if (bits & 2)
153                 acl_add_perm(permset, ACL_WRITE);
154         if (bits & 1)
155                 acl_add_perm(permset, ACL_EXECUTE);
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_acl(SMB_ACL_T the_acl) 
180 {
181         return acl_free(the_acl);
182 }
183
184 int sys_acl_free_qualifier(void *qual, UNUSED(SMB_ACL_TAG_T tagtype))
185 {
186         return acl_free(qual);
187 }
188
189 #elif defined(HAVE_TRU64_ACLS)
190 /*
191  * The interface to DEC/Compaq Tru64 UNIX ACLs
192  * is based on Draft 13 of the POSIX spec which is
193  * slightly different from the Draft 16 interface.
194  * 
195  * Also, some of the permset manipulation functions
196  * such as acl_clear_perm() and acl_add_perm() appear
197  * to be broken on Tru64 so we have to manipulate
198  * the permission bits in the permset directly.
199  */
200 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
201 {
202         SMB_ACL_ENTRY_T entry;
203
204         if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
205                 return -1;
206         }
207
208         errno = 0;
209         if ((entry = acl_get_entry(the_acl)) != NULL) {
210                 *entry_p = entry;
211                 return 1;
212         }
213
214         return errno ? -1 : 0;
215 }
216
217 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
218 {
219         return acl_get_tag_type( entry_d, tag_type_p);
220 }
221
222 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
223 {
224         return acl_get_qualifier( entry_d);
225 }
226
227 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
228 {
229         return acl_get_file((char *)path_p, type);
230 }
231
232 #if 0
233 SMB_ACL_T sys_acl_get_fd(int fd)
234 {
235         return acl_get_fd(fd, ACL_TYPE_ACCESS);
236 }
237 #endif
238
239 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
240 {
241         SMB_ACL_PERMSET_T permset;
242         int rc;
243         if ((rc = acl_get_permset(entry_d, &permset)) != 0)
244                 return rc;
245         *bits = *permset & 7;   /* Tru64 doesn't have acl_get_perm() */
246         return 0;
247 }
248
249 SMB_ACL_T sys_acl_init( int count)
250 {
251         return acl_init(count);
252 }
253
254 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
255 {
256         SMB_ACL_ENTRY_T entry;
257
258         if ((entry = acl_create_entry(pacl)) == NULL) {
259                 return -1;
260         }
261
262         *pentry = entry;
263         return 0;
264 }
265
266 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
267 {
268         return acl_set_tag_type(entry, tagtype);
269 }
270
271 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
272 {
273         return acl_set_qualifier(entry, qual);
274 }
275
276 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
277 {
278         SMB_ACL_PERMSET_T permset;
279         int rc;
280         if ((rc = acl_get_permset(entry, &permset)) != 0)
281                 return rc;
282         *permset = bits & 7;
283         return acl_set_permset(entry, permset);
284 }
285
286 int sys_acl_valid( SMB_ACL_T theacl )
287 {
288         acl_entry_t     entry;
289
290         return acl_valid(theacl, &entry);
291 }
292
293 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
294 {
295         return acl_set_file((char *)name, acltype, theacl);
296 }
297
298 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
299 {
300         return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
301 }
302
303 int sys_acl_delete_def_file(const char *name)
304 {
305         return acl_delete_def_file((char *)name);
306 }
307
308 int sys_acl_free_acl(SMB_ACL_T the_acl) 
309 {
310         return acl_free(the_acl);
311 }
312
313 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
314 {
315         return acl_free_qualifier(qual, tagtype);
316 }
317
318 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
319
320 /*
321  * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
322  * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
323  */
324
325 /*
326  * Note that while this code implements sufficient functionality
327  * to support the sys_acl_* interfaces it does not provide all
328  * of the semantics of the POSIX ACL interfaces.
329  *
330  * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
331  * from a call to sys_acl_get_entry() should not be assumed to be
332  * valid after calling any of the following functions, which may
333  * reorder the entries in the ACL.
334  *
335  *      sys_acl_valid()
336  *      sys_acl_set_file()
337  *      sys_acl_set_fd()
338  */
339
340 /*
341  * The only difference between Solaris and UnixWare / OpenUNIX is
342  * that the #defines for the ACL operations have different names
343  */
344 #if defined(HAVE_UNIXWARE_ACLS)
345
346 #define SETACL          ACL_SET
347 #define GETACL          ACL_GET
348 #define GETACLCNT       ACL_CNT
349
350 #endif
351
352
353 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
354 {
355         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
356                 errno = EINVAL;
357                 return -1;
358         }
359
360         if (entry_p == NULL) {
361                 errno = EINVAL;
362                 return -1;
363         }
364
365         if (entry_id == SMB_ACL_FIRST_ENTRY) {
366                 acl_d->next = 0;
367         }
368
369         if (acl_d->next < 0) {
370                 errno = EINVAL;
371                 return -1;
372         }
373
374         if (acl_d->next >= acl_d->count) {
375                 return 0;
376         }
377
378         *entry_p = &acl_d->acl[acl_d->next++];
379
380         return 1;
381 }
382
383 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
384 {
385         *type_p = entry_d->a_type;
386
387         return 0;
388 }
389
390 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
391 {
392         if (entry_d->a_type != SMB_ACL_USER
393             && entry_d->a_type != SMB_ACL_GROUP) {
394                 errno = EINVAL;
395                 return NULL;
396         }
397
398         return &entry_d->a_id;
399 }
400
401 /*
402  * There is no way of knowing what size the ACL returned by
403  * GETACL will be unless you first call GETACLCNT which means
404  * making an additional system call.
405  *
406  * In the hope of avoiding the cost of the additional system
407  * call in most cases, we initially allocate enough space for
408  * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
409  * be too small then we use GETACLCNT to find out the actual
410  * size, reallocate the ACL buffer, and then call GETACL again.
411  */
412
413 #define INITIAL_ACL_SIZE        16
414
415 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
416 {
417         SMB_ACL_T       acl_d;
418         int             count;          /* # of ACL entries allocated   */
419         int             naccess;        /* # of access ACL entries      */
420         int             ndefault;       /* # of default ACL entries     */
421
422         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
423                 errno = EINVAL;
424                 return NULL;
425         }
426
427         count = INITIAL_ACL_SIZE;
428         if ((acl_d = sys_acl_init(count)) == NULL) {
429                 return NULL;
430         }
431
432         /*
433          * If there isn't enough space for the ACL entries we use
434          * GETACLCNT to determine the actual number of ACL entries
435          * reallocate and try again. This is in a loop because it
436          * is possible that someone else could modify the ACL and
437          * increase the number of entries between the call to
438          * GETACLCNT and the call to GETACL.
439          */
440         while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
441             && errno == ENOSPC) {
442
443                 sys_acl_free_acl(acl_d);
444
445                 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
446                         return NULL;
447                 }
448
449                 if ((acl_d = sys_acl_init(count)) == NULL) {
450                         return NULL;
451                 }
452         }
453
454         if (count < 0) {
455                 sys_acl_free_acl(acl_d);
456                 return NULL;
457         }
458
459         /*
460          * calculate the number of access and default ACL entries
461          *
462          * Note: we assume that the acl() system call returned a
463          * well formed ACL which is sorted so that all of the
464          * access ACL entries preceed any default ACL entries
465          */
466         for (naccess = 0; naccess < count; naccess++) {
467                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
468                         break;
469         }
470         ndefault = count - naccess;
471         
472         /*
473          * if the caller wants the default ACL we have to copy
474          * the entries down to the start of the acl[] buffer
475          * and mask out the ACL_DEFAULT flag from the type field
476          */
477         if (type == SMB_ACL_TYPE_DEFAULT) {
478                 int     i, j;
479
480                 for (i = 0, j = naccess; i < ndefault; i++, j++) {
481                         acl_d->acl[i] = acl_d->acl[j];
482                         acl_d->acl[i].a_type &= ~ACL_DEFAULT;
483                 }
484
485                 acl_d->count = ndefault;
486         } else {
487                 acl_d->count = naccess;
488         }
489
490         return acl_d;
491 }
492
493 #if 0
494 SMB_ACL_T sys_acl_get_fd(int fd)
495 {
496         SMB_ACL_T       acl_d;
497         int             count;          /* # of ACL entries allocated   */
498         int             naccess;        /* # of access ACL entries      */
499
500         count = INITIAL_ACL_SIZE;
501         if ((acl_d = sys_acl_init(count)) == NULL) {
502                 return NULL;
503         }
504
505         while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
506             && errno == ENOSPC) {
507
508                 sys_acl_free_acl(acl_d);
509
510                 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
511                         return NULL;
512                 }
513
514                 if ((acl_d = sys_acl_init(count)) == NULL) {
515                         return NULL;
516                 }
517         }
518
519         if (count < 0) {
520                 sys_acl_free_acl(acl_d);
521                 return NULL;
522         }
523
524         /*
525          * calculate the number of access ACL entries
526          */
527         for (naccess = 0; naccess < count; naccess++) {
528                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
529                         break;
530         }
531         
532         acl_d->count = naccess;
533
534         return acl_d;
535 }
536 #endif
537
538 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
539 {
540         *bits = entry_d->a_perm;
541         return 0;
542 }
543
544 SMB_ACL_T sys_acl_init(int count)
545 {
546         SMB_ACL_T       a;
547
548         if (count < 0) {
549                 errno = EINVAL;
550                 return NULL;
551         }
552
553         /*
554          * note that since the definition of the structure pointed
555          * to by the SMB_ACL_T includes the first element of the
556          * acl[] array, this actually allocates an ACL with room
557          * for (count+1) entries
558          */
559         if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
560                 errno = ENOMEM;
561                 return NULL;
562         }
563
564         a->size = count + 1;
565         a->count = 0;
566         a->next = -1;
567
568         return a;
569 }
570
571
572 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
573 {
574         SMB_ACL_T       acl_d;
575         SMB_ACL_ENTRY_T entry_d;
576
577         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
578                 errno = EINVAL;
579                 return -1;
580         }
581
582         if (acl_d->count >= acl_d->size) {
583                 errno = ENOSPC;
584                 return -1;
585         }
586
587         entry_d         = &acl_d->acl[acl_d->count++];
588         entry_d->a_type = 0;
589         entry_d->a_id   = -1;
590         entry_d->a_perm = 0;
591         *entry_p        = entry_d;
592
593         return 0;
594 }
595
596 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
597 {
598         switch (tag_type) {
599                 case SMB_ACL_USER:
600                 case SMB_ACL_USER_OBJ:
601                 case SMB_ACL_GROUP:
602                 case SMB_ACL_GROUP_OBJ:
603                 case SMB_ACL_OTHER:
604                 case SMB_ACL_MASK:
605                         entry_d->a_type = tag_type;
606                         break;
607                 default:
608                         errno = EINVAL;
609                         return -1;
610         }
611
612         return 0;
613 }
614
615 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
616 {
617         if (entry_d->a_type != SMB_ACL_GROUP
618             && entry_d->a_type != SMB_ACL_USER) {
619                 errno = EINVAL;
620                 return -1;
621         }
622
623         entry_d->a_id = *((id_t *)qual_p);
624
625         return 0;
626 }
627
628 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
629 {
630         entry_d->a_perm = bits;
631         return 0;
632 }
633
634 /*
635  * sort the ACL and check it for validity
636  *
637  * if it's a minimal ACL with only 4 entries then we
638  * need to recalculate the mask permissions to make
639  * sure that they are the same as the GROUP_OBJ
640  * permissions as required by the UnixWare acl() system call.
641  *
642  * (note: since POSIX allows minimal ACLs which only contain
643  * 3 entries - ie there is no mask entry - we should, in theory,
644  * check for this and add a mask entry if necessary - however
645  * we "know" that the caller of this interface always specifies
646  * a mask so, in practice "this never happens" (tm) - if it *does*
647  * happen aclsort() will fail and return an error and someone will
648  * have to fix it ...)
649  */
650
651 static int acl_sort(SMB_ACL_T acl_d)
652 {
653         int     fixmask = (acl_d->count <= 4);
654
655         if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
656                 errno = EINVAL;
657                 return -1;
658         }
659         return 0;
660 }
661  
662 int sys_acl_valid(SMB_ACL_T acl_d)
663 {
664         return acl_sort(acl_d);
665 }
666
667 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
668 {
669         struct stat     s;
670         struct acl      *acl_p;
671         int             acl_count;
672         struct acl      *acl_buf        = NULL;
673         int             ret;
674
675         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
676                 errno = EINVAL;
677                 return -1;
678         }
679
680         if (acl_sort(acl_d) != 0) {
681                 return -1;
682         }
683
684         acl_p           = &acl_d->acl[0];
685         acl_count       = acl_d->count;
686
687         /*
688          * if it's a directory there is extra work to do
689          * since the acl() system call will replace both
690          * the access ACLs and the default ACLs (if any)
691          */
692         if (stat(name, &s) != 0) {
693                 return -1;
694         }
695         if (S_ISDIR(s.st_mode)) {
696                 SMB_ACL_T       acc_acl;
697                 SMB_ACL_T       def_acl;
698                 SMB_ACL_T       tmp_acl;
699                 int             i;
700
701                 if (type == SMB_ACL_TYPE_ACCESS) {
702                         acc_acl = acl_d;
703                         def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
704
705                 } else {
706                         def_acl = acl_d;
707                         acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
708                 }
709
710                 if (tmp_acl == NULL) {
711                         return -1;
712                 }
713
714                 /*
715                  * allocate a temporary buffer for the complete ACL
716                  */
717                 acl_count = acc_acl->count + def_acl->count;
718                 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
719
720                 if (acl_buf == NULL) {
721                         sys_acl_free_acl(tmp_acl);
722                         errno = ENOMEM;
723                         return -1;
724                 }
725
726                 /*
727                  * copy the access control and default entries into the buffer
728                  */
729                 memcpy(&acl_buf[0], &acc_acl->acl[0],
730                         acc_acl->count * sizeof(acl_buf[0]));
731
732                 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
733                         def_acl->count * sizeof(acl_buf[0]));
734
735                 /*
736                  * set the ACL_DEFAULT flag on the default entries
737                  */
738                 for (i = acc_acl->count; i < acl_count; i++) {
739                         acl_buf[i].a_type |= ACL_DEFAULT;
740                 }
741
742                 sys_acl_free_acl(tmp_acl);
743
744         } else if (type != SMB_ACL_TYPE_ACCESS) {
745                 errno = EINVAL;
746                 return -1;
747         }
748
749         ret = acl(name, SETACL, acl_count, acl_p);
750
751         SAFE_FREE(acl_buf);
752
753         return ret;
754 }
755
756 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
757 {
758         if (acl_sort(acl_d) != 0) {
759                 return -1;
760         }
761
762         return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
763 }
764
765 int sys_acl_delete_def_file(const char *path)
766 {
767         SMB_ACL_T       acl_d;
768         int             ret;
769
770         /*
771          * fetching the access ACL and rewriting it has
772          * the effect of deleting the default ACL
773          */
774         if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
775                 return -1;
776         }
777
778         ret = acl(path, SETACL, acl_d->count, acl_d->acl);
779
780         sys_acl_free_acl(acl_d);
781         
782         return ret;
783 }
784
785 int sys_acl_free_acl(SMB_ACL_T acl_d) 
786 {
787         SAFE_FREE(acl_d);
788         return 0;
789 }
790
791 int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
792 {
793         return 0;
794 }
795
796 #elif defined(HAVE_HPUX_ACLS)
797 #include <dl.h>
798
799 /*
800  * Based on the Solaris/SCO code - with modifications.
801  */
802
803 /*
804  * Note that while this code implements sufficient functionality
805  * to support the sys_acl_* interfaces it does not provide all
806  * of the semantics of the POSIX ACL interfaces.
807  *
808  * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
809  * from a call to sys_acl_get_entry() should not be assumed to be
810  * valid after calling any of the following functions, which may
811  * reorder the entries in the ACL.
812  *
813  *      sys_acl_valid()
814  *      sys_acl_set_file()
815  *      sys_acl_set_fd()
816  */
817
818 /* This checks if the POSIX ACL system call is defined */
819 /* which basically corresponds to whether JFS 3.3 or   */
820 /* higher is installed. If acl() was called when it    */
821 /* isn't defined, it causes the process to core dump   */
822 /* so it is important to check this and avoid acl()    */
823 /* calls if it isn't there.                            */
824
825 static BOOL hpux_acl_call_presence(void)
826 {
827
828         shl_t handle = NULL;
829         void *value;
830         int ret_val=0;
831         static BOOL already_checked=0;
832
833         if(already_checked)
834                 return True;
835
836
837         ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
838
839         if(ret_val != 0) {
840                 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
841                         ret_val, errno, strerror(errno)));
842                 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
843                 return False;
844         }
845
846         DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
847
848         already_checked = True;
849         return True;
850 }
851
852 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
853 {
854         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
855                 errno = EINVAL;
856                 return -1;
857         }
858
859         if (entry_p == NULL) {
860                 errno = EINVAL;
861                 return -1;
862         }
863
864         if (entry_id == SMB_ACL_FIRST_ENTRY) {
865                 acl_d->next = 0;
866         }
867
868         if (acl_d->next < 0) {
869                 errno = EINVAL;
870                 return -1;
871         }
872
873         if (acl_d->next >= acl_d->count) {
874                 return 0;
875         }
876
877         *entry_p = &acl_d->acl[acl_d->next++];
878
879         return 1;
880 }
881
882 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
883 {
884         *type_p = entry_d->a_type;
885
886         return 0;
887 }
888
889 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
890 {
891         if (entry_d->a_type != SMB_ACL_USER
892             && entry_d->a_type != SMB_ACL_GROUP) {
893                 errno = EINVAL;
894                 return NULL;
895         }
896
897         return &entry_d->a_id;
898 }
899
900 /*
901  * There is no way of knowing what size the ACL returned by
902  * ACL_GET will be unless you first call ACL_CNT which means
903  * making an additional system call.
904  *
905  * In the hope of avoiding the cost of the additional system
906  * call in most cases, we initially allocate enough space for
907  * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
908  * be too small then we use ACL_CNT to find out the actual
909  * size, reallocate the ACL buffer, and then call ACL_GET again.
910  */
911
912 #define INITIAL_ACL_SIZE        16
913
914 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
915 {
916         SMB_ACL_T       acl_d;
917         int             count;          /* # of ACL entries allocated   */
918         int             naccess;        /* # of access ACL entries      */
919         int             ndefault;       /* # of default ACL entries     */
920
921         if(hpux_acl_call_presence() == False) {
922                 /* Looks like we don't have the acl() system call on HPUX. 
923                  * May be the system doesn't have the latest version of JFS.
924                  */
925                 return NULL; 
926         }
927
928         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
929                 errno = EINVAL;
930                 return NULL;
931         }
932
933         count = INITIAL_ACL_SIZE;
934         if ((acl_d = sys_acl_init(count)) == NULL) {
935                 return NULL;
936         }
937
938         /*
939          * If there isn't enough space for the ACL entries we use
940          * ACL_CNT to determine the actual number of ACL entries
941          * reallocate and try again. This is in a loop because it
942          * is possible that someone else could modify the ACL and
943          * increase the number of entries between the call to
944          * ACL_CNT and the call to ACL_GET.
945          */
946         while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
947
948                 sys_acl_free_acl(acl_d);
949
950                 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
951                         return NULL;
952                 }
953
954                 if ((acl_d = sys_acl_init(count)) == NULL) {
955                         return NULL;
956                 }
957         }
958
959         if (count < 0) {
960                 sys_acl_free_acl(acl_d);
961                 return NULL;
962         }
963
964         /*
965          * calculate the number of access and default ACL entries
966          *
967          * Note: we assume that the acl() system call returned a
968          * well formed ACL which is sorted so that all of the
969          * access ACL entries preceed any default ACL entries
970          */
971         for (naccess = 0; naccess < count; naccess++) {
972                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
973                         break;
974         }
975         ndefault = count - naccess;
976         
977         /*
978          * if the caller wants the default ACL we have to copy
979          * the entries down to the start of the acl[] buffer
980          * and mask out the ACL_DEFAULT flag from the type field
981          */
982         if (type == SMB_ACL_TYPE_DEFAULT) {
983                 int     i, j;
984
985                 for (i = 0, j = naccess; i < ndefault; i++, j++) {
986                         acl_d->acl[i] = acl_d->acl[j];
987                         acl_d->acl[i].a_type &= ~ACL_DEFAULT;
988                 }
989
990                 acl_d->count = ndefault;
991         } else {
992                 acl_d->count = naccess;
993         }
994
995         return acl_d;
996 }
997
998 #if 0
999 SMB_ACL_T sys_acl_get_fd(int fd)
1000 {
1001         /*
1002          * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1003          */
1004
1005         files_struct *fsp = file_find_fd(fd);
1006
1007         if (fsp == NULL) {
1008                 errno = EBADF;
1009                 return NULL;
1010         }
1011
1012         /*
1013          * We know we're in the same conn context. So we
1014          * can use the relative path.
1015          */
1016
1017         return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
1018 }
1019 #endif
1020
1021 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1022 {
1023         *bits = entry_d->a_perm;
1024
1025         return 0;
1026 }
1027
1028 SMB_ACL_T sys_acl_init(int count)
1029 {
1030         SMB_ACL_T       a;
1031
1032         if (count < 0) {
1033                 errno = EINVAL;
1034                 return NULL;
1035         }
1036
1037         /*
1038          * note that since the definition of the structure pointed
1039          * to by the SMB_ACL_T includes the first element of the
1040          * acl[] array, this actually allocates an ACL with room
1041          * for (count+1) entries
1042          */
1043         if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
1044                 errno = ENOMEM;
1045                 return NULL;
1046         }
1047
1048         a->size = count + 1;
1049         a->count = 0;
1050         a->next = -1;
1051
1052         return a;
1053 }
1054
1055
1056 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1057 {
1058         SMB_ACL_T       acl_d;
1059         SMB_ACL_ENTRY_T entry_d;
1060
1061         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1062                 errno = EINVAL;
1063                 return -1;
1064         }
1065
1066         if (acl_d->count >= acl_d->size) {
1067                 errno = ENOSPC;
1068                 return -1;
1069         }
1070
1071         entry_d         = &acl_d->acl[acl_d->count++];
1072         entry_d->a_type = 0;
1073         entry_d->a_id   = -1;
1074         entry_d->a_perm = 0;
1075         *entry_p        = entry_d;
1076
1077         return 0;
1078 }
1079
1080 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1081 {
1082         switch (tag_type) {
1083                 case SMB_ACL_USER:
1084                 case SMB_ACL_USER_OBJ:
1085                 case SMB_ACL_GROUP:
1086                 case SMB_ACL_GROUP_OBJ:
1087                 case SMB_ACL_OTHER:
1088                 case SMB_ACL_MASK:
1089                         entry_d->a_type = tag_type;
1090                         break;
1091                 default:
1092                         errno = EINVAL;
1093                         return -1;
1094         }
1095
1096         return 0;
1097 }
1098
1099 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1100 {
1101         if (entry_d->a_type != SMB_ACL_GROUP
1102             && entry_d->a_type != SMB_ACL_USER) {
1103                 errno = EINVAL;
1104                 return -1;
1105         }
1106
1107         entry_d->a_id = *((id_t *)qual_p);
1108
1109         return 0;
1110 }
1111
1112 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1113 {
1114         entry_d->a_perm = bits;
1115
1116         return 0;
1117 }
1118
1119 /* Structure to capture the count for each type of ACE. */
1120
1121 struct hpux_acl_types {
1122         int n_user;
1123         int n_def_user;
1124         int n_user_obj;
1125         int n_def_user_obj;
1126
1127         int n_group;
1128         int n_def_group;
1129         int n_group_obj;
1130         int n_def_group_obj;
1131
1132         int n_other;
1133         int n_other_obj;
1134         int n_def_other_obj;
1135
1136         int n_class_obj;
1137         int n_def_class_obj;
1138
1139         int n_illegal_obj;
1140 };
1141
1142 /* count_obj:
1143  * Counts the different number of objects in a given array of ACL
1144  * structures.
1145  * Inputs:
1146  *
1147  * acl_count      - Count of ACLs in the array of ACL strucutres.
1148  * aclp           - Array of ACL structures.
1149  * acl_type_count - Pointer to acl_types structure. Should already be
1150  *                  allocated.
1151  * Output: 
1152  *
1153  * acl_type_count - This structure is filled up with counts of various 
1154  *                  acl types.
1155  */
1156
1157 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
1158 {
1159         int i;
1160
1161         memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
1162
1163         for(i=0;i<acl_count;i++) {
1164                 switch(aclp[i].a_type) {
1165                 case USER: 
1166                         acl_type_count->n_user++;
1167                         break;
1168                 case USER_OBJ: 
1169                         acl_type_count->n_user_obj++;
1170                         break;
1171                 case DEF_USER_OBJ: 
1172                         acl_type_count->n_def_user_obj++;
1173                         break;
1174                 case GROUP: 
1175                         acl_type_count->n_group++;
1176                         break;
1177                 case GROUP_OBJ: 
1178                         acl_type_count->n_group_obj++;
1179                         break;
1180                 case DEF_GROUP_OBJ: 
1181                         acl_type_count->n_def_group_obj++;
1182                         break;
1183                 case OTHER_OBJ: 
1184                         acl_type_count->n_other_obj++;
1185                         break;
1186                 case DEF_OTHER_OBJ: 
1187                         acl_type_count->n_def_other_obj++;
1188                         break;
1189                 case CLASS_OBJ:
1190                         acl_type_count->n_class_obj++;
1191                         break;
1192                 case DEF_CLASS_OBJ:
1193                         acl_type_count->n_def_class_obj++;
1194                         break;
1195                 case DEF_USER:
1196                         acl_type_count->n_def_user++;
1197                         break;
1198                 case DEF_GROUP:
1199                         acl_type_count->n_def_group++;
1200                         break;
1201                 default: 
1202                         acl_type_count->n_illegal_obj++;
1203                         break;
1204                 }
1205         }
1206 }
1207
1208 /* swap_acl_entries:  Swaps two ACL entries. 
1209  *
1210  * Inputs: aclp0, aclp1 - ACL entries to be swapped.
1211  */
1212
1213 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
1214 {
1215         struct acl temp_acl;
1216
1217         temp_acl.a_type = aclp0->a_type;
1218         temp_acl.a_id = aclp0->a_id;
1219         temp_acl.a_perm = aclp0->a_perm;
1220
1221         aclp0->a_type = aclp1->a_type;
1222         aclp0->a_id = aclp1->a_id;
1223         aclp0->a_perm = aclp1->a_perm;
1224
1225         aclp1->a_type = temp_acl.a_type;
1226         aclp1->a_id = temp_acl.a_id;
1227         aclp1->a_perm = temp_acl.a_perm;
1228 }
1229
1230 /* prohibited_duplicate_type
1231  * Identifies if given ACL type can have duplicate entries or 
1232  * not.
1233  *
1234  * Inputs: acl_type - ACL Type.
1235  *
1236  * Outputs: 
1237  *
1238  * Return.. 
1239  *
1240  * True - If the ACL type matches any of the prohibited types.
1241  * False - If the ACL type doesn't match any of the prohibited types.
1242  */ 
1243
1244 static BOOL hpux_prohibited_duplicate_type(int acl_type)
1245 {
1246         switch(acl_type) {
1247                 case USER:
1248                 case GROUP:
1249                 case DEF_USER: 
1250                 case DEF_GROUP:
1251                         return True;
1252                 default:
1253                         return False;
1254         }
1255 }
1256
1257 /* get_needed_class_perm
1258  * Returns the permissions of a ACL structure only if the ACL
1259  * type matches one of the pre-determined types for computing 
1260  * CLASS_OBJ permissions.
1261  *
1262  * Inputs: aclp - Pointer to ACL structure.
1263  */
1264
1265 static int hpux_get_needed_class_perm(struct acl *aclp)
1266 {
1267         switch(aclp->a_type) {
1268                 case USER: 
1269                 case GROUP_OBJ: 
1270                 case GROUP: 
1271                 case DEF_USER_OBJ: 
1272                 case DEF_USER:
1273                 case DEF_GROUP_OBJ: 
1274                 case DEF_GROUP:
1275                 case DEF_CLASS_OBJ:
1276                 case DEF_OTHER_OBJ: 
1277                         return aclp->a_perm;
1278                 default: 
1279                         return 0;
1280         }
1281 }
1282
1283 /* acl_sort for HPUX.
1284  * Sorts the array of ACL structures as per the description in
1285  * aclsort man page. Refer to aclsort man page for more details
1286  *
1287  * Inputs:
1288  *
1289  * acl_count - Count of ACLs in the array of ACL structures.
1290  * calclass  - If this is not zero, then we compute the CLASS_OBJ
1291  *             permissions.
1292  * aclp      - Array of ACL structures.
1293  *
1294  * Outputs:
1295  *
1296  * aclp     - Sorted array of ACL structures.
1297  *
1298  * Outputs:
1299  *
1300  * Returns 0 for success -1 for failure. Prints a message to the Samba
1301  * debug log in case of failure.
1302  */
1303
1304 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
1305 {
1306 #if !defined(HAVE_HPUX_ACLSORT)
1307         /*
1308          * The aclsort() system call is availabe on the latest HPUX General
1309          * Patch Bundles. So for HPUX, we developed our version of acl_sort 
1310          * function. Because, we don't want to update to a new 
1311          * HPUX GR bundle just for aclsort() call.
1312          */
1313
1314         struct hpux_acl_types acl_obj_count;
1315         int n_class_obj_perm = 0;
1316         int i, j;
1317  
1318         if(!acl_count) {
1319                 DEBUG(10,("Zero acl count passed. Returning Success\n"));
1320                 return 0;
1321         }
1322
1323         if(aclp == NULL) {
1324                 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
1325                 return -1;
1326         }
1327
1328         /* Count different types of ACLs in the ACLs array */
1329
1330         hpux_count_obj(acl_count, aclp, &acl_obj_count);
1331
1332         /* There should be only one entry each of type USER_OBJ, GROUP_OBJ, 
1333          * CLASS_OBJ and OTHER_OBJ 
1334          */
1335
1336         if( (acl_obj_count.n_user_obj  != 1) || 
1337                 (acl_obj_count.n_group_obj != 1) || 
1338                 (acl_obj_count.n_class_obj != 1) ||
1339                 (acl_obj_count.n_other_obj != 1) 
1340         ) {
1341                 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
1342 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
1343                 return -1;
1344         }
1345
1346         /* If any of the default objects are present, there should be only
1347          * one of them each.
1348          */
1349
1350         if( (acl_obj_count.n_def_user_obj  > 1) || (acl_obj_count.n_def_group_obj > 1) || 
1351                         (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
1352                 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
1353 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
1354                 return -1;
1355         }
1356
1357         /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl 
1358          * structures.  
1359          *
1360          * Sorting crieteria - First sort by ACL type. If there are multiple entries of
1361          * same ACL type, sort by ACL id.
1362          *
1363          * I am using the trival kind of sorting method here because, performance isn't 
1364          * really effected by the ACLs feature. More over there aren't going to be more
1365          * than 17 entries on HPUX. 
1366          */
1367
1368         for(i=0; i<acl_count;i++) {
1369                 for (j=i+1; j<acl_count; j++) {
1370                         if( aclp[i].a_type > aclp[j].a_type ) {
1371                                 /* ACL entries out of order, swap them */
1372
1373                                 hpux_swap_acl_entries((aclp+i), (aclp+j));
1374
1375                         } else if ( aclp[i].a_type == aclp[j].a_type ) {
1376
1377                                 /* ACL entries of same type, sort by id */
1378
1379                                 if(aclp[i].a_id > aclp[j].a_id) {
1380                                         hpux_swap_acl_entries((aclp+i), (aclp+j));
1381                                 } else if (aclp[i].a_id == aclp[j].a_id) {
1382                                         /* We have a duplicate entry. */
1383                                         if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
1384                                                 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
1385                                                         aclp[i].a_type, aclp[i].a_id));
1386                                                 return -1;
1387                                         }
1388                                 }
1389
1390                         }
1391                 }
1392         }
1393
1394         /* set the class obj permissions to the computed one. */
1395         if(calclass) {
1396                 int n_class_obj_index = -1;
1397
1398                 for(i=0;i<acl_count;i++) {
1399                         n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
1400
1401                         if(aclp[i].a_type == CLASS_OBJ)
1402                                 n_class_obj_index = i;
1403                 }
1404                 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
1405         }
1406
1407         return 0;
1408 #else
1409         return aclsort(acl_count, calclass, aclp);
1410 #endif
1411 }
1412
1413 /*
1414  * sort the ACL and check it for validity
1415  *
1416  * if it's a minimal ACL with only 4 entries then we
1417  * need to recalculate the mask permissions to make
1418  * sure that they are the same as the GROUP_OBJ
1419  * permissions as required by the UnixWare acl() system call.
1420  *
1421  * (note: since POSIX allows minimal ACLs which only contain
1422  * 3 entries - ie there is no mask entry - we should, in theory,
1423  * check for this and add a mask entry if necessary - however
1424  * we "know" that the caller of this interface always specifies
1425  * a mask so, in practice "this never happens" (tm) - if it *does*
1426  * happen aclsort() will fail and return an error and someone will
1427  * have to fix it ...)
1428  */
1429
1430 static int acl_sort(SMB_ACL_T acl_d)
1431 {
1432         int fixmask = (acl_d->count <= 4);
1433
1434         if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
1435                 errno = EINVAL;
1436                 return -1;
1437         }
1438         return 0;
1439 }
1440  
1441 int sys_acl_valid(SMB_ACL_T acl_d)
1442 {
1443         return acl_sort(acl_d);
1444 }
1445
1446 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1447 {
1448         struct stat     s;
1449         struct acl      *acl_p;
1450         int             acl_count;
1451         struct acl      *acl_buf        = NULL;
1452         int             ret;
1453
1454         if(hpux_acl_call_presence() == False) {
1455                 /* Looks like we don't have the acl() system call on HPUX. 
1456                  * May be the system doesn't have the latest version of JFS.
1457                  */
1458                 errno=ENOSYS;
1459                 return -1; 
1460         }
1461
1462         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
1463                 errno = EINVAL;
1464                 return -1;
1465         }
1466
1467         if (acl_sort(acl_d) != 0) {
1468                 return -1;
1469         }
1470
1471         acl_p           = &acl_d->acl[0];
1472         acl_count       = acl_d->count;
1473
1474         /*
1475          * if it's a directory there is extra work to do
1476          * since the acl() system call will replace both
1477          * the access ACLs and the default ACLs (if any)
1478          */
1479         if (stat(name, &s) != 0) {
1480                 return -1;
1481         }
1482         if (S_ISDIR(s.st_mode)) {
1483                 SMB_ACL_T       acc_acl;
1484                 SMB_ACL_T       def_acl;
1485                 SMB_ACL_T       tmp_acl;
1486                 int             i;
1487
1488                 if (type == SMB_ACL_TYPE_ACCESS) {
1489                         acc_acl = acl_d;
1490                         def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
1491
1492                 } else {
1493                         def_acl = acl_d;
1494                         acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
1495                 }
1496
1497                 if (tmp_acl == NULL) {
1498                         return -1;
1499                 }
1500
1501                 /*
1502                  * allocate a temporary buffer for the complete ACL
1503                  */
1504                 acl_count = acc_acl->count + def_acl->count;
1505                 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
1506
1507                 if (acl_buf == NULL) {
1508                         sys_acl_free_acl(tmp_acl);
1509                         errno = ENOMEM;
1510                         return -1;
1511                 }
1512
1513                 /*
1514                  * copy the access control and default entries into the buffer
1515                  */
1516                 memcpy(&acl_buf[0], &acc_acl->acl[0],
1517                         acc_acl->count * sizeof(acl_buf[0]));
1518
1519                 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
1520                         def_acl->count * sizeof(acl_buf[0]));
1521
1522                 /*
1523                  * set the ACL_DEFAULT flag on the default entries
1524                  */
1525                 for (i = acc_acl->count; i < acl_count; i++) {
1526                         acl_buf[i].a_type |= ACL_DEFAULT;
1527                 }
1528
1529                 sys_acl_free_acl(tmp_acl);
1530
1531         } else if (type != SMB_ACL_TYPE_ACCESS) {
1532                 errno = EINVAL;
1533                 return -1;
1534         }
1535
1536         ret = acl(name, ACL_SET, acl_count, acl_p);
1537
1538         if (acl_buf) {
1539                 free(acl_buf);
1540         }
1541
1542         return ret;
1543 }
1544
1545 #if 0
1546 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1547 {
1548         /*
1549          * HPUX doesn't have the facl call. Fake it using the path.... JRA.
1550          */
1551
1552         files_struct *fsp = file_find_fd(fd);
1553
1554         if (fsp == NULL) {
1555                 errno = EBADF;
1556                 return NULL;
1557         }
1558
1559         if (acl_sort(acl_d) != 0) {
1560                 return -1;
1561         }
1562
1563         /*
1564          * We know we're in the same conn context. So we
1565          * can use the relative path.
1566          */
1567
1568         return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
1569 }
1570 #endif
1571
1572 int sys_acl_delete_def_file(const char *path)
1573 {
1574         SMB_ACL_T       acl_d;
1575         int             ret;
1576
1577         /*
1578          * fetching the access ACL and rewriting it has
1579          * the effect of deleting the default ACL
1580          */
1581         if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
1582                 return -1;
1583         }
1584
1585         ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
1586
1587         sys_acl_free_acl(acl_d);
1588         
1589         return ret;
1590 }
1591
1592 int sys_acl_free_acl(SMB_ACL_T acl_d) 
1593 {
1594         free(acl_d);
1595         return 0;
1596 }
1597
1598 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1599 {
1600         return 0;
1601 }
1602
1603 #elif defined(HAVE_IRIX_ACLS)
1604
1605 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1606 {
1607         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
1608                 errno = EINVAL;
1609                 return -1;
1610         }
1611
1612         if (entry_p == NULL) {
1613                 errno = EINVAL;
1614                 return -1;
1615         }
1616
1617         if (entry_id == SMB_ACL_FIRST_ENTRY) {
1618                 acl_d->next = 0;
1619         }
1620
1621         if (acl_d->next < 0) {
1622                 errno = EINVAL;
1623                 return -1;
1624         }
1625
1626         if (acl_d->next >= acl_d->aclp->acl_cnt) {
1627                 return 0;
1628         }
1629
1630         *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1631
1632         return 1;
1633 }
1634
1635 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1636 {
1637         *type_p = entry_d->ae_tag;
1638
1639         return 0;
1640 }
1641
1642 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1643 {
1644         if (entry_d->ae_tag != SMB_ACL_USER
1645             && entry_d->ae_tag != SMB_ACL_GROUP) {
1646                 errno = EINVAL;
1647                 return NULL;
1648         }
1649
1650         return &entry_d->ae_id;
1651 }
1652
1653 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1654 {
1655         SMB_ACL_T       a;
1656
1657         if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1658                 errno = ENOMEM;
1659                 return NULL;
1660         }
1661         if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1662                 SAFE_FREE(a);
1663                 return NULL;
1664         }
1665         a->next = -1;
1666         a->freeaclp = True;
1667         return a;
1668 }
1669
1670 #if 0
1671 SMB_ACL_T sys_acl_get_fd(int fd)
1672 {
1673         SMB_ACL_T       a;
1674
1675         if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
1676                 errno = ENOMEM;
1677                 return NULL;
1678         }
1679         if ((a->aclp = acl_get_fd(fd)) == NULL) {
1680                 SAFE_FREE(a);
1681                 return NULL;
1682         }
1683         a->next = -1;
1684         a->freeaclp = True;
1685         return a;
1686 }
1687 #endif
1688
1689 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1690 {
1691         *bits = entry_d->ae_perm;
1692
1693         return 0;
1694 }
1695
1696 SMB_ACL_T sys_acl_init(int count)
1697 {
1698         SMB_ACL_T       a;
1699
1700         if (count < 0) {
1701                 errno = EINVAL;
1702                 return NULL;
1703         }
1704
1705         if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
1706                 errno = ENOMEM;
1707                 return NULL;
1708         }
1709
1710         a->next = -1;
1711         a->freeaclp = False;
1712         a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
1713         a->aclp->acl_cnt = 0;
1714
1715         return a;
1716 }
1717
1718
1719 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1720 {
1721         SMB_ACL_T       acl_d;
1722         SMB_ACL_ENTRY_T entry_d;
1723
1724         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1725                 errno = EINVAL;
1726                 return -1;
1727         }
1728
1729         if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
1730                 errno = ENOSPC;
1731                 return -1;
1732         }
1733
1734         entry_d         = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
1735         entry_d->ae_tag = 0;
1736         entry_d->ae_id  = 0;
1737         entry_d->ae_perm        = 0;
1738         *entry_p        = entry_d;
1739
1740         return 0;
1741 }
1742
1743 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1744 {
1745         switch (tag_type) {
1746                 case SMB_ACL_USER:
1747                 case SMB_ACL_USER_OBJ:
1748                 case SMB_ACL_GROUP:
1749                 case SMB_ACL_GROUP_OBJ:
1750                 case SMB_ACL_OTHER:
1751                 case SMB_ACL_MASK:
1752                         entry_d->ae_tag = tag_type;
1753                         break;
1754                 default:
1755                         errno = EINVAL;
1756                         return -1;
1757         }
1758
1759         return 0;
1760 }
1761
1762 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1763 {
1764         if (entry_d->ae_tag != SMB_ACL_GROUP
1765             && entry_d->ae_tag != SMB_ACL_USER) {
1766                 errno = EINVAL;
1767                 return -1;
1768         }
1769
1770         entry_d->ae_id = *((id_t *)qual_p);
1771
1772         return 0;
1773 }
1774
1775 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 bits)
1776 {
1777         entry_d->ae_perm = bits;
1778
1779         return 0;
1780 }
1781
1782 int sys_acl_valid(SMB_ACL_T acl_d)
1783 {
1784         return acl_valid(acl_d->aclp);
1785 }
1786
1787 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1788 {
1789         return acl_set_file(name, type, acl_d->aclp);
1790 }
1791
1792 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1793 {
1794         return acl_set_fd(fd, acl_d->aclp);
1795 }
1796
1797 int sys_acl_delete_def_file(const char *name)
1798 {
1799         return acl_delete_def_file(name);
1800 }
1801
1802 int sys_acl_free_acl(SMB_ACL_T acl_d) 
1803 {
1804         if (acl_d->freeaclp) {
1805                 acl_free(acl_d->aclp);
1806         }
1807         acl_free(acl_d);
1808         return 0;
1809 }
1810
1811 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1812 {
1813         return 0;
1814 }
1815
1816 #elif defined(HAVE_AIX_ACLS)
1817
1818 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1819
1820 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1821 {
1822         struct acl_entry_link *link;
1823         struct new_acl_entry *entry;
1824         int keep_going;
1825
1826         DEBUG(10,("This is the count: %d\n",theacl->count));
1827
1828         /* Check if count was previously set to -1. *
1829          * If it was, that means we reached the end *
1830          * of the acl last time.                    */
1831         if(theacl->count == -1)
1832                 return(0);
1833
1834         link = theacl;
1835         /* To get to the next acl, traverse linked list until index *
1836          * of acl matches the count we are keeping.  This count is  *
1837          * incremented each time we return an acl entry.            */
1838
1839         for(keep_going = 0; keep_going < theacl->count; keep_going++)
1840                 link = link->nextp;
1841
1842         entry = *entry_p =  link->entryp;
1843
1844         DEBUG(10,("*entry_p is %d\n",entry_p));
1845         DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1846
1847         /* Increment count */
1848         theacl->count++;
1849         if(link->nextp == NULL)
1850                 theacl->count = -1;
1851
1852         return(1);
1853 }
1854
1855 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1856 {
1857         /* Initialize tag type */
1858
1859         *tag_type_p = -1;
1860         DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1861
1862         /* Depending on what type of entry we have, *
1863          * return tag type.                         */
1864         switch(entry_d->ace_id->id_type) {
1865         case ACEID_USER:
1866                 *tag_type_p = SMB_ACL_USER;
1867                 break;
1868         case ACEID_GROUP:
1869                 *tag_type_p = SMB_ACL_GROUP;
1870                 break;
1871
1872         case SMB_ACL_USER_OBJ:
1873         case SMB_ACL_GROUP_OBJ:
1874         case SMB_ACL_OTHER:
1875                 *tag_type_p = entry_d->ace_id->id_type;
1876                 break;
1877  
1878         default:
1879                 return(-1);
1880         }
1881
1882         return(0);
1883 }
1884
1885 int sys_acl_get_access_bits(SMB_ACL_ENTRY_T entry_d, uint32 *bits)
1886 {
1887         SMB_ACL_PERMSET_T permset;
1888         DEBUG(10,("Starting AIX sys_acl_get_access_bits\n"));
1889         permset = &entry_d->ace_access;
1890         DEBUG(10,("*permset is %d\n",*permset));
1891         *bits = (*permset & S_IRUSR ? 4 : 0)
1892               | (*permset & S_IWUSR ? 2 : 0)
1893               | (*permset & S_IXUSR ? 1 : 0);
1894         DEBUG(10,("Ending AIX sys_acl_get_access_bits\n"));
1895         return(0);
1896 }
1897
1898 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1899 {
1900         return(entry_d->ace_id->id_data);
1901 }
1902
1903 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1904 {
1905         struct acl *file_acl = (struct acl *)NULL;
1906         struct acl_entry *acl_entry;
1907         struct new_acl_entry *new_acl_entry;
1908         struct ace_id *idp;
1909         struct acl_entry_link *acl_entry_link;
1910         struct acl_entry_link *acl_entry_link_head;
1911         int i;
1912         int rc = 0;
1913         uid_t user_id;
1914
1915         /* AIX has no DEFAULT */
1916         if  ( type == SMB_ACL_TYPE_DEFAULT ) {
1917                 errno = ENOTSUP;
1918                 return NULL;
1919         }
1920
1921         /* Get the acl using statacl */
1922  
1923         DEBUG(10,("Entering sys_acl_get_file\n"));
1924         DEBUG(10,("path_p is %s\n",path_p));
1925
1926         file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
1927  
1928         if(file_acl == NULL) {
1929                 errno=ENOMEM;
1930                 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1931                 return(NULL);
1932         }
1933
1934         memset(file_acl,0,BUFSIZ);
1935
1936         rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1937         if(rc == -1) {
1938                 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1939                 SAFE_FREE(file_acl);
1940                 return(NULL);
1941         }
1942
1943         DEBUG(10,("Got facl and returned it\n"));
1944
1945         /* Point to the first acl entry in the acl */
1946         acl_entry =  file_acl->acl_ext;
1947
1948         /* Begin setting up the head of the linked list *
1949          * that will be used for the storing the acl    *
1950          * in a way that is useful for the posix_acls.c *
1951          * code.                                          */
1952
1953         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1954         if(acl_entry_link_head == NULL)
1955                 return(NULL);
1956
1957         acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
1958         if(acl_entry_link->entryp == NULL) {
1959                 SAFE_FREE(file_acl);
1960                 errno = ENOMEM;
1961                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1962                 return(NULL);
1963         }
1964
1965         DEBUG(10,("acl_entry is %d\n",acl_entry));
1966         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1967
1968         /* Check if the extended acl bit is on.   *
1969          * If it isn't, do not show the           *
1970          * contents of the acl since AIX intends *
1971          * the extended info to remain unused     */
1972
1973         if(file_acl->acl_mode & S_IXACL){
1974                 /* while we are not pointing to the very end */
1975                 while(acl_entry < acl_last(file_acl)) {
1976                         /* before we malloc anything, make sure this is  */
1977                         /* a valid acl entry and one that we want to map */
1978                         idp = id_nxt(acl_entry->ace_id);
1979                         if((acl_entry->ace_type == ACC_SPECIFY ||
1980                                 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1981                                         acl_entry = acl_nxt(acl_entry);
1982                                         continue;
1983                         }
1984
1985                         idp = acl_entry->ace_id;
1986
1987                         /* Check if this is the first entry in the linked list. *
1988                          * The first entry needs to keep prevp pointing to NULL *
1989                          * and already has entryp allocated.                  */
1990
1991                         if(acl_entry_link_head->count != 0) {
1992                                 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
1993
1994                                 if(acl_entry_link->nextp == NULL) {
1995                                         SAFE_FREE(file_acl);
1996                                         errno = ENOMEM;
1997                                         DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1998                                         return(NULL);
1999                                 }
2000
2001                                 acl_entry_link->nextp->prevp = acl_entry_link;
2002                                 acl_entry_link = acl_entry_link->nextp;
2003                                 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2004                                 if(acl_entry_link->entryp == NULL) {
2005                                         SAFE_FREE(file_acl);
2006                                         errno = ENOMEM;
2007                                         DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2008                                         return(NULL);
2009                                 }
2010                                 acl_entry_link->nextp = NULL;
2011                         }
2012
2013                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2014
2015                         /* Don't really need this since all types are going *
2016                          * to be specified but, it's better than leaving it 0 */
2017
2018                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2019  
2020                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2021  
2022                         memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
2023
2024                         /* The access in the acl entries must be left shifted by *
2025                          * three bites, because they will ultimately be compared *
2026                          * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
2027
2028                         switch(acl_entry->ace_type){
2029                         case ACC_PERMIT:
2030                         case ACC_SPECIFY:
2031                                 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2032                                 acl_entry_link->entryp->ace_access <<= 6;
2033                                 acl_entry_link_head->count++;
2034                                 break;
2035                         case ACC_DENY:
2036                                 /* Since there is no way to return a DENY acl entry *
2037                                  * change to PERMIT and then shift.                 */
2038                                 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2039                                 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2040                                 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2041                                 acl_entry_link->entryp->ace_access <<= 6;
2042                                 acl_entry_link_head->count++;
2043                                 break;
2044                         default:
2045                                 return(0);
2046                         }
2047
2048                         DEBUG(10,("acl_entry = %d\n",acl_entry));
2049                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2050  
2051                         acl_entry = acl_nxt(acl_entry);
2052                 }
2053         } /* end of if enabled */
2054
2055         /* Since owner, group, other acl entries are not *
2056          * part of the acl entries in an acl, they must  *
2057          * be dummied up to become part of the list.     */
2058
2059         for( i = 1; i < 4; i++) {
2060                 DEBUG(10,("i is %d\n",i));
2061                 if(acl_entry_link_head->count != 0) {
2062                         acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2063                         if(acl_entry_link->nextp == NULL) {
2064                                 SAFE_FREE(file_acl);
2065                                 errno = ENOMEM;
2066                                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2067                                 return(NULL);
2068                         }
2069
2070                         acl_entry_link->nextp->prevp = acl_entry_link;
2071                         acl_entry_link = acl_entry_link->nextp;
2072                         acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2073                         if(acl_entry_link->entryp == NULL) {
2074                                 SAFE_FREE(file_acl);
2075                                 errno = ENOMEM;
2076                                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
2077                                 return(NULL);
2078                         }
2079                 }
2080
2081                 acl_entry_link->nextp = NULL;
2082
2083                 new_acl_entry = acl_entry_link->entryp;
2084                 idp = new_acl_entry->ace_id;
2085
2086                 new_acl_entry->ace_len = sizeof(struct acl_entry);
2087                 new_acl_entry->ace_type = ACC_PERMIT;
2088                 idp->id_len = sizeof(struct ace_id);
2089                 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2090                 memset(idp->id_data,0,sizeof(uid_t));
2091
2092                 switch(i) {
2093                 case 2:
2094                         new_acl_entry->ace_access = file_acl->g_access << 6;
2095                         idp->id_type = SMB_ACL_GROUP_OBJ;
2096                         break;
2097
2098                 case 3:
2099                         new_acl_entry->ace_access = file_acl->o_access << 6;
2100                         idp->id_type = SMB_ACL_OTHER;
2101                         break;
2102  
2103                 case 1:
2104                         new_acl_entry->ace_access = file_acl->u_access << 6;
2105                         idp->id_type = SMB_ACL_USER_OBJ;
2106                         break;
2107  
2108                 default:
2109                         return(NULL);
2110
2111                 }
2112
2113                 acl_entry_link_head->count++;
2114                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2115         }
2116
2117         acl_entry_link_head->count = 0;
2118         SAFE_FREE(file_acl);
2119
2120         return(acl_entry_link_head);
2121 }
2122
2123 #if 0
2124 SMB_ACL_T sys_acl_get_fd(int fd)
2125 {
2126         struct acl *file_acl = (struct acl *)NULL;
2127         struct acl_entry *acl_entry;
2128         struct new_acl_entry *new_acl_entry;
2129         struct ace_id *idp;
2130         struct acl_entry_link *acl_entry_link;
2131         struct acl_entry_link *acl_entry_link_head;
2132         int i;
2133         int rc = 0;
2134         uid_t user_id;
2135
2136         /* Get the acl using fstatacl */
2137    
2138         DEBUG(10,("Entering sys_acl_get_fd\n"));
2139         DEBUG(10,("fd is %d\n",fd));
2140         file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2141
2142         if(file_acl == NULL) {
2143                 errno=ENOMEM;
2144                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2145                 return(NULL);
2146         }
2147
2148         memset(file_acl,0,BUFSIZ);
2149
2150         rc = fstatacl(fd,0,file_acl,BUFSIZ);
2151         if(rc == -1) {
2152                 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
2153                 SAFE_FREE(file_acl);
2154                 return(NULL);
2155         }
2156
2157         DEBUG(10,("Got facl and returned it\n"));
2158
2159         /* Point to the first acl entry in the acl */
2160
2161         acl_entry =  file_acl->acl_ext;
2162         /* Begin setting up the head of the linked list *
2163          * that will be used for the storing the acl    *
2164          * in a way that is useful for the posix_acls.c *
2165          * code.                                        */
2166
2167         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
2168         if(acl_entry_link_head == NULL){
2169                 SAFE_FREE(file_acl);
2170                 return(NULL);
2171         }
2172
2173         acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2174
2175         if(acl_entry_link->entryp == NULL) {
2176                 errno = ENOMEM;
2177                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2178                 SAFE_FREE(file_acl);
2179                 return(NULL);
2180         }
2181
2182         DEBUG(10,("acl_entry is %d\n",acl_entry));
2183         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
2184  
2185         /* Check if the extended acl bit is on.   *
2186          * If it isn't, do not show the           *
2187          * contents of the acl since AIX intends  *
2188          * the extended info to remain unused     */
2189  
2190         if(file_acl->acl_mode & S_IXACL){
2191                 /* while we are not pointing to the very end */
2192                 while(acl_entry < acl_last(file_acl)) {
2193                         /* before we malloc anything, make sure this is  */
2194                         /* a valid acl entry and one that we want to map */
2195
2196                         idp = id_nxt(acl_entry->ace_id);
2197                         if((acl_entry->ace_type == ACC_SPECIFY ||
2198                                 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
2199                                         acl_entry = acl_nxt(acl_entry);
2200                                         continue;
2201                         }
2202
2203                         idp = acl_entry->ace_id;
2204  
2205                         /* Check if this is the first entry in the linked list. *
2206                          * The first entry needs to keep prevp pointing to NULL *
2207                          * and already has entryp allocated.                 */
2208
2209                         if(acl_entry_link_head->count != 0) {
2210                                 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2211                                 if(acl_entry_link->nextp == NULL) {
2212                                         errno = ENOMEM;
2213                                         DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2214                                         SAFE_FREE(file_acl);
2215                                         return(NULL);
2216                                 }
2217                                 acl_entry_link->nextp->prevp = acl_entry_link;
2218                                 acl_entry_link = acl_entry_link->nextp;
2219                                 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2220                                 if(acl_entry_link->entryp == NULL) {
2221                                         errno = ENOMEM;
2222                                         DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2223                                         SAFE_FREE(file_acl);
2224                                         return(NULL);
2225                                 }
2226
2227                                 acl_entry_link->nextp = NULL;
2228                         }
2229
2230                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
2231
2232                         /* Don't really need this since all types are going *
2233                          * to be specified but, it's better than leaving it 0 */
2234
2235                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
2236                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2237
2238                         memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
2239
2240                         /* The access in the acl entries must be left shifted by *
2241                          * three bites, because they will ultimately be compared *
2242                          * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
2243
2244                         switch(acl_entry->ace_type){
2245                         case ACC_PERMIT:
2246                         case ACC_SPECIFY:
2247                                 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
2248                                 acl_entry_link->entryp->ace_access <<= 6;
2249                                 acl_entry_link_head->count++;
2250                                 break;
2251                         case ACC_DENY:
2252                                 /* Since there is no way to return a DENY acl entry *
2253                                  * change to PERMIT and then shift.                 */
2254                                 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
2255                                 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
2256                                 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
2257                                 acl_entry_link->entryp->ace_access <<= 6;
2258                                 acl_entry_link_head->count++;
2259                                 break;
2260                         default:
2261                                 return(0);
2262                         }
2263
2264                         DEBUG(10,("acl_entry = %d\n",acl_entry));
2265                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
2266  
2267                         acl_entry = acl_nxt(acl_entry);
2268                 }
2269         } /* end of if enabled */
2270
2271         /* Since owner, group, other acl entries are not *
2272          * part of the acl entries in an acl, they must  *
2273          * be dummied up to become part of the list.     */
2274
2275         for( i = 1; i < 4; i++) {
2276                 DEBUG(10,("i is %d\n",i));
2277                 if(acl_entry_link_head->count != 0){
2278                         acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
2279                         if(acl_entry_link->nextp == NULL) {
2280                                 errno = ENOMEM;
2281                                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2282                                 SAFE_FREE(file_acl);
2283                                 return(NULL);
2284                         }
2285
2286                         acl_entry_link->nextp->prevp = acl_entry_link;
2287                         acl_entry_link = acl_entry_link->nextp;
2288                         acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
2289
2290                         if(acl_entry_link->entryp == NULL) {
2291                                 SAFE_FREE(file_acl);
2292                                 errno = ENOMEM;
2293                                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
2294                                 return(NULL);
2295                         }
2296                 }
2297
2298                 acl_entry_link->nextp = NULL;
2299  
2300                 new_acl_entry = acl_entry_link->entryp;
2301                 idp = new_acl_entry->ace_id;
2302  
2303                 new_acl_entry->ace_len = sizeof(struct acl_entry);
2304                 new_acl_entry->ace_type = ACC_PERMIT;
2305                 idp->id_len = sizeof(struct ace_id);
2306                 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
2307                 memset(idp->id_data,0,sizeof(uid_t));
2308  
2309                 switch(i) {
2310                 case 2:
2311                         new_acl_entry->ace_access = file_acl->g_access << 6;
2312                         idp->id_type = SMB_ACL_GROUP_OBJ;
2313                         break;
2314  
2315                 case 3:
2316                         new_acl_entry->ace_access = file_acl->o_access << 6;
2317                         idp->id_type = SMB_ACL_OTHER;
2318                         break;
2319  
2320                 case 1:
2321                         new_acl_entry->ace_access = file_acl->u_access << 6;
2322                         idp->id_type = SMB_ACL_USER_OBJ;
2323                         break;
2324  
2325                 default:
2326                         return(NULL);
2327                 }
2328  
2329                 acl_entry_link_head->count++;
2330                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
2331         }
2332
2333         acl_entry_link_head->count = 0;
2334         SAFE_FREE(file_acl);
2335  
2336         return(acl_entry_link_head);
2337 }
2338 #endif
2339
2340 SMB_ACL_T sys_acl_init( int count)
2341 {
2342         struct acl_entry_link *theacl = NULL;
2343  
2344         DEBUG(10,("Entering sys_acl_init\n"));
2345
2346         theacl = SMB_MALLOC_P(struct acl_entry_link);
2347         if(theacl == NULL) {
2348                 errno = ENOMEM;
2349                 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
2350                 return(NULL);
2351         }
2352
2353         theacl->count = 0;
2354         theacl->nextp = NULL;
2355         theacl->prevp = NULL;
2356         theacl->entryp = NULL;
2357         DEBUG(10,("Exiting sys_acl_init\n"));
2358         return(theacl);
2359 }
2360
2361 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2362 {
2363         struct acl_entry_link *theacl;
2364         struct acl_entry_link *acl_entryp;
2365         struct acl_entry_link *temp_entry;
2366         int counting;
2367
2368         DEBUG(10,("Entering the sys_acl_create_entry\n"));
2369
2370         theacl = acl_entryp = *pacl;
2371
2372         /* Get to the end of the acl before adding entry */
2373
2374         for(counting=0; counting < theacl->count; counting++){
2375                 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2376                 temp_entry = acl_entryp;
2377                 acl_entryp = acl_entryp->nextp;
2378         }
2379
2380         if(theacl->count != 0){
2381                 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
2382                 if(acl_entryp == NULL) {
2383                         errno = ENOMEM;
2384                         DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2385                         return(-1);
2386                 }
2387
2388                 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
2389                 acl_entryp->prevp = temp_entry;
2390                 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
2391         }
2392
2393         *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
2394         if(*pentry == NULL) {
2395                 errno = ENOMEM;
2396                 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
2397                 return(-1);
2398         }
2399
2400         memset(*pentry,0,sizeof(struct new_acl_entry));
2401         acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
2402         acl_entryp->entryp->ace_type = ACC_PERMIT;
2403         acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
2404         acl_entryp->nextp = NULL;
2405         theacl->count++;
2406         DEBUG(10,("Exiting sys_acl_create_entry\n"));
2407         return(0);
2408 }
2409
2410 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2411 {
2412         DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
2413         entry->ace_id->id_type = tagtype;
2414         DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
2415         DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
2416 }
2417
2418 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2419 {
2420         DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
2421         memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
2422         DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
2423         return(0);
2424 }
2425
2426 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits)
2427 {
2428         DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
2429         entry->ace_access = bits;
2430         DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
2431         DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
2432         return(0);
2433 }
2434
2435 int sys_acl_valid( SMB_ACL_T theacl )
2436 {
2437         int user_obj = 0;
2438         int group_obj = 0;
2439         int other_obj = 0;
2440         struct acl_entry_link *acl_entry;
2441
2442         for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
2443                 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
2444                 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
2445                 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
2446         }
2447
2448         DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
2449  
2450         if(user_obj != 1 || group_obj != 1 || other_obj != 1)
2451                 return(-1); 
2452
2453         return(0);
2454 }
2455
2456 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2457 {
2458         struct acl_entry_link *acl_entry_link = NULL;
2459         struct acl *file_acl = NULL;
2460         struct acl *file_acl_temp = NULL;
2461         struct acl_entry *acl_entry = NULL;
2462         struct ace_id *ace_id = NULL;
2463         uint id_type;
2464         uint ace_access;
2465         uint user_id;
2466         uint acl_length;
2467         uint rc;
2468
2469         DEBUG(10,("Entering sys_acl_set_file\n"));
2470         DEBUG(10,("File name is %s\n",name));
2471  
2472         /* AIX has no default ACL */
2473         if(acltype == SMB_ACL_TYPE_DEFAULT)
2474                 return(0);
2475
2476         acl_length = BUFSIZ;
2477         file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2478
2479         if(file_acl == NULL) {
2480                 errno = ENOMEM;
2481                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2482                 return(-1);
2483         }
2484
2485         memset(file_acl,0,BUFSIZ);
2486
2487         file_acl->acl_len = ACL_SIZ;
2488         file_acl->acl_mode = S_IXACL;
2489
2490         for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2491                 acl_entry_link->entryp->ace_access >>= 6;
2492                 id_type = acl_entry_link->entryp->ace_id->id_type;
2493
2494                 switch(id_type) {
2495                 case SMB_ACL_USER_OBJ:
2496                         file_acl->u_access = acl_entry_link->entryp->ace_access;
2497                         continue;
2498                 case SMB_ACL_GROUP_OBJ:
2499                         file_acl->g_access = acl_entry_link->entryp->ace_access;
2500                         continue;
2501                 case SMB_ACL_OTHER:
2502                         file_acl->o_access = acl_entry_link->entryp->ace_access;
2503                         continue;
2504                 case SMB_ACL_MASK:
2505                         continue;
2506                 }
2507
2508                 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2509                         acl_length += sizeof(struct acl_entry);
2510                         file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2511                         if(file_acl_temp == NULL) {
2512                                 SAFE_FREE(file_acl);
2513                                 errno = ENOMEM;
2514                                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
2515                                 return(-1);
2516                         }  
2517
2518                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2519                         SAFE_FREE(file_acl);
2520                         file_acl = file_acl_temp;
2521                 }
2522
2523                 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2524                 file_acl->acl_len += sizeof(struct acl_entry);
2525                 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2526                 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2527  
2528                 /* In order to use this, we'll need to wait until we can get denies */
2529                 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2530                 acl_entry->ace_type = ACC_SPECIFY; */
2531
2532                 acl_entry->ace_type = ACC_SPECIFY;
2533  
2534                 ace_id = acl_entry->ace_id;
2535  
2536                 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2537                 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2538                 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2539                 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2540                 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
2541         }
2542
2543         rc = chacl(name,file_acl,file_acl->acl_len);
2544         DEBUG(10,("errno is %d\n",errno));
2545         DEBUG(10,("return code is %d\n",rc));
2546         SAFE_FREE(file_acl);
2547         DEBUG(10,("Exiting the sys_acl_set_file\n"));
2548         return(rc);
2549 }
2550
2551 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2552 {
2553         struct acl_entry_link *acl_entry_link = NULL;
2554         struct acl *file_acl = NULL;
2555         struct acl *file_acl_temp = NULL;
2556         struct acl_entry *acl_entry = NULL;
2557         struct ace_id *ace_id = NULL;
2558         uint id_type;
2559         uint user_id;
2560         uint acl_length;
2561         uint rc;
2562  
2563         DEBUG(10,("Entering sys_acl_set_fd\n"));
2564         acl_length = BUFSIZ;
2565         file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
2566
2567         if(file_acl == NULL) {
2568                 errno = ENOMEM;
2569                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2570                 return(-1);
2571         }
2572
2573         memset(file_acl,0,BUFSIZ);
2574  
2575         file_acl->acl_len = ACL_SIZ;
2576         file_acl->acl_mode = S_IXACL;
2577
2578         for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2579                 acl_entry_link->entryp->ace_access >>= 6;
2580                 id_type = acl_entry_link->entryp->ace_id->id_type;
2581                 DEBUG(10,("The id_type is %d\n",id_type));
2582
2583                 switch(id_type) {
2584                 case SMB_ACL_USER_OBJ:
2585                         file_acl->u_access = acl_entry_link->entryp->ace_access;
2586                         continue;
2587                 case SMB_ACL_GROUP_OBJ:
2588                         file_acl->g_access = acl_entry_link->entryp->ace_access;
2589                         continue;
2590                 case SMB_ACL_OTHER:
2591                         file_acl->o_access = acl_entry_link->entryp->ace_access;
2592                         continue;
2593                 case SMB_ACL_MASK:
2594                         continue;
2595                 }
2596
2597                 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2598                         acl_length += sizeof(struct acl_entry);
2599                         file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
2600                         if(file_acl_temp == NULL) {
2601                                 SAFE_FREE(file_acl);
2602                                 errno = ENOMEM;
2603                                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2604                                 return(-1);
2605                         }
2606
2607                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2608                         SAFE_FREE(file_acl);
2609                         file_acl = file_acl_temp;
2610                 }
2611
2612                 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2613                 file_acl->acl_len += sizeof(struct acl_entry);
2614                 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2615                 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2616  
2617                 /* In order to use this, we'll need to wait until we can get denies */
2618                 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2619                         acl_entry->ace_type = ACC_SPECIFY; */
2620  
2621                 acl_entry->ace_type = ACC_SPECIFY;
2622  
2623                 ace_id = acl_entry->ace_id;
2624  
2625                 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2626                 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2627                 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2628                 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2629                 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2630         }
2631  
2632         rc = fchacl(fd,file_acl,file_acl->acl_len);
2633         DEBUG(10,("errno is %d\n",errno));
2634         DEBUG(10,("return code is %d\n",rc));
2635         SAFE_FREE(file_acl);
2636         DEBUG(10,("Exiting sys_acl_set_fd\n"));
2637         return(rc);
2638 }
2639
2640 int sys_acl_delete_def_file(const char *name)
2641 {
2642         /* AIX has no default ACL */
2643         return 0;
2644 }
2645
2646 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2647 {
2648         struct acl_entry_link *acl_entry_link;
2649
2650         for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2651                 SAFE_FREE(acl_entry_link->prevp->entryp);
2652                 SAFE_FREE(acl_entry_link->prevp);
2653         }
2654
2655         SAFE_FREE(acl_entry_link->prevp->entryp);
2656         SAFE_FREE(acl_entry_link->prevp);
2657         SAFE_FREE(acl_entry_link->entryp);
2658         SAFE_FREE(acl_entry_link);
2659  
2660         return(0);
2661 }
2662
2663 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2664 {
2665         return(0);
2666 }
2667
2668 #else /* No ACLs. */
2669
2670 #error No ACL functions defined for this platform!
2671
2672 #endif
2673
2674 /************************************************************************
2675  Deliberately outside the ACL defines. Return 1 if this is a "no acls"
2676  errno, 0 if not.
2677 ************************************************************************/
2678
2679 int no_acl_syscall_error(int err)
2680 {
2681 #if defined(ENOSYS)
2682         if (err == ENOSYS) {
2683                 return 1;
2684         }
2685 #endif
2686 #if defined(ENOTSUP)
2687         if (err == ENOTSUP) {
2688                 return 1;
2689         }
2690 #endif
2691         return 0;
2692 }
2693
2694 #endif /* SUPPORT_ACLS */