"Fossies" - the Fresh Open Source Software Archive

Member "libisofs-1.5.4/libisofs/fs_local.c" (8 Jul 2020, 21803 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 "fs_local.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  * Copyright (c) 2007 Vreixo Formoso
    3  * Copyright (c) 2009 - 2017 Thomas Schmitt
    4  * 
    5  * This file is part of the libisofs project; you can redistribute it and/or 
    6  * modify it under the terms of the GNU General Public License version 2 
    7  * or later as published by the Free Software Foundation. 
    8  * See COPYING file for details.
    9  */
   10 
   11 /*
   12  * Filesystem/FileSource implementation to access the local filesystem.
   13  */
   14 
   15 #ifdef HAVE_CONFIG_H
   16 #include "../config.h"
   17 #endif
   18 
   19 #include "fsource.h"
   20 #include "util.h"
   21 #include "aaip_0_2.h"
   22 
   23 #include <stdlib.h>
   24 #include <sys/types.h>
   25 #include <sys/stat.h>
   26 #include <fcntl.h>
   27 #include <errno.h>
   28 #include <dirent.h>
   29 #include <unistd.h>
   30 #include <libgen.h>
   31 #include <string.h>
   32 
   33 /* O_BINARY is needed for Cygwin but undefined elsewhere */
   34 #ifndef O_BINARY
   35 #define O_BINARY 0
   36 #endif
   37 
   38 static
   39 int iso_file_source_new_lfs(IsoFileSource *parent, const char *name, 
   40                             IsoFileSource **src);
   41 
   42 /*
   43  * We can share a local filesystem object, as it has no private atts.
   44  */
   45 IsoFilesystem *lfs= NULL;
   46 
   47 /* IMPORTANT: Any change must be reflected by lfs_clone_src() */
   48 typedef struct
   49 {
   50     /** reference to the parent (if root it points to itself) */
   51     IsoFileSource *parent;
   52     char *name;
   53     unsigned int openned :2; /* 0: not opened, 1: file, 2:dir */
   54     union
   55     {
   56         int fd;
   57         DIR *dir;
   58     } info;
   59 } _LocalFsFileSource;
   60 
   61 static
   62 char* lfs_get_path(IsoFileSource *src)
   63 {
   64     _LocalFsFileSource *data;
   65     data = src->data;
   66 
   67     if (data->parent == src) {
   68         return strdup("/");
   69     } else {
   70         char *path, *new_path;
   71         int pathlen;
   72 
   73         path = lfs_get_path(data->parent);
   74         if (path == NULL)
   75             return NULL;
   76         pathlen = strlen(path);
   77         new_path = realloc(path, pathlen + strlen(data->name) + 2);
   78         if (new_path == NULL) {
   79             free(path);
   80             return NULL;
   81         }
   82         path= new_path;
   83         if (pathlen != 1) {
   84             /* pathlen can only be 1 for root */
   85             path[pathlen] = '/';
   86             path[pathlen + 1] = '\0';
   87         }
   88         return strcat(path, data->name);
   89     }
   90 }
   91 
   92 static
   93 char* lfs_get_name(IsoFileSource *src)
   94 {
   95     _LocalFsFileSource *data;
   96     data = src->data;
   97     return strdup(data->name);
   98 }
   99 
  100 static
  101 int lfs_lstat(IsoFileSource *src, struct stat *info)
  102 {
  103     char *path;
  104 
  105     if (src == NULL || info == NULL) {
  106         return ISO_NULL_POINTER;
  107     }
  108     path = lfs_get_path(src);
  109     if (path == NULL)
  110         return ISO_OUT_OF_MEM;
  111 
  112     if (lstat(path, info) != 0) {
  113         int err;
  114 
  115         /* error, choose an appropriate return code */
  116         switch (errno) {
  117         case EACCES:
  118             err = ISO_FILE_ACCESS_DENIED;
  119             break;
  120         case ENOTDIR:
  121         case ENAMETOOLONG:
  122         case ELOOP:
  123             err = ISO_FILE_BAD_PATH;
  124             break;
  125         case ENOENT:
  126             err = ISO_FILE_DOESNT_EXIST;
  127             break;
  128         case EFAULT:
  129         case ENOMEM:
  130             err = ISO_OUT_OF_MEM;
  131             break;
  132         default:
  133             err = ISO_FILE_ERROR;
  134             break;
  135         }
  136         free(path);
  137         return err;
  138     }
  139     free(path);
  140     return ISO_SUCCESS;
  141 }
  142 
  143 static
  144 int lfs_stat(IsoFileSource *src, struct stat *info)
  145 {
  146     char *path;
  147 
  148     if (src == NULL || info == NULL) {
  149         return ISO_NULL_POINTER;
  150     }
  151     path = lfs_get_path(src);
  152     if (path == NULL)
  153         return ISO_OUT_OF_MEM;
  154 
  155     if (stat(path, info) != 0) {
  156         int err;
  157 
  158         /* error, choose an appropriate return code */
  159         switch (errno) {
  160         case EACCES:
  161             err = ISO_FILE_ACCESS_DENIED;
  162             break;
  163         case ENOTDIR:
  164         case ENAMETOOLONG:
  165         case ELOOP:
  166             err = ISO_FILE_BAD_PATH;
  167             break;
  168         case ENOENT:
  169             err = ISO_FILE_DOESNT_EXIST;
  170             break;
  171         case EFAULT:
  172         case ENOMEM:
  173             err = ISO_OUT_OF_MEM;
  174             break;
  175         default:
  176             err = ISO_FILE_ERROR;
  177             break;
  178         }
  179         free(path);
  180         return err;
  181     }
  182     free(path);
  183     return ISO_SUCCESS;
  184 }
  185 
  186 static
  187 int lfs_access(IsoFileSource *src)
  188 {
  189     int ret;
  190     char *path;
  191 
  192     if (src == NULL) {
  193         return ISO_NULL_POINTER;
  194     }
  195     path = lfs_get_path(src);
  196 
  197     ret = iso_eaccess(path);
  198     free(path);
  199     return ret;
  200 }
  201 
  202 static
  203 int lfs_open(IsoFileSource *src)
  204 {
  205     int err;
  206     struct stat info;
  207     _LocalFsFileSource *data;
  208     char *path;
  209 
  210     if (src == NULL) {
  211         return ISO_NULL_POINTER;
  212     }
  213 
  214     data = src->data;
  215     if (data->openned) {
  216         return ISO_FILE_ALREADY_OPENED;
  217     }
  218 
  219     /* is a file or a dir ? */
  220     err = lfs_stat(src, &info);
  221     if (err < 0) {
  222         return err;
  223     }
  224 
  225     path = lfs_get_path(src);
  226     if (S_ISDIR(info.st_mode)) {
  227         data->info.dir = opendir(path);
  228         data->openned = data->info.dir ? 2 : 0;
  229     } else {
  230         data->info.fd = open(path, O_RDONLY | O_BINARY);
  231         data->openned = data->info.fd != -1 ? 1 : 0;
  232     }
  233     free(path);
  234 
  235     /*
  236      * check for possible errors, note that many of possible ones are
  237      * parsed in the lstat call above 
  238      */
  239     if (data->openned == 0) {
  240         switch (errno) {
  241         case EACCES:
  242             err = ISO_FILE_ACCESS_DENIED;
  243             break;
  244         case EFAULT:
  245         case ENOMEM:
  246             err = ISO_OUT_OF_MEM;
  247             break;
  248         default:
  249             err = ISO_FILE_ERROR;
  250             break;
  251         }
  252         return err;
  253     }
  254 
  255     return ISO_SUCCESS;
  256 }
  257 
  258 static
  259 int lfs_close(IsoFileSource *src)
  260 {
  261     int ret;
  262     _LocalFsFileSource *data;
  263 
  264     if (src == NULL) {
  265         return ISO_NULL_POINTER;
  266     }
  267 
  268     data = src->data;
  269     switch (data->openned) {
  270     case 1: /* not dir */
  271         ret = close(data->info.fd) == 0 ? ISO_SUCCESS : ISO_FILE_ERROR;
  272         break;
  273     case 2: /* directory */
  274         ret = closedir(data->info.dir) == 0 ? ISO_SUCCESS : ISO_FILE_ERROR;
  275         break;
  276     default:
  277         ret = ISO_FILE_NOT_OPENED;
  278         break;
  279     }
  280     if (ret == ISO_SUCCESS) {
  281         data->openned = 0;
  282     }
  283     return ret;
  284 }
  285 
  286 static
  287 int lfs_read(IsoFileSource *src, void *buf, size_t count)
  288 {
  289     _LocalFsFileSource *data;
  290     size_t to_read, done = 0;
  291     int ret;
  292     uint8_t *buf8;
  293 
  294     if (src == NULL || buf == NULL) {
  295         return ISO_NULL_POINTER;
  296     }
  297     if (count == 0) {
  298         return ISO_WRONG_ARG_VALUE;
  299     }
  300 
  301     data = src->data;
  302     switch (data->openned) {
  303     case 1: /* not dir */
  304         buf8 = (uint8_t *) buf; /* for pointer arithmetic */
  305         for (to_read = count; to_read > 0; to_read = count - done) {
  306             if (to_read > 1024 * 1024)
  307                 to_read = 1024 * 1024;
  308             ret = read(data->info.fd, buf8 + done, to_read);
  309             if (ret < 0) {
  310                 /* error on read */
  311                 switch (errno) {
  312                 case EINTR:
  313                     return ISO_INTERRUPTED;
  314                 case EFAULT:
  315                     return ISO_OUT_OF_MEM;
  316                 case EIO:
  317                     return ISO_FILE_READ_ERROR;
  318                 }
  319                 return ISO_FILE_ERROR;
  320             }
  321             if (ret == 0) /* EOF */
  322         break;
  323             done += ret;
  324         }
  325         return done;
  326     case 2: /* directory */
  327         return ISO_FILE_IS_DIR;
  328     default:
  329         return ISO_FILE_NOT_OPENED;
  330     }
  331 }
  332 
  333 static
  334 off_t lfs_lseek(IsoFileSource *src, off_t offset, int flag)
  335 {
  336     _LocalFsFileSource *data;
  337     int whence;
  338 
  339     if (src == NULL) {
  340         return (off_t)ISO_NULL_POINTER;
  341     }
  342     switch (flag) {
  343     case 0: 
  344         whence = SEEK_SET; break;
  345     case 1: 
  346         whence = SEEK_CUR; break;
  347     case 2: 
  348         whence = SEEK_END; break;
  349     default: 
  350         return (off_t)ISO_WRONG_ARG_VALUE;
  351     }
  352 
  353     data = src->data;
  354     switch (data->openned) {
  355     case 1: /* not dir */
  356         {
  357             off_t ret;
  358             ret = lseek(data->info.fd, offset, whence);
  359             if (ret < 0) {
  360                 /* error on read */
  361                 switch (errno) {
  362                 case ESPIPE:
  363                     ret = (off_t)ISO_FILE_ERROR;
  364                     break;
  365                 default:
  366                     ret = (off_t)ISO_ERROR;
  367                     break;
  368                 }
  369             }
  370             return ret;
  371         }
  372     case 2: /* directory */
  373         return (off_t)ISO_FILE_IS_DIR;
  374     default:
  375         return (off_t)ISO_FILE_NOT_OPENED;
  376     }
  377 }
  378 
  379 static
  380 int lfs_readdir(IsoFileSource *src, IsoFileSource **child)
  381 {
  382     _LocalFsFileSource *data;
  383 
  384     if (src == NULL || child == NULL) {
  385         return ISO_NULL_POINTER;
  386     }
  387 
  388     data = src->data;
  389     switch (data->openned) {
  390     case 1: /* not dir */
  391         return ISO_FILE_IS_NOT_DIR;
  392     case 2: /* directory */
  393         {
  394             struct dirent *entry;
  395             int ret;
  396 
  397             /* while to skip "." and ".." dirs */
  398             while (1) {
  399                 entry = readdir(data->info.dir);
  400                 if (entry == NULL) {
  401                     if (errno == EBADF)
  402                         return ISO_FILE_ERROR;
  403                     else
  404                         return 0; /* EOF */
  405                 }
  406                 if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
  407                     break;
  408                 }
  409             }
  410 
  411             /* create the new FileSrc */
  412             ret = iso_file_source_new_lfs(src, entry->d_name, child);
  413             return ret;
  414         }
  415     default:
  416         return ISO_FILE_NOT_OPENED;
  417     }
  418 }
  419 
  420 static
  421 int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
  422 {
  423     int size, ret;
  424     char *path;
  425 
  426     if (src == NULL || buf == NULL) {
  427         return ISO_NULL_POINTER;
  428     }
  429 
  430     if (bufsiz <= 0) {
  431         return ISO_WRONG_ARG_VALUE;
  432     }
  433 
  434     path = lfs_get_path(src);
  435 
  436     /*
  437      * invoke readlink, with bufsiz -1 to reserve an space for
  438      * the NULL character
  439      */
  440     size = readlink(path, buf, bufsiz);
  441     free(path);
  442     if (size < 0) {
  443         /* error */
  444         switch (errno) {
  445         case EACCES:
  446             return ISO_FILE_ACCESS_DENIED;
  447         case ENOTDIR:
  448         case ENAMETOOLONG:
  449         case ELOOP:
  450             return ISO_FILE_BAD_PATH;
  451         case ENOENT:
  452             return ISO_FILE_DOESNT_EXIST;
  453         case EINVAL:
  454             return ISO_FILE_IS_NOT_SYMLINK;
  455         case EFAULT:
  456         case ENOMEM:
  457             return ISO_OUT_OF_MEM;
  458         default:
  459             return ISO_FILE_ERROR;
  460         }
  461     }
  462 
  463     /* NULL-terminate the buf */
  464     ret = ISO_SUCCESS;
  465     if ((size_t) size >= bufsiz) {
  466         ret = ISO_RR_PATH_TOO_LONG;
  467         size = bufsiz - 1;
  468     }
  469     buf[size] = '\0';
  470     return ret;
  471 }
  472 
  473 static
  474 IsoFilesystem* lfs_get_filesystem(IsoFileSource *src)
  475 {
  476     return src == NULL ? NULL : lfs;
  477 }
  478 
  479 static
  480 void lfs_free(IsoFileSource *src)
  481 {
  482     _LocalFsFileSource *data;
  483 
  484     data = src->data;
  485 
  486     /* close the file if it is already opened */
  487     if (data->openned) {
  488         src->class->close(src);
  489     }
  490     if (data->parent != src) {
  491         iso_file_source_unref(data->parent);
  492     }
  493     free(data->name);
  494     free(data);
  495     iso_filesystem_unref(lfs);
  496 }
  497 
  498 
  499 static 
  500 int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
  501 {
  502     int ret, no_non_user_perm= 0;
  503     size_t num_attrs = 0, *value_lengths = NULL, result_len;
  504     ssize_t sret;
  505     char *path = NULL, **names = NULL, **values = NULL;
  506     unsigned char *result = NULL;
  507 
  508     *aa_string = NULL;
  509 
  510     if ((flag & 6 ) == 6) { /* Neither ACL nor xattr shall be read */
  511         ret = 1;
  512         goto ex;
  513     }
  514     /* Obtain EAs and ACLs ("access" and "default"). ACLs encoded according
  515        to AAIP ACL representation. Clean out st_mode ACL entries.
  516     */ 
  517     path = iso_file_source_get_path(src);
  518     if (path == NULL) {
  519         ret = ISO_NULL_POINTER;
  520         goto ex;
  521     }
  522     ret = aaip_get_attr_list(path, &num_attrs, &names,
  523                              &value_lengths, &values,
  524                              (!(flag & 2)) | 2 | (flag & 4) | (flag & 8) | 16);
  525     if (ret <= 0) {
  526         if (ret == -2)
  527             ret = ISO_AAIP_NO_GET_LOCAL;
  528         else
  529             ret = ISO_FILE_ERROR;
  530         goto ex;
  531     }
  532     if(ret == 2)
  533         no_non_user_perm= 1;
  534       
  535     if (num_attrs == 0)
  536         result = NULL;
  537     else {
  538         sret = aaip_encode(num_attrs, names,
  539                            value_lengths, values, &result_len, &result, 0);
  540         if (sret < 0) {
  541             ret = sret;
  542             goto ex;
  543         }
  544     }
  545     *aa_string = result;
  546     ret = 1 + no_non_user_perm;
  547 ex:;
  548     if (path != NULL)
  549         free(path);
  550     if (names != NULL || value_lengths != NULL || values != NULL)
  551         aaip_get_attr_list(NULL, &num_attrs, &names, &value_lengths, &values,
  552                            1 << 15); /* free memory */
  553     return ret;
  554 }
  555 
  556 static
  557 int lfs_clone_src(IsoFileSource *old_source,
  558                   IsoFileSource **new_source, int flag)
  559 {
  560     IsoFileSource *src = NULL;
  561     char *new_name = NULL;
  562     _LocalFsFileSource *old_data, *new_data = NULL;
  563 
  564     if (flag)
  565         return ISO_STREAM_NO_CLONE; /* unknown option required */
  566 
  567     old_data = (_LocalFsFileSource *) old_source->data;
  568     *new_source = NULL;  
  569     src = calloc(1, sizeof(IsoFileSource));
  570     if (src == NULL)
  571         goto no_mem;
  572     new_name = strdup(old_data->name);
  573     if (new_name == NULL) 
  574         goto no_mem;
  575 
  576     new_data = calloc(1, sizeof(_LocalFsFileSource));
  577     if (new_data == NULL)
  578         goto no_mem;
  579     new_data->openned = 0;
  580     new_data->info.fd = -1; /* the value does not matter with (openned == 0) */
  581     new_data->name = new_name;
  582     new_data->parent = old_data->parent;
  583 
  584     src->class = old_source->class;
  585     src->refcount = 1;
  586     src->data = new_data;
  587     *new_source = src;
  588 
  589     iso_file_source_ref(new_data->parent);
  590     iso_filesystem_ref(lfs);
  591     return ISO_SUCCESS;
  592 no_mem:;
  593     if (src != NULL)
  594         free((char *) src);
  595     if (new_data != NULL)
  596         free((char *) new_data);
  597     if (new_name != NULL)
  598         free(new_name);
  599     return ISO_OUT_OF_MEM;
  600 }
  601 
  602 
  603 IsoFileSourceIface lfs_class = { 
  604 
  605     2, /* version */
  606     lfs_get_path,
  607     lfs_get_name,
  608     lfs_lstat,
  609     lfs_stat,
  610     lfs_access,
  611     lfs_open,
  612     lfs_close,
  613     lfs_read,
  614     lfs_readdir,
  615     lfs_readlink,
  616     lfs_get_filesystem,
  617     lfs_free,
  618     lfs_lseek,
  619     lfs_get_aa_string,
  620     lfs_clone_src
  621 
  622 };
  623 
  624 
  625 /**
  626  * 
  627  * @return
  628  *     1 success, < 0 error
  629  */
  630 static
  631 int iso_file_source_new_lfs(IsoFileSource *parent, const char *name, 
  632                             IsoFileSource **src)
  633 {
  634     IsoFileSource *lfs_src;
  635     _LocalFsFileSource *data;
  636 
  637     if (src == NULL) {
  638         return ISO_NULL_POINTER;
  639     }
  640 
  641     if (lfs == NULL) {
  642         /* this should never happen */
  643         return ISO_ASSERT_FAILURE;
  644     }
  645 
  646     /* allocate memory */
  647     data = malloc(sizeof(_LocalFsFileSource));
  648     if (data == NULL) {
  649         return ISO_OUT_OF_MEM;
  650     }
  651     lfs_src = malloc(sizeof(IsoFileSource));
  652     if (lfs_src == NULL) {
  653         free(data);
  654         return ISO_OUT_OF_MEM;
  655     }
  656 
  657     /* fill struct */
  658     data->name = name ? strdup(name) : NULL;
  659     data->openned = 0;
  660     if (parent) {
  661         data->parent = parent;
  662         iso_file_source_ref(parent);
  663     } else {
  664         data->parent = lfs_src;
  665     }
  666 
  667     lfs_src->refcount = 1;
  668     lfs_src->data = data;
  669     lfs_src->class = &lfs_class;
  670 
  671     /* take a ref to local filesystem */
  672     iso_filesystem_ref(lfs);
  673 
  674     /* return */
  675     *src = lfs_src;
  676     return ISO_SUCCESS;
  677 }
  678 
  679 static
  680 int lfs_get_root(IsoFilesystem *fs, IsoFileSource **root)
  681 {
  682     if (fs == NULL || root == NULL) {
  683         return ISO_NULL_POINTER;
  684     }
  685     return iso_file_source_new_lfs(NULL, NULL, root);
  686 }
  687 
  688 static
  689 int lfs_get_by_path(IsoFilesystem *fs, const char *path, IsoFileSource **file)
  690 {
  691     int ret;
  692     IsoFileSource *src;
  693     struct stat info;
  694     char *ptr, *brk_info, *component;
  695     
  696     if (fs == NULL || path == NULL || file == NULL) {
  697         return ISO_NULL_POINTER;
  698     }
  699     
  700     /* 
  701      * first of all check that it is a valid path.
  702      */
  703     if (lstat(path, &info) != 0) {
  704         int err;
  705 
  706         /* error, choose an appropriate return code */
  707         switch (errno) {
  708         case EACCES:
  709             err = ISO_FILE_ACCESS_DENIED;
  710             break;
  711         case ENOTDIR:
  712         case ENAMETOOLONG:
  713         case ELOOP:
  714             err = ISO_FILE_BAD_PATH;
  715             break;
  716         case ENOENT:
  717             err = ISO_FILE_DOESNT_EXIST;
  718             break;
  719         case EFAULT:
  720         case ENOMEM:
  721             err = ISO_OUT_OF_MEM;
  722             break;
  723         default:
  724             err = ISO_FILE_ERROR;
  725             break;
  726         }
  727         return err;
  728     }
  729     
  730     /* ok, path is valid. create the file source */
  731     ret = lfs_get_root(fs, &src);
  732     if (ret < 0) {
  733         return ret;
  734     }
  735     if (!strcmp(path, "/")) {
  736         /* we are looking for root */
  737         *file = src;
  738         return ISO_SUCCESS;
  739     }
  740 
  741     ptr = strdup(path);
  742     if (ptr == NULL) {
  743         iso_file_source_unref(src);
  744         return ISO_OUT_OF_MEM;
  745     }
  746     
  747     component = strtok_r(ptr, "/", &brk_info);
  748     while (component) {
  749         IsoFileSource *child = NULL;
  750         if (!strcmp(component, ".")) {
  751             child = src;
  752         } else if (!strcmp(component, "..")) {
  753             child = ((_LocalFsFileSource*)src->data)->parent;
  754             iso_file_source_ref(child);
  755             iso_file_source_unref(src);
  756         } else {
  757             ret = iso_file_source_new_lfs(src, component, &child);
  758             iso_file_source_unref(src);
  759             if (ret < 0) {
  760                 break;
  761             }
  762         }
  763         
  764         src = child;
  765         component = strtok_r(NULL, "/", &brk_info);
  766     }
  767 
  768     free(ptr);
  769     if (ret > 0) {
  770         *file = src;
  771     }
  772     return ret;
  773 }
  774 
  775 static
  776 unsigned int lfs_get_id(IsoFilesystem *fs)
  777 {
  778     return ISO_LOCAL_FS_ID;
  779 }
  780 
  781 static
  782 int lfs_fs_open(IsoFilesystem *fs)
  783 {
  784     /* open() operation is not needed */
  785     return ISO_SUCCESS;
  786 }
  787 
  788 static
  789 int lfs_fs_close(IsoFilesystem *fs)
  790 {
  791     /* close() operation is not needed */
  792     return ISO_SUCCESS;
  793 }
  794 
  795 static
  796 void lfs_fs_free(IsoFilesystem *fs)
  797 {
  798     lfs = NULL;
  799 }
  800 
  801 int iso_local_filesystem_new(IsoFilesystem **fs)
  802 {
  803     if (fs == NULL) {
  804         return ISO_NULL_POINTER;
  805     }
  806 
  807     if (lfs != NULL) {
  808         /* just take a new ref */
  809         iso_filesystem_ref(lfs);
  810     } else {
  811 
  812         lfs = malloc(sizeof(IsoFilesystem));
  813         if (lfs == NULL) {
  814             return ISO_OUT_OF_MEM;
  815         }
  816 
  817         /* fill struct */
  818         memcpy(lfs->type, "file", 4);
  819         lfs->refcount = 1;
  820         lfs->version = 0;
  821         lfs->data = NULL; /* we don't need private data */
  822         lfs->get_root = lfs_get_root;
  823         lfs->get_by_path = lfs_get_by_path;
  824         lfs->get_id = lfs_get_id;
  825         lfs->open = lfs_fs_open;
  826         lfs->close = lfs_fs_close;
  827         lfs->free = lfs_fs_free;
  828     }
  829     *fs = lfs;
  830     return ISO_SUCCESS;
  831 }
  832 
  833 
  834 int iso_local_attr_support(int flag)
  835 {
  836     int ret;
  837 
  838     ret= aaip_local_attr_support(flag & 255);
  839     return ret;
  840 }
  841 
  842 
  843 int iso_local_get_acl_text(char *disk_path, char **text, int flag)
  844 {
  845     int ret;
  846 
  847     ret = aaip_get_acl_text(disk_path, text, flag & (1 | 16 | 32 | (1 << 15)));
  848     return ret;
  849 }
  850 
  851 
  852 int iso_local_set_acl_text(char *disk_path, char *text, int flag)
  853 {
  854     int ret;
  855 
  856     ret = aaip_set_acl_text(disk_path, text, flag & (1 | 32));
  857     if (ret < 0)
  858         return ISO_AAIP_NO_SET_LOCAL;
  859     return ret;
  860 }
  861 
  862 
  863 int iso_local_get_attrs(char *disk_path, size_t *num_attrs, char ***names,
  864                         size_t **value_lengths, char ***values, int flag)
  865 {
  866     int ret;
  867 
  868     ret = aaip_get_attr_list(disk_path,
  869                              num_attrs, names, value_lengths, values,
  870                              (flag & (1 | 4 | 8 | 32 | (1 << 15))) | 2 | 16);
  871     if (ret <= 0)
  872         return ISO_AAIP_NO_GET_LOCAL;
  873     return 1 + (ret == 2);
  874 }
  875 
  876 
  877 int iso_local_set_attrs_errno(char *disk_path, size_t num_attrs, char **names,
  878                               size_t *value_lengths, char **values,
  879                               int *errnos, int flag)
  880 {
  881     int ret;
  882 
  883     ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths,
  884                              values, errnos,
  885                              (flag & (8 | 32 | 64 | 128)) | !(flag & 1));
  886     if (ret <= 0) {
  887         if (ret == -1)
  888             return ISO_OUT_OF_MEM;
  889         if (ret == -2)
  890             return ISO_AAIP_BAD_AASTRING;
  891         if (ret >= -5)
  892             return ISO_AAIP_NO_SET_LOCAL;
  893         if (ret == -6 || ret == -7)
  894             return ISO_AAIP_NOT_ENABLED;
  895         if (ret == -8)
  896             return ISO_AAIP_BAD_ATTR_NAME;
  897         return ret;
  898     }
  899     return 1;
  900 }
  901 
  902 
  903 int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names,
  904                         size_t *value_lengths, char **values, int flag)
  905 {
  906     int ret;
  907     int *errnos = NULL;
  908 
  909     if(num_attrs > 0) {
  910       errnos= calloc(num_attrs, sizeof(int));
  911       if(errnos == NULL)
  912         return ISO_OUT_OF_MEM;
  913     }
  914     ret= iso_local_set_attrs_errno(disk_path, num_attrs, names, value_lengths,
  915                                    values, errnos, flag);
  916     if(errnos != NULL)
  917       free(errnos);
  918     return ret;
  919 }
  920 
  921 
  922 int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag)
  923 {
  924     struct stat stbuf;
  925     int ret;
  926     char *a_text = NULL;
  927 
  928     if (flag & 32)
  929         ret = stat(disk_path, &stbuf);
  930     else
  931         ret = lstat(disk_path, &stbuf);
  932     if (ret == -1)
  933         return -1;
  934     *st_mode = stbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
  935     ret = iso_local_get_acl_text(disk_path, &a_text, 16 | (flag & 32));
  936     if (a_text != NULL) {
  937         aaip_cleanout_st_mode(a_text, st_mode, 4 | 16);
  938         iso_local_get_acl_text(disk_path, &a_text, 1 << 15); /* free a_text */
  939     }
  940     return 1;
  941 }
  942