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