"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