OpenCoverage

set-permissions.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/gnulib/lib/set-permissions.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* Set permissions of a file. -*- coding: utf-8 -*--
2-
3 Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.-
4-
5 This program is free software: you can redistribute it and/or modify-
6 it under the terms of the GNU General Public License as published by-
7 the Free Software Foundation; either version 3 of the License, or-
8 (at your option) any later version.-
9-
10 This program is distributed in the hope that it will be useful,-
11 but WITHOUT ANY WARRANTY; without even the implied warranty of-
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-
13 GNU General Public License for more details.-
14-
15 You should have received a copy of the GNU General Public License-
16 along with this program. If not, see <https://www.gnu.org/licenses/>.-
17-
18 Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */-
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 /* FreeBSD, IRIX, Tru64 */-
28# if HAVE_ACL_GET_FILE && !HAVE_ACL_TYPE_EXTENDED-
29-
30static acl_t-
31acl_from_mode (mode_t mode)-
32{-
33# if HAVE_ACL_FREE_TEXT /* Tru64 */-
34 char acl_text[] = "u::---,g::---,o::---,";-
35# else /* FreeBSD, IRIX */-
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 /* Solaris, Cygwin, not HP-UX */-
55static int-
56set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod)-
57{-
58# ifdef ACE_GETACL-
59 /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4-
60 file systems (whereas the other ones are used in UFS file systems). */-
61-
62 /* The flags in the ace_t structure changed in a binary incompatible way-
63 when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.-
64 How to distinguish the two conventions at runtime?-
65 We fetch the existing ACL. In the old convention, usually three ACEs have-
66 a_flags = ACE_OWNER / ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400.-
67 In the new convention, these values are not used. */-
68 int convention;-
69-
70 {-
71 /* Initially, try to read the entries into a stack-allocated buffer.-
72 Use malloc if it does not fit. */-
73 enum-
74 {-
75 alloc_init = 4000 / sizeof (ace_t), /* >= 3 */-
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 /* Increase the size of the buffer. */-
92 free (malloced);-
93 if (alloc > alloc_max / 2)-
94 {-
95 errno = ENOMEM;-
96 return -1;-
97 }-
98 alloc = 2 * alloc; /* <= alloc_max */-
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 /* Running on Solaris 10. */-
136 entries[0].a_type = OLD_ALLOW;-
137 entries[0].a_flags = OLD_ACE_OWNER;-
138 entries[0].a_who = 0; /* irrelevant */-
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; /* irrelevant */-
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 /* Running on Solaris 10 (newer version) or Solaris 11.-
153 The details here were found through "/bin/ls -lvd somefiles". */-
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; /* irrelevant */-
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; /* irrelevant */-
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; /* irrelevant */-
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; /* irrelevant */-
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; /* irrelevant */-
249 entries[0].a_perm = (mode >> 6) & 7;-
250 entries[1].a_type = GROUP_OBJ;-
251 entries[1].a_id = 0; /* irrelevant */-
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 /* HP-UX */-
277static int-
278context_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 /* HP-UX >= 11.11 */-
304static int-
305context_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; /* irrelevant */-
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; /* irrelevant */-
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 /* AIX */-
331static int-
332set_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 /* XXX Do we need to clear all types of ACLs for the given file, or is it-
346 sufficient to clear the first one? */-
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; /* no entries */-
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 /* older AIX */-
445static int-
446context_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; /* no entries */-
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 /* NonStop Kernel */-
458static int-
459context_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; /* irrelevant */-
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; /* irrelevant */-
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-
484static int-
485set_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 /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */-
492 /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */-
493# if !HAVE_ACL_TYPE_EXTENDED-
494 /* Linux, FreeBSD, IRIX, Tru64 */-
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 /* FreeBSD */-
546-
547 /* File systems either support POSIX ACLs (for example, ufs) or NFS4 ACLs-
548 (for example, zfs). */-
549-
550 /* TODO: Implement setting ACLs once get_permissions() reads them. */-
551-
552# endif-
553-
554# else /* HAVE_ACL_TYPE_EXTENDED */-
555 /* Mac OS X */-
556-
557 /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS)-
558 and acl_get_file (name, ACL_TYPE_DEFAULT)-
559 always return NULL / EINVAL. You have to use-
560 acl_get_file (name, ACL_TYPE_EXTENDED)-
561 or acl_get_fd (open (name, ...))-
562 to retrieve an ACL.-
563 On the other hand,-
564 acl_set_file (name, ACL_TYPE_ACCESS, acl)-
565 and acl_set_file (name, ACL_TYPE_DEFAULT, acl)-
566 have the same effect as-
567 acl_set_file (name, ACL_TYPE_EXTENDED, acl):-
568 Each of these calls sets the file's ACL. */-
569-
570 if (ctx->acl == NULL)-
571 {-
572 acl_t acl;-
573-
574 /* Remove ACLs if the file has ACLs. */-
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 /* Solaris, Cygwin, not HP-UX */-
614-
615 /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions-
616 of Unixware. The acl() call returns the access and default ACL both-
617 at once. */-
618-
619 /* If both ace_entries and entries are available, try SETACL before-
620 ACE_SETACL, because SETACL cannot fail with ENOTSUP whereas ACE_SETACL-
621 can. */-
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 /* HP-UX */-
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 /* AIX */-
700-
701 /* TODO: Implement setting ACLs once get_permissions() reads them. */-
702-
703 if (from_mode)-
704 ret = set_acls_from_mode (name, desc, mode, must_chmod);-
705-
706# elif HAVE_STATACL /* older AIX */-
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 /* NonStop Kernel */-
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 /* No ACLs */-
744-
745 /* Nothing to do. */-
746-
747# endif-
748-
749 return ret;-
750}-
751#endif-
752-
753/* If DESC is a valid file descriptor use fchmod to change the-
754 file's mode to MODE on systems that have fchmod. On systems-
755 that don't have fchmod and if DESC is invalid, use chmod on-
756 NAME instead.-
757 Return 0 if successful. Return -1 and set errno upon failure. */-
758-
759int-
760chmod_or_fchmod (const char *name, int desc, mode_t mode)-
761{-
762 if (HAVE_FCHMOD && desc != -1)
desc != -1Description
TRUEevaluated 3956 times by 3 tests
Evaluated by:
  • cp
  • ginstall
  • mv
FALSEevaluated 33951 times by 2 tests
Evaluated by:
  • cp
  • mv
3956-33951
763 return fchmod (desc, mode);
executed 3956 times by 3 tests: return fchmod (desc, mode);
Executed by:
  • cp
  • ginstall
  • mv
3956
764 else-
765 return chmod (name, mode);
executed 33951 times by 2 tests: return chmod (name, mode);
Executed by:
  • cp
  • mv
33951
766}-
767-
768/* Set the permissions in CTX on a file. If DESC is a valid file descriptor,-
769 use file descriptor operations, else use filename based operations on NAME.-
770 If access control lists are not available, fchmod the target file to the-
771 mode in CTX. Also sets the non-permission bits of the destination file-
772 (S_ISUID, S_ISGID, S_ISVTX) to those from the mode in CTX if any are set.-
773 Return 0 if successful. Return -1 and set errno upon failure. */-
774-
775int-
776set_permissions (struct permission_context *ctx, const char *name, int desc)-
777{-
778 bool acls_set _GL_UNUSED = false;-
779 bool early_chmod;-
780 bool must_chmod = false;-
781 int ret = 0;-
782-
783#if USE_ACL-
784# if HAVE_STATACL-
785 /* older AIX */-
786 /* There is no need to call chmod_or_fchmod, since the mode-
787 bits S_ISUID, S_ISGID, S_ISVTX are also stored in the ACL. */-
788-
789 early_chmod = false;-
790# else-
791 /* All other platforms */-
792 /* On Cygwin, it is necessary to call chmod before acl, because-
793 chmod can change the contents of the ACL (in ways that don't-
794 change the allowed accesses, but still visible). */-
795-
796 early_chmod = (! MODE_INSIDE_ACL || (ctx->mode & (S_ISUID | S_ISGID | S_ISVTX)));-
797# endif-
798#else-
799 /* No ACLs */-
800-
801 early_chmod = true;-
802#endif-
803-
804 if (early_chmod)
early_chmodDescription
TRUEevaluated 37907 times by 3 tests
Evaluated by:
  • cp
  • ginstall
  • mv
FALSEnever evaluated
0-37907
805 {-
806 ret = chmod_or_fchmod (name, desc, ctx->mode);-
807 if (ret != 0)
ret != 0Description
TRUEnever evaluated
FALSEevaluated 37907 times by 3 tests
Evaluated by:
  • cp
  • ginstall
  • mv
0-37907
808 return -1;
never executed: return -1;
0
809 }
executed 37907 times by 3 tests: end of block
Executed by:
  • cp
  • ginstall
  • mv
37907
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 /* If we can't set an acl which we expect to be able to set, try setting-
818 the permissions to ctx->mode. Due to possible inherited permissions,-
819 we cannot simply chmod. */-
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)
must_chmodDescription
TRUEnever evaluated
FALSEevaluated 37907 times by 3 tests
Evaluated by:
  • cp
  • ginstall
  • mv
! early_chmodDescription
TRUEnever evaluated
FALSEnever evaluated
0-37907
834 {-
835 int saved_errno = ret ? errno : 0;
retDescription
TRUEnever evaluated
FALSEnever evaluated
0
836-
837 ret = chmod_or_fchmod (name, desc, ctx->mode);-
838-
839 if (saved_errno)
saved_errnoDescription
TRUEnever evaluated
FALSEnever evaluated
0
840 {-
841 errno = saved_errno;-
842 ret = -1;-
843 }
never executed: end of block
0
844 }
never executed: end of block
0
845-
846 return ret;
executed 37907 times by 3 tests: return ret;
Executed by:
  • cp
  • ginstall
  • mv
37907
847}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2