"Fossies" - the Fresh Open Source Software Archive

Member "libisoburn-1.5.4/xorriso/match.c" (8 Jul 2020, 22516 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 "match.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.5.0_vs_1.5.2.

    1 
    2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
    3 
    4    Copyright 2007-2013 Thomas Schmitt, <scdbackup@gmx.net>
    5 
    6    Provided under GPL version 2 or later.
    7 
    8    This file contains the implementation of functions for pattern matching.
    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 <fcntl.h>
   25 #include <errno.h>
   26 
   27 #include "xorriso.h"
   28 #include "xorriso_private.h"
   29 #include "xorrisoburn.h"
   30 
   31 
   32 /* @param flag bit0= do not augment relative structured search by xorriso->wdi
   33                bit1= return 2 if bonked at start point by .. 
   34                      (caller then aborts or retries without bit0)
   35                bit2= eventually prepend wdx rather than wdi
   36    @return <=0 error, 1= ok, 2= with bit1: relative pattern exceeds start point
   37 */
   38 int Xorriso_prepare_regex(struct XorrisO *xorriso, char *adr, int flag)
   39 {
   40  int l,ret,i,count,bonked= 0,is_constant,is_still_relative= 0, adr_size;
   41  char *cpt,*npt,*adr_part= NULL, *absolute_adr= NULL, *adr_start,*wd;
   42 
   43  adr_size= 2 * SfileadrL;
   44  Xorriso_alloc_meM(adr_part, char, adr_size);
   45  Xorriso_alloc_meM(absolute_adr, char, adr_size);
   46 
   47  if(flag&4)
   48    wd= xorriso->wdx;
   49  else
   50    wd= xorriso->wdi;
   51 
   52  if(xorriso->search_mode>=2 && xorriso->search_mode<=4) {
   53    if(xorriso->search_mode==3 || xorriso->search_mode==4) {
   54      l= strlen(adr)+strlen(wd)+1;
   55      if(l * 2 + 2 > ((int) sizeof(xorriso->reg_expr)) || l * 2 + 2 > adr_size){
   56        sprintf(xorriso->info_text,"Search pattern too long");
   57        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   58        {ret= 0; goto ex;}
   59      }
   60    }
   61    Xorriso_destroy_re(xorriso,0);
   62    if(xorriso->structured_search && xorriso->search_mode==3) {
   63      if(adr[0]!='/')
   64        is_still_relative= 1;
   65      if(is_still_relative && !(flag&1)) {
   66        /* relative expression : prepend working directory */
   67        sprintf(absolute_adr,"%s/%s",wd,adr);
   68        adr_start= absolute_adr;
   69        xorriso->prepended_wd= 1;
   70        is_still_relative= 0;
   71      } else
   72        adr_start= adr;
   73      /* count slashes */;
   74      cpt= adr_start;
   75      while(*cpt=='/')
   76        cpt++;
   77      for(i= 0;1;i++) {
   78        cpt= strchr(cpt,'/');
   79        if(cpt==NULL)
   80      break;
   81        while(*cpt=='/')
   82          cpt++;
   83      }
   84      count= i+1;
   85      xorriso->re= TSOB_FELD(regex_t,count);
   86      if(xorriso->re==NULL)
   87        {ret= -1; goto ex;}
   88      xorriso->re_constants= TSOB_FELD(char *,count);
   89      if(xorriso->re_constants==NULL)
   90        {ret= -1; goto ex;}
   91      for(i= 0;i<count;i++)
   92        xorriso->re_constants[i]= NULL;
   93      xorriso->re_count= count;
   94      xorriso->re_fill= 0;
   95        
   96      /* loop over slash chunks*/;
   97      cpt= adr_start;
   98      xorriso->re_fill= 0;
   99      while(*cpt=='/')
  100        cpt++;
  101      for(i= 0;i<count;i++) {
  102        npt= strchr(cpt,'/');
  103        if(npt==NULL) {
  104          if((int) strlen(cpt) >= adr_size)
  105            {ret= -1; goto ex;}
  106          strcpy(adr_part,cpt);
  107        } else {
  108          if(npt-cpt >= adr_size)
  109            {ret= -1; goto ex;}
  110          strncpy(adr_part,cpt,npt-cpt);
  111          adr_part[npt-cpt]= 0;
  112        }
  113 
  114        if(adr_part[0]==0)
  115          goto next_adr_part;
  116        if(adr_part[0] == '.' && adr_part[1] == 0)
  117          goto next_adr_part;
  118        if(adr_part[0]=='.' && adr_part[1]=='.' && adr_part[2]==0) {
  119          /* delete previous part */
  120          if(xorriso->re_fill <= 0) {
  121            bonked= 1;
  122            goto next_adr_part;
  123          } 
  124          if(xorriso->re_constants[xorriso->re_fill-1]!=NULL) {
  125            free(xorriso->re_constants[xorriso->re_fill-1]);
  126            xorriso->re_constants[xorriso->re_fill-1]= NULL;
  127          } else
  128            regfree(&(xorriso->re[xorriso->re_fill-1]));
  129          (xorriso->re_fill)--;
  130          goto next_adr_part;
  131        }
  132        if(strcmp(adr_part,"*")==0) {
  133          adr_part[0]= 0;
  134          ret= 2;
  135        } else
  136          ret= Xorriso__bourne_to_reg(adr_part,xorriso->reg_expr,0);
  137        if(ret==2) {
  138          if(Sregex_string(&(xorriso->re_constants[xorriso->re_fill]),adr_part,0)
  139             <=0)
  140            {ret= -1; goto ex;}
  141        } else {
  142          if(regcomp(&(xorriso->re[xorriso->re_fill]),xorriso->reg_expr,0)!=0)
  143            goto cannot_compile;
  144        }
  145        xorriso->re_fill++;
  146 next_adr_part:;
  147        if(i==count-1)
  148      break;
  149        cpt= npt+1;
  150        while(*cpt=='/')
  151          cpt++;
  152      }
  153      if(bonked) {
  154        if(flag&2)
  155          {ret= 2; goto ex;}
  156        sprintf(xorriso->info_text, "Your '..' bonked at the %s directory.",
  157                is_still_relative ? "working" : "root");
  158        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE",0);
  159        {ret= 0; goto ex;}
  160      }
  161      if(xorriso->re_fill == 0 && is_still_relative) {
  162        /* "." and its equivalents end up here */
  163        if(Sregex_string(&(xorriso->re_constants[0]), ".", 0) <=0)
  164          {ret= -1; goto ex;}  
  165        xorriso->re_fill= 1;
  166      }
  167 
  168      Xorriso__bourne_to_reg(adr_start,xorriso->reg_expr,0); /* just for show */
  169 
  170    } else { 
  171      is_constant= 0;
  172      if(strcmp(adr,"*")==0 || adr[0]==0) {
  173        is_constant= 1;
  174      } else if(xorriso->search_mode==3 || xorriso->search_mode==4) {
  175        ret= Xorriso__bourne_to_reg(adr,xorriso->reg_expr,0);
  176        is_constant= (ret==2);
  177      } else {
  178        if(strlen(adr)>=sizeof(xorriso->reg_expr))
  179          {ret= -1; goto ex;}
  180        strcpy(xorriso->reg_expr,adr);
  181      }
  182      xorriso->re_count= 0; /* tells matcher that this is not structured */
  183      xorriso->re_constants= TSOB_FELD(char *,1);
  184      if(xorriso->re_constants==NULL)
  185        {ret= -1; goto ex;}
  186      xorriso->re_constants[0]= NULL;
  187      if(is_constant) {
  188        if(strcmp(adr,"*")==0) {
  189          if(Sregex_string(&(xorriso->re_constants[0]),"",0)<=0)
  190            {ret= -1; goto ex;}
  191        } else {
  192          if(Sregex_string(&(xorriso->re_constants[0]),adr,0)<=0)
  193            {ret= -1; goto ex;}
  194        }
  195        xorriso->re_fill= 1;
  196      } else { 
  197        xorriso->re= TSOB_FELD(regex_t,1);
  198        if(xorriso->re==NULL)
  199          {ret= -1; goto ex;}
  200        if(regcomp(&(xorriso->re[0]),xorriso->reg_expr,0)!=0) {
  201 cannot_compile:;
  202          sprintf(xorriso->info_text, "Cannot compile regular expression : %s",
  203                  xorriso->reg_expr);
  204          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE",0);
  205          {ret= 0; goto ex;}
  206        }
  207      }
  208 
  209    }
  210  }
  211  ret= 1;
  212 ex:;
  213  Xorriso_free_meM(adr_part);
  214  Xorriso_free_meM(absolute_adr);
  215  return(ret);
  216 }
  217 
  218 
  219 /* @param flag bit0= do not shortcut last component of to_match
  220                bit1= consider match if regex matches parent of path
  221                bit2= retry beginning at failed last component 
  222 
  223  @return 0=match , else no match 
  224 */
  225 int Xorriso_regexec(struct XorrisO *xorriso, char *to_match, int *failed_at,
  226                     int flag)
  227 {
  228  int ret,i,re_start= 0,reg_nomatch= -1;
  229  char *cpt,*npt, *adr_part= NULL, *mpt;
  230 
  231  Xorriso_alloc_meM(adr_part, char, SfileadrL);
  232 
  233  reg_nomatch= REG_NOMATCH;
  234 
  235  *failed_at= 0;
  236  if(!(xorriso->structured_search && xorriso->re_count>0)) {
  237    if(xorriso->re_constants!=NULL)
  238      if(xorriso->re_constants[0]!=NULL) {
  239        if(xorriso->re_constants[0][0]==0)
  240          {ret= 0; goto ex;}
  241        if(strcmp(xorriso->re_constants[0],to_match)!=0)
  242          {ret= reg_nomatch; goto ex;}
  243        {ret= 0; goto ex;}
  244      }  
  245    ret= regexec(&(xorriso->re[0]),to_match,1,xorriso->match,0);
  246    goto ex;
  247  }
  248 
  249  cpt= to_match;
  250  while(*cpt=='/')
  251   cpt++;
  252  if(flag&4)
  253    re_start= xorriso->re_failed_at;
  254  if(re_start<0)
  255    re_start= 0;
  256  for(i= re_start;i<xorriso->re_fill;i++) {
  257    *failed_at= i;
  258    npt= strchr(cpt,'/');
  259    if(npt==NULL) {
  260      if(i<xorriso->re_fill-1 && !(flag&1)) 
  261        {ret= reg_nomatch; goto ex;} /* this must be the last expression part */
  262      mpt= cpt;
  263    } else {
  264      strncpy(adr_part,cpt,npt-cpt);
  265      adr_part[npt-cpt]= 0;
  266      mpt= adr_part;
  267    }
  268    if(xorriso->re_constants[i]!=NULL) {
  269      if(xorriso->re_constants[i][0]!=0) /* empty constant matches anything */
  270        if(strcmp(xorriso->re_constants[i],mpt)!=0)
  271          {ret= reg_nomatch; goto ex;}
  272    } else {
  273      ret= regexec(&(xorriso->re[i]),mpt,1,xorriso->match,0);
  274      if(ret!=0)
  275        goto ex;
  276    }
  277    if(npt==NULL) {
  278      if(i>=xorriso->re_fill-1)
  279        {ret= 0; goto ex;} /* MATCH */
  280      *failed_at= i+1;
  281      {ret= reg_nomatch; goto ex;}
  282    }
  283    cpt= npt+1;
  284    while(*cpt=='/')
  285      cpt++; 
  286  }
  287  *failed_at= xorriso->re_fill;
  288  if(flag & 2)
  289    {ret= 0; goto ex;} /* MATCH */
  290  ret= reg_nomatch;
  291 ex:;
  292  Xorriso_free_meM(adr_part);
  293  return(ret);
  294 }
  295 
  296 
  297 int Xorriso_is_in_patternlist(struct XorrisO *xorriso,
  298                               struct Xorriso_lsT *patternlist, char *path,
  299                               int flag)
  300 {
  301  int ret, failed_at, i= 0;
  302  struct Xorriso_lsT *s;
  303 
  304  xorriso->search_mode= 3;
  305  xorriso->structured_search= 1;
  306 
  307  for(s= patternlist; s != NULL; s= Xorriso_lst_get_next(s, 0)) {
  308    ret= Xorriso_prepare_regex(xorriso, Xorriso_lst_get_text(s, 0), 0);
  309    if(ret <= 0)
  310      return(-1);
  311    /* Match path or parent of path */
  312    ret= Xorriso_regexec(xorriso, path, &failed_at, 2);
  313    if(ret == 0)
  314      return(i + 1);
  315    i++;
  316  }
  317  return(0);
  318 }
  319 
  320 
  321 char *Xorriso_get_pattern(struct XorrisO *xorriso,
  322                           struct Xorriso_lsT *patternlist, int index, int flag)
  323 {
  324  int i= 0;
  325  struct Xorriso_lsT *s;
  326 
  327  for(s= patternlist; s != NULL; s= Xorriso_lst_get_next(s, 0)) {
  328    if(i == index)
  329      return(Xorriso_lst_get_text(s, 0));
  330    i++;
  331  }
  332  return(NULL);
  333 }
  334 
  335 
  336 
  337 /* @param flag bit2= this is a disk_pattern
  338    @return <=0 failure , 1 pattern ok , 2 pattern needed prepended wd */
  339 int Xorriso_prepare_expansion_pattern(struct XorrisO *xorriso, char *pattern,
  340                                       int flag)
  341 {
  342  int ret, prepwd= 0;
  343 
  344  ret= Xorriso_prepare_regex(xorriso, pattern, 1|2|(flag&4));
  345  if(ret==2) {
  346    ret= Xorriso_prepare_regex(xorriso, pattern, flag&4);
  347    prepwd= 1;
  348  }
  349  if(ret<=0) {
  350    sprintf(xorriso->info_text,
  351            "Cannot compile pattern to regular expression:  %s", pattern);
  352    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  353    return(0);
  354  }
  355  return(1+prepwd);
  356 }
  357 
  358 
  359 /* @param flag bit0= count results rather than storing them
  360                bit1= unexpected change of number is a FATAL event
  361    @return <=0 error , 1 is root (end processing) ,
  362                        2 is not root (go on processing)
  363 */
  364 int Xorriso_check_for_root_pattern(struct XorrisO *xorriso, 
  365                int *filec, char **filev, int count_limit, off_t *mem, int flag)
  366 {
  367  if(xorriso->re_fill!=0)
  368    return(2);
  369  /* This is the empty pattern representing root */
  370  if(flag&1) {
  371    (*filec)++;
  372    (*mem)+= 8;
  373  } else {
  374    if(*filec >= count_limit) {
  375      sprintf(xorriso->info_text,
  376             "Number of matching files changed unexpectedly (> %d)",
  377              count_limit);
  378      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
  379                          (flag&2 ? "FATAL" : "WARNING"), 0);
  380      return(flag&2 ? -1 : 0);
  381    }
  382    filev[*filec]= strdup("/");
  383    if(filev[*filec]==NULL) {
  384      Xorriso_no_pattern_memory(xorriso, (off_t) 2, 0);
  385      return(-1);
  386    }
  387    (*filec)++;
  388  }
  389  return(1);
  390 }
  391 
  392 
  393 /* @param flag bit0= count result rather than storing it
  394                bit1= unexpected change of number is a FATAL event
  395 */
  396 int Xorriso_register_matched_adr(struct XorrisO *xorriso,
  397                                 char *adr, int count_limit,
  398                                 int *filec, char **filev, off_t *mem, int flag)
  399 {
  400  int l;
  401 
  402  if(flag&1) {
  403    (*filec)++;
  404    l= strlen(adr)+1;
  405    (*mem)+= sizeof(char *)+l;
  406    if(l % sizeof(char *))
  407      (*mem)+= sizeof(char *)-(l % sizeof(char *));
  408  } else {
  409    if(*filec >= count_limit) {
  410      sprintf(xorriso->info_text,
  411          "Number of matching files changed unexpectedly (> %d)",
  412          count_limit);
  413      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
  414                          (flag&2 ? "FATAL" : "WARNING"), 0);
  415      return(flag&2 ? -1 : 0);
  416    }
  417    filev[*filec]= strdup(adr);
  418    if(filev[*filec]==NULL) {
  419      Xorriso_no_pattern_memory(xorriso, (off_t) (strlen(adr)+1), 0);
  420      return(-1);
  421    }
  422    (*filec)++;
  423  }
  424  return(1);
  425 }
  426 
  427 
  428 /* @param flag bit0= count results rather than storing them
  429                bit1= this is a recursion
  430                bit2= prepend wd (automatically done if wd[0]!=0)
  431    @return <=0 error , 1 ok , 2 could not open directory
  432 */
  433 int Xorriso_obtain_pattern_files_x(
  434        struct XorrisO *xorriso, char *wd, char *dir_adr,
  435        int *filec, char **filev, int count_limit, off_t *mem,
  436        int *dive_count, int flag)
  437 {
  438  int ret, failed_at, follow_mount, follow_links;
  439  struct DirseQ *dirseq= NULL;
  440  struct stat stbuf;
  441  dev_t dir_dev;
  442  char *path;
  443  char *adr= NULL, *name= NULL, *path_data= NULL;
  444 
  445  adr= malloc(SfileadrL);
  446  name= malloc(SfileadrL);
  447  path_data= malloc(SfileadrL);
  448  if(adr==NULL || name==NULL || path_data==NULL) {
  449    Xorriso_no_malloc_memory(xorriso, &adr, 0);
  450    {ret= -1; goto ex;}
  451  }
  452  follow_mount= (xorriso->do_follow_mount || xorriso->do_follow_pattern);
  453  follow_links= (xorriso->do_follow_links || xorriso->do_follow_pattern);
  454  if(!(flag&2))
  455    *dive_count= 0;
  456  else
  457    (*dive_count)++;
  458 
  459  ret= Xorriso_check_for_root_pattern(xorriso, filec, filev, count_limit,
  460                                      mem, flag&1);
  461  if(ret!=2)
  462    goto ex;
  463 
  464  if(lstat(dir_adr, &stbuf)==-1)
  465    {ret= 2; goto ex;}
  466  dir_dev= stbuf.st_dev;
  467  if(S_ISLNK(stbuf.st_mode)) {
  468    if(stat(dir_adr, &stbuf)==-1)
  469      {ret= 2; goto ex;}
  470    if(dir_dev != stbuf.st_dev && !follow_mount)
  471      {ret= 2; goto ex;}
  472  }
  473  ret= Dirseq_new(&dirseq, dir_adr, 1);
  474  if(ret<0) {
  475    sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
  476    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  477    {ret= -1; goto ex;}
  478  }
  479  if(ret==0)
  480    {ret= 2; goto ex;}
  481 
  482  while(1) {
  483    ret= Dirseq_next_adr(dirseq,name,0);
  484    if(ret==0)
  485  break;
  486    if(ret<0) {
  487      sprintf(xorriso->info_text,"Failed to obtain next directory entry");
  488      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  489      {ret= -1; goto ex;}
  490    }
  491 
  492    ret= Xorriso_make_abs_adr(xorriso, wd, name, adr, flag&4);
  493    if(ret<=0)
  494      goto ex;
  495 
  496    ret= Xorriso_regexec(xorriso, adr, &failed_at, 1);
  497    if(ret>0) { /* no match */
  498      if(failed_at <= *dive_count) /* no hope for a match */
  499  continue;
  500      path= adr;
  501      if(adr[0]!='/') {
  502        path= path_data;
  503        ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, adr, path, 1|4);
  504        if(ret<=0)
  505          goto ex;
  506      }
  507 
  508      if(follow_links)
  509        ret= stat(path,&stbuf);
  510      else
  511        ret= lstat(path,&stbuf);
  512      if(ret==-1)
  513  continue;
  514      if(!S_ISDIR(stbuf.st_mode))
  515  continue;
  516      if(dir_dev != stbuf.st_dev && !follow_mount)
  517  continue;
  518 
  519      /* dive deeper */
  520      ret= Xorriso_obtain_pattern_files_x(xorriso, adr, path,
  521                            filec, filev, count_limit, mem, dive_count, flag|2);
  522      if(ret<=0)
  523        goto ex;
  524    } else {
  525      ret= Xorriso_register_matched_adr(xorriso, adr, count_limit,
  526                                        filec, filev, mem, flag&1);
  527      if(ret<0)
  528        goto ex;
  529      if(ret==0)
  530  break;
  531    }
  532  } 
  533  ret= 1;
  534 ex:;
  535  if(adr!=NULL)
  536    free(adr);
  537  if(name!=NULL)
  538    free(name);
  539  if(path_data!=NULL)
  540    free(path_data);
  541  Dirseq_destroy(&dirseq,0);
  542  if(flag&2)
  543    (*dive_count)--;
  544  return(ret);
  545 }
  546 
  547 
  548 int Xorriso_eval_nonmatch(struct XorrisO *xorriso, char *pattern,
  549                           int *nonconst_mismatches, off_t *mem, int flag)
  550 {
  551  int k,l;
  552 
  553  /* Is this a constant pattern ? */
  554  for(k= 0; k<xorriso->re_fill; k++) {
  555    if(xorriso->re_constants[k]==NULL)
  556  break;
  557    if(xorriso->re_constants[k][0]==0)
  558  break;
  559  }
  560  if(k<xorriso->re_fill)
  561    (*nonconst_mismatches)++; /* it is not */
  562 
  563  l= strlen(pattern)+1;
  564  (*mem)+= sizeof(char *)+l;
  565  if(l % sizeof(char *))
  566    (*mem)+= sizeof(char *)-(l % sizeof(char *));
  567  return(1);
  568 }
  569 
  570 
  571 /* @param flag bit0= a match count !=1 is a SORRY event
  572                bit1= a match count !=1 is a FAILURE event
  573 */
  574 int Xorriso_check_matchcount(struct XorrisO *xorriso,
  575                 int count, int nonconst_mismatches, int num_patterns,
  576                 char **patterns, int flag)
  577 {
  578 
  579  if((flag&1) && (count!=1 || nonconst_mismatches)){
  580    if(count-nonconst_mismatches>0)
  581      sprintf(xorriso->info_text,
  582              "Pattern match with more than one file object");
  583    else
  584      sprintf(xorriso->info_text, "No pattern match with any file object");
  585    if(num_patterns==1)
  586      sprintf(xorriso->info_text+strlen(xorriso->info_text), ": ");
  587    Text_shellsafe(patterns[0], xorriso->info_text, 1);
  588    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, 
  589                        (flag&2 ? "FAILURE" : "SORRY"), 0);
  590    return(0);
  591  }
  592  return(1);
  593 }
  594 
  595 
  596 int Xorriso_no_pattern_memory(struct XorrisO *xorriso, off_t mem, int flag)
  597 {
  598  char mem_text[80];
  599 
  600  Sfile_scale((double) mem, mem_text,5,1e4,1);
  601  sprintf(xorriso->info_text,
  602          "Cannot allocate enough memory (%s) for pattern expansion",
  603          mem_text);
  604  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  605  return(1);
  606 }
  607 
  608 
  609 int Xorriso_alloc_pattern_mem(struct XorrisO *xorriso, off_t mem, 
  610                               int count, char ***filev, int flag)
  611 {
  612  char mem_text[80], limit_text[80];
  613 
  614  Sfile_scale((double) mem, mem_text,5,1e4,0);
  615  sprintf(xorriso->info_text,
  616          "Temporary memory needed for pattern expansion : %s", mem_text);
  617  if(!(flag&1))
  618    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
  619  if(mem > xorriso->temp_mem_limit) {
  620    Sfile_scale((double) xorriso->temp_mem_limit, limit_text,5,1e4,1);
  621    sprintf(xorriso->info_text,
  622            "List of matching file addresses exceeds -temp_mem_limit (%s > %s)",
  623            mem_text, limit_text);
  624    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  625    return(0);
  626  }
  627 
  628  (*filev)= (char **) calloc(count, sizeof(char *));
  629  if(*filev==NULL) {
  630    Xorriso_no_pattern_memory(xorriso, mem, 0);
  631    return(-1);
  632  }
  633  return(1);
  634 }
  635 
  636 
  637 /* @param flag bit0= a match count !=1 is a FAILURE event
  638                bit1= with bit0 tolerate 0 matches if pattern is a constant
  639                bit3= do not add unresolved pattern to filev
  640 */
  641 int Xorriso_expand_disk_pattern(struct XorrisO *xorriso,
  642                            int num_patterns, char **patterns, int extra_filec,
  643                            int *filec, char ***filev, off_t *mem, int flag)
  644 {
  645  int ret, count= 0, abs_adr= 0, i, was_count, was_filec;
  646  int nonconst_mismatches= 0, dive_count= 0;
  647  char *dir_adr= NULL;
  648 
  649  Xorriso_alloc_meM(dir_adr, char, SfileadrL);
  650 
  651  *filec= 0;
  652  *filev= NULL;
  653 
  654  xorriso->search_mode= 3;
  655  xorriso->structured_search= 1;
  656 
  657  for(i= 0; i<num_patterns; i++) {
  658    abs_adr= 0;
  659    ret= Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 4);
  660    if(ret<=0)
  661      goto ex;
  662    if(ret==2)
  663      abs_adr= 4;
  664 
  665    if(patterns[i][0]=='/' || abs_adr) {
  666      strcpy(dir_adr, "/");
  667      abs_adr= 4;
  668    } else {
  669      strcpy(dir_adr, xorriso->wdx);
  670      if(dir_adr[0]==0)
  671        strcpy(dir_adr, "/");
  672      ret= Sfile_type(dir_adr, 1|4);
  673      if(ret!=2) {
  674        Xorriso_msgs_submit(xorriso, 0, dir_adr, 0, "ERRFILE", 0);
  675        sprintf(xorriso->info_text, "Address set by -cdx is not a directory: ");
  676        Text_shellsafe(dir_adr, xorriso->info_text, 1);
  677        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  678        ret= 0; goto ex;
  679      }
  680    }
  681 
  682    /* count the matches */
  683    was_count= count;
  684    ret= Xorriso_obtain_pattern_files_x(xorriso, "", dir_adr, &count, NULL, 0,
  685                                        mem, &dive_count, 1 | abs_adr);
  686    if(ret<=0)
  687      goto ex;
  688    if(was_count==count && strcmp(patterns[i],"*")!=0 && (flag&3)!=1 &&
  689       !(flag & 8)) {
  690      count++;
  691      ret= Xorriso_eval_nonmatch(xorriso, patterns[i],
  692                                 &nonconst_mismatches, mem, 0);
  693      if(ret<=0)
  694        goto ex;
  695    }
  696  }
  697 
  698  ret= Xorriso_check_matchcount(xorriso, count, nonconst_mismatches,
  699                                num_patterns, patterns, (flag&1)|2);
  700  if(ret<=0)
  701    goto ex;
  702 
  703  count+= extra_filec;
  704  (*mem)+= extra_filec * sizeof(char *);
  705 
  706  if(count<=0)
  707    {ret= !(flag & 8); goto ex;}
  708 
  709  ret= Xorriso_alloc_pattern_mem(xorriso, *mem, count, filev, 0);
  710  if(ret<=0)
  711    goto ex;
  712 
  713  /* now store addresses */
  714  for(i= 0; i<num_patterns; i++) {
  715    abs_adr= 0;
  716    ret= Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 4);
  717    if(ret<=0)
  718      goto ex;
  719    if(ret==2)
  720      abs_adr= 4;
  721 
  722    if(patterns[i][0]=='/' || abs_adr) {
  723      strcpy(dir_adr, "/");
  724      abs_adr= 4;
  725    } else {
  726      strcpy(dir_adr, xorriso->wdx);
  727      if(dir_adr[0]==0)
  728        strcpy(dir_adr, "/");
  729    }
  730 
  731    was_filec= *filec;
  732    ret= Xorriso_obtain_pattern_files_x(xorriso, "", dir_adr, filec, *filev,
  733                                        count, mem, &dive_count, abs_adr);
  734    if(ret<=0)
  735      goto ex;
  736 
  737    if(was_filec == *filec && strcmp(patterns[i],"*")!=0 && (flag & 3) != 1 &&
  738       !(flag & 8)) {
  739      (*filev)[*filec]= strdup(patterns[i]);
  740      if((*filev)[*filec]==NULL) {
  741        (*mem)= strlen(patterns[i])+1;
  742        Xorriso_no_pattern_memory(xorriso, *mem, 0);
  743        ret= -1; goto ex;
  744      }
  745      (*filec)++;
  746    } 
  747  }
  748 
  749  ret= 1;
  750 ex:;
  751  if(ret<=0) {
  752    if(filev!=NULL)
  753      Sfile_destroy_argv(&count, filev, 0);
  754    *filec= 0;
  755  }
  756  Xorriso_free_meM(dir_adr);
  757  return(ret);
  758 }
  759 
  760 
  761 /* @param flag bit0= command without pattern capability
  762                bit1= disk_pattern rather than iso_rr_pattern
  763 */
  764 int Xorriso_warn_of_wildcards(struct XorrisO *xorriso, char *path, int flag)
  765 {
  766  static int count_iso= 0, count_disk= 0, max_iso= 3, max_disk= 3;
  767 
  768  if(strchr(path,'*')!=NULL || strchr(path,'?')!=NULL ||
  769     strchr(path,'[')!=NULL) {
  770    if(flag & 2) {
  771      count_disk++;
  772      if(count_disk > max_disk)
  773        return(1);
  774    } else {
  775      count_iso++;
  776      if(count_iso > max_iso)
  777        return(1);
  778    }
  779    if(flag&1) {
  780      sprintf(xorriso->info_text,
  781       "Pattern expansion of wildcards \"*?[\" does not apply to this command");
  782    } else {
  783      sprintf(xorriso->info_text,
  784             "Pattern expansion of wildcards \"*?[\" is disabled by command %s",
  785             (flag&2) ? "-disk_pattern or -pathspecs" : "-iso_rr_pattern");
  786    }
  787    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
  788    sprintf(xorriso->info_text,"Pattern seen: ");
  789    Text_shellsafe(path, xorriso->info_text, 1);
  790    strcat(xorriso->info_text, "\n");
  791    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
  792    return(1);
  793  }
  794  return(0);
  795 }
  796