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 
Splitparts_new(struct SplitparT ** o,int count,int flag)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 
Splitparts_destroy(struct SplitparT ** o,int count,int flag)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 
Splitparts_set(struct SplitparT * o,int idx,char * name,int partno,int total_parts,off_t offset,off_t bytes,off_t total_bytes,int flag)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 
Splitparts_get(struct SplitparT * o,int idx,char ** name,int * partno,int * total_parts,off_t * offset,off_t * bytes,off_t * total_bytes,int flag)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 
Splitpart__read_next_num(char * base_pt,char ** next_pt,off_t * num,int flag)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 
Splitpart__parse(char * name,int * partno,int * total_parts,off_t * offset,off_t * bytes,off_t * total_bytes,int flag)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 
Splitpart__is_part_path(char * path,int flag)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 */
Splitpart__compose(char * adr,int partno,int total_parts,off_t offset,off_t bytes,off_t total_bytes,int flag)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 
Splitparts_cmp(const void * v1,const void * v2)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 
Splitparts_sort(struct SplitparT * o,int count,int flag)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 
Dirseq_new(struct DirseQ ** o,char * adr,int flag)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 
Dirseq_destroy(struct DirseQ ** o,int flag)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 
Dirseq_set_next(struct DirseQ * o,struct DirseQ * next,int flag)356 int Dirseq_set_next(struct DirseQ *o, struct DirseQ *next, int flag)
357 {
358  o->next= next;
359  return(1);
360 }
361 
362 
Dirseq_get_next(struct DirseQ * o,struct DirseQ ** next,int flag)363 int Dirseq_get_next(struct DirseQ *o, struct DirseQ **next, int flag)
364 {
365  *next= o->next;
366  return(1);
367 }
368 
369 
Dirseq_get_adr(struct DirseQ * o,char ** adrpt,int flag)370 int Dirseq_get_adr(struct DirseQ *o, char **adrpt, int flag)
371 {
372  *adrpt= o->adr;
373  return(1);
374 }
375 
376 
Dirseq_rewind(struct DirseQ * o,int flag)377 int Dirseq_rewind(struct DirseQ *o, int flag)
378 {
379  rewinddir(o->dirpt);
380  return(1);
381 }
382 
383 
Dirseq_next_adr(struct DirseQ * o,char reply[SfileadrL],int flag)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 
Dirseq_next_adrblock(struct DirseQ * o,char * replies[],int * reply_count,int max_replies,int flag)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 */
Xorriso_lst_new_binary(struct Xorriso_lsT ** lstring,char * data,int data_len,struct Xorriso_lsT * link,int flag)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 */
Xorriso_lst_new(struct Xorriso_lsT ** lstring,char * text,struct Xorriso_lsT * link,int flag)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 */
Xorriso_lst_destroy(struct Xorriso_lsT ** lstring,int flag)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 
Xorriso_lst_destroy_all(struct Xorriso_lsT ** lstring,int flag)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 
Xorriso_lst_append_binary(struct Xorriso_lsT ** entry,char * data,int data_len,int flag)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 
Xorriso_lst_get_next(struct Xorriso_lsT * entry,int flag)624 struct Xorriso_lsT *Xorriso_lst_get_next(struct Xorriso_lsT *entry, int flag)
625 {
626  return(entry->next);
627 }
628 
629 
Xorriso_lst_get_prev(struct Xorriso_lsT * entry,int flag)630 struct Xorriso_lsT *Xorriso_lst_get_prev(struct Xorriso_lsT *entry, int flag)
631 {
632  return(entry->prev);
633 }
634 
635 
Xorriso_lst_get_text(struct Xorriso_lsT * entry,int flag)636 char *Xorriso_lst_get_text(struct Xorriso_lsT *entry, int flag)
637 {
638  return(entry->text);
639 }
640 
641 
Xorriso_lst_detach_text(struct Xorriso_lsT * entry,int flag)642 int Xorriso_lst_detach_text(struct Xorriso_lsT *entry, int flag)
643 {
644  entry->text= NULL;
645  return(1);
646 }
647 
648 
Xorriso_lst_get_last(struct Xorriso_lsT * entry,struct Xorriso_lsT ** last,int flag)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 
Xorriso_lst_concat(struct Xorriso_lsT * first,struct Xorriso_lsT * second,int flag)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 
Exclusions_new(struct ExclusionS ** o,int flag)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 
Exclusions_destroy(struct ExclusionS ** o,int flag)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 
Exclusions_add_not_paths(struct ExclusionS * o,int descrc,char ** descrs,int pathc,char ** paths,int flag)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 */
Exclusions_add_not_leafs(struct ExclusionS * o,char * not_leafs_descr,regex_t * re,int flag)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 */
Exclusions_match(struct ExclusionS * o,char * abs_path,int flag)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 
Exclusions_get_descrs(struct ExclusionS * o,struct Xorriso_lsT ** not_paths_descr,struct Xorriso_lsT ** not_leafs_descr,int flag)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 
Linkitem_new(struct LinkiteM ** o,char * link_path,dev_t target_dev,ino_t target_ino,struct LinkiteM * next,int flag)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 
Linkitem_destroy(struct LinkiteM ** o,int flag)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 
Linkitem_reset_stack(struct LinkiteM ** o,struct LinkiteM * to,int flag)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 
Linkitem_find(struct LinkiteM * stack,dev_t target_dev,ino_t target_ino,struct LinkiteM ** result,int flag)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 
Linkitem_get_link_count(struct LinkiteM * item,int flag)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 
Permstack_push(struct PermiteM ** o,char * disk_path,struct stat * stbuf,int flag)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 */
Permstack_pop(struct PermiteM ** o,struct PermiteM * stopper,struct XorrisO * xorriso,int flag)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 
1033