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