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