This source file includes following definitions.
- acl_from_mode
- set_acls_from_mode
- context_acl_from_mode
- context_aclv_from_mode
- set_acls_from_mode
- context_acl_from_mode
- context_acl_from_mode
- set_acls
- chmod_or_fchmod
- set_permissions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22 #include "acl.h"
23
24 #include "acl-internal.h"
25
26 #if USE_ACL
27 # if ! defined HAVE_ACL_FROM_MODE && defined HAVE_ACL_FROM_TEXT
28 # if HAVE_ACL_GET_FILE && !HAVE_ACL_TYPE_EXTENDED
29
30 static acl_t
31 acl_from_mode (mode_t mode)
32 {
33 # if HAVE_ACL_FREE_TEXT
34 char acl_text[] = "u::---,g::---,o::---,";
35 # else
36 char acl_text[] = "u::---,g::---,o::---";
37 # endif
38
39 if (mode & S_IRUSR) acl_text[ 3] = 'r';
40 if (mode & S_IWUSR) acl_text[ 4] = 'w';
41 if (mode & S_IXUSR) acl_text[ 5] = 'x';
42 if (mode & S_IRGRP) acl_text[10] = 'r';
43 if (mode & S_IWGRP) acl_text[11] = 'w';
44 if (mode & S_IXGRP) acl_text[12] = 'x';
45 if (mode & S_IROTH) acl_text[17] = 'r';
46 if (mode & S_IWOTH) acl_text[18] = 'w';
47 if (mode & S_IXOTH) acl_text[19] = 'x';
48
49 return acl_from_text (acl_text);
50 }
51 # endif
52 # endif
53
54 # if HAVE_FACL && defined GETACL
55 static int
56 set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod)
57 {
58 # ifdef ACE_GETACL
59
60
61
62
63
64
65
66
67
68 int convention;
69
70 {
71
72
73 enum
74 {
75 alloc_init = 4000 / sizeof (ace_t),
76 alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t))
77 };
78 ace_t buf[alloc_init];
79 size_t alloc = alloc_init;
80 ace_t *entries = buf;
81 ace_t *malloced = NULL;
82 int count;
83
84 for (;;)
85 {
86 count = (desc != -1
87 ? facl (desc, ACE_GETACL, alloc, entries)
88 : acl (name, ACE_GETACL, alloc, entries));
89 if (count < 0 && errno == ENOSPC)
90 {
91
92 free (malloced);
93 if (alloc > alloc_max / 2)
94 {
95 errno = ENOMEM;
96 return -1;
97 }
98 alloc = 2 * alloc;
99 entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t));
100 if (entries == NULL)
101 {
102 errno = ENOMEM;
103 return -1;
104 }
105 continue;
106 }
107 break;
108 }
109
110 if (count <= 0)
111 convention = -1;
112 else
113 {
114 int i;
115
116 convention = 0;
117 for (i = 0; i < count; i++)
118 if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER))
119 {
120 convention = 1;
121 break;
122 }
123 }
124 free (malloced);
125 }
126
127 if (convention >= 0)
128 {
129 ace_t entries[6];
130 int count;
131 int ret;
132
133 if (convention)
134 {
135
136 entries[0].a_type = OLD_ALLOW;
137 entries[0].a_flags = OLD_ACE_OWNER;
138 entries[0].a_who = 0;
139 entries[0].a_access_mask = (mode >> 6) & 7;
140 entries[1].a_type = OLD_ALLOW;
141 entries[1].a_flags = OLD_ACE_GROUP;
142 entries[1].a_who = 0;
143 entries[1].a_access_mask = (mode >> 3) & 7;
144 entries[2].a_type = OLD_ALLOW;
145 entries[2].a_flags = OLD_ACE_OTHER;
146 entries[2].a_who = 0;
147 entries[2].a_access_mask = mode & 7;
148 count = 3;
149 }
150 else
151 {
152
153
154 entries[0].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE;
155 entries[0].a_flags = NEW_ACE_OWNER;
156 entries[0].a_who = 0;
157 entries[0].a_access_mask = 0;
158 entries[1].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE;
159 entries[1].a_flags = NEW_ACE_OWNER;
160 entries[1].a_who = 0;
161 entries[1].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS
162 | NEW_ACE_WRITE_ATTRIBUTES
163 | NEW_ACE_WRITE_ACL
164 | NEW_ACE_WRITE_OWNER;
165 if (mode & 0400)
166 entries[1].a_access_mask |= NEW_ACE_READ_DATA;
167 else
168 entries[0].a_access_mask |= NEW_ACE_READ_DATA;
169 if (mode & 0200)
170 entries[1].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
171 else
172 entries[0].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
173 if (mode & 0100)
174 entries[1].a_access_mask |= NEW_ACE_EXECUTE;
175 else
176 entries[0].a_access_mask |= NEW_ACE_EXECUTE;
177 entries[2].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE;
178 entries[2].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP;
179 entries[2].a_who = 0;
180 entries[2].a_access_mask = 0;
181 entries[3].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE;
182 entries[3].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP;
183 entries[3].a_who = 0;
184 entries[3].a_access_mask = 0;
185 if (mode & 0040)
186 entries[3].a_access_mask |= NEW_ACE_READ_DATA;
187 else
188 entries[2].a_access_mask |= NEW_ACE_READ_DATA;
189 if (mode & 0020)
190 entries[3].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
191 else
192 entries[2].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
193 if (mode & 0010)
194 entries[3].a_access_mask |= NEW_ACE_EXECUTE;
195 else
196 entries[2].a_access_mask |= NEW_ACE_EXECUTE;
197 entries[4].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE;
198 entries[4].a_flags = NEW_ACE_EVERYONE;
199 entries[4].a_who = 0;
200 entries[4].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS
201 | NEW_ACE_WRITE_ATTRIBUTES
202 | NEW_ACE_WRITE_ACL
203 | NEW_ACE_WRITE_OWNER;
204 entries[5].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE;
205 entries[5].a_flags = NEW_ACE_EVERYONE;
206 entries[5].a_who = 0;
207 entries[5].a_access_mask = NEW_ACE_READ_NAMED_ATTRS
208 | NEW_ACE_READ_ATTRIBUTES
209 | NEW_ACE_READ_ACL
210 | NEW_ACE_SYNCHRONIZE;
211 if (mode & 0004)
212 entries[5].a_access_mask |= NEW_ACE_READ_DATA;
213 else
214 entries[4].a_access_mask |= NEW_ACE_READ_DATA;
215 if (mode & 0002)
216 entries[5].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
217 else
218 entries[4].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
219 if (mode & 0001)
220 entries[5].a_access_mask |= NEW_ACE_EXECUTE;
221 else
222 entries[4].a_access_mask |= NEW_ACE_EXECUTE;
223 count = 6;
224 }
225 if (desc != -1)
226 ret = facl (desc, ACE_SETACL, count, entries);
227 else
228 ret = acl (name, ACE_SETACL, count, entries);
229 if (ret < 0 && errno != EINVAL && errno != ENOTSUP)
230 {
231 if (errno == ENOSYS)
232 {
233 *must_chmod = true;
234 return 0;
235 }
236 return -1;
237 }
238 if (ret == 0)
239 return 0;
240 }
241 # endif
242
243 {
244 aclent_t entries[3];
245 int ret;
246
247 entries[0].a_type = USER_OBJ;
248 entries[0].a_id = 0;
249 entries[0].a_perm = (mode >> 6) & 7;
250 entries[1].a_type = GROUP_OBJ;
251 entries[1].a_id = 0;
252 entries[1].a_perm = (mode >> 3) & 7;
253 entries[2].a_type = OTHER_OBJ;
254 entries[2].a_id = 0;
255 entries[2].a_perm = mode & 7;
256
257 if (desc != -1)
258 ret = facl (desc, SETACL,
259 sizeof (entries) / sizeof (aclent_t), entries);
260 else
261 ret = acl (name, SETACL,
262 sizeof (entries) / sizeof (aclent_t), entries);
263 if (ret < 0)
264 {
265 if (errno == ENOSYS || errno == EOPNOTSUPP)
266 {
267 *must_chmod = true;
268 return 0;
269 }
270 return -1;
271 }
272 return 0;
273 }
274 }
275
276 # elif HAVE_GETACL
277 static int
278 context_acl_from_mode (struct permission_context *ctx, const char *name, int desc)
279 {
280 struct stat statbuf;
281 int ret;
282
283 if (desc != -1)
284 ret = fstat (desc, &statbuf);
285 else
286 ret = stat (name, &statbuf);
287 if (ret < 0)
288 return -1;
289
290 ctx->entries[0].uid = statbuf.st_uid;
291 ctx->entries[0].gid = ACL_NSGROUP;
292 ctx->entries[0].mode = (ctx->mode >> 6) & 7;
293 ctx->entries[1].uid = ACL_NSUSER;
294 ctx->entries[1].gid = statbuf.st_gid;
295 ctx->entries[1].mode = (ctx->mode >> 3) & 7;
296 ctx->entries[2].uid = ACL_NSUSER;
297 ctx->entries[2].gid = ACL_NSGROUP;
298 ctx->entries[2].mode = ctx->mode & 7;
299 ctx->count = 3;
300 return 0;
301 }
302
303 # if HAVE_ACLV_H
304 static int
305 context_aclv_from_mode (struct permission_context *ctx)
306 {
307 int ret;
308
309 ctx->aclv_entries[0].a_type = USER_OBJ;
310 ctx->aclv_entries[0].a_id = 0;
311 ctx->aclv_entries[0].a_perm = (ctx->mode >> 6) & 7;
312 ctx->aclv_entries[1].a_type = GROUP_OBJ;
313 ctx->aclv_entries[1].a_id = 0;
314 ctx->aclv_entries[1].a_perm = (ctx->mode >> 3) & 7;
315 ctx->aclv_entries[2].a_type = CLASS_OBJ;
316 ctx->aclv_entries[2].a_id = 0;
317 ctx->aclv_entries[2].a_perm = (ctx->mode >> 3) & 7;
318 ctx->aclv_entries[3].a_type = OTHER_OBJ;
319 ctx->aclv_entries[3].a_id = 0;
320 ctx->aclv_entries[3].a_perm = ctx->mode & 7;
321 ctx->aclv_count = 4;
322
323 ret = aclsort (ctx->aclv_count, 1, ctx->aclv_entries);
324 if (ret > 0)
325 abort ();
326 return ret;
327 }
328 # endif
329
330 # elif HAVE_ACLX_GET && defined ACL_AIX_WIP
331 static int
332 set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod)
333 {
334 acl_type_list_t types;
335 size_t types_size = sizeof (types);
336 acl_type_t type;
337
338 if (aclx_gettypes (name, &types, &types_size) < 0
339 || types.num_entries == 0)
340 {
341 *must_chmod = true;
342 return 0;
343 }
344
345
346
347 type = types.entries[0];
348 if (type.u64 == ACL_AIXC)
349 {
350 union { struct acl a; char room[128]; } u;
351 int ret;
352
353 u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a;
354 u.a.acl_mode = mode & ~(S_IXACL | 0777);
355 u.a.u_access = (mode >> 6) & 7;
356 u.a.g_access = (mode >> 3) & 7;
357 u.a.o_access = mode & 7;
358
359 if (desc != -1)
360 ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS,
361 type, &u.a, u.a.acl_len, mode);
362 else
363 ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS,
364 type, &u.a, u.a.acl_len, mode);
365 if (!(ret < 0 && errno == ENOSYS))
366 return ret;
367 }
368 else if (type.u64 == ACL_NFS4)
369 {
370 union { nfs4_acl_int_t a; char room[128]; } u;
371 nfs4_ace_int_t *ace;
372 int ret;
373
374 u.a.aclVersion = NFS4_ACL_INT_STRUCT_VERSION;
375 u.a.aclEntryN = 0;
376 ace = &u.a.aclEntry[0];
377 {
378 ace->flags = ACE4_ID_SPECIAL;
379 ace->aceWho.special_whoid = ACE4_WHO_OWNER;
380 ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE;
381 ace->aceFlags = 0;
382 ace->aceMask =
383 (mode & 0400 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0)
384 | (mode & 0200
385 ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA
386 | ACE4_ADD_SUBDIRECTORY
387 : 0)
388 | (mode & 0100 ? ACE4_EXECUTE : 0);
389 ace->aceWhoString[0] = '\0';
390 ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace;
391 ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4];
392 u.a.aclEntryN++;
393 }
394 {
395 ace->flags = ACE4_ID_SPECIAL;
396 ace->aceWho.special_whoid = ACE4_WHO_GROUP;
397 ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE;
398 ace->aceFlags = 0;
399 ace->aceMask =
400 (mode & 0040 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0)
401 | (mode & 0020
402 ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA
403 | ACE4_ADD_SUBDIRECTORY
404 : 0)
405 | (mode & 0010 ? ACE4_EXECUTE : 0);
406 ace->aceWhoString[0] = '\0';
407 ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace;
408 ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4];
409 u.a.aclEntryN++;
410 }
411 {
412 ace->flags = ACE4_ID_SPECIAL;
413 ace->aceWho.special_whoid = ACE4_WHO_EVERYONE;
414 ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE;
415 ace->aceFlags = 0;
416 ace->aceMask =
417 (mode & 0004 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0)
418 | (mode & 0002
419 ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA
420 | ACE4_ADD_SUBDIRECTORY
421 : 0)
422 | (mode & 0001 ? ACE4_EXECUTE : 0);
423 ace->aceWhoString[0] = '\0';
424 ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace;
425 ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4];
426 u.a.aclEntryN++;
427 }
428 u.a.aclLength = (char *) ace - (char *) &u.a;
429
430 if (desc != -1)
431 ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS,
432 type, &u.a, u.a.aclLength, mode);
433 else
434 ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS,
435 type, &u.a, u.a.aclLength, mode);
436 if (!(ret < 0 && errno == ENOSYS))
437 return ret;
438 }
439
440 *must_chmod = true;
441 return 0;
442 }
443
444 # elif HAVE_STATACL
445 static int
446 context_acl_from_mode (struct permission_context *ctx)
447 {
448 ctx->u.a.acl_len = (char *) &ctx->u.a.acl_ext[0] - (char *) &ctx->u.a;
449 ctx->u.a.acl_mode = ctx->mode & ~(S_IXACL | 0777);
450 ctx->u.a.u_access = (ctx->mode >> 6) & 7;
451 ctx->u.a.g_access = (ctx->mode >> 3) & 7;
452 ctx->u.a.o_access = ctx->mode & 7;
453 ctx->have_u = true;
454 return 0;
455 }
456
457 # elif HAVE_ACLSORT
458 static int
459 context_acl_from_mode (struct permission_context *ctx)
460 {
461 int ret;
462
463 ctx->entries[0].a_type = USER_OBJ;
464 ctx->entries[0].a_id = 0;
465 ctx->entries[0].a_perm = (ctx->mode >> 6) & 7;
466 ctx->entries[1].a_type = GROUP_OBJ;
467 ctx->entries[1].a_id = 0;
468 ctx->entries[1].a_perm = (ctx->mode >> 3) & 7;
469 ctx->entries[2].a_type = CLASS_OBJ;
470 ctx->entries[2].a_id = 0;
471 ctx->entries[2].a_perm = (ctx->mode >> 3) & 7;
472 ctx->entries[3].a_type = OTHER_OBJ;
473 ctx->entries[3].a_id = 0;
474 ctx->entries[3].a_perm = ctx->mode & 7;
475 ctx->count = 4;
476
477 ret = aclsort (ctx->count, 1, entries);
478 if (ret > 0)
479 abort ();
480 return ret;
481 }
482 # endif
483
484 static int
485 set_acls (struct permission_context *ctx, const char *name, int desc,
486 int from_mode, bool *must_chmod, bool *acls_set)
487 {
488 int ret = 0;
489
490 # if HAVE_ACL_GET_FILE
491
492
493 # if !HAVE_ACL_TYPE_EXTENDED
494
495
496 # ifndef HAVE_ACL_FROM_TEXT
497 # error Must have acl_from_text (see POSIX 1003.1e draft 17).
498 # endif
499 # ifndef HAVE_ACL_DELETE_DEF_FILE
500 # error Must have acl_delete_def_file (see POSIX 1003.1e draft 17).
501 # endif
502
503 if (! ctx->acls_not_supported)
504 {
505 if (ret == 0 && from_mode)
506 {
507 if (ctx->acl)
508 acl_free (ctx->acl);
509 ctx->acl = acl_from_mode (ctx->mode);
510 if (ctx->acl == NULL)
511 ret = -1;
512 }
513
514 if (ret == 0 && ctx->acl)
515 {
516 if (HAVE_ACL_SET_FD && desc != -1)
517 ret = acl_set_fd (desc, ctx->acl);
518 else
519 ret = acl_set_file (name, ACL_TYPE_ACCESS, ctx->acl);
520 if (ret != 0)
521 {
522 if (! acl_errno_valid (errno))
523 {
524 ctx->acls_not_supported = true;
525 if (from_mode || acl_access_nontrivial (ctx->acl) == 0)
526 ret = 0;
527 }
528 }
529 else
530 {
531 *acls_set = true;
532 if (S_ISDIR(ctx->mode))
533 {
534 if (! from_mode && ctx->default_acl &&
535 acl_default_nontrivial (ctx->default_acl))
536 ret = acl_set_file (name, ACL_TYPE_DEFAULT,
537 ctx->default_acl);
538 else
539 ret = acl_delete_def_file (name);
540 }
541 }
542 }
543 }
544
545 # if HAVE_ACL_TYPE_NFS4
546
547
548
549
550
551
552 # endif
553
554 # else
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570 if (ctx->acl == NULL)
571 {
572 acl_t acl;
573
574
575 if (HAVE_ACL_GET_FD && desc != -1)
576 acl = acl_get_fd (desc);
577 else
578 acl = acl_get_file (name, ACL_TYPE_EXTENDED);
579 if (acl)
580 {
581 acl_free (acl);
582
583 acl = acl_init (0);
584 if (acl)
585 {
586 if (HAVE_ACL_SET_FD && desc != -1)
587 ret = acl_set_fd (desc, acl);
588 else
589 ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl);
590 acl_free (acl);
591 }
592 else
593 ret = -1;
594 }
595 }
596 else
597 {
598 if (HAVE_ACL_SET_FD && desc != -1)
599 ret = acl_set_fd (desc, ctx->acl);
600 else
601 ret = acl_set_file (name, ACL_TYPE_EXTENDED, ctx->acl);
602 if (ret != 0)
603 {
604 if (! acl_errno_valid (errno)
605 && ! acl_extended_nontrivial (ctx->acl))
606 ret = 0;
607 }
608 }
609 *acls_set = true;
610
611 # endif
612
613 # elif defined GETACL
614
615
616
617
618
619
620
621
622
623 if (from_mode)
624 return set_acls_from_mode (name, desc, ctx->mode, must_chmod);
625
626 if (ret == 0 && ctx->count)
627 {
628 if (desc != -1)
629 ret = facl (desc, SETACL, ctx->count, ctx->entries);
630 else
631 ret = acl (name, SETACL, ctx->count, ctx->entries);
632 if (ret < 0)
633 {
634 if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
635 && acl_nontrivial (ctx->count, ctx->entries) == 0)
636 ret = 0;
637 }
638 else
639 *acls_set = true;
640 }
641
642 # ifdef ACE_GETACL
643 if (ret == 0 && ctx->ace_count)
644 {
645 if (desc != -1)
646 ret = facl (desc, ACE_SETACL, ctx->ace_count, ctx->ace_entries);
647 else
648 ret = acl (name, ACE_SETACL, ctx->ace_count, ctx->ace_entries);
649 if (ret < 0)
650 {
651 if ((errno == ENOSYS || errno == EINVAL || errno == ENOTSUP)
652 && acl_ace_nontrivial (ctx->ace_count, ctx->ace_entries) == 0)
653 ret = 0;
654 }
655 else
656 *acls_set = true;
657 }
658 # endif
659
660 # elif HAVE_GETACL
661
662 if (from_mode)
663 ret = context_acl_from_mode (ctx, name, desc);
664
665 if (ret == 0 && ctx->count > 0)
666 {
667 if (desc != -1)
668 ret = fsetacl (desc, ctx->count, ctx->entries);
669 else
670 ret = setacl (name, ctx->count, ctx->entries);
671 if (ret < 0)
672 {
673 if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
674 && (from_mode || !acl_nontrivial (ctx->count, ctx->entries)))
675 ret = 0;
676 }
677 else
678 *acls_set = true;
679 }
680
681 # if HAVE_ACLV_H
682 if (from_mode)
683 ret = context_aclv_from_mode (ctx);
684
685 if (ret == 0 && ctx->aclv_count > 0)
686 {
687 ret = acl ((char *) name, ACL_SET, ctx->aclv_count, ctx->aclv_entries);
688 if (ret < 0)
689 {
690 if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
691 && (from_mode || !aclv_nontrivial (ctx->aclv_count, ctx->aclv_entries)))
692 ret = 0;
693 }
694 else
695 *acls_set = true;
696 }
697 # endif
698
699 # elif HAVE_ACLX_GET && ACL_AIX_WIP
700
701
702
703 if (from_mode)
704 ret = set_acls_from_mode (name, desc, mode, must_chmod);
705
706 # elif HAVE_STATACL
707
708 if (from_mode)
709 ret = context_acl_from_mode (ctx);
710
711 if (ret == 0 && ctx->have_u)
712 {
713 if (desc != -1)
714 ret = fchacl (desc, &ctx->u.a, ctx->u.a.acl_len);
715 else
716 ret = chacl ((char *) name, &ctx->u.a, ctx->u.a.acl_len);
717 if (ret < 0)
718 {
719 if (errno == ENOSYS && from_mode)
720 ret = 0;
721 }
722 else
723 *acls_set = true;
724 }
725
726 # elif HAVE_ACLSORT
727
728 if (from_mode)
729 ret = context_acl_from_mode (ctx);
730
731 if (ret == 0 && ctx->count)
732 {
733 ret = acl ((char *) name, ACL_SET, ctx->count, ctx->entries);
734 if (ret != 0)
735 {
736 if (!acl_nontrivial (ctx->count, ctx->entries))
737 ret = 0;
738 }
739 else
740 *acls_set = true;
741 }
742
743 # else
744
745
746
747 # endif
748
749 return ret;
750 }
751 #endif
752
753
754
755
756
757
758
759 int
760 chmod_or_fchmod (const char *name, int desc, mode_t mode)
761 {
762 if (HAVE_FCHMOD && desc != -1)
763 return fchmod (desc, mode);
764 else
765 return chmod (name, mode);
766 }
767
768
769
770
771
772
773
774
775 int
776 set_permissions (struct permission_context *ctx, const char *name, int desc)
777 {
778 _GL_UNUSED bool acls_set = false;
779 bool early_chmod;
780 bool must_chmod = false;
781 int ret = 0;
782
783 #if USE_ACL
784 # if HAVE_STATACL
785
786
787
788
789 early_chmod = false;
790 # else
791
792
793
794
795
796 early_chmod = (! MODE_INSIDE_ACL || (ctx->mode & (S_ISUID | S_ISGID | S_ISVTX)));
797 # endif
798 #else
799
800
801 early_chmod = true;
802 #endif
803
804 if (early_chmod)
805 {
806 ret = chmod_or_fchmod (name, desc, ctx->mode);
807 if (ret != 0)
808 return -1;
809 }
810
811 #if USE_ACL
812 ret = set_acls (ctx, name, desc, false, &must_chmod, &acls_set);
813 if (! acls_set)
814 {
815 int saved_errno = ret ? errno : 0;
816
817
818
819
820
821 ret = set_acls (ctx, name, desc, true, &must_chmod, &acls_set);
822 if (! acls_set)
823 must_chmod = true;
824
825 if (saved_errno)
826 {
827 errno = saved_errno;
828 ret = -1;
829 }
830 }
831 #endif
832
833 if (must_chmod && ! early_chmod)
834 {
835 int saved_errno = ret ? errno : 0;
836
837 ret = chmod_or_fchmod (name, desc, ctx->mode);
838
839 if (saved_errno)
840 {
841 errno = saved_errno;
842 ret = -1;
843 }
844 }
845
846 return ret;
847 }