"Fossies" - the Fresh Open Source Software Archive

Member "libisoburn-1.5.4/xorriso/aux_objects.c" (8 Jul 2020, 22940 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 "aux_objects.c" see the Fossies "Dox" file reference documentation.

    1 
    2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
    3 
    4    Copyright 2007-2010 Thomas Schmitt, <scdbackup@gmx.net>
    5 
    6    Provided under GPL version 2 or later.
    7 
    8    This file contains the implementations of classes:
    9 
   10    - SplitparT which represents byte intervals of data files.
   11 
   12    - DirseQ which crawls along a directory's content list.
   13 
   14    - ExclusionS which manages the list of excluded file paths and
   15      leaf patterns.
   16      Because of its structural identity it is also used for disk address
   17      oriented hiding at insert time as of mkisofs.
   18 
   19    - Xorriso_lsT which provides a generic double-linked list.
   20 
   21    - LinkiteM, PermiteM which temporarily record relations and states.
   22 
   23 */
   24 
   25 #ifdef HAVE_CONFIG_H
   26 #include "../config.h"
   27 #endif
   28 
   29 #include <ctype.h>
   30 #include <sys/types.h>
   31 #include <unistd.h>
   32 #include <stdlib.h>
   33 #include <stdio.h>
   34 #include <string.h>
   35 #include <sys/stat.h>
   36 #include <sys/time.h>
   37 #include <time.h>
   38 #include <utime.h>
   39 #include <dirent.h>
   40 #include <errno.h>
   41 
   42 
   43 #include "xorriso.h"
   44 #include "xorriso_private.h"
   45 
   46 
   47 /* ---------------------------- SplitparT ------------------------- */
   48 
   49 
   50 struct SplitparT {
   51  char *name;
   52  int partno;
   53  int total_parts;
   54  off_t offset;
   55  off_t bytes;
   56  off_t total_bytes;
   57 };
   58 
   59 static char Splitpart_wordS[][16]= {"part_", "_of_", "_at_", "_with_", "_of_"};
   60 
   61 
   62 int Splitparts_new(struct SplitparT **o, int count, int flag)
   63 {
   64  int i;
   65 
   66  (*o)= TSOB_FELD(struct SplitparT, count);
   67  if((*o)==NULL)
   68    return(-1);
   69  for(i= 0; i<count; i++) {
   70    (*o)[i].name= NULL;
   71    (*o)[i].partno= 0;
   72    (*o)[i].total_parts= 0;
   73    (*o)[i].offset= 0;
   74    (*o)[i].bytes= 0;
   75    (*o)[i].total_bytes= 0;
   76  }
   77  return(1);
   78 }
   79 
   80 
   81 int Splitparts_destroy(struct SplitparT **o, int count, int flag)
   82 {
   83  int i;
   84 
   85  if((*o)==NULL)
   86    return(0);
   87  for(i= 0; i<count; i++) {
   88    if((*o)[i].name!=NULL)
   89      free((*o)[i].name);
   90  }
   91  free(*o);
   92  *o= NULL;
   93  return(1);
   94 }
   95 
   96 
   97 int Splitparts_set(struct SplitparT *o, int idx,
   98                    char *name, int partno, int total_parts,
   99                    off_t offset, off_t bytes, off_t total_bytes, int flag)
  100 {
  101  if(o[idx].name!=NULL)
  102    free(o[idx].name);
  103  o[idx].name= strdup(name);
  104  if(o[idx].name==NULL)
  105    return(-1);
  106  o[idx].partno= partno;
  107  o[idx].total_parts= total_parts;
  108  o[idx].offset= offset;
  109  o[idx].bytes= bytes;
  110  o[idx].total_bytes= total_bytes;
  111  return(1);
  112 }
  113 
  114 
  115 int Splitparts_get(struct SplitparT *o, int idx, char **name, int *partno,
  116                    int *total_parts, off_t *offset, off_t *bytes,
  117                    off_t *total_bytes, int flag)
  118 {
  119  *name= o[idx].name;
  120  *partno= o[idx].partno;
  121  *total_parts= o[idx].total_parts;
  122  *offset= o[idx].offset;
  123  *bytes= o[idx].bytes;
  124  *total_bytes= o[idx].total_bytes;
  125  return(1);
  126 }
  127 
  128 
  129 int Splitpart__read_next_num(char *base_pt, char **next_pt, off_t *num,
  130                              int flag)
  131 {
  132  char *cpt, *ept, scale[4];
  133  double sfak;
  134 
  135  *num= 0;
  136  for(cpt= base_pt; *cpt!=0 && !isdigit(*cpt); cpt++);
  137  if(*cpt==0)
  138    return(0);
  139  for(ept= cpt; *ept!=0 && isdigit(*ept); ept++)
  140    *num= (*num)*10+(*ept)-'0';
  141  scale[0]= '1';
  142  scale[1]= *ept;
  143  scale[2]= 0;
  144  sfak= Scanf_io_size(scale, 0);
  145  *num *= (off_t) sfak;
  146  if(sfak > 1.0)
  147    ept++;
  148  *next_pt= ept;
  149  return(1);
  150 }
  151 
  152 
  153 int Splitpart__parse(char *name, int *partno, int *total_parts,
  154                     off_t *offset, off_t *bytes, off_t *total_bytes, int flag)
  155 
  156 {
  157  int ret; 
  158  off_t num;
  159  char *cpt, *ept;
  160 
  161  cpt= name;
  162  if(strncmp(cpt, Splitpart_wordS[0], strlen(Splitpart_wordS[0])) != 0)
  163    return(0);
  164  ret= Splitpart__read_next_num(cpt, &ept, &num, 0);
  165  if(ret<=0)
  166    return(ret);
  167  *partno= num;
  168  cpt= ept;
  169  if(strncmp(cpt, Splitpart_wordS[1], strlen(Splitpart_wordS[1])) != 0)
  170    return(0);
  171  ret= Splitpart__read_next_num(cpt, &ept, &num, 0);
  172  if(ret<=0)
  173    return(ret);
  174  *total_parts= num;
  175  cpt= ept;
  176  if(strncmp(cpt, Splitpart_wordS[2], strlen(Splitpart_wordS[2])) != 0)
  177    return(0);
  178  ret= Splitpart__read_next_num(cpt, &ept, offset, 0);
  179  if(ret<=0)
  180    return(ret);
  181  cpt= ept;
  182  if(strncmp(cpt, Splitpart_wordS[3], strlen(Splitpart_wordS[3])) != 0)
  183    return(0);
  184  ret= Splitpart__read_next_num(cpt, &ept, bytes, 0);
  185  if(ret<=0)
  186    return(ret);
  187  cpt= ept;
  188  if(strncmp(cpt, Splitpart_wordS[4], strlen(Splitpart_wordS[4])) != 0)
  189    return(0);
  190  ret= Splitpart__read_next_num(cpt, &ept, total_bytes, 0);
  191  if(ret<=0)
  192    return(ret);
  193  if(*ept != 0)
  194    return(0);
  195  return(1);
  196 }
  197 
  198 
  199 int Splitpart__is_part_path(char *path, int flag)
  200 {
  201  int partno, total_parts, ret;
  202  off_t offset, bytes, total_bytes;
  203  char *name;
  204 
  205  name= strrchr(path, '/');
  206  if(name == NULL)
  207    name= path;
  208  else
  209    name++;
  210  ret= Splitpart__parse(name, &partno, &total_parts, &offset, &bytes,
  211                        &total_bytes, 0);
  212  return(ret > 0);
  213 }
  214 
  215 
  216 /* part_#_of_#_at_#_with_#_of_#
  217 */
  218 int Splitpart__compose(char *adr, int partno, int total_parts,
  219                        off_t offset, off_t bytes, off_t total_bytes, int flag)
  220 {
  221  sprintf(adr, "%s%d%s%d%s", Splitpart_wordS[0], partno, Splitpart_wordS[1],
  222                             total_parts, Splitpart_wordS[2]);
  223  if((offset % (1024*1024))==0 && offset>0) {
  224    Sfile_off_t_text(adr+strlen(adr), offset / (1024*1024), 0);
  225    strcat(adr, "m");
  226  } else
  227    Sfile_off_t_text(adr+strlen(adr), offset, 0);
  228  strcat(adr, Splitpart_wordS[3]); 
  229  if((bytes % (1024*1024))==0) {
  230    Sfile_off_t_text(adr+strlen(adr), bytes / (1024*1024), 0);
  231    strcat(adr, "m");
  232  } else
  233    Sfile_off_t_text(adr+strlen(adr), bytes, 0);
  234  strcat(adr, Splitpart_wordS[4]);
  235  Sfile_off_t_text(adr+strlen(adr), total_bytes, 0);
  236  return(1);
  237 }
  238 
  239 
  240 int Splitparts_cmp(const void *v1, const void *v2)
  241 {
  242  struct SplitparT *p1, *p2;
  243 
  244  p1= (struct SplitparT *) v1;
  245  p2= (struct SplitparT *) v2;
  246  
  247  if(p1->partno>p2->partno)
  248    return(1);
  249  if(p1->partno<p2->partno)
  250    return(-1);
  251  if(p1->offset>p2->offset)
  252    return(1);
  253  if(p1->offset<p2->offset)
  254    return(-1);
  255  return(0);
  256 }
  257 
  258 
  259 int Splitparts_sort(struct SplitparT *o, int count, int flag)
  260 {
  261  qsort(o, (size_t) count, sizeof(struct SplitparT), Splitparts_cmp);
  262  return(1);
  263 }
  264 
  265 
  266 /* ---------------------------- End SplitparT ------------------------- */
  267 
  268 
  269 /* ------------------------------ DirseQ  ------------------------------ */
  270 
  271 
  272 static int Dirseq_buffer_sizE= 100;
  273 
  274 struct DirseQ {
  275   char adr[SfileadrL];
  276   DIR *dirpt;
  277   int count;  
  278   char **buffer;
  279   int buffer_size;
  280   int buffer_fill;
  281   int buffer_rpt;
  282 
  283   struct DirseQ *next;
  284 };
  285 
  286 int Dirseq_destroy(struct DirseQ **o, int flag);
  287 int Dirseq_next_adrblock(struct DirseQ *o, char *replies[], int *reply_count,
  288                          int max_replies, int flag);
  289 
  290 
  291 int Dirseq_new(struct DirseQ **o, char *adr, int flag)
  292 /*
  293  bit0= with non-fatal errors do not complain about failed opendir() 
  294 */
  295 {
  296  int ret,i,severe_error;
  297  struct DirseQ *m;
  298 
  299  m= *o= TSOB_FELD(struct DirseQ,1);
  300  if(m==NULL)
  301    return(-1);
  302  m->adr[0]= 0;
  303  m->dirpt= NULL;
  304  m->count= 0;
  305  m->buffer= NULL;
  306  m->buffer_size= 0;
  307  m->buffer_fill= 0;
  308  m->buffer_rpt= 0;
  309  m->next= NULL;
  310  if(Sfile_str(m->adr, adr, 0)<=0)
  311    {ret= -1; goto failed;}
  312  m->buffer= TSOB_FELD(char *,Dirseq_buffer_sizE);
  313  if(m->buffer==NULL)
  314    {ret= -1; goto failed;}
  315  m->buffer_size= Dirseq_buffer_sizE;
  316  for(i= 0;i<m->buffer_size;i++)
  317    m->buffer[i]= NULL;
  318  if(adr[0]==0)
  319    m->dirpt= opendir(".");
  320  else
  321    m->dirpt= opendir(adr);
  322  if(m->dirpt==NULL) {
  323    severe_error= (errno && errno!=ENOENT && errno!=EACCES && errno!=ENOTDIR);
  324    if(severe_error || !(flag&1))
  325      fprintf(stderr,"opendir(%s) failed : %s\n",adr,strerror(errno));
  326    ret= -severe_error;
  327    goto failed;
  328  }
  329  return(1);
  330 failed:;
  331  Dirseq_destroy(o,0);
  332  return(ret);
  333 }
  334 
  335 
  336 int Dirseq_destroy(struct DirseQ **o, int flag)
  337 {
  338  int i;
  339 
  340  if(*o==NULL)
  341    return(0);
  342  if((*o)->dirpt!=NULL)
  343    closedir((*o)->dirpt);
  344  if((*o)->buffer!=NULL) {
  345    for(i=0;i<(*o)->buffer_size;i++)
  346      if((*o)->buffer[i]!=NULL)
  347        free((*o)->buffer[i]);
  348    free((char *) (*o)->buffer);
  349  }
  350  free((char *) *o);
  351  (*o)= NULL;
  352  return(1);
  353 }
  354 
  355 
  356 int Dirseq_set_next(struct DirseQ *o, struct DirseQ *next, int flag)
  357 {
  358  o->next= next;
  359  return(1);
  360 }
  361 
  362 
  363 int Dirseq_get_next(struct DirseQ *o, struct DirseQ **next, int flag)
  364 {
  365  *next= o->next;
  366  return(1);
  367 }
  368 
  369 
  370 int Dirseq_get_adr(struct DirseQ *o, char **adrpt, int flag)
  371 {
  372  *adrpt= o->adr;
  373  return(1);
  374 }
  375 
  376 
  377 int Dirseq_rewind(struct DirseQ *o, int flag)
  378 {
  379  rewinddir(o->dirpt);
  380  return(1);
  381 }
  382 
  383 
  384 int Dirseq_next_adr(struct DirseQ *o, char reply[SfileadrL], int flag)
  385 /*
  386 flag:
  387  bit0= permission to use buffer
  388  bit1= do not increment counter
  389  bit2= ignore buffer in any case
  390  bit3= do not exclude '.' and '..'
  391  bit4= sort buffer
  392  bit5= sort only incomplete last buffer
  393 return:
  394  <0 error
  395  0= no more entries available
  396  1= ok, reply is valid
  397 */
  398 {
  399  int ret;
  400  struct dirent *entry;
  401  char *name;
  402 
  403  static int override_flag_0= 0,override_flag_1= 32;
  404  flag= (flag&~override_flag_0)|override_flag_1;
  405 
  406  if((flag&1) && o->buffer_rpt>=o->buffer_fill) {
  407    /* permission to buffer and buffer empty : load a buffer */
  408    ret= Dirseq_next_adrblock(o,o->buffer,&(o->buffer_fill),
  409                              o->buffer_size,2|4|(flag&16));
  410    if(ret<=0)
  411      return(ret);
  412    o->buffer_rpt= 0;
  413    if((flag&32) && o->buffer_fill<o->buffer_size && o->buffer_fill>0) 
  414      Sort_argv(o->buffer_fill,o->buffer,0);
  415  }
  416  if(o->buffer_rpt<o->buffer_fill && !(flag&4)) {
  417    ret= Sfile_str(reply,o->buffer[o->buffer_rpt],0);
  418    Sregex_string(&(o->buffer[o->buffer_rpt]),NULL,0);
  419    if(ret<=0)
  420      return(-1);
  421    (o->buffer_rpt)++;
  422    if(!(flag&2))
  423      o->count++;
  424    return(1);
  425  }
  426  do {
  427    entry= readdir(o->dirpt);
  428    if(entry==NULL) {
  429      /* >>> how to distinguish error from EOF , do i need a (FILE *) ? */
  430      return(0);
  431    }
  432    if(strlen(entry->d_name)>=SfileadrL) {
  433      fprintf(stderr,"--- oversized directory entry (number %d) :\n    %s",
  434                     o->count+1,entry->d_name);
  435      return(-1);
  436    }
  437    name= entry->d_name;
  438    if(flag&8)
  439  break;
  440    /* skip "." and ".." */
  441  } while(name[0]=='.' && ((name[1]=='.' && name[2]==0) || name[1]==0));
  442  if(Sfile_str(reply,name,0)<=0)
  443    return(-1);
  444  if(!(flag&2))
  445    o->count++;
  446  return(1);
  447 }
  448 
  449 
  450 int Dirseq_next_adrblock(struct DirseQ *o, char *replies[], int *reply_count,
  451                          int max_replies, int flag)
  452 /* @param replies A vector of Sregex_string pointers */
  453 /*
  454 flag:
  455  bit0= permission to use buffer
  456  bit1= do not increment counter
  457  bit2= ignore buffer in any case
  458  bit4= sort replies
  459 return:
  460  <0 error
  461  0= no more entries available
  462  1= ok, reply is valid
  463 */
  464 {
  465  int i,ret;
  466  char *reply= NULL;
  467 
  468  reply= TSOB_FELD(char, SfileadrL);
  469  if(reply == NULL)
  470    return(-1);
  471 
  472  *reply_count= 0;
  473  for(i=0;i<max_replies;i++) {
  474    ret= Dirseq_next_adr(o,reply,flag&(1|2|4));
  475    if(ret<0)
  476      goto ex;
  477    if(ret==0)
  478  break;
  479    if(Sregex_string(&(replies[i]),reply,0)<=0)
  480      {ret= -1; goto ex;}
  481    (*reply_count)++;
  482  }
  483  if((*reply_count)==0)
  484    {ret= 0; goto ex;}
  485  if(flag&16) 
  486    Sort_argv(*reply_count,replies,0);
  487  ret= 1;
  488 ex:;
  489  free(reply);
  490  return(ret);
  491 }
  492 
  493 
  494 /* ---------------------------- End DirseQ  ----------------------------- */
  495 
  496 
  497 /* ---------------------------- Xorriso_lsT ----------------------------- */
  498 
  499 
  500 /*
  501  @param flag Bitfield for control purposes
  502         bit0= insert before link rather than after it
  503         bit1= do not copy data (e.g. because *data is invalid)
  504         bit2= attach data directly by pointer rather than by copying
  505 */
  506 int Xorriso_lst_new_binary(struct Xorriso_lsT **lstring, char *data,
  507                            int data_len, struct Xorriso_lsT *link, int flag)
  508 {
  509  struct Xorriso_lsT *s;
  510 
  511  s= TSOB_FELD(struct Xorriso_lsT,1);
  512  if(s==NULL)
  513    return(-1);
  514  s->text= NULL;
  515  s->next= s->prev= NULL;
  516 
  517  if(flag & 4) {
  518    s->text= data;
  519  } else {
  520    if(data_len<=0)
  521      goto failed;
  522    s->text= Smem_malloC(data_len);
  523    if(s->text==NULL)
  524      goto failed;
  525    if(!(flag&2))
  526      memcpy(s->text,data,data_len);
  527  }
  528 
  529  if(link==NULL) {
  530    ;
  531  } else if(flag&1) {
  532    s->next= link;
  533    s->prev= link->prev;
  534    if(link->prev!=NULL) 
  535      link->prev->next= s;
  536    link->prev= s;
  537  } else {
  538    s->prev= link;
  539    s->next= link->next;
  540    if(link->next!=NULL) 
  541      link->next->prev= s;
  542    link->next= s;
  543  }
  544  *lstring= s;
  545  return(1);
  546 failed:;
  547  *lstring= s;
  548  Xorriso_lst_destroy(lstring,0);
  549  return(-1);
  550 }
  551 
  552 
  553 /*
  554  @param flag Bitfield for control purposes
  555              see Xorriso_lst_new_binary()
  556 */
  557 int Xorriso_lst_new(struct Xorriso_lsT **lstring, char *text,
  558                     struct Xorriso_lsT *link, int flag)
  559 {
  560  int ret;
  561 
  562  ret= Xorriso_lst_new_binary(lstring,text,strlen(text)+1,link,flag);
  563  return(ret);
  564 }
  565 
  566 
  567 /*
  568  @param flag Bitfield for control purposes
  569              bit0= do not set *lstring to NULL
  570 */
  571 int Xorriso_lst_destroy(struct Xorriso_lsT **lstring, int flag)
  572 {
  573  struct Xorriso_lsT *s;
  574 
  575  s= *lstring;
  576  if(s==NULL)
  577    return(0);
  578  if(s->prev!=NULL)
  579    s->prev->next= s->next;
  580  if(s->next!=NULL)
  581    s->next->prev= s->prev;
  582  if(s->text!=NULL)
  583    Smem_freE(s->text);
  584  Smem_freE((char *) s);
  585  if(!(flag&1))
  586    *lstring= NULL;
  587  return(1);
  588 }
  589 
  590 
  591 int Xorriso_lst_destroy_all(struct Xorriso_lsT **lstring, int flag)
  592 {
  593  struct Xorriso_lsT *s,*next;
  594 
  595  if(lstring==NULL)
  596    return(-1);
  597  if((*lstring)==NULL)
  598    return(0);
  599  for(s= *lstring; s->prev!=NULL; s= s->prev);
  600  for(;s!=NULL;s= next){
  601    next= s->next;
  602    Xorriso_lst_destroy(&s,0);
  603  }
  604  *lstring= NULL;
  605  return(1);
  606 }
  607 
  608 
  609 int Xorriso_lst_append_binary(struct Xorriso_lsT **entry,
  610                               char *data, int data_len, int flag)
  611 {
  612  struct Xorriso_lsT *target= NULL,*newby;
  613 
  614  if(*entry!=NULL)
  615    for(target= *entry; target->next!=NULL; target= target->next);
  616  if(Xorriso_lst_new_binary(&newby, data, data_len, target, flag & ~1)<=0)
  617    return(-1);
  618  if(*entry==NULL || (flag & 1))
  619    *entry= newby;
  620  return(1);
  621 }
  622 
  623 
  624 struct Xorriso_lsT *Xorriso_lst_get_next(struct Xorriso_lsT *entry, int flag)
  625 {
  626  return(entry->next);
  627 }
  628 
  629 
  630 struct Xorriso_lsT *Xorriso_lst_get_prev(struct Xorriso_lsT *entry, int flag)
  631 {
  632  return(entry->prev);
  633 }
  634 
  635 
  636 char *Xorriso_lst_get_text(struct Xorriso_lsT *entry, int flag)
  637 {
  638  return(entry->text);
  639 }
  640 
  641 
  642 int Xorriso_lst_detach_text(struct Xorriso_lsT *entry, int flag)
  643 {
  644  entry->text= NULL;
  645  return(1);
  646 }
  647 
  648 
  649 int Xorriso_lst_get_last(struct Xorriso_lsT *entry, struct Xorriso_lsT **last,
  650                          int flag)
  651 {
  652  *last= NULL;
  653  if(entry != NULL)
  654    for((*last)= entry; (*last)->next != NULL; (*last)= (*last)->next);
  655  return(1);
  656 } 
  657 
  658 
  659 int Xorriso_lst_concat(struct Xorriso_lsT *first, struct Xorriso_lsT *second,
  660                        int flag)
  661 {
  662  struct Xorriso_lsT *last;
  663 
  664  Xorriso_lst_get_last(first, &last, 0);
  665  if(last != NULL)
  666    last->next= second;
  667  if(second != NULL)
  668    second->prev= last;
  669  return(1);
  670 }
  671 
  672 /* --------------------------- End Xorriso_lsT ---------------------------- */
  673 
  674 
  675 /* ------------------------------ ExclusionS ------------------------------ */
  676 
  677 
  678 struct ExclusionS {
  679 
  680  /* Absolute input patterns which lead to not_paths */
  681  struct Xorriso_lsT *not_paths_descr;
  682 
  683  /* Actually banned absolute paths */
  684  struct Xorriso_lsT *not_paths;
  685 
  686  /* Input patterns which lead to not_leafs */
  687  struct Xorriso_lsT *not_leafs_descr;
  688 
  689  /* Compiled not_leaf patterns. Caution: not char[] but  regex_t */
  690  struct Xorriso_lsT *not_leafs;
  691  
  692 };
  693 
  694 
  695 int Exclusions_new(struct ExclusionS **o, int flag)
  696 {
  697  struct ExclusionS *m;
  698 
  699  m= *o= TSOB_FELD(struct ExclusionS, 1);
  700  if(m==NULL)
  701    return(-1);
  702  m->not_paths_descr= NULL;
  703  m->not_paths= NULL;
  704  m->not_leafs_descr= NULL;
  705  m->not_leafs= NULL;
  706  return(1);
  707 }
  708 
  709 
  710 int Exclusions_destroy(struct ExclusionS **o, int flag)
  711 {
  712  struct Xorriso_lsT *s,*next;
  713 
  714  if((*o)==NULL)
  715    return(0);
  716  Xorriso_lst_destroy_all(&((*o)->not_paths_descr), 0);
  717  Xorriso_lst_destroy_all(&((*o)->not_paths), 0);
  718  Xorriso_lst_destroy_all(&((*o)->not_leafs_descr), 0);
  719  for(s= (*o)->not_leafs; s!=NULL; s= next){
  720    next= s->next;
  721    regfree((regex_t *) s->text);
  722    Xorriso_lst_destroy(&s, 0);
  723  }
  724  free((char *) *o);
  725  (*o)= NULL;
  726  return(1);
  727 }
  728 
  729 
  730 int Exclusions_add_not_paths(struct ExclusionS *o, int descrc, char **descrs,
  731                              int pathc, char **paths, int flag)
  732 {
  733  struct Xorriso_lsT *s, *new_s;
  734  int i, ret;
  735 
  736  s= NULL;
  737  if(o->not_paths_descr!=NULL) 
  738    for(s= o->not_paths_descr; s->next!=NULL; s= s->next);
  739  for(i= 0; i<descrc; i++) {
  740    ret= Xorriso_lst_new(&new_s, descrs[i], s, 0);
  741    if(ret<=0)
  742      return(ret);
  743    if(o->not_paths_descr==NULL)
  744      o->not_paths_descr= new_s;
  745    s= new_s;
  746  }
  747  s= NULL;
  748  if(o->not_paths!=NULL) 
  749    for(s= o->not_paths; s->next!=NULL; s= s->next);
  750  for(i= 0; i<pathc; i++) {
  751    ret= Xorriso_lst_new(&new_s, paths[i], s, 0);
  752    if(ret<=0)
  753      return(ret);
  754    if(o->not_paths==NULL)
  755      o->not_paths= new_s;
  756    s= new_s;
  757  }
  758  return(1);
  759 }
  760 
  761 
  762 /* @return -1=cannot store , 0=cannot compile regex , 1=ok
  763 */
  764 int Exclusions_add_not_leafs(struct ExclusionS *o, char *not_leafs_descr,
  765                              regex_t *re, int flag)
  766 {
  767  int ret;
  768 
  769  ret= Xorriso_lst_append_binary(&(o->not_leafs_descr),
  770                             not_leafs_descr, strlen(not_leafs_descr)+1, 0);
  771  if(ret<=0)
  772    return(-1);
  773  ret= Xorriso_lst_append_binary(&(o->not_leafs), (char *) re, sizeof(regex_t), 0);
  774  if(ret<=0)
  775    return(-1);
  776  return(1);
  777 }
  778 
  779 
  780 /* @param flag bit0= whole subtree is banned with -not_paths 
  781    @return 0=no match , 1=not_paths , 2=not_leafs, <0=error
  782 */
  783 int Exclusions_match(struct ExclusionS *o, char *abs_path, int flag)
  784 {
  785  struct Xorriso_lsT *s;
  786  char *leaf= NULL, *leaf_pt;
  787  regmatch_t match[1];
  788  int ret, was_non_slash, l;
  789 
  790  /* test abs_paths */
  791  if(flag&1) {
  792    for(s= o->not_paths; s!=NULL; s= s->next) {
  793      l= strlen(s->text);
  794      if(strncmp(abs_path, s->text, l)==0)
  795        if(abs_path[l]=='/' || abs_path[l]==0)
  796          {ret= 1; goto ex;}
  797    }
  798  } else {
  799    for(s= o->not_paths; s!=NULL; s= s->next)
  800      if(strcmp(abs_path, s->text)==0)
  801        {ret= 1; goto ex;}
  802  }
  803 
  804  /* determine leafname */
  805  was_non_slash= 0;
  806  for(leaf_pt= abs_path+strlen(abs_path); leaf_pt >= abs_path; leaf_pt--) {
  807    if(*leaf_pt=='/') {
  808      if(was_non_slash) {
  809        leaf_pt++;
  810  break;
  811      }
  812    } else if(*leaf_pt!=0)
  813      was_non_slash= 1;
  814  }
  815  if(strlen(leaf_pt)>=SfileadrL)
  816    {ret= -1; goto ex;}
  817  leaf= strdup(leaf_pt);
  818  leaf_pt= strchr(leaf, '/');
  819  if(leaf_pt!=NULL)
  820    *leaf_pt= 0;
  821 
  822  /* test with leaf expressions */
  823  for(s= o->not_leafs; s!=NULL; s= s->next) {
  824    ret= regexec((regex_t *) s->text, leaf, 1, match, 0);
  825    if(ret==0)
  826      {ret= 2; goto ex;}
  827  }
  828  ret= 0;
  829 ex:
  830  if(leaf != NULL)
  831    free(leaf);
  832  return(ret);
  833 }
  834 
  835 
  836 int Exclusions_get_descrs(struct ExclusionS *o,
  837                           struct Xorriso_lsT **not_paths_descr,
  838                           struct Xorriso_lsT **not_leafs_descr, int flag)
  839 {
  840  *not_paths_descr= o->not_paths_descr;
  841  *not_leafs_descr= o->not_leafs_descr;
  842  return(1);
  843 }
  844 
  845 /* ---------------------------- End ExclusionS ---------------------------- */
  846 
  847 
  848 /* ------------------------------ LinkiteM -------------------------------- */
  849 
  850 struct LinkiteM {
  851  char *link_path;
  852  dev_t target_dev;
  853  ino_t target_ino;
  854  int link_count;
  855  struct LinkiteM *next;
  856 };
  857 
  858 
  859 int Linkitem_new(struct LinkiteM **o, char *link_path, dev_t target_dev,
  860                  ino_t target_ino, struct LinkiteM *next, int flag)
  861 {
  862  struct LinkiteM *m;
  863 
  864  m= *o= TSOB_FELD(struct LinkiteM,1);
  865  if(m==NULL)
  866    return(-1);
  867  m->target_dev= target_dev;
  868  m->target_ino= target_ino;
  869  m->next= next;
  870  m->link_count= 1;
  871  if(next!=NULL)
  872    m->link_count= m->next->link_count+1;
  873  m->link_path= strdup(link_path);
  874  if(m->link_path==NULL)
  875    goto failed;
  876  return(1);
  877 failed:;
  878  Linkitem_destroy(o, 0);
  879  return(-1);
  880 }
  881 
  882 
  883 int Linkitem_destroy(struct LinkiteM **o, int flag)
  884 {
  885  if((*o)==NULL)
  886    return(0);
  887  if((*o)->link_path!=NULL)
  888    free((*o)->link_path);
  889  free((char *) (*o));
  890  *o= NULL;
  891  return(1);
  892 }
  893 
  894 
  895 int Linkitem_reset_stack(struct LinkiteM **o, struct LinkiteM *to, int flag)
  896 {
  897  struct LinkiteM *m, *m_next= NULL;
  898 
  899  /* Prevent memory corruption */
  900  for(m= *o;  m!=to; m= m->next)
  901    if(m==NULL) { /* this may actually not happen */
  902      *o= to;
  903      return(-1);
  904    }
  905 
  906  for(m= *o; m!=to; m= m_next) {
  907    m_next= m->next;
  908    Linkitem_destroy(&m, 0);
  909  }
  910  *o= to;
  911  return(1);
  912 }
  913 
  914 
  915 int Linkitem_find(struct LinkiteM *stack, dev_t target_dev, ino_t target_ino,
  916                   struct LinkiteM **result, int flag)
  917 {
  918  struct LinkiteM *m;
  919 
  920  for(m= stack; m!=NULL; m= m->next) {
  921    if(target_dev == m->target_dev && target_ino == m->target_ino) {
  922      *result= m;
  923      return(1);
  924    }
  925  }
  926  return(0);
  927 }
  928 
  929 
  930 int Linkitem_get_link_count(struct LinkiteM *item, int flag)
  931 {
  932  return(item->link_count);
  933 }
  934 
  935 
  936 /* ------------------------------ PermstacK ------------------------------- */
  937 
  938 
  939 struct PermiteM {
  940  char *disk_path;
  941  struct stat stbuf;
  942  struct PermiteM *next;
  943 };
  944 
  945 
  946 int Permstack_push(struct PermiteM **o, char *disk_path, struct stat *stbuf,
  947                    int flag)
  948 {
  949  struct PermiteM *m;
  950 
  951  m= TSOB_FELD(struct PermiteM,1);
  952  if(m==NULL)
  953    return(-1);
  954  m->disk_path= NULL;
  955  memcpy(&(m->stbuf), stbuf, sizeof(struct stat));
  956  m->next= *o;
  957 
  958  m->disk_path= strdup(disk_path);
  959  if(m->disk_path==NULL)
  960    goto failed;
  961 
  962  *o= m;
  963  return(1);
  964 failed:;
  965  if(m->disk_path!=NULL)
  966    free(m->disk_path);
  967  free((char *) m);
  968  return(-1);
  969 }
  970 
  971 
  972 /* @param flag bit0= minimal transfer: access permissions only
  973                bit1= do not set timestamps
  974 */ 
  975 int Permstack_pop(struct PermiteM **o, struct PermiteM *stopper,
  976                   struct XorrisO *xorriso, int flag)
  977 {
  978  int ret;
  979  struct utimbuf utime_buffer;
  980  struct PermiteM *m, *m_next;
  981 
  982  if((*o)==stopper)
  983    return(1);
  984  for(m= *o; m!=NULL; m= m->next)
  985    if(m->next==stopper)
  986  break;
  987  if(m==NULL) {
  988    sprintf(xorriso->info_text,
  989            "Program error: Permstack_pop() : cannot find stopper");
  990    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  991    return(-1);
  992  }
  993 
  994  for(m= *o; m!=stopper; m= m_next) {
  995    ret= chmod(m->disk_path, m->stbuf.st_mode);
  996    if(ret==-1) {
  997      if(xorriso!=NULL) {
  998        sprintf(xorriso->info_text,
  999              "Cannot change access permissions of disk directory: chmod %o ",
 1000              (unsigned int) (m->stbuf.st_mode & 07777));
 1001        Text_shellsafe(m->disk_path, xorriso->info_text, 1);
 1002        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",
 1003                            0);
 1004      }
 1005    }
 1006    if(!(flag&1)) {
 1007      ret= chown(m->disk_path, m->stbuf.st_uid, m->stbuf.st_gid);
 1008                                                /* don't complain if it fails */
 1009      if(!(flag&2)) {
 1010        utime_buffer.actime= m->stbuf.st_atime;
 1011        utime_buffer.modtime= m->stbuf.st_mtime;
 1012        ret= utime(m->disk_path,&utime_buffer);
 1013        if(ret==-1 && xorriso!=NULL) {
 1014          sprintf(xorriso->info_text,
 1015                  "Cannot change timestamps of disk directory: ");
 1016          Text_shellsafe(m->disk_path, xorriso->info_text, 1);
 1017          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",
 1018                              0);
 1019        }
 1020      }
 1021    }
 1022    m_next= m->next;
 1023    free(m->disk_path);
 1024    free((char *) m);
 1025    *o= m_next;
 1026  }
 1027  return(1);
 1028 }
 1029 
 1030 
 1031 /* ---------------------------- End PermstacK ----------------------------- */
 1032