"Fossies" - the Fresh Open Source Software Archive

Member "libisoburn-1.5.4/xorriso/filters.c" (29 Oct 2020, 25077 Bytes) of package /linux/misc/libisoburn-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 "filters.c" see the Fossies "Dox" file reference documentation.

    1 
    2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
    3 
    4    Copyright 2007-2020 Thomas Schmitt, <scdbackup@gmx.net>
    5 
    6    Provided under GPL version 2 or later.
    7 
    8    This file contains functions which operate on data filter objects.
    9 */
   10 
   11 #ifdef HAVE_CONFIG_H
   12 #include "../config.h"
   13 #endif
   14 
   15 #include <ctype.h>
   16 #include <sys/types.h>
   17 #include <unistd.h>
   18 #include <stdlib.h>
   19 #include <stdio.h>
   20 #include <string.h>
   21 #include <sys/stat.h>
   22 #include <sys/time.h>
   23 #include <time.h>
   24 #include <errno.h>
   25 
   26 #include "lib_mgt.h"
   27 #include "iso_tree.h"
   28 #include "iso_img.h"
   29 
   30 /*
   31 
   32 #include "xorriso.h"
   33 #include "xorriso_private.h"
   34 #include "xorrisoburn.h"
   35 
   36 #include "iso_manip.h"
   37 #include "sort_cmp.h"
   38 
   39 */
   40 
   41 
   42 struct Xorriso_extF {
   43 
   44  int flag; /* unused yet */
   45 
   46  IsoExternalFilterCommand *cmd;
   47 
   48 };
   49 
   50 int Xorriso_extf_destroy(struct XorrisO *xorriso, struct Xorriso_extF **filter,
   51                          int flag);
   52 
   53 
   54 /* @param flag see struct Xorriso_extF.flag */
   55 int Xorriso_extf_new(struct XorrisO *xorriso, struct Xorriso_extF **filter,
   56                      char *path, int argc, char **argv, int behavior,
   57                      char *suffix, char *name, int flag)
   58 {
   59  int i;
   60  struct Xorriso_extF *o= NULL;
   61  IsoExternalFilterCommand *cmd;
   62 
   63  *filter= o= calloc(sizeof(struct Xorriso_extF), 1);
   64  if(o == NULL)
   65    goto failure;
   66  o->flag= flag;
   67  o->cmd= NULL;
   68  o->cmd= cmd= calloc(sizeof(IsoExternalFilterCommand), 1);
   69  if(cmd == NULL)
   70    goto failure;
   71  cmd->version= 0;
   72  cmd->refcount= 0;
   73  cmd->name= NULL;
   74  cmd->path= NULL;
   75  cmd->argv= NULL;
   76  cmd->argc= argc + 1;
   77  cmd->behavior= behavior;
   78  cmd->suffix= NULL;
   79  cmd->suffix= strdup(suffix);
   80  if(cmd->suffix == NULL)
   81    goto failure;
   82 
   83  cmd->path= strdup(path);
   84  if(cmd->path == NULL)
   85    goto failure;
   86  cmd->argv= calloc(sizeof(char *), argc + 2);
   87  if(cmd->argv == NULL)
   88    goto failure;
   89  for(i= 0; i < argc + 2; i++)
   90    cmd->argv[i]= NULL;
   91  cmd->argv[0]= strdup(path);
   92  if(cmd->argv[0] == NULL)
   93    goto failure;
   94  for(i= 0; i < argc; i++) {
   95    cmd->argv[i + 1]= strdup(argv[i]);
   96    if(cmd->argv[i] == NULL)
   97      goto failure;
   98  }
   99  cmd->name= strdup(name);
  100  if(cmd->name == NULL)
  101    goto failure;
  102  return(1);
  103 failure:;
  104  Xorriso_extf_destroy(xorriso, filter, 0);
  105  return(-1);
  106 }
  107 
  108 
  109 int Xorriso_extf_destroy(struct XorrisO *xorriso, struct Xorriso_extF **filter,
  110                          int flag)
  111 {
  112  int i;
  113  IsoExternalFilterCommand *cmd;
  114 
  115  if(*filter == NULL)
  116    return(0);
  117  cmd= (*filter)->cmd;
  118  if(cmd != NULL) {
  119    if(cmd->refcount > 0)
  120      return(0);
  121    if(cmd->path != NULL)
  122      free(cmd->path);
  123    if(cmd->suffix != NULL)
  124      free(cmd->suffix);
  125    if(cmd->argv != NULL) {
  126      for(i= 0; i < cmd->argc; i++)
  127        if(cmd->argv[i] != NULL)
  128          free(cmd->argv[i]);
  129      free((char *) cmd->argv);
  130    }
  131    if(cmd->name != NULL)
  132      free(cmd->name);
  133    free((char *) cmd);
  134  }
  135  free((char *) *filter);
  136  *filter= NULL;
  137  return(1);
  138 }
  139 
  140 
  141 int Xorriso_lookup_extf(struct XorrisO *xorriso, char *name,
  142                         struct Xorriso_lsT **found_lst, int flag)
  143 {
  144  struct Xorriso_extF *filter;
  145  struct Xorriso_lsT *lst;
  146 
  147  for(lst= xorriso->filters; lst != NULL; lst= Xorriso_lst_get_next(lst, 0)) {
  148    filter= (struct Xorriso_extF *) Xorriso_lst_get_text(lst, 0);
  149    if(strcmp(filter->cmd->name, name) == 0) {
  150      *found_lst= lst;
  151      return(1);
  152    }
  153  }
  154  return(0);
  155 }
  156 
  157 
  158 int Xorriso_destroy_all_extf(struct XorrisO *xorriso, int flag)
  159 {
  160  struct Xorriso_extF *filter;
  161  struct Xorriso_lsT *lst, *next_lst;
  162 
  163  for(lst= xorriso->filters; lst != NULL; lst= next_lst) {
  164    filter= (struct Xorriso_extF *) Xorriso_lst_get_text(lst, 0);
  165    Xorriso_lst_detach_text(lst, 0);
  166    next_lst= Xorriso_lst_get_next(lst, 0);
  167    Xorriso_lst_destroy(&lst, 0);
  168    Xorriso_extf_destroy(xorriso, &filter, 0);
  169  }
  170  xorriso->filters= NULL;
  171  return(1);
  172 }
  173 
  174 
  175 /*
  176  @param flag   bit0= return 2 if renaming is not possible by libisofs
  177                      (always: if demanded strip suffix is missing
  178                               or if suffix makes name length > 255)
  179                bit1= strip suffix rather than appending it
  180 */
  181 int Xorriso_rename_suffix(struct XorrisO *xorriso, IsoNode *node, char *suffix,
  182                           char *show_path, char new_name[], int flag)
  183 {
  184  int ret, lo= 0, ls= 0, strip_suffix;
  185  char *old_name= NULL, *show_name;
  186  IsoImage *volume;
  187 
  188  strip_suffix= !!(flag & 2);
  189  
  190  ret= Xorriso_get_volume(xorriso, &volume, 0);
  191  if(ret <= 0)
  192    goto ex;
  193  old_name= strdup((char *) iso_node_get_name(node));
  194  show_name= old_name;
  195  if(show_path != NULL)
  196    if(show_path[0] != 0)
  197      show_name= show_path;
  198  lo= strlen(old_name);
  199  ls= strlen(suffix);
  200  if(strip_suffix) {
  201    if(lo <= ls) {
  202      /* refuse gracefully */
  203      ret= 2; goto ex;
  204    }
  205    if(strcmp(old_name + lo - ls, suffix) != 0) {
  206      ret= 2; goto ex;
  207    }
  208    if(lo >= SfileadrL)
  209      goto cannot_remove_suffix;
  210    strcpy(new_name, old_name);
  211    new_name[lo - ls]= 0;
  212    ret = iso_image_set_node_name(volume, node, new_name, 1);
  213    if (ret < 0) {
  214      Xorriso_process_msg_queues(xorriso,0);
  215      if (!(flag & 1))
  216        Xorriso_report_iso_error(xorriso, "", ret,
  217                             "Error when renaming ISO node", 0, "FAILURE", 1);
  218 cannot_remove_suffix:;
  219      strcpy(xorriso->info_text, "-set_filter: Cannot remove suffix from ");
  220      Text_shellsafe(show_name, xorriso->info_text, 1);
  221      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
  222                          (flag & 1) ? "WARNING" : "FAILURE", 0);
  223      ret= 2 * (flag & 1); goto ex;
  224    }
  225  } else {
  226    /* check whether suffix already present */
  227    if(lo >= ls)
  228      if(strcmp(old_name + lo - ls, suffix) == 0) {
  229        /* refuse gracefully */
  230        ret= 2; goto ex;
  231      }
  232    if(lo + ls > 255) {
  233 cannot_append_suffix:;
  234      strcpy(xorriso->info_text, "-set_filter: Cannot append suffix to ");
  235      Text_shellsafe(show_name, xorriso->info_text, 1);
  236      strcat(xorriso->info_text, ". Left unfiltered.");
  237      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
  238                          (flag & 1) ? "WARNING" : "FAILURE", 0);
  239      ret= 2 * (flag & 1); goto ex;
  240    } 
  241    sprintf(new_name, "%s%s", old_name, suffix);
  242    ret = iso_image_set_node_name(volume, node, new_name, 1);
  243    if (ret < 0) {
  244      Xorriso_process_msg_queues(xorriso,0);
  245      if (!(flag & 1))
  246        Xorriso_report_iso_error(xorriso, "", ret,
  247                               "Error when renaming ISO node", 0, "FAILURE", 1);
  248      goto cannot_append_suffix;
  249    }
  250  }
  251 
  252  ret= 1;
  253 ex:;
  254  if(old_name != NULL)
  255    free(old_name);
  256  Xorriso_process_msg_queues(xorriso,0);
  257  return(ret);
  258 }
  259 
  260 
  261 /*
  262  @param flag   bit0= return 2 if renaming is not possible
  263                bit1= print pacifier messages
  264  */
  265 int Xorriso_set_filter(struct XorrisO *xorriso, void *in_node,
  266                        char *path, char *filter_name, int flag)
  267 {
  268  int ret, strip_suffix= 0, strip_filter= 0, filter_ret= 0;
  269  int explicit_suffix= 0, internal_filter= 0;
  270  IsoNode *node;
  271  IsoFile *file;
  272  struct Xorriso_lsT *found_lst;
  273  struct Xorriso_extF *found_filter;
  274  IsoExternalFilterCommand *cmd = NULL;
  275  char *old_name= NULL, *new_name= NULL, *suffix= "";
  276  IsoStream *stream;
  277  IsoImage *volume;
  278 
  279  Xorriso_alloc_meM(new_name, char, SfileadrL);
  280  new_name[0]= 0;
  281 
  282  node= (IsoNode *) in_node;
  283  if(node == NULL) {
  284    ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
  285    if(ret <= 0)
  286      goto ex;
  287  }
  288  if(!LIBISO_ISREG(node)) {
  289    strcpy(xorriso->info_text, "-set_filter: Not a regular data file node ");
  290    Text_shellsafe(path, xorriso->info_text, 1);
  291    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
  292    ret= 0; goto ex;
  293  }
  294  file= (IsoFile *) node;
  295 
  296  if(strncmp(filter_name, "--remove-all-filters", 20) == 0) {
  297    strip_filter= 1;
  298    strip_suffix= 1;
  299    if(strlen(filter_name) > 21) {
  300      strip_suffix= (filter_name[20] != '+');
  301      suffix= filter_name + 21;
  302      explicit_suffix= 1;
  303    }
  304  } else if(strcmp(filter_name, "--zisofs") == 0) {
  305    internal_filter= 1;
  306  } else if(strcmp(filter_name, "--zisofs-decode") == 0) {
  307    internal_filter= 2;
  308  } else if(strcmp(filter_name, "--gzip") == 0) {
  309    internal_filter= 3;
  310    suffix= ".gz";
  311    strip_suffix= 0;
  312    explicit_suffix= 1;
  313  } else if(strcmp(filter_name, "--gunzip") == 0 ||
  314            strcmp(filter_name, "--gzip-decode") == 0) {
  315    internal_filter= 4;
  316    suffix= ".gz";
  317    strip_suffix= 1;
  318    explicit_suffix= 1;
  319  } else {
  320    ret= Xorriso_lookup_extf(xorriso, filter_name, &found_lst, 0);
  321    if(ret < 0)
  322      goto ex;
  323    if(ret == 0) {
  324      strcpy(xorriso->info_text, "-set_filter: Not a registered filter name ");
  325      Text_shellsafe(filter_name, xorriso->info_text, 1);
  326      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  327      ret= 0; goto ex;
  328    }
  329    found_filter= (struct Xorriso_extF *) Xorriso_lst_get_text(found_lst, 0);
  330    cmd= found_filter->cmd;
  331    suffix= cmd->suffix;
  332    strip_suffix= cmd->behavior & 8;
  333  }
  334 
  335  if(suffix[0]) {
  336 
  337    /* >>> would need full iso_rr_path of node for showing */;
  338 
  339    old_name= strdup((char *) iso_node_get_name(node));
  340    ret= Xorriso_rename_suffix(xorriso, node, suffix, path, new_name,
  341                                (flag & 1) | (strip_suffix ? 2 : 0));
  342    if(ret <= 0 || ret == 2)
  343      goto ex;
  344  }
  345 
  346  if(strip_filter) {
  347    while(1) {
  348      if(!explicit_suffix) {
  349        stream= iso_file_get_stream(file);
  350 
  351        if(strncmp(stream->class->type, "gzip", 4) == 0) {
  352          suffix= ".gz";
  353          strip_suffix= 1;
  354        } else if(strncmp(stream->class->type, "pizg", 4) == 0) {
  355          suffix= ".gz";
  356          strip_suffix= 0;
  357        } else {
  358          ret= iso_stream_get_external_filter(stream, &cmd, 0);
  359          if(ret > 0) {
  360            suffix= cmd->suffix;
  361            strip_suffix= !(cmd->behavior & 8);
  362          }
  363        }
  364        if(suffix[0]) {
  365 
  366          /* >>> would need the current renaming state of path */;
  367 
  368          ret= Xorriso_rename_suffix(xorriso, node, suffix, NULL, new_name,
  369                                     (flag & 1) | (strip_suffix << 1));
  370          if(ret <= 0 || ret == 2)
  371            goto ex;
  372        }
  373      }
  374      ret= iso_file_remove_filter(file, 0);
  375      if(ret != 1)
  376    break;
  377    }
  378    filter_ret= 1;
  379  } else if (internal_filter == 1 || internal_filter == 2) {
  380    filter_ret = iso_file_add_zisofs_filter(file, 1 | (internal_filter & 2));
  381    if(filter_ret == (int) ISO_ZISOFS_TOO_MANY_PTR) {
  382      /* Remove all buffered currently unused block pointers and try again */
  383      ret= Xorriso_get_volume(xorriso, &volume, 0);
  384      if(ret < 0)
  385        goto ex;
  386      if(ret > 0) {
  387        Xorriso_msgs_submit(xorriso, 0,
  388                            "Overflow of zisofs block pointers happened.",
  389                            0, "WARNING", 0);
  390        Xorriso_msgs_submit(xorriso, 0,
  391                   "zisofs falling back to mode which needs 3 input read runs.",
  392                            0, "WARNING", 0);
  393        ret = iso_image_zisofs_discard_bpt(volume, 0);
  394        if(ret <= 0)
  395          goto ex;
  396        filter_ret = iso_file_add_zisofs_filter(file,
  397                                                1 | (internal_filter & 2));
  398      }
  399    }
  400    if(filter_ret < 0) {
  401      Xorriso_process_msg_queues(xorriso,0);
  402      if(!(internal_filter == 2 && filter_ret == (int) ISO_ZISOFS_WRONG_INPUT))
  403        Xorriso_report_iso_error(xorriso, "", filter_ret,
  404                     "Error when setting filter to ISO node", 0, "FAILURE", 1);
  405    }
  406  } else if (internal_filter == 3 || internal_filter == 4) {
  407    filter_ret = iso_file_add_gzip_filter(file,
  408                                          1 | ((internal_filter == 4) << 1));
  409    if(filter_ret < 0) {
  410      Xorriso_process_msg_queues(xorriso,0);
  411      Xorriso_report_iso_error(xorriso, "", filter_ret,
  412                     "Error when setting filter to ISO node", 0, "FAILURE", 1);
  413    }
  414  } else {
  415 
  416 #ifndef Xorriso_allow_extf_suiD
  417    /* This is a final safety precaution before iso_file_add_external_filter()
  418       performs fork() and executes the alleged filter program.
  419    */
  420    if(getuid() != geteuid()) {
  421      sprintf(xorriso->info_text,
  422           "-set_filter: UID and EUID differ. Will not run external programs.");
  423      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  424      ret= 0; goto ex;
  425    }
  426 #endif /* ! Xorriso_allow_extf_suiD */
  427 
  428    filter_ret = iso_file_add_external_filter(file, cmd, 0);
  429    if(filter_ret < 0) {
  430      Xorriso_process_msg_queues(xorriso,0);
  431      Xorriso_report_iso_error(xorriso, "", filter_ret,
  432                     "Error when setting filter to ISO node", 0, "FAILURE", 1);
  433    }
  434  }
  435  if(filter_ret != 1 && new_name[0] && old_name != NULL) {
  436    ret= Xorriso_get_volume(xorriso, &volume, 0);
  437    if(ret<=0)
  438      goto ex;
  439    ret = iso_image_set_node_name(volume, node, old_name, 1);
  440    if (ret < 0) {
  441      Xorriso_process_msg_queues(xorriso,0);
  442      if (!(flag & 1))
  443        Xorriso_report_iso_error(xorriso, "", ret,
  444                               "Error when renaming ISO node", 0, "FAILURE", 1);
  445    }
  446  }
  447  if(flag & 2) {
  448    xorriso->pacifier_count++;
  449    Xorriso_pacifier_callback(xorriso, "file filters processed",
  450                       xorriso->pacifier_count, xorriso->pacifier_total, "", 0);
  451  }
  452  if(filter_ret < 0) {
  453    ret= 0; goto ex;
  454  }
  455 
  456  ret= filter_ret;
  457 ex:;
  458  if(old_name != NULL)
  459    free(old_name);
  460  Xorriso_free_meM(new_name);
  461  Xorriso_process_msg_queues(xorriso,0);
  462  return(ret);
  463 }
  464 
  465 
  466 int Xorriso_external_filter_banned(struct XorrisO *xorriso, char *purpose,
  467                                    int flag)
  468 {
  469  int is_banned= 0;
  470 
  471 #ifndef Xorriso_allow_external_filterS
  472  /* To be controlled by: configure --enable-external-filters */
  473 
  474  sprintf(xorriso->info_text, "%s : Banned at compile time.", purpose);
  475  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  476  sprintf(xorriso->info_text,
  477 "This may be changed at compile time by ./configure option --enable-external-filters");
  478  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
  479  is_banned= 1;
  480  
  481 #endif /* ! Xorriso_allow_external_filterS */
  482 
  483 #ifndef Xorriso_allow_extf_suiD
  484  /* To be controlled by: configure --enable-external-filters-setuid */
  485 
  486  if(getuid() != geteuid()) {
  487    sprintf(xorriso->info_text,
  488           "-set_filter: UID and EUID differ. Will not run external programs.");
  489    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  490    sprintf(xorriso->info_text,
  491 "This may be changed at compile time by ./configure option --enable-external-filters-setuid");
  492    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
  493    is_banned= 1;
  494  }
  495 #endif /* ! Xorriso_allow_extf_suiD */
  496 
  497  if(xorriso->filter_list_closed) {
  498    sprintf(xorriso->info_text,
  499            "%s : Banned by previous command -close_filter_list", purpose);
  500    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  501    is_banned= 1;
  502  } 
  503  return(is_banned);
  504 }
  505 
  506 
  507 /* @param flag bit0= delete filter with the given name
  508 */
  509 int Xorriso_external_filter(struct XorrisO *xorriso,
  510                             char *name, char *options, char *path, 
  511                             int argc, char **argv, int flag)
  512 {
  513  int ret, delete= 0, behavior= 0, extf_flag= 0, is_banned= 0;
  514  char *what, *what_next, *suffix= "";
  515  struct Xorriso_lsT *lst;
  516  struct Xorriso_extF *found_filter, *new_filter= NULL;
  517 
  518  is_banned= Xorriso_external_filter_banned( xorriso,
  519                       flag & 1 ? "-unregister_filter" : "-external_filter", 0);
  520  if(is_banned)
  521    return(0);
  522  if((!(flag & 1)) && path[0] != '/') {
  523    sprintf(xorriso->info_text,
  524            "-external_filter : Given command path does not begin by '/' : ");
  525    Text_shellsafe(path, xorriso->info_text, 1);
  526    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  527    return(0);
  528  }
  529 
  530 
  531  delete= flag & 1;
  532  ret= Xorriso_lookup_extf(xorriso, name, &lst, 0);
  533  if(ret < 0)
  534    return(ret);
  535  if(ret > 0) {
  536    if(delete) {
  537      found_filter= (struct Xorriso_extF *) Xorriso_lst_get_text(lst, 0);
  538      if(found_filter->cmd->refcount > 0) {
  539        sprintf(xorriso->info_text,
  540  "-external_filter: Cannot remove filter because it is in use by %.f nodes : ",
  541               (double) found_filter->cmd->refcount);
  542        Text_shellsafe(name, xorriso->info_text, 1);
  543        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  544        ret= 0; goto ex;
  545      }
  546      Xorriso_lst_detach_text(lst, 0);
  547      if(xorriso->filters == lst)
  548        xorriso->filters= Xorriso_lst_get_next(lst, 0);
  549      Xorriso_lst_destroy(&lst, 0);
  550      Xorriso_extf_destroy(xorriso, &found_filter, 0);
  551      ret= 1; goto ex;
  552    }
  553    strcpy(xorriso->info_text,
  554           "-external_filter: filter with given name already existing: ");
  555    Text_shellsafe(name, xorriso->info_text, 1);
  556    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  557    ret= 0; goto ex;
  558  }
  559  if(delete) {
  560    strcpy(xorriso->info_text,
  561           "-external_filter: filter with given name does not exist: ");
  562    Text_shellsafe(name, xorriso->info_text, 1);
  563    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  564    ret= 0; goto ex;
  565  }
  566 
  567  for(what= options; what!=NULL; what= what_next) {
  568    what_next= strchr(what, ':');
  569    if(what_next!=NULL) {
  570      *what_next= 0;
  571      what_next++;
  572    }
  573    if(strncmp(what, "default", 7) == 0) {
  574      suffix= "";
  575      behavior= 0;
  576    } else if(strncmp(what, "suffix=", 7) == 0) {
  577      suffix= what + 7;
  578    } else if(strcmp(what, "remove_suffix") == 0) {
  579      behavior|= 8;
  580    } else if(strcmp(what, "if_nonempty") == 0) {
  581      behavior|= 1;
  582    } else if(strcmp(what, "if_reduction") == 0) {
  583      behavior|= 2;
  584    } else if(strcmp(what, "if_block_reduction") == 0) {
  585      behavior|= 4;
  586    } else if(strncmp(what, "used=", 5) == 0) {
  587      ; /* this is informational output from -status */
  588    } else if(what[0]) {
  589      strcpy(xorriso->info_text,
  590             "-external_filter: unknown option ");
  591      Text_shellsafe(what, xorriso->info_text, 1);
  592      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  593      ret= 0; goto ex;
  594    }
  595  }
  596 
  597  ret= Xorriso_extf_new(xorriso, &new_filter, path, argc, argv, behavior,
  598                        suffix, name, extf_flag);
  599  if(ret <= 0) {
  600 could_not_create:;
  601    strcpy(xorriso->info_text,
  602           "-external_filter: Could not create filter object");
  603    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  604    goto ex;
  605  }
  606  ret= Xorriso_lst_append_binary(&(xorriso->filters), (char *) new_filter,0, 4);
  607  if(ret <= 0)
  608    goto could_not_create;
  609  ret= 1;
  610 ex:;
  611  if(ret <= 0) {
  612    if(new_filter != NULL)
  613      Xorriso_extf_destroy(xorriso, &new_filter, 0);
  614  }
  615  return(ret);
  616 }
  617 
  618 
  619 int Xorriso_status_extf(struct XorrisO *xorriso, char *filter, FILE *fp,
  620                         int flag)
  621 /*
  622  bit1= do only report to fp
  623 */ 
  624 {
  625  int i, maxl= 4 * SfileadrL;
  626  struct Xorriso_extF *extf;
  627  struct Xorriso_lsT *lst;
  628  char *line;
  629 
  630  line= xorriso->result_line;
  631  for(lst= xorriso->filters; lst != NULL; lst= Xorriso_lst_get_next(lst, 0)) {
  632    extf= (struct Xorriso_extF *) Xorriso_lst_get_text(lst, 0);
  633    
  634    strcpy(xorriso->result_line, "-external_filter ");
  635    Text_shellsafe(extf->cmd->name, line, 1);
  636    if((int) strlen(line) > maxl)
  637  continue;
  638    strcat(line, " ");
  639    if(extf->cmd->suffix[0]) {
  640      strcat(line, "suffix=");
  641      Text_shellsafe(extf->cmd->suffix, line, 1);
  642      if((int) strlen(line) > maxl)
  643  continue;
  644      strcat(line, ":");
  645    }
  646    if(extf->cmd->behavior & 8)
  647      strcat(line, "remove_suffix:");
  648    if(extf->cmd->behavior & 1)
  649      strcat(line, "if_nonempty:");
  650    if(extf->cmd->behavior & 2)
  651      strcat(line, "if_reduction:");
  652    if(extf->cmd->behavior & 4)
  653      strcat(line, "if_block_reduction:");
  654    sprintf(line + strlen(line), "used=%.f ", (double) extf->cmd->refcount);
  655    if((int) strlen(line) > maxl)
  656  continue;
  657    Text_shellsafe(extf->cmd->path, line, 1);
  658    if((int) strlen(line) > maxl)
  659  continue;
  660    for(i= 1; i < extf->cmd->argc; i++) {
  661      strcat(line, " ");
  662      Text_shellsafe(extf->cmd->argv[i], line, 1);
  663      if((int) strlen(line) > maxl)
  664    break;
  665    }
  666    if(i < extf->cmd->argc)
  667  continue;
  668    strcat(line, " --\n");
  669    Xorriso_status_result(xorriso, filter, fp, flag&2);
  670  }
  671  if(xorriso->filter_list_closed) {
  672    strcpy(line, "-close_filter_list\n");
  673    Xorriso_status_result(xorriso, filter, fp, flag&2);
  674  }
  675  return(1);
  676 }
  677 
  678 /* @param flag bit0= iso_zisofs_set_params
  679                bit1= iso_zisofs_ctrl_susp_z2
  680 */
  681 int Xorriso_set_zisofs_params(struct XorrisO *xorriso, int flag)
  682 {
  683  int ret, i;
  684  struct iso_zisofs_ctrl ctrl;
  685 
  686  if(flag & 2) {
  687    iso_zisofs_ctrl_susp_z2(!!xorriso->zisofs_susp_z2);
  688  }
  689  if(!(flag & 1))
  690    return(1);
  691 
  692  memset(&ctrl, 0, sizeof(ctrl));
  693  ctrl.version= 1;
  694  ret= iso_zisofs_get_params(&ctrl, 0);
  695  if(ret < 0) {
  696    Xorriso_report_iso_error(xorriso, "", ret,
  697                   "Error when inquiring zisofs parameters before setting some",
  698                   0, "FAILURE", 1);
  699    return(0);
  700  }
  701 
  702  ctrl.compression_level= xorriso->zlib_level;
  703  if(xorriso->zisofs_block_size == (1 << 16))
  704    ctrl.block_size_log2= 16;
  705  else if(xorriso->zisofs_block_size == (1 << 17))
  706    ctrl.block_size_log2= 17;
  707  else
  708    ctrl.block_size_log2= 15;
  709 
  710  ctrl.v2_enabled= xorriso->zisofs_v2_enabled;
  711  ctrl.max_total_blocks= xorriso->zisofs_max_total_blocks;
  712  ctrl.max_file_blocks= xorriso->zisofs_max_file_blocks;
  713  ctrl.v2_block_size_log2= 17;
  714  for(i= 15; i <= 20; i++)
  715    if(xorriso->zisofs_v2_block_size == (1 << i))
  716      ctrl.v2_block_size_log2= i;
  717  ctrl.block_number_target= xorriso->zisofs_block_number_target;
  718  ctrl.bpt_discard_free_ratio= xorriso->zisofs_bpt_discard_free_ratio;
  719 
  720  ret= iso_zisofs_set_params(&ctrl, 0);
  721  Xorriso_process_msg_queues(xorriso,0);
  722  if(ret < 0) {
  723    Xorriso_report_iso_error(xorriso, "", ret,
  724                       "Error when setting zisofs parameters", 0, "FAILURE", 1);
  725    return(0);
  726  }
  727  return(1);
  728 }
  729 
  730 
  731 uint64_t Xorriso_zisofs_current_blocks(struct XorrisO *xorriso, int flag)
  732 {
  733  int ret;
  734  struct iso_zisofs_ctrl ctrl;
  735 
  736  memset(&ctrl, 0, sizeof(ctrl));
  737  ctrl.version= 1;
  738  ret = iso_zisofs_get_params(&ctrl, 0);
  739  if(ret != 1)
  740    return(0);
  741  return(ctrl.current_total_blocks);
  742 }
  743 
  744 
  745 int Xorriso_status_zisofs(struct XorrisO *xorriso, char *filter, FILE *fp,
  746                           int flag)
  747 /*
  748  bit0= only report non-default settings
  749  bit1= only report to fp
  750 */ 
  751 {
  752  off_t ziso_count= 0, osiz_count= 0;
  753  off_t gzip_count= 0, gunzip_count= 0;
  754  uint64_t used_blocks;
  755  int always= 0;
  756 
  757  iso_zisofs_get_refcounts(&ziso_count, &osiz_count, 0);
  758  iso_gzip_get_refcounts(&gzip_count, &gunzip_count, 0);
  759  if(!(flag & 1)) {
  760    always= 1;
  761  } else if(filter != NULL) {
  762    if(filter[0] != 0)
  763      always= 1;
  764  }
  765 
  766  if(always || !(
  767       xorriso->zlib_level == xorriso->zlib_level_default &&
  768       xorriso->zisofs_block_size == xorriso->zisofs_block_size_default &&
  769       xorriso->zisofs_by_magic == 0)) {
  770    sprintf(xorriso->result_line,
  771            "-zisofs level=%d:block_size=%dk:by_magic=%s\n",
  772            xorriso->zlib_level, xorriso->zisofs_block_size / 1024,
  773            xorriso->zisofs_by_magic == 1 ? "on" :
  774            xorriso->zisofs_by_magic == 2 ? "v2" : "off");
  775    Xorriso_status_result(xorriso, filter, fp, flag & 2);
  776  }
  777  if(always || !(
  778       xorriso->zisofs_v2_enabled == 0 &&
  779       xorriso->zisofs_v2_block_size == xorriso->zisofs_v2_block_size_default
  780       && xorriso->zisofs_block_number_target == -1)){
  781    sprintf(xorriso->result_line,
  782           "-zisofs version_2=%s:block_size_v2=%dk:susp_z2=%s:bpt_target=%.f\n",
  783            xorriso->zisofs_v2_enabled ? xorriso->zisofs_v2_enabled == 1 ?
  784                                               "as_needed" : "on" : "off",
  785            xorriso->zisofs_v2_block_size / 1024,
  786            xorriso->zisofs_susp_z2 ? "on" : "off",
  787            (double) xorriso->zisofs_block_number_target);
  788    Xorriso_status_result(xorriso, filter, fp, flag & 2);
  789  }
  790  used_blocks= Xorriso_zisofs_current_blocks(xorriso, 0);
  791  if(always || !(
  792    xorriso->zisofs_max_total_blocks ==
  793                                    xorriso->zisofs_max_total_blocks_default &&
  794    xorriso->zisofs_max_file_blocks ==
  795                                    xorriso->zisofs_max_file_blocks_default &&
  796    xorriso->zisofs_bpt_discard_free_ratio ==
  797                              xorriso->zisofs_bpt_discard_free_ratio_default)) {
  798    sprintf(xorriso->result_line,
  799           "-zisofs max_bpt=%.f:max_bpt_f=%.f:bpt_free_ratio=%.3f\n",
  800           (double) xorriso->zisofs_max_total_blocks * 8.0,
  801           (double) xorriso->zisofs_max_file_blocks * 8.0,
  802           xorriso->zisofs_bpt_discard_free_ratio);
  803    Xorriso_status_result(xorriso, filter, fp, flag & 2);
  804  }
  805  if(always || !(used_blocks == 0)) {
  806    sprintf(xorriso->result_line,
  807           "-zisofs bpt_used=%.f:bpt_ratio_used=%.3f\n",
  808            (double) used_blocks * 8.0,
  809            ((double) used_blocks) / (double) xorriso->zisofs_max_total_blocks);
  810    Xorriso_status_result(xorriso, filter, fp, flag & 2);
  811  }
  812  if(always || !(
  813     ziso_count == 0 && osiz_count == 0 &&
  814     gzip_count == 0 && gunzip_count == 0)) {
  815    sprintf(xorriso->result_line,
  816          "-zisofs ziso_used=%.f:osiz_used=%.f:gzip_used=%.f:gunzip_used=%.f\n",
  817          (double) ziso_count, (double) osiz_count,
  818          (double) gzip_count, (double) gunzip_count);
  819    Xorriso_status_result(xorriso, filter, fp, flag & 2);
  820  }
  821  return(1);
  822 }
  823