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