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