"Fossies" - the Fresh Open Source Software Archive 
Member "libisofs-1.5.4/libisofs/aaip-os-linux.c" (8 Jul 2020, 18784 Bytes) of package /linux/misc/libisofs-1.5.4.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "aaip-os-linux.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.5.2_vs_1.5.4.
1
2 /*
3
4 aaip-os-linux.c
5 Arbitrary Attribute Interchange Protocol , system adapter for getting and
6 setting of ACLs and xattr.
7
8 To be included by aaip_0_2.c for Linux
9
10 Copyright (c) 2009 - 2018 Thomas Schmitt
11
12 This file is part of the libisofs project; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License version 2
14 or later as published by the Free Software Foundation.
15 See COPYING file for details.
16
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include "../config.h"
21 #endif
22
23 #include <ctype.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <sys/stat.h>
30 #include <errno.h>
31
32
33 #ifdef Libisofs_with_aaip_acL
34 #include <sys/acl.h>
35 #endif
36
37 #ifdef Libisofs_with_aaip_xattR
38 #ifdef Libisofs_with_sys_xattR
39 #include <sys/xattr.h>
40 #else
41 #include <attr/xattr.h>
42 #endif
43 #endif
44
45
46 /* ------------------------------ Inquiry --------------------------------- */
47
48 /* See also API iso_local_attr_support().
49 @param flag
50 Bitfield for control purposes
51 bit0= inquire availability of ACL
52 bit1= inquire availability of xattr
53 bit2 - bit7= Reserved for future types.
54 It is permissibile to set them to 1 already now.
55 bit8 and higher: reserved, submit 0
56 @return
57 Bitfield corresponding to flag. If bits are set, th
58 bit0= ACL adapter is enabled
59 bit1= xattr adapter is enabled
60 bit2 - bit7= Reserved for future types.
61 bit8 and higher: reserved, do not interpret these
62 */
63 int aaip_local_attr_support(int flag)
64 {
65 int ret= 0;
66
67 #ifdef Libisofs_with_aaip_acL
68 if(flag & 1)
69 ret|= 1;
70 #endif
71 #ifdef Libisofs_with_aaip_xattR
72 if(flag & 2)
73 ret|= 2;
74 #endif
75
76 return(ret);
77 }
78
79
80 /* ------------------------------ Getters --------------------------------- */
81
82 /* Obtain the ACL of the given file in long text form.
83 @param path Path to the file
84 @param text Will hold the result. This is a managed object which
85 finally has to be freed by a call to this function
86 with bit15 of flag.
87 @param flag Bitfield for control purposes
88 bit0= obtain default ACL rather than access ACL
89 behave like bit4 if ACL is empty
90 bit4= set *text = NULL and return 2
91 if the ACL matches st_mode permissions.
92 bit5= in case of symbolic link: inquire link target
93 bit15= free text and return 1
94 @return 1 ok
95 2 only st_mode permissions exist and bit 4 is set
96 or empty ACL and bit0 is set
97 0 ACL support not enabled at compile time
98 or filesystem does not support ACL
99 -1 failure of system ACL service (see errno)
100 -2 attempt to inquire ACL of a symbolic link without
101 bit4 or bit5 or with no suitable link target
102 */
103 int aaip_get_acl_text(char *path, char **text, int flag)
104 {
105 #ifdef Libisofs_with_aaip_acL
106
107 acl_t acl= NULL;
108 struct stat stbuf;
109 int ret;
110
111 if(flag & (1 << 15)) {
112 if(*text != NULL)
113 acl_free(*text);
114 *text= NULL;
115 return(1);
116 }
117 *text= NULL;
118
119 if(flag & 32)
120 ret= stat(path, &stbuf);
121 else
122 ret= lstat(path, &stbuf);
123 if(ret == -1)
124 return(-1);
125 if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
126 if(flag & 16)
127 return(2);
128 return(-2);
129 }
130
131 acl= acl_get_file(path, (flag & 1) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS);
132 if(acl == NULL) {
133 if(errno == ENOTSUP) {
134 /* filesystem does not support ACL */
135 if(flag & 16)
136 return(2);
137
138 /* >>> ??? fake ACL from POSIX permissions ? */;
139
140 return(0);
141 }
142 return(-1);
143 }
144 *text= acl_to_text(acl, NULL);
145 acl_free(acl);
146
147 if(*text == NULL)
148 return(-1);
149 if(flag & 16) {
150 ret = aaip_cleanout_st_mode(*text, &(stbuf.st_mode), 2);
151 if(!(ret & (7 | 64)))
152 (*text)[0]= 0;
153 }
154 if(flag & (1 | 16)) {
155 if((*text)[0] == 0 || strcmp(*text, "\n") == 0) {
156 acl_free(*text);
157 *text= NULL;
158 return(2);
159 }
160 }
161 return(1);
162
163 #else /* Libisofs_with_aaip_acL */
164
165 return(0);
166
167 #endif /* ! Libisofs_with_aaip_acL */
168 }
169
170
171 #ifdef Libisofs_with_aaip_xattR
172
173 static int get_single_attr(char *path, char *name, size_t *value_length,
174 char **value_bytes, int flag)
175 {
176 ssize_t value_ret;
177
178 *value_bytes= NULL;
179 *value_length= 0;
180 if(flag & 32)
181 value_ret= getxattr(path, name, NULL, 0);
182 else
183 value_ret= lgetxattr(path, name, NULL, 0);
184 if(value_ret == -1)
185 return(0);
186 *value_bytes= calloc(value_ret + 1, 1);
187 if(*value_bytes == NULL)
188 return(-1);
189 if(flag & 32)
190 value_ret= getxattr(path, name, *value_bytes, value_ret);
191 else
192 value_ret= lgetxattr(path, name, *value_bytes, value_ret);
193 if(value_ret == -1) {
194 free(*value_bytes);
195 *value_bytes= NULL;
196 *value_length= 0;
197 return(0);
198 }
199 *value_length= value_ret;
200 return(1);
201 }
202
203 #endif /* Libisofs_with_aaip_xattR */
204
205
206 /* Obtain the Extended Attributes and/or the ACLs of the given file in a form
207 that is ready for aaip_encode().
208 @param path Path to the file
209 @param num_attrs Will return the number of name-value pairs
210 @param names Will return an array of pointers to 0-terminated names
211 @param value_lengths Will return an array with the lengths of values
212 @param values Will return an array of pointers to 8-bit values
213 @param flag Bitfield for control purposes
214 bit0= obtain ACL (access and eventually default)
215 bit1= use numeric ACL qualifiers rather than names
216 bit2= do not obtain attributes other than ACL
217 bit3= do not ignore eventual non-user attributes
218 I.e. those with a name which does not begin
219 by "user."
220 bit4= do not return trivial ACL that matches st_mode
221 bit5= in case of symbolic link: inquire link target
222 bit15= free memory of names, value_lengths, values
223 @return 1 ok
224 (reserved for FreeBSD: 2 ok, no permission to inspect
225 non-user namespaces.)
226 <=0 error
227 -1= out of memory
228 -2= program error with prediction of result size
229 -3= error with conversion of name to uid or gid
230 */
231 int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
232 size_t **value_lengths, char ***values, int flag)
233 {
234 int ret;
235
236 #ifdef Libisofs_with_aaip_acL
237 unsigned char *acl= NULL;
238 char *a_acl_text= NULL, *d_acl_text= NULL;
239 size_t acl_len= 0;
240 #define Libisofs_aaip_get_attr_activE yes
241 #endif
242 #ifdef Libisofs_with_aaip_xattR
243 char *list= NULL;
244 ssize_t value_ret, list_size= 0;
245 #define Libisofs_aaip_get_attr_activE yes
246 #endif
247 #ifdef Libisofs_aaip_get_attr_activE
248 ssize_t i, num_names= 0;
249 #endif
250
251 if(flag & (1 << 15)) { /* Free memory */
252 {ret= 1; goto ex;}
253 }
254
255 *num_attrs= 0;
256 *names= NULL;
257 *value_lengths= NULL;
258 *values= NULL;
259
260 #ifndef Libisofs_aaip_get_attr_activE
261
262 ret = 1;
263 ex:;
264 return ret;
265
266 #else /* Libisofs_aaip_get_attr_activE */
267
268 /* Set up arrays */
269
270 #ifdef Libisofs_with_aaip_xattR
271
272 if(!(flag & 4)) { /* Get xattr names */
273 if(flag & 32)
274 list_size= listxattr(path, list, 0);
275 else
276 list_size= llistxattr(path, list, 0);
277 if(list_size == -1) {
278 if(errno == ENOSYS) /* Function not implemented */
279 list_size= 0; /* Handle as if xattr was disabled at compile time */
280 else
281 {ret= -1; goto ex;}
282 }
283 if(list_size > 0) {
284 list= calloc(list_size, 1);
285 if(list == NULL)
286 {ret= -1; goto ex;}
287 if(flag & 32)
288 list_size= listxattr(path, list, list_size);
289 else
290 list_size= llistxattr(path, list, list_size);
291 if(list_size == -1)
292 {ret= -1; goto ex;}
293 }
294 for(i= 0; i < list_size; i+= strlen(list + i) + 1)
295 num_names++;
296 }
297
298 #endif /* ! Libisofs_with_aaip_xattR */
299
300 #ifdef Libisofs_with_aaip_acL
301
302 if(flag & 1)
303 num_names++;
304
305 #endif
306
307 if(num_names == 0)
308 {ret= 1; goto ex;}
309 (*names)= calloc(num_names, sizeof(char *));
310 (*value_lengths)= calloc(num_names, sizeof(size_t));
311 (*values)= calloc(num_names, sizeof(char *));
312 if(*names == NULL || *value_lengths == NULL || *values == NULL)
313 {ret= -1; goto ex;}
314
315 for(i= 0; i < num_names; i++) {
316 (*names)[i]= NULL;
317 (*values)[i]= NULL;
318 (*value_lengths)[i]= 0;
319 }
320
321 #ifdef Libisofs_with_aaip_xattR
322
323 if(!(flag & 4)) { /* Get xattr values */
324 for(i= 0; i < list_size && (size_t) num_names > *num_attrs;
325 i+= strlen(list + i) + 1) {
326 if(!(flag & 8))
327 if(strncmp(list + i, "user.", 5))
328 continue;
329 (*names)[(*num_attrs)++]= strdup(list + i);
330 if((*names)[(*num_attrs) - 1] == NULL)
331 {ret= -1; goto ex;}
332 }
333 for(i= 0; (size_t) i < *num_attrs; i++) {
334 if(!(flag & 8))
335 if(strncmp((*names)[i], "user.", 5))
336 continue;
337 value_ret= get_single_attr(path, (*names)[i], *value_lengths + i,
338 *values + i, flag & 32);
339 if(value_ret <= 0)
340 {ret= -1; goto ex;}
341 }
342 }
343
344 #endif /* Libisofs_with_aaip_xattR */
345
346 #ifdef Libisofs_with_aaip_acL
347
348 if(flag & 1) { /* Obtain ACL */
349
350 aaip_get_acl_text(path, &a_acl_text, flag & (16 | 32));
351 aaip_get_acl_text(path, &d_acl_text, 1 | (flag & 32));
352 if(a_acl_text == NULL && d_acl_text == NULL)
353 {ret= 1; goto ex;}
354 ret= aaip_encode_both_acl(a_acl_text, d_acl_text, (mode_t) 0,
355 &acl_len, &acl, (flag & 2));
356 if(ret <= 0)
357 goto ex;
358
359 /* Set as attribute with empty name */;
360 (*names)[*num_attrs]= strdup("");
361 if((*names)[*num_attrs] == NULL)
362 {ret= -1; goto ex;}
363 (*values)[*num_attrs]= (char *) acl;
364 acl= NULL;
365 (*value_lengths)[*num_attrs]= acl_len;
366 (*num_attrs)++;
367 }
368
369 #endif /* Libisofs_with_aaip_acL */
370
371 ret= 1;
372 ex:;
373 #ifdef Libisofs_with_aaip_acL
374 if(a_acl_text != NULL)
375 aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
376 if(d_acl_text != NULL)
377 aaip_get_acl_text("", &d_acl_text, 1 << 15); /* free */
378 if(acl != NULL)
379 free(acl);
380 #endif
381 #ifdef Libisofs_with_aaip_xattR
382 if(list != NULL)
383 free(list);
384 #endif
385
386 if(ret <= 0 || (flag & (1 << 15))) {
387 if(*names != NULL) {
388 for(i= 0; (size_t) i < *num_attrs; i++)
389 free((*names)[i]);
390 free(*names);
391 }
392 *names= NULL;
393 if(*value_lengths != NULL)
394 free(*value_lengths);
395 *value_lengths= NULL;
396 if(*values != NULL) {
397 for(i= 0; (size_t) i < *num_attrs; i++)
398 free((*values)[i]);
399 free(*values);
400 }
401 *values= NULL;
402 *num_attrs= 0;
403 }
404 return(ret);
405
406 #endif /* Libisofs_aaip_get_attr_activE */
407
408 }
409
410
411 /* ------------------------------ Setters --------------------------------- */
412
413
414 /* Set the ACL of the given file to a given list in long text form.
415 @param path Path to the file
416 @param text The input text (0 terminated, ACL long text form)
417 @param flag Bitfield for control purposes
418 bit0= set default ACL rather than access ACL
419 bit5= in case of symbolic link: manipulate link target
420 @return >0 ok
421 0 ACL support not enabled at compile time
422 -1 failure of system ACL service (see errno)
423 -2 attempt to manipulate ACL of a symbolic link
424 without bit5 or with no suitable link target
425 */
426 int aaip_set_acl_text(char *path, char *text, int flag)
427 {
428
429 #ifdef Libisofs_with_aaip_acL
430
431 int ret;
432 acl_t acl= NULL;
433 struct stat stbuf;
434
435 if(flag & 32)
436 ret= stat(path, &stbuf);
437 else
438 ret= lstat(path, &stbuf);
439 if(ret == -1)
440 return(-1);
441 if((stbuf.st_mode & S_IFMT) == S_IFLNK)
442 return(-2);
443
444 acl= acl_from_text(text);
445 if(acl == NULL) {
446 ret= -1; goto ex;
447 }
448 ret= acl_set_file(path, (flag & 1) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS, acl);
449 if(ret == -1)
450 goto ex;
451 ret= 1;
452 ex:
453 if(acl != NULL)
454 acl_free(acl);
455 return(ret);
456
457 #else /* Libisofs_with_aaip_acL */
458
459 return(0);
460
461 #endif /* ! Libisofs_with_aaip_acL */
462
463 }
464
465
466 static void register_errno(int *errnos, int i)
467 {
468 if(errno > 0)
469 errnos[i]= errno;
470 else
471 errnos[i]= -1;
472 }
473
474
475 /* Bring the given attributes and/or ACLs into effect with the given file.
476 @param flag Bitfield for control purposes
477 bit0= decode and set ACLs
478 bit1= first clear all existing attributes of the file
479 bit2= do not set attributes other than ACLs
480 bit3= do not ignore eventual non-user attributes.
481 I.e. those with a name which does not begin
482 by "user."
483 bit5= in case of symbolic link: manipulate link target
484 bit6= tolerate inappropriate presence or absence of
485 directory default ACL
486 bit7= avoid setting a name value pair if it already
487 exists and has the desired value.
488 @return 1 success
489 -1 error memory allocation
490 -2 error with decoding of ACL
491 -3 error with setting ACL
492 -4 error with setting attribute
493 -5 error with deleting attributes
494 -6 support of xattr not enabled at compile time
495 -7 support of ACL not enabled at compile time
496 ( -8 unsupported xattr namespace )
497 ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
498 */
499 int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
500 size_t *value_lengths, char **values,
501 int *errnos, int flag)
502 {
503 int ret, end_ret= 1;
504 size_t i, consumed, acl_text_fill, acl_idx= 0;
505 char *acl_text= NULL;
506 #ifdef Libisofs_with_aaip_xattR
507 char *list= NULL, *old_value;
508 ssize_t list_size= 0, value_ret;
509 size_t old_value_l;
510 int skip;
511 #endif
512 #ifdef Libisofs_with_aaip_acL
513 size_t h_consumed;
514 int has_default_acl= 0;
515 #endif
516
517 for(i= 0; i < num_attrs; i++)
518 errnos[i]= 0;
519
520 #ifdef Libisofs_with_aaip_xattR
521
522 if(flag & 2) { /* Delete all file attributes */
523 if(flag & 32)
524 list_size= listxattr(path, list, 0);
525 else
526 list_size= llistxattr(path, list, 0);
527 }
528 if(list_size > 0) { /* Delete all file attributes */
529 list= calloc(list_size, 1);
530 if(list == NULL)
531 {ret= -5; goto ex;}
532 if(flag & 32)
533 list_size= listxattr(path, list, list_size);
534 else
535 list_size= llistxattr(path, list, list_size);
536 if(list_size == -1)
537 {ret= -5; goto ex;}
538 for(i= 0; i < (size_t) list_size; i+= strlen(list + i) + 1) {
539 if(!(flag & 8))
540 if(strncmp(list + i, "user.", 5))
541 continue;
542 if(flag & 32)
543 ret= removexattr(path, list + i);
544 else
545 ret= lremovexattr(path, list + i);
546 if(ret == -1)
547 {ret= -5; goto ex;}
548 }
549 free(list); list= NULL;
550 }
551
552 #endif /* Libisofs_with_aaip_xattR */
553
554 for(i= 0; i < num_attrs; i++) {
555 if(names[i] == NULL || values[i] == NULL)
556 continue;
557 if(names[i][0] == 0) { /* ACLs */
558 if(flag & 1)
559 acl_idx= i + 1;
560 continue;
561 }
562 /* Extended Attribute */
563 if(flag & 4)
564 continue;
565 if(strncmp(names[i], "isofs.", 6) == 0)
566 continue;
567 if(!(flag & 8))
568 if(strncmp(names[i], "user.", 5))
569 continue;
570
571 #ifdef Libisofs_with_aaip_xattR
572
573 skip= 0;
574 if(flag & 128) {
575 value_ret= get_single_attr(path, names[i], &old_value_l,
576 &old_value, flag & 32);
577 if(value_ret > 0 && old_value_l == value_lengths[i]) {
578 if(memcmp(old_value, values[i], value_lengths[i]) == 0)
579 skip= 1;
580 }
581 if(old_value != NULL)
582 free(old_value);
583 }
584 if(!skip) {
585 if(flag & 32)
586 ret= setxattr(path, names[i], values[i], value_lengths[i], 0);
587 else
588 ret= lsetxattr(path, names[i], values[i], value_lengths[i], 0);
589 if(ret == -1) {
590 register_errno(errnos, i);
591 end_ret= -4;
592 continue;
593 }
594 }
595
596 #else
597
598 {ret= -6; goto ex;}
599
600 #endif /* Libisofs_with_aaip_xattR */
601
602 }
603
604 /* Decode ACLs */
605 /* It is important that this happens after restoring xattr which might be
606 representations of ACL, too. If isofs ACL are enabled, then they shall
607 override the xattr ones.
608 */
609 if(acl_idx == 0)
610 {ret= end_ret; goto ex;}
611 i= acl_idx - 1;
612 /* "access" ACL */
613 ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
614 &consumed, NULL, 0, &acl_text_fill, 1);
615 if(ret < -3)
616 goto ex;
617 if(ret <= 0)
618 {ret= -2; goto ex;}
619 acl_text= calloc(acl_text_fill, 1);
620 if(acl_text == NULL)
621 {ret= -1; goto ex;}
622 ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
623 &consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
624 if(ret < -3)
625 goto ex;
626 if(ret <= 0)
627 {ret= -2; goto ex;}
628
629 #ifdef Libisofs_with_aaip_acL
630
631 has_default_acl= (ret == 2);
632
633 ret= aaip_set_acl_text(path, acl_text, flag & 32);
634 if(ret == -1)
635 register_errno(errnos, i);
636 if(ret <= 0)
637 {ret= -3; goto ex;}
638 /* "default" ACL */
639 if(has_default_acl) {
640 free(acl_text);
641 acl_text= NULL;
642 ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
643 value_lengths[i] - consumed, &h_consumed,
644 NULL, 0, &acl_text_fill, 1);
645 if(ret < -3)
646 goto ex;
647 if(ret <= 0)
648 {ret= -2; goto ex;}
649 acl_text= calloc(acl_text_fill, 1);
650 if(acl_text == NULL)
651 {ret= -1; goto ex;}
652 ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
653 value_lengths[i] - consumed, &h_consumed,
654 acl_text, acl_text_fill, &acl_text_fill, 0);
655 if(ret < -3)
656 goto ex;
657 if(ret <= 0)
658 {ret= -2; goto ex;}
659 ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32));
660 if(ret == -1)
661 register_errno(errnos, i);
662 if(ret <= 0)
663 {ret= -3; goto ex;}
664 } else {
665 if(!(flag & 64)) {
666
667 /* >>> ??? take offense from missing default ACL ?
668 ??? does Linux demand a default ACL for directories with access ACL ?
669 */;
670
671 }
672 }
673 ret= end_ret;
674
675 #else
676
677 ret= -7;
678
679 #endif /* !Libisofs_with_aaip_acL */
680
681 ex:;
682 if(acl_text != NULL)
683 free(acl_text);
684
685 #ifdef Libisofs_with_aaip_xattR
686 if(list != NULL)
687 free(list);
688 #endif
689
690 return(ret);
691 }
692
693