"Fossies" - the Fresh Open Source Software Archive 
Member "xorriso-1.5.4/libisofs/aaip-os-freebsd.c" (30 Jan 2021, 31189 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.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-freebsd.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.5.2_vs_1.5.4.
1
2 /*
3
4 aaip-os-freebsd.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 FreeBSD, NetBSD, and OpenBSD
9
10 Copyright (c) 2009 - 2016 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 #ifdef Libisofs_with_aaip_acL
33 #include <sys/acl.h>
34 #endif
35
36 #ifdef Libisofs_with_freebsd_extattR
37 #include <sys/extattr.h>
38 #endif
39
40 #include <sys/statvfs.h>
41
42 /* <<< Use old ACL adapter code that is unable to deal with extattr */
43 /* # define Libisofs_old_freebsd_acl_adapteR */
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.
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_freebsd_extattR
72 if(flag & 2)
73 ret|= 2;
74 #endif
75
76 return(ret);
77 }
78
79
80 #ifdef Libisofs_with_freebsd_extattR
81
82 static int aaip_extattr_path_supp(char *path, int flag)
83 {
84
85 #ifdef MNT_EXTATTR
86
87 int ret;
88 struct statvfs statvfs_buf;
89
90 ret = statvfs(path, &statvfs_buf);
91 if(ret == -1)
92 return(1);
93 return(!!(statvfs_buf.f_flag & MNT_EXTATTR));
94
95 #else /* MNT_EXTATTR */
96
97 return(1);
98
99 #endif /* ! MNT_EXTATTR */
100
101 }
102
103 #endif /* Libisofs_with_freebsd_extattR */
104
105
106 /* ------------------------------ Getters --------------------------------- */
107
108 /* Obtain the ACL of the given file in long text form.
109 @param path Path to the file
110 @param text Will hold the result. This is a managed object which
111 finally has to be freed by a call to this function
112 with bit15 of flag.
113 @param flag Bitfield for control purposes
114 (bit0= obtain default ACL rather than access ACL)
115 bit4= set *text = NULL and return 2
116 if the ACL matches st_mode permissions.
117 bit5= in case of symbolic link: inquire link target
118 bit15= free text and return 1
119 @return > 0 ok
120 0 ACL support not enabled at compile time
121 or filesystem does not support ACL
122 -1 failure of system ACL service (see errno)
123 -2 attempt to inquire ACL of a symbolic
124 link without bit4 or bit5
125 */
126 int aaip_get_acl_text(char *path, char **text, int flag)
127 {
128 #ifdef Libisofs_with_aaip_acL
129 acl_t acl= NULL;
130 #endif
131 struct stat stbuf;
132 int ret;
133
134 if(flag & (1 << 15)) {
135 if(*text != NULL)
136 #ifdef Libisofs_with_aaip_acL
137 acl_free(*text);
138 #else
139 free(*text);
140 #endif
141 *text= NULL;
142 return(1);
143 }
144
145 *text= NULL;
146 if(flag & 32)
147 ret= stat(path, &stbuf);
148 else
149 ret= lstat(path, &stbuf);
150 if(ret == -1)
151 return(-1);
152 if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
153 if(flag & 16)
154 return(2);
155 return(-2);
156 }
157
158 /* Note: no ACL_TYPE_DEFAULT in FreeBSD */
159 if(flag & 1)
160 return(0);
161
162 #ifdef Libisofs_with_aaip_acL
163
164 acl= acl_get_file(path, ACL_TYPE_ACCESS);
165
166 if(acl == NULL) {
167 if(errno == EOPNOTSUPP) {
168 /* filesystem does not support ACL */
169 if(flag & 16)
170 return(2);
171
172 /* >>> ??? fake ACL from POSIX permissions ? */;
173
174 return(0);
175 }
176 return(-1);
177 }
178 *text= acl_to_text(acl, NULL);
179 acl_free(acl);
180
181 #else /* Libisofs_with_aaip_acL */
182
183 /* ??? >>> Fake ACL */;
184
185 return(0);
186
187 #endif /* ! Libisofs_with_aaip_acL */
188
189 if(*text == NULL)
190 return(-1);
191 if(flag & 16) {
192 ret = aaip_cleanout_st_mode(*text, &(stbuf.st_mode), 2);
193 if(!(ret & (7 | 64)))
194 (*text)[0]= 0;
195 if((*text)[0] == 0 || strcmp(*text, "\n") == 0) {
196 #ifdef Libisofs_with_aaip_acL
197 acl_free(*text);
198 #else
199 free(*text);
200 #endif
201 *text= NULL;
202 return(2);
203 }
204 }
205 return(1);
206 }
207
208
209 #ifndef Libisofs_old_freebsd_acl_adapteR
210
211 #ifdef Libisofs_with_freebsd_extattR
212
213 /*
214 @param flag Bitfield for control purposes
215 bit5= in case of symbolic link: inquire link target
216 */
217 static int aaip_extattr_make_list(char *path, int attrnamespace,
218 char **list, ssize_t *list_size, int flag)
219 {
220 *list= NULL;
221 *list_size= 0;
222
223 /* man 2 extattr_list_file:
224 If data is NULL in a call to extattr_get_file() and extattr_list_file()
225 then the size of defined extended attribute data will be returned,
226 */
227 if(flag & 32) /* follow link */
228 *list_size= extattr_list_file(path, attrnamespace, NULL, (size_t) 0);
229 else
230 *list_size= extattr_list_link(path, attrnamespace, NULL, (size_t) 0);
231 if(*list_size == -1) {
232 if(! aaip_extattr_path_supp(path, 0)) {
233 *list_size = 0;
234 return(2);
235 }
236 if(errno == EPERM && attrnamespace == EXTATTR_NAMESPACE_SYSTEM) {
237 *list_size = 0;
238 return(3);
239 }
240 return(0);
241 }
242 if(*list_size == 0)
243 return(2);
244 *list= calloc(*list_size, 1);
245 if(*list == NULL)
246 return(-1);
247 if(flag & 32)
248 *list_size= extattr_list_file(path, attrnamespace, *list,
249 (size_t) *list_size);
250 else
251 *list_size= extattr_list_link(path, attrnamespace, *list,
252 (size_t) *list_size);
253 if(*list_size == -1)
254 return(0);
255 return(1);
256 }
257
258
259 /*
260 @param flag Bitfield for control purposes
261 bit0= preserve existing namelist content
262 bit1= ignore names with NUL rather than returning error
263 */
264 static int aaip_extattr_make_namelist(char *path, char *attrnamespace,
265 char *list, ssize_t list_size,
266 char **namelist, ssize_t *namelist_size,
267 ssize_t *num_names, int flag)
268 {
269 int i, j, len, new_bytes= 0, space_len;
270 char *new_list= NULL, *wpt;
271
272 if(!(flag & 1)) {
273 *namelist= NULL;
274 *namelist_size= 0;
275 *num_names= 0;
276 }
277 if(list_size <= 0)
278 return(1);
279 space_len= strlen(attrnamespace);
280 for(i= 0; i < list_size; i+= len + 1) {
281 len= *((unsigned char *) (list + i));
282 if(len == 0)
283 return ISO_AAIP_BAD_ATTR_NAME; /* empty name is reserved for ACL */
284 for(j= 0; j < len; j++)
285 if(list[i + 1 + j] == 0) {
286 if(flag & 2)
287 continue;
288 return ISO_AAIP_BAD_ATTR_NAME; /* names may not contain 0-bytes */
289 }
290 new_bytes+= space_len + 1 + len + 1;
291 }
292 if((flag & 1) && *namelist_size > 0)
293 new_bytes+= *namelist_size;
294 new_list= calloc(new_bytes, 1);
295 if(new_list == NULL)
296 return(ISO_OUT_OF_MEM);
297 wpt= new_list;
298 if((flag & 1) && *namelist_size > 0) {
299 memcpy(new_list, *namelist, *namelist_size);
300 wpt= new_list + *namelist_size;
301 }
302 for(i= 0; i < list_size; i+= len + 1) {
303 len= *((unsigned char *) (list + i));
304 if(flag & 2) {
305 for(j= 0; j < len; j++)
306 if(list[i + j] == 0)
307 continue;
308 }
309 memcpy(wpt, attrnamespace, space_len);
310 wpt[space_len]= '.';
311 wpt+= space_len + 1;
312 memcpy(wpt, list + i + 1, len);
313 wpt+= len;
314 *(wpt++)= 0;
315 (*num_names)++;
316 }
317 if((flag & 1) && *namelist != NULL)
318 free(*namelist);
319 *namelist= new_list;
320 *namelist_size= new_bytes;
321 return(1);
322 }
323
324
325 static int get_single_attr(char *path, char *name, size_t *value_length,
326 char **value_bytes, int flag)
327 {
328 char *namept;
329 int attrnamespace;
330 ssize_t value_ret;
331
332 *value_bytes= NULL;
333 *value_length= 0;
334 if(strncmp(name, "user.", 5) == 0) {
335 attrnamespace= EXTATTR_NAMESPACE_USER;
336 namept= name + 5;
337 } else {
338 if(!(flag & 8))
339 return(0);
340 attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
341 namept= name + 7;
342 }
343 /* Predict length of value */
344 if(flag & 32) /* follow link */
345 value_ret= extattr_get_file(path, attrnamespace, namept, NULL, (size_t) 0);
346 else
347 value_ret= extattr_get_link(path, attrnamespace, namept, NULL, (size_t) 0);
348 if(value_ret == -1)
349 return(0);
350
351 *value_bytes= calloc(value_ret + 1, 1);
352 if(*value_bytes == NULL)
353 return(-1);
354
355 /* Obtain value */
356 if(flag & 32) /* follow link */
357 value_ret= extattr_get_file(path, attrnamespace, namept,
358 *value_bytes, (size_t) value_ret);
359 else
360 value_ret= extattr_get_link(path, attrnamespace, namept,
361 *value_bytes, (size_t) value_ret);
362 if(value_ret == -1) {
363 free(*value_bytes);
364 *value_bytes= NULL;
365 *value_length= 0;
366 return(0);
367 }
368 *value_length= value_ret;
369 return(1);
370 }
371
372 #endif /* Libisofs_with_freebsd_extattR */
373
374
375 /* Obtain the Extended Attributes and/or the ACLs of the given file in a form
376 that is ready for aaip_encode().
377 @param path Path to the file
378 @param num_attrs Will return the number of name-value pairs
379 @param names Will return an array of pointers to 0-terminated names
380 @param value_lengths Will return an array with the lengths of values
381 @param values Will return an array of pointers to 8-bit values
382 @param flag Bitfield for control purposes
383 bit0= obtain ACL (access and eventually default)
384 bit1= use numeric ACL qualifiers rather than names
385 bit2= do not obtain attributes other than ACL
386 bit3= do not ignore eventual non-user attributes
387 I.e. those with a name which does not begin
388 by "user."
389 bit4= do not return trivial ACL that matches st_mode
390 bit5= in case of symbolic link: inquire link target
391 bit15= free memory of names, value_lengths, values
392 @return 1 ok
393 2 ok, no permission to inspect non-user namespaces
394 <=0 error
395 -1= out of memory
396 -2= program error with prediction of result size
397 -3= error with conversion of name to uid or gid
398 */
399 int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
400 size_t **value_lengths, char ***values, int flag)
401 {
402 int ret;
403 ssize_t i, num_names= 0;
404
405 #ifdef Libisofs_with_aaip_acL
406 unsigned char *a_acl= NULL;
407 char *a_acl_text= NULL;
408 size_t a_acl_len= 0;
409 #endif
410 #ifdef Libisofs_with_freebsd_extattR
411 char *list= NULL, *user_list= NULL, *sys_list= NULL;
412 ssize_t value_ret, list_size= 0, user_list_size= 0;
413 ssize_t sys_list_size= 0;
414 int acl_names= 0;
415 #endif
416 int no_perm_for_system= 0;
417
418 if(flag & (1 << 15)) { /* Free memory */
419 {ret= 1; goto ex;}
420 }
421
422 *num_attrs= 0;
423 *names= NULL;
424 *value_lengths= NULL;
425 *values= NULL;
426
427 /* Set up arrays */
428
429 #ifdef Libisofs_with_freebsd_extattR
430
431 if(!(flag & 4)) { /* Get extattr names */
432
433 /* Linux : Names are encoded as name NUL
434 FreeBSD: Names are encoded as length_byte:chars (no NUL)
435 AAIP demands names not to contain NUL bytes.
436 */
437
438 /* Obtain lists of names
439 Must be done separately for namespaces. See man 9 extattr :
440 EXTATTR_NAMESPACE_USER , EXTATTR_NAMESPACE_SYSTEM
441 Must then be marked by "user." and "system." for libisofs use.
442 */
443 ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER,
444 &user_list, &user_list_size, flag & 32);
445 if(ret <= 0)
446 {ret= -1; goto ex;}
447 if(flag & 8) {
448 ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_SYSTEM,
449 &sys_list, &sys_list_size, flag & 32);
450 if(ret <= 0)
451 {ret= -1; goto ex;}
452 if(ret == 3)
453 no_perm_for_system= 1;
454 }
455
456 /* Check for NUL in names, convert into a linuxish list of namespace.name */
457 ret= aaip_extattr_make_namelist(path, "user", user_list, user_list_size,
458 &list, &list_size, &num_names, 0);
459 if(ret <= 0)
460 goto ex;
461 ret= aaip_extattr_make_namelist(path, "system", sys_list, sys_list_size,
462 &list, &list_size, &num_names, 1);
463 if(ret <= 0)
464 goto ex;
465 }
466
467 #endif /* Libisofs_with_freebsd_extattR */
468
469 #ifdef Libisofs_with_aaip_acL
470 if(flag & 1) {
471 num_names++;
472
473 #ifdef Libisofs_with_freebsd_extattR
474 acl_names= 1;
475 #endif
476
477 }
478 #endif
479
480 if(num_names == 0)
481 {ret= 1; goto ex;}
482 (*names)= calloc(num_names, sizeof(char *));
483 (*value_lengths)= calloc(num_names, sizeof(size_t));
484 (*values)= calloc(num_names, sizeof(char *));
485 if(*names == NULL || *value_lengths == NULL || *values == NULL)
486 {ret= -1; goto ex;}
487
488 for(i= 0; i < num_names; i++) {
489 (*names)[i]= NULL;
490 (*values)[i]= NULL;
491 (*value_lengths)[i]= 0;
492 }
493
494 #ifdef Libisofs_with_freebsd_extattR
495
496 if(!(flag & 4)) { /* Get xattr values */
497 for(i= 0; i < list_size && (size_t) num_names - acl_names > *num_attrs;
498 i+= strlen(list + i) + 1) {
499 if(!(flag & 8))
500 if(strncmp(list + i, "user.", 5))
501 continue;
502 (*names)[(*num_attrs)++]= strdup(list + i);
503 if((*names)[(*num_attrs) - 1] == NULL)
504 {ret= -1; goto ex;}
505 }
506
507 for(i= 0; (size_t) i < *num_attrs; i++) {
508 value_ret= get_single_attr(path, (*names)[i], *value_lengths + i,
509 *values + i, flag & (8 | 32));
510 if(value_ret <= 0)
511 {ret= -1; goto ex;}
512 }
513 }
514
515 #endif /* Libisofs_with_freebsd_extattR */
516
517 #ifdef Libisofs_with_aaip_acL
518
519 if(flag & 1) { /* Obtain ACL */
520 /* access-ACL */
521 aaip_get_acl_text(path, &a_acl_text, flag & (16 | 32));
522 if(a_acl_text == NULL) {
523 /* empty ACL / only st_mode info was found in ACL */
524 ret= 1 + no_perm_for_system;
525 goto ex;
526 }
527 ret= aaip_encode_acl(a_acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2);
528 if(ret <= 0)
529 goto ex;
530
531 /* Note: There are no default-ACL in FreeBSD */
532
533 /* Set as attribute with empty name */;
534 (*names)[*num_attrs]= strdup("");
535 if((*names)[*num_attrs] == NULL)
536 {ret= -1; goto ex;}
537 (*values)[*num_attrs]= (char *) a_acl;
538 a_acl= NULL;
539 (*value_lengths)[*num_attrs]= a_acl_len;
540 (*num_attrs)++;
541 }
542
543 #endif /* Libisofs_with_aaip_acL */
544
545 ret= 1 + no_perm_for_system;
546 ex:;
547 #ifdef Libisofs_with_aaip_acL
548 if(a_acl != NULL)
549 free(a_acl);
550 if(a_acl_text != NULL)
551 aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
552 #endif
553 #ifdef Libisofs_with_freebsd_extattR
554 if(list != NULL)
555 free(list);
556 if(user_list != NULL)
557 free(user_list);
558 if(sys_list != NULL)
559 free(sys_list);
560 #endif
561
562 if(ret <= 0 || (flag & (1 << 15))) {
563 if(*names != NULL) {
564 for(i= 0; (size_t) i < *num_attrs; i++)
565 free((*names)[i]);
566 free(*names);
567 }
568 *names= NULL;
569 if(*value_lengths != NULL)
570 free(*value_lengths);
571 *value_lengths= NULL;
572 if(*values != NULL) {
573 for(i= 0; (size_t) i < *num_attrs; i++)
574 free((*values)[i]);
575 free(*values);
576 }
577 *values= NULL;
578 *num_attrs= 0;
579 }
580 return(ret);
581 }
582
583 #else /* ! Libisofs_old_freebsd_acl_adapteR */
584
585 /* Obtain the Extended Attributes and/or the ACLs of the given file in a form
586 that is ready for aaip_encode().
587
588 Note: There are no Extended Attributes in FreeBSD. So only ACL will be
589 obtained.
590
591 @param path Path to the file
592 @param num_attrs Will return the number of name-value pairs
593 @param names Will return an array of pointers to 0-terminated names
594 @param value_lengths Will return an array with the lengths of values
595 @param values Will return an array of pointers to 8-bit values
596 @param flag Bitfield for control purposes
597 bit0= obtain ACL (access and eventually default)
598 bit1= use numeric ACL qualifiers rather than names
599 bit2= do not encode attributes other than ACL
600 bit3= do not ignore eventual non-user attributes
601 I.e. those which are not from name space
602 EXTATTR_NAMESPACE_USER
603 bit4= do not return trivial ACL that matches st_mode
604 bit15= free memory of names, value_lengths, values
605 @return >0 ok
606 <=0 error
607 -1= out of memory
608 -2= program error with prediction of result size
609 -3= error with conversion of name to uid or gid
610 */
611 int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
612 size_t **value_lengths, char ***values, int flag)
613 {
614 int ret;
615 ssize_t i, num_names;
616
617 #ifdef Libisofs_with_aaip_acL
618 size_t a_acl_len= 0;
619 unsigned char *a_acl= NULL;
620 char *acl_text= NULL;
621 #endif
622
623 if(flag & (1 << 15)) { /* Free memory */
624 {ret= 1; goto ex;}
625 }
626
627 *num_attrs= 0;
628 *names= NULL;
629 *value_lengths= NULL;
630 *values= NULL;
631
632 num_names= 0;
633 if(flag & 1)
634 num_names++;
635 if(num_names == 0)
636 {ret= 1; goto ex;}
637 (*names)= calloc(num_names, sizeof(char *));
638 (*value_lengths)= calloc(num_names, sizeof(size_t));
639 (*values)= calloc(num_names, sizeof(char *));
640 if(*names == NULL || *value_lengths == NULL || *values == NULL)
641 {ret= -1; goto ex;}
642
643 for(i= 0; i < num_names; i++) {
644 (*names)[i]= NULL;
645 (*values)[i]= NULL;
646 (*value_lengths)[i]= 0;
647 }
648
649 #ifdef Libisofs_with_aaip_acL
650
651 if(flag & 1) { /* Obtain ACL */
652 /* access-ACL */
653 aaip_get_acl_text(path, &acl_text, flag & (16 | 32));
654 if(acl_text == NULL)
655 {ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */
656 ret= aaip_encode_acl(acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2);
657 if(ret <= 0)
658 goto ex;
659 aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
660
661 /* Note: There are no default-ACL in FreeBSD */
662
663 /* Set as attribute with empty name */;
664 (*names)[*num_attrs]= strdup("");
665 if((*names)[*num_attrs] == NULL)
666 {ret= -1; goto ex;}
667 (*values)[*num_attrs]= (char *) a_acl;
668 a_acl= NULL;
669 (*value_lengths)[*num_attrs]= a_acl_len;
670 (*num_attrs)++;
671 }
672
673 #endif /* ! Libisofs_with_aaip_acL */
674
675 ret= 1;
676 ex:;
677 #ifdef Libisofs_with_aaip_acL
678 if(a_acl != NULL)
679 free(a_acl);
680 if(acl_text != NULL)
681 aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
682 #endif /* Libisofs_with_aaip_acL */
683
684 if(ret <= 0 || (flag & (1 << 15))) {
685 if(*names != NULL) {
686 for(i= 0; i < (ssize_t) *num_attrs; i++)
687 free((*names)[i]);
688 free(*names);
689 }
690 *names= NULL;
691 if(*value_lengths != NULL)
692 free(*value_lengths);
693 *value_lengths= NULL;
694 if(*values != NULL) {
695 for(i= 0; i < (ssize_t) *num_attrs; i++)
696 free((*values)[i]);
697 free(*values);
698 }
699 *values= NULL;
700 *num_attrs= 0;
701 }
702 return(ret);
703 }
704
705 #endif /* Libisofs_old_freebsd_acl_adapteR */
706
707
708 /* ------------------------------ Setters --------------------------------- */
709
710
711 /* Set the ACL of the given file to a given list in long text form.
712 @param path Path to the file
713 @param text The input text (0 terminated, ACL long text form)
714 @param flag Bitfield for control purposes
715 bit0= set default ACL rather than access ACL
716 bit5= in case of symbolic link: manipulate link target
717 bit6= tolerate inappropriate presence or absence of
718 directory default ACL
719 @return > 0 ok
720 0 no suitable ACL manipulation adapter available
721 -1 failure of system ACL service (see errno)
722 -2 attempt to manipulate ACL of a symbolic link
723 without bit5 or with no suitable link target
724 */
725 int aaip_set_acl_text(char *path, char *text, int flag)
726 {
727
728 #ifdef Libisofs_with_aaip_acL
729
730 int ret;
731 acl_t acl= NULL;
732 struct stat stbuf;
733
734 if(flag & 32)
735 ret= stat(path, &stbuf);
736 else
737 ret= lstat(path, &stbuf);
738 if(ret == -1)
739 return(-1);
740 if((stbuf.st_mode & S_IFMT) == S_IFLNK)
741 return(-2);
742
743 acl= acl_from_text(text);
744 if(acl == NULL) {
745 ret= -1; goto ex;
746 }
747
748 /* Note: no ACL_TYPE_DEFAULT in FreeBSD */
749 if(flag & 1)
750 {ret= 0; goto ex;}
751
752 ret= acl_set_file(path, ACL_TYPE_ACCESS, acl);
753
754 if(ret == -1)
755 goto ex;
756 ret= 1;
757 ex:
758 if(acl != NULL)
759 acl_free(acl);
760 return(ret);
761
762 #else /* Libisofs_with_aaip_acL */
763
764 return(0);
765
766 #endif /* ! Libisofs_with_aaip_acL */
767
768 }
769
770
771 #ifndef Libisofs_old_freebsd_acl_adapteR
772
773 #ifdef Libisofs_with_freebsd_extattR
774
775 /*
776 @param flag Bitfield for control purposes
777 bit5= in case of symbolic link: manipulate link target
778 */
779 static int aaip_extattr_delete_names(char *path, int attrnamespace,
780 char *list, ssize_t list_size, int flag)
781 {
782 int len;
783 char name[256];
784 ssize_t value_ret, i;
785
786 for(i= 0; i < list_size; i+= len + 1) {
787 len= *((unsigned char *) (list + i));
788 if(len > 0)
789 strncpy(name, list + i + 1, len);
790 name[len]= 0;
791 if(flag & 32)
792 value_ret= extattr_delete_file(path, attrnamespace, name);
793 else
794 value_ret= extattr_delete_file(path, attrnamespace, name);
795 if(value_ret == -1)
796 return(0);
797 }
798 return(1);
799 }
800
801 #endif /* Libisofs_with_freebsd_extattR */
802
803
804 static void register_errno(int *errnos, int i, int in_errno)
805 {
806 if(in_errno > 0)
807 errnos[i]= in_errno;
808 else
809 errnos[i]= -1;
810 }
811
812
813 /* Bring the given attributes and/or ACLs into effect with the given file.
814 @param flag Bitfield for control purposes
815 bit0= decode and set ACLs
816 bit1= first clear all existing attributes of the file
817 bit2= do not set attributes other than ACLs
818 bit3= do not ignore eventual non-user attributes.
819 I.e. those with a name which does not begin
820 by "user."
821 bit5= in case of symbolic link: manipulate link target
822 bit6= tolerate inappropriate presence or absence of
823 directory default ACL
824 bit7= void setting a name value pair if it already
825 exists and has the desired value.
826 @return 1 success
827 -1 error memory allocation
828 -2 error with decoding of ACL
829 -3 error with setting ACL
830 -4 error with setting attribute
831 -5 error with deleting attributes
832 -6 support of xattr not enabled at compile time
833 -7 support of ACL not enabled at compile time
834 -8 unsupported xattr namespace
835 ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
836 */
837 int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
838 size_t *value_lengths, char **values,
839 int *errnos, int flag)
840 {
841 int ret, has_default_acl= 0, end_ret= 1;
842 size_t i, consumed, acl_text_fill, acl_idx= 0;
843 char *acl_text= NULL;
844 #ifdef Libisofs_with_freebsd_extattR
845 char *user_list= NULL, *sys_list= NULL, *namept, *old_value;
846 ssize_t user_list_size= 0, sys_list_size= 0, value_ret;
847 int attrnamespace;
848 size_t old_value_l;
849 int skip;
850 #endif
851
852 for(i= 0; i < num_attrs; i++)
853 errnos[i]= 0;
854
855 #ifdef Libisofs_with_freebsd_extattR
856
857 if(flag & 2) { /* Delete all file attributes */
858 ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER,
859 &user_list, &user_list_size, flag & 32);
860 if(ret <= 0)
861 {ret= -1; goto ex;}
862 ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_USER,
863 user_list, user_list_size, flag & 32);
864 if(ret <= 0)
865 {ret= -5; goto ex;}
866 if(flag & 8) {
867 ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_SYSTEM,
868 &sys_list, &sys_list_size, flag & 32);
869 if(ret <= 0)
870 {ret= -5; goto ex;}
871 ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_SYSTEM,
872 sys_list, sys_list_size, flag & 32);
873 if(ret <= 0)
874 {ret= -5; goto ex;}
875 }
876 }
877
878 #endif /* Libisofs_with_freebsd_extattR */
879
880 for(i= 0; i < num_attrs; i++) {
881 if(names[i] == NULL || values[i] == NULL)
882 continue;
883 if(names[i][0] == 0) { /* ACLs */
884 if(flag & 1)
885 acl_idx= i + 1;
886 continue;
887 }
888 /* Extended Attribute */
889 if(flag & 4)
890 continue;
891
892 #ifdef Libisofs_with_freebsd_extattR
893
894 if(strncmp(names[i], "user.", 5) == 0) {
895 attrnamespace= EXTATTR_NAMESPACE_USER;
896 namept= names[i] + 5;
897 } else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8)) {
898 continue;
899 } else if(strncmp(names[i], "system.", 7) == 0) {
900 attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
901 namept= names[i] + 7;
902 } else {
903 register_errno(errnos, i, (int) EFAULT);
904 end_ret= -8;
905 continue;
906 }
907 skip= 0;
908 if(flag & 128) {
909 value_ret= get_single_attr(path, names[i], &old_value_l,
910 &old_value, flag & (8 | 32));
911 if(value_ret > 0 && old_value_l == value_lengths[i]) {
912 if(memcmp(old_value, values[i], value_lengths[i]) == 0)
913 skip= 1;
914 }
915 if(old_value != NULL)
916 free(old_value);
917 }
918 if(!skip) {
919 if(flag & 32)
920 ret= extattr_set_file(path, attrnamespace, namept,
921 values[i], value_lengths[i]);
922 else
923 ret= extattr_set_link(path, attrnamespace, namept,
924 values[i], value_lengths[i]);
925 if(ret == -1) {
926 register_errno(errnos, i, errno);
927 if(end_ret != 1)
928 end_ret= -4;
929 continue;
930 }
931 }
932
933 #else
934
935 if(strncmp(names[i], "user.", 5) == 0)
936 ;
937 else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8))
938 continue;
939 {ret= -6; goto ex;}
940
941 #endif /* Libisofs_with_freebsd_extattR */
942
943 }
944
945 /* Decode ACLs */
946 /* It is important that this happens after restoring xattr which might be
947 representations of ACL, too. If isofs ACL are enabled, then they shall
948 override the xattr ones.
949 */
950 if(acl_idx == 0)
951 {ret= end_ret; goto ex;}
952 i= acl_idx - 1;
953
954 ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
955 &consumed, NULL, 0, &acl_text_fill, 1);
956 if(ret < -3)
957 goto ex;
958 if(ret <= 0)
959 {ret= -2; goto ex;}
960 acl_text= calloc(acl_text_fill, 1);
961 if(acl_text == NULL)
962 {ret= -1; goto ex;}
963 ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
964 &consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
965 if(ret < -3)
966 goto ex;
967 if(ret <= 0)
968 {ret= -2; goto ex;}
969 has_default_acl= (ret == 2);
970
971 #ifdef Libisofs_with_aaip_acL
972 ret= aaip_set_acl_text(path, acl_text, flag & (32 | 64));
973 if(ret == -1)
974 register_errno(errnos, i, errno);
975 if(ret <= 0)
976 {ret= -3; goto ex;}
977 #else
978 {ret= -7; goto ex;}
979 #endif
980
981 if(has_default_acl && !(flag & 64))
982 {ret= -3; goto ex;}
983
984 ret= end_ret;
985 ex:;
986 if(acl_text != NULL)
987 free(acl_text);
988 #ifdef Libisofs_with_freebsd_extattR
989 if(user_list != NULL)
990 free(user_list);
991 if(sys_list != NULL)
992 free(sys_list);
993 #endif /* Libisofs_with_freebsd_extattR */
994 return(ret);
995 }
996
997 #else /* ! Libisofs_old_freebsd_acl_adapteR */
998
999
1000 /* Bring the given attributes and/or ACLs into effect with the given file.
1001
1002 Note: There are no Extended Attributes in FreeBSD. So only ACL get set.
1003
1004 @param flag Bitfield for control purposes
1005 bit0= decode and set ACLs
1006 ( bit1= first clear all existing attributes of the file )
1007 ( bit2= do not set attributes other than ACLs )
1008 ( bit3= do not ignore eventual non-user attributes.
1009 I.e. those with a name which does not begin
1010 by "user." )
1011 @return 1 success
1012 -1 error memory allocation
1013 -2 error with decoding of ACL
1014 -3 error with setting ACL
1015 ( -4 error with setting attribute )
1016 ( -5 error with deleting attribute )
1017 -6 support of xattr not enabled at compile time
1018 -7 support of ACL not enabled at compile time
1019 */
1020 int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
1021 size_t *value_lengths, char **values, int flag)
1022 {
1023 int ret, has_default_acl= 0, was_xattr= 0;
1024 size_t i, consumed, acl_text_fill;
1025 char *acl_text= NULL, *list= NULL;
1026
1027 for(i= 0; i < num_attrs; i++) {
1028 if(names[i] == NULL || values[i] == NULL)
1029 continue;
1030 if(names[i][0] == 0) { /* Decode ACLs */
1031 /* access ACL */
1032 if(!(flag & 1))
1033 continue;
1034 ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
1035 &consumed, NULL, 0, &acl_text_fill, 1);
1036 if(ret <= 0)
1037 {ret= -2; goto ex;}
1038 acl_text= calloc(acl_text_fill, 1);
1039 if(acl_text == NULL)
1040 {ret= -1; goto ex;}
1041 ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
1042 &consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
1043 if(ret <= 0)
1044 {ret= -2; goto ex;}
1045 has_default_acl= (ret == 2);
1046
1047 #ifdef Libisofs_with_aaip_acL
1048 ret= aaip_set_acl_text(path, acl_text, flag & 32);
1049 if(ret <= 0)
1050 {ret= -3; goto ex;}
1051 #else
1052 {ret= -7; goto ex;}
1053 #endif
1054 /* "default" ACL */
1055 if(has_default_acl) {
1056 free(acl_text);
1057 acl_text= NULL;
1058 ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
1059 value_lengths[i] - consumed, &consumed,
1060 NULL, 0, &acl_text_fill, 1);
1061 if(ret <= 0)
1062 {ret= -2; goto ex;}
1063 acl_text= calloc(acl_text_fill, 1);
1064 if(acl_text == NULL)
1065 {ret= -1; goto ex;}
1066 ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
1067 value_lengths[i] - consumed, &consumed,
1068 acl_text, acl_text_fill, &acl_text_fill, 0);
1069 if(ret <= 0)
1070 {ret= -2; goto ex;}
1071 ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32));
1072 if(ret <= 0)
1073 {ret= -3; goto ex;}
1074 }
1075 } else {
1076 if(flag & 4)
1077 continue;
1078 if(!(flag & 8))
1079 if(strncmp(names[i], "user.", 5))
1080 continue;
1081 was_xattr= 1;
1082 }
1083 }
1084 ret= 1;
1085 if(was_xattr)
1086 ret= -6;
1087 ex:;
1088 if(acl_text != NULL)
1089 free(acl_text);
1090 if(list != NULL)
1091 free(list);
1092 return(ret);
1093 }
1094
1095 #endif /* Libisofs_old_freebsd_acl_adapteR */
1096