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