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-linux.c
Go to the documentation of this file.
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 */
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 
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 aaip_local_attr_support(int flag)
Definition: aaip-os-linux.c:63
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
int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag)
Definition: aaip_0_2.c:618