xorriso  1.5.4.pl02
About: GNU xorriso creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions. It is suitable for incremental data backup and for production of bootable ISO 9660 images. GNU xorriso is a statical compilation of the libraries libburn, libisofs, libisoburn, and libjte.
  Fossies Dox: xorriso-1.5.4.pl02.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

aaip-os-freebsd.c
Go to the documentation of this file.
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 */
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 
int aaip_set_attr_list(char *path, size_t num_attrs, char **names, size_t *value_lengths, char **values, int *errnos, int flag)
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag)
int aaip_set_acl_text(char *path, char *text, int flag)
int aaip_get_acl_text(char *path, char **text, int flag)
static void register_errno(int *errnos, int i, int in_errno)
int aaip_local_attr_support(int flag)
int aaip_encode_acl(char *acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag)
Definition: aaip_0_2.c:292
int aaip_cleanout_st_mode(char *acl_text, mode_t *in_st_mode, int flag)
Definition: aaip_0_2.c:720
int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed, char *acl_text, size_t acl_text_size, size_t *acl_text_fill, int flag)
Definition: aaip_0_2.c:2103
#define ISO_OUT_OF_MEM
Definition: libisofs.h:8745
#define ISO_AAIP_BAD_ATTR_NAME
Definition: libisofs.h:9108