"Fossies" - the Fresh Open Source Software Archive 
Member "xorriso-1.5.4/xorriso/iso_tree.c" (30 Jan 2021, 77300 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.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 "iso_tree.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.5.2_vs_1.5.4.
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 functions which access nodes of the
9 libisofs tree model.
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 <errno.h>
26
27 #include <pwd.h>
28 #include <grp.h>
29
30
31 #include "xorriso.h"
32 #include "xorriso_private.h"
33 #include "xorrisoburn.h"
34
35 #include "lib_mgt.h"
36 #include "iso_img.h"
37 #include "iso_tree.h"
38 #include "iso_manip.h"
39 #include "sort_cmp.h"
40
41
42 /* @param eff_path returns resulting effective path.
43 Must provide at least SfileadrL bytes of storage.
44 @param flag bit0= do not produce problem events (unless faulty path format)
45 bit1= do not use libisofs (work literally or in disk world)
46 bit2= (implies bit1) this is an address in the disk world
47 bit3= return root directory as "/" and not as ""
48 bit4= (with bit2) determine type of disk file eff_path
49 and return 0 if not existing
50 bit5= (with bit3) this is not a parameter
51 bit6= insist in having an ISO image, even with bits1+2
52 @return -1 = faulty path format, 0 = not found ,
53 1 = found simple node , 2 = found directory
54 */
55 int Xorriso_normalize_img_path(struct XorrisO *xorriso, char *wd,
56 char *img_path, char eff_path[], int flag)
57 {
58 int ret, is_dir= 0, done= 0;
59 IsoImage *volume;
60 IsoDir *dir= NULL;
61 IsoNode *node= NULL;
62 char *path= NULL, *apt, *npt, *cpt, *link_target= NULL;
63
64 Xorriso_alloc_meM(path, char, SfileadrL);
65 Xorriso_alloc_meM(link_target, char, SfileadrL);
66
67 if(flag & 4)
68 flag|= 2;
69 if((flag&64) || !(flag&2)) {
70 ret= Xorriso_get_volume(xorriso, &volume, 0);
71 if(ret<=0)
72 goto ex;
73 }
74
75 eff_path[0]= 0;
76 if(img_path[0]==0) {
77 if(flag&8)
78 strcpy(eff_path, "/");
79 {ret= 2; goto ex;} /* root directory */
80 }
81
82 apt= npt= path;
83 if(img_path[0]!='/') {
84 strcpy(path, wd);
85 ret= Sfile_add_to_path(path, img_path, 0);
86 if(ret<=0)
87 goto much_too_long;
88 } else
89 if(Sfile_str(path, img_path, 0)<=0)
90 {ret= -1; goto ex;}
91
92 if(path[0]!='/') {
93 sprintf(xorriso->info_text,
94 "Internal error: Unresolvable relative addressing in iso_rr_path '%s'",
95 img_path);
96 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FATAL", 0);
97 {ret= -1; goto ex;}
98 } else if(path[1]==0) {
99 if(flag&8)
100 strcpy(eff_path, "/");
101 {ret= 2; goto ex;} /* root directory */
102 }
103
104 if(apt[0] == '.')
105 if(apt[1] == 0 || apt[1] == '/')
106 is_dir= 1;
107 for(npt= apt; !done; apt= npt+1) {
108 npt= strchr(apt, '/');
109 if(npt==NULL) {
110 npt= apt+strlen(apt);
111 done= 1;
112 } else
113 *npt= 0;
114 if(*apt==0) {
115 *apt= '/';
116 apt++;
117 if(done)
118 break;
119 continue;
120 }
121 if(strcmp(apt,".")==0)
122 continue;
123 if(strcmp(apt,"..")==0) {
124 if(!(flag&2)) {
125 node= (IsoNode *) dir;
126 if(node==NULL) {
127 bonked_root:;
128 sprintf(xorriso->info_text,
129 "Relative addressing in path exceeds root directory: ");
130 Text_shellsafe(img_path, xorriso->info_text, 1);
131 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
132 {ret= -1; goto ex;}
133 }
134 dir= iso_node_get_parent(node);
135
136 /* >>> Get absolute path of node as eff_path, to avoid link problems */;
137
138 }
139 if(flag & 4) {
140 /* Linux-ish local filesystem semantics:
141 If the parent is a symbolic link, do not ascend to its parent,
142 but to the parent of the link target.
143 >>> ??? Are there systems which do it differently ?
144 */
145 if(Sfile_type(eff_path, 0) == 3) {
146 ret= Xorriso_resolve_link(xorriso, eff_path, link_target, 2);
147 if(ret <= 0)
148 {ret= -1; goto ex;}
149 strcpy(eff_path, link_target);
150 }
151 }
152
153 /* truncate eff_path */;
154 cpt= strrchr(eff_path, '/');
155 if(cpt==NULL) /* ??? if not flag&2 then this is a bug */
156 goto bonked_root;
157 *cpt= 0;
158 is_dir= 1;
159 continue;
160 }
161 is_dir= 0;
162 ret= Sfile_add_to_path(eff_path, apt, 0);
163 if(ret<=0) {
164 much_too_long:;
165 sprintf(xorriso->info_text, "Effective path gets much too long (%d)",
166 (int) (strlen(eff_path)+strlen(apt)+1));
167 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
168 {ret= -1; goto ex;}
169 }
170 if(!(flag&2)) {
171 dir= (IsoDir *) node;
172 ret= Xorriso_node_from_path(xorriso, volume, eff_path, &node, flag&1);
173 if(ret<=0)
174 {ret= 0; goto ex;}
175 if(dir==NULL) /* could be false with "/dir/.." */
176 dir= iso_node_get_parent(node);
177 is_dir= LIBISO_ISDIR(node);
178 }
179 }
180 if(flag&16) {
181 ret= Sfile_type(eff_path,
182 1|(4*(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&32)))
183 ));
184 if(ret<0)
185 {ret= 0; goto ex;}
186 if(ret==2)
187 is_dir= 1;
188 else
189 is_dir= 0;
190 }
191 ret= 1+!!is_dir;
192 ex:;
193 Xorriso_free_meM(path);
194 Xorriso_free_meM(link_target);
195 return(ret);
196 }
197
198
199 int Xorriso_get_node_by_path(struct XorrisO *xorriso,
200 char *in_path, char *eff_path,
201 IsoNode **node, int flag)
202 {
203 int ret;
204 char *path= NULL;
205 IsoImage *volume;
206
207 Xorriso_alloc_meM(path, char, SfileadrL);
208
209 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, in_path, path, 0);
210 if(ret<=0)
211 goto ex;
212 if(eff_path!=NULL)
213 strcpy(eff_path, path);
214 ret= Xorriso_get_volume(xorriso, &volume, 0);
215 if(ret<=0)
216 goto ex;
217 ret= Xorriso_node_from_path(xorriso, volume, path, node, 0);
218 if(ret<=0)
219 {ret= 0; goto ex;}
220 ret= 1;
221 ex:;
222 Xorriso_free_meM(path);
223 return(ret);
224 }
225
226
227 /* @param flag
228 */
229 int Xorriso_node_get_dev(struct XorrisO *xorriso, IsoNode *node,
230 char *path, dev_t *dev, int flag)
231 {
232 *dev= iso_special_get_dev((IsoSpecial *) node);
233 return(1);
234 }
235
236
237 /* @param flag bit0= *node is already valid
238 bit1= add extra block for size estimation
239 bit2= complain loudely if path is missing in image
240 bit3= stbuf is to be used without eventual ACL
241 bit4= try to obtain a better st_nlink count if hardlinks
242 are enabled
243 bit5= do not look for truncated versions of path component
244 */
245 int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf,
246 IsoNode **node, int flag)
247 {
248 int ret, min_hl, max_hl, node_idx, i;
249 IsoImage *volume;
250 IsoBoot *bootcat;
251 uint32_t lba;
252 char *catcontent = NULL;
253 off_t catsize;
254 dev_t dev_number;
255
256 memset((char *) stbuf, 0, sizeof(struct stat));
257 if(!(flag&1)) {
258 ret= Xorriso_get_volume(xorriso, &volume, 0);
259 if(ret<=0)
260 return(-1);
261 ret= Xorriso_node_from_path(xorriso, volume, path, node,
262 ((flag >> 4) & 2) | !(flag&4));
263 if(ret<=0)
264 *node= NULL;
265 }
266 if(*node==NULL)
267 return(0);
268
269 /* >>> stbuf->st_dev */
270 /* >>> stbuf->st_ino */
271
272 if(flag & 8)
273 stbuf->st_mode= iso_node_get_perms_wo_acl(*node) & 07777;
274 else
275 stbuf->st_mode= iso_node_get_permissions(*node) & 07777;
276 if(LIBISO_ISDIR(*node))
277 stbuf->st_mode|= S_IFDIR;
278 else if(LIBISO_ISREG(*node))
279 stbuf->st_mode|= S_IFREG;
280 else if(LIBISO_ISLNK(*node))
281 stbuf->st_mode|= S_IFLNK;
282 else if(LIBISO_ISCHR(*node)) {
283 stbuf->st_mode|= S_IFCHR;
284 Xorriso_node_get_dev(xorriso, *node, path, &dev_number, 0);
285 stbuf->st_rdev= dev_number;
286 } else if(LIBISO_ISBLK(*node)) {
287 stbuf->st_mode|= S_IFBLK;
288 /* ts B11124:
289 Debian mips and mipsel have sizeof(stbuf.st_rdev) == 4
290 whereas sizeof(dev_t) is 8.
291 This workaround assumes that the returned numbers fit into 4 bytes.
292 The may stem from the local filesystem or from the ISO image.
293 At least there will be no memory corruption but only an integer rollover.
294 */
295 Xorriso_node_get_dev(xorriso, *node, path, &dev_number, 0);
296 stbuf->st_rdev= dev_number;
297 } else if(LIBISO_ISFIFO(*node))
298 stbuf->st_mode|= S_IFIFO;
299 else if(LIBISO_ISSOCK(*node))
300 stbuf->st_mode|= S_IFSOCK;
301 else if(LIBISO_ISBOOT(*node))
302 stbuf->st_mode|= Xorriso_IFBOOT;
303
304 /* >>> With directories this should be : number of subdirs + 2 */
305 /* >>> ??? How to obtain RR hardlink number for other types ? */
306 /* This may get overridden farther down */
307 stbuf->st_nlink= 1;
308
309 stbuf->st_uid= iso_node_get_uid(*node);
310 stbuf->st_gid= iso_node_get_gid(*node);
311
312 if(LIBISO_ISREG(*node))
313 stbuf->st_size= iso_file_get_size((IsoFile *) *node)+ (2048 * !!(flag&2));
314 else if(LIBISO_ISBOOT(*node)) {
315 ret= Xorriso_get_volume(xorriso, &volume, 0);
316 if(ret <= 0)
317 return(-1);
318 ret= iso_image_get_bootcat(volume, &bootcat, &lba, &catcontent, &catsize);
319 if(catcontent != NULL)
320 free(catcontent);
321 if(ret < 0) {
322 Xorriso_process_msg_queues(xorriso,0);
323 return(-1);
324 }
325 stbuf->st_size= catsize;
326 } else
327 stbuf->st_size= 0;
328
329 stbuf->st_blksize= 2048;
330 stbuf->st_blocks= stbuf->st_size / (off_t) 2048;
331 if(stbuf->st_blocks * (off_t) 2048 != stbuf->st_size)
332 stbuf->st_blocks++;
333
334 stbuf->st_atime= iso_node_get_atime(*node);
335 stbuf->st_mtime= iso_node_get_mtime(*node);
336 stbuf->st_ctime= iso_node_get_ctime(*node);
337
338 if(LIBISO_ISDIR(*node) || (xorriso->ino_behavior & 1) || (!(flag & 16)) ||
339 xorriso->hln_array == NULL)
340 return(1);
341
342 /* Try to obtain a better link count */
343 ret= Xorriso_search_hardlinks(xorriso, *node, &node_idx, &min_hl, &max_hl, 0);
344 if(ret < 0)
345 return(ret);
346 if(ret > 0 && node_idx >= 0) {
347 for(i= min_hl; i <= max_hl; i++) {
348 if(i == node_idx)
349 continue;
350 /* Check whether node is still valid */
351 if(iso_node_get_parent(xorriso->hln_array[i]) != NULL)
352 stbuf->st_nlink++;
353 }
354 }
355 return(1);
356 }
357
358
359 /* @param flag >>> bit0= follow links (i.e. stat() rather than lstat()
360 bit1= do not return -2 on severe errors
361 bit2= complain loudely if path is missing in image
362 */
363 int Xorriso_iso_lstat(struct XorrisO *xorriso, char *path, struct stat *stbuf,
364 int flag)
365 {
366 int ret;
367 IsoNode *node;
368
369 if(flag&1) {
370
371 /* >>> follow link in ISO image */;
372
373 }
374
375 ret= Xorriso_fake_stbuf(xorriso, path, stbuf, &node, flag&4);
376 if(ret>0)
377 return(0);
378 if(ret<0 && !(flag&2))
379 return(-2);
380 return(-1);
381 }
382
383
384 int Xorriso_node_is_valid(struct XorrisO *xorriso, IsoNode *in_node, int flag)
385 {
386 IsoNode *node, *parent;
387
388 for(node= in_node; 1; node= parent) {
389 parent= (IsoNode *) iso_node_get_parent(node);
390 if(parent == node)
391 break;
392 if(parent == NULL)
393 return(0); /* Node is not in the tree (any more) */
394 }
395 return(1);
396 }
397
398
399 int Xorriso_path_from_node(struct XorrisO *xorriso, IsoNode *in_node,
400 char path[SfileadrL], int flag)
401 {
402 int ret, i, comp_count= 0;
403 IsoNode *node, *parent, **components= NULL;
404 char *wpt, *npt;
405
406 for(node= in_node; 1; node= parent) {
407 parent= (IsoNode *) iso_node_get_parent(node);
408 if(parent == node)
409 break;
410 if(parent == NULL)
411 return(0); /* Node is not in the tree (any more) */
412 comp_count++;
413 }
414 if(comp_count == 0) {
415 strcpy(path, "/");
416 return(1);
417 }
418 components= calloc(comp_count, sizeof(IsoNode *));
419 if(components == NULL) {
420 Xorriso_no_malloc_memory(xorriso, NULL, 0);
421 ret= -1; goto ex;
422 }
423 i= comp_count;
424 for(node= in_node; 1; node= parent) {
425 parent= (IsoNode *) iso_node_get_parent(node);
426 if(parent == node)
427 break;
428 components[--i]= node;
429 }
430
431 wpt= path;
432 for(i= 0; i < comp_count; i++) {
433 npt= (char *) iso_node_get_name(components[i]);
434 if((wpt - path) + strlen(npt) + 1 >= SfileadrL) {
435
436 /* >>> path is getting much too long */;
437
438 ret= -1; goto ex;
439 }
440 *(wpt++)= '/';
441 strcpy(wpt, npt);
442 wpt+= strlen(npt);
443 *wpt= 0;
444 }
445 ret= 1;
446 ex:;
447 if(components != NULL)
448 free(components);
449 return(ret);
450 }
451
452
453 /* <<< The lookup from node pointer will be done by Xorriso_path_from_node()
454 (Currently it runs a full tree traversal)
455 Parameter node and flag bit0 will vanish then
456 */
457 /* @param flag bit0= use lba rather than node pointer
458 */
459 int Xorriso_path_from_lba(struct XorrisO *xorriso, IsoNode *node, int lba,
460 char path[SfileadrL], int flag)
461 {
462 int ret;
463 struct FindjoB *job= NULL;
464 struct stat dir_stbuf;
465 char *found_path;
466
467 path[0]= 0;
468 if((flag & 1) && lba <= 0)
469 return(0);
470
471 ret= Findjob_new(&job, "/", 0);
472 if(ret <= 0) {
473 Xorriso_no_findjob(xorriso, "path_from_node", 0);
474 return(ret);
475 }
476 if(flag & 1)
477 Findjob_set_lba_range(job, lba, 1, 0);
478 else
479 Findjob_set_wanted_node(job, (void *) node, 0);
480 Findjob_set_action_found_path(job, 0);
481 ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0,
482 NULL, "/", &dir_stbuf, 0, 0);
483 if(ret > 0) {
484 ret= 1;
485 Findjob_get_found_path(job, &found_path, 0);
486 if(found_path == NULL)
487 ret= 0;
488 else if(Sfile_str(path, found_path, 0) <= 0)
489 ret= -1;
490 }
491 Findjob_destroy(&job, 0);
492 return(ret);
493 }
494
495
496 /* @param flag bit0= in_node is valid, do not resolve iso_adr
497 bit2= recognize and parse split parts despite
498 xorriso->split_size <= 0
499 */
500 int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr,
501 void *in_node,
502 struct SplitparT **parts, int *count,
503 struct stat *total_stbuf, int flag)
504 {
505 int ret, i, incomplete= 0, overlapping= 0;
506 int partno, total_parts, first_total_parts= -1;
507 off_t offset, bytes, total_bytes, first_total_bytes= -1, first_bytes= -1;
508 off_t size, covered;
509
510 IsoImage *volume;
511 IsoDir *dir_node;
512 IsoDirIter *iter= NULL;
513 IsoNode *node;
514 char *name;
515 struct stat stbuf, first_stbuf;
516
517 *count= 0;
518 *parts= NULL;
519
520 if(xorriso->split_size <= 0 && !(flag & 4))
521 return(0);
522
523 if(flag&1) {
524 node= (IsoNode *) in_node;
525 } else {
526 ret= Xorriso_get_volume(xorriso, &volume, 0);
527 if(ret<=0)
528 return(-1);
529 ret= Xorriso_node_from_path(xorriso, volume, iso_adr, &node, 1);
530 if(ret<=0)
531 return(-1);
532 }
533 if(!LIBISO_ISDIR(node))
534 return(0);
535 dir_node= (IsoDir *) node;
536
537 ret= iso_dir_get_children(dir_node, &iter);
538 if(ret<0) {
539 cannot_iter:;
540 Xorriso_cannot_create_iter(xorriso, ret, 0);
541 return(-1);
542 }
543
544 for(i= 0; iso_dir_iter_next(iter, &node) == 1; i++) {
545 name= (char *) iso_node_get_name(node);
546 ret= Splitpart__parse(name, &partno, &total_parts,
547 &offset, &bytes, &total_bytes, 0);
548 if(ret<=0)
549 {ret= 0; goto ex;}
550 if(i==0) {
551 first_total_parts= total_parts;
552 first_bytes= bytes;
553 first_total_bytes= total_bytes;
554 Xorriso_fake_stbuf(xorriso, "", &first_stbuf, &node, 1);
555 size= first_stbuf.st_size;
556 } else {
557 if(first_total_parts!=total_parts || first_total_bytes!=total_bytes ||
558 (first_bytes!=bytes && partno!=total_parts))
559 {ret= 0; goto ex;}
560 Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
561 if(first_stbuf.st_mode != stbuf.st_mode ||
562 first_stbuf.st_uid != stbuf.st_uid ||
563 first_stbuf.st_gid != stbuf.st_gid ||
564 first_stbuf.st_mtime != stbuf.st_mtime ||
565 first_stbuf.st_ctime != stbuf.st_ctime)
566 {ret= 0; goto ex;}
567 size= stbuf.st_size;
568 }
569 /* check for plausible size */
570 if(!((partno != total_parts && size == bytes) ||
571 (partno == total_parts && size <= bytes)))
572 {ret= 0; goto ex;}
573 if(offset != first_bytes * (off_t) (partno - 1))
574 {ret= 0; goto ex;}
575 (*count)++;
576 }
577 if(*count <= 0 || *count != first_total_parts)
578 {ret= 0; goto ex;}
579
580 ret= Splitparts_new(parts, (*count)+1, 0); /* (have one end marker item) */
581 if(ret<=0)
582 return(ret);
583
584 iso_dir_iter_free(iter);
585 ret= iso_dir_get_children(dir_node, &iter);
586 if(ret<0)
587 goto cannot_iter;
588 for(i= 0; i<*count; i++) {
589 ret= iso_dir_iter_next(iter, &node);
590 if(ret!=1)
591 break;
592 name= (char *) iso_node_get_name(node);
593 ret= Splitpart__parse(name, &partno, &total_parts,
594 &offset, &bytes, &total_bytes, 0);
595 if(ret<=0)
596 {ret= 0; goto ex;}
597 ret= Splitparts_set(*parts, i, name, partno, total_parts, offset, bytes,
598 total_bytes, 0);
599 if(ret<=0)
600 goto ex;
601 }
602
603 Splitparts_sort(*parts, *count, 0);
604
605 covered= 0;
606 for(i= 0; i<*count; i++) {
607 Splitparts_get(*parts, i, &name, &partno, &total_parts, &offset, &bytes,
608 &total_bytes, 0);
609 if(offset>covered)
610 incomplete= 1;
611 else if(offset<covered)
612 overlapping= 1;
613 if(offset+bytes > covered)
614 covered= offset+bytes;
615 }
616 if(total_bytes>covered)
617 incomplete= 1;
618 memcpy(total_stbuf, &first_stbuf, sizeof(struct stat));
619 total_stbuf->st_size= total_bytes;
620 ret= !(overlapping || incomplete);
621 ex:;
622 if(iter!=NULL)
623 iso_dir_iter_free(iter);
624 return(ret);
625 }
626
627
628 /* @param flag bit0= node is valid, do not resolve path
629 bit1= insist in complete collection of part files
630 bit2= recognize and parse split parts despite
631 xorriso->split_size <= 0
632 */
633 int Xorriso_is_split(struct XorrisO *xorriso, char *path, void *node,
634 int flag)
635 {
636 struct SplitparT *split_parts= NULL;
637 int split_count= 0, ret;
638 struct stat stbuf;
639
640 ret= Xorriso_identify_split(xorriso, path, node, &split_parts,
641 &split_count, &stbuf, flag & 7);
642 if(split_parts!=NULL)
643 Splitparts_destroy(&split_parts, split_count, 0);
644 return(ret>0);
645 }
646
647
648 /* @param node Opaque handle to IsoNode which is to be inquired instead of path if it is not NULL.
649 @param path is used as address if node is NULL.
650 @param acl_text if acl_text is not NULL, then *acl_text will be set to the
651 ACL text (without comments) of the file object. In this
652 case it finally has to be freed by the caller.
653 @param flag bit0= do not report to result but only retrieve ACL text
654 bit1= check for existence of true ACL (not fabricated),
655 do not allocate and set acl_text but return 1 or 2
656 bit2-3: what ALC to retrieve:
657 0= "access" and "default", mark "default:"
658 1= "access" only
659 2= "default" only, do not mark "default:"
660 bit4= get "access" ACL only if not trivial
661 @return 2 ok, no ACL available, eventual *acl_text will be NULL
662 1 ok, ACL available, eventual *acl_text stems from malloc()
663 <=0 error
664 */
665 int Xorriso_getfacl(struct XorrisO *xorriso, void *in_node, char *path,
666 char **acl_text, int flag)
667 {
668 int ret, d_ret, result_len= 0, pass, what;
669 IsoNode *node;
670 char *text= NULL, *d_text= NULL, *cpt, *npt;
671 uid_t uid;
672 gid_t gid;
673 struct passwd *pwd;
674 struct group *grp;
675
676 what= (flag >> 2) & 3;
677 if(acl_text != NULL)
678 *acl_text= NULL;
679
680 node= (IsoNode *) in_node;
681 if(node == NULL) {
682 ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
683 if(ret<=0)
684 goto ex;
685 }
686 ret= iso_node_get_acl_text(node, &text, &d_text, flag & 16);
687 d_ret= (d_text != NULL);
688 if(ret < 0 || d_ret < 0) {
689 if(path != NULL && path[0] != 0) {
690 strcpy(xorriso->info_text, "Error with obtaining ACL of ");
691 Text_shellsafe(path, xorriso->info_text, 1);
692 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
693 }
694 ret= 0; goto ex;
695 }
696 if(flag & 2) {
697 ret= 1 + (ret != 1 && d_ret == 0);
698 goto ex;
699 }
700 if((ret == 0 || ret == 2) && d_ret == 0) {
701 if(flag & 1) {
702 ret= 1 + (ret == 0);
703 goto ex;
704 }
705 strcpy(xorriso->info_text, "No ACL associated with ");
706 Text_shellsafe(path, xorriso->info_text, 1);
707 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
708 if(ret == 0)
709 {ret= 2; goto ex;}
710 }
711
712 if(!(flag & 1)) {
713 ret= Xorriso_getfname(xorriso, path, 0);
714 if(ret <= 0)
715 goto ex;
716 uid= iso_node_get_uid(node);
717 pwd= getpwuid(uid);
718 if(pwd == NULL)
719 sprintf(xorriso->result_line, "# owner: %.f\n", (double) uid);
720 else
721 sprintf(xorriso->result_line, "# owner: %s\n", pwd->pw_name);
722 Xorriso_result(xorriso, 0);
723 gid= iso_node_get_gid(node);
724 grp= getgrgid(gid);
725 if(grp == NULL)
726 sprintf(xorriso->result_line, "# group: %.f\n", (double) gid);
727 else
728 sprintf(xorriso->result_line, "# group: %s\n", grp->gr_name);
729 Xorriso_result(xorriso, 0);
730 }
731
732 for(pass= 0; pass < 1 + (acl_text != NULL && !(flag & 2)); pass++) {
733 if(pass) {
734 if(result_len == 0)
735 break;
736 *acl_text= calloc(result_len + 1, 1);
737 if(*acl_text == NULL) {
738 Xorriso_no_malloc_memory(xorriso, NULL, 0);
739 ret= -1; goto ex;
740 }
741 }
742 if(text != NULL && what <= 1) {
743 for(npt= cpt= text; npt != NULL; cpt= npt + 1) {
744 npt= strchr(cpt, '\n');
745 if(npt != NULL)
746 *npt= 0;
747 if(*cpt == 0) {
748 if(d_text != NULL || pass) {
749 if(npt != NULL)
750 *npt= '\n';
751 continue;
752 }
753 } else
754 result_len+= strlen(cpt) + 1;
755 if(pass) {
756 sprintf(*acl_text + strlen(*acl_text), "%s\n", cpt);
757 } else if(!(flag & 1)) {
758 if(Sfile_str(xorriso->result_line, cpt, 0) <= 0)
759 goto too_long;
760 strcat(xorriso->result_line, "\n");
761 Xorriso_result(xorriso, 0);
762 }
763 if(npt != NULL)
764 *npt= '\n';
765 }
766 }
767 if(d_text != NULL && (what == 0 || what == 2)) {
768 for(npt= cpt= d_text; npt != NULL; cpt= npt + 1) {
769 npt= strchr(cpt, '\n');
770 if(npt != NULL)
771 *npt= 0;
772 if(*cpt != 0) {
773 if(pass) {
774 if(what == 0)
775 sprintf(*acl_text + strlen(*acl_text), "default:%s\n", cpt);
776 else
777 sprintf(*acl_text + strlen(*acl_text), "%s\n", cpt);
778 } else {
779 xorriso->result_line[0]= 0;
780 if(what == 0)
781 if(Sfile_str(xorriso->result_line, "default:", 0) <= 0)
782 goto too_long;
783 if(Sfile_str(xorriso->result_line, cpt, 1) <= 0)
784 goto too_long;
785 result_len+= strlen(cpt) + 9;
786 }
787 } else
788 xorriso->result_line[0]= 0;
789 if(pass== 0 && !(flag & 1)) {
790 strcat(xorriso->result_line, "\n");
791 Xorriso_result(xorriso, 0);
792 }
793 if(npt != NULL)
794 *npt= '\n';
795 }
796 }
797 }
798 if(result_len == 0) {
799 if(acl_text != NULL)
800 *acl_text= NULL;
801 ret= 2;
802 } else {
803 ret= 1;
804 }
805 ex:;
806 iso_node_get_acl_text(node, &text, &d_text, 1 << 15);
807 return(ret);
808 too_long:
809 Xorriso_msgs_submit(xorriso, 0, "Oversized ACL", 0, "FAILURE", 0);
810 ret= 0;
811 goto ex;
812 }
813
814
815 /*
816 @param flag bit0= do not report to result but only retrieve attr text
817 bit1= path is disk_path
818 bit3= do not ignore non-user attributes
819 bit4= ignore isofs. attributes despite bit3
820 bit5= in case of symbolic link on disk: inquire link target
821 bit6= check for existence of xattr, return 0 or 1
822 (depends also on bit3)
823 */
824 int Xorriso_getfattr(struct XorrisO *xorriso, void *in_node, char *path,
825 char **attr_text, int flag)
826 {
827 int ret= 1, i, bsl_mem, result_len= 0, pass;
828 size_t num_attrs= 0, *value_lengths= NULL;
829 char **names= NULL, **values= NULL, *bsl;
830
831 if(attr_text != NULL)
832 *attr_text= NULL;
833 if((xorriso->do_aaip & 1024) && !(flag & 8))
834 flag|= 8 | 16;
835 ret= Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
836 &value_lengths, &values, flag & (2 | 8 | 32));
837 if(ret <= 0)
838 goto ex;
839 if(flag & 64) {
840 ret= (num_attrs > 0);
841 goto ex;
842 }
843 if(num_attrs == 0)
844 {ret= 2; goto ex;}
845
846 if(!(flag & 1)) {
847 ret= Xorriso_getfname(xorriso, path, 0);
848 if(ret <= 0)
849 goto ex;
850 }
851 for(pass= 0; pass < 1 + (attr_text != NULL); pass++) {
852 if(pass) {
853 *attr_text= calloc(result_len + 1, 1);
854 if(*attr_text == NULL) {
855 Xorriso_no_malloc_memory(xorriso, NULL, 0);
856 ret= -1; goto ex;
857 }
858 }
859 for(i= 0; i < (int) num_attrs; i++) {
860 if(flag & 16)
861 if(strncmp(names[i], "isofs.", 6) == 0)
862 continue;
863 if(strlen(names[i]) + value_lengths[i] >= SfileadrL) {
864 sprintf(xorriso->result_line, "# oversized: name %d , value %d bytes\n",
865 (int) strlen(names[i]), (int) value_lengths[i]);
866 } else {
867 ret= Sfile_bsl_encoder(&bsl, names[i], strlen(names[i]), 8);
868 if(ret <= 0)
869 {ret= -1; goto ex;}
870 strcpy(xorriso->result_line, bsl);
871 free(bsl);
872 ret= Sfile_bsl_encoder(&bsl, values[i], value_lengths[i], 8);
873 if(ret <= 0)
874 {ret= -1; goto ex;}
875 sprintf(xorriso->result_line + strlen(xorriso->result_line),
876 "=\"%s\"\n", bsl);
877 free(bsl);
878 }
879 /* temporarily disable -backslash_codes with result output */
880 result_len+= strlen(xorriso->result_line);
881 if(pass) {
882 strcat(*attr_text, xorriso->result_line);
883 } else if(!(flag & 1)) {
884 bsl_mem= xorriso->bsl_interpretation;
885 xorriso->bsl_interpretation= 0;
886 Xorriso_result(xorriso, 0);
887 xorriso->bsl_interpretation= bsl_mem;
888 }
889 }
890 }
891 if((flag & 16) && attr_text != NULL)
892 if(*attr_text != NULL)
893 if((*attr_text)[0] == 0) {
894 free(*attr_text);
895 *attr_text= NULL;
896 ret= 2;
897 goto ex;
898 }
899 if(!(flag & 1)) {
900 strcpy(xorriso->result_line, "\n");
901 Xorriso_result(xorriso, 0);
902 }
903 ret= 1;
904 ex:;
905 Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
906 &value_lengths, &values, 1 << 15);
907 return(ret);
908 }
909
910
911 /*
912 @param flag bit0= with mode "e" : Use echo -e encoding but
913 do not put out commands and quotation marks.
914 Rather apply double backslash.
915 */
916 int Xorriso_append_extattr_comp(struct XorrisO *xorriso,
917 char *comp, size_t comp_len,
918 char *mode, int flag)
919 {
920 int ret;
921 size_t line_limit;
922 char *line, *wpt, *bsl = NULL;
923 unsigned char *upt, *uval;
924
925 line= xorriso->result_line;
926 line_limit= sizeof(xorriso->result_line);
927 uval= (unsigned char *) comp;
928
929 if(*mode == 'q') {
930 Text_shellsafe(comp, line, 1);
931 } else if(*mode == 'e' || mode[0] == 0) {
932 for(upt= uval; (size_t) (upt - uval) < comp_len; upt++)
933 if(*upt <= 037 || *upt >= 0177)
934 break;
935 if((size_t) (upt - uval) < comp_len || (flag & 1)) {
936 /* Use "$(echo -e '\0xyz')" */;
937 if(!(flag & 1))
938 strcat(line, "\"$(echo -e '");
939 wpt= line + strlen(line);
940 for(upt= uval; (size_t) (upt - uval) < comp_len; upt++) {
941 if(wpt - line + 5 + 3 + 1 > (ssize_t) line_limit)
942 /* "\\0xyz" + "')\"" + 0 */
943 goto too_much;
944 if(*upt <= 037 || *upt >= 0177 || *upt == '\\' || *upt == '\'') {
945 if(flag & 1)
946 *(wpt++)= '\\';
947 sprintf((char *) wpt, "\\0%-3.3o", *upt);
948 wpt+= strlen(wpt);
949 } else {
950 *(wpt++)= *upt;
951 }
952 }
953 *wpt= 0;
954 if(!(flag & 1))
955 strcpy(wpt, "')\"");
956 } else {
957 Text_shellsafe(comp, line, 1);
958 }
959 } else if(*mode == 'b') {
960 ret= Sfile_bsl_encoder(&bsl, comp, comp_len, 8);
961 if(ret <= 0)
962 {ret= -1; goto ex;}
963 if(strlen(line) + strlen(bsl) + 1 > line_limit)
964 goto too_much;
965 strcat(line, bsl);
966 free(bsl);
967 bsl= NULL;
968 } else if(*mode == 'r') {
969 if(strlen(line) + strlen(comp) + 1 > line_limit)
970 goto too_much;
971 strcat(line, comp);
972 }
973 ret= 1;
974 ex:;
975 if(bsl != NULL)
976 free(bsl);
977 return(ret);
978 too_much:;
979 Xorriso_msgs_submit(xorriso, 0, "Oversized BSD-style file attribute",
980 0, "FAILURE", 0);
981 ret= -1;
982 goto ex;
983 }
984
985
986 /*
987 @param flag bit1= path is disk_path
988 bit3= do not ignore eventual non-user attributes.
989 bit5= in case of symbolic link on disk: inquire link target
990 */
991 int Xorriso_list_extattr(struct XorrisO *xorriso, void *in_node, char *path,
992 char *show_path, char *mode, int flag)
993 {
994 int ret= 1, i, bsl_mem;
995 size_t num_attrs= 0, *value_lengths= NULL;
996 char **names= NULL, **values= NULL, *cpt, *space_pt, *name_pt, *path_pt;
997 char *line;
998 unsigned char *upt, *uval;
999
1000 line= xorriso->result_line;
1001 ret= Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
1002 &value_lengths, &values, flag & (2 | 8 | 32));
1003 if(ret <= 0)
1004 goto ex;
1005 if(flag & 64) {
1006 ret= (num_attrs > 0);
1007 goto ex;
1008 }
1009 if(num_attrs == 0)
1010 {ret= 2; goto ex;}
1011
1012 strcpy(line, "n=");
1013 path_pt= show_path + (show_path[0] == '/');
1014 if(path_pt[0] == 0)
1015 path_pt= ".";
1016 ret= Xorriso_append_extattr_comp(xorriso, path_pt, strlen(path_pt), mode, 0);
1017 if(ret <= 0)
1018 goto ex;
1019 strcat(line, "\n");
1020 Xorriso_result(xorriso, 0);
1021 for(i= 0; i < (int) num_attrs; i++) {
1022 line[0]= 0;
1023 uval= (unsigned char *) values[i];
1024
1025 if(strlen(names[i]) + value_lengths[i] >= SfileadrL) {
1026 sprintf(line,
1027 "echo 'OMITTED: Oversized: name %d bytes, value %d bytes in file '\"$n\" >&2\n",
1028 (int) strlen(names[i]), (int) value_lengths[i]);
1029 Xorriso_result(xorriso, 0);
1030 continue;
1031 }
1032
1033 /* Form: $c space name value $n */
1034
1035 /* Split namespace from name */
1036 cpt= strchr(names[i], '.');
1037 if(cpt == NULL) {
1038 space_pt= "user";
1039 name_pt= names[i];
1040 } else {
1041 *cpt= 0;
1042 space_pt= names[i];
1043 name_pt= cpt + 1;
1044 }
1045
1046 /* FreeBSD setextattr cannot set 0-bytes */
1047 for(upt= uval; (size_t) (upt - uval) < value_lengths[i]; upt++)
1048 if(*upt == 0
1049 )
1050 break;
1051 if((size_t) (upt - uval) < value_lengths[i]) {
1052 strcpy(line, "echo 'OMITTED: Value contains 0-bytes : space \"'\"");
1053 ret= Xorriso_append_extattr_comp(xorriso, space_pt, strlen(space_pt),
1054 "e", 1);
1055 if(ret <= 0)
1056 goto ex;
1057 strcat(line, "\"'\" , name \"'\"");
1058 ret= Xorriso_append_extattr_comp(xorriso, name_pt, strlen(name_pt),
1059 "e", 1);
1060 if(ret <= 0)
1061 goto ex;
1062 strcat(line, "\"'\" in file '\"");
1063 ret= Xorriso_append_extattr_comp(xorriso, path_pt, strlen(path_pt),
1064 "e", 1);
1065 if(ret <= 0)
1066 goto ex;
1067 strcat(line, "\" >&2\n");
1068
1069 /* temporarily disable -backslash_codes with result output */
1070 bsl_mem= xorriso->bsl_interpretation;
1071 xorriso->bsl_interpretation= 0;
1072 Xorriso_result(xorriso, 0);
1073 xorriso->bsl_interpretation= bsl_mem;
1074 strcpy(line, "# ");
1075 }
1076
1077 strcat(line, "$c ");
1078 ret= Xorriso_append_extattr_comp(xorriso, space_pt, strlen(space_pt),
1079 mode, 0);
1080 if(ret <= 0)
1081 goto ex;
1082 strcat(line, " ");
1083 ret= Xorriso_append_extattr_comp(xorriso,name_pt, strlen(name_pt), mode, 0);
1084 if(ret <= 0)
1085 goto ex;
1086 strcat(line, " ");
1087 ret= Xorriso_append_extattr_comp(xorriso, values[i], value_lengths[i],
1088 mode, 0);
1089 if(ret <= 0)
1090 goto ex;
1091 strcat(line, " \"$n\"\n");
1092
1093 /* temporarily disable -backslash_codes with result output */
1094 bsl_mem= xorriso->bsl_interpretation;
1095 xorriso->bsl_interpretation= 0;
1096 Xorriso_result(xorriso, 0);
1097 xorriso->bsl_interpretation= bsl_mem;
1098 }
1099 strcpy(line, "\n");
1100 Xorriso_result(xorriso, 0);
1101 ret= 1;
1102 ex:;
1103 Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
1104 &value_lengths, &values, 1 << 15);
1105 return(ret);
1106 }
1107
1108
1109 /*
1110 @param flag
1111 Bitfield for control purposes
1112 bit0= get default ACL rather than access ACL
1113 bit4= set *text = NULL and return 2
1114 if the ACL matches st_mode permissions.
1115 bit5= in case of symbolic link: inquire link target
1116 bit15= free text and return 1
1117 @return
1118 1 ok
1119 2 ok, trivial ACL found while bit4 is set, *text is NULL
1120 0 no ACL manipulation adapter available / ACL not supported by fs
1121 -1 failure of system ACL service (see errno)
1122 -2 attempt to inquire ACL of a symbolic link without bit4 or bit5
1123 resp. with no suitable link target
1124 */
1125 int Xorriso_local_getfacl(struct XorrisO *xorriso, char *disk_path,
1126 char **text, int flag)
1127 {
1128 int ret, skip= 0, colons= 0, countdown= 0;
1129 char *acl= NULL, *cpt, *wpt;
1130
1131 if(flag & (1 << 15)) {
1132 if(*text != NULL)
1133 free(*text);
1134 *text= NULL;
1135 return(1);
1136 }
1137 *text= NULL;
1138 ret= iso_local_get_acl_text(disk_path, &acl, flag & (1 | 16 | 32));
1139 Xorriso_process_msg_queues(xorriso,0);
1140 if(ret < 0 || ret == 2)
1141 return(ret);
1142 if(acl == NULL)
1143 return(0);
1144 *text= strdup(acl);
1145 iso_local_get_acl_text(disk_path, &acl, 1 << 15);
1146 if(*text == NULL) {
1147 Xorriso_no_malloc_memory(xorriso, NULL, 0);
1148 return(-1);
1149 }
1150
1151 /* Garbage collection about trailing remarks after 3 permission chars */
1152 wpt= *text;
1153 for(cpt= *text; *cpt; cpt++) {
1154 if(skip) {
1155 if(*cpt == '\n')
1156 skip= 0;
1157 else
1158 continue;
1159 }
1160 if(*cpt == ':' && !countdown) {
1161 colons++;
1162 if(colons == 2) {
1163 countdown= 4;
1164 colons= 0;
1165 }
1166 }
1167 if(countdown > 0) {
1168 countdown--;
1169 if(countdown == 0)
1170 skip= 1;
1171 }
1172 *wpt= *cpt;
1173 wpt++;
1174 }
1175 *wpt= 0;
1176
1177 return(1);
1178 }
1179
1180
1181 /*
1182 @param flag
1183 bit1= path is disk_path
1184 bit3= do not ignore eventual non-user attributes.
1185 bit5= in case of symbolic link on disk: inquire link target
1186 bit15= free memory
1187 */
1188 int Xorriso_get_attrs(struct XorrisO *xorriso, void *in_node, char *path,
1189 size_t *num_attrs, char ***names,
1190 size_t **value_lengths, char ***values, int flag)
1191 {
1192 int ret, i, widx;
1193 IsoNode *node;
1194
1195 if(flag & (1 << 15)) {
1196 if(flag & 2) {
1197 iso_local_get_attrs(NULL, num_attrs, names, value_lengths, values,
1198 1 << 15);
1199 } else {
1200 iso_node_get_attrs(NULL, num_attrs, names, value_lengths, values,
1201 1 << 15);
1202 }
1203 return(1);
1204 }
1205
1206 *num_attrs= 0;
1207 if(flag & 2) {
1208 ret= iso_local_get_attrs(path, num_attrs, names, value_lengths, values,
1209 flag & (8 | 32));
1210 if(ret < 0) {
1211 strcpy(xorriso->info_text, "Error with reading xattr of disk file ");
1212 Text_shellsafe(path, xorriso->info_text, 1);
1213 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
1214 }
1215 } else {
1216 node= (IsoNode *) in_node;
1217 if(node == NULL) {
1218 ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
1219 if(ret<=0)
1220 goto ex;
1221 }
1222 ret= iso_node_get_attrs(node, num_attrs, names, value_lengths, values,
1223 0);
1224 if(ret < 0) {
1225 Xorriso_report_iso_error(xorriso, "", ret,
1226 "Error when obtaining xattr of ISO node", 0, "FAILURE", 1);
1227 goto ex;
1228 }
1229
1230 if(!(flag & 8)) {
1231 /* Filter away any non-userspace xattr */;
1232 widx= 0;
1233 for(i= 0; i < (int) *num_attrs; i++) {
1234 if(strncmp((*names)[i], "user.", 5) != 0) {
1235 free((*names)[i]);
1236 (*names)[i]= NULL;
1237 if((*values)[i] != NULL) {
1238 free((*values)[i]);
1239 (*values)[i]= NULL;
1240 }
1241 } else {
1242 if(widx != i) {
1243 (*names)[widx]= (*names)[i];
1244 (*value_lengths)[widx]= (*value_lengths)[i];
1245 (*values)[widx]= (*values)[i];
1246 (*names)[i]= NULL;
1247 (*value_lengths)[i]= 0;
1248 (*values)[i]= NULL;
1249 }
1250 widx++;
1251 }
1252 }
1253 *num_attrs= widx;
1254 }
1255 }
1256 ret= 1;
1257 ex:;
1258 Xorriso_process_msg_queues(xorriso,0);
1259 return(ret);
1260 }
1261
1262
1263 int Xorriso_get_attr_value(struct XorrisO *xorriso, void *in_node, char *path,
1264 char *name, size_t *value_length, char **value, int flag)
1265 {
1266 int ret;
1267 size_t num_attrs= 0, *value_lengths= NULL, i;
1268 char **names = NULL, **values= NULL;
1269
1270 *value= NULL;
1271 *value_length= 0;
1272 ret= Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
1273 &value_lengths, &values, 8);
1274 if(ret <= 0)
1275 goto ex;
1276
1277 for(i= 0; i < num_attrs; i++) {
1278 if(strcmp(name, names[i]) != 0)
1279 continue;
1280 *value= calloc(value_lengths[i] + 1, 1);
1281 if(*value == NULL)
1282 {ret= -1; goto ex;}
1283 memcpy(*value, values[i], value_lengths[i]);
1284 (*value)[value_lengths[i]]= 0;
1285 *value_length= value_lengths[i];
1286 ret= 1; goto ex;
1287 }
1288 ret= 0;
1289 ex:
1290 Xorriso_get_attrs(xorriso, in_node, path, &num_attrs, &names,
1291 &value_lengths, &values, 1 << 15);
1292 return(ret);
1293 }
1294
1295
1296 int Xorriso_stream_type(struct XorrisO *xorriso, IsoNode *node,
1297 IsoStream *stream, char type_text[], int flag)
1298 {
1299 int ret, lba, stream_type, block_size_log2;
1300 uint8_t zisofs_algo[2], algo_num;
1301 char text[5];
1302
1303 strncpy(text, stream->class->type, 4);
1304 text[4]= 0;
1305 if(strcmp(text, "fsrc") == 0) {
1306 ret= Xorriso__file_start_lba(node, &lba, 0);
1307 if(ret > 0 && lba > 0)
1308 strcpy(type_text, "image");
1309 else
1310 strcpy(type_text, "disk");
1311 } else if(strcmp(text, "ziso") == 0 || strcmp(text, "osiz") == 0) {
1312 if(strcmp(text, "ziso") == 0)
1313 strcpy(type_text, "--zisofs");
1314 else
1315 strcpy(type_text, "--zisofs-decode");
1316 ret= iso_stream_get_zisofs_par(stream, &stream_type, zisofs_algo, &algo_num,
1317 &block_size_log2, 0);
1318 if(ret == 1)
1319 sprintf(type_text + strlen(type_text), ":%c%c:%dk",
1320 zisofs_algo[0], zisofs_algo[1], 1 << (block_size_log2 - 10));
1321 } else if(strcmp(text, "gzip") == 0) {
1322 strcpy(type_text, "--gzip");
1323 } else if(strcmp(text, "pizg") == 0) {
1324 strcpy(type_text, "--gunzip");
1325 } else if(strcmp(text, "cout") == 0 || strcmp(text, "boot") == 0 ||
1326 strcmp(text, "user") == 0 || strcmp(text, "extf") == 0) {
1327 strcpy(type_text, text);
1328 } else {
1329 Text_shellsafe(text, type_text, 0);
1330 }
1331 return(1);
1332 }
1333
1334
1335 /*
1336 @param flag bit0= do not report to result but only retrieve md5 text
1337 @return 1= ok, 0= no md5 available, <0= other error
1338 */
1339 int Xorriso_get_md5(struct XorrisO *xorriso, void *in_node, char *path,
1340 char md5[16], int flag)
1341 {
1342 int ret= 1, i;
1343 char *wpt;
1344 IsoImage *image;
1345 IsoNode *node;
1346
1347 ret= Xorriso_get_volume(xorriso, &image, 0);
1348 if(ret <= 0)
1349 goto ex;
1350 node= (IsoNode *) in_node;
1351 if(node == NULL) {
1352 ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
1353 if(ret<=0)
1354 goto ex;
1355 }
1356 if(!LIBISO_ISREG(node))
1357 return(0);
1358 ret= iso_file_get_md5(image, (IsoFile *) node, md5, 0);
1359 Xorriso_process_msg_queues(xorriso,0);
1360 if(ret <= 0)
1361 goto ex;
1362 if(flag & 1)
1363 {ret= 1; goto ex;}
1364
1365 wpt= xorriso->result_line;
1366 for(i= 0; i < 16; i++) {
1367 sprintf(wpt, "%2.2x", ((unsigned char *) md5)[i]);
1368 wpt+= 2;
1369 }
1370 strcpy(wpt, " ");
1371 wpt+= 2;
1372 Xorriso_getfname(xorriso, path, 1 | 2);
1373 ret= 1;
1374 ex:;
1375 return(ret);
1376 }
1377
1378
1379 int Xorriso_make_md5(struct XorrisO *xorriso, void *in_node, char *path,
1380 int flag)
1381 {
1382 int ret;
1383 off_t size;
1384 IsoNode *node;
1385
1386 node= (IsoNode *) in_node;
1387 if(node == NULL) {
1388 ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
1389 if(ret <= 0)
1390 return(ret);
1391 }
1392 if(!LIBISO_ISREG(node))
1393 return(0);
1394 ret= iso_file_make_md5((IsoFile *) node, 0);
1395 size= iso_file_get_size((IsoFile *) node);
1396 xorriso->pacifier_count+= size;
1397 xorriso->pacifier_byte_count+= size;
1398 Xorriso_pacifier_callback(xorriso, "content bytes read",
1399 xorriso->pacifier_count, 0, "", 8);
1400 Xorriso_process_msg_queues(xorriso, 0);
1401 if(ret < 0) {
1402 Xorriso_report_iso_error(xorriso, "", ret,
1403 "Error when computing MD5", 0, "FAILURE", 1);
1404 return(0);
1405 }
1406 Xorriso_set_change_pending(xorriso, 1);
1407 return(1);
1408 }
1409
1410
1411 /* @param flag bit0= do not only sum up sizes but also print subdirs
1412
1413 bit2= do not report result by Xorriso_result()
1414 */
1415 int Xorriso_show_du_subs(struct XorrisO *xorriso, IsoDir *dir_node,
1416 char *abs_path, char *rel_path, off_t *size,
1417 off_t boss_mem, int flag)
1418 {
1419 int i, ret, no_sort= 0, filec= 0, l;
1420 IsoDirIter *iter= NULL;
1421 IsoNode *node, **node_array= NULL;
1422 char *name;
1423 off_t sub_size, report_size, mem= 0;
1424 char *path= NULL, *show_path= NULL, *sfe= NULL;
1425
1426 Xorriso_alloc_meM(sfe, char, 5 * SfileadrL);
1427 Xorriso_alloc_meM(path, char, SfileadrL);
1428 Xorriso_alloc_meM(show_path, char, SfileadrL);
1429
1430 *size= 0;
1431 ret= iso_dir_get_children(dir_node, &iter);
1432 if(ret<0) {
1433 cannot_create_iter:;
1434 Xorriso_cannot_create_iter(xorriso, ret, 0);
1435 {ret= -1; goto ex;}
1436 }
1437 for(i= 0; iso_dir_iter_next(iter, &node) == 1; ) {
1438 sub_size= 0;
1439 name= (char *) iso_node_get_name(node);
1440 strcpy(show_path, rel_path);
1441 if(Sfile_add_to_path(show_path, name, 0)<=0)
1442 goto much_too_long;
1443 if(LIBISO_ISDIR(node)) {
1444 strcpy(path, abs_path);
1445 if(Sfile_add_to_path(path, name, 0)<=0) {
1446 much_too_long:;
1447 Xorriso_much_too_long(xorriso, strlen(path)+strlen(name)+1, 2);
1448 {ret= -1; goto ex;}
1449 }
1450 filec++;
1451 l= strlen(rel_path)+1;
1452 mem+= l;
1453 if(l % sizeof(char *))
1454 mem+= sizeof(char *)-(l % sizeof(char *));
1455 if(flag&1) /* diving and counting is done further below */
1456 continue;
1457 ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node,
1458 path, show_path, &sub_size, boss_mem, 0);
1459 if(ret<0)
1460 goto ex;
1461 if(ret==0)
1462 continue;
1463 }
1464
1465 if(LIBISO_ISREG(node)) {
1466 sub_size+= iso_file_get_size((IsoFile *) node)+2048;
1467 /*
1468 sub_size+= iso_file_get_size((IsoFile *) node)+strlen(name)+1;
1469 */
1470 }
1471
1472 if(sub_size>0)
1473 (*size)+= sub_size;
1474 Xorriso_process_msg_queues(xorriso,0);
1475 }
1476
1477 if(filec<=0 || !(flag&1))
1478 {ret= 1; goto ex;}
1479
1480 /* Reset iteration */
1481 iso_dir_iter_free(iter);
1482 iter= NULL;
1483 Xorriso_process_msg_queues(xorriso,0);
1484
1485 ret= Xorriso_sorted_node_array(xorriso, dir_node, &filec, &node_array,
1486 boss_mem, 1|2|4);
1487 if(ret<0)
1488 goto ex;
1489 if(ret==0) {
1490 no_sort= 1;
1491 ret= iso_dir_get_children(dir_node, &iter);
1492 if(ret<0)
1493 goto cannot_create_iter;
1494 }
1495
1496 for(i= 0; (no_sort || i<filec) && !(xorriso->request_to_abort); i++) {
1497 if(no_sort) {
1498 ret= iso_dir_iter_next(iter, &node);
1499 if(ret!=1)
1500 break;
1501 if(!LIBISO_ISDIR(node))
1502 continue;
1503 } else
1504 node= node_array[i];
1505
1506 sub_size= 0;
1507 name= (char *) iso_node_get_name(node);
1508 strcpy(show_path, rel_path);
1509 if(Sfile_add_to_path(show_path, name, 0)<=0)
1510 goto much_too_long;
1511 strcpy(path, abs_path);
1512 if(Sfile_add_to_path(path, name, 0)<=0)
1513 goto much_too_long;
1514 ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node,
1515 path, show_path, &sub_size, boss_mem+mem, flag&1);
1516 if(ret<0)
1517 goto ex;
1518
1519 if(LIBISO_ISREG(node)) {
1520 sub_size+= iso_file_get_size((IsoFile *) node)+2048;
1521 /*
1522 sub_size+= iso_tree_node_get_size((IsoFile *) node)+strlen(name)+1;
1523 */
1524 }
1525 if(sub_size>0)
1526 (*size)+= sub_size;
1527 report_size= sub_size/1024;
1528 if(report_size*1024<sub_size)
1529 report_size++;
1530 if(!(flag & 4)) {
1531 if(xorriso->sh_style_result)
1532 sprintf(xorriso->result_line, "%-7.f ",(double) (report_size));
1533 else
1534 sprintf(xorriso->result_line, "%7.f ",(double) (report_size));
1535 sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n",
1536 Xorriso_esc_filepath(xorriso, show_path, sfe, 0));
1537 Xorriso_result(xorriso, 0);
1538 }
1539 }
1540 ret= 1;
1541 ex:;
1542 Xorriso_free_meM(sfe);
1543 Xorriso_free_meM(path);
1544 Xorriso_free_meM(show_path);
1545 if(iter!=NULL)
1546 iso_dir_iter_free(iter);
1547 if(node_array!=NULL)
1548 free((char *) node_array);
1549 Xorriso_process_msg_queues(xorriso,0);
1550 return(ret);
1551 }
1552
1553
1554 int Xorriso_sorted_dir_i(struct XorrisO *xorriso, IsoDir *dir_node,
1555 int *filec, char ***filev, off_t boss_mem, int flag)
1556 {
1557 int i,j,ret;
1558 IsoDirIter *iter= NULL;
1559 IsoNode *node;
1560 char *name;
1561 off_t mem;
1562
1563 (*filec)= 0;
1564 (*filev)= NULL;
1565
1566 ret= iso_dir_get_children(dir_node, &iter);
1567 if(ret<0) {
1568 cannot_iter:;
1569 Xorriso_cannot_create_iter(xorriso, ret, 0);
1570 {ret= -1; goto ex;}
1571 }
1572 mem= 0;
1573 for(i= 0; iso_dir_iter_next(iter, &node) == 1; ) {
1574 name= (char *) iso_node_get_name(node);
1575 mem+= sizeof(char *)+strlen(name)+8;
1576 (*filec)++;
1577 }
1578 iso_dir_iter_free(iter);
1579 iter= NULL;
1580 if(*filec==0)
1581 {ret= 1; goto ex;}
1582
1583 ret= Xorriso_check_temp_mem_limit(xorriso, mem+boss_mem, 2);
1584 if(ret<=0)
1585 goto ex;
1586 (*filev)= (char **) calloc(*filec, sizeof(char *));
1587 if(*filev==NULL)
1588 {ret= -1; goto ex; }
1589 ret= iso_dir_get_children(dir_node, &iter);
1590 if(ret<0)
1591 goto cannot_iter;
1592 for(i= 0; i<*filec; i++) {
1593 ret= iso_dir_iter_next(iter, &node);
1594 if(ret!=1)
1595 break;
1596 name= (char *) iso_node_get_name(node);
1597 (*filev)[i]= strdup(name);
1598 if((*filev)[i]==NULL) {
1599 for(j= 0; j<i; j++)
1600 if((*filev)[j]!=NULL)
1601 free((*filev)[j]);
1602 free((char *) (*filev));
1603 ret= -1; goto ex;
1604 }
1605 }
1606 Sort_argv(*filec, *filev, 0);
1607 ret= 1;
1608 ex:;
1609 if(iter!=NULL)
1610 iso_dir_iter_free(iter);
1611 return(ret);
1612 }
1613
1614
1615 int Xorriso_node_eff_hidden(struct XorrisO *xorriso, IsoNode *node, int flag)
1616 {
1617 int hidden_state= 0, ret;
1618 IsoNode *current, *parent;
1619
1620 current= node;
1621 for(current= node; hidden_state != 7;) {
1622 ret= iso_node_get_hidden(current);
1623 if(ret & LIBISO_HIDE_ON_RR)
1624 hidden_state|= 1;
1625 if(ret & LIBISO_HIDE_ON_JOLIET)
1626 hidden_state|= 2;
1627 if(ret & LIBISO_HIDE_ON_HFSPLUS)
1628 hidden_state|= 4;
1629 parent= (IsoNode *) iso_node_get_parent(current);
1630 if(parent == current)
1631 break;
1632 current= parent;
1633 }
1634 return(hidden_state);
1635 }
1636
1637
1638 /* @param flag bit0= do not truncate components which contain any of "*?["
1639 */
1640 int Xorriso_truncate_path_comps(struct XorrisO *xorriso, char *path,
1641 char *buffer, char **resultpt, int flag)
1642 {
1643 char *rpt, *basrpt, *wpt, *baswpt, *cpt;
1644 int ended, ret, skip;
1645
1646 *resultpt= path;
1647
1648 /* Check component lengths */
1649 rpt= path;
1650 if(*rpt == '/')
1651 rpt++;
1652 for(ended= 0; !ended;) {
1653 basrpt= rpt;
1654 rpt= strchr(basrpt, '/');
1655 if(rpt == NULL) {
1656 rpt= basrpt + strlen(basrpt);
1657 ended= 1;
1658 }
1659 skip= 0;
1660 if(flag & 1) {
1661 for(cpt= basrpt; cpt < rpt; cpt++) {
1662 if(strchr("*?[", *cpt) != NULL) {
1663 skip= 1;
1664 break;
1665 }
1666 }
1667 }
1668 if((!skip) && rpt - basrpt > xorriso->file_name_limit) {
1669 ended= 0;
1670 break;
1671 }
1672 if(*rpt == '/')
1673 rpt++;
1674 }
1675 if(ended)
1676 return(1); /* All short enough */
1677
1678 /* Some truncation is needed */
1679 buffer[0]= 0;
1680 wpt= buffer;
1681 if(path[0] == '/')
1682 *(wpt++)= '/';
1683 rpt= path;
1684 if(*rpt == '/')
1685 rpt++;
1686 for(ended= 0; !ended;) {
1687 basrpt= rpt;
1688 baswpt= wpt;
1689 rpt= strchr(basrpt, '/');
1690 if(rpt == NULL) {
1691 rpt= basrpt + strlen(basrpt);
1692 ended= 1;
1693 }
1694 skip= 0;
1695 for(cpt= basrpt; cpt < rpt; cpt++) {
1696 *(wpt++)= *cpt;
1697 if((flag & 1) && strchr("*?[", *cpt) != NULL)
1698 skip= 1;
1699 }
1700 *wpt= 0;
1701 if((!skip) && rpt - basrpt > xorriso->file_name_limit) {
1702 ret= iso_truncate_leaf_name(1, xorriso->file_name_limit, baswpt, 0);
1703 Xorriso_process_msg_queues(xorriso, 0);
1704 if(ret < 0)
1705 return(0);
1706 wpt= baswpt + strlen(baswpt);
1707 }
1708 if(!ended) {
1709 *(wpt++)= '/';
1710 rpt++;
1711 }
1712 }
1713 *resultpt= buffer;
1714 return(1);
1715 }
1716
1717
1718 /* @param flag bit0= long format
1719 bit1= do not print count of nodes
1720 bit2= du format
1721 bit3= print directories as themselves (ls -d)
1722 bit5= do not look for truncated versions of path component
1723 */
1724 int Xorriso_ls_filev(struct XorrisO *xorriso, char *wd,
1725 int filec, char **filev, off_t boss_mem, int flag)
1726 {
1727 int i, ret, was_error= 0, dfilec= 0, pass, passes, hidden_state= 0;
1728 IsoNode *node;
1729 IsoImage *volume;
1730 char *path= NULL, *link_target= NULL, *rpt, **dfilev= NULL;
1731 char *a_text= NULL, *d_text= NULL, *namept;
1732 off_t size;
1733 struct stat stbuf;
1734
1735 Xorriso_alloc_meM(path, char, SfileadrL);
1736 Xorriso_alloc_meM(link_target, char, SfileadrL);
1737
1738 rpt= xorriso->result_line;
1739
1740 ret= Xorriso_get_volume(xorriso, &volume, 0);
1741 if(ret<=0)
1742 goto ex;
1743
1744 Sort_argv(filec, filev, 0);
1745
1746 /* Count valid nodes, warn of invalid ones */
1747 for(i= 0; i<filec; i++) {
1748 ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4);
1749 if(ret<=0) {
1750 was_error++;
1751 continue;
1752 }
1753 ret= Xorriso_node_from_path(xorriso, volume, path, &node,
1754 1 | ((flag >> 4) & 2));
1755 if(ret<=0) {
1756 sprintf(xorriso->info_text, "Not found in ISO image: ");
1757 Text_shellsafe(path, xorriso->info_text, 1);
1758 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
1759 was_error++;
1760 continue;
1761 }
1762 }
1763
1764 if((flag&8) && !(flag&(2|4))) {
1765 sprintf(xorriso->info_text, "Valid ISO nodes found: %d\n", filec-was_error);
1766 Xorriso_info(xorriso,1);
1767 if(filec-was_error<=0)
1768 {ret= !was_error; goto ex;}
1769 }
1770
1771 passes= 1+!(flag&(4|8));
1772 for(pass= 0; pass<passes; pass++)
1773 for(i= 0; i<filec && !(xorriso->request_to_abort); i++) {
1774 rpt[0]= 0;
1775 ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4);
1776 if(ret<=0)
1777 continue;
1778 ret= Xorriso_fake_stbuf(xorriso, path, &stbuf, &node, ((flag&4) >> 1) | 16);
1779 if(ret<=0)
1780 continue;
1781 if(LIBISO_ISDIR(node) && !(flag&(4|8))) {
1782 if(pass==0)
1783 continue;
1784 if(filec>1) {
1785 strcpy(xorriso->result_line, "\n");
1786 Xorriso_result(xorriso,0);
1787 Xorriso_esc_filepath(xorriso, filev[i], xorriso->result_line, 0);
1788 strcat(xorriso->result_line, ":\n");
1789 Xorriso_result(xorriso,0);
1790 }
1791 ret= Xorriso_sorted_dir_i(xorriso,
1792 (IsoDir *) node, &dfilec, &dfilev, boss_mem, 0);
1793 if(ret<=0) {
1794
1795 /* >>> libisofs iterator loop and single item Xorriso_lsx_filev() */;
1796
1797 } else {
1798 if(flag&1) {
1799 sprintf(xorriso->result_line, "total %d\n", dfilec);
1800 Xorriso_result(xorriso,0);
1801 }
1802 Xorriso_ls_filev(xorriso, path,
1803 dfilec, dfilev, boss_mem, (flag & 1) | 2 | 8);
1804 }
1805 if(dfilec>0)
1806 Sfile_destroy_argv(&dfilec, &dfilev, 0);
1807 continue;
1808 } else
1809 if(pass>0)
1810 continue;
1811 link_target[0]= 0;
1812 if((flag&5)==1) { /* -ls_l */
1813 iso_node_get_acl_text(node, &a_text, &d_text, 16);
1814 hidden_state= Xorriso_node_eff_hidden(xorriso, node, 0);
1815 ret= Xorriso_format_ls_l(xorriso, &stbuf,
1816 1 | ((a_text != NULL || d_text != NULL) << 1) |
1817 (hidden_state << 2));
1818 iso_node_get_acl_text(node, &a_text, &d_text, 1 << 15);
1819 if(ret<=0)
1820 continue;
1821 if(LIBISO_ISLNK(node)) {
1822 if(Sfile_str(link_target, (char *) iso_symlink_get_dest(
1823 (IsoSymlink *) node), 0)<=0)
1824 link_target[0]= 0;
1825 }
1826 } else if(flag&4) { /* -du or -dus */
1827 size= stbuf.st_size;
1828 if(S_ISDIR(stbuf.st_mode)) {
1829 ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node,
1830 path, filev[i], &size, boss_mem, flag&1);
1831 if(ret<0)
1832 {ret= -1; goto ex;}
1833 if(ret==0)
1834 continue;
1835 }
1836 if(xorriso->sh_style_result)
1837 sprintf(rpt, "%-7.f ",(double) (size/1024));
1838 else
1839 sprintf(rpt, "%7.f ",(double) (size/1024));
1840 }
1841 Xorriso_truncate_path_comps(xorriso, filev[i], path, &namept, 0);
1842 if(link_target[0] && (flag&5)==1) {
1843 Xorriso_esc_filepath(xorriso, namept, xorriso->result_line, 1);
1844 strcat(xorriso->result_line, " -> ");
1845 Xorriso_esc_filepath(xorriso, link_target, xorriso->result_line, 1 | 2);
1846 } else {
1847 Xorriso_esc_filepath(xorriso, namept, xorriso->result_line, 1);
1848 }
1849 strcat(xorriso->result_line, "\n");
1850 Xorriso_result(xorriso, 0);
1851 }
1852 ret= !was_error;
1853 ex:;
1854 Xorriso_free_meM(path);
1855 Xorriso_free_meM(link_target);
1856 return(ret);
1857 }
1858
1859
1860 /*
1861 @return: <=0 = error, 1= directory tree, 2= path leads to non-directory
1862 */
1863 int Xorriso_get_dus(struct XorrisO *xorriso, char *iso_rr_path, off_t *size,
1864 off_t boss_mem, int flag)
1865 {
1866 int ret;
1867 IsoNode *node;
1868 char *path= NULL;
1869 struct stat stbuf;
1870
1871 Xorriso_alloc_meM(path, char, SfileadrL);
1872
1873 ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, iso_rr_path, path,
1874 1 | 2 | 4);
1875 if(ret <= 0)
1876 goto ex;
1877 ret= Xorriso_fake_stbuf(xorriso, path, &stbuf, &node, 0);
1878 if(ret <= 0)
1879 goto ex;
1880 if(!S_ISDIR(stbuf.st_mode)) {
1881 *size= stbuf.st_size;
1882 ret= 2; goto ex;
1883 }
1884 ret= Xorriso_show_du_subs(xorriso, (IsoDir *) node, path, iso_rr_path, size,
1885 boss_mem, 4);
1886 if(ret <= 0)
1887 goto ex;
1888 ret= 1;
1889 ex:
1890 Xorriso_free_meM(path);
1891 return(ret);
1892 }
1893
1894
1895 /* This function needs less buffer memory than Xorriso_ls_filev() but cannot
1896 perform structured pattern matching as done by Xorriso_expand_pattern()
1897 for subsequent Xorriso_ls_filev().
1898 @param flag bit0= long format
1899 bit1= only check for directory existence
1900 bit2= do not apply search pattern but accept any file
1901 bit3= just count nodes and return number
1902 */
1903 int Xorriso_ls(struct XorrisO *xorriso, int flag)
1904 {
1905 int ret, i, filec= 0, failed_at, no_sort= 0;
1906 IsoNode *node, **node_array= NULL;
1907 IsoDir *dir_node;
1908 IsoDirIter *iter= NULL;
1909 char *link_target= NULL, *npt, *rpt;
1910 struct stat stbuf;
1911
1912 Xorriso_alloc_meM(link_target, char, SfileadrL);
1913
1914 rpt= xorriso->result_line;
1915
1916 ret= Xorriso_dir_from_path(xorriso, "Working directory", xorriso->wdi,
1917 &dir_node, 0);
1918 if(ret <= 0)
1919 goto ex;
1920 ret= iso_dir_get_children(dir_node, &iter);
1921 if(ret<0) {
1922 cannot_create_iter:;
1923 Xorriso_cannot_create_iter(xorriso, ret, 0);
1924 {ret= -1; goto ex;}
1925 }
1926 Xorriso_process_msg_queues(xorriso,0);
1927
1928 for(i= 0; iso_dir_iter_next(iter, &node) == 1; ) {
1929 npt= (char *) iso_node_get_name(node);
1930 if(!(flag&4)) {
1931 ret= Xorriso_regexec(xorriso, npt, &failed_at, 0);
1932 if(ret)
1933 continue; /* no match */
1934 }
1935 filec++;
1936 }
1937 /* Reset iteration */
1938 iso_dir_iter_free(iter);
1939 iter= NULL;
1940 Xorriso_process_msg_queues(xorriso,0);
1941 if(flag&8)
1942 {ret= filec; goto ex;}
1943 sprintf(xorriso->info_text, "Valid ISO nodes found: %d\n", filec);
1944 Xorriso_info(xorriso,1);
1945
1946 ret= Xorriso_sorted_node_array(xorriso, dir_node, &filec, &node_array, 0,
1947 flag&4);
1948 if(ret<0)
1949 goto ex;
1950 if(ret==0) {
1951 no_sort= 1;
1952 ret= iso_dir_get_children(dir_node, &iter);
1953 if(ret<0)
1954 goto cannot_create_iter;
1955 }
1956
1957 for(i= 0; i<filec && !(xorriso->request_to_abort); i++) {
1958 if(no_sort) {
1959 ret= iso_dir_iter_next(iter, &node);
1960 if(ret!=1)
1961 break;
1962 npt= (char *) iso_node_get_name(node);
1963 if(!(flag&4)) {
1964 ret= Xorriso_regexec(xorriso, npt, &failed_at, 0);
1965 if(ret)
1966 continue; /* no match */
1967 }
1968 } else
1969 node= node_array[i];
1970
1971 npt= (char *) iso_node_get_name(node);
1972 link_target[0]= 0;
1973 if(LIBISO_ISLNK(node)) {
1974 if(Sfile_str(link_target, (char *) iso_symlink_get_dest(
1975 (IsoSymlink *) node), 0)<=0)
1976 link_target[0]= 0;
1977 }
1978 rpt[0]= 0;
1979 if(flag&1) {
1980 ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
1981 if(ret<=0)
1982 continue;
1983 ret= Xorriso_format_ls_l(xorriso, &stbuf, 1);
1984 if(ret<=0)
1985 continue;
1986 }
1987 if(link_target[0] && (flag&1)) {
1988 Xorriso_esc_filepath(xorriso, npt, xorriso->result_line, 1);
1989 strcat(xorriso->result_line, " -> ");
1990 Xorriso_esc_filepath(xorriso, link_target, xorriso->result_line, 1 | 2);
1991 } else {
1992 Xorriso_esc_filepath(xorriso, npt, xorriso->result_line, 1);
1993 }
1994 strcat(xorriso->result_line, "\n");
1995 Xorriso_result(xorriso, 0);
1996 }
1997
1998 ret= 1;
1999 ex:;
2000 if(iter!=NULL)
2001 iso_dir_iter_free(iter);
2002 Xorriso_process_msg_queues(xorriso,0);
2003 if(node_array!=NULL)
2004 free((char *) node_array);
2005 Xorriso_free_meM(link_target);
2006 return(ret);
2007 }
2008
2009
2010 /* @param flag bit0= count results rather than storing them
2011 bit1= this is a recursion
2012 bit2= prepend wd (automatically done if wd[0]!=0)
2013 */
2014 int Xorriso_obtain_pattern_files_i(
2015 struct XorrisO *xorriso, char *wd, IsoDir *dir,
2016 int *filec, char **filev, int count_limit, off_t *mem,
2017 int *dive_count, int flag)
2018 {
2019 int ret, failed_at;
2020 IsoDirIter *iter= NULL;
2021 IsoNode *node;
2022 char *name;
2023 char *adr= NULL;
2024
2025 adr= malloc(SfileadrL);
2026 if(adr==NULL) {
2027 Xorriso_no_malloc_memory(xorriso, &adr, 0);
2028 {ret= -1; goto ex;}
2029 }
2030
2031 if(!(flag&2))
2032 *dive_count= 0;
2033 else
2034 (*dive_count)++;
2035 ret= Xorriso_check_for_root_pattern(xorriso, filec, filev, count_limit,
2036 mem, (flag&1)|2);
2037 if(ret!=2)
2038 goto ex;
2039
2040 ret= iso_dir_get_children(dir, &iter);
2041 if(ret<0) {
2042 Xorriso_cannot_create_iter(xorriso, ret, 0);
2043 {ret= -1; goto ex;}
2044 }
2045 while(iso_dir_iter_next(iter, &node) == 1) {
2046 name= (char *) iso_node_get_name(node);
2047 ret= Xorriso_make_abs_adr(xorriso, wd, name, adr, flag&4);
2048 if(ret<=0)
2049 goto ex;
2050 ret= Xorriso_regexec(xorriso, adr, &failed_at, 1);
2051 if(ret) { /* no match */
2052 if(failed_at <= *dive_count) /* no hope for a match */
2053 continue;
2054
2055 if(!LIBISO_ISDIR(node)) {
2056
2057 /* >>> How to deal with softlinks ? */
2058
2059 continue;
2060 }
2061 /* dive deeper */
2062 ret= Xorriso_obtain_pattern_files_i(
2063 xorriso, adr, (IsoDir *) node,
2064 filec, filev, count_limit, mem, dive_count, flag|2);
2065 if(ret<=0)
2066 goto ex;
2067 } else {
2068 ret= Xorriso_register_matched_adr(xorriso, adr, count_limit,
2069 filec, filev, mem, (flag&1)|2);
2070 if(ret<=0)
2071 goto ex;
2072 }
2073 }
2074 ret= 1;
2075 ex:;
2076 if(adr!=NULL)
2077 free(adr);
2078 if(flag&2)
2079 (*dive_count)--;
2080 if(iter != NULL)
2081 iso_dir_iter_free(iter);
2082 return(ret);
2083 }
2084
2085
2086 /* @param flag bit0= a match count !=1 is a FAILURE event
2087 bit1= with bit0 tolerate 0 matches if pattern is a constant
2088 bit2= do not issue debug messages about temporary memory needs
2089 bit3= do not add unresolved pattern to filev
2090 */
2091 int Xorriso_expand_pattern(struct XorrisO *xorriso,
2092 int num_patterns, char **patterns, int extra_filec,
2093 int *filec, char ***filev, off_t *mem, int flag)
2094 {
2095 int ret, count= 0, abs_adr= 0, i, was_count, was_filec;
2096 int nonconst_mismatches= 0, dive_count= 0;
2097 IsoImage *volume;
2098 IsoDir *dir= NULL, *root_dir;
2099 IsoNode *iso_node;
2100
2101 *filec= 0;
2102 *filev= NULL;
2103
2104 xorriso->search_mode= 3;
2105 xorriso->structured_search= 1;
2106
2107 ret= Xorriso_get_volume(xorriso, &volume, 0);
2108 if(ret<=0)
2109 return(ret);
2110 root_dir= iso_image_get_root(volume);
2111 if(root_dir==NULL) {
2112 Xorriso_process_msg_queues(xorriso,0);
2113 sprintf(xorriso->info_text,
2114 "While expanding pattern : Cannot obtain root node of ISO image");
2115 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
2116 ret= -1; goto ex;
2117 }
2118
2119 for(i= 0; i<num_patterns; i++) {
2120 ret= Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 0);
2121 if(ret<=0)
2122 return(ret);
2123 if(ret==2)
2124 abs_adr= 4;
2125 if(patterns[i][0]=='/' || abs_adr) {
2126 dir= root_dir;
2127 abs_adr= 4;
2128 } else {
2129 /* This is done so late to allow the following:
2130 It is not an error if xorriso->wdi does not exist yet, but one may
2131 not use it as base for relative address searches.
2132 */
2133 ret= Xorriso_node_from_path(xorriso, volume, xorriso->wdi, &iso_node, 1);
2134 dir= (IsoDir *) iso_node;
2135 if(ret<=0) {
2136 Xorriso_process_msg_queues(xorriso,0);
2137 sprintf(xorriso->info_text, "While expanding pattern ");
2138 Text_shellsafe(patterns[i], xorriso->info_text, 1);
2139 strcat(xorriso->info_text,
2140 " : Working directory does not exist in ISO image");
2141 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2142 ret= 0; goto ex;
2143 }
2144 if(!LIBISO_ISDIR((IsoNode *) dir)) {
2145 sprintf(xorriso->info_text,
2146 "Working directory path does not lead to a directory in ISO image");
2147 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2148 ret= 0; goto ex;
2149 }
2150 }
2151
2152 /* count the matches */
2153 was_count= count;
2154 ret= Xorriso_obtain_pattern_files_i(xorriso, "", dir, &count, NULL, 0,
2155 mem, &dive_count, 1 | abs_adr);
2156 if(ret<=0)
2157 goto ex;
2158 if(was_count==count && strcmp(patterns[i],"*")!=0 && (flag&3)!=1 &&
2159 !(flag & 8)) {
2160 count++;
2161 Xorriso_eval_nonmatch(xorriso, patterns[i], &nonconst_mismatches, mem, 0);
2162 }
2163 }
2164
2165 ret= Xorriso_check_matchcount(xorriso, count, nonconst_mismatches,
2166 num_patterns, patterns, (flag&1)|2);
2167 if(ret<=0)
2168 goto ex;
2169 count+= extra_filec;
2170 (*mem)+= extra_filec * sizeof(char *);
2171 if(count<=0)
2172 {ret= !!(flag & 8); goto ex;}
2173 ret= Xorriso_alloc_pattern_mem(xorriso, *mem, count, filev, !!(flag & 4));
2174 if(ret<=0)
2175 goto ex;
2176 /* now store addresses */
2177 for(i= 0; i<num_patterns; i++) {
2178 ret= Xorriso_prepare_expansion_pattern(xorriso, patterns[i], 0);
2179 if(ret<=0)
2180 return(ret);
2181 if(ret==2)
2182 abs_adr= 4;
2183
2184 was_filec= *filec;
2185 ret= Xorriso_obtain_pattern_files_i(xorriso, "", dir, filec, *filev, count,
2186 mem, &dive_count, abs_adr);
2187 if(ret<=0)
2188 goto ex;
2189 if(was_filec == *filec && strcmp(patterns[i],"*")!=0 && (flag&3) != 1 &&
2190 !(flag & 8)) {
2191 (*filev)[*filec]= strdup(patterns[i]);
2192 if((*filev)[*filec]==NULL) {
2193 (*mem)= strlen(patterns[i])+1;
2194 Xorriso_no_pattern_memory(xorriso, *mem, 0);
2195 ret= -1; goto ex;
2196 }
2197 (*filec)++;
2198 }
2199 }
2200 ret= 1;
2201 ex:;
2202 if(ret<=0) {
2203 Sfile_destroy_argv(&count, filev, 0);
2204 *filec= 0;
2205 }
2206 return(ret);
2207 }
2208
2209
2210 int Xorriso__start_end_lbas(IsoNode *node,
2211 int *lba_count, int **start_lbas, int **end_lbas,
2212 off_t **section_sizes, off_t *size, int flag)
2213 {
2214 int section_count= 0, ret, i;
2215 struct iso_file_section *sections= NULL;
2216
2217 *lba_count= 0;
2218 *start_lbas= *end_lbas= NULL;
2219 *section_sizes= NULL;
2220 *size= 0;
2221 if(!LIBISO_ISREG(node))
2222 return(0);
2223 *size= iso_file_get_size((IsoFile *) node);
2224 ret= iso_file_get_old_image_sections((IsoFile *) node, §ion_count,
2225 §ions, 0);
2226 if(ret < 0)
2227 {ret= -1; goto ex;}
2228 if(ret != 1 || section_count <= 0)
2229 {ret= 0; goto ex;}
2230 *start_lbas= calloc(section_count, sizeof(int));
2231 *end_lbas= calloc(section_count, sizeof(int));
2232 *section_sizes= calloc(section_count, sizeof(off_t));
2233 if(*start_lbas == NULL || *end_lbas == NULL || *section_sizes == NULL)
2234 {ret= -1; goto ex;}
2235 for(i= 0; i < section_count; i++) {
2236 (*start_lbas)[i]= sections[i].block;
2237 (*end_lbas)[i]= sections[i].block + sections[i].size / 2048 - 1;
2238 if(sections[i].size % 2048)
2239 (*end_lbas)[i]++;
2240 (*section_sizes)[i]= sections[i].size;
2241 }
2242 *lba_count= section_count;
2243 ret= 1;
2244 ex:;
2245 if(sections != NULL)
2246 free((char *) sections);
2247 if(ret <= 0) {
2248 if((*start_lbas) != NULL)
2249 free((char *) *start_lbas);
2250 if((*end_lbas) != NULL)
2251 free((char *) *end_lbas);
2252 *start_lbas= *end_lbas= NULL;
2253 *lba_count= 0;
2254 }
2255 return(ret);
2256 }
2257
2258
2259 int Xorriso__file_start_lba(IsoNode *node,
2260 int *lba, int flag)
2261 {
2262 int *start_lbas= NULL, *end_lbas= NULL, lba_count= 0, i, ret;
2263 off_t size, *section_sizes= NULL;
2264
2265 *lba= -1;
2266 ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas,
2267 §ion_sizes, &size, 0);
2268 if(ret <= 0)
2269 return(ret);
2270 for(i= 0; i < lba_count; i++) {
2271 if(*lba < 0 || start_lbas[i] < *lba)
2272 *lba= start_lbas[i];
2273 }
2274 if(start_lbas != NULL)
2275 free((char *) start_lbas);
2276 if(end_lbas != NULL)
2277 free((char *) end_lbas);
2278 if(section_sizes != NULL)
2279 free((char *) section_sizes);
2280 if(*lba < 0)
2281 return(0);
2282 return(1);
2283 }
2284
2285
2286 /* flag bit0= examine sub directories rather than data files
2287 */
2288 int Xorriso_dir_disk_path(struct XorrisO *xorriso, IsoNode *dir_node,
2289 char disk_path[SfileadrL], int flag)
2290 {
2291 int ret;
2292 char *npt;
2293 IsoNode *node;
2294 IsoDir *dir;
2295 IsoDirIter *iter= NULL;
2296
2297 dir= (IsoDir *) dir_node;
2298 ret= iso_dir_get_children(dir, &iter);
2299 if(ret<0) {
2300 Xorriso_cannot_create_iter(xorriso, ret, 0);
2301 {ret= -1; goto ex;}
2302 }
2303 while(1) {
2304 ret= iso_dir_iter_next(iter, &node);
2305 if(ret < 0) {
2306 Xorriso_report_iso_error(xorriso, "", ret,
2307 "Error when iterating over directory", 0, "FAILURE", 1);
2308 ret= -1; goto ex;
2309 }
2310 if(ret == 0)
2311 break;
2312
2313 if(LIBISO_ISDIR(node) && (flag & 1)) {
2314 ret= Xorriso_dir_disk_path(xorriso, node, disk_path, flag);
2315 if(ret < 0)
2316 goto ex;
2317 if(ret == 0)
2318 continue;
2319 } else if(LIBISO_ISREG(node) && !(flag & 1)) {
2320 ret= Xorriso_retrieve_disk_path(xorriso, node, disk_path, 0);
2321 if(ret < 0)
2322 goto ex;
2323 if(ret == 0)
2324 continue;
2325 } else
2326 continue;
2327 /* Use its parent dir as answer */
2328 npt= strrchr(disk_path, '/');
2329 if(npt == NULL || npt == disk_path)
2330 strcpy(disk_path, "/");
2331 else
2332 *npt= 0;
2333 ret= 1; goto ex;
2334 }
2335 if(!(flag & 1))
2336 ret= Xorriso_dir_disk_path(xorriso, dir_node, disk_path, 1);
2337 else
2338 ret= 0;
2339 ex:
2340 if(iter != NULL)
2341 iso_dir_iter_free(iter);
2342 return(ret);
2343 }
2344
2345
2346 int Xorriso_retrieve_disk_path(struct XorrisO *xorriso, IsoNode *node,
2347 char disk_path[SfileadrL], int flag)
2348 {
2349 IsoFile *file;
2350 IsoStream *stream= NULL, *input_stream;
2351 char type_text[80], *source_path = NULL;
2352 int ret;
2353
2354 if(LIBISO_ISDIR(node)) {
2355 ret= Xorriso_dir_disk_path(xorriso, node, disk_path, 0);
2356 return(ret);
2357 }
2358
2359 if(!LIBISO_ISREG(node))
2360 return(0);
2361
2362 /* Obtain most fundamental input stream */
2363 file= (IsoFile *) node;
2364 input_stream= iso_file_get_stream(file);
2365 if(input_stream == NULL)
2366 return(0);
2367 while(1) {
2368 stream= input_stream;
2369 input_stream= iso_stream_get_input_stream(stream, 0);
2370 if(input_stream == NULL)
2371 break;
2372 }
2373
2374 /* Obtain disk path if applicable */
2375 type_text[0]= 0;
2376 Xorriso_stream_type(xorriso, node, stream, type_text, 0);
2377 if(strcmp(type_text, "disk") != 0 && strcmp(type_text, "cout") != 0)
2378 return(0); /* among othersi rejected: "image" */
2379 source_path= iso_stream_get_source_path(stream, 0);
2380 if(source_path == NULL)
2381 return(0);
2382 if(strlen(source_path) >= SfileadrL) {
2383 free(source_path);
2384 return(0);
2385 }
2386 strcpy(disk_path, source_path);
2387 free(source_path);
2388 return(1);
2389 }
2390
2391
2392 /* @param flag bit0= show numbers from iso_stream_get_id
2393 */
2394 int Xorriso_show_stream(struct XorrisO *xorriso, void *in_node,
2395 char *path, int flag)
2396 {
2397 int ret;
2398 IsoNode *node;
2399 IsoFile *file;
2400 IsoStream *stream= NULL, *input_stream;
2401 IsoExternalFilterCommand *cmd;
2402 char type_text[80], *source_path= NULL;
2403 unsigned int fs_id;
2404 dev_t dev_id;
2405 ino_t ino_id;
2406
2407 node= (IsoNode *) in_node;
2408 if(node == NULL) {
2409 ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
2410 if(ret <= 0)
2411 goto ex;
2412 }
2413 if(!LIBISO_ISREG(node))
2414 {ret= 2; goto ex;}
2415 file= (IsoFile *) node;
2416 input_stream= iso_file_get_stream(file);
2417 Text_shellsafe(path, xorriso->result_line, 0);
2418 while(1) {
2419 stream= input_stream;
2420 input_stream= iso_stream_get_input_stream(stream, 0);
2421 if(input_stream == NULL)
2422 break;
2423 strcat(xorriso->result_line, " < ");
2424 Xorriso_stream_type(xorriso, node, stream, type_text, 0);
2425 strcat(xorriso->result_line, type_text);
2426 if(flag & 1) {
2427 iso_stream_get_id(stream, &fs_id, &dev_id, &ino_id);
2428 sprintf(xorriso->result_line + strlen(xorriso->result_line),
2429 "[%u,%lu,%lu]", fs_id, (unsigned long) dev_id,
2430 (unsigned long) ino_id);
2431 }
2432 ret= iso_stream_get_external_filter(stream, &cmd, 0);
2433 if(ret < 0) {
2434 Xorriso_process_msg_queues(xorriso,0);
2435 Xorriso_report_iso_error(xorriso, "", ret,
2436 "Error when inquiring filter command of node", 0, "FAILURE", 1);
2437 ret= 0; goto ex;
2438 }
2439 if(ret > 0) {
2440 strcat(xorriso->result_line, ":");
2441 Text_shellsafe(cmd->name, xorriso->result_line, 1);
2442 }
2443 if(strlen(xorriso->result_line) > SfileadrL) {
2444 Xorriso_result(xorriso, 0);
2445 xorriso->result_line[0]= 0;
2446 }
2447 }
2448 strcat(xorriso->result_line, " < ");
2449 Xorriso_stream_type(xorriso, node, stream, type_text, 0);
2450 strcat(xorriso->result_line, type_text);
2451 if(flag & 1) {
2452 iso_stream_get_id(stream, &fs_id, &dev_id, &ino_id);
2453 sprintf(xorriso->result_line + strlen(xorriso->result_line), "[%u,%lu,%lu]",
2454 fs_id, (unsigned long) dev_id, (unsigned long) ino_id);
2455 }
2456
2457 source_path= iso_stream_get_source_path(stream, 0);
2458 if(source_path != NULL) {
2459 strcat(xorriso->result_line, ":");
2460 Text_shellsafe(source_path, xorriso->result_line, 1);
2461 }
2462
2463 strcat(xorriso->result_line, "\n");
2464 Xorriso_result(xorriso, 0);
2465 ret= 1;
2466 ex:;
2467 if(source_path != NULL)
2468 free(source_path);
2469 return(ret);
2470 }
2471
2472
2473 /* @param damage_start Returns first damaged byte address
2474 @param damage_end Returns first byte address after last damaged byte
2475 @return <0 error, 0=undamaged , 1=damaged
2476 */
2477 int Xorriso_file_eval_damage(struct XorrisO *xorriso, IsoNode *node,
2478 off_t *damage_start, off_t *damage_end,
2479 int flag)
2480 {
2481 int *start_lbas= NULL, *end_lbas= NULL, lba_count= 0, sect;
2482 int i, sectors, sector_size, ret;
2483 off_t sect_base= 0, size= 0, byte, *section_sizes= NULL;
2484 struct SectorbitmaP *map;
2485
2486 *damage_start= *damage_end= -1;
2487 map= xorriso->in_sector_map;
2488 if(map == NULL)
2489 return(0);
2490 Sectorbitmap_get_layout(map, §ors, §or_size, 0);
2491 sector_size/= 2048;
2492
2493 ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas,
2494 §ion_sizes, &size, 0);
2495 if(ret <= 0) {
2496 Xorriso_process_msg_queues(xorriso, 0);
2497 return(ret);
2498 }
2499 for(sect= 0; sect < lba_count; sect++) {
2500 for(i= start_lbas[sect]; i <= end_lbas[sect]; i+= sector_size) {
2501 if(Sectorbitmap_is_set(map, i / sector_size, 0) == 0) {
2502 byte= ((off_t) 2048) * ((off_t) (i - start_lbas[sect])) + sect_base;
2503 if(*damage_start < 0 || byte < *damage_start)
2504 *damage_start= byte;
2505 if(byte + (off_t) 2048 > *damage_end)
2506 *damage_end= byte + (off_t) 2048;
2507 }
2508 }
2509 sect_base+= ((off_t) 2048) *
2510 ((off_t) (end_lbas[sect] - start_lbas[sect] + 1));
2511 }
2512 if(*damage_end > size)
2513 *damage_end= size;
2514 if(start_lbas != NULL)
2515 free((char *) start_lbas);
2516 if(end_lbas != NULL)
2517 free((char *) end_lbas);
2518 if(section_sizes != NULL)
2519 free((char *) section_sizes);
2520 if(*damage_start < 0)
2521 return(0);
2522 return(1);
2523 }
2524
2525
2526 /* @param flag bit0= report_sections : section size rather than total size
2527 bit1= last_data_file_block : looking for highest data file block
2528 */
2529 int Xorriso_report_lba(struct XorrisO *xorriso, char *show_path,
2530 IsoNode *node, uint32_t *last_block, int flag)
2531 {
2532 int ret, *start_lbas= NULL, *end_lbas= NULL, lba_count, i;
2533 off_t size, *section_sizes= NULL;
2534
2535 ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas,
2536 §ion_sizes, &size, 0);
2537 if(ret < 0) {
2538 Xorriso_process_msg_queues(xorriso, 0);
2539 {ret= -1; goto ex;}
2540 }
2541 if(ret == 0)
2542 {ret= 1; goto ex;} /* it is ok to ignore other types */
2543 for(i= 0; i < lba_count; i++) {
2544 if(flag & 1)
2545 size= section_sizes[i];
2546 if(flag & 2) {
2547 if(end_lbas[i] > 0 && (uint32_t) end_lbas[i] > *last_block)
2548 *last_block= end_lbas[i];
2549 } else {
2550 sprintf(xorriso->result_line,
2551 "File data lba: %2d , %8d , %8d , %8.f , ",
2552 i, start_lbas[i], end_lbas[i] + 1 - start_lbas[i], (double) size);
2553 Text_shellsafe(show_path, xorriso->result_line, 1);
2554 strcat(xorriso->result_line, "\n");
2555 Xorriso_result(xorriso, 0);
2556 }
2557 }
2558 ret= 1;
2559 ex:;
2560 if(start_lbas != NULL)
2561 free((char *) start_lbas);
2562 if(end_lbas != NULL)
2563 free((char *) end_lbas);
2564 if(section_sizes != NULL)
2565 free((char *) section_sizes);
2566 return(ret);
2567 }
2568
2569
2570 int Xorriso_report_damage(struct XorrisO *xorriso, char *show_path,
2571 IsoNode *node, int flag)
2572 {
2573 int ret;
2574 off_t size= 0, damage_start, damage_end;
2575
2576 ret= Xorriso_file_eval_damage(xorriso, node, &damage_start, &damage_end, 0);
2577 if(ret < 0)
2578 return(0);
2579
2580 if(LIBISO_ISREG(node))
2581 size= iso_file_get_size((IsoFile *) node);
2582 if(ret > 0) {
2583 sprintf(xorriso->result_line, "File damaged : %8.f , %8.f , %8.f , ",
2584 (double) damage_start, (double) (damage_end - damage_start) ,
2585 (double) size);
2586 } else {
2587 sprintf(xorriso->result_line, "File seems ok: %8.f , %8.f , %8.f , ",
2588 -1.0, -1.0, (double) size);
2589 }
2590 Text_shellsafe(show_path, xorriso->result_line, 1);
2591 strcat(xorriso->result_line, "\n");
2592 Xorriso_result(xorriso, 0);
2593 return(1);
2594 }
2595
2596
2597 /* @param flag bit0= do not accept hln_targets[i] != NULL as *node_idx
2598 bit1= use *node_idx as found index rather than searching it
2599 bit2= with bit1: use xorriso->node_array rather than hln_array
2600 */
2601 int Xorriso_search_hardlinks(struct XorrisO *xorriso, IsoNode *node,
2602 int *node_idx, int *min_hl, int *max_hl, int flag)
2603 {
2604 int idx, ret, i, node_count;
2605 void *np, **node_array;
2606
2607 node_array= xorriso->hln_array;
2608 node_count= xorriso->hln_count;
2609 *min_hl= *max_hl= -1;
2610 np= node;
2611 if(flag & 2) {
2612 idx= *node_idx;
2613 if(flag & 4) {
2614 node_array= xorriso->node_array;
2615 node_count= xorriso->node_counter;
2616 }
2617 } else {
2618 *node_idx= -1;
2619 ret= Xorriso_search_in_hln_array(xorriso, np, &idx, 0);
2620 if(ret <= 0)
2621 return(ret);
2622 }
2623 for(i= idx - 1; i >= 0 ; i--)
2624 if(Xorriso__findi_sorted_ino_cmp(&(node_array[i]), &np) != 0)
2625 break;
2626 *min_hl= i + 1;
2627 for(i= idx + 1; i < node_count; i++)
2628 if(Xorriso__findi_sorted_ino_cmp(&(node_array[i]), &np) != 0)
2629 break;
2630 *max_hl= i - 1;
2631
2632 /* Search for *node_idx */
2633 if(flag & 2)
2634 return(1);
2635 for(i= *min_hl; i <= *max_hl; i++)
2636 if(node_array[i] == np) {
2637 if((flag & 1) && xorriso->hln_targets != NULL && !(flag & 4))
2638 if(xorriso->hln_targets[i] != NULL)
2639 continue;
2640 *node_idx= i;
2641 break;
2642 }
2643 return(1);
2644 }
2645
2646
2647 /* @param flag bit0=do not complain about non existent node
2648 bit1= do not try to find truncated name first
2649 */
2650 int Xorriso_node_from_path(struct XorrisO *xorriso, IsoImage *volume,
2651 char *path, IsoNode **node, int flag)
2652 {
2653 int ret;
2654 char *path_pt;
2655
2656 path_pt= path;
2657 if(path[0]==0)
2658 path_pt= "/";
2659 if(volume == NULL) {
2660 ret= Xorriso_get_volume(xorriso, &volume, 0);
2661 if(ret <= 0)
2662 return(ret);
2663 }
2664 *node= NULL;
2665 ret= 2;
2666 if(!(flag & 2))
2667 ret= iso_image_path_to_node(volume, path_pt, node);
2668 if(ret == 2)
2669 ret= iso_tree_path_to_node(volume, path_pt, node);
2670 Xorriso_process_msg_queues(xorriso,0);
2671 if(ret<=0 || (*node)==NULL) {
2672 if(!(flag&1)) {
2673 sprintf(xorriso->info_text, "Cannot find path ");
2674 Text_shellsafe(path_pt, xorriso->info_text, 1);
2675 strcat(xorriso->info_text, " in loaded ISO image");
2676 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2677 }
2678 return(0);
2679 }
2680 return(1);
2681 }
2682
2683
2684 /* @param flag bit0=do not complain about non existent node
2685 bit1= do not try to find truncated name first
2686 */
2687 int Xorriso_dir_from_path(struct XorrisO *xorriso, char *purpose,
2688 char *path, IsoDir **dir_node, int flag)
2689 {
2690 IsoImage *volume;
2691 IsoNode *node;
2692 int ret, is_dir= 0;
2693
2694 ret= Xorriso_get_volume(xorriso, &volume, 0);
2695 if(ret<=0)
2696 return(ret);
2697
2698 ret= Xorriso_node_from_path(xorriso, volume, path, &node, flag & 3);
2699 if(ret<=0)
2700 goto wdi_is_not_a_dir;
2701 if(LIBISO_ISDIR(node))
2702 is_dir= 1;
2703 if(!is_dir) {
2704 wdi_is_not_a_dir:;
2705 sprintf(xorriso->info_text,
2706 "%s path does not lead to a directory in ISO image", purpose);
2707 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2708 return(0);
2709 }
2710 *dir_node= (IsoDir *) node;
2711 return(1);
2712 }
2713
2714
2715 /*
2716 @param flag bit0= do not remove leading slash
2717 bit1= append flatly to result_line and put out
2718 */
2719 int Xorriso_getfname(struct XorrisO *xorriso, char *path, int flag)
2720 {
2721 int ret, path_offset= 0, bsl_mem;
2722 char *bsl_path= NULL;
2723
2724 if(path[0] == '/' && !(flag & 1))
2725 path_offset= 1;
2726
2727 /* backslash escaped path rather than shellsafe path */
2728 ret= Sfile_bsl_encoder(&bsl_path, path + path_offset,
2729 strlen(path + path_offset), 8);
2730 if(ret <= 0)
2731 return(-1);
2732 if(flag & 2) {
2733 sprintf(xorriso->result_line + strlen(xorriso->result_line),
2734 "%s\n", bsl_path[0] ? bsl_path : ".");
2735 } else {
2736 sprintf(xorriso->result_line, "# file: %s\n", bsl_path[0] ? bsl_path : ".");
2737 }
2738 free(bsl_path);
2739 bsl_path= NULL;
2740 /* temporarily disable -backslash_codes with result output */
2741 bsl_mem= xorriso->bsl_interpretation;
2742 xorriso->bsl_interpretation= 0;
2743 Xorriso_result(xorriso, 0);
2744 xorriso->bsl_interpretation= bsl_mem;
2745 return(1);
2746 }
2747
2748
2749 int Xorriso_is_plain_image_file(struct XorrisO *xorriso, void *in_node,
2750 char *path, int flag)
2751 {
2752 int ret, lba;
2753 IsoStream *stream;
2754 IsoNode *node;
2755
2756 node= (IsoNode *) in_node;
2757 if(node == NULL) {
2758 ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
2759 if(ret<=0)
2760 return(ret);
2761 }
2762
2763 ret= Xorriso__file_start_lba(node, &lba, 0);
2764 if(ret > 0) { /* Stream source is from loaded image */
2765 stream= iso_file_get_stream((IsoFile *) node);
2766 if(stream != NULL)
2767 if(iso_stream_get_input_stream(stream, 0) == NULL)
2768 return(1);
2769 }
2770 return(0);
2771 }
2772