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