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