"Fossies" - the Fresh Open Source Software Archive 
Member "libisoburn-1.5.4/xorriso/disk_ops.c" (8 Jul 2020, 62223 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 "disk_ops.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-2019 Thomas Schmitt, <scdbackup@gmx.net>
5
6 Provided under GPL version 2 or later.
7
8 This file contains the implementation of actions on onjects of disk
9 filesystems.
10 */
11
12 #ifdef HAVE_CONFIG_H
13 #include "../config.h"
14 #endif
15
16 #include <ctype.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <sys/stat.h>
23 #include <sys/time.h>
24 #include <time.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <pwd.h>
28 #include <grp.h>
29
30 /* O_BINARY is needed for Cygwin but undefined elsewhere */
31 #ifndef O_BINARY
32 #define O_BINARY 0
33 #endif
34
35
36 #include "xorriso.h"
37 #include "xorriso_private.h"
38 #include "xorrisoburn.h"
39
40
41
42 /* @param flag bit0= simple readlink(): no normalization, no multi-hop
43 bit1= this is potentially a recursion
44 */
45 int Xorriso_resolve_link(struct XorrisO *xorriso, char *link_path,
46 char result_path[SfileadrL], int flag)
47 {
48 ssize_t l;
49 struct stat stbuf;
50 int link_count= 0, ret, show_errno= 0;
51 char *buf= NULL, *dirbuf= NULL, *lpt, *spt;
52 static int link_limit= 100;
53
54 if(flag & 1) {
55 xorriso->resolve_link_rec_count++;
56 if(xorriso->resolve_link_rec_count > xorriso->resolve_link_rec_limit) {
57 Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
58 sprintf(xorriso->info_text, "Too many link recursions before : ");
59 Text_shellsafe(link_path, xorriso->info_text, 1);
60 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, show_errno,
61 "FAILURE", 0);
62 {ret= 0; goto ex;}
63 }
64 } else
65 xorriso->resolve_link_rec_count= 0;
66
67 Xorriso_alloc_meM(buf, char, SfileadrL);
68 Xorriso_alloc_meM(dirbuf, char, SfileadrL);
69
70 if(!(flag&1))
71 if(stat(link_path, &stbuf)==-1)
72 if(errno==ELOOP) {
73 show_errno= errno;
74 goto too_many_hops;
75 }
76 lpt= link_path;
77 while(1) {
78 l= readlink(lpt, buf, SfileadrL-1);
79 if(l==-1) {
80 handle_error:;
81 Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
82 sprintf(xorriso->info_text, "Cannot obtain link target of : ");
83 Text_shellsafe(link_path, xorriso->info_text, 1);
84 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
85 handle_abort:;
86 if(strcmp(lpt, link_path)!=0) {
87 sprintf(xorriso->info_text,
88 "Problem occurred with intermediate path : ");
89 Text_shellsafe(lpt, xorriso->info_text, 1);
90 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
91 }
92 {ret= 0; goto ex;}
93 }
94 buf[l]= 0;
95 if(l==0) {
96 Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
97 sprintf(xorriso->info_text, "Empty link target with : ");
98 Text_shellsafe(link_path, xorriso->info_text, 1);
99 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
100 goto handle_abort;
101 }
102
103 if(flag&1) {
104 strcpy(result_path, buf);
105 {ret= 1; goto ex;}
106 }
107
108 /* normalize relative to disk_path */
109 if(Sfile_str(dirbuf, lpt, 0)<=0)
110 {ret= -1; goto ex;}
111 while(1) {
112 spt= strrchr(dirbuf,'/');
113 if(spt!=NULL) {
114 *spt= 0;
115 if(*(spt+1)!=0)
116 break;
117 } else
118 break;
119 }
120 ret= Xorriso_normalize_img_path(xorriso, dirbuf, buf, result_path, 2|4);
121 if(ret<=0) {
122 goto ex;
123 }
124
125 if(lstat(result_path, &stbuf)==-1) {
126 lpt= result_path;
127 goto handle_error;
128 }
129 if(!S_ISLNK(stbuf.st_mode))
130 break;
131
132 lpt= result_path;
133 link_count++;
134 if(link_count>link_limit) {
135 too_many_hops:;
136 Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
137 sprintf(xorriso->info_text, "Too many link hops with : ");
138 Text_shellsafe(link_path, xorriso->info_text, 1);
139 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, show_errno,
140 "FAILURE", 0);
141 {ret= 0; goto ex;}
142 }
143 }
144 ret= 1;
145 ex:;
146 Xorriso_free_meM(buf);
147 Xorriso_free_meM(dirbuf);
148 if(xorriso->resolve_link_rec_count > 0)
149 xorriso->resolve_link_rec_count--;
150 return(ret);
151 }
152
153
154 int Xorriso_convert_uidstring(struct XorrisO *xorriso, char *uid_string,
155 uid_t *uid, int flag)
156 {
157 double num= 0.0;
158 char text[80];
159 struct passwd *pwd;
160
161 sscanf(uid_string, "%lf", &num);
162 sprintf(text,"%.f",num);
163 if(strcmp(text,uid_string)==0) {
164 *uid= num;
165 return(1);
166 }
167 pwd= getpwnam(uid_string);
168 if(pwd==NULL) {
169 sprintf(xorriso->info_text, "-uid: Not a known user: '%s'", uid_string);
170 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
171 return(0);
172 }
173 *uid= pwd->pw_uid;
174 return(1);
175 }
176
177
178 int Xorriso_convert_gidstring(struct XorrisO *xorriso, char *gid_string,
179 gid_t *gid, int flag)
180 {
181 double num= 0.0;
182 char text[80];
183 struct group *grp;
184
185 sscanf(gid_string, "%lf", &num);
186 sprintf(text,"%.f",num);
187 if(strcmp(text,gid_string)==0) {
188 *gid= num;
189 return(1);
190 }
191 grp= getgrnam(gid_string);
192 if(grp==NULL) {
193 sprintf(xorriso->info_text, "-gid: Not a known group: '%s'", gid_string);
194 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
195 return(0);
196 }
197 *gid= grp->gr_gid;
198 return(1);
199 }
200
201
202 int Xorriso_convert_modstring(struct XorrisO *xorriso, char *cmd, char *mode,
203 mode_t *mode_and, mode_t *mode_or, int flag)
204 {
205 int who_val= 0;
206 char *mpt, *vpt, *opt;
207 unsigned int num= 0;
208 mode_t mode_val,mask;
209
210 *mode_and= ~0;
211 *mode_or= 0;
212 if(mode[0]=='0') {
213 *mode_and= 0;
214 sscanf(mode,"%o",&num);
215 *mode_or= num;
216 } else if(strchr(mode,'+')!=NULL || strchr(mode,'-')!=NULL
217 || strchr(mode,'=')!=NULL) {
218 /* [ugoa][+-][rwxst] */;
219 for(mpt= mode; mpt!=NULL; mpt= strchr(mpt, ',')) {
220 if(*mpt==',')
221 mpt++;
222 if(strlen(mpt)<2)
223 goto unrecognizable;
224 who_val= 0;
225 for(vpt= mpt; *vpt!='+' && *vpt!='-' && *vpt!='='; vpt++) {
226 if(*vpt=='u')
227 who_val|= 4;
228 else if(*vpt=='g')
229 who_val|= 2;
230 else if(*vpt=='o')
231 who_val|= 1;
232 else if(*vpt=='a')
233 who_val|= 7;
234 else
235 goto unrecognizable;
236 }
237 opt= vpt;
238 mode_val= 0;
239 for(vpt= opt+1; *vpt!=0 && *vpt!=','; vpt++) {
240 if(*vpt=='r') {
241 if(who_val&4)
242 mode_val|= S_IRUSR;
243 if(who_val&2)
244 mode_val|= S_IRGRP;
245 if(who_val&1)
246 mode_val|= S_IROTH;
247 } else if(*vpt=='w') {
248 if(who_val&4)
249 mode_val|= S_IWUSR;
250 if(who_val&2)
251 mode_val|= S_IWGRP;
252 if(who_val&1)
253 mode_val|= S_IWOTH;
254 } else if(*vpt=='x') {
255 if(who_val&4)
256 mode_val|= S_IXUSR;
257 if(who_val&2)
258 mode_val|= S_IXGRP;
259 if(who_val&1)
260 mode_val|= S_IXOTH;
261 } else if(*vpt=='s') {
262 if(who_val&4)
263 mode_val|= S_ISUID;
264 if(who_val&2)
265 mode_val|= S_ISGID;
266 } else if(*vpt=='t') {
267 if(who_val&1)
268 mode_val|= S_ISVTX;
269 } else
270 goto unrecognizable;
271 }
272 if(*opt=='+') {
273 (*mode_or)|= mode_val;
274 } else if(*opt=='=') {
275 mask= 0;
276 if(who_val&1)
277 mask|= S_IRWXO|S_ISVTX;
278 if(who_val&2)
279 mask|= S_IRWXG|S_ISGID;
280 if(who_val&4)
281 mask|= S_IRWXU|S_ISUID;
282 (*mode_and)&= ~(mask);
283 (*mode_or)= ((*mode_or) & ~mask) | mode_val;
284 } else if(*opt=='-') {
285 (*mode_or)&= ~mode_val;
286 (*mode_and)&= ~mode_val;
287 }
288 }
289 } else {
290 unrecognizable:;
291 sprintf(xorriso->info_text,
292 "%s: Unrecognizable or faulty permission mode ", cmd);
293 Text_shellsafe(mode, xorriso->info_text, 1);
294 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
295 return(0);
296 }
297 return(1);
298 }
299
300
301 /* @param flag bit0= for Xorriso_msgs_submit: use pager
302 bit1= do not issue warnings
303 */
304 int Xorriso_hop_link(struct XorrisO *xorriso, char *link_path,
305 struct LinkiteM **link_stack, struct stat *stbuf, int flag)
306 {
307 int ret;
308 struct LinkiteM *litm;
309
310 if(*link_stack != NULL) {
311 if(Linkitem_get_link_count(*link_stack, 0) >= xorriso->follow_link_limit) {
312 sprintf(xorriso->info_text,
313 "Too many symbolic links in single tree branch at : ");
314 Text_shellsafe(link_path, xorriso->info_text, 1);
315 if(!(flag&2))
316 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,"WARNING",flag&1);
317 return(0);
318 }
319 }
320 ret= stat(link_path, stbuf);
321 if(ret==-1)
322 return(0);
323 ret= Linkitem_find(*link_stack, stbuf->st_dev, stbuf->st_ino, &litm, 0);
324 if(ret>0) {
325 sprintf(xorriso->info_text, "Detected symbolic link loop around : ");
326 Text_shellsafe(link_path, xorriso->info_text, 1);
327 if(!(flag&2))
328 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", flag&1);
329 return(0);
330 }
331 ret= Linkitem_new(&litm, link_path, stbuf->st_dev, stbuf->st_ino,
332 *link_stack, 0);
333 if(ret<=0) {
334 sprintf(xorriso->info_text,
335 "Cannot add new item to link loop prevention stack");
336 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", flag&1);
337 return(-1);
338 }
339 *link_stack= litm;
340 return(1);
341 }
342
343
344 /* @param flag bit0= do not only sum up sizes but also print subdirs
345 bit1= this is a recursion
346 bit2= do not report result by Xorriso_result()
347 @return <=0 error , 1 ok , 2 could not open directory
348 */
349 int Xorriso_show_dux_subs(struct XorrisO *xorriso,
350 char *abs_path, char *rel_path, off_t *size,
351 off_t boss_mem,
352 struct LinkiteM *link_stack,
353 int flag)
354 {
355 int i, ret, no_sort= 0, filec= 0, l, j, fc, no_dive, is_link;
356 char **filev= NULL, *namept;
357 off_t sub_size, report_size, mem= 0;
358 struct DirseQ *dirseq= NULL;
359 struct stat stbuf;
360 dev_t dir_dev;
361 struct LinkiteM *own_link_stack;
362 char *path= NULL, *show_path= NULL, *name= NULL, *sfe= NULL;
363
364 own_link_stack= link_stack;
365 namept= name;
366 *size= 0;
367
368 Xorriso_alloc_meM(sfe, char, 5 * SfileadrL);
369 Xorriso_alloc_meM(path, char, SfileadrL);
370 Xorriso_alloc_meM(show_path, char, SfileadrL);
371 Xorriso_alloc_meM(name, char, SfileadrL);
372
373 if(lstat(abs_path, &stbuf)==-1)
374 {ret= 2; goto ex;}
375 dir_dev= stbuf.st_dev;
376 if(S_ISLNK(stbuf.st_mode)) {
377 if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&2))))
378 {ret= 2; goto ex;}
379 if(stat(abs_path, &stbuf)==-1)
380 {ret= 2; goto ex;}
381 if(dir_dev != stbuf.st_dev &&
382 !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&2))))
383 {ret= 2; goto ex;}
384 }
385 ret= Dirseq_new(&dirseq, abs_path, 1);
386 if(ret<0) {
387 sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
388 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
389 {ret= -1; goto ex;}
390 }
391 if(ret==0)
392 {ret= 2; goto ex;}
393
394 while(1) {
395 Linkitem_reset_stack(&own_link_stack, link_stack, 0);
396 ret= Dirseq_next_adr(dirseq,name,0);
397 if(ret<0)
398 goto ex;
399 if(ret==0)
400 break;
401
402 sub_size= 0;
403 strcpy(show_path, rel_path);
404 if(Sfile_add_to_path(show_path, name, 0)<=0)
405 goto much_too_long;
406
407 strcpy(path, abs_path);
408 if(Sfile_add_to_path(path, name, 0)<=0) {
409 much_too_long:;
410 Xorriso_much_too_long(xorriso, strlen(path)+strlen(name)+1, 2);
411 {ret= -1; goto ex;}
412 }
413 no_dive= 0;
414
415 ret= lstat(path, &stbuf);
416 if(ret==-1)
417 continue;
418 is_link= S_ISLNK(stbuf.st_mode);
419 if(is_link && xorriso->do_follow_links) {
420 ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1);
421 if(ret<0)
422 {ret= -1; goto ex;}
423 if(ret!=1)
424 no_dive= 1;
425 }
426 if(!S_ISDIR(stbuf.st_mode))
427 no_dive= 1;
428 if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
429 no_dive= 1;
430 if(!no_dive) {
431 filec++;
432 l= strlen(rel_path)+1;
433 mem+= l;
434 if(l % sizeof(char *))
435 mem+= sizeof(char *)-(l % sizeof(char *));
436 if(flag&1) /* diving and counting is done further below */
437 continue;
438 ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size, boss_mem,
439 own_link_stack,2);
440 if(ret<0)
441 goto ex;
442 if(ret==0)
443 continue;
444 }
445
446 /*
447 sub_size+= stbuf.st_size+strlen(name)+1;
448 */
449 sub_size+= stbuf.st_size+2048;
450 if(sub_size>0)
451 (*size)+= sub_size;
452 }
453
454 if(filec<=0 || !(flag&1))
455 {ret= 1; goto ex;}
456
457 /* Try to get a sorted list of directory names */
458 mem+= (filec+1)*sizeof(char *);
459 ret= Xorriso_check_temp_mem_limit(xorriso, mem+boss_mem, 2);
460 if(ret<0)
461 goto ex;
462 Dirseq_rewind(dirseq, 0);
463 if(ret==0) {
464 no_sort_possible:;
465 no_sort= 1;
466 } else {
467 filev= (char **) calloc(filec+1, sizeof(char *));
468 if(filev==NULL)
469 goto no_sort_possible;
470 else {
471 for(i= 0; i<filec; i++)
472 filev[i]= NULL;
473 fc= 0;
474 while(1) {
475 ret= Dirseq_next_adr(dirseq,name,0);
476 if(ret<0)
477 goto ex;
478 if(ret==0)
479 break;
480 strcpy(path, abs_path);
481 if(Sfile_add_to_path(path, name, 0)<=0)
482 goto much_too_long;
483
484 ret= lstat(path,&stbuf);
485 if(ret==-1)
486 continue;
487 is_link= S_ISLNK(stbuf.st_mode);
488 if(is_link && xorriso->do_follow_links) {
489 ret= stat(path,&stbuf);
490 if(ret==-1)
491 continue;
492 }
493 if(!S_ISDIR(stbuf.st_mode))
494 continue;
495 if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
496 continue;
497
498 if(fc>=filec) { /* Number of files changed (or programming error) */
499 revoke_sorting:;
500 for(j=0; j<fc; j++)
501 free((char *) filev[j]);
502 free((char *) filev);
503 filev= NULL;
504 goto no_sort_possible;
505 }
506
507 filev[fc]= strdup(name);
508 if(filev[fc]==NULL)
509 goto revoke_sorting;
510 fc++;
511 }
512 filec= fc;
513 if(filec>1)
514 Sort_argv(filec, filev, 0);
515 }
516 }
517
518 for(i= 0; (no_sort || i<filec) && !(xorriso->request_to_abort); i++) {
519 Linkitem_reset_stack(&own_link_stack, link_stack, 0);
520 if(no_sort) {
521 ret= Dirseq_next_adr(dirseq,name,0);
522 if(ret<0)
523 goto ex;
524 if(ret==0)
525 break;
526 } else
527 namept= filev[i];
528
529 sub_size= 0;
530 strcpy(show_path, rel_path);
531 if(Sfile_add_to_path(show_path, namept, 0)<=0)
532 goto much_too_long;
533 strcpy(path, abs_path);
534 if(Sfile_add_to_path(path, namept, 0)<=0)
535 goto much_too_long;
536 no_dive= 0;
537
538 ret= lstat(path,&stbuf);
539 if(ret==-1)
540 continue;
541 is_link= S_ISLNK(stbuf.st_mode);
542 if(is_link && xorriso->do_follow_links) {
543 ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1);
544 if(ret<0)
545 {ret= -1; goto ex;}
546 if(ret!=1)
547 continue;
548 }
549 if(!S_ISDIR(stbuf.st_mode))
550 continue;
551 if(dir_dev == stbuf.st_dev || xorriso->do_follow_mount) {
552 ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size,
553 boss_mem+mem, own_link_stack, 2|(flag&1));
554 if(ret<0)
555 goto ex;
556 }
557
558 /*
559 sub_size+= stbuf.st_size+strlen(namept)+1;
560 */
561 sub_size+= stbuf.st_size+2048;
562 if(sub_size>0)
563 (*size)+= sub_size;
564 report_size= sub_size/1024;
565 if(report_size*1024<sub_size)
566 report_size++;
567 if(!(flag & 4)) {
568 if(xorriso->sh_style_result)
569 sprintf(xorriso->result_line, "%-7.f ",(double) (report_size));
570 else
571 sprintf(xorriso->result_line, "%7.f ",(double) (report_size));
572 sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n",
573 Xorriso_esc_filepath(xorriso,show_path, sfe, 0));
574 Xorriso_result(xorriso, 0);
575 }
576 }
577
578 ret= 1;
579 ex:;
580 Xorriso_free_meM(sfe);
581 Xorriso_free_meM(path);
582 Xorriso_free_meM(show_path);
583 Xorriso_free_meM(name);
584 Linkitem_reset_stack(&own_link_stack, link_stack, 0);
585 Dirseq_destroy(&dirseq, 0);
586 if(filev!=NULL) {
587 for(i=0; i<filec; i++)
588 if(filev[i]!=NULL)
589 free((char *) filev[i]);
590 free((char *) filev);
591 }
592 return(ret);
593 }
594
595
596 /* @param flag bit1= add '+' to perms
597 bit2-7: hidden_state :
598 bit2= hide in ISO/RR
599 bit3= hide in Joliet
600 bit4= hide in HFS+
601 */
602 int Xorriso__mode_to_perms(mode_t st_mode, char perms[11], int flag)
603 {
604 int hidden_state;
605
606 strcpy(perms,"--------- ");
607 if(st_mode&S_IRUSR) perms[0]= 'r';
608 if(st_mode&S_IWUSR) perms[1]= 'w';
609 if(st_mode&S_IXUSR) perms[2]= 'x';
610 if(st_mode&S_ISUID) {
611 if(st_mode&S_IXUSR)
612 perms[2]= 's';
613 else
614 perms[2]= 'S';
615 }
616 if(st_mode&S_IRGRP) perms[3]= 'r';
617 if(st_mode&S_IWGRP) perms[4]= 'w';
618 if(st_mode&S_IXGRP) perms[5]= 'x';
619 if(st_mode&S_ISGID) {
620 if(st_mode&S_IXGRP)
621 perms[5]= 's';
622 else
623 perms[5]= 'S';
624 }
625 if(st_mode&S_IROTH) perms[6]= 'r';
626 if(st_mode&S_IWOTH) perms[7]= 'w';
627 if(st_mode&S_IXOTH) perms[8]= 'x';
628 if(st_mode&S_ISVTX) {
629 if(st_mode&S_IXOTH)
630 perms[8]= 't';
631 else
632 perms[8]= 'T';
633 }
634
635 hidden_state= (flag >> 2) & 63;
636 if(hidden_state == 1)
637 perms[9]= 'I';
638 else if(hidden_state == 2)
639 perms[9]= 'J';
640 else if(hidden_state == 4)
641 perms[9]= 'A';
642 else if(hidden_state)
643 perms[9]= 'H';
644 if(flag & 2) {
645 if(hidden_state)
646 perms[9]= tolower(perms[9]);
647 else
648 perms[9]= '+';
649 }
650 return(1);
651 }
652
653
654 /* @param flag bit0= recognize Xorriso_IFBOOT as file type
655 bit1= add '+' to perms
656 bit2-7: hidden_state :
657 bit2= hide in ISO/RR
658 bit3= hide in Joliet
659 bit4= hide in HFS+
660 */
661 int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag)
662 {
663 int show_major_minor= 0, high_shift= 0, high_mask= 0;
664 char *rpt, perms[11], mm_text[80];
665 mode_t st_mode;
666 dev_t dev, major, minor;
667
668 rpt= xorriso->result_line;
669 rpt[0]= 0;
670 st_mode= stbuf->st_mode;
671
672 if(S_ISDIR(st_mode))
673 strcat(rpt, "d");
674 else if(S_ISREG(st_mode)) {
675 strcat(rpt, "-");
676 } else if(S_ISLNK(st_mode))
677 strcat(rpt, "l");
678 else if(S_ISBLK(st_mode)) {
679 strcat(rpt, "b");
680 show_major_minor= 1;
681 } else if(S_ISCHR(st_mode)) {
682 strcat(rpt, "c");
683 show_major_minor= 1;
684 } else if(S_ISFIFO(st_mode))
685 strcat(rpt, "p");
686 else if(S_ISSOCK(st_mode))
687 strcat(rpt, "s");
688 else if((flag & 1) && (st_mode & S_IFMT) == Xorriso_IFBOOT)
689 strcat(rpt, "e");
690 else
691 strcat(rpt, "?");
692
693 Xorriso__mode_to_perms(st_mode, perms, flag & (2 | 252));
694 strcat(rpt, perms);
695
696 sprintf(rpt+strlen(rpt)," %3u ",(unsigned int) stbuf->st_nlink);
697
698 sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_uid);
699 sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_gid);
700 if(show_major_minor) {
701 dev= stbuf->st_rdev;
702
703 /* according to /usr/include/sys/sysmacros.h : gnu_dev_major(),_minor()
704 >>> but this looks as if it should go to some system dependency
705 >>> in FreeBSD dev_t is 32 bit
706 */
707 if(sizeof(dev_t) > 4) {
708 high_shift= 32;
709 high_mask= ~0xfff;
710 }
711 major= (((dev >> 8) & 0xfff) |
712 ((unsigned int) (dev >> high_shift) & high_mask))
713 & 0xffffffff;
714 minor= (((dev & 0xff) | ((unsigned int) (dev >> 12) & ~0xff))) & 0xffffffff;
715
716 sprintf(mm_text, "%u,%u", (unsigned int) major, (unsigned int) minor);
717 sprintf(rpt+strlen(rpt), "%8s ", mm_text);
718 } else
719 sprintf(rpt+strlen(rpt), "%8.f ", (double) stbuf->st_size);
720
721 Ftimetxt(stbuf->st_mtime, rpt+strlen(rpt), 0);
722 strcat(rpt, " ");
723
724 return(1);
725 }
726
727
728 struct DirentrY {
729 char *adr;
730 struct DirentrY *next;
731 };
732
733
734 int Xorriso_sorted_dir_x(struct XorrisO *xorriso, char *dir_path,
735 int *filec, char ***filev, off_t boss_mem, int flag)
736 {
737 int count= 0, ret;
738 char *name= NULL;
739 struct DirseQ *dirseq= NULL;
740 off_t mem;
741 struct DirentrY *last= NULL, *current= NULL;
742
743 Xorriso_alloc_meM(name, char, SfileadrL);
744
745 *filec= 0;
746 *filev= NULL;
747 mem= boss_mem;
748 ret= Dirseq_new(&dirseq, dir_path, 1);
749 if(ret<=0)
750 goto ex;
751 while(1) { /* loop over directory content */
752 ret= Dirseq_next_adr(dirseq,name,0);
753 if(ret==0)
754 break;
755 if(ret<0)
756 goto ex;
757 mem+= strlen(name)+8+sizeof(struct DirentrY)+sizeof(char *);
758 if(mem>xorriso->temp_mem_limit)
759 {ret= 0; goto ex;}
760
761 current= (struct DirentrY *) calloc(1, sizeof(struct DirentrY));
762 if(current==NULL) {
763 Xorriso_no_malloc_memory(xorriso, NULL, 0);
764 {ret= -1; goto ex;}
765 }
766 current->adr= NULL;
767 current->next= last;
768 last= current;
769 last->adr= strdup(name);
770 if(last->adr==NULL) {
771 Xorriso_no_malloc_memory(xorriso, NULL, 0);
772 {ret= -1; goto ex;}
773 }
774 count++;
775 }
776 *filec= count;
777 if(count==0)
778 {ret= 1; goto ex;}
779 (*filev)= (char **) calloc(count, sizeof(char *));
780 if(*filev==NULL) {
781 Xorriso_no_malloc_memory(xorriso, NULL, 0);
782 {ret= -1; goto ex; }
783 }
784 count= 0;
785 for(current= last; current!=NULL; current= last) {
786 last= current->next;
787 (*filev)[count++]= current->adr;
788 free((char *) current);
789 }
790 Sort_argv(*filec, *filev, 0);
791 ret= 1;
792 ex:;
793 for(current= last; current!=NULL; current= last) {
794 last= current->next;
795 free(current->adr);
796 free((char *) current);
797 }
798 Xorriso_free_meM(name);
799 Dirseq_destroy(&dirseq, 0);
800 return(ret);
801 }
802
803
804 /* @param flag bit0= long format
805 bit1= do not print count of nodes
806 bit2= du format
807 bit3= print directories as themselves (ls -d)
808 */
809 int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd,
810 int filec, char **filev, off_t boss_mem, int flag)
811 {
812 int i, ret, was_error= 0, dfilec= 0, pass, passes;
813 char *path= NULL, *acl_text= NULL;
814 char *rpt, *link_target= NULL, **dfilev= NULL;
815 off_t size;
816 struct stat stbuf;
817
818 Xorriso_alloc_meM(path, char, SfileadrL);
819 Xorriso_alloc_meM(link_target, char, SfileadrL);
820
821 rpt= xorriso->result_line;
822
823 Sort_argv(filec, filev, 0);
824
825 /* Count valid nodes, warn of invalid ones */
826 for(i= 0; i<filec; i++) {
827 ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4|8);
828 if(ret<=0) {
829 was_error++;
830 continue;
831 }
832 ret= lstat(path, &stbuf);
833 if(ret==-1) {
834 sprintf(xorriso->info_text, "Not found in local filesystem: ");
835 Text_shellsafe(path, xorriso->info_text, 1);
836 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 1);
837 was_error++;
838 continue;
839 }
840 }
841
842 if((flag&8) && !(flag&(2|4))) {
843 sprintf(xorriso->info_text,"Valid local files found: %d\n",filec-was_error);
844 Xorriso_info(xorriso,1);
845 if(filec-was_error<=0)
846 {ret= !was_error; goto ex;}
847 }
848
849 passes= 1+!(flag&(4|8));
850 for(pass= 0; pass<passes; pass++)
851 for(i= 0; i<filec && !(xorriso->request_to_abort); i++) {
852 ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4);
853 if(ret<=0)
854 continue;
855 ret= lstat(path, &stbuf);
856 if(ret==-1)
857 continue;
858 if(S_ISLNK(stbuf.st_mode) &&
859 (xorriso->do_follow_links || xorriso->do_follow_param)) {
860 ret= stat(path, &stbuf);
861 if(ret==-1)
862 ret= lstat(path, &stbuf);
863 if(ret==-1)
864 continue;
865 }
866 if(S_ISDIR(stbuf.st_mode) && !(flag&(4|8))) {
867 if(pass==0)
868 continue;
869 if(filec>1) {
870 strcpy(xorriso->result_line, "\n");
871 Xorriso_result(xorriso,0);
872 Xorriso_esc_filepath(xorriso,filev[i], xorriso->result_line, 0);
873 strcat(xorriso->result_line, ":\n");
874 Xorriso_result(xorriso,0);
875 }
876 ret= Xorriso_sorted_dir_x(xorriso, path, &dfilec, &dfilev, boss_mem, 0);
877 if(ret<=0) {
878
879 /* >>> DirseQ loop and single item Xorriso_lsx_filev() */;
880
881 } else {
882 if(flag&1) {
883 sprintf(xorriso->result_line, "total %d\n", dfilec);
884 Xorriso_result(xorriso,0);
885 }
886 Xorriso_lsx_filev(xorriso, path,
887 dfilec, dfilev, boss_mem, (flag&1)|2|8);
888 }
889 if(dfilec>0)
890 Sfile_destroy_argv(&dfilec, &dfilev, 0);
891 continue;
892 } else
893 if(pass>0)
894 continue;
895 link_target[0]= 0;
896 rpt[0]= 0;
897 if((flag&5)==1) {
898 Xorriso_local_getfacl(xorriso, path, &acl_text, 16);
899 ret= Xorriso_format_ls_l(xorriso, &stbuf, (acl_text != NULL) << 1);
900 Xorriso_local_getfacl(xorriso, path, &acl_text, 1 << 15);
901 if(ret<=0)
902 continue;
903 if(S_ISLNK(stbuf.st_mode)) {
904 ret= Xorriso_resolve_link(xorriso, path, link_target, 1);
905 if(ret<=0)
906 link_target[0]= 0;
907 }
908 } else if(flag&4) { /* -dux or -dusx */
909 size= stbuf.st_size;
910 if(S_ISDIR(stbuf.st_mode)) {
911 ret= Xorriso_show_dux_subs(xorriso, path, filev[i], &size, boss_mem,
912 NULL, flag&1);
913 if(ret<0)
914 {ret= -1; goto ex;}
915 if(ret==0)
916 continue;
917 }
918 if(xorriso->sh_style_result)
919 sprintf(rpt, "%-7.f ",(double) (size/1024));
920 else
921 sprintf(rpt, "%7.f ",(double) (size/1024));
922 }
923 if(link_target[0]) {
924 Xorriso_esc_filepath(xorriso,filev[i], xorriso->result_line, 1);
925 strcat(xorriso->result_line, " -> ");
926 Xorriso_esc_filepath(xorriso,link_target, xorriso->result_line, 1 | 2);
927 } else {
928 Xorriso_esc_filepath(xorriso,filev[i], xorriso->result_line, 1);
929 }
930 strcat(xorriso->result_line, "\n");
931 Xorriso_result(xorriso, 0);
932 }
933 ret= !was_error;
934 ex:;
935 Xorriso_free_meM(path);
936 Xorriso_free_meM(link_target);
937 return(ret);
938 }
939
940
941 /*
942 @param flag >>> bit0= remove whole sub tree: rm -r
943 bit1= remove empty directory: rmdir
944 bit2= recursion: do not reassure in mode 2 "tree"
945 bit3= this is for overwriting and not for plain removal
946 bit4= count deleted files in xorriso->pacifier_count
947 bit5= with bit0 only remove directory content, not the directory
948 bit6= permission to call Xorriso_make_accessible()
949 @return <=0 = error
950 1 = removed leaf file object
951 2 = removed directory or tree
952 3 = did not remove on user revocation
953 */
954 int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag)
955 {
956 int ret, is_dir= 0, made_accessible= 0;
957 struct stat victim_stbuf;
958 struct DirseQ *dirseq= NULL;
959 char *sfe= NULL, *sub_path= NULL;
960 struct PermiteM *perm_stack_mem;
961
962 perm_stack_mem= xorriso->perm_stack;
963
964 /* Avoiding large local memory objects in order to save stack space */
965 sfe= malloc(5*SfileadrL);
966 sub_path= malloc(2*SfileadrL);
967 if(sfe==NULL || sub_path==NULL) {
968 Xorriso_no_malloc_memory(xorriso, &sfe, 0);
969 {ret= -1; goto ex;}
970 }
971
972 if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0)
973 {ret= 0; goto ex;}
974
975 ret= lstat(path, &victim_stbuf);
976 if(ret==-1) {
977 if((flag & 64) && errno == EACCES) {
978 ret= Xorriso_make_accessible(xorriso, path, 0);
979 if(ret < 0)
980 goto ex;
981 made_accessible= 1;
982 ret= lstat(path, &victim_stbuf);
983 }
984 if(ret==-1) {
985 sprintf(xorriso->info_text, "Cannot lstat(%s)",
986 Text_shellsafe(path, sfe, 0));
987 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
988 {ret= 0; goto ex;}
989 }
990 }
991 if(strcmp(path, "/")==0) {
992 sprintf(xorriso->info_text, "May not delete root directory");
993 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
994 {ret= 0; goto ex;}
995 }
996 if(S_ISDIR(victim_stbuf.st_mode))
997 is_dir= 1;
998 if(!is_dir) {
999 if(flag&2) { /* rmdir */
1000 sprintf(xorriso->info_text, "%s in disk filesystem is not a directory",
1001 Text_shellsafe(path, sfe, 0));
1002 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1003 ret= 0; goto ex;
1004 }
1005 } else {
1006 if(flag&1) { /* rm -r */
1007
1008 #ifdef Osirrox_not_yeT
1009 /* >>> */
1010
1011 struct stat *victim_node= NULL;
1012
1013 victim_node= &victim_stbuf;
1014
1015 if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) ||
1016 (flag&32)) {
1017 /* Iterate over subordinates and delete them */
1018 mem= boss_mem;
1019
1020 ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem,
1021 &iter, &node_array, &node_count, &node_idx,
1022 &node, 1|2);
1023 if(ret<=0) {
1024 cannot_create_iter:;
1025 Xorriso_cannot_create_iter(xorriso, ret, 0);
1026 ret= -1; goto ex;
1027 }
1028 pl= strlen(path);
1029 strcpy(sub_path, path);
1030 if(pl==0 || sub_path[pl-1]!='/') {
1031 sub_path[pl++]= '/';
1032 sub_path[pl]= 0;
1033 }
1034 sub_name= sub_path+pl;
1035 while(1) {
1036 ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter,
1037 &node_array, &node_count, &node_idx, &node, 0);
1038 if(ret<0)
1039 goto ex;
1040 if(ret==0 || xorriso->request_to_abort)
1041 break;
1042 name= (char *) iso_node_get_name(node);
1043 if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0)
1044 {ret= 0; goto rm_r_problem_handler;}
1045 strcpy(sub_name, name);
1046 ret= Xorriso_rmi(xorriso, iter, mem, sub_path, (flag&(1|2|8|16))|4);
1047 if(ret==3 || ret<=0 || xorriso->request_to_abort) {
1048 rm_r_problem_handler:;
1049 not_removed= 1;
1050 fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
1051 if(fret<0)
1052 goto dir_not_removed;
1053 }
1054 }
1055 if(flag&32)
1056 {ret= 2; goto ex;}
1057
1058 if(not_removed) {
1059 dir_not_removed:;
1060 sprintf(xorriso->info_text, "Directory not removed: %s",
1061 Text_shellsafe(path, sfe, 0));
1062 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1063 if(ret>0)
1064 ret= 3;
1065 goto ex;
1066 }
1067 }
1068
1069 #else /* Osirrox_not_yeT */
1070
1071 sprintf(xorriso->info_text, "-rm_rx is not implemented yet");
1072 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1073 ret= 0; goto ex;
1074
1075 #endif /* !Osirrox_not_yeT */
1076
1077 } else {
1078 if(!(flag&2)) { /* not rmdir */
1079 sprintf(xorriso->info_text, "%s in disk filesystem is a directory",
1080 Text_shellsafe(path, sfe, 0));
1081 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1082 ret= 0; goto ex;
1083 }
1084 ret= Dirseq_new(&dirseq, path, 1);
1085 if(ret>0) {
1086 ret= Dirseq_next_adr(dirseq, sfe, 0);
1087 if(ret>0) {
1088 sprintf(xorriso->info_text,
1089 "Directory not empty on attempt to delete: %s",
1090 Text_shellsafe(path, sfe, 0));
1091 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1092 ret= 0; goto ex;
1093 }
1094 }
1095 }
1096 }
1097 if(xorriso->request_to_abort)
1098 {ret= 3; goto ex;}
1099 ret= Xorriso_reassure_restore(xorriso, path, (flag&(4|8)) | !!is_dir);
1100 if(ret<=0 || ret==3)
1101 goto ex;
1102 if(is_dir)
1103 ret= rmdir(path);
1104 else
1105 ret= unlink(path);
1106 if(ret == -1) {
1107 if((flag & 64) && errno == EACCES && !made_accessible) {
1108 ret= Xorriso_make_accessible(xorriso, path, 0);
1109 if(ret < 0)
1110 goto ex;
1111 made_accessible= 1;
1112 if(is_dir)
1113 ret= rmdir(path);
1114 else
1115 ret= unlink(path);
1116 }
1117 if(ret == -1) {
1118 sprintf(xorriso->info_text, "Cannot delete from disk filesystem %s",
1119 Text_shellsafe(path, sfe, 0));
1120 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
1121 ret= -1; goto ex;
1122 }
1123 }
1124 if(flag&16)
1125 xorriso->pacifier_count++;
1126 ret= 1+!!is_dir;
1127 ex:;
1128 if(made_accessible)
1129 Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
1130 if(sfe!=NULL)
1131 free(sfe);
1132 if(sub_path!=NULL)
1133 free(sub_path);
1134 Dirseq_destroy(&dirseq, 0);
1135 return(ret);
1136 }
1137
1138
1139 /* @param flag bit0= recursion
1140 */
1141 int Xorriso_findx_action(struct XorrisO *xorriso, struct FindjoB *job,
1142 char *abs_path, char *show_path, int depth, int flag)
1143 {
1144 int ret= 0, type, action= 0, dpl= 0, compare_result, uret;
1145 uid_t user= 0;
1146 gid_t group= 0;
1147 time_t date= 0;
1148 mode_t mode_or= 0, mode_and= ~1;
1149 char *target, *text_2, *wdi_mem= NULL, *disk_prefix, *iso_path= NULL;
1150 char *basename;
1151 struct FindjoB *subjob;
1152 struct stat stbuf;
1153
1154 Xorriso_alloc_meM(iso_path, char, SfileadrL);
1155
1156 action= Findjob_get_action_parms(job, &target, &text_2, &user, &group,
1157 &mode_and, &mode_or, &type, &date, &subjob, 0);
1158 if(action<0)
1159 action= 0;
1160 if(action==15 || action==16 || action==18 || action==19 || action==20) {
1161 /* in_iso , not_in_iso, add_missing , empty_iso_dir , is_full_in_iso */
1162 Findjob_get_start_path(job, &disk_prefix, 0);
1163 if(strncmp(abs_path, disk_prefix, strlen(disk_prefix))!=0)
1164 {ret= -1; goto ex;}
1165 dpl= strlen(disk_prefix);
1166 if(strlen(target)+strlen(abs_path)-dpl >= SfileadrL)
1167 {ret= -1; goto ex;}
1168 if(abs_path[dpl]=='/')
1169 dpl++;
1170 ret= Xorriso_make_abs_adr(xorriso, target, abs_path+dpl, iso_path, 4);
1171 if(ret<=0)
1172 {goto ex;}
1173
1174 }
1175 if(action==15) { /* in_iso */
1176 ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
1177 if(ret<0)
1178 {ret= 1; goto ex;}
1179 Text_shellsafe(show_path, xorriso->result_line, 0);
1180 strcat(xorriso->result_line, "\n");
1181 Xorriso_result(xorriso, 0);
1182 ret= 1;
1183 } else if(action==16) { /* not_in_iso */
1184 ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl,
1185 &compare_result, 4);
1186 if(ret<xorriso->find_compare_result)
1187 xorriso->find_compare_result= ret;
1188 if(ret>=0)
1189 ret= 1;
1190 } else if(action==18) { /* add_missing */
1191 ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl,
1192 &compare_result, 4|(1u<<31));
1193 if(ret<xorriso->find_compare_result)
1194 xorriso->find_compare_result= ret;
1195 if(ret==0) {
1196 uret= Xorriso_update_interpreter(xorriso, NULL, NULL, compare_result,
1197 abs_path, iso_path, ((flag&1)<<2) | 2);
1198 if(uret<=0)
1199 ret= 0;
1200 }
1201 if(ret>=0)
1202 ret= 1;
1203 } else if(action==19) { /* empty_iso_dir */
1204 ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
1205 if(ret<0)
1206 {ret= 1; goto ex;}
1207 if(!S_ISDIR(stbuf.st_mode))
1208 {ret= 1; goto ex;}
1209 ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, iso_path, 1|32);
1210 if(ret>0) {
1211 sprintf(xorriso->info_text, "Emptied directory ");
1212 Text_shellsafe(iso_path, xorriso->info_text, 1);
1213 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
1214 }
1215 } else if(action==20) { /* is_full_in_iso */
1216 ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
1217 if(ret<0)
1218 {ret= 1; goto ex;}
1219 if(!S_ISDIR(stbuf.st_mode))
1220 {ret= 1; goto ex;}
1221 wdi_mem= strdup(xorriso->wdi);
1222 if(wdi_mem == NULL) {
1223 Xorriso_no_malloc_memory(xorriso, NULL, 0);
1224 {ret= -1; goto ex;}
1225 }
1226 strcpy(xorriso->wdi, iso_path);
1227 ret= Xorriso_ls(xorriso, 4|8);
1228 strcpy(xorriso->wdi, wdi_mem);
1229 if(ret>0) {
1230 strcpy(xorriso->result_line, "d ");
1231 Text_shellsafe(iso_path, xorriso->result_line, 1);
1232 strcat(xorriso->result_line,
1233 " (ISO) : non-empty directory (would not match mount point)\n");
1234 Xorriso_result(xorriso,0);
1235 }
1236 {ret= 1; goto ex;}
1237 } else if(action == 40) { /* estimate_size */
1238 basename= strrchr(abs_path, '/');
1239 if(basename != NULL)
1240 basename++;
1241 else
1242 basename= abs_path;
1243 ret= lstat(abs_path, &stbuf);
1244 if(ret != -1)
1245 ret= Xorriso_estimate_file_size(xorriso, job, basename, stbuf.st_mode,
1246 stbuf.st_size, 0);
1247 } else if(action == 44) { /* list_extattr */
1248 ret= Xorriso_list_extattr(xorriso, NULL, abs_path, show_path, target, 2);
1249 } else {
1250 Xorriso_esc_filepath(xorriso,show_path, xorriso->result_line, 0);
1251 strcat(xorriso->result_line, "\n");
1252 Xorriso_result(xorriso, 0);
1253 ret= 1;
1254 }
1255 ex:;
1256 if(action==15 || action==16 || action==18 || action==19 || action==20)
1257 if(xorriso->no_volset_present)
1258 xorriso->request_to_abort= 1; /* Need an image. No use to try again. */
1259 if(wdi_mem != NULL)
1260 free(wdi_mem);
1261 Xorriso_free_meM(iso_path);
1262 return(ret);
1263 }
1264
1265
1266 /* @param flag bit0=recursion
1267 */
1268 int Xorriso_findx(struct XorrisO *xorriso, struct FindjoB *job,
1269 char *abs_dir_parm, char *dir_path,
1270 struct stat *dir_stbuf, int depth,
1271 struct LinkiteM *link_stack, int flag)
1272 {
1273 int ret,is_link, no_dive;
1274 struct DirseQ *dirseq= NULL;
1275 struct stat stbuf;
1276 struct LinkiteM *own_link_stack;
1277 char *abs_dir_path, *namept;
1278 char *name= NULL, *path= NULL, *sfe= NULL;
1279 char *abs_dir_path_data= NULL, *abs_path= NULL;
1280
1281 job->depth= depth;
1282
1283 if(xorriso->request_to_abort)
1284 {ret= 0; goto ex;}
1285
1286 Xorriso_alloc_meM(sfe, char, 5*SfileadrL);
1287 Xorriso_alloc_meM(name, char, SfileadrL);
1288 Xorriso_alloc_meM(path, char, SfileadrL);
1289 Xorriso_alloc_meM(abs_dir_path_data, char, SfileadrL);
1290 Xorriso_alloc_meM(abs_path, char, SfileadrL);
1291
1292 own_link_stack= link_stack;
1293 abs_dir_path= abs_dir_parm;
1294 if(abs_dir_path[0]==0) {
1295 ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, dir_path,
1296 abs_dir_path_data, 1|2|8);
1297 if(ret<=0)
1298 goto ex;
1299 abs_dir_path= abs_dir_path_data;
1300 ret= Xorriso_path_is_excluded(xorriso, abs_dir_path, !(flag&1));
1301 if(ret<0)
1302 goto ex;
1303 if(ret>0)
1304 {ret= 0; goto ex;}
1305 ret= lstat(abs_dir_path, dir_stbuf);
1306 if(ret==-1)
1307 {ret= 0; goto ex;}
1308 if(S_ISLNK(dir_stbuf->st_mode) &&
1309 (xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
1310 if(stat(abs_dir_path, &stbuf)!=-1)
1311 if(dir_stbuf->st_dev == stbuf.st_dev ||
1312 (xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1))))
1313 memcpy(dir_stbuf, &stbuf, sizeof(struct stat));
1314
1315 namept= strrchr(dir_path, '/');
1316 if(namept==NULL)
1317 namept= dir_path;
1318 else
1319 namept++;
1320
1321 ret= Findjob_test_2(xorriso, job, NULL, namept, dir_path, NULL, dir_stbuf,
1322 0);
1323 if(ret<0)
1324 goto ex;
1325 if(ret>0) {
1326 ret= Xorriso_findx_action(xorriso, job, abs_dir_path, dir_path, depth,
1327 flag&1);
1328 if(xorriso->request_to_abort)
1329 {ret= 0; goto ex;}
1330 if(ret<=0) {
1331 if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
1332 goto ex;
1333 }
1334 }
1335 }
1336 if(xorriso->request_to_abort)
1337 {ret= 1; goto ex;}
1338 if(!S_ISDIR(dir_stbuf->st_mode))
1339 {ret= 2; goto ex;}
1340
1341 ret= Dirseq_new(&dirseq, abs_dir_path, 1);
1342 if(ret<0) {
1343 sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
1344 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
1345 {ret= -1; goto ex;}
1346 }
1347 if(ret==0)
1348 {ret= 2; goto ex;}
1349
1350 job->depth++;
1351 while(!xorriso->request_to_abort) {
1352 Linkitem_reset_stack(&own_link_stack, link_stack, 0);
1353 ret= Dirseq_next_adr(dirseq,name,0);
1354 if(ret==0)
1355 break;
1356 if(ret<0) {
1357 sprintf(xorriso->info_text,"Failed to obtain next directory entry");
1358 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
1359 {ret= -1; goto ex;}
1360 }
1361 ret= Xorriso_make_abs_adr(xorriso, abs_dir_path, name, abs_path, 1);
1362 if(ret<=0)
1363 goto ex;
1364 ret= Xorriso_make_abs_adr(xorriso, dir_path, name, path, 4);
1365 if(ret<=0)
1366 goto ex;
1367 ret= Xorriso_path_is_excluded(xorriso, abs_path, 0); /* (is never param) */
1368 if(ret<0)
1369 goto ex;
1370 if(ret>0)
1371 continue;
1372 ret= lstat(abs_path, &stbuf);
1373 if(ret==-1)
1374 continue;
1375 no_dive= 0;
1376
1377 is_link= S_ISLNK(stbuf.st_mode);
1378 if(is_link && xorriso->do_follow_links) {
1379 ret= Xorriso_hop_link(xorriso, abs_path, &own_link_stack, &stbuf, 2);
1380 if(ret<0)
1381 {ret= -1; goto ex;}
1382 if(ret!=1)
1383 no_dive= 1;
1384 }
1385
1386 ret= Findjob_test_2(xorriso, job, NULL, name, path, dir_stbuf, &stbuf, 0);
1387 if(ret<0)
1388 goto ex;
1389 if(ret>0) {
1390 ret= Xorriso_findx_action(xorriso, job, abs_path, path, depth, flag&1);
1391 if(xorriso->request_to_abort)
1392 {ret= 0; goto ex;}
1393 if(ret<=0) {
1394 if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
1395 goto ex;
1396 }
1397 }
1398 if(!S_ISDIR(stbuf.st_mode))
1399 no_dive= 1;
1400 if(dir_stbuf->st_dev != stbuf.st_dev && !xorriso->do_follow_mount)
1401 no_dive= 1;
1402 if(!no_dive) {
1403 ret= Xorriso_findx(xorriso, job, abs_path, path, &stbuf, depth+1,
1404 own_link_stack, flag|1);
1405 if(ret<0)
1406 goto ex;
1407 }
1408 }
1409
1410 ret= 1;
1411 ex:;
1412 job->depth= depth;
1413 Xorriso_free_meM(sfe);
1414 Xorriso_free_meM(name);
1415 Xorriso_free_meM(path);
1416 Xorriso_free_meM(abs_dir_path_data);
1417 Xorriso_free_meM(abs_path);
1418 Dirseq_destroy(&dirseq, 0);
1419 return(ret);
1420 }
1421
1422
1423 /* @param flag bit0= no hardlink reconstruction
1424 bit1= do not set xorriso->node_*_prefixes
1425 bit5= -extract_single: eventually do not insert directory tree
1426 */
1427 int Xorriso_restore_sorted(struct XorrisO *xorriso, int count,
1428 char **src_array, char **tgt_array,
1429 int *problem_count, int flag)
1430 {
1431 int i, ret, with_node_array= 0, hflag= 0, hret;
1432
1433 *problem_count= 0;
1434 if(!(((xorriso->ino_behavior & 16) && xorriso->do_restore_sort_lba) ||
1435 (xorriso->ino_behavior & 4) || (flag & 1))) {
1436 ret= Xorriso_make_hln_array(xorriso, 0);
1437 if(ret<=0)
1438 goto ex;
1439 }
1440 if(xorriso->do_restore_sort_lba) {
1441 /* Count affected nodes */
1442 Xorriso_destroy_node_array(xorriso, 0);
1443 for(i= 0; i < count; i++) {
1444 if(src_array[i] == NULL || tgt_array[i] == NULL)
1445 continue;
1446 /* sort_lba : Make directories plus node_array and then
1447 run array extractor (with eventual hardlink detection)
1448 */
1449 hflag= (1 << 7) | ((!!(flag & 2)) << 9) | (flag & 32);
1450 ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
1451 (off_t) 0, (off_t) 0, hflag);
1452 if(ret <= 0) {
1453 (*problem_count)++;
1454 hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
1455 if(hret < 0)
1456 goto ex;
1457 }
1458 with_node_array= 1;
1459 }
1460 }
1461
1462 if(with_node_array) {
1463 /* Allocate and fill node array */
1464 if(xorriso->node_counter <= 0)
1465 {ret= 2; goto ex;}
1466 ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit, 0,
1467 !xorriso->do_restore_sort_lba);
1468 if(ret<=0)
1469 goto ex;
1470 for(i= 0; i < count; i++) {
1471 if(src_array[i] == NULL || tgt_array[i] == NULL)
1472 continue;
1473 ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
1474 (off_t) 0, (off_t) 0, (2 << 7) | (flag & 32));
1475 if(ret <= 0) {
1476 (*problem_count)++;
1477 hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
1478 if(hret < 0)
1479 goto ex;
1480 }
1481 }
1482 }
1483
1484 /* Perform restore operations */
1485 if(xorriso->do_restore_sort_lba) {
1486 ret= Xorriso_restore_node_array(xorriso, 0);
1487 if(ret <= 0)
1488 goto ex;
1489 } else {
1490 for(i= 0; i < count; i++) {
1491 if(src_array[i] == NULL || tgt_array[i] == NULL)
1492 continue;
1493 ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
1494 (off_t) 0, (off_t) 0, flag & 32);
1495 if(ret <= 0) {
1496 (*problem_count)++;
1497 hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
1498 if(hret < 0)
1499 goto ex;
1500 }
1501 }
1502 }
1503
1504 ret= 1;
1505 ex:;
1506 return(ret);
1507 }
1508
1509
1510 /* @param flag bit0= path is a directory
1511 bit2= recursion: do not reassure in mode 2 "tree"
1512 bit3-7= question text mode
1513 0= plain removal
1514 1= replacing file object
1515 2= overwriting of content, keeping file object
1516 3= appending of content, keeping file object
1517 */
1518 int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag)
1519 {
1520 int ret, mode;
1521
1522 mode= (flag >> 3) & 31;
1523 while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4)))
1524 && !xorriso->request_not_to_ask) {
1525 /* ls -ld */
1526 Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 1|2|8);
1527 if(flag&1) /* du -s */
1528 Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 2|4);
1529 if(mode == 3)
1530 sprintf(xorriso->info_text,
1531 "File exists. Append content ? n= no, y= yes, x= abort, @= stop asking\n");
1532 else if(mode == 2)
1533 sprintf(xorriso->info_text,
1534 "File exists. Overwrite content ? n= no, y= yes, x= abort, @= stop asking\n");
1535 else if(mode == 1)
1536 sprintf(xorriso->info_text,
1537 "File exists. Remove ? n= keep old, y= remove, x= abort, @= stop asking\n");
1538 else
1539 sprintf(xorriso->info_text,
1540 "Remove above file ? n= keep it, y= remove it, x= abort, @= stop asking\n");
1541 Xorriso_info(xorriso, 4);
1542 ret= Xorriso_request_confirmation(xorriso, 1|2|4|16);
1543 if(ret<=0)
1544 goto ex;
1545 if(xorriso->request_to_abort) {
1546 sprintf(xorriso->info_text,
1547 "File alteration operation aborted by user before file: ");
1548 Text_shellsafe(path, xorriso->info_text, 1);
1549 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1550 ret= 3; goto ex;
1551 }
1552 if(ret==3)
1553 continue;
1554 if(ret==6) /* yes */
1555 break;
1556 if(ret==4) { /* yes, do not ask again */
1557 xorriso->request_not_to_ask= 1;
1558 break;
1559 }
1560 if(ret==1) { /* no */
1561 sprintf(xorriso->info_text, "Kept in existing state: ");
1562 Text_shellsafe(path, xorriso->info_text, 1);
1563 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1564 ret= 3; goto ex;
1565 }
1566 }
1567 ret= 1;
1568 ex:
1569 return(ret);
1570 }
1571
1572
1573 /* @param flag bit7= return 4 if restore fails from denied permission
1574 do not issue error message
1575 @return <=0 failure , 1 success ,
1576 4 with bit7: permission to create file was denied
1577 */
1578 int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path,
1579 char *tmp_path, int *fd, int flag)
1580 {
1581 char *cpt;
1582
1583 cpt= strrchr(orig_path, '/');
1584 if(cpt==NULL)
1585 tmp_path[0]= 0;
1586 else {
1587 strncpy(tmp_path, orig_path, cpt+1-orig_path);
1588 tmp_path[cpt+1-orig_path]= 0;
1589 }
1590 strcat(tmp_path, "_tmp_xorriso_restore_XXXXXX");
1591 *fd= mkstemp(tmp_path);
1592 if(*fd==-1) {
1593 if(errno == EACCES && (flag & 128))
1594 return(4);
1595 strcpy(xorriso->info_text, "Cannot create temporary file : ");
1596 Text_shellsafe(tmp_path, xorriso->info_text, 1);
1597 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
1598 return(0);
1599 }
1600 fchmod(*fd, S_IRUSR|S_IWUSR);
1601 return(1);
1602 }
1603
1604
1605 /* @param flag bit0= change regardless of xorriso->do_auto_chmod
1606 bit1= desired is only rx
1607 @return -1=severe error , -2= cannot chmod, 0= nothing to do, 1 = chmoded
1608 */
1609 int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag)
1610 {
1611 int ret, is_link= 0;
1612 char *path_pt, *link_target= NULL;
1613 mode_t mode, desired= S_IRUSR | S_IWUSR | S_IXUSR;
1614 struct stat stbuf;
1615
1616 Xorriso_alloc_meM(link_target, char, SfileadrL);
1617
1618 if(!(xorriso->do_auto_chmod || (flag & 1)))
1619 {ret= 0; goto ex;}
1620
1621 if(flag & 2)
1622 desired &= ~S_IWUSR;
1623 path_pt= disk_path;
1624 ret= lstat(path_pt, &stbuf);
1625 if(ret==-1)
1626 {ret= 0; goto ex;}
1627 if(S_ISLNK(stbuf.st_mode)) {
1628 is_link= 1;
1629 ret= stat(path_pt, &stbuf);
1630 if(ret==-1)
1631 {ret= 0; goto ex;}
1632 }
1633 if(!S_ISDIR(stbuf.st_mode))
1634 {ret= 0; goto ex;}
1635 if(is_link) {
1636 ret= Xorriso_resolve_link(xorriso, path_pt, link_target, 0);
1637 if(ret<=0)
1638 goto ex;
1639 path_pt= link_target;
1640 }
1641 if((stbuf.st_mode & desired) == desired)
1642 {ret= 0; goto ex;}
1643 if(stbuf.st_uid!=geteuid())
1644 {ret= -2; goto ex;}
1645
1646 mode= (stbuf.st_mode | desired) & 07777;
1647 ret= chmod(path_pt, mode);
1648 if(ret==-1) {
1649 sprintf(xorriso->info_text,
1650 "Cannot change access permissions of disk directory: chmod %o ",
1651 (unsigned int) (mode & 07777));
1652 Text_shellsafe(path_pt, xorriso->info_text, 1);
1653 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0);
1654 {ret= -2; goto ex;}
1655 }
1656 ret= Permstack_push(&(xorriso->perm_stack), path_pt, &stbuf, 0);
1657 if(ret<=0)
1658 goto ex;
1659 ret= 1;
1660 ex:;
1661 Xorriso_free_meM(link_target);
1662 return(ret);
1663 }
1664
1665
1666 int Xorriso_make_accessible(struct XorrisO *xorriso, char *disk_path, int flag)
1667 {
1668 int done= 0, ret, just_rx= 2;
1669 char *npt, *apt, *path, *wpt;
1670
1671 Xorriso_alloc_meM(path, char, SfileadrL);
1672
1673 apt= disk_path;
1674 wpt= path;
1675 for(npt= apt; !done; apt= npt + 1) {
1676 npt= strchr(apt, '/');
1677 if(npt == NULL)
1678 break;
1679 if(strchr(npt + 1, '/') == NULL)
1680 just_rx= 0;
1681 strncpy(wpt, apt, npt + 1 - apt);
1682 wpt+= npt + 1 - apt;
1683 *wpt= 0;
1684 ret= Xorriso_auto_chmod(xorriso, path, just_rx);
1685 if(ret == -1)
1686 {ret= -1; goto ex;}
1687 if(ret == -2)
1688 {ret= 0; goto ex;}
1689 }
1690 ret= 1;
1691 ex:
1692 Xorriso_free_meM(path);
1693 return(ret);
1694 }
1695
1696
1697 /* @param flag bit0= prefer to find a match after *img_prefixes
1698 (but deliver img_prefixes if no other can be found)
1699 */
1700 int Xorriso_make_restore_path(struct XorrisO *xorriso,
1701 struct Xorriso_lsT **img_prefixes, struct Xorriso_lsT **disk_prefixes,
1702 char img_path[SfileadrL], char disk_path[SfileadrL], int flag)
1703 {
1704 int li;
1705 struct Xorriso_lsT *s, *d, *found_s= NULL, *found_d= NULL;
1706 char *ipfx, *dpfx;
1707
1708 /* Obtain disk_path by replacing start piece of img_path */
1709
1710 d= *disk_prefixes;
1711 for(s= *img_prefixes; s != NULL;
1712 s= Xorriso_lst_get_next(s, 0), d= Xorriso_lst_get_next(d, 0)) {
1713
1714 ipfx= Xorriso_lst_get_text(s, 0);
1715 li= strlen(ipfx);
1716 dpfx= Xorriso_lst_get_text(d, 0);
1717 if(li == 1 && ipfx[0] == '/') {
1718 li= 0;
1719 if(img_path[0] != '/')
1720 continue;
1721 } else {
1722 if(strncmp(img_path, ipfx, li) != 0)
1723 continue;
1724 if(img_path[li] != 0 && img_path[li] != '/')
1725 continue;
1726 }
1727 if(strlen(dpfx) + strlen(img_path) - li + 1 >= SfileadrL)
1728 return(-1);
1729 if(img_path[li]=='/') {
1730 if(dpfx[0] == '/' && dpfx[1] == 0)
1731 sprintf(disk_path, "/%s", img_path + li + 1);
1732 else
1733 sprintf(disk_path, "%s/%s", dpfx, img_path + li + 1);
1734 } else
1735 strcpy(disk_path, dpfx); /* img_path[li] is 0, img_path equals ipfx */
1736 found_s= s;
1737 found_d= d;
1738 if(s != *img_prefixes || !(flag & 1))
1739 break;
1740 }
1741 *img_prefixes= found_s;
1742 *disk_prefixes= found_d;
1743 return(found_s != NULL);
1744 }
1745
1746
1747 /* @param flag bit0=permission to run Xorriso_make_accessible
1748 */
1749 int Xorriso_restore_make_hl(struct XorrisO *xorriso,
1750 char *old_path, char *new_path, int flag)
1751 {
1752 int ret;
1753 struct PermiteM *perm_stack_mem;
1754
1755 ret= link(old_path, new_path);
1756 if(ret == 0)
1757 return(1);
1758 if(errno == EACCES && (flag & 1)) {
1759 perm_stack_mem= xorriso->perm_stack;
1760 ret= Xorriso_make_accessible(xorriso, new_path, 0);
1761 if(ret > 0) {
1762 ret= link(old_path, new_path);
1763 if(ret == 0) {
1764 Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
1765 return(1);
1766 }
1767 }
1768 Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
1769 }
1770
1771 sprintf(xorriso->info_text, "Hardlinking failed: ");
1772 Text_shellsafe(new_path, xorriso->info_text, 1);
1773 strcat(xorriso->info_text, " -> ");
1774 Text_shellsafe(old_path, xorriso->info_text, 1 | 2);
1775 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "WARNING", 0);
1776 return(0);
1777 }
1778
1779
1780 int Xorriso_afile_fopen(struct XorrisO *xorriso,
1781 char *filename, char *mode, FILE **ret_fp, int flag)
1782 /*
1783 bit0= do not print error message on failure
1784 bit1= do not open stdin
1785 */
1786 {
1787 FILE *fp= NULL;
1788
1789 *ret_fp= NULL;
1790 if(strcmp(filename,"-")==0) {
1791 if(mode[0]=='a' || mode[0]=='w' ||
1792 (mode[0]=='r' && mode[1]=='+') ||
1793 (mode[0]=='r' && mode[1]=='b' && mode[2]=='+'))
1794 fp= stdout;
1795 else if(flag & 2) {
1796 Xorriso_msgs_submit(xorriso, 0, "Not allowed as input path: '-'", 0,
1797 "FAILURE", 0);
1798 return(0);
1799 } else {
1800 Xorriso_msgs_submit(xorriso, 0, "Ready for data at standard input", 0,
1801 "NOTE", 0);
1802 fp= stdin;
1803 }
1804 } else if(strncmp(filename,"tcp:",4)==0){
1805 Xorriso_msgs_submit(xorriso, 0, "TCP/IP service isn't implemented yet.", 0,
1806 "FAILURE", 0);
1807 } else if(strncmp(filename,"file:",5)==0){
1808 fp= fopen(filename+5,mode);
1809 } else {
1810 fp= fopen(filename,mode);
1811 }
1812 if(fp==NULL){
1813 if(!(flag&1)) {
1814 sprintf(xorriso->info_text,
1815 "Failed to open file '%s' in %s mode", filename, mode);
1816 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
1817 }
1818 return(0);
1819 }
1820 *ret_fp= fp;
1821 return(1);
1822 }
1823
1824
1825 /*
1826 @param flag bit0= make absolute command paths with known systems
1827 bit1= do not allow prefixes with cmd
1828 bit2= interpret unprefixed cmd as shell:
1829 bit3= do not care for device filetype
1830 */
1831 int Xorriso_make_mount_cmd(struct XorrisO *xorriso, char *cmd,
1832 int lba, int track, int session, char *volid,
1833 char *devadr, char result[SfileadrL], int flag)
1834 {
1835 int ret, reg_file= 0, is_safe= 0, sys_code= 0;
1836 char *form= NULL, session_text[12], track_text[12], lba_text[12];
1837 char *vars[5][2], *sfe= NULL, *volid_sfe= NULL, *cpt, *sysname;
1838 char *cooked_dev= NULL, *eff_dev;
1839 struct stat stbuf;
1840
1841 Xorriso_alloc_meM(form, char, 6 * SfileadrL);
1842 Xorriso_alloc_meM(sfe, char, 5 * SfileadrL);
1843 Xorriso_alloc_meM(volid_sfe, char, 5 * 80 + 1);
1844 Xorriso_alloc_meM(cooked_dev, char, SfileadrL);
1845
1846 if(strlen(cmd) > SfileadrL) {
1847 Xorriso_msgs_submit(xorriso, 0, "Argument much too long", 0, "FAILURE", 0);
1848 {ret= 0; goto ex;}
1849 }
1850 eff_dev= devadr;
1851 ret= stat(devadr, &stbuf);
1852 if(ret != -1 && !(flag & 8))
1853 if(S_ISREG(stbuf.st_mode))
1854 reg_file= 1;
1855 if(strncmp(cmd, "linux:", 6) == 0 && !(flag & 2)) {
1856 cpt= cmd + 6;
1857 sys_code= 1;
1858 } else if(strncmp(cmd, "freebsd:", 8) == 0 && !(flag & 2)) {
1859 cpt= cmd + 8;
1860 sys_code= 2;
1861 } else if(strncmp(cmd, "netbsd:", 7) == 0 && !(flag & 2)) {
1862 cpt= cmd + 7;
1863 sys_code= 3;
1864 } else if(strncmp(cmd, "string:", 7) == 0 && !(flag & 2)) {
1865 cpt= cmd + 7;
1866 strcpy(form, cpt);
1867 } else if(flag & 4) {
1868 cpt= cmd;
1869 strcpy(form, cpt);
1870 } else {
1871 cpt= cmd;
1872 ret= System_uname(&sysname, NULL, NULL, NULL, 0);
1873 if(ret <= 0) {
1874 Xorriso_msgs_submit(xorriso, 0,
1875 "-mount*: Cannot determine current system type",
1876 0, "FAILURE", 0);
1877 {ret= 0; goto ex;}
1878 } else if(strcmp(sysname, "FreeBSD") == 0 ||
1879 strcmp(sysname, "GNU/kFreeBSD") == 0) {
1880 /* "GNU/kFreeBSD" = Debian kfreebsd */
1881 sys_code= 2;
1882 } else if(strcmp(sysname, "NetBSD") == 0) {
1883 sys_code= 3;
1884 } else if(strcmp(sysname, "Linux") == 0) {
1885 sys_code= 1;
1886 } else {
1887 sprintf(xorriso->info_text, "-mount*: Unsupported system type %s",
1888 Text_shellsafe(sysname, sfe, 0));
1889 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1890 {ret= 0; goto ex;}
1891 }
1892 }
1893
1894 if(sys_code == 1) { /* GNU/Linux */
1895 sprintf(form,
1896 "%smount -t iso9660 -o %snodev,noexec,nosuid,ro,sbsector=%%sbsector%% %%device%% %s",
1897 (flag & 1 ? "/bin/" : ""),
1898 (reg_file || (xorriso->mount_opts_flag & 1) ? "loop," : ""),
1899 Text_shellsafe(cpt, sfe, 0));
1900 is_safe= 1;
1901 } else if(sys_code == 2 || sys_code == 3) { /* FreeBSD , NetBSD */
1902 if(reg_file) {
1903
1904 /* <<< Considered to create vnode as of
1905 J.R. Oldroyd <fbsd@opal.com>, 20 Nov 2008
1906 but for now refraining from creating that persistent file object
1907
1908 strcpy(form, "n=$(mdconfig -a -t vnode -f %device%)");
1909 sprintf(form + strlen(form),
1910 " && mount -t cd9660 -o noexec,nosuid -s %%sbsector%% /dev/\"$n\" %s",
1911 Text_shellsafe(cmd+8, sfe, 0));
1912 */
1913
1914 Xorriso_msgs_submit(xorriso, 0,
1915 "Detected regular file as mount device with BSD style command.",
1916 0, "FAILURE", 0);
1917 if(sys_code == 2) {
1918 Xorriso_msgs_submit(xorriso, 0,
1919 "Command mdconfig -a -t vnode -f can create a device node which uses the file",
1920 0, "HINT", 0);
1921 } else {
1922 Xorriso_msgs_submit(xorriso, 0,
1923 "Command vnconfig -c vndX can create a device node which uses the file",
1924 0, "HINT", 0);
1925 }
1926 {ret= 0; goto ex;}
1927 } else {
1928 if(sys_code == 3 && strncmp(devadr, "/dev/rcd", 8) == 0) {
1929 sprintf(cooked_dev, "/dev/cd%s", devadr + 8);
1930 eff_dev= cooked_dev;
1931 }
1932 sprintf(form,
1933 "%smount_cd9660 -o noexec,nosuid -s %%sbsector%% %%device%% %s",
1934 (flag & 1 ? "/sbin/" : ""), Text_shellsafe(cpt, sfe, 0));
1935 }
1936 is_safe= 1;
1937 }
1938 sprintf(session_text, "%d", session);
1939 sprintf(track_text, "%d", track);
1940 sprintf(lba_text, "%d", lba);
1941 vars[0][0]= "sbsector";
1942 vars[0][1]= lba_text;
1943 vars[1][0]= "track";
1944 vars[1][1]= track_text;
1945 vars[2][0]= "session";
1946 vars[2][1]= session_text;
1947 vars[3][0]= "volid";
1948 vars[3][1]= Text_shellsafe(volid, volid_sfe, 0);
1949 vars[4][0]= "device";
1950 vars[4][1]= Text_shellsafe(eff_dev, sfe, 0);
1951 ret= Sregex_resolve_var(form, vars, 5, "%", "%", "%", result, SfileadrL, 0);
1952 if(ret <= 0)
1953 goto ex;
1954 ret= 1 + is_safe;
1955 ex:;
1956 Xorriso_free_meM(cooked_dev);
1957 Xorriso_free_meM(volid_sfe);
1958 Xorriso_free_meM(sfe);
1959 Xorriso_free_meM(form);
1960 return(ret);
1961 }
1962
1963
1964 int Xorriso_append_scdbackup_record(struct XorrisO *xorriso, int flag)
1965 {
1966 FILE *fp= NULL;
1967 char dummy[81], name[81], timestamp[81], size[81], md5[81];
1968
1969 if(xorriso->scdbackup_tag_written[0] == 0)
1970 return(1);
1971
1972 name[0]= timestamp[0]= size[0]= md5[0]= 0;
1973 sscanf(xorriso->scdbackup_tag_written, "%s %s %s %s %s %s %s",
1974 dummy, dummy, dummy, name, timestamp, size, md5);
1975 sprintf(xorriso->info_text, "scdbackup tag written : %s %s %s %s\n",
1976 name, timestamp, size, md5);
1977 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1978
1979 if(xorriso->scdbackup_tag_listname[0]) {
1980 fp= fopen(xorriso->scdbackup_tag_listname, "a");
1981 if(fp==0) {
1982 strcpy(xorriso->info_text, "-scdbackup_tag: Cannot open file ");
1983 Text_shellsafe(xorriso->scdbackup_tag_listname, xorriso->info_text, 1);
1984 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1985 return(0);
1986 }
1987 fprintf(fp, "%s %s %s %s\n", name, timestamp, size, md5);
1988 fclose(fp);
1989 }
1990 return(1);
1991 }
1992
1993
1994 /* @param flag bit0= for append rather than overwrite
1995 */
1996 int Xorriso_is_concat_target(struct XorrisO *xorriso, char *target,
1997 int *ftype, int *fd, int flag)
1998 {
1999 int ret;
2000 char *why= "";
2001
2002 *ftype= 0;
2003 *fd = -1;
2004
2005 if(strcmp(target, "-") == 0) {
2006 *fd= 1;
2007 *ftype= 8; /* character device */
2008 return(1);
2009 }
2010
2011 *ftype= Sfile_type(target, 1 | 8 | 16);
2012 if(*ftype == -1)
2013 return(2); /* not yet existing regular */
2014
2015 if(*ftype & 1024) {
2016 *fd= Sfile_get_dev_fd_no(target, 0);
2017 *ftype &= ~1024;
2018 }
2019 if(*ftype & 2048) {
2020 why= "fstat(2) returned -1 on file descriptor number.";
2021 goto not_usable;
2022 }
2023
2024 if(*ftype == 3) {
2025 if(!xorriso->do_follow_concat) {
2026 why= "May not follow symbolic link. No -follow \"...:concat:...\".";
2027 goto not_usable;
2028 }
2029 *ftype= Sfile_type(target, 1 | 4 | 8);
2030 if(*ftype == -1)
2031 return(2); /* not yet existing regular */
2032 }
2033 if(*ftype == 2) {
2034 why= "May not write data into a directory.";
2035 goto not_usable;
2036 }
2037 if(*ftype == 0) {
2038 why= "Cannot determine file type.";
2039 goto not_usable;
2040 }
2041 if(*ftype == 7) {
2042
2043 /* >>> what to do with UNIX socket ? */;
2044
2045 why= "Cannot yet handle socket file as target.";
2046 goto not_usable;
2047 }
2048
2049 if(xorriso->do_overwrite != 1 && xorriso->do_overwrite != 2) {
2050 why= "May not alter existing file.";
2051 goto not_usable;
2052 }
2053 ret= Xorriso_reassure_restore(xorriso, target, (2 + (flag & 1)) << 3);
2054 if(ret <= 0 || ret == 0) {
2055 why= "User revoked alteration of existing file.";
2056 goto not_usable;
2057 }
2058
2059 if(*ftype == 1)
2060 return(2); /* existing regular */
2061 if(*ftype == 4 || *ftype == 6 || *ftype == 8)
2062 return(1); /* named pipe, block device, character device */
2063
2064 not_usable:;
2065 sprintf(xorriso->info_text,
2066 "Unsuitable -concat target: ");
2067 Text_shellsafe(target, xorriso->info_text, 1);
2068 sprintf(xorriso->info_text + strlen(xorriso->info_text), ". %s", why);
2069 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2070 return(0);
2071 }
2072
2073
2074 int Xorriso_concat(struct XorrisO *xorriso, char *mode, char *target,
2075 int progc, char **progv,
2076 int filec, char **filev, int flag)
2077 {
2078 int ret, i, fd= -1, target_is_regular= 0, fd_opened= 0, ftype, prog_forked= 0;
2079 int status;
2080 int open_mode= O_WRONLY | O_CREAT;
2081 struct stat stbuf;
2082 pid_t forked_pid;
2083
2084 for(i= 0; i < filec; i++) {
2085 ret= Xorriso_iso_lstat(xorriso, filev[i], &stbuf, 4);
2086 if(ret == -1)
2087 goto ex;
2088 if(!S_ISREG(stbuf.st_mode)) {
2089 sprintf(xorriso->info_text,
2090 "-concat: iso_rr_path is not a regular data file: ");
2091 Text_shellsafe(filev[i], xorriso->info_text, 1);
2092 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2093 ret= 0; goto ex;
2094 }
2095 }
2096 if(strcmp(mode, "overwrite") == 0) {
2097 ret= Xorriso_is_concat_target(xorriso, target, &ftype, &fd, 0);
2098 if(ret <= 0)
2099 goto ex;
2100 if(ret == 2) {
2101 target_is_regular= 1;
2102 open_mode |= O_TRUNC;
2103 }
2104 if(fd == -1) {
2105 fd= open(target, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666);
2106 fd_opened= 1;
2107 }
2108 } else if(strcmp(mode, "append") == 0) {
2109 ret= Xorriso_is_concat_target(xorriso, target, &ftype, &fd, 1);
2110 if(ret <= 0)
2111 goto ex;
2112 target_is_regular= (ret == 2);
2113 if(fd == -1) {
2114 fd= open(target, O_WRONLY | O_CREAT | O_BINARY, 0666);
2115 fd_opened= 1;
2116 if(fd != -1 && target_is_regular) {
2117 ret= lseek(fd, (off_t) 0, SEEK_END);
2118 if(ret == -1) {
2119 sprintf(xorriso->info_text,
2120 "-concat append: Cannot lseek(2) to file end of ");
2121 Text_shellsafe(target, xorriso->info_text, 1);
2122 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2123 ret= 0; goto ex;
2124 }
2125 }
2126 }
2127
2128 } else if(strcmp(mode, "pipe") == 0) {
2129 ret= Xorriso_pipe_open(xorriso, "-concat pipe", progv[0], progc, progv,
2130 "", &fd, &forked_pid, 2 | 8);
2131 if(ret <= 0)
2132 goto ex;
2133 fd_opened= 1;
2134 prog_forked= 1;
2135
2136 } else {
2137 sprintf(xorriso->info_text, "-concat: Unknown mode ");
2138 Text_shellsafe(mode, xorriso->info_text, 1);
2139 strcat(xorriso->info_text, ". Known modes: overwrite, append, pipe");
2140 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2141 ret= 0; goto ex;
2142 }
2143 if(fd == -1) {
2144 sprintf(xorriso->info_text,
2145 "-concat: Cannot open file handle to ");
2146 Text_shellsafe(target, xorriso->info_text, 1);
2147 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2148 ret= 0; goto ex;
2149 }
2150
2151 for(i= 0; i < filec; i++) {
2152 ret= Xorriso_iso_file_to_fd(xorriso, filev[i], fd, 0);
2153 if(ret <= 0) {
2154 if(i < filec - 1) {
2155 ret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
2156 if(ret < 0) {
2157 sprintf(xorriso->info_text,
2158 "-concat: Aborted although %d files stay unprocessed.",
2159 filec - i + 1);
2160 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2161 ret= 0; goto ex;
2162 }
2163 }
2164 }
2165 }
2166
2167 ret= 1;
2168 ex:;
2169 if(fd_opened && fd != -1)
2170 close(fd);
2171 if(prog_forked)
2172 Xorriso_wait_child_end(xorriso, forked_pid, &status, 0);
2173 return(ret);
2174 }