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