"Fossies" - the Fresh Open Source Software Archive

Member "libisofs-1.5.4/libisofs/aaip-os-linux.c" (8 Jul 2020, 18784 Bytes) of package /linux/misc/libisofs-1.5.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "aaip-os-linux.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.5.2_vs_1.5.4.

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