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