"Fossies" - the Fresh Open Source Software Archive 
Member "libisoburn-1.5.6/xorriso/read_run.c" (30 May 2022, 87591 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 "read_run.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
3 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
4
5 Copyright 2007-2022 Thomas Schmitt, <scdbackup@gmx.net>
6
7 Provided under GPL version 2 or later.
8
9 This file contains functions which are needed to read data
10 from ISO image.
11 */
12
13 #ifdef HAVE_CONFIG_H
14 #include "../config.h"
15 #endif
16
17 #include <ctype.h>
18 #include <sys/types.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include <time.h>
26 #include <errno.h>
27
28 #include <fcntl.h>
29 #include <utime.h>
30
31 /* O_BINARY is needed for Cygwin but undefined elsewhere */
32 #ifndef O_BINARY
33 #define O_BINARY 0
34 #endif
35
36
37 #include "lib_mgt.h"
38 #include "drive_mgt.h"
39 #include "iso_img.h"
40 #include "iso_tree.h"
41 #include "iso_manip.h"
42 #include "read_run.h"
43 #include "sort_cmp.h"
44 #include "disk_ops.h"
45
46
47 int Xorriso__read_pacifier(IsoImage *image, IsoFileSource *filesource)
48 {
49 struct XorrisO *xorriso;
50
51 xorriso= (struct XorrisO *) iso_image_get_attached_data(image);
52 if(xorriso==NULL)
53 return(1);
54 Xorriso_process_msg_queues(xorriso,0);
55 xorriso->pacifier_count++;
56 if(xorriso->pacifier_count%10)
57 return(1);
58 Xorriso_pacifier_callback(xorriso, "nodes read", xorriso->pacifier_count, 0,
59 "", 0);
60 return(1);
61 }
62
63
64 /* @param flag bit0= open IsoNode *node_pt rather than looking up pathname
65 bit1= dig out the most original stream for reading
66 */
67 int Xorriso_iso_file_open(struct XorrisO *xorriso, char *pathname,
68 void *node_pt, void **stream, int flag)
69 {
70 int ret;
71 char *eff_path= NULL;
72 IsoNode *node= NULL;
73 IsoFile *filenode= NULL;
74 IsoStream *iso_stream= NULL, *input_stream;
75
76 Xorriso_alloc_meM(eff_path, char, SfileadrL);
77
78 *stream= NULL;
79 if(flag&1) {
80 node= (IsoNode *) node_pt;
81 } else {
82 ret= Xorriso_get_node_by_path(xorriso, pathname, eff_path, &node, 0);
83 if(ret<=0)
84 goto ex;
85 }
86 if(!LIBISO_ISREG(node)) {
87 sprintf(xorriso->info_text,
88 "Given path does not lead to a regular data file in the image");
89 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
90 {ret= 0; goto ex;}
91 }
92
93 filenode= (IsoFile *) node;
94 iso_stream= iso_file_get_stream(filenode);
95 if(iso_stream==NULL) {
96 Xorriso_process_msg_queues(xorriso,0);
97 sprintf(xorriso->info_text,
98 "Could not obtain source stream of file in the image for reading");
99 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
100 {ret= 0; goto ex;}
101 }
102 if(flag & 2) {
103 /* Dig out the most original stream */
104 while(1) {
105 input_stream= iso_stream_get_input_stream(iso_stream, 0);
106 if(input_stream == NULL)
107 break;
108 iso_stream= input_stream;
109 }
110 }
111 if(!iso_stream_is_repeatable(iso_stream)) {
112 sprintf(xorriso->info_text,
113 "The data production of the file in the image is one-time only");
114 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
115 {ret= 0; goto ex;}
116 }
117 ret= iso_stream_open(iso_stream);
118 if(ret<0) {
119 sprintf(xorriso->info_text,
120 "Could not open data file in the image for reading");
121 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
122 {ret= 0; goto ex;}
123 }
124 Xorriso_process_msg_queues(xorriso,0);
125 *stream= iso_stream;
126
127 #ifdef NIX
128 /* <<< */
129 {
130 unsigned int fs_id;
131 dev_t dev_id;
132 ino_t ino;
133
134 iso_stream_get_id(iso_stream, &fs_id, &dev_id, &ino);
135 fprintf(stderr, "xorriso_debug: iso_ino= %ld\n", (long int) ino);
136 }
137 #endif
138
139 ret= 1;
140 ex:;
141 Xorriso_free_meM(eff_path);
142 return(ret);
143 }
144
145
146 int Xorriso_iso_file_read(struct XorrisO *xorriso, void *stream, char *buf,
147 int count, int flag)
148 {
149 int ret, rcnt= 0;
150 IsoStream *stream_pt;
151
152 stream_pt= (IsoStream *) stream;
153
154 while(rcnt<count) {
155 ret= iso_stream_read(stream_pt, (void *) (buf+rcnt), (size_t) (count-rcnt));
156 if(ret==0) /* EOF */
157 break;
158 if(ret<0) { /* error */
159 Xorriso_process_msg_queues(xorriso,0);
160 Xorriso_report_iso_error(xorriso, "", ret, "Error on read",
161 0, "FAILURE", 1 | ((ret == -1)<<2) );
162 return(-1);
163 }
164 rcnt+= ret;
165 }
166 return(rcnt);
167 }
168
169
170 int Xorriso_iso_file_close(struct XorrisO *xorriso, void **stream, int flag)
171 {
172 int ret;
173
174 if(*stream==NULL)
175 return(0);
176 ret= iso_stream_close(*stream);
177 if(ret==1)
178 *stream= NULL;
179 Xorriso_process_msg_queues(xorriso,0);
180 return(ret);
181 }
182
183
184 /* @param flag bit0= in_node is valid, do not resolve img_path
185 bit1= test mode: print DEBUG messages
186 @return <0 = error,
187 0 = surely not identical regular files ,
188 1 = surely identical
189 2 = potentially depending on unknown disk file (e.g. -cut_out)
190 */
191 int Xorriso_restore_is_identical(struct XorrisO *xorriso, void *in_node,
192 char *img_path, char *disk_path,
193 char type_text[5], int flag)
194 {
195 int ret;
196 unsigned int fs_id;
197 dev_t dev_id;
198 ino_t ino_id;
199 IsoStream *stream;
200 IsoImage *volume;
201 IsoNode *node;
202 struct stat stbuf;
203 int dummy;
204
205 memset(type_text, 0, 5);
206 if(!Xorriso_change_is_pending(xorriso, 0))
207 return(0);
208 if(flag&1) {
209 node= (IsoNode *) in_node;
210 } else {
211 ret= Xorriso_get_volume(xorriso, &volume, 0);
212 if(ret<=0)
213 return(-1);
214 ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1);
215 if(ret<=0)
216 return(-1);
217 }
218 ret= Xorriso__file_start_lba(node, &dummy, 0);
219 if(ret != 0) {
220 Xorriso_process_msg_queues(xorriso, 0);
221 return(0);
222 }
223 if(!LIBISO_ISREG(node))
224 return(0);
225 stream= iso_file_get_stream((IsoFile *) node);
226 memcpy(type_text, stream->class->type, 4);
227 iso_stream_get_id(stream, &fs_id, &dev_id, &ino_id);
228 if(flag&2) {
229 sprintf(xorriso->info_text, "%s : fs=%d dev=%.f ino=%.f (%s)",
230 img_path, fs_id, (double) dev_id, (double) ino_id, type_text);
231 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
232 }
233 ret= stat(disk_path, &stbuf);
234 if(ret==-1)
235 return(0);
236 if(flag&2) {
237 sprintf(xorriso->info_text, "%s : dev=%.f ino=%.f",
238 disk_path, (double) stbuf.st_dev, (double) stbuf.st_ino);
239 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
240 }
241 if(fs_id!=1)
242 return(2);
243
244 /* >>> obtain underlying dev_t ino_t of type "cout" */;
245
246 if(strcmp(type_text, "fsrc")!=0)
247 return(2);
248 if(stbuf.st_dev==dev_id && stbuf.st_ino==ino_id)
249 return(1);
250 return(0);
251 }
252
253
254 int Xorriso_iso_file_to_fd(struct XorrisO *xorriso, char *path, int fd,
255 int flag)
256 {
257 int ret, rret, wret, to_write, wanted;
258 void *stream= NULL;
259 char *buffer= NULL, *wpt;
260 off_t todo;
261 static int buffer_size= 64 * 1024;
262
263 Xorriso_alloc_meM(buffer, char, buffer_size);
264
265 ret= Xorriso_iso_file_open(xorriso, path, NULL, &stream, 0);
266 if(ret <= 0)
267 goto ex;
268
269 todo= iso_stream_get_size((IsoStream *) stream);
270 while(todo > 0) {
271 if(todo < buffer_size)
272 wanted= todo;
273 else
274 wanted= buffer_size;
275 rret = Xorriso_iso_file_read(xorriso, stream, buffer, wanted, 0);
276 if(rret <= 0)
277 {ret= -1; goto ex;}
278 todo-= rret;
279 wpt= buffer;
280 for(to_write= rret; to_write > 0;) {
281 wret= write(fd, wpt, to_write);
282 if(wret <= 0) {
283 if(wret == 0)
284 sprintf(xorriso->info_text,
285 "Strange behavior of write(2): return == 0 with ");
286 else
287 sprintf(xorriso->info_text, "Write error with ");
288 Text_shellsafe(path, xorriso->info_text, 1);
289 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text,
290 wret == 0 ? 0 : errno, "FAILURE",0);
291 ret= 0; goto ex;
292 }
293 to_write-= wret;
294 wpt+= wret;
295 }
296 }
297 ret= 1;
298 ex:;
299 if(stream != NULL)
300 Xorriso_iso_file_close(xorriso, &stream, 0);
301 Xorriso_free_meM(buffer);
302 return(ret);
303 }
304
305
306 /* @param flag bit0= minimal transfer: access permissions only
307 bit1= keep directory open: keep owner, allow rwx for owner
308 and push directory onto xorriso->perm_stack
309 */
310 int Xorriso_restore_properties(struct XorrisO *xorriso, char *disk_path,
311 IsoNode *node, int flag)
312 {
313 int ret, is_dir= 0, errno_copy= 0, local_attrs_set= 0, i, err_count;
314 mode_t mode;
315 uid_t uid, disk_uid;
316 gid_t gid, disk_gid;
317 struct utimbuf utime_buffer;
318 struct stat stbuf;
319 size_t num_attrs= 0, *value_lengths= NULL;
320 char **names= NULL, **values= NULL;
321 int *errnos= NULL;
322
323 ret= lstat(disk_path, &stbuf);
324 if(ret==-1) {
325 sprintf(xorriso->info_text,
326 "Cannot obtain properties of disk file ");
327 Text_shellsafe(disk_path, xorriso->info_text, 1);
328 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
329 {ret= 0; goto ex;}
330 }
331 disk_uid= uid= stbuf.st_uid;
332 disk_gid= stbuf.st_gid;
333
334 is_dir= S_ISDIR(stbuf.st_mode);
335
336 mode= iso_node_get_permissions(node);
337
338 if(xorriso->do_aaip & (2 | 8 | 16)) {
339 ret= iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values,
340 (!!(xorriso->do_aaip & 2)) | (!(xorriso->do_aaip & (8 | 16))) << 2);
341 if (ret < 0) {
342 strcpy(xorriso->info_text, "Error with obtaining ACL and xattr for ");
343 Text_shellsafe(disk_path, xorriso->info_text, 1);
344 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
345 {ret= 0; goto ex;}
346 }
347 if(num_attrs > 0) {
348 Xorriso_alloc_meM(errnos, int, num_attrs);
349 ret= iso_local_set_attrs_errno(disk_path, num_attrs, names, value_lengths,
350 values, errnos,
351 ((!(xorriso->do_strict_acl & 1)) << 6) |
352 ((!!(xorriso->do_aaip & 1024)) << 3) );
353 if(ret < 0) {
354 cannot_set_xattr:;
355 errno_copy= errno;
356 if(ret != (int) ISO_AAIP_NO_SET_LOCAL)
357 errno_copy= 0;
358 Xorriso_report_iso_error(xorriso, "", ret,
359 "Error on iso_local_set_attrs",
360 0, "FAILURE", 1 | ((ret == -1)<<2) );
361 sprintf(xorriso->info_text, "Disk file ");
362 Text_shellsafe(disk_path, xorriso->info_text, 1);
363 err_count= 0;
364 for(i= 0; (unsigned int) i < num_attrs; i++) {
365 if(errnos[i] == 0)
366 continue;
367 if(err_count >= 3) {
368 strcat(xorriso->info_text, " , and more");
369 break;
370 }
371 err_count++;
372 errno_copy= 0; /* Detail errno overrides final errno */
373 if(names[i][0] == 0)
374 sprintf(xorriso->info_text + strlen(xorriso->info_text), " , ACL ");
375 else
376 sprintf(xorriso->info_text + strlen(xorriso->info_text),
377 " , xattr %s ", names[i]);
378 if(errnos[i] < 0)
379 Text_shellsafe("Unknown error", xorriso->info_text, 1);
380 else
381 Text_shellsafe(strerror(errnos[i]), xorriso->info_text, 1);
382 }
383 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno_copy,
384 "FAILURE",0);
385 {ret= 0; goto ex;}
386 }
387 local_attrs_set= 1;
388 }
389 Xorriso_process_msg_queues(xorriso,0);
390 }
391 if(!(xorriso->do_aaip & 2))
392 mode= iso_node_get_perms_wo_acl(node);
393
394 if(is_dir && (flag&2)) {
395 ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node,
396 1 | ((!!(xorriso->do_aaip & 2)) << 3));
397 if(ret<=0)
398 {ret= 0; goto ex;}
399 ret= Permstack_push(&(xorriso->perm_stack), disk_path, &stbuf, 0);
400 if(ret<=0) {
401 Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
402 strcpy(xorriso->info_text,
403 "Cannot memorize permissions for disk directory");
404 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
405 {ret= -1; goto ex;}
406 }
407 mode|= S_IRUSR|S_IWUSR|S_IXUSR;
408 }
409 ret= chmod(disk_path, mode);
410 if(ret==-1) {
411 cannot_set_perm:;
412 sprintf(xorriso->info_text,
413 "Cannot change access permissions of disk file ");
414 Text_shellsafe(disk_path, xorriso->info_text, 1);
415 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
416 {ret= 0; goto ex;}
417 }
418
419 if(flag&1)
420 {ret= 1; goto ex;}
421
422 utime_buffer.actime= iso_node_get_atime(node);
423 utime_buffer.modtime= iso_node_get_mtime(node);
424 ret= utime(disk_path,&utime_buffer);
425 if(ret==-1) {
426 sprintf(xorriso->info_text,
427 "Cannot change atime, mtime of disk file ");
428 Text_shellsafe(disk_path, xorriso->info_text, 1);
429 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
430 {ret= 0; goto ex;}
431 }
432
433 gid= iso_node_get_gid(node);
434 if(!(S_ISDIR(stbuf.st_mode) && (flag&2)))
435 uid= iso_node_get_uid(node);
436
437 if(uid != disk_uid || gid != disk_gid) {
438
439 ret= chown(disk_path, uid, gid); /* don't complain if it fails */
440
441 /* Check whether xattr are still set and try to set them again if needed.
442 E.g. Linux 3.16 removes security.capability on chown(2).
443 */
444 if(local_attrs_set && (xorriso->do_aaip & 1024)) {
445 ret= iso_local_set_attrs_errno(disk_path, num_attrs, names, value_lengths,
446 values, errnos,
447 1 | ((!!(xorriso->do_aaip & 1024)) << 3) |
448 128);
449 if(ret < 0)
450 goto cannot_set_xattr;
451 }
452
453 /* Check whether setuid or setgid bits got reset */
454 ret= lstat(disk_path, &stbuf);
455 if(ret != -1) {
456 if((mode ^ stbuf.st_mode) & (S_ISUID | S_ISGID)) {
457 ret= chmod(disk_path, mode);
458 if(ret==-1)
459 goto cannot_set_perm;
460 }
461 }
462
463 }
464 ret= 1;
465 ex:;
466 iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values,1 << 15);
467 if(errnos != NULL)
468 free(errnos);
469 return(ret);
470 }
471
472
473 /* @param flag
474 bit1= minimal transfer: access permissions only
475 bit2= keep directory open: keep owner, allow rwx for owner
476 push to xorriso->perm_stack
477 */
478 int Xorriso_restore_implicit_properties(struct XorrisO *xorriso,
479 char *full_disk_path, char *disk_path, char *full_img_path, int flag)
480 {
481 int ret, nfic, ndc, nfdc, d, i;
482 char *nfi= NULL, *nd= NULL, *nfd= NULL, *cpt;
483 struct stat stbuf;
484 IsoNode *node;
485
486 Xorriso_alloc_meM(nfi, char, SfileadrL);
487 Xorriso_alloc_meM(nd, char, SfileadrL);
488 Xorriso_alloc_meM(nfd, char, SfileadrL);
489
490 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, full_disk_path, nfd,
491 1|2|4);
492 if(ret<=0)
493 goto ex;
494 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, nd, 1|2);
495 if(ret<=0)
496 goto ex;
497 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, full_img_path, nfi,
498 1|2);
499 if(ret<=0)
500 goto ex;
501 nfdc= Sfile_count_components(nfd, 0);
502 ndc= Sfile_count_components(nd, 0);
503 nfic= Sfile_count_components(nfi, 0);
504 d= nfdc-ndc;
505 if(d<0)
506 {ret= -1; goto ex;}
507 if(d>nfic)
508 {ret= 0; goto ex;}
509 for(i= 0; i<d; i++) {
510 cpt= strrchr(nfi, '/');
511 if(cpt==NULL)
512 {ret= -1; goto ex;} /* should not happen */
513 *cpt= 0;
514 }
515 if(nfi[0]==0)
516 strcpy(nfi, "/");
517 ret= Xorriso_fake_stbuf(xorriso, nfi, &stbuf, &node, 0);
518 if(ret<=0)
519 {ret= 0; goto ex;}
520 ret= Xorriso_restore_properties(xorriso, nd, node, ((flag>>1)&3));
521 if(ret<=0)
522 goto ex;
523 sprintf(xorriso->info_text, "Restored properties for ");
524 Text_shellsafe(nd, xorriso->info_text, 1);
525 strcat(xorriso->info_text, " from ");
526 Text_shellsafe(nfi, xorriso->info_text, 1 | 2);
527 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
528 ret= 1;
529 ex:;
530 Xorriso_free_meM(nfi);
531 Xorriso_free_meM(nd);
532 Xorriso_free_meM(nfd);
533 return(ret);
534 }
535
536
537 /* If defined the position accounting will be done by lseek() and used to
538 * verify the position accounting in struct Xorriso_sparse_statE.
539 * # def ine Xorriso_check_sparsE yes
540 */
541
542 struct Xorriso_sparse_statE {
543 int use_lseek;
544 off_t cur_pos;
545 off_t after_last_written;
546 int warnings;
547 };
548
549
550 #ifdef Xorriso_check_sparsE
551
552 static int Xorriso_sparse_warn(struct XorrisO *xorriso,
553 struct Xorriso_sparse_statE *sparse_state,
554 int occasion, char *msg, int flag)
555 {
556 if(sparse_state->warnings & (1 << occasion))
557 return(1);
558 sparse_state->warnings|= 1 << occasion;
559 Xorriso_msgs_submit(xorriso, 0, msg, 0, "SORRY", 0);
560 return(1);
561 }
562
563 #endif /* Xorriso_check_sparsE */
564
565
566 static int Xorriso_sparse_init(struct XorrisO *xorriso,
567 struct Xorriso_sparse_statE **sparse_state,
568 int write_fd, int flag)
569 {
570 struct Xorriso_sparse_statE *o= NULL;
571 off_t cur_pos;
572 struct stat stbuf;
573 int ret;
574
575 *sparse_state= NULL;
576
577 /* Check whether sparse writing is disabled */
578 if(xorriso->sparse_min_gap <= 0)
579 {ret= 0; goto ex;}
580
581 /* Analyze write_fd */
582 ret= fstat(write_fd, &stbuf);
583 if(ret == -1)
584 {ret= 0; goto ex;}
585 if(!S_ISREG(stbuf.st_mode))
586 {ret= 0; goto ex;}
587 cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR);
588 if(cur_pos < stbuf.st_size)
589 {ret= 0; goto ex;}
590
591 Xorriso_alloc_meM(o, struct Xorriso_sparse_statE, 1);
592
593 /* Initialize sparse_state */
594 o->use_lseek= 1;
595 o->cur_pos= o->after_last_written= cur_pos;
596 o->warnings= 0;
597
598 ret= 1;
599 ex:;
600 if(ret >= 1)
601 *sparse_state= o;
602 else
603 Xorriso_free_meM(o);
604 return(ret);
605 }
606
607
608 static int Xorriso_sparse_zeroize(struct XorrisO *xorriso,
609 struct Xorriso_sparse_statE *sparse_state,
610 int write_fd, off_t start, off_t count,
611 int flag)
612 {
613 int ret, buf_size= 32 * 1024, buf_fill, wret;
614 off_t todo, seek_ret;
615 char *buf= NULL;
616
617 if(count <= 0)
618 {ret= 2; goto ex;}
619 Xorriso_alloc_meM(buf, char, buf_size);
620
621 seek_ret= lseek(write_fd, start, SEEK_SET);
622 if(seek_ret == -1)
623 {ret= -1; goto ex;}
624 sparse_state->cur_pos= seek_ret;
625 for(todo= count; todo > 0; ) {
626 if(buf_size < todo)
627 buf_fill= buf_size;
628 else
629 buf_fill= todo;
630 wret= write(write_fd, buf, buf_fill);
631 if(wret <= 0)
632 {ret= wret; goto ex;}
633 todo-= wret;
634 sparse_state->cur_pos+= wret;
635 }
636 ret= 1;
637 ex:;
638 Xorriso_free_meM(buf);
639 return(ret);
640 }
641
642
643 /* @param flag bit0= this is the last buffer of the stream
644 */
645 static int Xorriso_sparse_write(struct XorrisO *xorriso,
646 struct Xorriso_sparse_statE *sparse_state,
647 int write_fd, char *buf, int count,
648 int flag)
649 {
650 int wret, i, ret;
651 off_t cur_pos= -1, seek_ret;
652 static char zero[32]= {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
653 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
654
655 if(sparse_state == NULL)
656 goto do_write;
657 if(!sparse_state->use_lseek)
658 goto do_write;
659 if(flag & 1)
660 goto do_write;
661
662 #ifdef Xorriso_check_sparsE
663
664 cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR);
665 if(cur_pos == -1)
666 goto do_write;
667 if(cur_pos != sparse_state->cur_pos) {
668 Xorriso_sparse_warn(xorriso, sparse_state, 0,
669 "cur_pos deviation in Xorriso_sparse_write:intro", 0);
670 sparse_state->cur_pos= cur_pos;
671 }
672
673 #else
674
675 cur_pos= sparse_state->cur_pos;
676
677 #endif
678
679 /* Check for all zeros */
680 if(count % 32)
681 goto do_write;
682 for(i= 0; i < count; i+= 32)
683 if(memcmp(buf + i, zero, 32))
684 break;
685 if(i < count)
686 goto do_write;
687
688 /* Omit write() until next non-zero buffer or end of writing */
689
690 #ifdef Xorriso_check_sparsE
691
692 /* Only for debugging: Do real lseek() instead of write() */
693 seek_ret= lseek(write_fd, cur_pos + count, SEEK_SET);
694 if(seek_ret == -1)
695 return(-1);
696
697 #endif
698
699 sparse_state->cur_pos= cur_pos + count;
700 return(count);
701
702 do_write:
703 if(sparse_state != NULL) {
704 /* Check whether the gap since after_last_written is too small.
705 If so: fill the whole gap by writing zeros.
706 */
707 if(sparse_state->after_last_written < cur_pos) {
708 if(xorriso->sparse_min_gap > cur_pos - sparse_state->after_last_written) {
709 ret= Xorriso_sparse_zeroize(xorriso, sparse_state, write_fd,
710 sparse_state->after_last_written,
711 cur_pos - sparse_state->after_last_written, 0);
712 if(ret < 0)
713 return(ret);
714 if(ret == 0) {
715 seek_ret= lseek(write_fd, cur_pos, SEEK_SET);
716 if(seek_ret == -1)
717 return(-1);
718 sparse_state->cur_pos= seek_ret;
719 }
720 }
721 }
722 }
723
724
725 if(sparse_state != NULL) {
726
727 #ifdef Xorriso_check_sparsE
728
729 cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR);
730 if(cur_pos != sparse_state->cur_pos) {
731 Xorriso_sparse_warn(xorriso, sparse_state, 1,
732 "cur_pos deviation in Xorriso_sparse_write:do_write", 0);
733 sparse_state->cur_pos= cur_pos;
734 }
735
736 #else
737
738 /* lseek() has been delayed until now */
739 if(sparse_state->after_last_written != sparse_state->cur_pos) {
740 seek_ret= lseek(write_fd, sparse_state->cur_pos, SEEK_SET);
741 if(seek_ret == -1)
742 return(-1);
743 }
744
745 #endif /* ! Xorriso_check_sparsE */
746
747 }
748 wret= write(write_fd, buf, count);
749 if(sparse_state != NULL && wret > 0 && cur_pos >= 0)
750 sparse_state->cur_pos= sparse_state->after_last_written= cur_pos + wret;
751 return(wret);
752 }
753
754
755 static int Xorriso_sparse_finish(struct XorrisO *xorriso,
756 struct Xorriso_sparse_statE **sparse_state,
757 int write_fd, int flag)
758 {
759 int ret;
760 off_t cur_pos;
761 struct Xorriso_sparse_statE *o;
762
763 if(sparse_state == NULL)
764 return(0);
765 o= *sparse_state;
766 if(o == NULL)
767 return(1);
768 if(write_fd == -1)
769 {ret= 1; goto ex;}
770
771 #ifdef Xorriso_check_sparsE
772
773 cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR);
774 if(cur_pos == -1)
775 {ret= -1; goto ex;}
776 if(cur_pos != o->cur_pos) {
777 Xorriso_sparse_warn(xorriso, o, 2,
778 "cur_pos deviation in Xorriso_sparse_finish", 0);
779 o->cur_pos= cur_pos;
780 }
781
782 #else
783
784 cur_pos= o->cur_pos;
785
786 #endif /* ! Xorriso_check_sparsE */
787
788 if(o->after_last_written < cur_pos) {
789 /* Check whether the gap since after_last_written is too small.
790 If so: fill the whole gap by writing zeros, else: write a last zero byte.
791 */
792 if(xorriso->sparse_min_gap > cur_pos - o->after_last_written)
793 ret= Xorriso_sparse_zeroize(xorriso, o, write_fd, o->after_last_written,
794 cur_pos - o->after_last_written, 0);
795 else
796 ret= Xorriso_sparse_zeroize(xorriso, o, write_fd, cur_pos - 1, (off_t) 1,
797 0);
798 if(ret <= 0)
799 goto ex;
800 }
801 ret= 1;
802 ex:;
803 Xorriso_free_meM(o);
804 *sparse_state= NULL;
805 return(ret);
806 }
807
808
809 /* @param flag bit0= Minimal transfer: access permissions only
810 bit1= *_offset and bytes are valid for writing to regular file
811 bit2= This is not a parameter. Do not report if ignored
812 bit3= do not restore properties
813 bit4= issue pacifier messages with long lasting copying
814 bit7= return 4 if restore fails from denied permission
815 do not issue error message
816 @return <0 severe error , 0 failure , 1 success ,
817 2 regularly not installed (disallowed device, UNIX domain socket)
818 4 with bit7: permission to restore was denied
819 */
820 int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node,
821 char *img_path, off_t img_offset,
822 char *disk_path, off_t disk_offset, off_t bytes,
823 int flag)
824 {
825 int ret= 0, write_fd= -1, wanted, wret, open_flags, l_errno= 0;
826 int target_deleted= 0, buf_size= 32 * 1024;
827 char *what= "[unknown filetype]";
828 char *buf= NULL, type_text[5], *temp_path= NULL, *buf_pt, *reason;
829 char *link_target, *open_path_pt= NULL;
830 off_t todo= 0, size, seek_ret, last_p_count= 0, already_done, read_count= 0;
831 void *data_stream= NULL;
832 mode_t mode;
833 dev_t dev= 0;
834 struct stat stbuf;
835 struct utimbuf utime_buffer;
836 IsoImage *volume;
837 IsoBoot *bootcat;
838 uint32_t lba;
839 char *catcontent = NULL;
840 off_t catsize, iso_node_size, wanted_size, cap;
841 char disk_md5[16], iso_md5[16];
842 void *ctx= NULL;
843 int use_md5= 0, i, sparse_ret= 3;
844 struct Xorriso_sparse_statE *sparse_state= NULL;
845
846 Xorriso_alloc_meM(buf, char, buf_size);
847 Xorriso_alloc_meM(temp_path, char, SfileadrL);
848
849 if(!(flag & 2))
850 img_offset= bytes= 0;
851 if(LIBISO_ISDIR(node)) {
852 what= "directory";
853 ret= mkdir(disk_path, 0777);
854 l_errno= errno;
855
856 } else if(LIBISO_ISREG(node) || ISO_NODE_IS_BOOTCAT(node)) {
857 if(ISO_NODE_IS_BOOTCAT(node)) {
858 what= "boot catalog";
859 } else {
860 what= "regular file";
861 ret= Xorriso_iso_file_open(xorriso, img_path, (void *) node, &data_stream,
862 1);
863 if(ret<=0)
864 goto ex;
865 if((xorriso->do_md5 & 65) == 65 && !(flag & 2)) {
866 ret= Xorriso_is_plain_image_file(xorriso, (void *) node, img_path, 0);
867 if(ret > 0) {
868 ret= Xorriso_get_md5(xorriso, (void *) node, img_path, iso_md5, 1);
869 if(ret > 0)
870 ret= Xorriso_md5_start(xorriso, &ctx, 0);
871 if(ret > 0) {
872 use_md5= 1;
873 } else if(xorriso->do_md5 & 128) {
874 sprintf(xorriso->info_text,
875 "Cannot obtain any recorded MD5 of file ");
876 Text_shellsafe(img_path, xorriso->info_text, 1);
877 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
878 ret= Xorriso_eval_problem_status(xorriso, 0, 1 | 2);
879 if(ret < 0)
880 {ret= 0; goto ex;}
881 }
882 }
883 }
884 }
885 open_path_pt= disk_path;
886 ret= stat(open_path_pt, &stbuf);
887 if(ret == -1 && errno == EACCES && (flag & 128))
888 {ret= 4; goto ex;}
889 if(flag&2) {
890 if(ret != -1) {
891 wanted_size= disk_offset + bytes;
892 iso_node_size= iso_file_get_size((IsoFile *) node);
893 if(wanted_size > disk_offset + iso_node_size)
894 wanted_size= disk_offset + iso_node_size;
895 cap= wanted_size;
896 ret= Xorriso_determine_capacity(xorriso, open_path_pt, &cap, &reason,
897 3);
898 if(ret <= 0 || (cap <= 0 && !S_ISREG(stbuf.st_mode))) {
899 if(ret > 0)
900 reason= "has addressable range 0";
901 sprintf(xorriso->info_text,
902 "Restore offset demanded. But target file (%s) ",
903 Ftypetxt(stbuf.st_mode, 0));
904 Text_shellsafe(disk_path, xorriso->info_text, 1);
905 strcat(xorriso->info_text, reason);
906 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE",0); l_errno= 0;
907 goto cannot_restore;
908 }
909 if(cap < wanted_size && !S_ISREG(stbuf.st_mode)) {
910
911 /* >>> non-regular file might be too small to take the interval */;
912
913 }
914 }
915 } else {
916 /* If source and target are the same disk file then do not copy content */
917 ret= Xorriso_restore_is_identical(xorriso, (void *) node, img_path,
918 disk_path, type_text, 1);
919 if(ret<0)
920 goto ex;
921 if(ret==1) {
922 /* preliminarily emulate touch (might get overridden later) */
923 utime_buffer.actime= stbuf.st_atime;
924 utime_buffer.modtime= time(0);
925 utime(disk_path,&utime_buffer);
926 goto restore_properties;
927 }
928 if(ret==2) {
929 /* Extract to temporary file and rename only after copying */
930 ret= Xorriso_make_tmp_path(xorriso, disk_path, temp_path, &write_fd,
931 128);
932 if(ret <= 0 || ret == 4)
933 goto ex;
934 open_path_pt= temp_path;
935 }
936 }
937 if(write_fd==-1) {
938 open_flags= O_WRONLY|O_CREAT;
939 if(disk_offset==0 || !(flag&2))
940 open_flags|= O_EXCL;
941 write_fd= open(open_path_pt, open_flags | O_BINARY, S_IRUSR | S_IWUSR);
942 l_errno= errno;
943 if(write_fd == -1 && errno == EACCES && (flag & 128))
944 {ret= 4; goto ex;}
945 if(write_fd==-1)
946 goto cannot_restore;
947 }
948 if(ISO_NODE_IS_BOOTCAT(node)) {
949 ret= Xorriso_get_volume(xorriso, &volume, 0);
950 if(ret<=0)
951 goto ex;
952 ret= iso_image_get_bootcat(volume, &bootcat, &lba, &catcontent, &catsize);
953 if(ret < 0)
954 goto ex;
955 todo= size= catsize;
956 } else {
957 todo= size= iso_file_get_size((IsoFile *) node);
958 }
959 if(flag&2) {
960 if(bytes<size)
961 todo= size= bytes;
962 seek_ret= lseek(write_fd, disk_offset, SEEK_SET);
963 l_errno= errno;
964 if(seek_ret == -1) {
965 sprintf(xorriso->info_text,
966 "Cannot address byte %.f in filesystem path ",
967 (double) disk_offset);
968 Text_shellsafe(open_path_pt, xorriso->info_text, 1);
969 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
970 goto cannot_restore;
971 }
972 }
973 if(ISO_NODE_IS_FILE(node))
974 Xorriso_sparse_init(xorriso, &sparse_state, write_fd, 0);
975
976 while(todo>0) {
977 wanted= buf_size;
978 if(wanted>todo)
979 wanted= todo;
980 if(ISO_NODE_IS_BOOTCAT(node)) {
981 ret= todo;
982 buf_pt= catcontent;
983 } else {
984 ret= Xorriso_iso_file_read(xorriso, data_stream, buf, wanted, 0);
985 buf_pt= buf;
986 }
987 if(ret<=0) {
988 if(xorriso->extract_error_mode == 0 &&
989 Xorriso_is_plain_image_file(xorriso, node, "", 0)) {
990 close(write_fd);
991 write_fd= -1;
992 already_done= (size - todo) / (off_t) 2048;
993 already_done*= (off_t) 2048;
994 sprintf(xorriso->info_text,
995 "Starting best_effort handling on ISO file ");
996 Text_shellsafe(img_path, xorriso->info_text, 1);
997 sprintf(xorriso->info_text + strlen(xorriso->info_text),
998 " at byte %.f", (double) already_done);
999 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1000 ret= Xorriso_read_file_data(xorriso, node, img_path, open_path_pt,
1001 already_done, already_done, size - already_done, 2);
1002 if(ret >= 0)
1003 xorriso->pacifier_byte_count+= todo;
1004 if(ret > 0)
1005 todo= 0;
1006 else
1007 todo= -1;
1008 }
1009 if(ret <= 0) {
1010 sprintf(xorriso->info_text, "Cannot read all bytes from ISO file ");
1011 Text_shellsafe(img_path, xorriso->info_text, 1);
1012 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1013 }
1014 break;
1015 }
1016 read_count+= ret;
1017 if(use_md5)
1018 Xorriso_md5_compute(xorriso, ctx, buf_pt, ret, 0);
1019
1020 if(img_offset > read_count - ret) {
1021 /* skip the desired amount of bytes */
1022 if(read_count <= img_offset)
1023 continue;
1024 buf_pt= buf_pt + (img_offset - (read_count - ret));
1025 ret= read_count - img_offset;
1026 }
1027
1028 if(sparse_state == NULL)
1029 wret= write(write_fd, buf_pt, ret);
1030 else
1031 wret= Xorriso_sparse_write(xorriso, sparse_state, write_fd, buf_pt, ret,
1032 0);
1033 if(wret>=0) {
1034 todo-= wret;
1035 xorriso->pacifier_byte_count+= wret;
1036 if((flag&16) &&
1037 xorriso->pacifier_byte_count - last_p_count >= 128*1024) {
1038 Xorriso_pacifier_callback(xorriso, "files restored",
1039 xorriso->pacifier_count,
1040 xorriso->pacifier_total, "", 2 | 4 | 8);
1041 last_p_count= xorriso->pacifier_byte_count;
1042 }
1043 }
1044 if(wret != ret) {
1045 sprintf(xorriso->info_text,
1046 "Cannot write all bytes to disk filesystem path ");
1047 Text_shellsafe(open_path_pt, xorriso->info_text, 1);
1048 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
1049 break;
1050 }
1051 }
1052
1053 if(use_md5) {
1054 ret= Xorriso_md5_end(xorriso, &ctx, disk_md5, 0);
1055 if(ret <= 0) {
1056 sprintf(xorriso->info_text,
1057 "Internal problem with obtaining computed MD5 for extracted data of ");
1058 goto bad_md5;
1059 } else {
1060 for(i= 0; i < 16; i++)
1061 if(iso_md5[i] != disk_md5[i])
1062 break;
1063 if(i < 16) {
1064 sprintf(xorriso->info_text,
1065 "MD5 of extracted data does not match recorded MD5 of file ");
1066 bad_md5:;
1067 Text_shellsafe(img_path, xorriso->info_text, 1);
1068 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
1069 ret= Xorriso_eval_problem_status(xorriso, 0, 1 | 2);
1070 if(ret < 0)
1071 {ret= 0; goto ex;}
1072 }
1073 }
1074 }
1075
1076 if(write_fd != -1) {
1077 sparse_ret= Xorriso_sparse_finish(xorriso, &sparse_state, write_fd, 0);
1078 close(write_fd);
1079 }
1080 write_fd= -1;
1081 if(todo > 0 && xorriso->extract_error_mode == 2) {
1082 unlink(open_path_pt);
1083 target_deleted= 1;
1084 }
1085 if(! ISO_NODE_IS_BOOTCAT(node))
1086 Xorriso_iso_file_close(xorriso, &data_stream, 0);
1087 data_stream= NULL;
1088 if(temp_path==open_path_pt && !target_deleted) {
1089 ret= rename(temp_path, disk_path);
1090 if(ret==-1) {
1091 sprintf(xorriso->info_text, "Cannot rename temporary path ");
1092 Text_shellsafe(temp_path, xorriso->info_text, 1);
1093 strcat(xorriso->info_text, " to final disk path ");
1094 Text_shellsafe(disk_path, xorriso->info_text, 1 | 2);
1095 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
1096 unlink(temp_path);
1097 ret= 0; goto ex;
1098 }
1099 }
1100 ret= -(todo > 0);
1101 l_errno= 0;
1102 if(sparse_ret <= 0) {
1103 strcpy(xorriso->info_text, "Could not finalize sparse extraction of ");
1104 Text_shellsafe(disk_path, xorriso->info_text, 1 | 2);
1105 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text,
1106 sparse_ret < 0 ? errno : 0, "FAILURE", 0);
1107 }
1108
1109 } else if(LIBISO_ISLNK(node)) {
1110 what= "symbolic link";
1111 link_target= (char *) iso_symlink_get_dest((IsoSymlink *) node);
1112 ret= symlink(link_target, disk_path);
1113 l_errno= errno;
1114
1115 } else if(LIBISO_ISCHR(node)) {
1116 what= "character device";
1117 if(xorriso->allow_restore!=2) {
1118 ignored:;
1119 if(!(flag&4)) {
1120 sprintf(xorriso->info_text, "Ignored file type: %s ", what);
1121 Text_shellsafe(img_path, xorriso->info_text, 1);
1122 strcat(xorriso->info_text, " = ");
1123 Text_shellsafe(disk_path, xorriso->info_text, 1 | 2);
1124 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1125 }
1126 {ret= 2; goto ex;}
1127 }
1128 mode= S_IFCHR | 0777;
1129 ret= Xorriso_node_get_dev(xorriso, node, img_path, &dev, 0);
1130 if(ret<=0)
1131 goto ex;
1132 if(dev == (dev_t) 1) {
1133 probably_damaged:;
1134 sprintf(xorriso->info_text,
1135 "Most probably damaged device file not restored: mknod ");
1136 Text_shellsafe(disk_path, xorriso->info_text, 1);
1137 sprintf(xorriso->info_text + strlen(xorriso->info_text),
1138 " %s 0 1", LIBISO_ISCHR(node) ? "c" : "b");
1139 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
1140 ret= 0; goto ex;
1141 }
1142 ret= mknod(disk_path, mode, dev);
1143 l_errno= errno;
1144
1145 } else if(LIBISO_ISBLK(node)) {
1146 what= "block device";
1147 if(xorriso->allow_restore!=2)
1148 goto ignored;
1149 mode= S_IFBLK | 0777;
1150 ret= Xorriso_node_get_dev(xorriso, node, img_path, &dev, 0);
1151 if(ret<=0)
1152 goto ex;
1153 if(dev == (dev_t) 1)
1154 goto probably_damaged;
1155 ret= mknod(disk_path, mode, dev);
1156 l_errno= errno;
1157
1158 } else if(LIBISO_ISFIFO(node)) {
1159 what= "named pipe";
1160 mode= S_IFIFO | 0777;
1161 ret= mknod(disk_path, mode, dev);
1162 l_errno= errno;
1163
1164 } else if(LIBISO_ISSOCK(node)) {
1165 what= "unix socket";
1166 /* Restoring a socket file is not possible. One rather needs to restart
1167 the service which temporarily created the socket. */
1168 goto ignored;
1169
1170 } else {
1171 sprintf(xorriso->info_text, "Cannot restore file type '%s'", what);
1172 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
1173 ret= 0; goto ex;
1174
1175 }
1176 if(ret == -1 && l_errno == EACCES && (flag & 128))
1177 {ret= 4; goto ex;}
1178 if(ret==-1) {
1179 cannot_restore:;
1180 sprintf(xorriso->info_text,
1181 "Cannot restore %s to disk filesystem: ", what);
1182 Text_shellsafe(img_path, xorriso->info_text, 1);
1183 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, l_errno, "FAILURE", 0);
1184 ret= 0; goto ex;
1185 }
1186
1187 restore_properties:;
1188 if((flag&8) || LIBISO_ISLNK(node))
1189 ret= 1;
1190 else
1191 ret= Xorriso_restore_properties(xorriso, disk_path, node, flag&1);
1192 if(todo < 0)
1193 ret= 0;
1194 ex:;
1195 if(write_fd != -1) {
1196 close(write_fd);
1197 if(ret <= 0 && xorriso->extract_error_mode == 2 && open_path_pt != NULL)
1198 unlink(open_path_pt);
1199 }
1200 Xorriso_free_meM(buf);
1201 Xorriso_free_meM(temp_path);
1202 if(catcontent != NULL)
1203 free(catcontent);
1204 if(data_stream!=NULL)
1205 Xorriso_iso_file_close(xorriso, &data_stream, 0);
1206 if(ctx != NULL)
1207 Xorriso_md5_end(xorriso, &ctx, disk_md5, 0);
1208 if(sparse_state != NULL)
1209 Xorriso_sparse_finish(xorriso, &sparse_state, -1, 0);
1210 Xorriso_process_msg_queues(xorriso,0);
1211 return(ret);
1212 }
1213
1214
1215 /* Handle overwrite situation in disk filesystem.
1216 @param node intended source of overwriting or NULL
1217 @param flag
1218 bit4= return 3 on rejection by exclusion or user
1219 bit6= permission to call Xorriso_make_accessible()
1220 */
1221 int Xorriso_restore_overwrite(struct XorrisO *xorriso,
1222 IsoNode *node, char *img_path,
1223 char *path, char *nominal_path,
1224 struct stat *stbuf, int flag)
1225 {
1226 int ret;
1227 char type_text[5];
1228
1229 Xorriso_process_msg_queues(xorriso,0);
1230 if(xorriso->do_overwrite==1 ||
1231 (xorriso->do_overwrite==2 && !S_ISDIR(stbuf->st_mode))) {
1232
1233 ret= Xorriso_restore_is_identical(xorriso, (void *) node, img_path,
1234 path, type_text, (node!=NULL));
1235 if(ret<0)
1236 return(ret);
1237 if(ret>0) /* will be handled properly by restore functions */
1238 ret= Xorriso_reassure_restore(xorriso, path, 8);
1239 else
1240 ret= Xorriso_rmx(xorriso, (off_t) 0, path, 8 | (flag & 64));
1241 if(ret<=0)
1242 return(ret);
1243 if(ret==3) {
1244 sprintf(xorriso->info_text, "User revoked restoring of (ISO) file: ");
1245 Text_shellsafe(img_path, xorriso->info_text, 1);
1246 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1247 return(3*!!(flag&16));
1248 }
1249 return(1);
1250 }
1251 Xorriso_msgs_submit(xorriso, 0, nominal_path, 0, "ERRFILE", 0);
1252 sprintf(xorriso->info_text, "While restoring ");
1253 Text_shellsafe(nominal_path, xorriso->info_text, 1);
1254 strcat(xorriso->info_text, " : ");
1255 if(strcmp(nominal_path, path) == 0)
1256 strcat(xorriso->info_text, "file object");
1257 else
1258 Text_shellsafe(path, xorriso->info_text, 1 | 2);
1259 strcat(xorriso->info_text, " exists and may not be overwritten");
1260 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1261 return(0);
1262 }
1263
1264
1265 /*
1266 @return <0 error,
1267 bit0= hardlink created
1268 bit1= siblings with target NULL found
1269 bit2= siblings with non-NULL target found
1270 */
1271 int Xorriso_restore_target_hl(struct XorrisO *xorriso, IsoNode *node,
1272 char *disk_path, int *node_idx, int flag)
1273 {
1274 int ret, min_hl, max_hl, i, null_target_sibling= 0, link_sibling= 0;
1275
1276 if(xorriso->hln_targets == NULL)
1277 return(0);
1278 ret= Xorriso_search_hardlinks(xorriso, node, node_idx, &min_hl, &max_hl, 1);
1279 if(ret < 0)
1280 return(ret);
1281 if(ret == 0 || *node_idx < 0 || min_hl == max_hl)
1282 return(0);
1283 for(i= min_hl; i <= max_hl; i++) {
1284 if(xorriso->hln_targets[i] == NULL) {
1285 if(i != *node_idx)
1286 null_target_sibling= 1;
1287 continue;
1288 }
1289 link_sibling= 1;
1290 ret= Xorriso_restore_make_hl(xorriso, xorriso->hln_targets[i], disk_path,
1291 !!xorriso->do_auto_chmod);
1292 if(ret > 0)
1293 return(1);
1294 }
1295 return((null_target_sibling << 1) | (link_sibling << 2));
1296 }
1297
1298
1299 /*
1300 @return <0 error,
1301 bit0= hardlink created
1302 bit2= siblings lower index found
1303 */
1304 int Xorriso_restore_prefix_hl(struct XorrisO *xorriso, IsoNode *node,
1305 char *disk_path, int node_idx, int flag)
1306 {
1307 int ret, min_hl, max_hl, i, link_sibling= 0, hflag;
1308 char *old_path= NULL, *img_path= NULL;
1309 struct Xorriso_lsT *img_prefixes= NULL, *disk_prefixes= NULL;
1310
1311 Xorriso_alloc_meM(old_path, char, SfileadrL);
1312 Xorriso_alloc_meM(img_path, char, SfileadrL);
1313
1314 ret= Xorriso_search_hardlinks(xorriso, node, &node_idx, &min_hl, &max_hl,
1315 2 | 4);
1316 if(ret < 0)
1317 goto ex;
1318 if(ret == 0 || min_hl == max_hl)
1319 {ret= 0; goto ex;}
1320
1321 for(i= min_hl; i < node_idx; i++) {
1322 link_sibling= 1;
1323 ret= Xorriso_path_from_node(xorriso, xorriso->node_array[i], img_path, 0);
1324 if(ret < 0)
1325 goto ex;
1326 if(ret == 0)
1327 continue; /* Node is deleted from tree (Should not happen here) */
1328 hflag= 1;
1329 if(i == min_hl) {
1330 hflag= 0;
1331 } else if(xorriso->node_array[i] != xorriso->node_array[i - 1]) {
1332 hflag= 0;
1333 }
1334 if(hflag == 0) {
1335 img_prefixes= xorriso->node_img_prefixes;
1336 disk_prefixes= xorriso->node_disk_prefixes;
1337 }
1338 ret= Xorriso_make_restore_path(xorriso, &img_prefixes, &disk_prefixes,
1339 img_path, old_path, hflag);
1340 if(ret <= 0)
1341 goto ex;
1342 ret= Xorriso_restore_make_hl(xorriso, old_path, disk_path,
1343 !!xorriso->do_auto_chmod);
1344 if(ret > 0)
1345 {ret= 1; goto ex;}
1346 }
1347 ret= link_sibling << 2;
1348 ex:;
1349 Xorriso_free_meM(old_path);
1350 Xorriso_free_meM(img_path);
1351 return(ret);
1352 }
1353
1354
1355 /* @return <0 = error , 0 = availmem exhausted first time , 1 = ok
1356 2 = availmem exhausted repeated
1357 */
1358 int Xorriso_register_node_target(struct XorrisO *xorriso, int node_idx,
1359 char *disk_path, int flag)
1360 {
1361 int l;
1362
1363 if(xorriso->node_targets_availmem == 0)
1364 return(2);
1365 if(xorriso->hln_targets == NULL || node_idx < 0 ||
1366 node_idx >= xorriso->hln_count)
1367 return(0);
1368 if(xorriso->hln_targets[node_idx] != NULL) {
1369 xorriso->node_targets_availmem+= strlen(xorriso->hln_targets[node_idx]) +1;
1370 free(xorriso->hln_targets[node_idx]);
1371 }
1372 l= strlen(disk_path);
1373 if(xorriso->node_targets_availmem <= l + 1) {
1374 sprintf(xorriso->info_text,
1375 "Hardlink target buffer exceeds -temp_mem_limit. Hardlinks may get divided.");
1376 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1377 xorriso->node_targets_availmem= 0;
1378 return(0);
1379 }
1380 xorriso->hln_targets[node_idx]= strdup(disk_path);
1381 if(xorriso->hln_targets[node_idx] == NULL) {
1382 Xorriso_no_malloc_memory(xorriso, NULL, 0);
1383 return(-1);
1384 }
1385 xorriso->node_targets_availmem-= (l + 1);
1386 return(1);
1387 }
1388
1389
1390 /*
1391 @param flag bit0= offset and bytes is valid for writing to regular file
1392 bit1= do not report copied files
1393 bit2= -follow, -not_*: this is not a command parameter
1394 bit3= keep directory open: keep owner, allow rwx for owner
1395 bit4= do not look for hardlinks even if enabled
1396 bit6= this is a copy action: do not fake times and ownership
1397 bit7= return 4 if restore fails from denied permission
1398 do not issue error message
1399 bit10= do not restore properties
1400 @return <=0 = error , 1 = added leaf file object , 2 = added directory ,
1401 3= regularly not installed (disallowed device, UNIX domain socket)
1402 4 = with bit7: permission to restore was denied
1403 */
1404 int Xorriso_restore_disk_object(struct XorrisO *xorriso,
1405 char *img_path, IsoNode *node,
1406 char *disk_path,
1407 off_t offset, off_t bytes, int flag)
1408 {
1409 int ret, i, split_count= 0, partno, total_parts, leaf_is_split= 0;
1410 int record_hl_path= 0, node_idx, cannot_register= 0, no_props;
1411 off_t total_bytes;
1412 char *part_name, *part_path= NULL, *img_path_pt= NULL;
1413 IsoImage *volume;
1414 IsoNode *part_node, *first_part_node= NULL;
1415 struct SplitparT *split_parts= NULL;
1416 struct stat stbuf;
1417
1418 Xorriso_alloc_meM(part_path, char, SfileadrL);
1419
1420 no_props= !!(flag & 1024);
1421
1422 ret= Xorriso_get_volume(xorriso, &volume, 0);
1423 if(ret<=0)
1424 goto ex;
1425
1426 if(LIBISO_ISDIR(node) && xorriso->do_concat_split)
1427 leaf_is_split= Xorriso_identify_split(xorriso, img_path, node,
1428 &split_parts, &split_count, &stbuf, 1 | 4);
1429 if(leaf_is_split) {
1430 /* map all files in directory img_path into regular file disk_path */
1431
1432 for(i=0 ; i<split_count; i++) {
1433 Splitparts_get(split_parts, i, &part_name, &partno, &total_parts,
1434 &offset, &bytes, &total_bytes, 0);
1435
1436 strcpy(part_path, img_path);
1437 if(Sfile_add_to_path(part_path, part_name, 0)<=0) {
1438 Xorriso_much_too_long(xorriso, strlen(img_path)+strlen(part_name)+1, 2);
1439 goto restoring_failed;
1440 }
1441 ret= Xorriso_node_from_path(xorriso, volume, part_path, &part_node, 0);
1442 if(ret<=0)
1443 goto restoring_failed;
1444 if(i==0)
1445 first_part_node= part_node;
1446 if(offset+bytes>total_bytes)
1447 bytes= total_bytes-offset;
1448 ret= Xorriso_tree_restore_node(xorriso, part_node, part_path, (off_t) 0,
1449 disk_path, offset, bytes,
1450 (!!(flag&64)) | 2 | (flag & (4 | 128)) | 8 | ( 16 * !(flag&2)));
1451 if(ret<=0)
1452 goto restoring_failed;
1453 if(ret == 4)
1454 goto ex;
1455 }
1456 if(first_part_node != NULL && !no_props)
1457 Xorriso_restore_properties(xorriso, disk_path, first_part_node,
1458 !!(flag&64));
1459 goto went_well;
1460 }
1461
1462 #ifdef Osirrox_not_yeT
1463
1464 if(resolve_link) {
1465 ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0);
1466 if(ret<=0)
1467 goto ex;
1468 disk_path_pt= resolved_disk_path;
1469 } else
1470
1471 #endif /* Osirrox_not_yeT */
1472
1473 img_path_pt= img_path;
1474
1475 if(!((xorriso->ino_behavior & 4) || (flag & (1 | 16)) || LIBISO_ISDIR(node))){
1476 /* Try to restore as hardlink */
1477 ret= Xorriso_restore_target_hl(xorriso, node, disk_path, &node_idx,
1478 !!xorriso->do_auto_chmod);
1479 if(ret < 0) {
1480 goto ex;
1481 } else if(ret & 1) {
1482 /* Success, hardlink was created */
1483 goto went_well;
1484 } else if(ret & 2) {
1485 /* Did not establish hardlink. Hardlink siblings with target NULL found.*/
1486 record_hl_path= 1;
1487 }
1488 if(ret & 4) {
1489 /* Found siblings with non-NULL target, but did not link. */
1490 ret= Xorriso_eval_problem_status(xorriso, 1, 1 | 2);
1491 if(ret < 0)
1492 {ret= 0; goto ex;}
1493 }
1494 }
1495
1496 ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, (off_t) 0,
1497 disk_path, offset, bytes,
1498 (flag&(4 | 8 | 128)) | (!!(flag&64)) | ((flag&1)<<1) | ( 16 * !(flag&2))
1499 | (no_props << 3));
1500 if(ret == 4)
1501 goto ex;
1502 if(ret > 0 && (flag & 8) && !no_props)
1503 ret= Xorriso_restore_properties(xorriso, disk_path, node, 2 | !!(flag&64));
1504 if(ret<=0) {
1505 restoring_failed:;
1506 sprintf(xorriso->info_text, "Restoring failed: ");
1507 Text_shellsafe(img_path, xorriso->info_text, 1);
1508 strcat(xorriso->info_text, " = ");
1509 Text_shellsafe(disk_path, xorriso->info_text, 1 | 2);
1510 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
1511 {ret= 0; goto ex;}
1512 }
1513 if(ret==2)
1514 {ret= 3; goto ex;}
1515 if(record_hl_path) { /* Start of a disk hardlink family */
1516 ret= Xorriso_register_node_target(xorriso, node_idx, disk_path, 0);
1517 if(ret < 0)
1518 goto ex;
1519 if(ret == 0)
1520 cannot_register= 1;
1521 }
1522
1523 went_well:;
1524 xorriso->pacifier_count++;
1525 if(!(flag&2))
1526 Xorriso_pacifier_callback(xorriso, "files restored",
1527 xorriso->pacifier_count,
1528 xorriso->pacifier_total, "", 4 | 8);
1529 ret= 1;
1530 ex:;
1531 if(split_parts!=NULL)
1532 Splitparts_destroy(&split_parts, split_count, 0);
1533 Xorriso_free_meM(part_path);
1534 if(ret > 0 && cannot_register)
1535 ret= 0;
1536 return(ret);
1537 }
1538
1539
1540 /* @param flag bit0= source is a directory and not to be restored as split file
1541 >>> bit6= permission to call Xorriso_make_accessible()
1542 @return <=0 error , 1=collision handled , 2=no collision , 3=revoked by user
1543 */
1544 int Xorriso_handle_collision(struct XorrisO *xorriso,
1545 IsoNode *node, char *img_path,
1546 char *disk_path, char *nominal_disk_path,
1547 int *stbuf_ret, int flag)
1548 {
1549 int ret, target_is_dir= 0, target_is_link= 0, stat_ret, made_accessible= 0;
1550 struct stat target_stbuf, lt_stbuf;
1551 struct PermiteM *perm_stack_mem;
1552
1553 perm_stack_mem= xorriso->perm_stack;
1554
1555 /* does a disk file exist with this name ? */
1556 *stbuf_ret= lstat(disk_path, &target_stbuf);
1557 if(*stbuf_ret==-1) {
1558 if((flag & 64) && errno == EACCES) {
1559 ret= Xorriso_make_accessible(xorriso, disk_path, 0);
1560 if(ret < 0)
1561 goto ex;
1562 made_accessible= 1;
1563 *stbuf_ret= lstat(disk_path, &target_stbuf);
1564 }
1565 if(*stbuf_ret==-1)
1566 {ret= 2; goto ex;}
1567 }
1568 target_is_link= S_ISLNK(target_stbuf.st_mode);
1569 if(target_is_link) {
1570 stat_ret= stat(disk_path, <_stbuf);
1571 if(stat_ret == -1) {
1572 if((flag & 64) && errno == EACCES && !made_accessible) {
1573 ret= Xorriso_make_accessible(xorriso, disk_path, 0);
1574 if(ret < 0)
1575 goto ex;
1576 made_accessible= 1;
1577 stat_ret= stat(disk_path, <_stbuf);
1578 }
1579 }
1580 if(stat_ret != -1)
1581 target_is_dir= S_ISDIR(lt_stbuf.st_mode);
1582 } else {
1583 target_is_dir= S_ISDIR(target_stbuf.st_mode);
1584 }
1585 if(target_is_dir && (!target_is_link) && !(flag&1)) {
1586 strcpy(xorriso->info_text, "Attempt to replace DISK directory ");
1587 Text_shellsafe(nominal_disk_path,
1588 xorriso->info_text+strlen(xorriso->info_text), 0);
1589 strcat(xorriso->info_text, " by ISO file ");
1590 Text_shellsafe(img_path, xorriso->info_text+strlen(xorriso->info_text), 0);
1591 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1592 ret= 0; goto ex;
1593 }
1594
1595 if(!(target_is_dir && (flag&1))) {
1596 Xorriso_process_msg_queues(xorriso,0);
1597 ret= Xorriso_restore_overwrite(xorriso, node, img_path, disk_path,
1598 nominal_disk_path, &target_stbuf, 16 | (flag & 64));
1599 if(ret==3)
1600 {ret= 3; goto ex;}
1601 if(ret<=0)
1602 goto ex;
1603 *stbuf_ret= -1; /* It might still exist but will be handled properly */
1604 }
1605 ret= 1;
1606 ex:;
1607 if(made_accessible)
1608 Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
1609 return(ret);
1610 }
1611
1612
1613 /* @param flag bit0= recursion is active
1614 bit1= do not report restored files
1615 bit6= this is a copy action: do not fake times and ownership
1616 bit7+8=
1617 0= direct operation
1618 1= create only directories,
1619 count nodes in xorriso->node_counter
1620 2= only register non-directory nodes in
1621 xorriso->node_array
1622 3= count nodes in xorriso->node_counter,
1623 create no directory
1624 */
1625 int Xorriso_restore_tree(struct XorrisO *xorriso, IsoDir *dir,
1626 char *img_dir_path, char *disk_dir_path,
1627 off_t boss_mem,
1628 struct LinkiteM *link_stack, int flag)
1629 {
1630 IsoImage *volume;
1631 IsoNode *node;
1632 IsoDirIter *iter= NULL;
1633 IsoNode **node_array= NULL;
1634 int node_count= 0, node_idx;
1635 int ret, source_is_dir, fret, was_failure= 0;
1636 int do_not_dive, source_is_split= 0, len_dp, len_ip, stbuf_ret, hflag, hret;
1637 char *name, *disk_name, *leaf_name, *srcpt, *stbuf_src= "";
1638 struct LinkiteM *own_link_stack;
1639 char *sfe= NULL, *sfe2= NULL;
1640 char *disk_path= NULL, *img_path= NULL, *link_target= NULL;
1641 off_t mem;
1642 struct PermiteM *perm_stack_mem;
1643 struct stat stbuf;
1644 int dir_create= 0, node_register= 0, do_node_count= 0, normal_mode= 0;
1645
1646 perm_stack_mem= xorriso->perm_stack;
1647 switch((flag >> 7) & 3) {
1648 case 0: normal_mode= 1;
1649 break; case 1: dir_create= 1;
1650 break; case 2: node_register= 1;
1651 break; case 3: do_node_count= 1;
1652 }
1653
1654 /* Avoiding large local memory objects in order to save stack space */
1655 sfe= malloc(5*SfileadrL);
1656 sfe2= malloc(5*SfileadrL);
1657 disk_path= malloc(2*SfileadrL);
1658 img_path= malloc(2*SfileadrL);
1659 link_target= malloc(SfileadrL);
1660 if(sfe==NULL || sfe2==NULL || disk_path==NULL || img_path==NULL ||
1661 link_target==NULL) {
1662 Xorriso_no_malloc_memory(xorriso, &sfe, 0);
1663 {ret= -1; goto ex;}
1664 }
1665
1666 own_link_stack= link_stack;
1667
1668 ret= Xorriso_get_volume(xorriso, &volume, 0);
1669 if(ret<=0)
1670 goto ex;
1671
1672 stbuf_src= img_dir_path;
1673 node= (IsoNode *) dir;
1674 ret= Xorriso_fake_stbuf(xorriso, stbuf_src, &stbuf, &node, 1);
1675 if(ret<=0) {
1676 Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0);
1677 sprintf(xorriso->info_text,"Cannot open as (ISO) source directory: %s",
1678 Text_shellsafe(img_dir_path, sfe, 0));
1679 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1680 {ret= 0; goto ex;}
1681 }
1682
1683 #ifdef Osirrox_not_yeT
1684
1685 dev_t dir_dev;
1686 dir_dev= stbuf.st_dev;
1687
1688 if(S_ISLNK(stbuf.st_mode)) {
1689 if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
1690 {ret= 2; goto ex;}
1691 stbuf_src= disk_dir_path;
1692 if(stat(disk_dir_path, &stbuf)==-1)
1693 goto cannot_open_dir;
1694 if(dir_dev != stbuf.st_dev &&
1695 !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1))))
1696 {ret= 2; goto ex;}
1697 }
1698
1699 #endif /* Osirrox_not_yeT */
1700
1701 if(!S_ISDIR(stbuf.st_mode)) {
1702 Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0);
1703 sprintf(xorriso->info_text,"Is not a directory in ISO image: %s",
1704 Text_shellsafe(img_dir_path, sfe, 0));
1705 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1706 {ret= 0; goto ex;}
1707 }
1708
1709 mem= boss_mem;
1710 ret= Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count,
1711 &node_idx, &node,
1712 1 | 4 * (normal_mode && (xorriso->ino_behavior & 4)));
1713 if(ret<=0)
1714 goto ex;
1715
1716 if(Sfile_str(img_path, img_dir_path,0)<=0) {
1717 much_too_long:;
1718 Xorriso_much_too_long(xorriso, SfileadrL, 2);
1719 {ret= 0; goto ex;}
1720 }
1721 if(img_path[0]==0 || img_path[strlen(img_path)-1]!='/')
1722 strcat(img_path,"/");
1723 name= img_path+strlen(img_path);
1724 if(Sfile_str(disk_path, disk_dir_path, 0)<=0)
1725 goto much_too_long;
1726 if(disk_path[0]==0 || disk_path[strlen(disk_path)-1]!='/')
1727 strcat(disk_path,"/");
1728 disk_name= disk_path+strlen(disk_path);
1729
1730 len_dp= strlen(disk_path);
1731 len_ip= strlen(img_path);
1732
1733 while(1) { /* loop over ISO directory content */
1734 stbuf_src= "";
1735
1736 #ifdef Osirrox_not_yeT
1737
1738 Linkitem_reset_stack(&own_link_stack, link_stack, 0);
1739
1740 #endif
1741
1742 srcpt= img_path;
1743 Xorriso_process_msg_queues(xorriso,0);
1744 ret= Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count,
1745 &node_idx, &node, 0);
1746 if(ret<0)
1747 goto ex;
1748 if(ret==0 || xorriso->request_to_abort)
1749 break;
1750 leaf_name= (char *) iso_node_get_name(node);
1751 if(Xorriso_much_too_long(xorriso, len_dp + strlen(leaf_name)+1, 0)<=0)
1752 {ret= 0; goto was_problem;}
1753 if(Xorriso_much_too_long(xorriso, len_ip + strlen(leaf_name)+1, 0)<=0)
1754 {ret= 0; goto was_problem;}
1755 /* name and disk_name are pointers into img_path and disk_path */
1756 strcpy(name, leaf_name);
1757 strcpy(disk_name, leaf_name);
1758 ret= Xorriso_path_is_excluded(xorriso, disk_path, 2);
1759 if(ret < 0)
1760 goto was_problem;
1761 if(ret > 0)
1762 continue;
1763
1764 stbuf_src= srcpt;
1765 ret= Xorriso_fake_stbuf(xorriso, img_path, &stbuf, &node, 1);
1766 if(ret<=0)
1767 goto was_problem;
1768 source_is_dir= 0;
1769
1770 #ifdef Osirrox_not_yeT
1771
1772 /* ??? Link following in the image would cause severe problems
1773 with Xorriso_path_from_node() */
1774
1775 int source_is_link;
1776
1777 source_is_link= S_ISLNK(stbuf.st_mode);
1778 if(xorriso->do_follow_links && source_is_link) {
1779 /* Xorriso_hop_link checks for wide link loops */
1780 ret= Xorriso_hop_link(xorriso, srcpt, &own_link_stack, &hstbuf, 0);
1781 if(ret<0)
1782 goto was_problem;
1783 if(ret==1) {
1784 ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 0);
1785 if(ret<=0)
1786 goto was_problem;
1787 srcpt= link_target;
1788 stbuf_src= srcpt;
1789 if(lstat(srcpt, &stbuf)==-1)
1790 goto cannot_lstat;
1791 } else {
1792 if(Xorriso_eval_problem_status(xorriso, 0, 1|2)<0)
1793 {ret= 0; goto was_problem;}
1794 }
1795 } else if (S_ISLNK(stbuf.st_mode)) {
1796 ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1);
1797 if(ret<=0)
1798 goto was_problem;
1799 }
1800
1801 #endif /* Osirrox_not_yeT */
1802
1803 do_not_dive= 0;
1804 if(S_ISDIR(stbuf.st_mode))
1805 source_is_dir= 1;
1806 source_is_split= 0;
1807 if(source_is_dir)
1808 source_is_split= Xorriso_is_split(xorriso, img_path, node, 1 | 2 | 4);
1809 if(source_is_split)
1810 do_not_dive= 1;
1811
1812 if(source_is_dir || !(dir_create || do_node_count || node_register)) {
1813 ret= Xorriso_handle_collision(xorriso, node, img_path,
1814 disk_path, disk_path, &stbuf_ret,
1815 (source_is_dir && !source_is_split));
1816 if(ret<=0 || ret==3)
1817 goto was_problem;
1818 } else {
1819 stbuf_ret= -1;
1820 }
1821
1822 if(stbuf_ret!=-1) { /* (Can only happen with directory) */
1823 Xorriso_auto_chmod(xorriso, disk_path, 0);
1824 } else {
1825 hflag= 4 | (flag & (2|64));
1826 if(source_is_dir && !do_not_dive)
1827 hflag|= 8; /* keep directory open for user */
1828 if((dir_create || do_node_count) && !source_is_dir) {
1829 xorriso->node_counter++;
1830 } else if(node_register && !source_is_dir) {
1831 if(xorriso->node_counter < xorriso->node_array_size) {
1832 xorriso->node_array[xorriso->node_counter++]= (void *) node;
1833 iso_node_ref(node);
1834 }
1835 } else if(node_register || do_node_count) {
1836 ret= 1;
1837 } else {
1838 ret= Xorriso_restore_disk_object(xorriso, img_path, node, disk_path,
1839 (off_t) 0, (off_t) 0, hflag);
1840 if(ret == 3) /* intentionally not restored */
1841 do_not_dive= 1;
1842 }
1843 if(ret<=0)
1844 goto was_problem;
1845 }
1846 if(source_is_dir && !do_not_dive) {
1847 ret= Xorriso_restore_tree(xorriso, (IsoDir *) node,
1848 img_path, disk_path, mem,
1849 own_link_stack, 1 | (flag & (2 | (3 << 7))));
1850 /* eventually restore exact access permissions of directory */
1851 hret= Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso,
1852 !!(flag&64));
1853 if(hret<=0 && hret<ret)
1854 ret= hret;
1855 if(ret<=0)
1856 goto was_problem;
1857 }
1858
1859 continue; /* regular bottom of loop */
1860 was_problem:;
1861 was_failure= 1;
1862 fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
1863 if(fret<0)
1864 goto ex;
1865 Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, !!(flag&64));
1866 }
1867
1868 ret= 1;
1869 ex:
1870 Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, !!(flag&64));
1871 if(sfe!=NULL)
1872 free(sfe);
1873 if(sfe2!=NULL)
1874 free(sfe2);
1875 if(disk_path!=NULL)
1876 free(disk_path);
1877 if(img_path!=NULL)
1878 free(img_path);
1879 if(link_target!=NULL)
1880 free(link_target);
1881 Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count,
1882 &node_idx, &node, (1u<<31));
1883
1884 Xorriso_process_msg_queues(xorriso,0);
1885
1886 #ifdef Osirrox_not_yeT
1887
1888 Linkitem_reset_stack(&own_link_stack, link_stack, 0);
1889
1890 #endif
1891
1892 if(ret<=0)
1893 return(ret);
1894 return(!was_failure);
1895 }
1896
1897
1898 /*
1899 @param flag
1900 >>> bit0= mkdir: graft in as empty directory, not as copy from iso
1901 bit1= do not report copied files
1902 bit2= -follow, -not_*: this is not a command parameter
1903 bit3= use offset and cut_size for -paste_in
1904 bit4= return 3 on rejection by exclusion or user
1905 bit5= if directory then do not add sub tree
1906 bit6= this is a copy action: do not fake times and ownership
1907 bit7+8= operation mode
1908 0= direct operation
1909 1= create only directories,
1910 count nodes in xorriso->node_counter
1911 2= only register non-directory nodes in
1912 xorriso->node_array
1913 3= count nodes in xorriso->node_counter,
1914 create no directory
1915 bit9= with operation mode 1 do net register prefixes
1916 bit10= with bit3: do not restore properties to leaf file
1917 @return <=0 = error , 1 = added leaf file object , 2 = added directory ,
1918 3 = rejected
1919 */
1920 int Xorriso_restore(struct XorrisO *xorriso,
1921 char *img_path, char *disk_path,
1922 off_t offset, off_t bytes, int flag)
1923 {
1924 IsoImage *volume;
1925 char *path= NULL, *apt, *npt;
1926 IsoNode *node= NULL;
1927 int done= 0, is_dir= 0, ret, source_is_dir, stbuf_ret, hret;
1928 int dir_create= 0, node_count= 0, node_register= 0, path_size;
1929 int leaf_is_split= 0, source_is_split= 0, new_dir_made= 0, no_props;
1930 struct stat stbuf;
1931 struct PermiteM *perm_stack_mem;
1932
1933 perm_stack_mem= xorriso->perm_stack;
1934
1935 path_size= SfileadrL;
1936 Xorriso_alloc_meM(path, char, path_size);
1937
1938 switch((flag >> 7) & 3) {
1939 case 1: dir_create= 1;
1940 break; case 2: node_register= 1;
1941 break; case 3: node_count= 1;
1942 }
1943 no_props= (!!(flag & 8)) * (flag & 1024);
1944
1945 if(dir_create && !(flag & (1 << 9))) {
1946 ret= Xorriso_lst_append_binary(&(xorriso->node_disk_prefixes),
1947 disk_path, strlen(disk_path) + 1, 0);
1948 if(ret <= 0)
1949 goto ex;
1950 ret= Xorriso_lst_append_binary(&(xorriso->node_img_prefixes),
1951 img_path, strlen(img_path) + 1, 0);
1952 if(ret <= 0)
1953 goto ex;
1954 }
1955
1956 ret= Xorriso_path_is_excluded(xorriso, disk_path, 4 | 2 | !(flag & 4));
1957 if(ret < 0)
1958 {ret= 0; goto ex;}
1959 if(ret > 0) {
1960 if(!(flag & 4)) {
1961 strcpy(xorriso->info_text,
1962 "Excluded from restoring by -not_path or -not_leaf :");
1963 Text_shellsafe(disk_path, xorriso->info_text, 1);
1964 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
1965 }
1966 {ret= 3*!!(flag&16); goto ex;}
1967 }
1968
1969 ret= Xorriso_get_volume(xorriso, &volume, 0);
1970 if(ret<=0)
1971 goto ex;
1972
1973 strncpy(path, disk_path, path_size - 1);
1974 path[path_size - 1]= 0;
1975 apt= npt= path;
1976
1977 if(!(flag&1)) {
1978 ret= Xorriso_fake_stbuf(xorriso, img_path, &stbuf, &node, 0);
1979 if(ret>0) {
1980 if(S_ISDIR(stbuf.st_mode))
1981 is_dir= 1;
1982
1983 #ifdef Osirrox_not_yeT
1984
1985 /* ??? this would cause severe problems with Xorriso_path_from_node() */
1986
1987 else if((stbuf.st_mode&S_IFMT)==S_IFLNK &&
1988 (xorriso->do_follow_links ||
1989 (xorriso->do_follow_param && !(flag&4)))) {
1990 resolve_link= 1;
1991 ret= Xorriso_iso_lstat(xorriso, img_path, &stbuf, 1|2);
1992 if(ret!=-1) {
1993 if(S_ISDIR(stbuf.st_mode))
1994 is_dir= 1;
1995 }
1996 }
1997 #endif /* Osirrox_not_yeT */
1998
1999 } else {
2000 Xorriso_process_msg_queues(xorriso,0);
2001 Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
2002 sprintf(xorriso->info_text,
2003 "Cannot determine attributes of (ISO) source file ");
2004 Text_shellsafe(img_path, xorriso->info_text, 1);
2005 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
2006 ret= 0; goto ex;
2007 }
2008 if(is_dir && xorriso->do_concat_split)
2009 leaf_is_split= Xorriso_is_split(xorriso, img_path, node, 1 | 2 | 4);
2010 }
2011 for(npt= apt; !done; apt= npt+1) {
2012 npt= strchr(apt, '/');
2013 if(npt==NULL) {
2014 npt= apt+strlen(apt);
2015 done= 1;
2016 } else
2017 *npt= 0;
2018 if(*apt==0) {
2019 *apt= '/';
2020 apt++;
2021 if(done)
2022 goto attach_source;
2023 continue;
2024 }
2025 source_is_dir= (is_dir || (flag&1) || !done);
2026 source_is_split= done && leaf_is_split;
2027
2028 stbuf_ret= -1;
2029 if((flag&8) && done) {
2030
2031 /* ??? move down from Xorriso_paste_in() :
2032 check whether target does not exist or both are suitable */;
2033
2034 } else if(source_is_dir || !(dir_create || node_count || node_register)) {
2035 ret= Xorriso_handle_collision(xorriso, node, img_path, path, disk_path,
2036 &stbuf_ret, (source_is_dir && !source_is_split));
2037 if(ret<=0 || ret==3)
2038 goto ex;
2039 }
2040
2041 new_dir_made= 0;
2042 if(stbuf_ret==-1 && (source_is_dir && !source_is_split) &&
2043 !(node_count || node_register)) {
2044 /* make a directory */
2045 ret= mkdir(path, 0777);
2046 if(ret==-1) {
2047 Xorriso_process_msg_queues(xorriso,0);
2048 Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
2049 sprintf(xorriso->info_text,
2050 "While restoring '%s' : could not insert '%s'", disk_path, path);
2051 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
2052 {ret= 0; goto ex;}
2053 }
2054 if(!done) {
2055 /* keep rwx for the owner */
2056 Xorriso_restore_implicit_properties(xorriso, disk_path, path,
2057 img_path, 4);
2058 }
2059 new_dir_made= 1;
2060 } else if((source_is_dir && !source_is_split)) {
2061 if(!(node_count || node_register))
2062 Xorriso_auto_chmod(xorriso, path, 0);
2063 }
2064 if(done) {
2065 attach_source:;
2066
2067 if(flag&1) {
2068 /* directory was created above */;
2069
2070 } else if(is_dir && !source_is_split) {
2071
2072 if(!node_register) {
2073 if(new_dir_made) { /* keep open and push to Permstack */
2074 ret= Xorriso_restore_properties(xorriso, disk_path, node,
2075 2 | !!(flag&64));
2076 if(ret <= 0) {
2077 hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
2078 if(hret < 0)
2079 goto ex;
2080 }
2081 }
2082 }
2083 if(!(flag&32)) {
2084 ret= Xorriso_restore_tree(xorriso, (IsoDir *) node, img_path, path,
2085 (off_t) 0, NULL, flag & (2 | 64 | (3 << 7)));
2086 if(ret <= 0) {
2087 hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
2088 if(hret < 0)
2089 goto ex;
2090 }
2091 if(new_dir_made && !(flag&64))
2092 /* set timestamps which Permstack_pop() will not set */
2093 Xorriso_restore_properties(xorriso, disk_path, node, 2);
2094 }
2095 } else {
2096 if(dir_create || node_count) {
2097 xorriso->node_counter++;
2098 } else if(node_register) {
2099 if(xorriso->node_counter < xorriso->node_array_size) {
2100 xorriso->node_array[xorriso->node_counter++]= (void *) node;
2101 iso_node_ref(node);
2102 }
2103 } else {
2104 ret= Xorriso_restore_disk_object(xorriso, img_path, node, path,
2105 offset, bytes, (flag & (2|4|64)) | no_props | !!(flag&8));
2106 if(ret <= 0) {
2107 hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2);
2108 if(hret < 0)
2109 goto ex;
2110 }
2111 }
2112 }
2113 } else
2114 *npt= '/';
2115 }
2116 Xorriso_process_msg_queues(xorriso,0);
2117 ret= 1 + (is_dir && !leaf_is_split);
2118 ex:;
2119 /* restore exact access permissions of stacked paths */
2120 hret= Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso,
2121 2 | !!(flag&64));
2122 if(hret<=0 && hret<ret)
2123 ret= hret;
2124 Xorriso_free_meM(path);
2125 return(ret);
2126 }
2127
2128
2129 int Xorriso_restore_node_array(struct XorrisO *xorriso, int flag)
2130 {
2131 int i, ret, fret, hflag, stbuf_ret, faulty_family= 0;
2132 struct PermiteM *perm_stack_mem;
2133 char *img_path= NULL, *disk_path= NULL;
2134 IsoNode *node;
2135 struct Xorriso_lsT *img_prefixes= NULL, *disk_prefixes= NULL;
2136
2137 perm_stack_mem= xorriso->perm_stack;
2138
2139 Xorriso_alloc_meM(img_path, char, SfileadrL);
2140 Xorriso_alloc_meM(disk_path, char, SfileadrL);
2141
2142 Xorriso_sort_node_array(xorriso, 0);
2143
2144 disk_path[0]= 0;
2145 for(i= 0; i < xorriso->node_counter; i++) {
2146 node= (IsoNode *) xorriso->node_array[i];
2147 ret= Xorriso_path_from_node(xorriso, node, img_path, 0);
2148 if(ret < 0)
2149 goto ex;
2150 if(ret == 0)
2151 continue; /* Node is deleted from tree (Should not happen here) */
2152 hflag= 1;
2153 if(i == 0) {
2154 hflag= 0;
2155 } else if(node != xorriso->node_array[i - 1]) {
2156 hflag= 0;
2157 }
2158 if(hflag == 0) {
2159 img_prefixes= xorriso->node_img_prefixes;
2160 disk_prefixes= xorriso->node_disk_prefixes;
2161 }
2162 ret= Xorriso_make_restore_path(xorriso, &img_prefixes, &disk_prefixes,
2163 img_path, disk_path, hflag);
2164 if(ret<=0)
2165 goto was_problem;
2166
2167 /* (Exclusion must already be handled when the node array gets filled,
2168 because of no distinction between parameter and tree passenger here.)
2169 */
2170
2171 ret= Xorriso_handle_collision(xorriso, node, img_path, disk_path, disk_path,
2172 &stbuf_ret, 64);
2173 if(ret<=0 || ret==3)
2174 goto was_problem;
2175 if(xorriso->hln_array != NULL && !(xorriso->ino_behavior & 16)) {
2176 /* Eventual lookup of hardlinks will be done in
2177 Xorriso_restore_disk_object() */;
2178 } else if(i > 0 && !(xorriso->ino_behavior & 4)) {
2179 if(Xorriso__findi_sorted_ino_cmp(&(xorriso->node_array[i-1]),
2180 &(xorriso->node_array[i])) == 0) {
2181 if(faulty_family) {
2182 sprintf(xorriso->info_text, "Hardlinking omitted with ");
2183 Text_shellsafe(disk_path, xorriso->info_text, 1);
2184 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
2185 } else {
2186 /* Try to install hardlink to a sibling */
2187 ret= Xorriso_restore_prefix_hl(xorriso, node, disk_path, i, 0);
2188 if(ret < 0) {
2189 goto was_problem;
2190 } else if(ret & 1) {
2191 /* Success, hardlink was created */
2192 xorriso->pacifier_count++;
2193 continue;
2194 }
2195 if(ret & 4) {
2196 /* Found elder siblings, but did not link. */
2197 ret= Xorriso_eval_problem_status(xorriso, 1, 1 | 2);
2198 if(ret < 0)
2199 {ret= 0; goto ex;}
2200 }
2201 }
2202 } else
2203 faulty_family= 0;
2204 }
2205
2206 ret= Xorriso_restore_disk_object(xorriso, img_path, node, disk_path,
2207 (off_t) 0, (off_t) 0,
2208 4 | (xorriso->ino_behavior & 16) | 128);
2209 if(ret<=0)
2210 goto was_problem;
2211 if(ret == 4) {
2212 /* Failed from lack of permission */
2213 ret= Xorriso_make_accessible(xorriso, disk_path, 0);
2214 if(ret < 0)
2215 goto ex;
2216 ret= Xorriso_restore_disk_object(xorriso, img_path, node, disk_path,
2217 (off_t) 0, (off_t) 0, 4 | (xorriso->ino_behavior & 16));
2218 if(ret<=0)
2219 goto was_problem;
2220 Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
2221 }
2222
2223 continue; /* regular bottom of loop */
2224 was_problem:;
2225 faulty_family= 1;
2226 fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
2227 if(fret<0)
2228 goto ex;
2229 Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
2230 }
2231 ret= 1;
2232 ex:;
2233 Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
2234 Xorriso_free_meM(img_path);
2235 Xorriso_free_meM(disk_path);
2236 return(ret);
2237 }
2238
2239
2240 /* @param flag bit0= -follow, -not: disk_path is not a command parameter
2241 */
2242 int Xorriso_paste_in(struct XorrisO *xorriso, char *disk_path,
2243 off_t startbyte, off_t bytecount, char *iso_rr_path, int flag)
2244 {
2245 int ret, no_props= 0;
2246 off_t wanted_size, cap;
2247 char *eff_source= NULL, *eff_dest= NULL, *reason;
2248 struct stat stbuf, disk_stbuf;
2249 IsoNode *node;
2250
2251 Xorriso_alloc_meM(eff_source, char, SfileadrL);
2252 Xorriso_alloc_meM(eff_dest, char, SfileadrL);
2253
2254 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_dest,
2255 2|4);
2256 if(ret<=0)
2257 goto ex;
2258 ret= Xorriso_path_is_excluded(xorriso, disk_path, 4 | 2 | !(flag & 1));
2259 if(ret > 0 && !(flag & 1)) {
2260 strcpy(xorriso->info_text,
2261 "Excluded from restoring by -not_path or -not_leaf :");
2262 Text_shellsafe(disk_path, xorriso->info_text, 1);
2263 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
2264 }
2265 if(ret!=0)
2266 {ret= 0; goto ex;}
2267
2268 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, iso_rr_path,
2269 eff_source, 2);
2270 if(ret<=0)
2271 goto ex;
2272 ret= Xorriso_fake_stbuf(xorriso, eff_source, &stbuf, &node, 4);
2273 if(ret<=0)
2274 {ret= 0; goto ex;}
2275 if(!S_ISREG(stbuf.st_mode)) {
2276 Xorriso_msgs_submit(xorriso, 0, eff_dest, 0, "ERRFILE", 0);
2277 sprintf(xorriso->info_text, "-paste_in: ISO file ");
2278 Text_shellsafe(eff_source, xorriso->info_text, 1);
2279 strcat(xorriso->info_text, " is not a data file");
2280 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
2281 {ret= 0; goto ex;}
2282 }
2283
2284 /* >>> ??? flag bit to obtain startbyte and bytecount from file name */;
2285
2286 ret= lstat(eff_dest, &disk_stbuf);
2287 if(ret != -1) {
2288 no_props= 1 << 10;
2289 wanted_size= startbyte + bytecount;
2290 if(wanted_size > stbuf.st_size)
2291 wanted_size= stbuf.st_size;
2292 cap= wanted_size;
2293 ret= Xorriso_determine_capacity(xorriso, eff_dest, &cap, &reason, 3);
2294 if(ret <= 0 || (cap <= 0 && !S_ISREG(disk_stbuf.st_mode))) {
2295 Xorriso_msgs_submit(xorriso, 0, eff_dest, 0, "ERRFILE", 0);
2296 if(ret > 0)
2297 reason= "has addressable range 0";
2298 sprintf(xorriso->info_text, "-paste_in: DISK file (%s) ",
2299 Ftypetxt(disk_stbuf.st_mode, 0));
2300 Text_shellsafe(eff_dest, xorriso->info_text, 1);
2301 sprintf(xorriso->info_text + strlen(xorriso->info_text),
2302 " exists but %s", reason);
2303 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2304 {ret= 0; goto ex;}
2305 }
2306 if(cap < wanted_size && !S_ISREG(disk_stbuf.st_mode)) {
2307
2308 /* >>> non-regular file might be too small to take the interval */;
2309
2310 }
2311 }
2312
2313 ret= Xorriso_restore(xorriso, eff_source, eff_dest, startbyte, bytecount,
2314 8 | no_props);
2315 ex:;
2316 Xorriso_free_meM(eff_source);
2317 Xorriso_free_meM(eff_dest);
2318 return(ret);
2319 }
2320
2321
2322 int Xorriso_extract_cut(struct XorrisO *xorriso,
2323 char *img_path, char *disk_path,
2324 off_t img_offset, off_t bytes, int flag)
2325 {
2326 int ret, stbuf_ret, read_raw;
2327 double mem_lut= 0.0;
2328 char *eff_img_path= NULL, *eff_disk_path= NULL;
2329 IsoImage *volume;
2330 IsoNode *node;
2331
2332 Xorriso_alloc_meM(eff_img_path, char, SfileadrL);
2333 Xorriso_alloc_meM(eff_disk_path, char, SfileadrL);
2334
2335 ret= Xorriso_get_volume(xorriso, &volume, 0);
2336 if(ret<=0)
2337 goto ex;
2338 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi,
2339 img_path, eff_img_path, 0);
2340 if(ret<=0)
2341 goto ex;
2342 ret= Xorriso_node_from_path(xorriso, volume, eff_img_path, &node, 0);
2343 if(ret<=0)
2344 goto ex;
2345 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx,
2346 disk_path, eff_disk_path, 2 | 4);
2347 if(ret<=0)
2348 goto ex;
2349 ret= Xorriso_path_is_excluded(xorriso, eff_disk_path, 1 | 2 | 4);
2350 if(ret < 0)
2351 goto ex;
2352 if(ret > 0) {
2353 strcpy(xorriso->info_text,
2354 "Excluded from restoring by -not_path or -not_leaf :");
2355 Text_shellsafe(eff_disk_path, xorriso->info_text, 1);
2356 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
2357 {ret= 0; goto ex;}
2358 }
2359
2360 /* If it is a non-filtered stream from the ISO image
2361 and img_offset is a multiple of 2048
2362 then use Xorriso_read_file_data() for random access offset.
2363 */
2364 if(!LIBISO_ISREG(node)) {
2365 Xorriso_msgs_submit(xorriso, 0, eff_disk_path, 0, "ERRFILE", 0);
2366 sprintf(xorriso->info_text, "-extract_cut: ISO file ");
2367 Text_shellsafe(eff_img_path, xorriso->info_text, 1);
2368 strcat(xorriso->info_text, " is not a data file");
2369 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2370 {ret= 0; goto ex;}
2371 }
2372 ret= Xorriso_handle_collision(xorriso, node, img_path, eff_disk_path,
2373 disk_path, &stbuf_ret, 0);
2374 if(ret<=0 || ret==3)
2375 {ret= 0; goto ex;}
2376
2377 Xorriso_pacifier_reset(xorriso, 0);
2378 mem_lut= xorriso->last_update_time;
2379 read_raw= 0;
2380 if((img_offset % 2048) == 0) {
2381 ret= Xorriso_is_plain_image_file(xorriso, node, "", 0);
2382 if(ret > 0)
2383 read_raw= 1;
2384 }
2385 if (read_raw) {
2386 ret= Xorriso_read_file_data(xorriso, node, eff_img_path, eff_disk_path,
2387 img_offset, (off_t) 0, bytes, 0);
2388 if(ret<=0)
2389 goto ex;
2390 } else {
2391 ret= Xorriso_tree_restore_node(xorriso, node, eff_img_path, img_offset,
2392 eff_disk_path, (off_t) 0, bytes, 2 | 8);
2393 if(ret<=0)
2394 goto ex;
2395 }
2396
2397 ret= Xorriso_restore_properties(xorriso, eff_disk_path, node, 0);
2398 if(ret<=0)
2399 goto ex;
2400
2401 if(mem_lut != xorriso->last_update_time)
2402 Xorriso_pacifier_callback(xorriso, "blocks read",
2403 xorriso->pacifier_count, 0, "", 1 | 8 | 16 | 32);
2404 ret= 1;
2405 ex:;
2406 Xorriso_free_meM(eff_img_path);
2407 Xorriso_free_meM(eff_disk_path);
2408 return(ret);
2409 }
2410
2411
2412 /* @param flag bit0= ignore node and img_path, operate on whole medium
2413 bit1= for Xorriso_check_interval(): no pacifier messages
2414 */
2415 int Xorriso_read_file_data(struct XorrisO *xorriso, IsoNode *node,
2416 char *img_path, char *disk_path,
2417 off_t img_offset, off_t disk_offset,
2418 off_t bytes, int flag)
2419 {
2420 int ret, i, lba_count= 0, *start_lbas= NULL, *end_lbas= NULL, read_chunk= 16;
2421 int lba, count, blocks, quality, spot, bad_extract= 0;
2422 int data_to_skip= 0;
2423 uint32_t indev_blocks;
2424 off_t size= 0, file_base_bytes= 0, file_processed_bytes= 0, img_adr;
2425 off_t new_file_base_bytes, upto_file_bytes, start_byte= 0;
2426 off_t *section_sizes = NULL;
2427 struct SpotlisT *spotlist= NULL;
2428 struct CheckmediajoB *job= NULL;
2429
2430 upto_file_bytes= img_offset + bytes;
2431 data_to_skip= img_offset % (off_t) 2048;
2432
2433 if(flag & 1) {
2434 lba_count= 1;
2435 Xorriso_alloc_meM(start_lbas, int, 1);
2436 Xorriso_alloc_meM(end_lbas, int, 1);
2437 Xorriso_alloc_meM(section_sizes, off_t, 1);
2438 start_lbas[0]= 0;
2439 ret= Xorriso_obtain_indev_readsize(xorriso, &indev_blocks, 0);
2440 if(ret > 0)
2441 end_lbas[0]= indev_blocks - 1;
2442 else
2443 end_lbas[0]= 0x7ffffffe;
2444 size= ((off_t) end_lbas[0]) * 2048;
2445 section_sizes[0]= size;
2446 } else {
2447 ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas,
2448 §ion_sizes, &size, 0);
2449 if(ret <= 0) {
2450 Xorriso_process_msg_queues(xorriso,0);
2451 sprintf(xorriso->info_text, "File object ");
2452 Text_shellsafe(img_path, xorriso->info_text, 1);
2453 strcat(xorriso->info_text,
2454 " is currently not a data file from the loaded image");
2455 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2456 goto ex;
2457 }
2458 }
2459 if(img_offset + bytes < size && bytes > 0)
2460 size= img_offset + bytes;
2461
2462 ret= Checkmediajob_new(&job, 0);
2463 if(ret <= 0)
2464 goto ex;
2465 if(xorriso->check_media_default != NULL)
2466 Checkmediajob_copy(xorriso->check_media_default, job, 0);
2467 job->min_lba= -1;
2468 job->max_lba= -1;
2469 job->sector_map_path[0]= 0;
2470
2471 ret= Spotlist_new(&spotlist, 0);
2472 if(ret <= 0)
2473 {ret= -1; goto ex;}
2474
2475 if(Sfile_str(job->data_to_path, disk_path, 0) <= 0)
2476 {ret= -1; goto ex;}
2477 ret= Xorriso_open_job_data_to(xorriso, job, 0);
2478 if(ret <= 0)
2479 goto ex;
2480
2481 for(i= 0; i < lba_count && file_base_bytes < upto_file_bytes; i++) {
2482 lba= start_lbas[i];
2483 count= end_lbas[i] + 1 - start_lbas[i];
2484 new_file_base_bytes= file_base_bytes + ((off_t) count) * (off_t) 2048;
2485
2486 /* skip intervals before img_offset */
2487 if(new_file_base_bytes <= img_offset) {
2488 file_base_bytes= new_file_base_bytes;
2489 continue;
2490 }
2491 /* Eventually adjust first interval start */
2492 img_adr= ((off_t) lba) * (off_t) 2048;
2493 if(file_base_bytes < img_offset) {
2494 img_adr+= img_offset - file_base_bytes;
2495 lba= img_adr / (off_t) 2048;
2496 count= end_lbas[i] + 1 - lba;
2497 file_base_bytes= img_offset;
2498 }
2499
2500 /* Omit surplus blocks */
2501 if(new_file_base_bytes > upto_file_bytes)
2502 count-= (new_file_base_bytes - upto_file_bytes) / (off_t) 2048;
2503 /* Adjust job */
2504 job->data_to_offset= file_processed_bytes - img_adr + disk_offset;
2505 job->data_to_limit= size - file_base_bytes;
2506 job->data_to_skip= data_to_skip;
2507 data_to_skip= 0;
2508 file_processed_bytes+= ((off_t) count) * (off_t) 2048;
2509 ret= Xorriso_check_interval(xorriso, spotlist, job, lba, count, read_chunk,
2510 0, (flag & 2));
2511 if(ret <= 0)
2512 goto ex;
2513 if (ret == 2) {
2514 sprintf(xorriso->info_text, "Attempt aborted to extract data from ");
2515 Text_shellsafe(img_path, xorriso->info_text, 1);
2516 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2517 ret= 0; goto ex;
2518 }
2519 file_base_bytes= new_file_base_bytes;
2520 }
2521
2522 /* Use spotlist to evaluate damage */
2523 file_base_bytes= 0;
2524 count= Spotlist_count(spotlist, 0);
2525 for(spot= 0; spot < count; spot++) {
2526 ret= Spotlist_get_item(spotlist, spot, &lba, &blocks, &quality, 0);
2527 if(ret <= 0)
2528 continue;
2529 if(quality < Xorriso_read_quality_valiD) {
2530 for(i= 0; i < lba_count; i++) {
2531 if(start_lbas[i] <= lba && end_lbas[i] >= lba) {
2532 start_byte= (lba - start_lbas[i]) * (off_t) 2048 + file_base_bytes;
2533 break;
2534 }
2535 file_base_bytes+= ((off_t) (end_lbas[i] + 1 - start_lbas[i]))
2536 * (off_t) 2048;
2537 }
2538 if(i < lba_count) {
2539 sprintf(xorriso->info_text, "Bad extract : %14.f , %14.f , ",
2540 (double) start_byte, ((double) blocks) * 2048.0);
2541 Text_shellsafe(disk_path, xorriso->info_text, 1);
2542 strcat(xorriso->info_text, "\n");
2543 Xorriso_info(xorriso, 0);
2544 bad_extract= 1;
2545 }
2546 }
2547 }
2548
2549 ret= !bad_extract;
2550 ex:;
2551 if(start_lbas != NULL)
2552 free((char *) start_lbas);
2553 if(end_lbas != NULL)
2554 free((char *) end_lbas);
2555 if(section_sizes != NULL)
2556 free((char *) section_sizes);
2557 Spotlist_destroy(&spotlist, 0);
2558 Checkmediajob_destroy(&job, 0);
2559 return(ret);
2560 }
2561
2562
2563 int Xorriso_extract_boot_images(struct XorrisO *xorriso, char *disk_dir_path,
2564 int flag)
2565 {
2566 int ret, img_count= 0, i, was_problem= 0;
2567 char **imgs= NULL, *eff_path= NULL, *cpt, *eff_namept;
2568 struct stat stbuf;
2569 off_t byte_offset, byte_size;
2570
2571 Xorriso_alloc_meM(eff_path, char, SfileadrL);
2572 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_dir_path,
2573 eff_path, 2 | 4);
2574 if(ret <= 0)
2575 goto ex;
2576 if(strlen(eff_path) > SfileadrL - 80) {
2577 sprintf(xorriso->info_text,
2578 "-extract_boot_images: disk_path is too long (%lu)\n",
2579 (unsigned long int) strlen(eff_path));
2580 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2581 ret= 0; goto ex;
2582 }
2583 ret= stat(eff_path, &stbuf);
2584 if(ret == 0) {
2585 if(!S_ISDIR(stbuf.st_mode)) {
2586 sprintf(xorriso->info_text,
2587 "-extract_boot_images: disk_path is not a directory : ");
2588 Text_shellsafe(eff_path, xorriso->info_text, 1);
2589 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2590 ret= 0; goto ex;
2591 }
2592 } else {
2593 ret= mkdir(eff_path, 0777);
2594 if(ret == -1) {
2595 sprintf(xorriso->info_text,
2596 "-extract_boot_images: cannot create directory : ");
2597 Text_shellsafe(eff_path, xorriso->info_text, 1);
2598 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
2599 ret= 0; goto ex;
2600 }
2601 }
2602 strcat(eff_path, "/");
2603 eff_namept= eff_path + strlen(eff_path);
2604
2605 ret= Xorriso_list_boot_images(xorriso, &imgs, &img_count, 0);
2606 if(ret <= 0)
2607 goto ex;
2608
2609 /* Interpret list and create files */
2610 for(i= 0; i < img_count; i++) {
2611 ret= Xorriso_eval_problem_status(xorriso, 1, 1 | 2);
2612 if(ret < 0)
2613 {ret= 0; goto ex;}
2614 cpt= strchr(imgs[i], '/');
2615 if(cpt == NULL)
2616 continue;
2617 *cpt= 0;
2618 cpt+= 2;
2619 ret= Sfile_text_to_off_t(cpt, &byte_offset, 0);
2620 if(ret <= 0)
2621 continue;
2622 cpt+= ret;
2623 if(*cpt == 0)
2624 continue;
2625 cpt++;
2626 ret= Sfile_text_to_off_t(cpt, &byte_size, 0);
2627 if(ret <= 0)
2628 continue;
2629
2630 strcpy(eff_namept, imgs[i]);
2631 sprintf(xorriso->info_text, "%s : offset=%.f size=%.f\n",
2632 eff_path, (double) byte_offset, (double) byte_size);
2633 Xorriso_info(xorriso, 0);
2634
2635 ret= stat(eff_path, &stbuf);
2636 if(ret != -1) {
2637 sprintf(xorriso->info_text,
2638 "-extract_boot_images: File already exists on disk: ");
2639 Text_shellsafe(eff_path, xorriso->info_text, 1);
2640 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
2641 continue;
2642 }
2643 ret= Xorriso_read_file_data(xorriso, NULL, NULL, eff_path,
2644 byte_offset, (off_t) 0, byte_size, 1);
2645 if(ret <= 0)
2646 was_problem= 1;
2647 }
2648 ret= Xorriso_eval_problem_status(xorriso, 1, 1 | 2);
2649 if(ret < 0 || was_problem)
2650 {ret= 0; goto ex;}
2651
2652 ret= 1;
2653 ex:;
2654 Xorriso_free_meM(eff_path);
2655 Xorriso_list_boot_images(xorriso, &imgs, &img_count, 1 << 15);
2656 return(ret);
2657 }
2658
2659
2660 /* @param node Opaque handle to IsoNode which is to be inquired instead of path if it is not NULL.
2661 @param path is used as address if node is NULL.
2662 @param flag bit0= do not report to result but only indicate outcome
2663 by return value
2664 bit1= silently ignore nodes without MD5
2665 bit2= do not only report mismatches but also matches
2666 @return 3= not a data file
2667 2= no MD5 attached to node
2668 1= ok, MD5 compared and matching
2669 0= not ok, MD5 mismatch
2670 <0= other error
2671 */
2672 int Xorriso_check_md5(struct XorrisO *xorriso, void *in_node, char *path,
2673 int flag)
2674 {
2675 int ret, wanted, rret, buffer_size= 64 * 1024;
2676 IsoImage *image;
2677 IsoNode *node;
2678 IsoFile *file;
2679 char node_md5[16], data_md5[16], *buffer= NULL;
2680 void *stream= NULL, *ctx= NULL;
2681 off_t todo;
2682
2683 Xorriso_alloc_meM(buffer, char, 64 * 1024);
2684
2685 node= (IsoNode *) in_node;
2686 if(node == NULL) {
2687 ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
2688 if(ret<=0)
2689 {ret= -1; goto ex;}
2690 }
2691 if(!LIBISO_ISREG(node)) {
2692 strcpy(xorriso->info_text, "-check_md5: Not a data file: ");
2693 Text_shellsafe(path, xorriso->info_text, 1);
2694 if(!(flag & 2))
2695 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
2696 ret= 3; goto ex;
2697 }
2698 file= (IsoFile *) node;
2699
2700 /* obtain MD5 */
2701 ret= Xorriso_get_volume(xorriso, &image, 0);
2702 if(ret <= 0)
2703 {ret= -1; goto ex;}
2704 ret= iso_file_get_md5(image, file, node_md5, 0);
2705 Xorriso_process_msg_queues(xorriso,0);
2706 if(ret < 0)
2707 {ret= -1; goto ex;}
2708 if(ret == 0) {
2709 strcpy(xorriso->info_text, "-check_md5: No MD5 recorded with file: ");
2710 Text_shellsafe(path, xorriso->info_text, 1);
2711 if(!(flag & 2))
2712 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
2713 ret= 2; goto ex;
2714 }
2715
2716 /* Read file and compute MD5 */;
2717 ret= Xorriso_iso_file_open(xorriso, path, (void *) node, &stream, 1 | 2);
2718 if(ret <= 0)
2719 {ret= -1; goto ex;}
2720 ret= iso_md5_start(&ctx);
2721 if(ret < 0)
2722 goto ex;
2723 todo= iso_stream_get_size(stream);
2724 while(todo > 0) {
2725 if(todo < buffer_size)
2726 wanted= todo;
2727 else
2728 wanted= buffer_size;
2729 rret = Xorriso_iso_file_read(xorriso, stream, buffer, wanted, 0);
2730 if(rret <= 0)
2731 {ret= -1; goto ex;}
2732 todo-= rret;
2733 ret = iso_md5_compute(ctx, buffer, rret);
2734 if(ret < 0)
2735 goto ex;
2736 xorriso->pacifier_count+= rret;
2737 xorriso->pacifier_byte_count+= rret;
2738 Xorriso_pacifier_callback(xorriso, "content bytes read",
2739 xorriso->pacifier_count, 0, "", 8);
2740 ret= Xorriso_check_for_abort(
2741 xorriso,
2742 xorriso->check_media_default != NULL
2743 ? xorriso->check_media_default->abort_file_path
2744 : "/var/opt/xorriso/do_abort_check_media",
2745 Sfile_microtime(0), &xorriso->last_abort_file_time, 0);
2746 if(ret == 1)
2747 {ret= -2; goto ex;}
2748 }
2749 ret= iso_md5_end(&ctx, data_md5);
2750 if(ret < 0)
2751 goto ex;
2752
2753 /* Report outcome */
2754 Xorriso_process_msg_queues(xorriso,0);
2755 if(! iso_md5_match(node_md5, data_md5)) {
2756 sprintf(xorriso->result_line, "MD5 MISMATCH: ");
2757 Text_shellsafe(path, xorriso->result_line, 1);
2758 strcat(xorriso->result_line, "\n");
2759 if(!(flag & 1))
2760 Xorriso_result(xorriso,0);
2761 ret= 0;
2762 } else {
2763 sprintf(xorriso->result_line, "md5 match : ");
2764 Text_shellsafe(path, xorriso->result_line, 1);
2765 strcat(xorriso->result_line, "\n");
2766 if(flag & 4)
2767 Xorriso_result(xorriso,0);
2768 ret= 1;
2769 }
2770
2771 ex:;
2772 Xorriso_process_msg_queues(xorriso,0);
2773 Xorriso_iso_file_close(xorriso, &stream, 0);
2774 if(ctx != NULL)
2775 iso_md5_end(&ctx, data_md5);
2776 Xorriso_free_meM(buffer);
2777 if(ret < 0) {
2778 if(ret == -2)
2779 sprintf(xorriso->result_line, "Aborted at: ");
2780 else
2781 sprintf(xorriso->result_line, "NOT READABLE: ");
2782 Text_shellsafe(path, xorriso->result_line, 1);
2783 strcat(xorriso->result_line, "\n");
2784 if(!(flag & 1))
2785 Xorriso_result(xorriso,0);
2786 if(ret == -2)
2787 xorriso->request_to_abort= 1;
2788 }
2789 return(ret);
2790 }
2791