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