Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header.
[samba.git] / source3 / lib / sysacls.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.2.
4    Samba system utilities for ACL support.
5    Copyright (C) Jeremy Allison 2000.
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 /*
25  This file wraps all differing system ACL interfaces into a consistent
26  one based on the POSIX interface. It also returns the correct errors
27  for older UNIX systems that don't support ACLs.
28
29  The interfaces that each ACL implementation must support are as follows :
30
31  int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
32  int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
33  int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p
34  void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
35  SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
36  SMB_ACL_T sys_acl_get_fd(int fd)
37  int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset);
38  int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
39  char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
40  SMB_ACL_T sys_acl_init( int count)
41  int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
42  int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
43  int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
44  int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
45  int sys_acl_valid( SMB_ACL_T theacl )
46  int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
47  int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
48  int sys_acl_delete_def_file(const char *path)
49
50  This next one is not POSIX complient - but we *have* to have it !
51  More POSIX braindamage.
52
53  int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
54
55  The generic POSIX free is the following call. We split this into
56  several different free functions as we may need to add tag info
57  to structures when emulating the POSIX interface.
58
59  int sys_acl_free( void *obj_p)
60
61  The calls we actually use are :
62
63  int sys_acl_free_text(char *text) - free acl_to_text
64  int sys_acl_free_acl(SMB_ACL_T posix_acl)
65  int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
66
67 */
68
69 #if defined(HAVE_POSIX_ACLS)
70
71 /* Identity mapping - easy. */
72
73 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
74 {
75         return acl_get_entry( the_acl, entry_id, entry_p);
76 }
77
78 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
79 {
80         return acl_get_tag_type( entry_d, tag_type_p);
81 }
82
83 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
84 {
85         return acl_get_permset( entry_d, permset_p);
86 }
87
88 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
89 {
90         return acl_get_qualifier( entry_d);
91 }
92
93 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
94 {
95         return acl_get_file( path_p, type);
96 }
97
98 SMB_ACL_T sys_acl_get_fd(int fd)
99 {
100         return acl_get_fd(fd);
101 }
102
103 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
104 {
105         return acl_clear_perms(permset);
106 }
107
108 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
109 {
110         return acl_add_perm(permset, perm);
111 }
112
113 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
114 {
115 #if defined(HAVE_ACL_GET_PERM_NP)
116         /*
117          * Required for TrustedBSD-based ACL implementations where
118          * non-POSIX.1e functions are denoted by a _np (non-portable)
119          * suffix.
120          */
121         return acl_get_perm_np(permset, perm);
122 #else
123         return acl_get_perm(permset, perm);
124 #endif
125 }
126
127 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
128 {
129         return acl_to_text( the_acl, plen);
130 }
131
132 SMB_ACL_T sys_acl_init( int count)
133 {
134         return acl_init(count);
135 }
136
137 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
138 {
139         return acl_create_entry(pacl, pentry);
140 }
141
142 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
143 {
144         return acl_set_tag_type(entry, tagtype);
145 }
146
147 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
148 {
149         return acl_set_qualifier(entry, qual);
150 }
151
152 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
153 {
154         return acl_set_permset(entry, permset);
155 }
156
157 int sys_acl_valid( SMB_ACL_T theacl )
158 {
159         return acl_valid(theacl);
160 }
161
162 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
163 {
164         return acl_set_file(name, acltype, theacl);
165 }
166
167 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
168 {
169         return acl_set_fd(fd, theacl);
170 }
171
172 int sys_acl_delete_def_file(const char *name)
173 {
174         return acl_delete_def_file(name);
175 }
176
177 int sys_acl_free_text(char *text)
178 {
179         return acl_free(text);
180 }
181
182 int sys_acl_free_acl(SMB_ACL_T the_acl) 
183 {
184         return acl_free(the_acl);
185 }
186
187 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
188 {
189         return acl_free(qual);
190 }
191
192 #elif defined(HAVE_TRU64_ACLS)
193 /*
194  * The interface to DEC/Compaq Tru64 UNIX ACLs
195  * is based on Draft 13 of the POSIX spec which is
196  * slightly different from the Draft 16 interface.
197  * 
198  * Also, some of the permset manipulation functions
199  * such as acl_clear_perm() and acl_add_perm() appear
200  * to be broken on Tru64 so we have to manipulate
201  * the permission bits in the permset directly.
202  */
203 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
204 {
205         SMB_ACL_ENTRY_T entry;
206
207         if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
208                 return -1;
209         }
210
211         errno = 0;
212         if ((entry = acl_get_entry(the_acl)) != NULL) {
213                 *entry_p = entry;
214                 return 1;
215         }
216
217         return errno ? -1 : 0;
218 }
219
220 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
221 {
222         return acl_get_tag_type( entry_d, tag_type_p);
223 }
224
225 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
226 {
227         return acl_get_permset( entry_d, permset_p);
228 }
229
230 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
231 {
232         return acl_get_qualifier( entry_d);
233 }
234
235 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
236 {
237         return acl_get_file((char *)path_p, type);
238 }
239
240 SMB_ACL_T sys_acl_get_fd(int fd)
241 {
242         return acl_get_fd(fd, ACL_TYPE_ACCESS);
243 }
244
245 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
246 {
247         *permset = 0;           /* acl_clear_perm() is broken on Tru64  */
248
249         return 0;
250 }
251
252 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
253 {
254         if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) {
255                 errno = EINVAL;
256                 return -1;
257         }
258
259         *permset |= perm;       /* acl_add_perm() is broken on Tru64    */
260
261         return 0;
262 }
263
264 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
265 {
266         return *permset & perm; /* Tru64 doesn't have acl_get_perm() */
267 }
268
269 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
270 {
271         return acl_to_text( the_acl, plen);
272 }
273
274 SMB_ACL_T sys_acl_init( int count)
275 {
276         return acl_init(count);
277 }
278
279 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
280 {
281         SMB_ACL_ENTRY_T entry;
282
283         if ((entry = acl_create_entry(pacl)) == NULL) {
284                 return -1;
285         }
286
287         *pentry = entry;
288         return 0;
289 }
290
291 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
292 {
293         return acl_set_tag_type(entry, tagtype);
294 }
295
296 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
297 {
298         return acl_set_qualifier(entry, qual);
299 }
300
301 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
302 {
303         return acl_set_permset(entry, permset);
304 }
305
306 int sys_acl_valid( SMB_ACL_T theacl )
307 {
308         acl_entry_t     entry;
309
310         return acl_valid(theacl, &entry);
311 }
312
313 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
314 {
315         return acl_set_file((char *)name, acltype, theacl);
316 }
317
318 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
319 {
320         return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
321 }
322
323 int sys_acl_delete_def_file(const char *name)
324 {
325         return acl_delete_def_file((char *)name);
326 }
327
328 int sys_acl_free_text(char *text)
329 {
330         /*
331          * (void) cast and explicit return 0 are for DEC UNIX
332          *  which just #defines acl_free_text() to be free()
333          */
334         (void) acl_free_text(text);
335         return 0;
336 }
337
338 int sys_acl_free_acl(SMB_ACL_T the_acl) 
339 {
340         return acl_free(the_acl);
341 }
342
343 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
344 {
345         return acl_free_qualifier(qual, tagtype);
346 }
347
348 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
349
350 /*
351  * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
352  * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
353  */
354
355 /*
356  * Note that while this code implements sufficient functionality
357  * to support the sys_acl_* interfaces it does not provide all
358  * of the semantics of the POSIX ACL interfaces.
359  *
360  * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
361  * from a call to sys_acl_get_entry() should not be assumed to be
362  * valid after calling any of the following functions, which may
363  * reorder the entries in the ACL.
364  *
365  *      sys_acl_valid()
366  *      sys_acl_set_file()
367  *      sys_acl_set_fd()
368  */
369
370 /*
371  * The only difference between Solaris and UnixWare / OpenUNIX is
372  * that the #defines for the ACL operations have different names
373  */
374 #if defined(HAVE_UNIXWARE_ACLS)
375
376 #define SETACL          ACL_SET
377 #define GETACL          ACL_GET
378 #define GETACLCNT       ACL_CNT
379
380 #endif
381
382
383 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
384 {
385         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
386                 errno = EINVAL;
387                 return -1;
388         }
389
390         if (entry_p == NULL) {
391                 errno = EINVAL;
392                 return -1;
393         }
394
395         if (entry_id == SMB_ACL_FIRST_ENTRY) {
396                 acl_d->next = 0;
397         }
398
399         if (acl_d->next < 0) {
400                 errno = EINVAL;
401                 return -1;
402         }
403
404         if (acl_d->next >= acl_d->count) {
405                 return 0;
406         }
407
408         *entry_p = &acl_d->acl[acl_d->next++];
409
410         return 1;
411 }
412
413 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
414 {
415         *type_p = entry_d->a_type;
416
417         return 0;
418 }
419
420 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
421 {
422         *permset_p = &entry_d->a_perm;
423
424         return 0;
425 }
426
427 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
428 {
429         if (entry_d->a_type != SMB_ACL_USER
430             && entry_d->a_type != SMB_ACL_GROUP) {
431                 errno = EINVAL;
432                 return NULL;
433         }
434
435         return &entry_d->a_id;
436 }
437
438 /*
439  * There is no way of knowing what size the ACL returned by
440  * GETACL will be unless you first call GETACLCNT which means
441  * making an additional system call.
442  *
443  * In the hope of avoiding the cost of the additional system
444  * call in most cases, we initially allocate enough space for
445  * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
446  * be too small then we use GETACLCNT to find out the actual
447  * size, reallocate the ACL buffer, and then call GETACL again.
448  */
449
450 #define INITIAL_ACL_SIZE        16
451
452 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
453 {
454         SMB_ACL_T       acl_d;
455         int             count;          /* # of ACL entries allocated   */
456         int             naccess;        /* # of access ACL entries      */
457         int             ndefault;       /* # of default ACL entries     */
458
459         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
460                 errno = EINVAL;
461                 return NULL;
462         }
463
464         count = INITIAL_ACL_SIZE;
465         if ((acl_d = sys_acl_init(count)) == NULL) {
466                 return NULL;
467         }
468
469         /*
470          * If there isn't enough space for the ACL entries we use
471          * GETACLCNT to determine the actual number of ACL entries
472          * reallocate and try again. This is in a loop because it
473          * is possible that someone else could modify the ACL and
474          * increase the number of entries between the call to
475          * GETACLCNT and the call to GETACL.
476          */
477         while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
478             && errno == ENOSPC) {
479
480                 sys_acl_free_acl(acl_d);
481
482                 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
483                         return NULL;
484                 }
485
486                 if ((acl_d = sys_acl_init(count)) == NULL) {
487                         return NULL;
488                 }
489         }
490
491         if (count < 0) {
492                 sys_acl_free_acl(acl_d);
493                 return NULL;
494         }
495
496         /*
497          * calculate the number of access and default ACL entries
498          *
499          * Note: we assume that the acl() system call returned a
500          * well formed ACL which is sorted so that all of the
501          * access ACL entries preceed any default ACL entries
502          */
503         for (naccess = 0; naccess < count; naccess++) {
504                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
505                         break;
506         }
507         ndefault = count - naccess;
508         
509         /*
510          * if the caller wants the default ACL we have to copy
511          * the entries down to the start of the acl[] buffer
512          * and mask out the ACL_DEFAULT flag from the type field
513          */
514         if (type == SMB_ACL_TYPE_DEFAULT) {
515                 int     i, j;
516
517                 for (i = 0, j = naccess; i < ndefault; i++, j++) {
518                         acl_d->acl[i] = acl_d->acl[j];
519                         acl_d->acl[i].a_type &= ~ACL_DEFAULT;
520                 }
521
522                 acl_d->count = ndefault;
523         } else {
524                 acl_d->count = naccess;
525         }
526
527         return acl_d;
528 }
529
530 SMB_ACL_T sys_acl_get_fd(int fd)
531 {
532         SMB_ACL_T       acl_d;
533         int             count;          /* # of ACL entries allocated   */
534         int             naccess;        /* # of access ACL entries      */
535
536         count = INITIAL_ACL_SIZE;
537         if ((acl_d = sys_acl_init(count)) == NULL) {
538                 return NULL;
539         }
540
541         while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
542             && errno == ENOSPC) {
543
544                 sys_acl_free_acl(acl_d);
545
546                 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
547                         return NULL;
548                 }
549
550                 if ((acl_d = sys_acl_init(count)) == NULL) {
551                         return NULL;
552                 }
553         }
554
555         if (count < 0) {
556                 sys_acl_free_acl(acl_d);
557                 return NULL;
558         }
559
560         /*
561          * calculate the number of access ACL entries
562          */
563         for (naccess = 0; naccess < count; naccess++) {
564                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
565                         break;
566         }
567         
568         acl_d->count = naccess;
569
570         return acl_d;
571 }
572
573 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
574 {
575         *permset_d = 0;
576
577         return 0;
578 }
579
580 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
581 {
582         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
583             && perm != SMB_ACL_EXECUTE) {
584                 errno = EINVAL;
585                 return -1;
586         }
587
588         if (permset_d == NULL) {
589                 errno = EINVAL;
590                 return -1;
591         }
592
593         *permset_d |= perm;
594
595         return 0;
596 }
597
598 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
599 {
600         return *permset_d & perm;
601 }
602
603 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
604 {
605         int     i;
606         int     len, maxlen;
607         char    *text;
608
609         /*
610          * use an initial estimate of 20 bytes per ACL entry
611          * when allocating memory for the text representation
612          * of the ACL
613          */
614         len     = 0;
615         maxlen  = 20 * acl_d->count;
616         if ((text = malloc(maxlen)) == NULL) {
617                 errno = ENOMEM;
618                 return NULL;
619         }
620
621         for (i = 0; i < acl_d->count; i++) {
622                 struct acl      *ap     = &acl_d->acl[i];
623                 struct passwd   *pw;
624                 struct group    *gr;
625                 char            tagbuf[12];
626                 char            idbuf[12];
627                 char            *tag;
628                 char            *id     = "";
629                 char            perms[4];
630                 int             nbytes;
631
632                 switch (ap->a_type) {
633                         /*
634                          * for debugging purposes it's probably more
635                          * useful to dump unknown tag types rather
636                          * than just returning an error
637                          */
638                         default:
639                                 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
640                                         ap->a_type);
641                                 tag = tagbuf;
642                                 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
643                                         (long)ap->a_id);
644                                 id = idbuf;
645                                 break;
646
647                         case SMB_ACL_USER:
648                                 if ((pw = sys_getpwuid(ap->a_id)) == NULL) {
649                                         slprintf(idbuf, sizeof(idbuf)-1, "%ld",
650                                                 (long)ap->a_id);
651                                         id = idbuf;
652                                 } else {
653                                         id = pw->pw_name;
654                                 }
655                         case SMB_ACL_USER_OBJ:
656                                 tag = "user";
657                                 break;
658
659                         case SMB_ACL_GROUP:
660                                 if ((gr = getgrgid(ap->a_id)) == NULL) {
661                                         slprintf(idbuf, sizeof(idbuf)-1, "%ld",
662                                                 (long)ap->a_id);
663                                         id = idbuf;
664                                 } else {
665                                         id = gr->gr_name;
666                                 }
667                         case SMB_ACL_GROUP_OBJ:
668                                 tag = "group";
669                                 break;
670
671                         case SMB_ACL_OTHER:
672                                 tag = "other";
673                                 break;
674
675                         case SMB_ACL_MASK:
676                                 tag = "mask";
677                                 break;
678
679                 }
680
681                 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
682                 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
683                 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
684                 perms[3] = '\0';
685
686                 /*          <tag>      :  <qualifier>   :  rwx \n  \0 */
687                 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
688
689                 /*
690                  * If this entry would overflow the buffer
691                  * allocate enough additional memory for this
692                  * entry and an estimate of another 20 bytes
693                  * for each entry still to be processed
694                  */
695                 if ((len + nbytes) > maxlen) {
696                         char *oldtext = text;
697
698                         maxlen += nbytes + 20 * (acl_d->count - i);
699
700                         if ((text = Realloc(oldtext, maxlen)) == NULL) {
701                                 SAFE_FREE(oldtext);
702                                 errno = ENOMEM;
703                                 return NULL;
704                         }
705                 }
706
707                 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
708                 len += nbytes - 1;
709         }
710
711         if (len_p)
712                 *len_p = len;
713
714         return text;
715 }
716
717 SMB_ACL_T sys_acl_init(int count)
718 {
719         SMB_ACL_T       a;
720
721         if (count < 0) {
722                 errno = EINVAL;
723                 return NULL;
724         }
725
726         /*
727          * note that since the definition of the structure pointed
728          * to by the SMB_ACL_T includes the first element of the
729          * acl[] array, this actually allocates an ACL with room
730          * for (count+1) entries
731          */
732         if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) {
733                 errno = ENOMEM;
734                 return NULL;
735         }
736
737         a->size = count + 1;
738         a->count = 0;
739         a->next = -1;
740
741         return a;
742 }
743
744
745 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
746 {
747         SMB_ACL_T       acl_d;
748         SMB_ACL_ENTRY_T entry_d;
749
750         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
751                 errno = EINVAL;
752                 return -1;
753         }
754
755         if (acl_d->count >= acl_d->size) {
756                 errno = ENOSPC;
757                 return -1;
758         }
759
760         entry_d         = &acl_d->acl[acl_d->count++];
761         entry_d->a_type = 0;
762         entry_d->a_id   = -1;
763         entry_d->a_perm = 0;
764         *entry_p        = entry_d;
765
766         return 0;
767 }
768
769 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
770 {
771         switch (tag_type) {
772                 case SMB_ACL_USER:
773                 case SMB_ACL_USER_OBJ:
774                 case SMB_ACL_GROUP:
775                 case SMB_ACL_GROUP_OBJ:
776                 case SMB_ACL_OTHER:
777                 case SMB_ACL_MASK:
778                         entry_d->a_type = tag_type;
779                         break;
780                 default:
781                         errno = EINVAL;
782                         return -1;
783         }
784
785         return 0;
786 }
787
788 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
789 {
790         if (entry_d->a_type != SMB_ACL_GROUP
791             && entry_d->a_type != SMB_ACL_USER) {
792                 errno = EINVAL;
793                 return -1;
794         }
795
796         entry_d->a_id = *((id_t *)qual_p);
797
798         return 0;
799 }
800
801 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
802 {
803         if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
804                 return EINVAL;
805         }
806
807         entry_d->a_perm = *permset_d;
808
809         return 0;
810 }
811
812 /*
813  * sort the ACL and check it for validity
814  *
815  * if it's a minimal ACL with only 4 entries then we
816  * need to recalculate the mask permissions to make
817  * sure that they are the same as the GROUP_OBJ
818  * permissions as required by the UnixWare acl() system call.
819  *
820  * (note: since POSIX allows minimal ACLs which only contain
821  * 3 entries - ie there is no mask entry - we should, in theory,
822  * check for this and add a mask entry if necessary - however
823  * we "know" that the caller of this interface always specifies
824  * a mask so, in practice "this never happens" (tm) - if it *does*
825  * happen aclsort() will fail and return an error and someone will
826  * have to fix it ...)
827  */
828
829 static int acl_sort(SMB_ACL_T acl_d)
830 {
831         int     fixmask = (acl_d->count <= 4);
832
833         if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
834                 errno = EINVAL;
835                 return -1;
836         }
837         return 0;
838 }
839  
840 int sys_acl_valid(SMB_ACL_T acl_d)
841 {
842         return acl_sort(acl_d);
843 }
844
845 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
846 {
847         struct stat     s;
848         struct acl      *acl_p;
849         int             acl_count;
850         struct acl      *acl_buf        = NULL;
851         int             ret;
852
853         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
854                 errno = EINVAL;
855                 return -1;
856         }
857
858         if (acl_sort(acl_d) != 0) {
859                 return -1;
860         }
861
862         acl_p           = &acl_d->acl[0];
863         acl_count       = acl_d->count;
864
865         /*
866          * if it's a directory there is extra work to do
867          * since the acl() system call will replace both
868          * the access ACLs and the default ACLs (if any)
869          */
870         if (stat(name, &s) != 0) {
871                 return -1;
872         }
873         if (S_ISDIR(s.st_mode)) {
874                 SMB_ACL_T       acc_acl;
875                 SMB_ACL_T       def_acl;
876                 SMB_ACL_T       tmp_acl;
877                 int             i;
878
879                 if (type == SMB_ACL_TYPE_ACCESS) {
880                         acc_acl = acl_d;
881                         def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
882
883                 } else {
884                         def_acl = acl_d;
885                         acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
886                 }
887
888                 if (tmp_acl == NULL) {
889                         return -1;
890                 }
891
892                 /*
893                  * allocate a temporary buffer for the complete ACL
894                  */
895                 acl_count = acc_acl->count + def_acl->count;
896                 acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0]));
897
898                 if (acl_buf == NULL) {
899                         sys_acl_free_acl(tmp_acl);
900                         errno = ENOMEM;
901                         return -1;
902                 }
903
904                 /*
905                  * copy the access control and default entries into the buffer
906                  */
907                 memcpy(&acl_buf[0], &acc_acl->acl[0],
908                         acc_acl->count * sizeof(acl_buf[0]));
909
910                 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
911                         def_acl->count * sizeof(acl_buf[0]));
912
913                 /*
914                  * set the ACL_DEFAULT flag on the default entries
915                  */
916                 for (i = acc_acl->count; i < acl_count; i++) {
917                         acl_buf[i].a_type |= ACL_DEFAULT;
918                 }
919
920                 sys_acl_free_acl(tmp_acl);
921
922         } else if (type != SMB_ACL_TYPE_ACCESS) {
923                 errno = EINVAL;
924                 return -1;
925         }
926
927         ret = acl(name, SETACL, acl_count, acl_p);
928
929         SAFE_FREE(acl_buf);
930
931         return ret;
932 }
933
934 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
935 {
936         if (acl_sort(acl_d) != 0) {
937                 return -1;
938         }
939
940         return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
941 }
942
943 int sys_acl_delete_def_file(const char *path)
944 {
945         SMB_ACL_T       acl_d;
946         int             ret;
947
948         /*
949          * fetching the access ACL and rewriting it has
950          * the effect of deleting the default ACL
951          */
952         if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
953                 return -1;
954         }
955
956         ret = acl(path, SETACL, acl_d->count, acl_d->acl);
957
958         sys_acl_free_acl(acl_d);
959         
960         return ret;
961 }
962
963 int sys_acl_free_text(char *text)
964 {
965         SAFE_FREE(text);
966         return 0;
967 }
968
969 int sys_acl_free_acl(SMB_ACL_T acl_d) 
970 {
971         SAFE_FREE(acl_d);
972         return 0;
973 }
974
975 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
976 {
977         return 0;
978 }
979
980 #elif defined(HAVE_IRIX_ACLS)
981
982 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
983 {
984         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
985                 errno = EINVAL;
986                 return -1;
987         }
988
989         if (entry_p == NULL) {
990                 errno = EINVAL;
991                 return -1;
992         }
993
994         if (entry_id == SMB_ACL_FIRST_ENTRY) {
995                 acl_d->next = 0;
996         }
997
998         if (acl_d->next < 0) {
999                 errno = EINVAL;
1000                 return -1;
1001         }
1002
1003         if (acl_d->next >= acl_d->aclp->acl_cnt) {
1004                 return 0;
1005         }
1006
1007         *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
1008
1009         return 1;
1010 }
1011
1012 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
1013 {
1014         *type_p = entry_d->ae_tag;
1015
1016         return 0;
1017 }
1018
1019 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1020 {
1021         *permset_p = entry_d;
1022
1023         return 0;
1024 }
1025
1026 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
1027 {
1028         if (entry_d->ae_tag != SMB_ACL_USER
1029             && entry_d->ae_tag != SMB_ACL_GROUP) {
1030                 errno = EINVAL;
1031                 return NULL;
1032         }
1033
1034         return &entry_d->ae_id;
1035 }
1036
1037 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
1038 {
1039         SMB_ACL_T       a;
1040
1041         if ((a = malloc(sizeof(*a))) == NULL) {
1042                 errno = ENOMEM;
1043                 return NULL;
1044         }
1045         if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
1046                 SAFE_FREE(a);
1047                 return NULL;
1048         }
1049         a->next = -1;
1050         a->freeaclp = True;
1051         return a;
1052 }
1053
1054 SMB_ACL_T sys_acl_get_fd(int fd)
1055 {
1056         SMB_ACL_T       a;
1057
1058         if ((a = malloc(sizeof(*a))) == NULL) {
1059                 errno = ENOMEM;
1060                 return NULL;
1061         }
1062         if ((a->aclp = acl_get_fd(fd)) == NULL) {
1063                 SAFE_FREE(a);
1064                 return NULL;
1065         }
1066         a->next = -1;
1067         a->freeaclp = True;
1068         return a;
1069 }
1070
1071 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
1072 {
1073         permset_d->ae_perm = 0;
1074
1075         return 0;
1076 }
1077
1078 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1079 {
1080         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
1081             && perm != SMB_ACL_EXECUTE) {
1082                 errno = EINVAL;
1083                 return -1;
1084         }
1085
1086         if (permset_d == NULL) {
1087                 errno = EINVAL;
1088                 return -1;
1089         }
1090
1091         permset_d->ae_perm |= perm;
1092
1093         return 0;
1094 }
1095
1096 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
1097 {
1098         return permset_d->ae_perm & perm;
1099 }
1100
1101 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
1102 {
1103         return acl_to_text(acl_d->aclp, len_p);
1104 }
1105
1106 SMB_ACL_T sys_acl_init(int count)
1107 {
1108         SMB_ACL_T       a;
1109
1110         if (count < 0) {
1111                 errno = EINVAL;
1112                 return NULL;
1113         }
1114
1115         if ((a = malloc(sizeof(*a) + sizeof(struct acl))) == NULL) {
1116                 errno = ENOMEM;
1117                 return NULL;
1118         }
1119
1120         a->next = -1;
1121         a->freeaclp = False;
1122         a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
1123         a->aclp->acl_cnt = 0;
1124
1125         return a;
1126 }
1127
1128
1129 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
1130 {
1131         SMB_ACL_T       acl_d;
1132         SMB_ACL_ENTRY_T entry_d;
1133
1134         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
1135                 errno = EINVAL;
1136                 return -1;
1137         }
1138
1139         if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
1140                 errno = ENOSPC;
1141                 return -1;
1142         }
1143
1144         entry_d         = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
1145         entry_d->ae_tag = 0;
1146         entry_d->ae_id  = 0;
1147         entry_d->ae_perm        = 0;
1148         *entry_p        = entry_d;
1149
1150         return 0;
1151 }
1152
1153 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
1154 {
1155         switch (tag_type) {
1156                 case SMB_ACL_USER:
1157                 case SMB_ACL_USER_OBJ:
1158                 case SMB_ACL_GROUP:
1159                 case SMB_ACL_GROUP_OBJ:
1160                 case SMB_ACL_OTHER:
1161                 case SMB_ACL_MASK:
1162                         entry_d->ae_tag = tag_type;
1163                         break;
1164                 default:
1165                         errno = EINVAL;
1166                         return -1;
1167         }
1168
1169         return 0;
1170 }
1171
1172 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
1173 {
1174         if (entry_d->ae_tag != SMB_ACL_GROUP
1175             && entry_d->ae_tag != SMB_ACL_USER) {
1176                 errno = EINVAL;
1177                 return -1;
1178         }
1179
1180         entry_d->ae_id = *((id_t *)qual_p);
1181
1182         return 0;
1183 }
1184
1185 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
1186 {
1187         if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
1188                 return EINVAL;
1189         }
1190
1191         entry_d->ae_perm = permset_d->ae_perm;
1192
1193         return 0;
1194 }
1195
1196 int sys_acl_valid(SMB_ACL_T acl_d)
1197 {
1198         return acl_valid(acl_d->aclp);
1199 }
1200
1201 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
1202 {
1203         return acl_set_file(name, type, acl_d->aclp);
1204 }
1205
1206 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
1207 {
1208         return acl_set_fd(fd, acl_d->aclp);
1209 }
1210
1211 int sys_acl_delete_def_file(const char *name)
1212 {
1213         return acl_delete_def_file(name);
1214 }
1215
1216 int sys_acl_free_text(char *text)
1217 {
1218         return acl_free(text);
1219 }
1220
1221 int sys_acl_free_acl(SMB_ACL_T acl_d) 
1222 {
1223         if (acl_d->freeaclp) {
1224                 acl_free(acl_d->aclp);
1225         }
1226         acl_free(acl_d);
1227         return 0;
1228 }
1229
1230 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
1231 {
1232         return 0;
1233 }
1234
1235 #elif defined(HAVE_AIX_ACLS)
1236
1237 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
1238
1239 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1240 {
1241         struct acl_entry_link *link;
1242         struct new_acl_entry *entry;
1243         int keep_going;
1244
1245         DEBUG(10,("This is the count: %d\n",theacl->count));
1246
1247         /* Check if count was previously set to -1. *
1248          * If it was, that means we reached the end *
1249          * of the acl last time.                    */
1250         if(theacl->count == -1)
1251                 return(0);
1252
1253         link = theacl;
1254         /* To get to the next acl, traverse linked list until index *
1255          * of acl matches the count we are keeping.  This count is  *
1256          * incremented each time we return an acl entry.            */
1257
1258         for(keep_going = 0; keep_going < theacl->count; keep_going++)
1259                 link = link->nextp;
1260
1261         entry = *entry_p =  link->entryp;
1262
1263         DEBUG(10,("*entry_p is %d\n",entry_p));
1264         DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
1265
1266         /* Increment count */
1267         theacl->count++;
1268         if(link->nextp == NULL)
1269                 theacl->count = -1;
1270
1271         return(1);
1272 }
1273
1274 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1275 {
1276         /* Initialize tag type */
1277
1278         *tag_type_p = -1;
1279         DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
1280
1281         /* Depending on what type of entry we have, *
1282          * return tag type.                         */
1283         switch(entry_d->ace_id->id_type) {
1284         case ACEID_USER:
1285                 *tag_type_p = SMB_ACL_USER;
1286                 break;
1287         case ACEID_GROUP:
1288                 *tag_type_p = SMB_ACL_GROUP;
1289                 break;
1290
1291         case SMB_ACL_USER_OBJ:
1292         case SMB_ACL_GROUP_OBJ:
1293         case SMB_ACL_OTHER:
1294                 *tag_type_p = entry_d->ace_id->id_type;
1295                 break;
1296  
1297         default:
1298                 return(-1);
1299         }
1300
1301         return(0);
1302 }
1303
1304 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1305 {
1306         DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
1307         *permset_p = &entry_d->ace_access;
1308         DEBUG(10,("**permset_p is %d\n",**permset_p));
1309         if(!(**permset_p & S_IXUSR) &&
1310                 !(**permset_p & S_IWUSR) &&
1311                 !(**permset_p & S_IRUSR) &&
1312                 (**permset_p != 0))
1313                         return(-1);
1314
1315         DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
1316         return(0);
1317 }
1318
1319 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
1320 {
1321         return(entry_d->ace_id->id_data);
1322 }
1323
1324 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
1325 {
1326         struct acl *file_acl = (struct acl *)NULL;
1327         struct acl_entry *acl_entry;
1328         struct new_acl_entry *new_acl_entry;
1329         struct ace_id *idp;
1330         struct acl_entry_link *acl_entry_link;
1331         struct acl_entry_link *acl_entry_link_head;
1332         int i;
1333         int rc = 0;
1334         uid_t user_id;
1335
1336         /* Get the acl using statacl */
1337  
1338         DEBUG(10,("Entering sys_acl_get_file\n"));
1339         DEBUG(10,("path_p is %s\n",path_p));
1340
1341         file_acl = (struct acl *)malloc(BUFSIZ);
1342  
1343         if(file_acl == NULL) {
1344                 errno=ENOMEM;
1345                 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
1346                 return(NULL);
1347         }
1348
1349         memset(file_acl,0,BUFSIZ);
1350
1351         rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
1352         if(rc == -1) {
1353                 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
1354                 SAFE_FREE(file_acl);
1355                 return(NULL);
1356         }
1357
1358         DEBUG(10,("Got facl and returned it\n"));
1359
1360         /* Point to the first acl entry in the acl */
1361         acl_entry =  file_acl->acl_ext;
1362
1363         /* Begin setting up the head of the linked list *
1364          * that will be used for the storing the acl    *
1365          * in a way that is useful for the posix_acls.c *
1366          * code.                                          */
1367
1368         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1369         if(acl_entry_link_head == NULL)
1370                 return(NULL);
1371
1372         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1373         if(acl_entry_link->entryp == NULL) {
1374                 SAFE_FREE(file_acl);
1375                 errno = ENOMEM;
1376                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1377                 return(NULL);
1378         }
1379
1380         DEBUG(10,("acl_entry is %d\n",acl_entry));
1381         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1382
1383         /* Check if the extended acl bit is on.   *
1384          * If it isn't, do not show the           *
1385          * contents of the acl since AIX intends *
1386          * the extended info to remain unused     */
1387
1388         if(file_acl->acl_mode & S_IXACL){
1389                 /* while we are not pointing to the very end */
1390                 while(acl_entry < acl_last(file_acl)) {
1391                         /* before we malloc anything, make sure this is  */
1392                         /* a valid acl entry and one that we want to map */
1393                         idp = id_nxt(acl_entry->ace_id);
1394                         if((acl_entry->ace_type == ACC_SPECIFY ||
1395                                 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1396                                         acl_entry = acl_nxt(acl_entry);
1397                                         continue;
1398                         }
1399
1400                         idp = acl_entry->ace_id;
1401
1402                         /* Check if this is the first entry in the linked list. *
1403                          * The first entry needs to keep prevp pointing to NULL *
1404                          * and already has entryp allocated.                  */
1405
1406                         if(acl_entry_link_head->count != 0) {
1407                                 acl_entry_link->nextp = (struct acl_entry_link *)
1408                                                                                         malloc(sizeof(struct acl_entry_link));
1409
1410                                 if(acl_entry_link->nextp == NULL) {
1411                                         SAFE_FREE(file_acl);
1412                                         errno = ENOMEM;
1413                                         DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1414                                         return(NULL);
1415                                 }
1416
1417                                 acl_entry_link->nextp->prevp = acl_entry_link;
1418                                 acl_entry_link = acl_entry_link->nextp;
1419                                 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1420                                 if(acl_entry_link->entryp == NULL) {
1421                                         SAFE_FREE(file_acl);
1422                                         errno = ENOMEM;
1423                                         DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1424                                         return(NULL);
1425                                 }
1426                                 acl_entry_link->nextp = NULL;
1427                         }
1428
1429                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1430
1431                         /* Don't really need this since all types are going *
1432                          * to be specified but, it's better than leaving it 0 */
1433
1434                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1435  
1436                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1437  
1438                         memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
1439
1440                         /* The access in the acl entries must be left shifted by *
1441                          * three bites, because they will ultimately be compared *
1442                          * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
1443
1444                         switch(acl_entry->ace_type){
1445                         case ACC_PERMIT:
1446                         case ACC_SPECIFY:
1447                                 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1448                                 acl_entry_link->entryp->ace_access <<= 6;
1449                                 acl_entry_link_head->count++;
1450                                 break;
1451                         case ACC_DENY:
1452                                 /* Since there is no way to return a DENY acl entry *
1453                                  * change to PERMIT and then shift.                 */
1454                                 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1455                                 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1456                                 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1457                                 acl_entry_link->entryp->ace_access <<= 6;
1458                                 acl_entry_link_head->count++;
1459                                 break;
1460                         default:
1461                                 return(0);
1462                         }
1463
1464                         DEBUG(10,("acl_entry = %d\n",acl_entry));
1465                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1466  
1467                         acl_entry = acl_nxt(acl_entry);
1468                 }
1469         } /* end of if enabled */
1470
1471         /* Since owner, group, other acl entries are not *
1472          * part of the acl entries in an acl, they must  *
1473          * be dummied up to become part of the list.     */
1474
1475         for( i = 1; i < 4; i++) {
1476                 DEBUG(10,("i is %d\n",i));
1477                 if(acl_entry_link_head->count != 0) {
1478                         acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1479                         if(acl_entry_link->nextp == NULL) {
1480                                 SAFE_FREE(file_acl);
1481                                 errno = ENOMEM;
1482                                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1483                                 return(NULL);
1484                         }
1485
1486                         acl_entry_link->nextp->prevp = acl_entry_link;
1487                         acl_entry_link = acl_entry_link->nextp;
1488                         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1489                         if(acl_entry_link->entryp == NULL) {
1490                                 SAFE_FREE(file_acl);
1491                                 errno = ENOMEM;
1492                                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
1493                                 return(NULL);
1494                         }
1495                 }
1496
1497                 acl_entry_link->nextp = NULL;
1498
1499                 new_acl_entry = acl_entry_link->entryp;
1500                 idp = new_acl_entry->ace_id;
1501
1502                 new_acl_entry->ace_len = sizeof(struct acl_entry);
1503                 new_acl_entry->ace_type = ACC_PERMIT;
1504                 idp->id_len = sizeof(struct ace_id);
1505                 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1506                 memset(idp->id_data,0,sizeof(uid_t));
1507
1508                 switch(i) {
1509                 case 2:
1510                         new_acl_entry->ace_access = file_acl->g_access << 6;
1511                         idp->id_type = SMB_ACL_GROUP_OBJ;
1512                         break;
1513
1514                 case 3:
1515                         new_acl_entry->ace_access = file_acl->o_access << 6;
1516                         idp->id_type = SMB_ACL_OTHER;
1517                         break;
1518  
1519                 case 1:
1520                         new_acl_entry->ace_access = file_acl->u_access << 6;
1521                         idp->id_type = SMB_ACL_USER_OBJ;
1522                         break;
1523  
1524                 default:
1525                         return(NULL);
1526
1527                 }
1528
1529                 acl_entry_link_head->count++;
1530                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1531         }
1532
1533         acl_entry_link_head->count = 0;
1534         SAFE_FREE(file_acl);
1535
1536         return(acl_entry_link_head);
1537 }
1538
1539 SMB_ACL_T sys_acl_get_fd(int fd)
1540 {
1541         struct acl *file_acl = (struct acl *)NULL;
1542         struct acl_entry *acl_entry;
1543         struct new_acl_entry *new_acl_entry;
1544         struct ace_id *idp;
1545         struct acl_entry_link *acl_entry_link;
1546         struct acl_entry_link *acl_entry_link_head;
1547         int i;
1548         int rc = 0;
1549         uid_t user_id;
1550
1551         /* Get the acl using fstatacl */
1552    
1553         DEBUG(10,("Entering sys_acl_get_fd\n"));
1554         DEBUG(10,("fd is %d\n",fd));
1555         file_acl = (struct acl *)malloc(BUFSIZ);
1556
1557         if(file_acl == NULL) {
1558                 errno=ENOMEM;
1559                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1560                 return(NULL);
1561         }
1562
1563         memset(file_acl,0,BUFSIZ);
1564
1565         rc = fstatacl(fd,0,file_acl,BUFSIZ);
1566         if(rc == -1) {
1567                 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
1568                 SAFE_FREE(file_acl);
1569                 return(NULL);
1570         }
1571
1572         DEBUG(10,("Got facl and returned it\n"));
1573
1574         /* Point to the first acl entry in the acl */
1575
1576         acl_entry =  file_acl->acl_ext;
1577         /* Begin setting up the head of the linked list *
1578          * that will be used for the storing the acl    *
1579          * in a way that is useful for the posix_acls.c *
1580          * code.                                        */
1581
1582         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
1583         if(acl_entry_link_head == NULL){
1584                 SAFE_FREE(file_acl);
1585                 return(NULL);
1586         }
1587
1588         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1589
1590         if(acl_entry_link->entryp == NULL) {
1591                 errno = ENOMEM;
1592                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1593                 SAFE_FREE(file_acl);
1594                 return(NULL);
1595         }
1596
1597         DEBUG(10,("acl_entry is %d\n",acl_entry));
1598         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
1599  
1600         /* Check if the extended acl bit is on.   *
1601          * If it isn't, do not show the           *
1602          * contents of the acl since AIX intends  *
1603          * the extended info to remain unused     */
1604  
1605         if(file_acl->acl_mode & S_IXACL){
1606                 /* while we are not pointing to the very end */
1607                 while(acl_entry < acl_last(file_acl)) {
1608                         /* before we malloc anything, make sure this is  */
1609                         /* a valid acl entry and one that we want to map */
1610
1611                         idp = id_nxt(acl_entry->ace_id);
1612                         if((acl_entry->ace_type == ACC_SPECIFY ||
1613                                 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
1614                                         acl_entry = acl_nxt(acl_entry);
1615                                         continue;
1616                         }
1617
1618                         idp = acl_entry->ace_id;
1619  
1620                         /* Check if this is the first entry in the linked list. *
1621                          * The first entry needs to keep prevp pointing to NULL *
1622                          * and already has entryp allocated.                 */
1623
1624                         if(acl_entry_link_head->count != 0) {
1625                                 acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1626                                 if(acl_entry_link->nextp == NULL) {
1627                                         errno = ENOMEM;
1628                                         DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1629                                         SAFE_FREE(file_acl);
1630                                         return(NULL);
1631                                 }
1632                                 acl_entry_link->nextp->prevp = acl_entry_link;
1633                                 acl_entry_link = acl_entry_link->nextp;
1634                                 acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1635                                 if(acl_entry_link->entryp == NULL) {
1636                                         errno = ENOMEM;
1637                                         DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1638                                         SAFE_FREE(file_acl);
1639                                         return(NULL);
1640                                 }
1641
1642                                 acl_entry_link->nextp = NULL;
1643                         }
1644
1645                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
1646
1647                         /* Don't really need this since all types are going *
1648                          * to be specified but, it's better than leaving it 0 */
1649
1650                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
1651                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1652
1653                         memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
1654
1655                         /* The access in the acl entries must be left shifted by *
1656                          * three bites, because they will ultimately be compared *
1657                          * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
1658
1659                         switch(acl_entry->ace_type){
1660                         case ACC_PERMIT:
1661                         case ACC_SPECIFY:
1662                                 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
1663                                 acl_entry_link->entryp->ace_access <<= 6;
1664                                 acl_entry_link_head->count++;
1665                                 break;
1666                         case ACC_DENY:
1667                                 /* Since there is no way to return a DENY acl entry *
1668                                  * change to PERMIT and then shift.                 */
1669                                 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
1670                                 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
1671                                 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
1672                                 acl_entry_link->entryp->ace_access <<= 6;
1673                                 acl_entry_link_head->count++;
1674                                 break;
1675                         default:
1676                                 return(0);
1677                         }
1678
1679                         DEBUG(10,("acl_entry = %d\n",acl_entry));
1680                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
1681  
1682                         acl_entry = acl_nxt(acl_entry);
1683                 }
1684         } /* end of if enabled */
1685
1686         /* Since owner, group, other acl entries are not *
1687          * part of the acl entries in an acl, they must  *
1688          * be dummied up to become part of the list.     */
1689
1690         for( i = 1; i < 4; i++) {
1691                 DEBUG(10,("i is %d\n",i));
1692                 if(acl_entry_link_head->count != 0){
1693                         acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1694                         if(acl_entry_link->nextp == NULL) {
1695                                 errno = ENOMEM;
1696                                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1697                                 SAFE_FREE(file_acl);
1698                                 return(NULL);
1699                         }
1700
1701                         acl_entry_link->nextp->prevp = acl_entry_link;
1702                         acl_entry_link = acl_entry_link->nextp;
1703                         acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1704
1705                         if(acl_entry_link->entryp == NULL) {
1706                                 SAFE_FREE(file_acl);
1707                                 errno = ENOMEM;
1708                                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
1709                                 return(NULL);
1710                         }
1711                 }
1712
1713                 acl_entry_link->nextp = NULL;
1714  
1715                 new_acl_entry = acl_entry_link->entryp;
1716                 idp = new_acl_entry->ace_id;
1717  
1718                 new_acl_entry->ace_len = sizeof(struct acl_entry);
1719                 new_acl_entry->ace_type = ACC_PERMIT;
1720                 idp->id_len = sizeof(struct ace_id);
1721                 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
1722                 memset(idp->id_data,0,sizeof(uid_t));
1723  
1724                 switch(i) {
1725                 case 2:
1726                         new_acl_entry->ace_access = file_acl->g_access << 6;
1727                         idp->id_type = SMB_ACL_GROUP_OBJ;
1728                         break;
1729  
1730                 case 3:
1731                         new_acl_entry->ace_access = file_acl->o_access << 6;
1732                         idp->id_type = SMB_ACL_OTHER;
1733                         break;
1734  
1735                 case 1:
1736                         new_acl_entry->ace_access = file_acl->u_access << 6;
1737                         idp->id_type = SMB_ACL_USER_OBJ;
1738                         break;
1739  
1740                 default:
1741                         return(NULL);
1742                 }
1743  
1744                 acl_entry_link_head->count++;
1745                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
1746         }
1747
1748         acl_entry_link_head->count = 0;
1749         SAFE_FREE(file_acl);
1750  
1751         return(acl_entry_link_head);
1752 }
1753
1754 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
1755 {
1756         *permset = *permset & ~0777;
1757         return(0);
1758 }
1759
1760 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1761 {
1762         if((perm != 0) &&
1763                         (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
1764                 return(-1);
1765
1766         *permset |= perm;
1767         DEBUG(10,("This is the permset now: %d\n",*permset));
1768         return(0);
1769 }
1770
1771 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
1772 {
1773         return(NULL);
1774 }
1775
1776 SMB_ACL_T sys_acl_init( int count)
1777 {
1778         struct acl_entry_link *theacl = NULL;
1779  
1780         DEBUG(10,("Entering sys_acl_init\n"));
1781
1782         theacl = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1783         if(theacl == NULL) {
1784                 errno = ENOMEM;
1785                 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
1786                 return(NULL);
1787         }
1788
1789         theacl->count = 0;
1790         theacl->nextp = NULL;
1791         theacl->prevp = NULL;
1792         theacl->entryp = NULL;
1793         DEBUG(10,("Exiting sys_acl_init\n"));
1794         return(theacl);
1795 }
1796
1797 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1798 {
1799         struct acl_entry_link *theacl;
1800         struct acl_entry_link *acl_entryp;
1801         struct acl_entry_link *temp_entry;
1802         int counting;
1803
1804         DEBUG(10,("Entering the sys_acl_create_entry\n"));
1805
1806         theacl = acl_entryp = *pacl;
1807
1808         /* Get to the end of the acl before adding entry */
1809
1810         for(counting=0; counting < theacl->count; counting++){
1811                 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
1812                 temp_entry = acl_entryp;
1813                 acl_entryp = acl_entryp->nextp;
1814         }
1815
1816         if(theacl->count != 0){
1817                 temp_entry->nextp = acl_entryp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link));
1818                 if(acl_entryp == NULL) {
1819                         errno = ENOMEM;
1820                         DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
1821                         return(-1);
1822                 }
1823
1824                 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
1825                 acl_entryp->prevp = temp_entry;
1826                 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
1827         }
1828
1829         *pentry = acl_entryp->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry));
1830         if(*pentry == NULL) {
1831                 errno = ENOMEM;
1832                 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
1833                 return(-1);
1834         }
1835
1836         memset(*pentry,0,sizeof(struct new_acl_entry));
1837         acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
1838         acl_entryp->entryp->ace_type = ACC_PERMIT;
1839         acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
1840         acl_entryp->nextp = NULL;
1841         theacl->count++;
1842         DEBUG(10,("Exiting sys_acl_create_entry\n"));
1843         return(0);
1844 }
1845
1846 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1847 {
1848         DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
1849         entry->ace_id->id_type = tagtype;
1850         DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
1851         DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
1852 }
1853
1854 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
1855 {
1856         DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
1857         memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
1858         DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
1859         return(0);
1860 }
1861
1862 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1863 {
1864         DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
1865         if(!(*permset & S_IXUSR) &&
1866                 !(*permset & S_IWUSR) &&
1867                 !(*permset & S_IRUSR) &&
1868                 (*permset != 0))
1869                         return(-1);
1870
1871         entry->ace_access = *permset;
1872         DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
1873         DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
1874         return(0);
1875 }
1876
1877 int sys_acl_valid( SMB_ACL_T theacl )
1878 {
1879         int user_obj = 0;
1880         int group_obj = 0;
1881         int other_obj = 0;
1882         struct acl_entry_link *acl_entry;
1883
1884         for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
1885                 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
1886                 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
1887                 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
1888         }
1889
1890         DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
1891  
1892         if(user_obj != 1 || group_obj != 1 || other_obj != 1)
1893                 return(-1); 
1894
1895         return(0);
1896 }
1897
1898 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1899 {
1900         struct acl_entry_link *acl_entry_link = NULL;
1901         struct acl *file_acl = NULL;
1902         struct acl *file_acl_temp = NULL;
1903         struct acl_entry *acl_entry = NULL;
1904         struct ace_id *ace_id = NULL;
1905         uint id_type;
1906         uint ace_access;
1907         uint user_id;
1908         uint acl_length;
1909         uint rc;
1910
1911         DEBUG(10,("Entering sys_acl_set_file\n"));
1912         DEBUG(10,("File name is %s\n",name));
1913  
1914         /* AIX has no default ACL */
1915         if(acltype == SMB_ACL_TYPE_DEFAULT)
1916                 return(0);
1917
1918         acl_length = BUFSIZ;
1919         file_acl = (struct acl *)malloc(BUFSIZ);
1920
1921         if(file_acl == NULL) {
1922                 errno = ENOMEM;
1923                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
1924                 return(-1);
1925         }
1926
1927         memset(file_acl,0,BUFSIZ);
1928
1929         file_acl->acl_len = ACL_SIZ;
1930         file_acl->acl_mode = S_IXACL;
1931
1932         for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
1933                 acl_entry_link->entryp->ace_access >>= 6;
1934                 id_type = acl_entry_link->entryp->ace_id->id_type;
1935
1936                 switch(id_type) {
1937                 case SMB_ACL_USER_OBJ:
1938                         file_acl->u_access = acl_entry_link->entryp->ace_access;
1939                         continue;
1940                 case SMB_ACL_GROUP_OBJ:
1941                         file_acl->g_access = acl_entry_link->entryp->ace_access;
1942                         continue;
1943                 case SMB_ACL_OTHER:
1944                         file_acl->o_access = acl_entry_link->entryp->ace_access;
1945                         continue;
1946                 case SMB_ACL_MASK:
1947                         continue;
1948                 }
1949
1950                 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
1951                         acl_length += sizeof(struct acl_entry);
1952                         file_acl_temp = (struct acl *)malloc(acl_length);
1953                         if(file_acl_temp == NULL) {
1954                                 SAFE_FREE(file_acl);
1955                                 errno = ENOMEM;
1956                                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
1957                                 return(-1);
1958                         }  
1959
1960                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
1961                         SAFE_FREE(file_acl);
1962                         file_acl = file_acl_temp;
1963                 }
1964
1965                 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
1966                 file_acl->acl_len += sizeof(struct acl_entry);
1967                 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
1968                 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
1969  
1970                 /* In order to use this, we'll need to wait until we can get denies */
1971                 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
1972                 acl_entry->ace_type = ACC_SPECIFY; */
1973
1974                 acl_entry->ace_type = ACC_SPECIFY;
1975  
1976                 ace_id = acl_entry->ace_id;
1977  
1978                 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
1979                 DEBUG(10,("The id type is %d\n",ace_id->id_type));
1980                 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
1981                 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
1982                 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
1983         }
1984
1985         rc = chacl(name,file_acl,file_acl->acl_len);
1986         DEBUG(10,("errno is %d\n",errno));
1987         DEBUG(10,("return code is %d\n",rc));
1988         SAFE_FREE(file_acl);
1989         DEBUG(10,("Exiting the sys_acl_set_file\n"));
1990         return(rc);
1991 }
1992
1993 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
1994 {
1995         struct acl_entry_link *acl_entry_link = NULL;
1996         struct acl *file_acl = NULL;
1997         struct acl *file_acl_temp = NULL;
1998         struct acl_entry *acl_entry = NULL;
1999         struct ace_id *ace_id = NULL;
2000         uint id_type;
2001         uint user_id;
2002         uint acl_length;
2003         uint rc;
2004  
2005         DEBUG(10,("Entering sys_acl_set_fd\n"));
2006         acl_length = BUFSIZ;
2007         file_acl = (struct acl *)malloc(BUFSIZ);
2008
2009         if(file_acl == NULL) {
2010                 errno = ENOMEM;
2011                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2012                 return(-1);
2013         }
2014
2015         memset(file_acl,0,BUFSIZ);
2016  
2017         file_acl->acl_len = ACL_SIZ;
2018         file_acl->acl_mode = S_IXACL;
2019
2020         for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
2021                 acl_entry_link->entryp->ace_access >>= 6;
2022                 id_type = acl_entry_link->entryp->ace_id->id_type;
2023                 DEBUG(10,("The id_type is %d\n",id_type));
2024
2025                 switch(id_type) {
2026                 case SMB_ACL_USER_OBJ:
2027                         file_acl->u_access = acl_entry_link->entryp->ace_access;
2028                         continue;
2029                 case SMB_ACL_GROUP_OBJ:
2030                         file_acl->g_access = acl_entry_link->entryp->ace_access;
2031                         continue;
2032                 case SMB_ACL_OTHER:
2033                         file_acl->o_access = acl_entry_link->entryp->ace_access;
2034                         continue;
2035                 case SMB_ACL_MASK:
2036                         continue;
2037                 }
2038
2039                 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
2040                         acl_length += sizeof(struct acl_entry);
2041                         file_acl_temp = (struct acl *)malloc(acl_length);
2042                         if(file_acl_temp == NULL) {
2043                                 SAFE_FREE(file_acl);
2044                                 errno = ENOMEM;
2045                                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
2046                                 return(-1);
2047                         }
2048
2049                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
2050                         SAFE_FREE(file_acl);
2051                         file_acl = file_acl_temp;
2052                 }
2053
2054                 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
2055                 file_acl->acl_len += sizeof(struct acl_entry);
2056                 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
2057                 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
2058  
2059                 /* In order to use this, we'll need to wait until we can get denies */
2060                 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
2061                         acl_entry->ace_type = ACC_SPECIFY; */
2062  
2063                 acl_entry->ace_type = ACC_SPECIFY;
2064  
2065                 ace_id = acl_entry->ace_id;
2066  
2067                 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
2068                 DEBUG(10,("The id type is %d\n",ace_id->id_type));
2069                 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
2070                 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
2071                 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
2072         }
2073  
2074         rc = fchacl(fd,file_acl,file_acl->acl_len);
2075         DEBUG(10,("errno is %d\n",errno));
2076         DEBUG(10,("return code is %d\n",rc));
2077         SAFE_FREE(file_acl);
2078         DEBUG(10,("Exiting sys_acl_set_fd\n"));
2079         return(rc);
2080 }
2081
2082 int sys_acl_delete_def_file(const char *name)
2083 {
2084         /* AIX has no default ACL */
2085         return 0;
2086 }
2087
2088 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2089 {
2090         return(*permset & perm);
2091 }
2092
2093 int sys_acl_free_text(char *text)
2094 {
2095         return(0);
2096 }
2097
2098 int sys_acl_free_acl(SMB_ACL_T posix_acl)
2099 {
2100         struct acl_entry_link *acl_entry_link;
2101
2102         for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
2103                 SAFE_FREE(acl_entry_link->prevp->entryp);
2104                 SAFE_FREE(acl_entry_link->prevp);
2105         }
2106
2107         SAFE_FREE(acl_entry_link->prevp->entryp);
2108         SAFE_FREE(acl_entry_link->prevp);
2109         SAFE_FREE(acl_entry_link->entryp);
2110         SAFE_FREE(acl_entry_link);
2111  
2112         return(0);
2113 }
2114
2115 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2116 {
2117         return(0);
2118 }
2119
2120 #else /* No ACLs. */
2121
2122 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
2123 {
2124         errno = ENOSYS;
2125         return -1;
2126 }
2127
2128 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
2129 {
2130         errno = ENOSYS;
2131         return -1;
2132 }
2133
2134 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
2135 {
2136         errno = ENOSYS;
2137         return -1;
2138 }
2139
2140 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
2141 {
2142         errno = ENOSYS;
2143         return NULL;
2144 }
2145
2146 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
2147 {
2148         errno = ENOSYS;
2149         return (SMB_ACL_T)NULL;
2150 }
2151
2152 SMB_ACL_T sys_acl_get_fd(int fd)
2153 {
2154         errno = ENOSYS;
2155         return (SMB_ACL_T)NULL;
2156 }
2157
2158 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
2159 {
2160         errno = ENOSYS;
2161         return -1;
2162 }
2163
2164 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2165 {
2166         errno = ENOSYS;
2167         return -1;
2168 }
2169
2170 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
2171 {
2172         errno = ENOSYS;
2173         return (permset & perm) ? 1 : 0;
2174 }
2175
2176 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
2177 {
2178         errno = ENOSYS;
2179         return NULL;
2180 }
2181
2182 int sys_acl_free_text(char *text)
2183 {
2184         errno = ENOSYS;
2185         return -1;
2186 }
2187
2188 SMB_ACL_T sys_acl_init( int count)
2189 {
2190         errno = ENOSYS;
2191         return NULL;
2192 }
2193
2194 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
2195 {
2196         errno = ENOSYS;
2197         return -1;
2198 }
2199
2200 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
2201 {
2202         errno = ENOSYS;
2203         return -1;
2204 }
2205
2206 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
2207 {
2208         errno = ENOSYS;
2209         return -1;
2210 }
2211
2212 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
2213 {
2214         errno = ENOSYS;
2215         return -1;
2216 }
2217
2218 int sys_acl_valid( SMB_ACL_T theacl )
2219 {
2220         errno = ENOSYS;
2221         return -1;
2222 }
2223
2224 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2225 {
2226         errno = ENOSYS;
2227         return -1;
2228 }
2229
2230 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
2231 {
2232         errno = ENOSYS;
2233         return -1;
2234 }
2235
2236 int sys_acl_delete_def_file(const char *name)
2237 {
2238         errno = ENOSYS;
2239         return -1;
2240 }
2241
2242 int sys_acl_free_acl(SMB_ACL_T the_acl) 
2243 {
2244         errno = ENOSYS;
2245         return -1;
2246 }
2247
2248 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
2249 {
2250         errno = ENOSYS;
2251         return -1;
2252 }
2253
2254 #endif /* No ACLs. */