Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c
3153 views
1
/*-
2
* Copyright (c) 2003-2009 Tim Kientzle
3
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
4
* Copyright (c) 2017 Martin Matuska
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*/
27
28
#include "archive_platform.h"
29
30
#if ARCHIVE_ACL_FREEBSD
31
32
#ifdef HAVE_ERRNO_H
33
#include <errno.h>
34
#endif
35
#ifdef HAVE_FCNTL_H
36
#include <fcntl.h>
37
#endif
38
#ifdef HAVE_SYS_TYPES_H
39
#include <sys/types.h>
40
#endif
41
#ifdef HAVE_SYS_ACL_H
42
#define _ACL_PRIVATE /* For debugging */
43
#include <sys/acl.h>
44
#endif
45
46
#include "archive_entry.h"
47
#include "archive_private.h"
48
#include "archive_read_disk_private.h"
49
#include "archive_write_disk_private.h"
50
51
typedef struct {
52
const int a_perm; /* Libarchive permission or flag */
53
const int p_perm; /* Platform permission or flag */
54
} acl_perm_map_t;
55
56
static const acl_perm_map_t acl_posix_perm_map[] = {
57
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
58
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
59
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
60
};
61
62
static const int acl_posix_perm_map_size =
63
(int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
64
65
#if ARCHIVE_ACL_FREEBSD_NFS4
66
static const acl_perm_map_t acl_nfs4_perm_map[] = {
67
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
68
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
69
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
70
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
71
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
72
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
73
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
74
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
75
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
76
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
77
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
78
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
79
{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
80
{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
81
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
82
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
83
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
84
};
85
86
static const int acl_nfs4_perm_map_size =
87
(int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
88
89
static const acl_perm_map_t acl_nfs4_flag_map[] = {
90
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
91
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
92
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
93
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
94
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
95
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
96
#ifdef ACL_ENTRY_INHERITED
97
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
98
#endif
99
};
100
101
static const int acl_nfs4_flag_map_size =
102
(int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
103
#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
104
105
static int
106
translate_acl(struct archive_read_disk *a,
107
struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
108
{
109
#if ARCHIVE_ACL_FREEBSD_NFS4
110
int brand;
111
acl_flagset_t acl_flagset;
112
acl_entry_type_t acl_type;
113
#endif
114
acl_tag_t acl_tag;
115
acl_entry_t acl_entry;
116
acl_permset_t acl_permset;
117
int i, entry_acl_type, perm_map_size;
118
const acl_perm_map_t *perm_map;
119
int r, s, ae_id, ae_tag, ae_perm;
120
void *q;
121
const char *ae_name;
122
123
#if ARCHIVE_ACL_FREEBSD_NFS4
124
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
125
// Make sure the "brand" on this ACL is consistent
126
// with the default_entry_acl_type bits provided.
127
if (acl_get_brand_np(acl, &brand) != 0) {
128
archive_set_error(&a->archive, errno,
129
"Failed to read ACL brand");
130
return (ARCHIVE_WARN);
131
}
132
switch (brand) {
133
case ACL_BRAND_POSIX:
134
switch (default_entry_acl_type) {
135
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
136
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
137
break;
138
default:
139
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
140
"Invalid ACL entry type for POSIX.1e ACL");
141
return (ARCHIVE_WARN);
142
}
143
break;
144
case ACL_BRAND_NFS4:
145
if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
146
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
147
"Invalid ACL entry type for NFSv4 ACL");
148
return (ARCHIVE_WARN);
149
}
150
break;
151
default:
152
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
153
"Unknown ACL brand");
154
return (ARCHIVE_WARN);
155
}
156
#endif
157
158
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
159
if (s == -1) {
160
archive_set_error(&a->archive, errno,
161
"Failed to get first ACL entry");
162
return (ARCHIVE_WARN);
163
}
164
165
while (s == 1) {
166
ae_id = -1;
167
ae_name = NULL;
168
ae_perm = 0;
169
170
if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
171
archive_set_error(&a->archive, errno,
172
"Failed to get ACL tag type");
173
return (ARCHIVE_WARN);
174
}
175
switch (acl_tag) {
176
case ACL_USER:
177
q = acl_get_qualifier(acl_entry);
178
if (q != NULL) {
179
ae_id = (int)*(uid_t *)q;
180
acl_free(q);
181
ae_name = archive_read_disk_uname(&a->archive,
182
ae_id);
183
}
184
ae_tag = ARCHIVE_ENTRY_ACL_USER;
185
break;
186
case ACL_GROUP:
187
q = acl_get_qualifier(acl_entry);
188
if (q != NULL) {
189
ae_id = (int)*(gid_t *)q;
190
acl_free(q);
191
ae_name = archive_read_disk_gname(&a->archive,
192
ae_id);
193
}
194
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
195
break;
196
case ACL_MASK:
197
ae_tag = ARCHIVE_ENTRY_ACL_MASK;
198
break;
199
case ACL_USER_OBJ:
200
ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
201
break;
202
case ACL_GROUP_OBJ:
203
ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
204
break;
205
case ACL_OTHER:
206
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
207
break;
208
#if ARCHIVE_ACL_FREEBSD_NFS4
209
case ACL_EVERYONE:
210
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
211
break;
212
#endif
213
default:
214
/* Skip types that libarchive can't support. */
215
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
216
continue;
217
}
218
219
// XXX acl_type maps to allow/deny/audit/YYYY bits
220
entry_acl_type = default_entry_acl_type;
221
222
#if ARCHIVE_ACL_FREEBSD_NFS4
223
if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
224
/*
225
* acl_get_entry_type_np() fails with non-NFSv4 ACLs
226
*/
227
if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
228
archive_set_error(&a->archive, errno, "Failed "
229
"to get ACL type from a NFSv4 ACL entry");
230
return (ARCHIVE_WARN);
231
}
232
switch (acl_type) {
233
case ACL_ENTRY_TYPE_ALLOW:
234
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
235
break;
236
case ACL_ENTRY_TYPE_DENY:
237
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
238
break;
239
case ACL_ENTRY_TYPE_AUDIT:
240
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
241
break;
242
case ACL_ENTRY_TYPE_ALARM:
243
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
244
break;
245
default:
246
archive_set_error(&a->archive, errno,
247
"Invalid NFSv4 ACL entry type");
248
return (ARCHIVE_WARN);
249
}
250
251
/*
252
* Libarchive stores "flag" (NFSv4 inheritance bits)
253
* in the ae_perm bitmap.
254
*
255
* acl_get_flagset_np() fails with non-NFSv4 ACLs
256
*/
257
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
258
archive_set_error(&a->archive, errno,
259
"Failed to get flagset from a NFSv4 "
260
"ACL entry");
261
return (ARCHIVE_WARN);
262
}
263
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
264
r = acl_get_flag_np(acl_flagset,
265
acl_nfs4_flag_map[i].p_perm);
266
if (r == -1) {
267
archive_set_error(&a->archive, errno,
268
"Failed to check flag in a NFSv4 "
269
"ACL flagset");
270
return (ARCHIVE_WARN);
271
} else if (r)
272
ae_perm |= acl_nfs4_flag_map[i].a_perm;
273
}
274
}
275
#endif
276
277
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
278
archive_set_error(&a->archive, errno,
279
"Failed to get ACL permission set");
280
return (ARCHIVE_WARN);
281
}
282
283
#if ARCHIVE_ACL_FREEBSD_NFS4
284
if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
285
perm_map_size = acl_nfs4_perm_map_size;
286
perm_map = acl_nfs4_perm_map;
287
} else {
288
#endif
289
perm_map_size = acl_posix_perm_map_size;
290
perm_map = acl_posix_perm_map;
291
#if ARCHIVE_ACL_FREEBSD_NFS4
292
}
293
#endif
294
295
for (i = 0; i < perm_map_size; ++i) {
296
r = acl_get_perm_np(acl_permset, perm_map[i].p_perm);
297
if (r == -1) {
298
archive_set_error(&a->archive, errno,
299
"Failed to check permission in an ACL "
300
"permission set");
301
return (ARCHIVE_WARN);
302
} else if (r)
303
ae_perm |= perm_map[i].a_perm;
304
}
305
306
archive_entry_acl_add_entry(entry, entry_acl_type,
307
ae_perm, ae_tag,
308
ae_id, ae_name);
309
310
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
311
if (s == -1) {
312
archive_set_error(&a->archive, errno,
313
"Failed to get next ACL entry");
314
return (ARCHIVE_WARN);
315
}
316
}
317
return (ARCHIVE_OK);
318
}
319
320
static int
321
set_acl(struct archive *a, int fd, const char *name,
322
struct archive_acl *abstract_acl, __LA_MODE_T mode,
323
int ae_requested_type, const char *tname)
324
{
325
int acl_type = 0;
326
acl_t acl;
327
acl_entry_t acl_entry;
328
acl_permset_t acl_permset;
329
#if ARCHIVE_ACL_FREEBSD_NFS4
330
acl_flagset_t acl_flagset;
331
int r;
332
#endif
333
int ret;
334
int ae_type, ae_permset, ae_tag, ae_id;
335
int perm_map_size;
336
const acl_perm_map_t *perm_map;
337
uid_t ae_uid;
338
gid_t ae_gid;
339
const char *ae_name;
340
int entries;
341
int i;
342
343
ret = ARCHIVE_OK;
344
entries = archive_acl_reset(abstract_acl, ae_requested_type);
345
if (entries == 0)
346
return (ARCHIVE_OK);
347
348
349
switch (ae_requested_type) {
350
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
351
acl_type = ACL_TYPE_ACCESS;
352
break;
353
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
354
acl_type = ACL_TYPE_DEFAULT;
355
break;
356
#if ARCHIVE_ACL_FREEBSD_NFS4
357
case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
358
acl_type = ACL_TYPE_NFS4;
359
break;
360
#endif
361
default:
362
errno = ENOENT;
363
archive_set_error(a, errno, "Unsupported ACL type");
364
return (ARCHIVE_FAILED);
365
}
366
367
if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {
368
errno = EINVAL;
369
archive_set_error(a, errno,
370
"Cannot set default ACL on non-directory");
371
return (ARCHIVE_WARN);
372
}
373
374
acl = acl_init(entries);
375
if (acl == (acl_t)NULL) {
376
archive_set_error(a, errno,
377
"Failed to initialize ACL working storage");
378
return (ARCHIVE_FAILED);
379
}
380
381
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
382
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
383
if (acl_create_entry(&acl, &acl_entry) != 0) {
384
archive_set_error(a, errno,
385
"Failed to create a new ACL entry");
386
ret = ARCHIVE_FAILED;
387
goto exit_free;
388
}
389
switch (ae_tag) {
390
case ARCHIVE_ENTRY_ACL_USER:
391
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
392
acl_set_tag_type(acl_entry, ACL_USER);
393
acl_set_qualifier(acl_entry, &ae_uid);
394
break;
395
case ARCHIVE_ENTRY_ACL_GROUP:
396
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
397
acl_set_tag_type(acl_entry, ACL_GROUP);
398
acl_set_qualifier(acl_entry, &ae_gid);
399
break;
400
case ARCHIVE_ENTRY_ACL_USER_OBJ:
401
acl_set_tag_type(acl_entry, ACL_USER_OBJ);
402
break;
403
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
404
acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
405
break;
406
case ARCHIVE_ENTRY_ACL_MASK:
407
acl_set_tag_type(acl_entry, ACL_MASK);
408
break;
409
case ARCHIVE_ENTRY_ACL_OTHER:
410
acl_set_tag_type(acl_entry, ACL_OTHER);
411
break;
412
#if ARCHIVE_ACL_FREEBSD_NFS4
413
case ARCHIVE_ENTRY_ACL_EVERYONE:
414
acl_set_tag_type(acl_entry, ACL_EVERYONE);
415
break;
416
#endif
417
default:
418
archive_set_error(a, ARCHIVE_ERRNO_MISC,
419
"Unsupported ACL tag");
420
ret = ARCHIVE_FAILED;
421
goto exit_free;
422
}
423
424
#if ARCHIVE_ACL_FREEBSD_NFS4
425
r = 0;
426
switch (ae_type) {
427
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
428
r = acl_set_entry_type_np(acl_entry,
429
ACL_ENTRY_TYPE_ALLOW);
430
break;
431
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
432
r = acl_set_entry_type_np(acl_entry,
433
ACL_ENTRY_TYPE_DENY);
434
break;
435
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
436
r = acl_set_entry_type_np(acl_entry,
437
ACL_ENTRY_TYPE_AUDIT);
438
break;
439
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
440
r = acl_set_entry_type_np(acl_entry,
441
ACL_ENTRY_TYPE_ALARM);
442
break;
443
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
444
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
445
// These don't translate directly into the system ACL.
446
break;
447
default:
448
archive_set_error(a, ARCHIVE_ERRNO_MISC,
449
"Unsupported ACL entry type");
450
ret = ARCHIVE_FAILED;
451
goto exit_free;
452
}
453
454
if (r != 0) {
455
archive_set_error(a, errno,
456
"Failed to set ACL entry type");
457
ret = ARCHIVE_FAILED;
458
goto exit_free;
459
}
460
#endif
461
462
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
463
archive_set_error(a, errno,
464
"Failed to get ACL permission set");
465
ret = ARCHIVE_FAILED;
466
goto exit_free;
467
}
468
if (acl_clear_perms(acl_permset) != 0) {
469
archive_set_error(a, errno,
470
"Failed to clear ACL permissions");
471
ret = ARCHIVE_FAILED;
472
goto exit_free;
473
}
474
#if ARCHIVE_ACL_FREEBSD_NFS4
475
if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
476
perm_map_size = acl_nfs4_perm_map_size;
477
perm_map = acl_nfs4_perm_map;
478
} else {
479
#endif
480
perm_map_size = acl_posix_perm_map_size;
481
perm_map = acl_posix_perm_map;
482
#if ARCHIVE_ACL_FREEBSD_NFS4
483
}
484
#endif
485
486
for (i = 0; i < perm_map_size; ++i) {
487
if (ae_permset & perm_map[i].a_perm) {
488
if (acl_add_perm(acl_permset,
489
perm_map[i].p_perm) != 0) {
490
archive_set_error(a, errno,
491
"Failed to add ACL permission");
492
ret = ARCHIVE_FAILED;
493
goto exit_free;
494
}
495
}
496
}
497
498
#if ARCHIVE_ACL_FREEBSD_NFS4
499
if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
500
/*
501
* acl_get_flagset_np() fails with non-NFSv4 ACLs
502
*/
503
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
504
archive_set_error(a, errno,
505
"Failed to get flagset from an NFSv4 "
506
"ACL entry");
507
ret = ARCHIVE_FAILED;
508
goto exit_free;
509
}
510
if (acl_clear_flags_np(acl_flagset) != 0) {
511
archive_set_error(a, errno,
512
"Failed to clear flags from an NFSv4 "
513
"ACL flagset");
514
ret = ARCHIVE_FAILED;
515
goto exit_free;
516
}
517
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
518
if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
519
if (acl_add_flag_np(acl_flagset,
520
acl_nfs4_flag_map[i].p_perm) != 0) {
521
archive_set_error(a, errno,
522
"Failed to add flag to "
523
"NFSv4 ACL flagset");
524
ret = ARCHIVE_FAILED;
525
goto exit_free;
526
}
527
}
528
}
529
}
530
#endif
531
}
532
533
/* Try restoring the ACL through 'fd' if we can. */
534
if (fd >= 0) {
535
if (acl_set_fd_np(fd, acl, acl_type) == 0)
536
ret = ARCHIVE_OK;
537
else {
538
if (errno == EOPNOTSUPP) {
539
/* Filesystem doesn't support ACLs */
540
ret = ARCHIVE_OK;
541
} else {
542
archive_set_error(a, errno,
543
"Failed to set acl on fd: %s", tname);
544
ret = ARCHIVE_WARN;
545
}
546
}
547
}
548
#if HAVE_ACL_SET_LINK_NP
549
else if (acl_set_link_np(name, acl_type, acl) != 0)
550
#else
551
/* FreeBSD older than 8.0 */
552
else if (S_ISLNK(mode)) {
553
/* acl_set_file() follows symbolic links, skip */
554
ret = ARCHIVE_OK;
555
} else if (acl_set_file(name, acl_type, acl) != 0)
556
#endif
557
{
558
if (errno == EOPNOTSUPP) {
559
/* Filesystem doesn't support ACLs */
560
ret = ARCHIVE_OK;
561
} else {
562
archive_set_error(a, errno, "Failed to set acl: %s",
563
tname);
564
ret = ARCHIVE_WARN;
565
}
566
}
567
exit_free:
568
acl_free(acl);
569
return (ret);
570
}
571
572
int
573
archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
574
struct archive_entry *entry, int *fd)
575
{
576
const char *accpath;
577
acl_t acl;
578
int r;
579
580
accpath = NULL;
581
582
if (*fd < 0) {
583
accpath = archive_read_disk_entry_setup_path(a, entry, fd);
584
if (accpath == NULL)
585
return (ARCHIVE_WARN);
586
}
587
588
archive_entry_acl_clear(entry);
589
590
acl = NULL;
591
592
#if ARCHIVE_ACL_FREEBSD_NFS4
593
/* Try NFSv4 ACL first. */
594
if (*fd >= 0)
595
acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
596
else if (!a->follow_symlinks)
597
acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
598
else
599
acl = acl_get_file(accpath, ACL_TYPE_NFS4);
600
601
/* Ignore "trivial" ACLs that just mirror the file mode. */
602
if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
603
acl_free(acl);
604
acl = NULL;
605
return (ARCHIVE_OK);
606
}
607
608
if (acl != NULL) {
609
r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
610
acl_free(acl);
611
acl = NULL;
612
613
if (r != ARCHIVE_OK) {
614
archive_set_error(&a->archive, errno,
615
"Couldn't translate NFSv4 ACLs");
616
}
617
618
return (r);
619
}
620
#endif
621
622
/* Retrieve access ACL from file. */
623
if (*fd >= 0)
624
acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS);
625
#if HAVE_ACL_GET_LINK_NP
626
else if (!a->follow_symlinks)
627
acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
628
#else
629
else if ((!a->follow_symlinks)
630
&& (archive_entry_filetype(entry) == AE_IFLNK))
631
/* We can't get the ACL of a symlink, so we assume it can't
632
have one. */
633
acl = NULL;
634
#endif
635
else
636
acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
637
638
#if HAVE_ACL_IS_TRIVIAL_NP
639
/* Ignore "trivial" ACLs that just mirror the file mode. */
640
if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
641
acl_free(acl);
642
acl = NULL;
643
}
644
#endif
645
646
if (acl != NULL) {
647
r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
648
acl_free(acl);
649
acl = NULL;
650
651
if (r != ARCHIVE_OK) {
652
archive_set_error(&a->archive, errno,
653
"Couldn't translate access ACLs");
654
return (r);
655
}
656
}
657
658
/* Only directories can have default ACLs. */
659
if (S_ISDIR(archive_entry_mode(entry))) {
660
if (*fd >= 0)
661
acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
662
else
663
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
664
if (acl != NULL) {
665
r = translate_acl(a, entry, acl,
666
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
667
acl_free(acl);
668
if (r != ARCHIVE_OK) {
669
archive_set_error(&a->archive, errno,
670
"Couldn't translate default ACLs");
671
return (r);
672
}
673
}
674
}
675
return (ARCHIVE_OK);
676
}
677
678
int
679
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
680
struct archive_acl *abstract_acl, __LA_MODE_T mode)
681
{
682
int ret = ARCHIVE_OK;
683
684
(void)mode; /* UNUSED */
685
686
if ((archive_acl_types(abstract_acl)
687
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
688
if ((archive_acl_types(abstract_acl)
689
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
690
ret = set_acl(a, fd, name, abstract_acl, mode,
691
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
692
if (ret != ARCHIVE_OK)
693
return (ret);
694
}
695
if ((archive_acl_types(abstract_acl)
696
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
697
ret = set_acl(a, fd, name, abstract_acl, mode,
698
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
699
700
/* Simultaneous POSIX.1e and NFSv4 is not supported */
701
return (ret);
702
}
703
#if ARCHIVE_ACL_FREEBSD_NFS4
704
else if ((archive_acl_types(abstract_acl) &
705
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
706
ret = set_acl(a, fd, name, abstract_acl, mode,
707
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
708
}
709
#endif
710
return (ret);
711
}
712
#endif /* ARCHIVE_ACL_FREEBSD */
713
714