1
2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
3
4 Copyright 2007-2017 Thomas Schmitt, <scdbackup@gmx.net>
5
6 Provided under GPL version 2 or later.
7
8 This file contains functions which operate on drives and media.
9 */
10
11 #ifdef HAVE_CONFIG_H
12 #include "../config.h"
13 #endif
14
15 #include <ctype.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/stat.h>
22 #include <sys/time.h>
23 #include <time.h>
24 #include <errno.h>
25 #include <pthread.h>
26
27
28 #include "xorriso.h"
29 #include "xorriso_private.h"
30
31 #include "lib_mgt.h"
32 #include "drive_mgt.h"
33 #include "iso_img.h"
34 #include "sort_cmp.h"
35 #include "write_run.h"
36 #include "read_run.h"
37
38
un0(const char * text)39 static const char *un0(const char *text)
40 {
41 if(text == NULL)
42 return("");
43 return(text);
44 }
45
46
47
48
Xorriso_auto_driveadr(struct XorrisO * xorriso,char * adr,char * result,int flag)49 int Xorriso_auto_driveadr(struct XorrisO *xorriso, char *adr, char *result,
50 int flag)
51 {
52 int ret, is_known_mmc= 0, does_exist= 0;
53 char *path_pt, *libburn_adr= NULL;
54 char *abs_pt, *abs_adr= NULL;
55 struct stat stbuf;
56
57 Xorriso_alloc_meM(libburn_adr, char, BURN_DRIVE_ADR_LEN + SfileadrL);
58 Xorriso_alloc_meM(abs_adr, char, SfileadrL);
59 path_pt= adr;
60 if(strncmp(adr, "stdio:", 6) == 0)
61 path_pt= adr + 6;
62 else if(strncmp(adr, "mmc:", 4) == 0)
63 path_pt= adr + 4;
64
65
66 /* <<< replace by Xorriso_normalize_img_path() ? */;
67
68 if(path_pt[0] != '/') {
69 abs_pt= getcwd(abs_adr, SfileadrL - 1);
70 if(abs_pt == NULL) {
71 Xorriso_msgs_submit(xorriso, 0,
72 "Relative drive path given. Cannot determine working directory.",
73 errno, "FAILURE", 0);
74 {ret= -1; goto ex;}
75 }
76 ret= Sfile_add_to_path(abs_adr, path_pt, 0);
77 if(ret <= 0)
78 {ret= -1; goto ex;}
79 }
80
81 is_known_mmc= burn_drive_convert_fs_adr(path_pt, libburn_adr);
82 does_exist= (stat(path_pt, &stbuf) != -1);
83 Xorriso_process_msg_queues(xorriso,0);
84
85 ret= Xorriso_is_in_patternlist(xorriso, xorriso->drive_whitelist, path_pt, 0);
86 if(ret > 0)
87 goto ok;
88 ret= Xorriso_is_in_patternlist(xorriso, xorriso->drive_blacklist, path_pt, 0);
89 if(ret < 0)
90 goto ex;
91 if(ret) {
92 strcpy(xorriso->info_text, "Drive address ");
93 Text_shellsafe(adr, xorriso->info_text, 1);
94 strcat(xorriso->info_text,
95 " rejected because: -drive_class 'banned' ");
96 Text_shellsafe(Xorriso_get_pattern(xorriso, xorriso->drive_blacklist,
97 ret - 1, 0),
98 xorriso->info_text, 1);
99 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
100 {ret= 0; goto ex;}
101 }
102 /* if in greylist and not MMC and not stdio prefix: reject */
103 if(is_known_mmc < 0)
104 goto ex;
105 if(adr == path_pt && !is_known_mmc) { /* no prefix, no MMC */
106 ret= Xorriso_is_in_patternlist(xorriso, xorriso->drive_greylist, path_pt,0);
107 if(ret < 0)
108 goto ex;
109 if(ret) {
110 strcpy(xorriso->info_text, "Drive address ");
111 Text_shellsafe(adr, xorriso->info_text, 1);
112 strcat(xorriso->info_text, " rejected because: ");
113 if(does_exist)
114 strcat(xorriso->info_text, "not MMC");
115 else
116 strcat(xorriso->info_text, "not existing");
117 strcat(xorriso->info_text, " and -drive_class 'caution' ");
118 Text_shellsafe(Xorriso_get_pattern(xorriso,xorriso->drive_greylist,
119 ret - 1, 0),
120 xorriso->info_text, 1);
121 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
122 sprintf(xorriso->info_text,
123 "If the address is a legitimate %s, prepend \"stdio:\"",
124 does_exist ? "target" : "address for a new regular file");
125 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
126 {ret= 0; goto ex;}
127 }
128 }
129 ok:;
130 if(strncmp(adr, "mmc:", 4) == 0) {
131 if(Sfile_str(result, path_pt, 0) <= 0)
132 {ret= 0; goto ex;}
133 } else if(adr == path_pt && is_known_mmc <= 0) {
134 Sfile_str(result, "stdio:", 0);
135 if(Sfile_str(result, adr, 1) <= 0)
136 {ret= 0; goto ex;}
137 } else {
138 if(Sfile_str(result, adr, 0) <= 0)
139 {ret= 0; goto ex;}
140 }
141 if(strncmp(result, "stdio:", 6)==0) {
142 if(xorriso->ban_stdio_write) {
143 strcpy(xorriso->info_text, "Drive address banned by -ban_stdio_write : ");
144 Text_shellsafe(result, xorriso->info_text, 1);
145 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
146 {ret= 0; goto ex;}
147 }
148 }
149 ret= 1;
150 ex:;
151 Xorriso_free_meM(libburn_adr);
152 Xorriso_free_meM(abs_adr);
153 return(ret);
154 }
155
156
Xorriso_grasp_loaded_aaip(struct XorrisO * xorriso,IsoImage * volset,int flag)157 static int Xorriso_grasp_loaded_aaip(struct XorrisO *xorriso, IsoImage *volset,
158 int flag)
159 {
160 int ret, change_pending_rec;
161 IsoNode *root_node;
162 size_t value_length;
163 char *value= NULL;
164 double num;
165 struct FindjoB *job= NULL;
166 struct stat dir_stbuf;
167
168 /* To be re-instated at function end */
169 change_pending_rec= xorriso->volset_change_pending;
170
171 /* Look for isofs.st and put it into xorriso->isofs_st_in */
172 root_node= (IsoNode *) iso_image_get_root(volset);
173 ret= iso_node_lookup_attr(root_node, "isofs.st", &value_length, &value, 0);
174 if(ret > 0) {
175 if(value_length > 0) {
176 sscanf(value, "%lf", &num);
177 if(num > 0)
178 xorriso->isofs_st_in= num;
179 }
180 free(value);
181 }
182
183 if(xorriso->do_hfsplus) {
184 /* Bring isofs.hx to iso_hfsplus_xinfo_func,
185 isofs.hb to IsoImage blessings
186 */
187 ret= Findjob_new(&job, "/", 0);
188 if(ret<=0) {
189 Xorriso_no_findjob(xorriso, "xorriso", 0);
190 {ret= -1; goto ex;}
191 }
192 Findjob_set_action_target(job, 49, NULL, 0);
193 ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
194 &dir_stbuf, 0, 0);
195 if(ret <= 0)
196 goto ex;
197 }
198
199 ret= 1;
200 ex:;
201 xorriso->volset_change_pending= change_pending_rec;
202 Findjob_destroy(&job, 0);
203 return(ret);
204 }
205
206
207 /* @param flag bit0= aquire as isoburn input drive
208 bit1= aquire as libburn output drive (as isoburn drive if bit0)
209 bit2= regard overwriteable media as blank
210 bit3= if the drive is a regular disk file: truncate it to
211 the write start address
212 bit5= do not print toc
213 bit6= do not calm down drive after aquiring it
214 bit7= re-assess rather than aquire:
215 Do not give up drives,
216 use isoburn_drive_aquire() with re-assessment bit
217 @return <=0 failure , 1= ok
218 2=success, but not writeable with bit1
219 3=success, but not blank and not ISO with bit0
220 */
Xorriso_aquire_drive(struct XorrisO * xorriso,char * adr,char * show_adr,int flag)221 int Xorriso_aquire_drive(struct XorrisO *xorriso, char *adr, char *show_adr,
222 int flag)
223 {
224 int ret, hret, not_writeable= 0, has_what, aquire_flag, load_lba, ext;
225 int lba, track, session, params_flag, adr_mode, read_ret, start_lba;
226 int truncate_mode;
227 uint32_t size, offst;
228 struct burn_drive_info *dinfo= NULL, *out_dinfo= NULL, *in_dinfo= NULL;
229 struct burn_drive *drive= NULL, *out_drive= NULL, *in_drive= NULL;
230 enum burn_disc_status state;
231 IsoImage *volset = NULL;
232 struct isoburn_read_opts *ropts= NULL;
233 char *libburn_adr= NULL, *off_adr= NULL, *boot_fate, *sev;
234 char volid[33], *adr_data= NULL, *adr_pt;
235
236 Xorriso_alloc_meM(libburn_adr, char, SfileadrL);
237 Xorriso_alloc_meM(off_adr, char, SfileadrL);
238 Xorriso_alloc_meM(adr_data, char, 163);
239
240 if(show_adr == NULL) {
241 show_adr= adr;
242 ret= burn_drive_convert_fs_adr(adr, off_adr);
243 if(ret > 0)
244 adr= off_adr;
245 }
246
247 if((flag&3)==0) {
248 sprintf(xorriso->info_text,
249 "XORRISOBURN program error : Xorriso_aquire_drive bit0+bit1 not set");
250 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
251 {ret= -1; goto ex;}
252 }
253 if(!(flag & 128)) {
254 ret= Xorriso_give_up_drive(xorriso, (flag&3)|8);
255 if(ret<=0)
256 goto ex;
257 }
258 if(flag & 1)
259 xorriso->isofs_st_out= time(0) - 1;
260
261 ret= Xorriso_auto_driveadr(xorriso, adr, libburn_adr, 0);
262 if(ret <= 0)
263 goto ex;
264 if(strcmp(libburn_adr,"stdio:/dev/fd/1")==0) {
265 if(xorriso->dev_fd_1<0) {
266 sprintf(xorriso->info_text,
267 "-*dev \"stdio:/dev/fd/1\" was not a start argument. Cannot use it now.");
268 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
269 {ret= 0; goto ex;}
270 } else {
271 sprintf(libburn_adr, "stdio:/dev/fd/%d", xorriso->dev_fd_1);
272 }
273 }
274
275 if(flag & 128) {
276 if(flag & 1)
277 Xorriso_get_drive_handles(xorriso, &in_dinfo, &in_drive, "", 16);
278 if(flag & 2)
279 Xorriso_get_drive_handles(xorriso, &out_dinfo, &out_drive, "", 2 | 16);
280 if(in_dinfo != NULL && (out_dinfo == NULL || out_dinfo == in_dinfo)) {
281 dinfo= in_dinfo;
282 if(flag & 2)
283 xorriso->outdev_is_exclusive= xorriso->indev_is_exclusive;
284 } else if(out_dinfo != NULL && in_dinfo == NULL) {
285 dinfo= out_dinfo;
286 if(flag & 1)
287 xorriso->indev_is_exclusive= xorriso->outdev_is_exclusive;
288 } else if(out_dinfo != NULL || in_dinfo != NULL) {
289 sprintf(xorriso->info_text,
290 "Two different drives shall be re-assed in one call");
291 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
292 {ret= 0; goto ex;}
293 } else {
294 sprintf(xorriso->info_text, "No drive acquired on re-assessment");
295 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
296 {ret= 0; goto ex;}
297 }
298 } else if((flag&3)==1 && xorriso->out_drive_handle!=NULL) {
299 ret= Xorriso_get_drive_handles(xorriso, &out_dinfo, &out_drive,
300 "on attempt to compare new indev with outdev", 2);
301 if(ret<=0)
302 goto ex;
303 ret= burn_drive_equals_adr(out_drive, libburn_adr, 1);
304 if(ret==1) {
305 dinfo= out_dinfo;
306 xorriso->indev_is_exclusive= xorriso->outdev_is_exclusive;
307 }
308 } else if((flag&3)==2 && xorriso->in_drive_handle!=NULL) {
309 ret= Xorriso_get_drive_handles(xorriso, &in_dinfo, &in_drive,
310 "on attempt to compare new outdev with indev", 0);
311 if(ret<=0)
312 goto ex;
313 ret= burn_drive_equals_adr(in_drive, libburn_adr, 1);
314 if(ret==1) {
315 dinfo= in_dinfo;
316 xorriso->outdev_is_exclusive= xorriso->indev_is_exclusive;
317 }
318 }
319
320 if(dinfo == NULL || (flag & 128)) {
321 aquire_flag= 1 | ((flag&(8|4))>>1) | ((xorriso->toc_emulation_flag & 3)<<3);
322 if(xorriso->toc_emulation_flag & 4)
323 aquire_flag|= 128;
324 if(xorriso->toc_emulation_flag & 8)
325 aquire_flag|= 512;
326 if(!(xorriso->do_aaip & 1))
327 aquire_flag|= 32;
328 if((xorriso->ino_behavior & (1 | 2)) && !(xorriso->do_aaip & (4 | 32))) {
329 aquire_flag|= 64;
330 } else if(xorriso->do_aaip & 1024) {
331 aquire_flag|= 1024;
332 }
333 if(flag & 128)
334 aquire_flag|= 256;
335 burn_preset_device_open(xorriso->drives_exclusive |
336 (xorriso->linux_scsi_dev_family << 2), 0, 0);
337 burn_allow_drive_role_4(1 | (xorriso->early_stdio_test & 14));
338 ret= isoburn_drive_aquire(&dinfo, libburn_adr, aquire_flag);
339 burn_preset_device_open(1 | (xorriso->linux_scsi_dev_family << 2), 0, 0);
340 Xorriso_process_msg_queues(xorriso,0);
341 if(ret<=0) {
342 if(flag & 128)
343 sprintf(xorriso->info_text,"Cannot re-assess drive '%s'", adr);
344 else
345 sprintf(xorriso->info_text,"Cannot acquire drive '%s'", adr);
346 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
347 ret= 0; goto ex;
348 }
349 xorriso->use_immed_bit_default= burn_drive_get_immed(dinfo[0].drive) > 0 ?
350 1 : -1;
351 if(xorriso->use_immed_bit != 0)
352 burn_drive_set_immed(dinfo[0].drive, xorriso->use_immed_bit > 0);
353 state= isoburn_disc_get_status(dinfo[0].drive);
354 ret= isoburn_get_img_partition_offset(dinfo[0].drive, &offst);
355 if((state == BURN_DISC_APPENDABLE || state == BURN_DISC_FULL) && ret == 1) {
356 sprintf(xorriso->info_text,
357 "ISO image bears MBR with -boot_image any partition_offset=%lu",
358 (unsigned long) offst);
359 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
360 }
361
362 if(flag&1)
363 if(xorriso->image_start_mode&(1<<31)) /* used up setting */
364 xorriso->image_start_mode= 0; /* no need to perform auto setting */
365 if(flag & 1)
366 xorriso->indev_is_exclusive= xorriso->drives_exclusive;
367 if(flag & 2)
368 xorriso->outdev_is_exclusive= xorriso->drives_exclusive;
369 }
370 drive= dinfo[0].drive;
371 volset= isoburn_get_attached_image(drive);
372 if(volset != NULL) {
373 ret= iso_image_set_truncate_mode(volset, 1, xorriso->file_name_limit);
374 iso_image_unref(volset);
375 volset= NULL;
376 Xorriso_process_msg_queues(xorriso,0);
377 if(ret < 0)
378 {ret= 0; goto ex;}
379 }
380 state= isoburn_disc_get_status(drive);
381 Xorriso_process_msg_queues(xorriso,0);
382 if(flag&1) {
383 if(xorriso->image_start_mode&(1<<31)) /* used up setting */
384 xorriso->image_start_mode&= ~0xffff; /* perform auto setting */
385 if((xorriso->image_start_mode&(1<<30))) { /* if enabled at all */
386 adr_pt= xorriso->image_start_value;
387 adr_mode= xorriso->image_start_mode & 0xffff;
388 if(adr_mode == 4 && strlen(adr_pt) <= 80) {
389 /* Convert volid search expression into lba */
390 params_flag= 0;
391 ret= Xorriso__bourne_to_reg(xorriso->image_start_value, adr_data, 0);
392 if(ret == 1)
393 params_flag|= 4;
394 ret= isoburn_get_mount_params(drive, 4, adr_data, &lba, &track,
395 &session, volid, params_flag);
396 Xorriso_process_msg_queues(xorriso,0);
397 if(ret <= 0)
398 goto ex;
399 if(session <= 0 || track <= 0 || ret == 2) {
400 Xorriso_msgs_submit(xorriso, 0,
401 "-load : Given address does not point to an ISO 9660 session",
402 0, "FAILURE", 0);
403 ret= 0; goto ex;
404 }
405 sprintf(volid, "%d", lba);
406 adr_pt= volid;
407 adr_mode= 3;
408 }
409 ret= isoburn_set_msc1(drive, adr_mode, adr_pt,
410 !!(xorriso->image_start_mode & (1<<16)));
411 if(ret<=0)
412 goto ex;
413 if(xorriso->image_start_mode&(1<<31))
414 xorriso->image_start_mode= 0; /* disable msc1 setting completely */
415 else
416 xorriso->image_start_mode|= (1<<31); /* mark as used up */
417 }
418 }
419 if(flag&1) {
420 volset= isoburn_get_attached_image(drive);
421 if(volset != NULL) { /* The image object is already created */
422 iso_image_unref(volset);
423 volset= NULL;
424 }
425 }
426
427 if(flag&2) {
428 xorriso->out_drive_handle= dinfo;
429 if(Sfile_str(xorriso->outdev, show_adr, 0)<=0)
430 {ret= -1; goto ex;}
431 ret= burn_drive_convert_fs_adr(adr, xorriso->outdev_off_adr);
432 if(ret <= 0)
433 xorriso->outdev_off_adr[0]= 0;
434 if(state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE) {
435 sprintf(xorriso->info_text, "Disc status unsuitable for writing");
436 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
437 not_writeable= 1;
438 }
439 }
440 if(flag&1) {
441 xorriso->in_drive_handle= dinfo;
442 if(Sfile_str(xorriso->indev, show_adr, 0)<=0)
443 {ret= -1; goto ex;}
444 ret= burn_drive_convert_fs_adr(adr, xorriso->indev_off_adr);
445 if(ret <= 0)
446 xorriso->indev_off_adr[0]= 0;
447 } else if(flag&2) {
448 if(xorriso->in_volset_handle==NULL) {
449 /* No volume loaded: create empty one */
450 ret= Xorriso_create_empty_iso(xorriso, 0);
451 if(ret<=0)
452 goto ex;
453 } else {
454 iso_image_ref((IsoImage *) xorriso->in_volset_handle);
455 start_lba= -1;
456 ret= Xorriso_get_drive_handles(xorriso, &in_dinfo, &in_drive,
457 "on attempt to attach ISO image object to outdev", 16);
458 if(ret > 0)
459 start_lba= isoburn_get_attached_start_lba(in_drive);
460 ret= isoburn_attach_image(drive, (IsoImage *) xorriso->in_volset_handle);
461 if(ret<=0) {
462 sprintf(xorriso->info_text,
463 "Failed to attach ISO image object to outdev");
464 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
465 {ret= -1; goto ex;}
466 }
467 if(start_lba >= 0)
468 isoburn_attach_start_lba(drive, lba, 0);
469 }
470 if(!(flag&32))
471 Xorriso_toc(xorriso, 1 | 2 | 8);
472 {ret= 1+not_writeable; goto ex;}
473 }
474
475 if(xorriso->in_volset_handle!=NULL)
476 iso_image_unref((IsoImage *) xorriso->in_volset_handle);
477 xorriso->in_volset_handle= NULL;
478 Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
479 Xorriso_destroy_hln_array(xorriso, 0);
480 Xorriso_destroy_di_array(xorriso, 0);
481 xorriso->boot_count= 0;
482 xorriso->system_area_clear_loaded=
483 (strcmp(xorriso->system_area_disk_path, "/dev/zero") == 0);
484
485 /* check for invalid state */
486 if(state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE &&
487 state != BURN_DISC_FULL) {
488 sprintf(xorriso->info_text,
489 "Disc status not blank and unsuitable for reading");
490 sev= "FAILURE";
491 if(xorriso->img_read_error_mode==2)
492 sev= "FATAL";
493 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, sev, 0);
494 Xorriso_give_up_drive(xorriso, 1|((flag&32)>>2));
495 ret= 3; goto ex;
496 }
497 /* fill read opts */
498 ret= isoburn_ropt_new(&ropts, 0);
499 if(ret<=0)
500 goto ex;
501
502 ret= Xorriso_set_data_cache(xorriso, ropts, xorriso->cache_num_tiles,
503 xorriso->cache_tile_blocks,
504 xorriso->cache_default);
505 if(ret<=0)
506 goto ex;
507
508 ext= isoburn_ropt_noiso1999;
509 if(xorriso->read_fs & 1)
510 ext|= isoburn_ropt_norock;
511 if(xorriso->read_fs & 2)
512 ext|= isoburn_ropt_nojoliet;
513 if((xorriso->ino_behavior & (1 | 2)) && !(xorriso->do_aaip & (1 | 4 | 32))
514 && !(xorriso->do_md5 & 1) && !(xorriso->do_hfsplus))
515 ext|= isoburn_ropt_noaaip;
516 if(!(xorriso->do_aaip & 1))
517 ext|= isoburn_ropt_noacl;
518 if(!(xorriso->do_aaip & 4))
519 ext|= isoburn_ropt_noea;
520 if(xorriso->ino_behavior & 1)
521 ext|= isoburn_ropt_noino;
522 if(!(xorriso->do_md5 & 1))
523 ext|= isoburn_ropt_nomd5;
524 if(xorriso->do_md5 & 32)
525 ext|= isoburn_ropt_nomd5tag;
526 if(xorriso->ecma119_map == 0)
527 ext|= isoburn_ropt_map_unmapped;
528 else if(xorriso->ecma119_map == 2)
529 ext|= isoburn_ropt_map_uppercase;
530 else if(xorriso->ecma119_map == 3)
531 ext|= isoburn_ropt_map_lowercase;
532 else
533 ext|= isoburn_ropt_map_stripped;
534
535 isoburn_ropt_set_extensions(ropts, ext);
536
537 isoburn_ropt_set_default_perms(ropts, (uid_t) 0, (gid_t) 0, (mode_t) 0555);
538 isoburn_ropt_set_input_charset(ropts, xorriso->in_charset);
539 isoburn_ropt_set_auto_incharset(ropts, !!(xorriso->do_aaip & 512));
540 isoburn_ropt_set_displacement(ropts, xorriso->displacement,
541 xorriso->displacement_sign);
542 isoburn_ropt_set_truncate_mode(ropts, 1, xorriso->file_name_limit);
543
544 Xorriso_set_image_severities(xorriso, 1); /* No DEBUG messages */
545 Xorriso_pacifier_reset(xorriso, 0);
546 isoburn_set_read_pacifier(drive, Xorriso__read_pacifier, (void *) xorriso);
547
548 /* <<< Trying to work around too much tolerance on bad image trees.
549 Better would be a chance to instruct libisofs what to do in
550 case of image read errors. There is a risk to mistake other SORRYs.
551 */
552 if(xorriso->img_read_error_mode>0)
553 iso_set_abort_severity("SORRY");
554
555 if(state != BURN_DISC_BLANK) {
556 ret= isoburn_disc_get_msc1(drive, &load_lba);
557 if(ret > 0) {
558 sprintf(xorriso->info_text,
559 "Loading ISO image tree from LBA %d", load_lba);
560 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
561 }
562 ret= Xorriso_assert_volid(xorriso, load_lba, 0);
563 if(ret <= 0)
564 goto ex;
565 }
566 if(xorriso->read_speed != -2)
567 burn_drive_set_speed(drive, xorriso->read_speed, 0);
568 read_ret= ret= isoburn_read_image(drive, ropts, &volset);
569
570 /* <<< Resetting to normal thresholds */
571 if(xorriso->img_read_error_mode>0)
572 Xorriso_set_abort_severity(xorriso, 0);
573
574 if(ret<=0) {
575 Xorriso_process_msg_queues(xorriso,0);
576 Xorriso_set_image_severities(xorriso, 0);
577 Xorriso_give_up_drive(xorriso, 1|((flag&32)>>2));
578 sprintf(xorriso->info_text,"Cannot read ISO image tree");
579 sev= "FAILURE";
580 if(xorriso->img_read_error_mode==2)
581 sev= "FATAL";
582 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, sev, 0);
583 if(read_ret == (int) ISO_SB_TREE_CORRUPTED && (xorriso->do_md5 & 1)) {
584 Xorriso_msgs_submit(xorriso, 0,
585 "This might be false MD5 alarm if an add-on session was written by growisofs.",
586 0, "HINT", 0);
587 Xorriso_msgs_submit(xorriso, 0,
588 "In this case you get an ISO image tree by option -md5 'load_check_off'",
589 0, "HINT", 0);
590 } else if(xorriso->img_read_error_mode!=0) {
591 Xorriso_msgs_submit(xorriso, 0, "You might get a partial or altered ISO image tree by option -error_behavior 'image_loading' 'best_effort' if -abort_on is set to be tolerant enough.",
592 0, "HINT", 0);
593 }
594
595
596 ret= 3; goto ex;
597 }
598 Xorriso_pacifier_callback(xorriso, "nodes read", xorriso->pacifier_count, 0,
599 "", 1); /* report end count */
600 xorriso->in_volset_handle= (void *) volset;
601 xorriso->in_sector_map= NULL;
602 Xorriso_set_image_severities(xorriso, 0);
603
604 /* Might have changed due to isofs.nt */
605 iso_image_get_truncate_mode(volset, &truncate_mode,
606 &(xorriso->file_name_limit));
607 Xorriso_process_msg_queues(xorriso,0);
608
609 Xorriso_update_volid(xorriso, 0);
610 strncpy(xorriso->application_id,
611 un0(iso_image_get_application_id(volset)), 128);
612 xorriso->application_id[128]= 0;
613 strncpy(xorriso->publisher, un0(iso_image_get_publisher_id(volset)), 128);
614 xorriso->publisher[128]= 0;
615 strncpy(xorriso->system_id, un0(iso_image_get_system_id(volset)), 32);
616 xorriso->system_id[32]= 0;
617 strncpy(xorriso->volset_id, un0(iso_image_get_volset_id(volset)), 128);
618 xorriso->volset_id[128]= 0;
619 strncpy(xorriso->copyright_file,
620 un0(iso_image_get_copyright_file_id(volset)), 37);
621 xorriso->copyright_file[37]= 0;
622 strncpy(xorriso->biblio_file, un0(iso_image_get_biblio_file_id(volset)), 37);
623 xorriso->biblio_file[37]= 0;
624 strncpy(xorriso->abstract_file,
625 un0(iso_image_get_abstract_file_id(volset)), 37);
626 xorriso->abstract_file[37]= 0;
627
628 if(xorriso->out_drive_handle != NULL &&
629 xorriso->out_drive_handle != xorriso->in_drive_handle) {
630 start_lba= -1;
631 ret= Xorriso_get_drive_handles(xorriso, &in_dinfo, &in_drive,
632 "on attempt to attach ISO image volset to outdev", 16);
633 if(ret > 0)
634 start_lba= isoburn_get_attached_start_lba(in_drive);
635 ret= Xorriso_get_drive_handles(xorriso, &out_dinfo, &out_drive,
636 "on attempt to attach ISO image volset to outdev", 2);
637 if(ret<=0)
638 goto ex;
639 iso_image_ref((IsoImage *) xorriso->in_volset_handle);
640 isoburn_attach_image(out_drive, xorriso->in_volset_handle);
641 if(start_lba >= 0)
642 isoburn_attach_start_lba(out_drive, ret, 0);
643 }
644 Xorriso_process_msg_queues(xorriso,0);
645 isoburn_ropt_get_size_what(ropts, &size, &has_what);
646 if(has_what & isoburn_ropt_has_el_torito) {
647 if(xorriso->boot_image_bin_path[0])
648 boot_fate= "replaced by new boot image";
649 else if(xorriso->patch_isolinux_image & 1)
650 boot_fate= "patched at boot info table";
651 else if(xorriso->keep_boot_image)
652 boot_fate= "kept unchanged";
653 else
654 boot_fate= "discarded";
655 sprintf(xorriso->info_text,
656 "Detected El-Torito boot information which currently is set to be %s",
657 boot_fate);
658 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
659 Xorriso_record_boot_info(xorriso, 0);
660 }
661
662 if(flag & 1) {
663 ret= Xorriso_grasp_loaded_aaip(xorriso, volset, 0);
664 if(ret <= 0)
665 goto ex;
666 }
667
668 if(!(flag&32)) {
669 Xorriso_toc(xorriso, 1 | 8);
670 if(xorriso->loaded_volid[0] != 0 &&
671 (state == BURN_DISC_APPENDABLE || state == BURN_DISC_FULL)) {
672 sprintf(xorriso->info_text,"Volume id : '%s'\n",
673 xorriso->loaded_volid);
674 Xorriso_info(xorriso, 0);
675 }
676 if(strcmp(xorriso->loaded_volid, xorriso->volid) != 0 &&
677 !xorriso->volid_default) {
678 sprintf(xorriso->info_text, "New volume id: '%s'\n", xorriso->volid);
679 Xorriso_info(xorriso, 0);
680 }
681 }
682
683 ret= 1+not_writeable;
684 ex:
685 Xorriso_process_msg_queues(xorriso,0);
686 if(ret<=0) {
687 hret= Xorriso_give_up_drive(xorriso, (flag&3)|((flag&32)>>2));
688 if(hret<ret)
689 ret= hret;
690 } else {
691 if(drive != NULL && (xorriso->do_calm_drive & 1) && !(flag & 64))
692 burn_drive_snooze(drive, 0); /* No need to make noise from start */
693 }
694 if(ropts!=NULL)
695 isoburn_ropt_destroy(&ropts, 0);
696 Xorriso_free_meM(off_adr);
697 Xorriso_free_meM(libburn_adr);
698 Xorriso_free_meM(adr_data);
699 return(ret);
700 }
701
702
703 /* @param flag bit0=input drive
704 bit1=output drive
705 bit2=eject
706 bit3=no info message or toc
707 */
Xorriso_give_up_drive(struct XorrisO * xorriso,int flag)708 int Xorriso_give_up_drive(struct XorrisO *xorriso, int flag)
709 {
710 int in_is_out_too, ret, do_eject;
711 struct burn_drive_info *dinfo;
712 struct burn_drive *drive;
713
714 in_is_out_too= (xorriso->in_drive_handle == xorriso->out_drive_handle);
715 if((flag&4) && in_is_out_too && (flag&(1|2))) {
716 if((flag&3)!=3) {
717 sprintf(xorriso->info_text,"Giving up for -eject whole -dev ");
718 Text_shellsafe(xorriso->indev, xorriso->info_text, 1);
719 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
720 }
721 flag|= 3; /* give up in/out drive to eject it */
722 }
723
724 if((flag&1) && xorriso->in_drive_handle != NULL) {
725 Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
726 "on attempt to give up drive", 0);
727
728 if(!in_is_out_too) {
729 do_eject= !!(flag&4);
730 if((flag & 4) && !xorriso->indev_is_exclusive) {
731 sprintf(xorriso->info_text,
732 "Will not eject medium in non-exclusively acquired input drive.");
733 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
734 do_eject= 0;
735 }
736 if(drive!=NULL)
737 isoburn_drive_release(drive, do_eject);
738 if(dinfo!=NULL)
739 burn_drive_info_free(dinfo);
740 }
741 xorriso->in_drive_handle= NULL;
742 xorriso->indev[0]= 0;
743
744 if(xorriso->in_volset_handle!=NULL)
745 iso_image_unref((IsoImage *) xorriso->in_volset_handle);
746 xorriso->in_volset_handle= NULL;
747 Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
748 Xorriso_destroy_di_array(xorriso, 0);
749 Xorriso_destroy_hln_array(xorriso, 0);
750 xorriso->loaded_volid[0]= 0;
751 xorriso->isofs_st_out= time(0) - 1;
752 xorriso->isofs_st_in= 0;
753 xorriso->volset_change_pending= 0;
754 xorriso->no_volset_present= 0;
755 xorriso->loaded_boot_bin_lba= 0;
756 xorriso->loaded_boot_cat_path[0]= 0;
757 xorriso->boot_count= 0;
758 in_is_out_too= 0;
759 }
760 if((flag&2) && xorriso->out_drive_handle!=NULL) {
761 do_eject= !!(flag&4);
762 if((flag & 4) && !xorriso->outdev_is_exclusive) {
763 sprintf(xorriso->info_text,
764 "Will not eject medium in non-exclusively acquired drive.");
765 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
766 do_eject= 0;
767 }
768 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
769 "on attempt to give up drive", 2);
770 if(ret >= 0 && !in_is_out_too) {
771 if(drive!=NULL)
772 isoburn_drive_release(drive, do_eject);
773 if(dinfo!=NULL)
774 burn_drive_info_free(dinfo);
775 }
776 xorriso->out_drive_handle= NULL;
777 xorriso->outdev[0]= 0;
778 xorriso->outdev_off_adr[0]= 0;
779 } else if((flag&1) && xorriso->out_drive_handle!=NULL) {
780 ret= Xorriso_create_empty_iso(xorriso, 0);
781 if(ret<=0)
782 return(ret);
783 if(!(flag&8)) {
784 sprintf(xorriso->info_text,
785 "Only the output drive remains. Created empty ISO image.\n");
786 Xorriso_info(xorriso, 0);
787 Xorriso_toc(xorriso, 1 | 2 | 8);
788 }
789 }
790 Xorriso_process_msg_queues(xorriso,0);
791 return(1);
792 }
793
794
Xorriso_may_burn(struct XorrisO * xorriso,int flag)795 int Xorriso_may_burn(struct XorrisO *xorriso, int flag)
796 {
797
798 if(xorriso->outdev_is_exclusive)
799 return(1);
800 sprintf(xorriso->info_text, "The output drive was not acquired exclusively.");
801 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
802 sprintf(xorriso->info_text, "A possible remedy is: -osirrox 'o_excl_on'");
803 if(xorriso->outdev[0]) {
804 strcat(xorriso->info_text," -outdev ");
805 Text_shellsafe(xorriso->outdev, xorriso->info_text, 1);
806 }
807 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
808 return(0);
809 }
810
811
812 /* @param flag bit1=report about output drive rather than input drive
813 bit2=do not try to read ISO heads
814 */
Xorriso_toc_to_string(struct XorrisO * xorriso,char ** toc_text,int flag)815 int Xorriso_toc_to_string(struct XorrisO *xorriso, char **toc_text, int flag)
816 {
817 int ret, stack_handle, toc_ret, l;
818 struct Xorriso_lsT *results= NULL, *infos= NULL, *lpt;
819
820 *toc_text= NULL;
821 ret= Xorriso_push_outlists(xorriso, &stack_handle, 1);
822 if(ret <= 0)
823 goto ex;
824 toc_ret= Xorriso_toc(xorriso, flag & (2 | 4));
825 ret= Xorriso_pull_outlists(xorriso, stack_handle, &results, &infos, 0);
826 if(ret <= 0)
827 goto ex;
828 if(toc_ret <= 0)
829 {ret= toc_ret; goto ex;}
830 l= 0;
831 for(lpt= results; lpt != NULL; lpt= Xorriso_lst_get_next(lpt, 0))
832 l+= strlen(Xorriso_lst_get_text(lpt, 0));
833 *toc_text= calloc(l + 1, 1);
834 l= 0;
835 for(lpt= results; lpt != NULL; lpt= Xorriso_lst_get_next(lpt, 0)) {
836 strcpy((*toc_text) + l, Xorriso_lst_get_text(lpt, 0));
837 l+= strlen(Xorriso_lst_get_text(lpt, 0));
838 }
839 ex:;
840 Xorriso_lst_destroy_all(&results, 0);
841 Xorriso_lst_destroy_all(&infos, 0);
842 return(ret);
843 }
844
845
846 /* @param flag bit0+1= what to give up and/or re-assess in what role
847 0=give up outdev
848 1=give up indev if not outdev, re-assess outdev as indev
849 2=re-assess outdev as outdev
850 3=give up indev if not outdev, re-assess outdev as dev
851 */
Xorriso_reaquire_outdev(struct XorrisO * xorriso,int flag)852 int Xorriso_reaquire_outdev(struct XorrisO *xorriso, int flag)
853 {
854 int ret, aq_flag;
855 char *drive_name= NULL, *off_name= NULL;
856
857 Xorriso_alloc_meM(drive_name, char, SfileadrL);
858 Xorriso_alloc_meM(off_name, char, SfileadrL);
859 aq_flag= flag&3;
860 strcpy(drive_name, xorriso->outdev);
861 if(xorriso->outdev_off_adr[0])
862 strcpy(off_name, xorriso->outdev_off_adr);
863 else
864 strcpy(off_name, drive_name);
865
866 if(aq_flag == 0) {
867 Xorriso_give_up_drive(xorriso, 2);
868 sprintf(xorriso->info_text,"Gave up -outdev ");
869 Text_shellsafe(xorriso->indev, xorriso->info_text, 1);
870 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
871 {ret= 1; goto ex;}
872 }
873
874 /* Only give up indev, and only if it is not outdev */;
875 if(xorriso->in_drive_handle != xorriso->out_drive_handle &&
876 xorriso->in_drive_handle != NULL && (aq_flag & 1))
877 Xorriso_give_up_drive(xorriso, 1 | 8);
878 sprintf(xorriso->info_text,"Re-assessing -outdev ");
879 Text_shellsafe(drive_name, xorriso->info_text, 1);
880 if(strcmp(drive_name, off_name) != 0) {
881 strcat(xorriso->info_text, " (");
882 Text_shellsafe(off_name, xorriso->info_text, 1);
883 strcat(xorriso->info_text, ")");
884 }
885 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
886
887 /* Re-assess outdev */
888 ret= Xorriso_aquire_drive(xorriso, off_name, drive_name, aq_flag | 128);
889 if(ret<=0) {
890 sprintf(xorriso->info_text,"Could not re-assess -outdev ");
891 Text_shellsafe(drive_name, xorriso->info_text, 1);
892 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
893 goto ex;
894 }
895
896 ret= 1;
897 ex:;
898 Xorriso_free_meM(drive_name);
899 Xorriso_free_meM(off_name);
900 return(ret);
901 }
902
903
904 /* @param flag
905 bit3=report to info channel (else to result channel)
906 */
Xorriso_toc_line(struct XorrisO * xorriso,int flag)907 int Xorriso_toc_line(struct XorrisO *xorriso, int flag)
908 {
909 if(!(flag & 8)) {
910 Xorriso_result(xorriso,0);
911 return(1);
912 }
913 strcpy(xorriso->info_text, xorriso->result_line);
914 Xorriso_info(xorriso, 0);
915 return(1);
916 }
917
918
919 /* @param flag
920 bit1=report about output drive
921 bit3=report to info channel (else to result channel)
922 bit4=do no report failure if no drive acquired
923 */
Xorriso_media_product(struct XorrisO * xorriso,int flag)924 int Xorriso_media_product(struct XorrisO *xorriso, int flag)
925 {
926 int ret, profile_no;
927 struct burn_drive_info *dinfo;
928 struct burn_drive *drive;
929 char *product_id= NULL, *media_code1= NULL, *media_code2= NULL;
930 char *book_type= NULL, *manuf= NULL, profile_name[80], *respt;
931
932 respt= xorriso->result_line;
933
934 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
935 "on attempt to print media product info",
936 flag & (2 | 16));
937 if(ret <= 0)
938 return(ret);
939 ret= burn_disc_get_media_id(drive, &product_id, &media_code1, &media_code2,
940 &book_type, 0);
941 if(ret > 0) {
942 ret= burn_disc_get_profile(drive, &profile_no, profile_name);
943 if(ret <= 0)
944 return(ret);
945 sprintf(respt, "Media product: %s , ", product_id);
946 manuf= burn_guess_manufacturer(profile_no, media_code1, media_code2, 0);
947 if(manuf != NULL) {
948 if(strncmp(manuf, "Unknown ", 8) == 0)
949 sprintf(respt + strlen(respt), "(not found in manufacturer list)\n");
950 else
951 sprintf(respt + strlen(respt), "%s\n", manuf);
952 } else
953 sprintf(respt + strlen(respt), "(error during manufacturer lookup)\n");
954 free(product_id);
955 free(media_code1);
956 free(media_code2);
957 if(book_type != NULL)
958 free(book_type);
959 if(manuf != NULL)
960 free(manuf);
961 Xorriso_toc_line(xorriso, flag & 8);
962 }
963 Xorriso_process_msg_queues(xorriso,0);
964
965 return(1);
966 }
967
968
969 /* @param flag bit0=short report form
970 bit1=report about output drive
971 bit2=do not try to read ISO heads
972 bit3=report to info channel (else to result channel)
973 bit4=do no report failure if no drive acquired
974 bit5=only report "Drive current" and "Drive type"
975 bit6=report "Media product" with bit0
976 bit7=only report "Drive current"
977 */
Xorriso_toc(struct XorrisO * xorriso,int flag)978 int Xorriso_toc(struct XorrisO *xorriso, int flag)
979 {
980 int num_sessions= 0, num_tracks= 0, lba= 0, nwa= -1, ret;
981 int track_count= 0, session_no, track_no, profile_no= -1, track_size;
982 int last_track_start= 0, last_track_size= -1, num_data= 0, is_data= 0;
983 int is_inout_drive= 0, drive_role, status, num_formats, emul_lba;
984 int not_recognizable= 0, start_lba, end_lba;
985 int sessions_seen, open_sessions= 0, have_real_open_session= 0;
986 char profile_name[80],*respt,*devadr, *typetext= "";
987 struct burn_toc_entry toc_entry;
988 struct burn_drive_info *dinfo;
989 struct burn_multi_caps *caps= NULL;
990 struct burn_drive *drive;
991 enum burn_disc_status s;
992 char mem_text[80], *num_free_text;
993 off_t start_byte= 0, num_free= 0, size;
994 unsigned dummy;
995 struct isoburn_toc_disc *disc= NULL;
996 struct isoburn_toc_session **sessions;
997 struct isoburn_toc_track **tracks;
998 int image_blocks= 0;
999 char volume_id[33];
1000 struct burn_toc_entry next_toc_entry;
1001 int disk_category, part_version, num_layers, num_blocks;
1002 char *book_name;
1003 int num_data_from_format= 0;
1004 char *sno = NULL;
1005 int sno_len, i, is_bdr_pow= 0;
1006
1007 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
1008 "on attempt to print Table Of Content",
1009 flag & (2 | 16));
1010 if(ret<=0)
1011 {ret= 0; goto ex;}
1012
1013 respt= xorriso->result_line;
1014
1015 if(strcmp(xorriso->indev, xorriso->outdev)==0)
1016 is_inout_drive= 1;
1017 if(flag&2)
1018 devadr= xorriso->outdev;
1019 else
1020 devadr= xorriso->indev;
1021 sprintf(respt, "Drive current: %s '%s'\n",
1022 (is_inout_drive ? "-dev" : (flag&2 ? "-outdev" : "-indev")),
1023 devadr);
1024 Xorriso_toc_line(xorriso, flag & 8);
1025 if(flag & 128)
1026 {ret= 1; goto ex;}
1027 sprintf(respt, "Drive type : vendor '%s' product '%s' revision '%s'\n",
1028 dinfo[0].vendor, dinfo[0].product, dinfo[0].revision);
1029 if((flag & 32) || !(flag & 1))
1030 Xorriso_toc_line(xorriso, flag & 8);
1031 if(flag & 32)
1032 {ret= 1; goto ex;}
1033
1034 if(!(flag & 1)) {
1035 burn_drive_get_serial_no(drive, &sno, &sno_len);
1036 if(sno_len > 0) {
1037 sprintf(respt, "Drive id : '%s'\n", sno);
1038 Xorriso_toc_line(xorriso, flag & 8);
1039 }
1040 if(sno != NULL)
1041 free(sno);
1042 sno= NULL;
1043 }
1044
1045 ret= burn_disc_get_profile(drive, &profile_no, profile_name);
1046 s= isoburn_disc_get_status(drive);
1047 if(profile_no == 0x0002 && s == BURN_DISC_EMPTY)
1048 profile_no= 0;
1049 is_bdr_pow= burn_drive_get_bd_r_pow(drive);
1050 sprintf(respt, "Media current: ");
1051 drive_role= burn_drive_get_drive_role(drive);
1052 if (profile_no > 0 && ret > 0) {
1053 if (profile_name[0])
1054 sprintf(respt+strlen(respt), "%s", profile_name);
1055 else
1056 sprintf(respt+strlen(respt), "%4.4Xh", profile_no);
1057 if(is_bdr_pow)
1058 sprintf(respt+strlen(respt), ", Pseudo Overwrite formatted");
1059 else if(drive_role==2)
1060 sprintf(respt+strlen(respt), ", overwriteable");
1061 else if(drive_role == 4)
1062 sprintf(respt+strlen(respt), ", random read-only");
1063 else if(drive_role == 5)
1064 sprintf(respt+strlen(respt), ", random write-only");
1065 else if(drive_role==0 || drive_role==3)
1066 sprintf(respt+strlen(respt), ", sequential");
1067 strcat(respt, "\n");
1068 } else {
1069 sprintf(respt+strlen(respt), "is not recognizable\n");
1070 not_recognizable= 1;
1071 }
1072 Xorriso_toc_line(xorriso, flag & 8);
1073
1074 if((flag & 64) || !(flag & 1)) {
1075 Xorriso_media_product(xorriso, flag & (2 | 8 | 16));
1076 if(xorriso->request_to_abort)
1077 {ret= 1; goto ex;}
1078 }
1079
1080 sprintf(respt, "Media status : ");
1081 if(is_bdr_pow) {
1082 sprintf(respt+strlen(respt), "is unsuitable , is POW formatted");
1083 } else if (s == BURN_DISC_FULL) {
1084 if(not_recognizable)
1085 sprintf(respt+strlen(respt), "is not recognizable\n");
1086 else
1087 sprintf(respt+strlen(respt), "is written , is closed");
1088 } else if (s == BURN_DISC_APPENDABLE) {
1089 sprintf(respt+strlen(respt), "is written , is appendable");
1090 } else if (s == BURN_DISC_BLANK) {
1091 sprintf(respt+strlen(respt), "is blank");
1092 } else if (s == BURN_DISC_EMPTY)
1093 sprintf(respt+strlen(respt), "is not present");
1094 else
1095 sprintf(respt+strlen(respt), "is not recognizable");
1096 if(s == BURN_DISC_APPENDABLE || s == BURN_DISC_BLANK) {
1097 ret= burn_disc_next_track_is_damaged(drive, 0);
1098 if(ret & 1)
1099 sprintf(respt+strlen(respt), " , but next track is damaged");
1100 else if(ret & 2)
1101 sprintf(respt+strlen(respt), " , but no writable address");
1102 else if(profile_no == 0x14) { /* DVD-RW sequential */
1103 ret= burn_disc_get_multi_caps(drive, BURN_WRITE_TAO, &caps, 0);
1104 if(ret == 0)
1105 sprintf(respt+strlen(respt), " , but will need -close on");
1106 if(caps != NULL)
1107 burn_disc_free_multi_caps(&caps);
1108 } else if(profile_no == 0x15) { /* DVD-RW DL */
1109 sprintf(respt+strlen(respt), " , but will need -close \"on\"");
1110 }
1111 }
1112 strcat(respt, "\n");
1113 Xorriso_toc_line(xorriso, flag & 8);
1114
1115 if((s == BURN_DISC_FULL || s == BURN_DISC_APPENDABLE ||
1116 s == BURN_DISC_BLANK) && !(flag & 1)) {
1117 burn_drive_get_media_sno(drive, &sno, &sno_len);
1118 if(sno_len > 0) {
1119 sprintf(respt, "Media id : ");
1120 respt+= strlen(respt);
1121 for(i= 0; i < sno_len && i < 1024; i++) {
1122 sprintf(respt, "%2.2X", (unsigned int) ((unsigned char *) sno)[i]);
1123 respt+= 2;
1124 }
1125 if(i < sno_len)
1126 strcat(respt, "...");
1127 strcat(respt, "\n");
1128 Xorriso_toc_line(xorriso, flag & 8);
1129 }
1130 if(sno != NULL)
1131 free(sno);
1132 sno= NULL;
1133 respt= xorriso->result_line;
1134
1135 ret= burn_get_read_capacity(drive, &num_data, 0);
1136 if(ret != 1 || s == BURN_DISC_BLANK)
1137 num_data= 0;
1138 num_free= isoburn_disc_available_space(drive, NULL) / 2048;
1139 nwa= -1;
1140 if (s == BURN_DISC_APPENDABLE) {
1141 ret= isoburn_disc_track_lba_nwa(drive, NULL, 0, &lba, &nwa);
1142 if(ret <= 0)
1143 nwa= -1;
1144 } else if(s == BURN_DISC_BLANK) {
1145 ret= isoburn_disc_track_lba_nwa(drive, NULL, 0, &lba, &nwa);
1146 if(ret == 1) {
1147 num_free+= nwa;
1148 nwa= 0;
1149 }
1150 }
1151 lba= num_data + num_free;
1152 if(nwa >= 0) {
1153 lba= nwa + num_free;
1154 if(nwa < num_data)
1155 num_data= nwa;
1156 }
1157
1158 /* If closed CD-RW : obtain ATIP lead out address */
1159 if(profile_no == 0x0a) {
1160 ret= burn_disc_read_atip(drive);
1161 if(ret < 0)
1162 goto ex;
1163 ret= burn_drive_get_start_end_lba(drive, &start_lba, &end_lba, 0);
1164 if(s == BURN_DISC_FULL && ret == 1) {
1165 lba= end_lba - 2;
1166 } else {
1167 if(ret == 1 && end_lba - 2 > lba) {
1168 sprintf(xorriso->info_text,
1169 "ATIP end_lba %d > overall %d", end_lba, lba);
1170 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
1171 }
1172 }
1173 } else if(profile_no == 0x14) {
1174 ret= burn_disc_get_phys_format_info(drive, &disk_category,
1175 &book_name, &part_version,
1176 &num_layers, &num_blocks, 0);
1177 if(ret == 1 && num_blocks > lba)
1178 lba= num_blocks;
1179 }
1180
1181 if(drive_role == 4 || is_bdr_pow)
1182 num_free_text = "unused";
1183 else
1184 num_free_text = "writable";
1185 sprintf(respt, "Media blocks : %d readable , %d %s , %d overall\n",
1186 num_data, (int) num_free, num_free_text, lba);
1187 Xorriso_toc_line(xorriso, flag & 8);
1188 }
1189
1190 if(s == BURN_DISC_BLANK) {
1191 sprintf(respt, "Media summary: 0 sessions, 0 data blocks, 0 data");
1192 num_free= isoburn_disc_available_space(drive, NULL);
1193 Sfile_scale((double) num_free, mem_text,5,1e4,1);
1194 sprintf(respt+strlen(respt), ", %s free\n", mem_text);
1195 Xorriso_toc_line(xorriso, flag & 8);
1196 }
1197 if(s != BURN_DISC_FULL && s != BURN_DISC_APPENDABLE)
1198 {ret= 1; goto ex;}
1199 if(xorriso->request_to_abort)
1200 {ret= 1; goto ex;}
1201 if(is_bdr_pow) {
1202 sprintf(respt,
1203 "Media summary: unsuitable Pseudo Overwrite formatted BD-R\n");
1204 Xorriso_toc_line(xorriso, flag & 8);
1205 {ret= 1; goto ex;}
1206 }
1207
1208 if(!(flag & 2))
1209 Xorriso_show_boot_info(xorriso, 1 | (flag & 8) | ((flag & 1) << 1));
1210
1211 disc= isoburn_toc_drive_get_disc(drive);
1212 if(flag & 4)
1213 sprintf(respt, "TOC layout : %3s , %9s , %10s\n",
1214 "Idx", "sbsector", "Size");
1215 else
1216 sprintf(respt, "TOC layout : %3s , %9s , %10s , %s\n",
1217 "Idx", "sbsector", "Size", "Volume Id");
1218 if(!(flag&1))
1219 Xorriso_toc_line(xorriso, flag & 8);
1220
1221 if (disc==NULL) {
1222 Xorriso_process_msg_queues(xorriso,0);
1223 if(drive_role == 5 && s == BURN_DISC_APPENDABLE) {
1224 ret= burn_disc_track_lba_nwa(drive, NULL, 0, &lba, &nwa);
1225 if(ret != 1)
1226 lba= 0;
1227 } else {
1228 ret= isoburn_get_min_start_byte(drive, &start_byte, 0);
1229 nwa= start_byte / 2048;
1230 if(ret<=0) {
1231 Xorriso_process_msg_queues(xorriso,0);
1232 if(flag&1)
1233 {ret= 1; goto ex;}
1234 sprintf(xorriso->info_text, "Cannot obtain Table Of Content");
1235 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
1236 {ret= 0; goto ex;}
1237 }
1238 }
1239
1240 /* fabricate TOC */
1241 typetext= "Other session";
1242 if(flag & 4) {
1243 ret= 0;
1244 typetext= "Session ";
1245 } else
1246 ret= isoburn_read_iso_head(drive, 0, &image_blocks, volume_id, 1);
1247 if(ret>0) {
1248 sprintf(respt, "ISO session : %3d , %9d , %9ds , %s\n",
1249 1, 0, image_blocks, volume_id);
1250 nwa= image_blocks;
1251 } else {
1252 ret= burn_disc_get_formats(drive, &status, &size, &dummy,
1253 &num_formats);
1254 if(ret <= 0 || status != BURN_FORMAT_IS_FORMATTED)
1255 size= 0;
1256 if(size <= 0) {
1257 ret= burn_get_read_capacity(drive, &num_data, 0);
1258 if(ret == 1)
1259 size= ((off_t) num_data) * (off_t) 2048;
1260 } else {
1261 num_data_from_format= 1;
1262 }
1263 nwa= lba + size / 2048;
1264 num_data= nwa - lba;
1265 sprintf(respt, "%13s: %3d , %9d , %9ds , \n",
1266 typetext, 1, lba, num_data);
1267 }
1268 if(!(flag&1))
1269 Xorriso_toc_line(xorriso, flag & 8);
1270 last_track_start= lba;
1271 /*
1272 num_payload= num_data= last_track_size= nwa;
1273 */
1274 num_sessions= 1;
1275 } else {
1276 num_data= 0;
1277 sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions);
1278 open_sessions= isoburn_toc_disc_get_incmpl_sess(disc);
1279 for (session_no= 0;
1280 session_no < num_sessions + open_sessions &&
1281 !(xorriso->request_to_abort);
1282 session_no++) {
1283 tracks= isoburn_toc_session_get_tracks(sessions[session_no], &num_tracks);
1284 if (tracks == NULL || num_tracks <= 0)
1285 continue;
1286 if(session_no == num_sessions + open_sessions - 1 && open_sessions > 0)
1287 have_real_open_session= 1;
1288 for(track_no= 0; track_no<num_tracks && !(xorriso->request_to_abort);
1289 track_no++) {
1290 track_count++;
1291 is_data= 0;
1292 isoburn_toc_track_get_entry(tracks[track_no], &toc_entry);
1293 if (toc_entry.extensions_valid & 1) {
1294 /* DVD extension valid */
1295 lba= toc_entry.start_lba;
1296 track_size= toc_entry.track_blocks;
1297 } else {
1298 lba= burn_msf_to_lba(toc_entry.pmin, toc_entry.psec,
1299 toc_entry.pframe);
1300 if(track_no==num_tracks-1) {
1301 isoburn_toc_session_get_leadout_entry(sessions[session_no],
1302 &next_toc_entry);
1303 } else {
1304 isoburn_toc_track_get_entry(tracks[track_no+1], &next_toc_entry);
1305 }
1306 track_size= burn_msf_to_lba(next_toc_entry.pmin, next_toc_entry.psec,
1307 next_toc_entry.pframe) - lba;
1308 }
1309 if(flag&(1|4))
1310 ret= 0;
1311 else {
1312 ret= isoburn_toc_track_get_emul(tracks[track_no], &emul_lba,
1313 &image_blocks, volume_id, 0);
1314 if(ret <= 0)
1315 ret= isoburn_read_iso_head(drive, lba, &image_blocks, volume_id, 1);
1316 if(image_blocks > track_size) {
1317 sprintf(xorriso->info_text,
1318 "Session %d bears ISO image size %ds larger than track size %ds",
1319 session_no + 1, image_blocks, track_size);
1320 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING",
1321 0);
1322 image_blocks= track_size;
1323 }
1324 }
1325 if(session_no >= num_sessions && track_no == 0) {
1326 if(ret <= 0)
1327 volume_id[0]= 0;
1328 sprintf(respt, "Incmp session: %3d , %9d , %9ds , %s\n",
1329 session_no+1, lba, image_blocks, volume_id);
1330 } else if(ret>0 && track_no==0) {
1331 sprintf(respt, "ISO session : %3d , %9d , %9ds , %s\n",
1332 session_no+1, lba, image_blocks , volume_id);
1333 } else if(ret>0) {
1334 sprintf(respt, "ISO track : %3d , %9d , %9ds , %s\n",
1335 track_count, lba, image_blocks , volume_id);
1336 } else if(track_no==0) {
1337 typetext= "Other session";
1338 if(flag & 4)
1339 typetext= "Session ";
1340 sprintf(respt, "%13s: %3d , %9d , %9ds , \n",
1341 typetext, session_no+1, lba, track_size);
1342 } else {
1343 typetext= "Other track ";
1344 if(flag & 4)
1345 typetext= "Track ";
1346 sprintf(respt, "%13s: %3d , %9d , %9ds , \n",
1347 typetext, track_count, lba, track_size);
1348 }
1349 if(!(flag&1))
1350 Xorriso_toc_line(xorriso, flag & 8);
1351 /*
1352 if(track_no>0)
1353 num_payload+= lba - last_track_start;
1354 */
1355 last_track_start= lba;
1356 if((toc_entry.control&7)>=4) /* data track */
1357 is_data= 1;
1358 }
1359 isoburn_toc_session_get_leadout_entry(sessions[session_no], &toc_entry);
1360 if (toc_entry.extensions_valid & 1) {
1361 lba= toc_entry.start_lba;
1362 } else {
1363 lba= burn_msf_to_lba(toc_entry.pmin, toc_entry.psec, toc_entry.pframe);
1364 }
1365 last_track_size= lba - last_track_start;
1366 /*
1367 num_payload+= last_track_size;
1368 */
1369 if(is_data)
1370 num_data+= last_track_size;
1371 }
1372 }
1373 if(xorriso->request_to_abort)
1374 {ret= 1; goto ex;}
1375 /*
1376 num_wasted= lba - num_payload;
1377 num_nondata= lba - num_data;
1378 */
1379
1380 Sfile_scale(((double) num_data) * 2048.0, mem_text,5,1e4,1);
1381 sessions_seen= num_sessions + open_sessions;
1382 if(open_sessions > 0 && !have_real_open_session)
1383 sessions_seen--;
1384 sprintf(respt, "Media summary: %d session%s, %d data blocks, %s data",
1385 sessions_seen, (sessions_seen == 1 ? "" : "s"), num_data, mem_text);
1386 if(num_data_from_format)
1387 num_free= 0;
1388 else
1389 num_free= isoburn_disc_available_space(drive, NULL);
1390 Sfile_scale((double) num_free, mem_text,5,1e4,1);
1391 sprintf(respt+strlen(respt), ", %s free", mem_text);
1392
1393 sprintf(respt+strlen(respt), "\n");
1394 Xorriso_toc_line(xorriso, flag & 8);
1395
1396 if (s==BURN_DISC_APPENDABLE && nwa!=0) {
1397 ret= isoburn_disc_track_lba_nwa(drive, NULL, 0, &lba, &nwa);
1398 if(ret>0) {
1399 sprintf(respt, "Media nwa : %ds\n", nwa);
1400 if(!(flag&1))
1401 Xorriso_toc_line(xorriso, flag & 8);
1402 }
1403 }
1404 if(profile_no == 0x41 && sessions_seen >= 300) {
1405 sprintf(xorriso->info_text,
1406 "Sequential BD-R medium now contains %d sessions. It is likely to soon fail writing.",
1407 sessions_seen);
1408 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
1409 }
1410
1411 if(have_real_open_session) {
1412 sprintf(xorriso->info_text, "Incomplete session encountered !");
1413 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
1414 }
1415
1416 if (disc!=NULL)
1417 isoburn_toc_disc_free(disc);
1418 Xorriso_process_msg_queues(xorriso,0);
1419 ret= 1;
1420 ex:;
1421 return(ret);
1422 }
1423
1424
1425 /* @param flag bit0= try to find 'meaningful' links for enumerated devices
1426 */
Xorriso_show_devices(struct XorrisO * xorriso,int flag)1427 int Xorriso_show_devices(struct XorrisO *xorriso, int flag)
1428 {
1429 char *adr= NULL, *link_adr= NULL, *adrpt;
1430 int i, j, max_dev_len= 1, pad, ret;
1431 struct burn_drive_info *drive_list= NULL;
1432 unsigned int drive_count;
1433 char *respt, perms[8];
1434 struct stat stbuf;
1435
1436 Xorriso_alloc_meM(adr, char, BURN_DRIVE_ADR_LEN);
1437 Xorriso_alloc_meM(link_adr, char, BURN_DRIVE_ADR_LEN);
1438
1439 sprintf(xorriso->info_text, "Beginning to scan for devices ...\n");
1440 Xorriso_info(xorriso,0);
1441
1442 burn_drive_clear_whitelist();
1443 while(!burn_drive_scan(&drive_list, &drive_count)) {
1444 Xorriso_process_msg_queues(xorriso,0);
1445 usleep(100000);
1446 }
1447 Xorriso_process_msg_queues(xorriso,0);
1448 if(drive_count == 0) {
1449
1450 /* >>> was a drive_list created at all ? */
1451 /* >>> must it be freed ? */
1452
1453 sprintf(xorriso->info_text, "No drives found");
1454 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
1455 {ret= 0; goto ex;}
1456 }
1457 sprintf(xorriso->info_text, "Full drive scan done\n");
1458 Xorriso_info(xorriso,0);
1459
1460 sprintf(xorriso->info_text, "-----------------------------------------------------------------------------\n");
1461 Xorriso_info(xorriso,0);
1462 respt= xorriso->result_line;
1463 for(i= 0; i < (int) drive_count && !(xorriso->request_to_abort); i++) {
1464 if(burn_drive_get_adr(&(drive_list[i]), adr)<=0)
1465 strcpy(adr, "-get_adr_failed-");
1466 Xorriso_process_msg_queues(xorriso,0);
1467 adrpt= adr;
1468 if(flag & 1) {
1469 ret= burn_lookup_device_link(adr, link_adr, "/dev", NULL, 0, 0);
1470 if(ret < 0)
1471 goto ex;
1472 if(ret == 1)
1473 adrpt= link_adr;
1474 }
1475 if((int) strlen(adrpt) > max_dev_len)
1476 max_dev_len= strlen(adrpt);
1477 }
1478 for(i= 0; i < (int) drive_count && !(xorriso->request_to_abort); i++) {
1479 if(burn_drive_get_adr(&(drive_list[i]), adr)<=0)
1480 strcpy(adr, "-get_adr_failed-");
1481 Xorriso_process_msg_queues(xorriso,0);
1482 if(stat(adr,&stbuf)==-1) {
1483 sprintf(perms,"errno=%d",errno);
1484 } else {
1485 strcpy(perms,"------");
1486 if(stbuf.st_mode&S_IRUSR) perms[0]= 'r';
1487 if(stbuf.st_mode&S_IWUSR) perms[1]= 'w';
1488 if(stbuf.st_mode&S_IRGRP) perms[2]= 'r';
1489 if(stbuf.st_mode&S_IWGRP) perms[3]= 'w';
1490 if(stbuf.st_mode&S_IROTH) perms[4]= 'r';
1491 if(stbuf.st_mode&S_IWOTH) perms[5]= 'w';
1492 }
1493 adrpt= adr;
1494 if(flag & 1) {
1495 ret= burn_lookup_device_link(adr, link_adr, "/dev", NULL, 0, 0);
1496 if(ret < 0)
1497 goto ex;
1498 if(ret == 1)
1499 adrpt= link_adr;
1500 }
1501 sprintf(respt, "%d -dev '%s' ", i, adrpt);
1502 pad= max_dev_len-strlen(adrpt);
1503 if(pad>0)
1504 for(j= 0; j<pad; j++)
1505 strcat(respt, " ");
1506 sprintf(respt+strlen(respt), "%s : '%-8.8s' '%s' \n",
1507 perms, drive_list[i].vendor, drive_list[i].product);
1508 Xorriso_result(xorriso,0);
1509 }
1510 sprintf(xorriso->info_text, "-----------------------------------------------------------------------------\n");
1511 Xorriso_info(xorriso,0);
1512
1513 burn_drive_info_free(drive_list);
1514 ret= 1;
1515 ex:;
1516 Xorriso_process_msg_queues(xorriso,0);
1517 Xorriso_free_meM(adr);
1518 Xorriso_free_meM(link_adr);
1519 return(ret);
1520 }
1521
1522
Xorriso_tell_media_space(struct XorrisO * xorriso,int * media_space,int * free_space,int flag)1523 int Xorriso_tell_media_space(struct XorrisO *xorriso,
1524 int *media_space, int *free_space, int flag)
1525 {
1526 int ret;
1527 struct burn_drive_info *dinfo;
1528 struct burn_drive *drive;
1529 struct burn_write_opts *burn_options;
1530
1531 (*free_space)= (*media_space)= 0;
1532
1533 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
1534 "on attempt to -tell_media_space", 2);
1535 if(ret<=0)
1536 return(0);
1537
1538 ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0);
1539 if(ret<=0)
1540 return(-1);
1541 (*free_space)= (*media_space)=
1542 isoburn_disc_available_space(drive, burn_options) / (off_t) 2048;
1543 burn_write_opts_free(burn_options);
1544
1545 if(Xorriso_change_is_pending(xorriso, 0)) {
1546 ret= Xorriso_write_session(xorriso, 1);
1547 if(ret>0) {
1548 (*free_space)-= ret;
1549 } else {
1550 Xorriso_process_msg_queues(xorriso,0);
1551 return(0);
1552 }
1553 }
1554 Xorriso_process_msg_queues(xorriso,0);
1555 return(1);
1556 }
1557
1558
1559 /* @return <=0 error, 1 success
1560 */
Xorriso_list_formats(struct XorrisO * xorriso,int flag)1561 int Xorriso_list_formats(struct XorrisO *xorriso, int flag)
1562 {
1563 int ret, i, status, num_formats, profile_no, type, alloc_blocks, free_blocks;
1564 off_t size;
1565 unsigned dummy;
1566 char status_text[80], profile_name[90], *respt;
1567 struct burn_drive_info *dinfo;
1568 struct burn_drive *drive;
1569
1570 respt= xorriso->result_line;
1571
1572 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
1573 "on attempt to obtain format descriptor list", 1 | 2);
1574 if(ret<=0)
1575 return(0);
1576 if(ret == 2)
1577 goto ex;
1578 ret = burn_disc_get_formats(drive, &status, &size, &dummy,
1579 &num_formats);
1580 if(ret<=0) {
1581 sprintf(xorriso->info_text, "Cannot obtain format list info");
1582 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
1583 ret= 0; goto ex;
1584 }
1585 ret= Xorriso_toc(xorriso, 3);
1586 if(ret<=0)
1587 goto ex;
1588 ret= burn_disc_get_profile(drive, &profile_no, profile_name);
1589 if(ret<=0)
1590 goto ex;
1591
1592 if(status == BURN_FORMAT_IS_UNFORMATTED)
1593 sprintf(status_text, "unformatted, up to %.1f MiB",
1594 ((double) size) / 1024.0 / 1024.0);
1595 else if(status == BURN_FORMAT_IS_FORMATTED) {
1596 if(profile_no==0x12 || profile_no==0x13 || profile_no==0x1a ||
1597 profile_no==0x43)
1598 sprintf(status_text, "formatted, with %.1f MiB",
1599 ((double) size) / 1024.0 / 1024.0);
1600 else
1601 sprintf(status_text, "written, with %.1f MiB",
1602 ((double) size) / 1024.0 / 1024.0);
1603 } else if(status == BURN_FORMAT_IS_UNKNOWN) {
1604 if (profile_no > 0)
1605 sprintf(status_text, "intermediate or unknown");
1606 else
1607 sprintf(status_text, "no media or unknown media");
1608 } else
1609 sprintf(status_text, "illegal status according to MMC-5");
1610 sprintf(respt, "Format status: %s\n", status_text);
1611 Xorriso_result(xorriso,0);
1612 ret= burn_disc_get_bd_spare_info(drive, &alloc_blocks, &free_blocks, 0);
1613 if(ret == 1) {
1614 sprintf(respt, "BD Spare Area: %d blocks consumed, %d blocks available\n",
1615 alloc_blocks - free_blocks, free_blocks);
1616 Xorriso_result(xorriso,0);
1617 }
1618
1619 for (i= 0; i < num_formats; i++) {
1620 ret= burn_disc_get_format_descr(drive, i, &type, &size, &dummy);
1621 if (ret <= 0)
1622 continue;
1623 sprintf(respt, "Format idx %-2d: %2.2Xh , %.fs , %.1f MiB\n",
1624 i, type, ((double) size) / 2048.0, ((double) size) / 1024.0/1024.0);
1625 Xorriso_result(xorriso,0);
1626 }
1627 ret= 1;
1628 ex:;
1629 return(ret);
1630 }
1631
1632
1633 /* @param flag bit0= This is write speed. Consider the existence of
1634 combo drives (e.g. DVD-ROM/CD-RW or BD-ROM/DVD+-RW)
1635 */
Xorriso_choose_speed_factor(struct XorrisO * xorriso,int speed,int profile,struct burn_drive * drive,double * speed_factor,char ** speed_unit,int flag)1636 int Xorriso_choose_speed_factor(struct XorrisO *xorriso,
1637 int speed, int profile,
1638 struct burn_drive *drive,
1639 double *speed_factor, char **speed_unit,
1640 int flag)
1641 {
1642 int i, no_dvd_read= 1, no_dvd_write= 1, no_bd_read= 1, no_bd_write= 1, ret;
1643 int num_profiles, profiles[64];
1644 char is_current[64];
1645
1646 *speed_unit= "D";
1647 *speed_factor= 1385000.0;
1648
1649 if((flag & 1) || profile == 0x00) {
1650 ret= burn_drive_get_all_profiles(drive, &num_profiles,
1651 profiles, is_current);
1652 if(ret > 0) {
1653 for(i= 0; i < num_profiles; i++) {
1654 if(profiles[i] > 0x10 && profiles[i] < 0x30)
1655 no_dvd_read= no_dvd_write= 0;
1656 else if(profiles[i] == 0x10)
1657 no_dvd_read= 0;
1658 else if(profiles[i] > 0x40 && profiles[i] <= 0x43)
1659 no_bd_read= no_bd_write= 0;
1660 else if(profiles[i] == 0x40)
1661 no_bd_read= 0;
1662 }
1663 }
1664 }
1665 if(profile == 0x00) { /* No medium loaded, guess from profile list */
1666 if(flag & 1) {
1667 if(no_bd_write && no_dvd_write)
1668 *speed_unit= "C";
1669 else if(!no_bd_write)
1670 *speed_unit= "B";
1671 } else {
1672 if(no_bd_read && no_dvd_read)
1673 *speed_unit= "C";
1674 else if(!no_bd_read)
1675 *speed_unit= "B";
1676 }
1677 } else if((profile > 0x00 && profile <= 0x0a) ||
1678 (((no_dvd_write && no_bd_write) && (flag & 1)))) {
1679 *speed_unit= "C";
1680 } else if((profile >= 0x40 && profile <= 0x43) &&
1681 !(no_bd_write && (flag & 1))) {
1682 *speed_unit= "B";
1683 }
1684 if((*speed_unit)[0] == 'C')
1685 *speed_factor= 75.0 * 2352.0;
1686 else if((*speed_unit)[0] == 'B')
1687 *speed_factor= 4495625.0;
1688 return(1);
1689 }
1690
1691
1692 /* For sorting the int *speeds array
1693 */
Xorriso__reverse_int_cmp(const void * a,const void * b)1694 int Xorriso__reverse_int_cmp(const void *a, const void *b)
1695 {
1696 int diff;
1697
1698 diff= *((int *) a) - *((int *) b);
1699 if(diff < 0)
1700 return(1);
1701 else if(diff > 0)
1702 return(-1);
1703 return(0);
1704 }
1705
1706
1707 /* @flag bit0= do not issue TOC
1708 bit1= Report about outdev (else indev)
1709 bit2= Report about write speed (else read speed)
1710 @return <=0 error, 1 success
1711 */
Xorriso_list_speeds_sub(struct XorrisO * xorriso,int flag)1712 int Xorriso_list_speeds_sub(struct XorrisO *xorriso, int flag)
1713 {
1714 int ret, high= -1, low= 0x7fffffff, is_cd= 0, i, speed, profile= 0;
1715 int inout_flag, prev_speed= -1, speed_count= 0;
1716 int *speeds= NULL;
1717 char *respt, *speed_unit= "D";
1718 double speed_factor= 1385000.0, cd_factor= 75.0 * 2352;
1719 struct burn_drive_info *dinfo;
1720 struct burn_drive *drive;
1721 struct burn_speed_descriptor *speed_list= NULL, *item, *other;
1722
1723 respt= xorriso->result_line;
1724
1725 inout_flag= (flag & 2);
1726 if(inout_flag && xorriso->out_drive_handle == NULL)
1727 inout_flag= 0;
1728 else if(xorriso->in_drive_handle == NULL)
1729 inout_flag= 2;
1730 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
1731 "on attempt to obtain speed descriptor list",
1732 1 | inout_flag);
1733 if(ret<=0)
1734 return(0);
1735 if(ret == 2)
1736 goto ex;
1737 ret= burn_drive_get_speedlist(drive, &speed_list);
1738 if(ret < 0) {
1739 sprintf(xorriso->info_text, "Cannot obtain speed list info");
1740 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
1741 ret= 0; goto ex;
1742 }
1743 if(!(flag & 1)) {
1744 ret= Xorriso_toc(xorriso, 1 | inout_flag);
1745 if(ret<=0) {
1746 sprintf(xorriso->info_text,
1747 "Cannot obtain overview of drive and media content");
1748 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
1749 ret= 0; goto ex;
1750 }
1751 }
1752
1753 speed_count= 0;
1754 for(item= speed_list; item != NULL; item= item->next)
1755 speed_count++;
1756 if(speed_count > 0)
1757 Xorriso_alloc_meM(speeds, int, speed_count);
1758
1759 speed_count= 0;
1760 for(item= speed_list; item != NULL; item= item->next) {
1761
1762 sprintf(xorriso->info_text,
1763 "read_speed= %5dk , write_speed= %5dk , source= %d",
1764 item->read_speed, item->write_speed, item->source);
1765 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
1766
1767 if(item->source == 1) {
1768 /* CD mode page 2Ah : report only if not same speed by GET PERFORMANCE */
1769 if(!(flag & 4))
1770 continue; /* 2Ah only tells write speed */
1771 for(other= speed_list; other != NULL; other= other->next)
1772 if(other->source == 2 && item->write_speed == other->write_speed)
1773 break;
1774 if(other != NULL)
1775 continue;
1776 }
1777 if(flag & 4) {
1778 if(item->write_speed <= 0)
1779 continue;
1780 speed= item->write_speed;
1781 } else {
1782 if(item->read_speed <= 0)
1783 continue;
1784 speed= item->read_speed;
1785 }
1786 speeds[speed_count]= speed;
1787 if(item->profile_loaded > 0)
1788 profile= item->profile_loaded;
1789 speed_count++;
1790 }
1791
1792 if(speed_count > 0)
1793 qsort(speeds, (size_t) speed_count, sizeof(int), Xorriso__reverse_int_cmp);
1794
1795 if(profile >= 0x08 && profile <= 0x0a)
1796 is_cd= profile;
1797 for(i= 0; i < speed_count; i++) {
1798
1799 speed= speeds[i];
1800 if(speed == prev_speed)
1801 continue;
1802 prev_speed= speed;
1803 if(flag & 4)
1804 sprintf(respt, "Write speed : ");
1805 else
1806 sprintf(respt, "Read speed : ");
1807
1808 Xorriso_choose_speed_factor(xorriso, speed, profile, drive,
1809 &speed_factor, &speed_unit, !!(flag & 4));
1810 sprintf(respt + strlen(respt), " %5dk , %4.1fx%s\n",
1811 speed, ((double) speed) * 1000.0 / speed_factor, speed_unit);
1812 Xorriso_result(xorriso,0);
1813 if(speed > high)
1814 high= speed;
1815 if(speed < low)
1816 low= speed;
1817 }
1818
1819 /* Maybe there is ATIP info (about write speed only) */
1820 if(is_cd && (flag & 4)) {
1821 ret= burn_disc_read_atip(drive);
1822 if(ret < 0)
1823 goto ex;
1824 if(ret > 0) {
1825 for(i= 0; i < 2; i++) {
1826 if(i == 0)
1827 ret= burn_drive_get_min_write_speed(drive);
1828 else
1829 ret= burn_drive_get_write_speed(drive);
1830 if(ret > 0) {
1831 if(ret < low || (i == 0 && ret != low)) {
1832 sprintf(respt, "Write speed l: ");
1833 sprintf(respt + strlen(respt), " %5dk , %4.1fx%s\n",
1834 ret, ((double) ret) * 1000.0 / cd_factor, "C");
1835 Xorriso_result(xorriso,0);
1836 low= ret;
1837 }
1838 if(ret > high || (i == 1 && ret != high)) {
1839 sprintf(respt, "Write speed h: ");
1840 sprintf(respt + strlen(respt), " %5dk , %4.1fx%s\n",
1841 ret, ((double) ret) * 1000.0 / cd_factor, "C");
1842 Xorriso_result(xorriso,0);
1843 high= ret;
1844 }
1845 }
1846 }
1847 }
1848 }
1849 if(high > -1) {
1850 Xorriso_choose_speed_factor(xorriso, low, profile, drive,
1851 &speed_factor, &speed_unit, !!(flag & 4));
1852 if(flag & 4)
1853 sprintf(respt, "Write speed L: ");
1854 else
1855 sprintf(respt, "Read speed L : ");
1856 sprintf(respt + strlen(respt), " %5dk , %4.1fx%s\n",
1857 low, ((double) low) * 1000.0 / speed_factor, speed_unit);
1858 Xorriso_result(xorriso,0);
1859 Xorriso_choose_speed_factor(xorriso, low, profile, drive,
1860 &speed_factor, &speed_unit, !!(flag & 4));
1861 if(flag & 4)
1862 sprintf(respt, "Write speed H: ");
1863 else
1864 sprintf(respt, "Read speed H : ");
1865 sprintf(respt + strlen(respt), " %5dk , %4.1fx%s\n",
1866 high, ((double) high) * 1000.0 / speed_factor, speed_unit);
1867 Xorriso_result(xorriso,0);
1868 ret= burn_drive_get_best_speed(drive, 0, &item, 2);
1869 if(ret > 0 && item != NULL && (flag & 4))
1870 if(item->write_speed != high) {
1871 sprintf(respt, "Write speed 0: %5dk , %4.1fx%s\n",
1872 item->write_speed,
1873 ((double) item->write_speed) * 1000.0 / speed_factor, speed_unit);
1874 Xorriso_result(xorriso,0);
1875 }
1876 } else {
1877 sprintf(xorriso->info_text,
1878 "Could not get any %s speed information from drive",
1879 (flag & 4) ? "write" : "read");
1880 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1881 ret= 2; goto ex;
1882 }
1883 ret= 1;
1884 ex:;
1885 if(speed_list != NULL)
1886 burn_drive_free_speedlist(&speed_list);
1887 Xorriso_free_meM(speeds);
1888 return(ret);
1889 }
1890
1891
Xorriso_list_speeds(struct XorrisO * xorriso,int flag)1892 int Xorriso_list_speeds(struct XorrisO *xorriso, int flag)
1893 {
1894 int ret;
1895
1896 if(xorriso->out_drive_handle == NULL && xorriso->in_drive_handle == NULL) {
1897 Xorriso_msgs_submit(xorriso, 0,
1898 "No drive acquired on attempt to list speeds", 0, "FAILURE", 0);
1899 return(0);
1900 }
1901 if(xorriso->in_drive_handle != NULL) {
1902 ret= Xorriso_list_speeds_sub(xorriso, 0);
1903 if(ret <= 0)
1904 return(ret);
1905 }
1906 if(xorriso->out_drive_handle != NULL &&
1907 xorriso->out_drive_handle != xorriso->in_drive_handle) {
1908 ret= Xorriso_list_speeds_sub(xorriso, 2);
1909 if(ret <= 0)
1910 return(ret);
1911 }
1912 if(xorriso->out_drive_handle != NULL) {
1913 ret= Xorriso_list_speeds_sub(xorriso, 1 | 2 | 4);
1914 if(ret <= 0)
1915 return(ret);
1916 }
1917 return(1);
1918 }
1919
1920
1921 /* @param flag bit0= cdrecord style
1922 bit1= obtain outdrive, else indrive
1923 @return <=0 error, 1 success
1924 */
Xorriso_list_profiles(struct XorrisO * xorriso,int flag)1925 int Xorriso_list_profiles(struct XorrisO *xorriso, int flag)
1926 {
1927 int ret, i;
1928 struct burn_drive_info *dinfo;
1929 struct burn_drive *drive;
1930 int num_profiles, profiles[64];
1931 char is_current[64], profile_name[90], *respt;
1932
1933 respt= xorriso->result_line;
1934
1935 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
1936 "on attempt to obtain profile list", 1 | (flag & 2));
1937 if(ret<=0)
1938 return(0);
1939 burn_drive_get_all_profiles(drive, &num_profiles, profiles, is_current);
1940 for(i= 0; i < num_profiles; i++) {
1941 ret= burn_obtain_profile_name(profiles[i], profile_name);
1942 if(ret <= 0)
1943 strcpy(profile_name, "unknown");
1944 sprintf(respt, "%s 0x%4.4X (%s)%s\n",
1945 flag & 1 ? "Profile:" : "Profile :",
1946 (unsigned int) profiles[i],
1947 profile_name, is_current[i] ? " (current)" : "");
1948 Xorriso_result(xorriso,0);
1949 }
1950 return(1);
1951 }
1952
1953
1954 /* @param flag bit0= -inq
1955 bit1= -checkdrive
1956 */
Xorriso_atip(struct XorrisO * xorriso,int flag)1957 int Xorriso_atip(struct XorrisO *xorriso, int flag)
1958 {
1959 int ret, profile_number= 0, is_bdr_pow= 0;
1960 int num_profiles= 0, profiles[64], i, can_write= 0, pf, no_medium= 0;
1961 char is_current[64];
1962 char *respt, profile_name[80];
1963 double x_speed_max, x_speed_min= -1.0;
1964 struct burn_drive_info *dinfo;
1965 struct burn_drive *drive;
1966 enum burn_disc_status s;
1967 char *manuf= NULL, *media_code1= NULL, *media_code2= NULL;
1968 char *book_type= NULL, *product_id= NULL;
1969
1970 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
1971 "on attempt to print drive and media info", 2);
1972 if(ret<=0)
1973 return(0);
1974 respt= xorriso->result_line;
1975 sprintf(respt, "Device type : ");
1976 ret= burn_drive_get_drive_role(drive);
1977 if(ret==0)
1978 sprintf(respt+strlen(respt), "%s\n", "Emulated (null-drive)");
1979 else if(ret==2)
1980 sprintf(respt+strlen(respt), "%s\n",
1981 "Emulated (stdio-drive, 2k random read-write)");
1982 else if(ret==3)
1983 sprintf(respt+strlen(respt), "%s\n",
1984 "Emulated (stdio-drive, sequential write-only)");
1985 else if(ret == 4)
1986 sprintf(respt+strlen(respt), "%s\n",
1987 "Emulated (stdio-drive, 2k random read-only)");
1988 else if(ret == 5)
1989 sprintf(respt+strlen(respt), "%s\n",
1990 "Emulated (stdio-drive, 2k random write-only)");
1991 else if(ret!=1)
1992 sprintf(respt+strlen(respt), "%s\n","Emulated (stdio-drive)");
1993 else
1994 sprintf(respt+strlen(respt), "%s\n","Removable CD-ROM");
1995 sprintf(respt+strlen(respt), "Vendor_info : '%s'\n",dinfo->vendor);
1996 sprintf(respt+strlen(respt), "Identifikation : '%s'\n",dinfo->product);
1997 sprintf(respt+strlen(respt), "Revision : '%s'\n",dinfo->revision);
1998 Xorriso_result(xorriso,1);
1999 if(flag&1)
2000 return(1);
2001
2002 /* Do not report "Supported modes: SAO TAO" with -ROM drives */
2003 burn_drive_get_all_profiles(drive, &num_profiles, profiles, is_current);
2004 if(num_profiles > 0) {
2005 for(i= 0; i < num_profiles; i++) {
2006 pf= profiles[i];
2007 if(pf == 0x09 || pf == 0x0a || pf == 0x11 || pf == 0x12 || pf == 0x13 ||
2008 pf == 0x14 || pf == 0x15 || pf == 0x1a || pf == 0x1b || pf == 0x2b ||
2009 pf == 0x41 || pf == 0x43 || pf == 0xffff) {
2010 can_write= 1;
2011 break;
2012 }
2013 }
2014 } else
2015 can_write= 1;
2016 if(can_write) {
2017 sprintf(respt, "Driver flags : BURNFREE\n");
2018 sprintf(respt+strlen(respt), "Supported modes: SAO TAO\n");
2019 Xorriso_result(xorriso,1);
2020 } else if(flag & 2) {
2021 sprintf(xorriso->info_text, "Not a CD/DVD/BD recorder");
2022 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
2023 }
2024 if(flag&2)
2025 return(1);
2026
2027 is_bdr_pow= burn_drive_get_bd_r_pow(drive);
2028 s= burn_disc_get_status(drive);
2029 ret= burn_disc_get_profile(drive,&profile_number,profile_name);
2030 if(ret<=0) {
2031 profile_number= 0;
2032 strcpy(profile_name, "-unidentified-");
2033 }
2034 if(s != BURN_DISC_UNSUITABLE) {
2035 ret= burn_disc_read_atip(drive);
2036 if(ret>0) {
2037 ret= burn_drive_get_min_write_speed(drive);
2038 x_speed_min= ((double) ret)/176.4;
2039 }
2040 }
2041 if(s==BURN_DISC_EMPTY) {
2042 sprintf(respt, "Current: none\n");
2043 Xorriso_result(xorriso,1);
2044 sprintf(xorriso->info_text, "No recognizable medium found in drive");
2045 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
2046 no_medium= 1;
2047 } else
2048 sprintf(respt, "Current: %s%s\n",profile_name,
2049 is_bdr_pow ? ", Pseudo Overwrite formatted" : "");
2050 Xorriso_result(xorriso,1);
2051 Xorriso_list_profiles(xorriso, 1 | 2);
2052 if(no_medium)
2053 return(1);
2054 if(strstr(profile_name,"BD")==profile_name) {
2055 printf("Mounted Media: %2.2Xh, %s\n", profile_number, profile_name);
2056 } else if(strstr(profile_name,"DVD")==profile_name) {
2057 sprintf(respt, "book type: %s (emulated booktype)\n", profile_name);
2058 Xorriso_result(xorriso,1);
2059 if(profile_number == 0x13) {
2060 sprintf(respt, "xorriso: message for sdvdbackup: \"(growisofs mode Restricted Overwrite)\"\n");
2061 Xorriso_result(xorriso,1);
2062 }
2063 } else {
2064 sprintf(respt, "ATIP info from disk:\n");
2065 Xorriso_result(xorriso,1);
2066 if(burn_disc_erasable(drive))
2067 sprintf(respt, " Is erasable\n");
2068 else
2069 sprintf(respt, " Is not erasable\n");
2070 Xorriso_result(xorriso,1);
2071 { int start_lba,end_lba,min,sec,fr;
2072 ret= burn_drive_get_start_end_lba(drive,&start_lba,&end_lba,0);
2073 if(ret>0) {
2074 burn_lba_to_msf(start_lba,&min,&sec,&fr);
2075 sprintf(respt, " ATIP start of lead in: %d (%-2.2d:%-2.2d/%-2.2d)\n",
2076 start_lba,min,sec,fr);
2077 Xorriso_result(xorriso,1);
2078 burn_lba_to_msf(end_lba,&min,&sec,&fr);
2079 sprintf(respt, " ATIP start of lead out: %d (%-2.2d:%-2.2d/%-2.2d)\n",
2080 end_lba,min,sec,fr);
2081 Xorriso_result(xorriso,1);
2082 }
2083 }
2084 ret= burn_drive_get_write_speed(drive);
2085 x_speed_max= ((double) ret)/176.4;
2086 if(x_speed_min<0)
2087 x_speed_min= x_speed_max;
2088 sprintf(respt,
2089 " 1T speed low: %.f 1T speed high: %.f\n",x_speed_min,x_speed_max);
2090 Xorriso_result(xorriso,1);
2091 }
2092
2093 ret= burn_disc_get_media_id(drive, &product_id, &media_code1, &media_code2,
2094 &book_type, 0);
2095 if(ret > 0 && media_code1 != NULL && media_code2 != NULL)
2096 manuf= burn_guess_manufacturer(profile_number, media_code1, media_code2, 0);
2097 if(product_id != NULL) {
2098 sprintf(respt, "Product Id: %s\n", product_id);
2099 Xorriso_result(xorriso,1);
2100 }
2101 if(manuf != NULL) {
2102 sprintf(respt, "Producer: %s\n", manuf);
2103 Xorriso_result(xorriso, 1);
2104 }
2105 if(profile_number == 0x09 || profile_number == 0x0a) {
2106 sprintf(respt, "Manufacturer: %s\n", manuf);
2107 Xorriso_result(xorriso, 1);
2108 } else if(product_id != NULL && media_code1 != NULL && media_code2 != NULL){
2109 free(product_id);
2110 free(media_code1);
2111 free(media_code2);
2112 if(book_type != NULL)
2113 free(book_type);
2114 product_id= media_code1= media_code2= book_type= NULL;
2115 ret= burn_disc_get_media_id(drive, &product_id, &media_code1, &media_code2,
2116 &book_type, 1);
2117 if(ret > 0) {
2118 sprintf(respt, "Manufacturer: '%s'\n", media_code1);
2119 Xorriso_result(xorriso, 1);
2120 if(media_code2[0]) {
2121 sprintf(respt, "Media type: '%s'\n", media_code2);
2122 Xorriso_result(xorriso, 1);
2123 }
2124 }
2125 }
2126 if(manuf != NULL)
2127 free(manuf);
2128 if(media_code1 != NULL)
2129 free(media_code1);
2130 if(media_code2 != NULL)
2131 free(media_code2);
2132 if(book_type != NULL)
2133 free(book_type);
2134 if(product_id != NULL)
2135 free(product_id);
2136 return(1);
2137 }
2138
2139
2140 /* @param flag bit1= outdev rather than indev
2141 @return <0 error, 0 = no profile to see , 1= ok , 2= ok, is CD profile
2142 3= ok, is BD profile
2143 */
Xorriso_get_profile(struct XorrisO * xorriso,int * profile_number,char profile_name[80],int flag)2144 int Xorriso_get_profile(struct XorrisO *xorriso, int *profile_number,
2145 char profile_name[80], int flag)
2146 {
2147 int ret;
2148 struct burn_drive_info *dinfo;
2149 struct burn_drive *drive;
2150
2151 *profile_number= 0;
2152 profile_name[0]= 0;
2153 if(((flag&2) && xorriso->out_drive_handle==NULL) ||
2154 ((!(flag&2)) && xorriso->in_drive_handle==NULL))
2155 return(0);
2156 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
2157 "on attempt to determine media type", flag&2);
2158 if(ret<=0)
2159 return(0);
2160 ret=burn_disc_get_profile(drive, profile_number, profile_name);
2161 if(ret<=0)
2162 return(ret);
2163 if(*profile_number==0x08 || *profile_number==0x09 || *profile_number==0x0a)
2164 return(2);
2165 if(*profile_number == 0x40 || *profile_number == 0x41 ||
2166 *profile_number == 0x42 || *profile_number == 0x43)
2167 return(3);
2168 return(0);
2169 }
2170
2171
2172 /* @param flag bit0= grow_overwriteable_iso
2173 bit1= obtain info from outdev
2174 bit2= no need to obtain msc2 (NWA)
2175 */
Xorriso_msinfo(struct XorrisO * xorriso,int * msc1,int * msc2,int flag)2176 int Xorriso_msinfo(struct XorrisO *xorriso, int *msc1, int *msc2, int flag)
2177 {
2178 int ret, dummy, is_bdr_pow= 0;
2179 struct burn_drive *drive;
2180 struct burn_drive_info *dinfo;
2181 enum burn_disc_status disc_state;
2182
2183 *msc1= *msc2= -1;
2184 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
2185 "on attempt to obtain msinfo", flag&2);
2186 if(ret<=0)
2187 return(ret);
2188
2189 is_bdr_pow= burn_drive_get_bd_r_pow(drive);
2190 if(is_bdr_pow) {
2191 Xorriso_process_msg_queues(xorriso,0);
2192 sprintf(xorriso->info_text,
2193 "%s medium is unsuitably POW formatted BD-R. Cannot obtain -msinfo.",
2194 (flag&2) ? "Output" : "Input");
2195 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2196 return(0);
2197 }
2198 if(flag&1)
2199 disc_state= isoburn_disc_get_status(drive);
2200 else
2201 disc_state= burn_disc_get_status(drive);
2202 if(disc_state != BURN_DISC_APPENDABLE &&
2203 !(disc_state == BURN_DISC_FULL && (flag & 4))) {
2204 Xorriso_process_msg_queues(xorriso,0);
2205 if(!(flag & 4)) {
2206 sprintf(xorriso->info_text,
2207 "%s medium is not appendable. Cannot obtain -msinfo.",
2208 (flag&2) ? "Output" : "Input");
2209 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2210 }
2211 return(0);
2212 }
2213 ret= isoburn_disc_get_msc1(drive, msc1);
2214 if(ret<=0) {
2215 Xorriso_process_msg_queues(xorriso,0);
2216 sprintf(xorriso->info_text, "Cannot obtain address of most recent session");
2217 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2218 return(0);
2219 }
2220 if(flag & 4)
2221 return(1);
2222 ret= isoburn_disc_track_lba_nwa(drive, NULL, 0, &dummy, msc2);
2223 if(ret<0) {
2224 Xorriso_process_msg_queues(xorriso,0);
2225 sprintf(xorriso->info_text, "Cannot obtain next writeable address on media");
2226 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2227 return(0);
2228 }
2229 return(1);
2230 }
2231
2232
2233 /* @param flag bit0=input drive
2234 bit1=output drive
2235 bit2= wake up rather than calm down
2236 */
Xorriso_drive_snooze(struct XorrisO * xorriso,int flag)2237 int Xorriso_drive_snooze(struct XorrisO *xorriso, int flag)
2238 {
2239 int in_is_out_too, ret;
2240 struct burn_drive_info *dinfo;
2241 struct burn_drive *drive;
2242
2243 in_is_out_too= (xorriso->in_drive_handle == xorriso->out_drive_handle);
2244 if((flag & 1) && xorriso->in_drive_handle != NULL) {
2245 Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
2246 "on attempt to calm drive", 0);
2247 burn_drive_snooze(drive, !!(flag & 4));
2248 if(in_is_out_too)
2249 {ret= 1; goto ex;}
2250 }
2251 if((flag&2) && xorriso->out_drive_handle!=NULL) {
2252 Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
2253 "on attempt to calm drive", 2);
2254 burn_drive_snooze(drive, !!(flag & 4));
2255 }
2256 ret= 1;
2257 ex:;
2258 Xorriso_process_msg_queues(xorriso,0);
2259 return(ret);
2260 }
2261
2262
2263 /* @param flag bit0= enable SCSI command logging to stderr */
Xorriso_scsi_log(struct XorrisO * xorriso,int flag)2264 int Xorriso_scsi_log(struct XorrisO *xorriso, int flag)
2265 {
2266 if(flag == 0)
2267 burn_set_scsi_logging(0);
2268 else
2269 burn_set_scsi_logging(2|4);
2270 return(1);
2271 }
2272
2273
Xorriso_check_md5_range(struct XorrisO * xorriso,off_t start_lba,off_t end_lba,char md5[16],int flag)2274 int Xorriso_check_md5_range(struct XorrisO *xorriso, off_t start_lba,
2275 off_t end_lba, char md5[16], int flag)
2276 {
2277 int ret;
2278 struct burn_drive_info *dinfo= NULL;
2279 struct burn_drive *drive= NULL;
2280 off_t pos, data_count, to_read;
2281 char *data= NULL, data_md5[16];
2282 void *ctx = NULL;
2283
2284 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
2285 "on attempt to check session MD5 checksum", 0);
2286 if(ret <= 0)
2287 goto ex;
2288
2289 Xorriso_alloc_meM(data, char, 64 * 1024);
2290
2291 ret= iso_md5_start(&ctx);
2292 if(ret <= 0) {
2293 Xorriso_no_malloc_memory(xorriso, NULL, 0);
2294 goto ex;
2295 }
2296 if(xorriso->read_speed != -2)
2297 burn_drive_set_speed(drive, xorriso->read_speed, 0);
2298 Xorriso_process_msg_queues(xorriso,0);
2299 for(pos= start_lba; pos < end_lba; pos+= 32) {
2300 to_read= 32;
2301 if(pos + to_read > end_lba)
2302 to_read= end_lba - pos;
2303 ret= burn_read_data(drive, pos * (off_t) 2048, data,
2304 to_read * (off_t) 2048, &data_count, 0);
2305 if(ret <= 0)
2306 goto ex;
2307 iso_md5_compute(ctx, data, (int) data_count);
2308 xorriso->pacifier_count+= data_count;
2309 xorriso->pacifier_byte_count+= data_count;
2310 Xorriso_pacifier_callback(xorriso, "content bytes read",
2311 xorriso->pacifier_count, 0, "", 8);
2312 }
2313 iso_md5_end(&ctx, data_md5);
2314 ret= 1;
2315 if(! iso_md5_match(md5, data_md5))
2316 ret= 0;
2317 ex:;
2318 Xorriso_process_msg_queues(xorriso,0);
2319 if(ctx != NULL)
2320 iso_md5_end(&ctx, data_md5);
2321 Xorriso_free_meM(data);
2322 return(ret);
2323 }
2324
2325
Xorriso_check_session_md5(struct XorrisO * xorriso,char * severity,int flag)2326 int Xorriso_check_session_md5(struct XorrisO *xorriso, char *severity,
2327 int flag)
2328 {
2329 int ret, i;
2330 IsoImage *image;
2331 uint32_t start_lba, end_lba;
2332 char md5[16], md5_text[33];
2333
2334 ret= Xorriso_get_volume(xorriso, &image, 0);
2335 if(ret<=0)
2336 return(ret);
2337 ret= iso_image_get_session_md5(image, &start_lba, &end_lba, md5, 0);
2338 Xorriso_process_msg_queues(xorriso,0);
2339 if(ret < 0)
2340 return(ret);
2341 if(ret == 0) {
2342 sprintf(xorriso->info_text,
2343 "No session MD5 is recorded with the loaded session");
2344 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
2345 return(0);
2346 }
2347
2348 sprintf(xorriso->info_text, "Checking loaded session by its recorded MD5.\n");
2349 Xorriso_info(xorriso, 0);
2350 for(i= 0; i < 16; i++)
2351 sprintf(md5_text + 2 * i, "%2.2x", ((unsigned char *) md5)[i]);
2352 sprintf(xorriso->result_line,
2353 "Session MD5 %s , LBA %.f , %.f blocks\n",
2354 md5_text, (double) start_lba, (double) end_lba - start_lba);
2355 Xorriso_result(xorriso,0);
2356 ret= Xorriso_check_md5_range(xorriso, (off_t) start_lba, (off_t) end_lba,
2357 md5, 0);
2358 return(ret);
2359 }
2360
2361
Xorriso_check_for_abort(struct XorrisO * xorriso,char * abort_file_path,double post_read_time,double * last_abort_file_time,int flag)2362 int Xorriso_check_for_abort(struct XorrisO *xorriso,
2363 char *abort_file_path,
2364 double post_read_time,
2365 double *last_abort_file_time, int flag)
2366 {
2367 struct stat stbuf;
2368
2369 if(abort_file_path[0] == 0)
2370 return(0);
2371 if(post_read_time - *last_abort_file_time >= 0.1) {
2372 if(stat(abort_file_path, &stbuf) != -1) {
2373 if(stbuf.st_mtime >= xorriso->start_time) {
2374 sprintf(xorriso->info_text,
2375 "-check_media: Found fresh abort_file=%s", abort_file_path);
2376 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
2377 return(1);
2378 }
2379 }
2380 *last_abort_file_time= post_read_time;
2381 }
2382 return(0);
2383 }
2384
2385
2386 struct xorriso_md5_state {
2387
2388 /* Resources */
2389 struct XorrisO *xorriso;
2390 void *ctx;
2391 struct SpotlisT *spotlist;
2392 pthread_mutex_t spot_mutex;
2393
2394 /* Checksum tag cursor */
2395 uint32_t md5_start;
2396 uint32_t next_tag;
2397 int chain_broken;
2398 int in_track_gap;
2399 int was_sb_tag;
2400 int md5_spot_value;
2401 uint32_t md5_spot_lba;
2402
2403 /* Asynchronous operation */
2404
2405 int slave_state; /* Operated by slave
2406 0= not yet started
2407 1= slave is started
2408 2= slave has reached its end
2409 3= slave failed to start
2410 */
2411 int chunk_size;
2412 int num_chunks;
2413 char **chunk;
2414 int *chunk_state; /* 0= content invalid (set by boss at creation time),
2415 1= content readable (set by boss),
2416 2= content was read (set by MD5 slave),
2417 3= end-of-processing (set by boss when done)
2418 */
2419 int *chunk_fill; /* Actual number of valid bytes in chunk */
2420 uint32_t *chunk_lba;
2421 int chunk_w_idx; /* Write index. Operated by boss */
2422 int chunk_r_idx; /* Read index. Operated by MD5 slave */
2423
2424 off_t w_sleeps;
2425 off_t r_sleeps;
2426
2427 };
2428
2429
Xorriso__add_spot(struct xorriso_md5_state * state,int start_lba,int blocks,int quality,int flag)2430 int Xorriso__add_spot(struct xorriso_md5_state *state,
2431 int start_lba, int blocks, int quality, int flag)
2432 {
2433 int ret, uret;
2434
2435 if(state->chunk != NULL) {
2436 ret= pthread_mutex_lock(&(state->spot_mutex));
2437 if(ret != 0)
2438 return(0);
2439 }
2440 ret= Spotlist_add_item(state->spotlist, start_lba, blocks, quality, 0);
2441 if(state->chunk != NULL) {
2442 uret= pthread_mutex_unlock(&(state->spot_mutex));
2443 if(uret != 0 && ret > 0)
2444 ret= 0;
2445 }
2446 return(ret);
2447 }
2448
2449
Xorriso_chunk_md5(struct XorrisO * xorriso,char * data,int to_read,uint32_t from_lba,struct xorriso_md5_state * state,int flag)2450 int Xorriso_chunk_md5(struct XorrisO *xorriso, char *data, int to_read,
2451 uint32_t from_lba, struct xorriso_md5_state *state, int flag)
2452 {
2453 int j, ret= 0, valid, tag_type, decode_ret= 0;
2454 uint32_t lba, pos, range_start, range_size;
2455 char md5[16], tag_md5[16], *tag_type_name= "", *comparison, *sev_text;
2456 void *cloned_ctx= NULL;
2457
2458 for(j= 0; j < to_read; j++) {
2459 lba= j + from_lba;
2460 if(lba < state->md5_start)
2461 continue;
2462 ret= decode_ret= 0;
2463 if(lba > state->md5_start + 16 &&
2464 (state->next_tag == 0 || state->chain_broken || lba == state->next_tag)){
2465 ret= iso_util_decode_md5_tag(data + j * 2048, &tag_type,
2466 &pos, &range_start, &range_size,
2467 &(state->next_tag), tag_md5,
2468 !!state->chain_broken);
2469 decode_ret= ret;
2470 }
2471 valid= (ret == 1 || ret == (int) ISO_MD5_AREA_CORRUPTED) && pos == lba;
2472 if(valid && tag_type == 2 && (lba < state->md5_start + 32 ||
2473 state->in_track_gap)){
2474 tag_type_name= "superblock";
2475 state->was_sb_tag= 1;
2476 if(state->in_track_gap && range_start != state->md5_start &&
2477 range_start < lba && lba - range_start <= (uint32_t) j) {
2478 /* Looking for next session : start computing in hindsight.
2479 Session start and superblock tag are supposed to be in the
2480 same 64 kB chunk.
2481 */
2482 iso_md5_end(&(state->ctx), md5);
2483 ret= iso_md5_start(&(state->ctx));
2484 if(ret < 0) {
2485 Xorriso_no_malloc_memory(xorriso, NULL, 0);
2486 ret= -1; goto ex;
2487 }
2488 iso_md5_compute(&(state->ctx), data + (j - (lba - range_start)) * 2048,
2489 (lba - range_start) * 2048);
2490 state->md5_start= range_start;
2491 state->in_track_gap= 0;
2492 }
2493 } else if(valid && tag_type == 4 && lba < 32) {
2494 tag_type_name= "relocated 64kB superblock";
2495 }else if(valid && tag_type == 3 && state->was_sb_tag) {
2496 tag_type_name= "tree";
2497 }else if(valid && tag_type == 1) {
2498
2499 /* >>> ??? allow this without superblock and tree tag ? */
2500
2501 tag_type_name= "session";
2502 } else {
2503 tag_type_name= "";
2504 }
2505 if (tag_type_name[0]) {
2506 if(range_start != state->md5_start) {
2507 sprintf(xorriso->info_text,
2508 "Found MD5 %s tag which covers different data range", tag_type_name);
2509 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0);
2510 sprintf(xorriso->info_text, " Expected: %u Found: %u",
2511 (unsigned int) state->md5_start, range_start);
2512 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0);
2513 state->chain_broken= 1;
2514 valid= 0;
2515 } else {
2516 ret= iso_md5_clone(state->ctx, &cloned_ctx);
2517 if(ret <= 0) {
2518 Xorriso_no_malloc_memory(xorriso, NULL, 0);
2519 ret= -1; goto ex;
2520 }
2521 iso_md5_end(&cloned_ctx, md5);
2522
2523 if(decode_ret == (int) ISO_MD5_AREA_CORRUPTED) {
2524 comparison= "CORRUPTED";
2525 sev_text= "WARNING";
2526 state->md5_spot_value= Xorriso_read_quality_md5_mismatcH;
2527 state->chain_broken= 1;
2528 } else if(! iso_md5_match(tag_md5, md5)) {
2529 comparison= "NON-MATCHING";
2530 sev_text= "WARNING";
2531 state->md5_spot_value= Xorriso_read_quality_md5_mismatcH;
2532 state->chain_broken= 1;
2533 } else {
2534 comparison= "matching";
2535 sev_text= "UPDATE";
2536 state->md5_spot_value= Xorriso_read_quality_md5_matcH;
2537 }
2538 state->md5_spot_lba= lba;
2539 sprintf(xorriso->info_text,
2540 "Found %s MD5 %s tag: start=%d size=%d",
2541 comparison, tag_type_name, state->md5_start,
2542 lba - state->md5_start);
2543 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, sev_text, 0);
2544 }
2545 if(valid && (tag_type == 1 || (tag_type == 4 && pos == lba && lba < 32))){
2546 if(state->md5_spot_value != Xorriso_read_quality_untesteD &&
2547 Xorriso_read_quality_md5_mismatcH <= xorriso->check_media_bad_limit){
2548 ret= Xorriso__add_spot(state, state->md5_start,
2549 state->md5_spot_lba - state->md5_start, state->md5_spot_value, 0);
2550 if(ret <= 0)
2551 goto ex;
2552 }
2553 state->md5_spot_value= Xorriso_read_quality_untesteD;
2554 state->md5_start = lba + 1;
2555 if(state->md5_start % 32)
2556 state->md5_start= state->md5_start + (32 - (state->md5_start % 32));
2557 state->next_tag= 0;
2558
2559 iso_md5_end(&(state->ctx), md5);
2560 ret= iso_md5_start(&(state->ctx));
2561 if(ret < 0) {
2562 Xorriso_no_malloc_memory(xorriso, NULL, 0);
2563 ret= -1; goto ex;
2564 }
2565 if(tag_type == 1)
2566 state->in_track_gap= 1;
2567 continue;
2568 }
2569 }
2570 iso_md5_compute(state->ctx, data + j * 2048, 2048);
2571 }
2572 ret= 1;
2573 ex:;
2574 return(ret);
2575 }
2576
2577
Xorriso__md5_slave(void * state_pt)2578 static void *Xorriso__md5_slave(void *state_pt)
2579 {
2580 struct xorriso_md5_state *state;
2581 int ret, c_state, c_idx;
2582 static int u_wait= 1;
2583
2584 state= state_pt;
2585 state->slave_state= 1;
2586
2587 while(1) {
2588 c_idx= state->chunk_r_idx;
2589 c_state= state->chunk_state[c_idx];
2590 if(c_state == 1) {
2591 ret= Xorriso_chunk_md5(state->xorriso, state->chunk[c_idx],
2592 state->chunk_fill[c_idx], state->chunk_lba[c_idx],
2593 state, 0);
2594 if(ret <= 0)
2595 goto ex;
2596 state->chunk_state[c_idx]= 2;
2597 state->chunk_r_idx= (c_idx + 1) % state->num_chunks;
2598 } else if(c_state == 3) {
2599 goto ex;
2600 } else {
2601
2602 /* >>> have a timeout ? */;
2603
2604 if(u_wait > 0)
2605 usleep(u_wait);
2606 state->r_sleeps++;
2607 }
2608 }
2609
2610 ex:;
2611 state->slave_state= 2;
2612 return NULL;
2613 }
2614
2615
Xorriso_start_chunk_md5(struct XorrisO * xorriso,struct xorriso_md5_state * state,int flag)2616 int Xorriso_start_chunk_md5(struct XorrisO *xorriso,
2617 struct xorriso_md5_state *state, int flag)
2618 {
2619 int ret, u_wait= 1000;
2620 pthread_attr_t attr;
2621 pthread_attr_t *attr_pt = NULL;
2622 pthread_t thread;
2623
2624 pthread_attr_init(&attr);
2625 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2626 attr_pt= &attr;
2627
2628 ret= pthread_create(&thread, attr_pt, Xorriso__md5_slave, state);
2629 if(ret != 0) {
2630 sprintf(xorriso->info_text,
2631 "-check_media: Cannot create thread for MD5 computation");
2632 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
2633 ret= 0; goto ex;
2634 }
2635
2636 while(state->slave_state != 1) {
2637
2638 /* >>> have a timeout ? */;
2639 /* >>> if this fails set state->slave_state= 3 */
2640
2641 usleep(u_wait);
2642 }
2643 ret= 1;
2644 ex:;
2645 return(ret);
2646 }
2647
2648
Xorriso__wait_chunk_md5(struct xorriso_md5_state * state,int u_wait,int flag)2649 int Xorriso__wait_chunk_md5(struct xorriso_md5_state *state,
2650 int u_wait, int flag)
2651 {
2652 if(state->chunk_state == NULL)
2653 return(1);
2654 while(state->chunk_state[state->chunk_w_idx] == 1) {
2655
2656 /* >>> have a timeout ? */;
2657
2658 usleep(u_wait);
2659 state->w_sleeps++;
2660 }
2661 return(1);
2662 }
2663
2664
Xorriso__wait_slave_md5_end(struct xorriso_md5_state * state,int u_wait,int flag)2665 int Xorriso__wait_slave_md5_end(struct xorriso_md5_state *state,
2666 int u_wait, int flag)
2667 {
2668 while(state->slave_state == 1) {
2669
2670 /* >>> have a timeout ? */;
2671
2672 usleep(u_wait);
2673 }
2674 return(1);
2675 }
2676
2677
Xorriso__end_slave_md5(struct xorriso_md5_state * state,int u_wait,int flag)2678 int Xorriso__end_slave_md5(struct xorriso_md5_state *state,
2679 int u_wait, int flag)
2680 {
2681 int i, ret;
2682
2683 /* Tell slave thread to end */
2684 for(i= 0; i < state->num_chunks; i++) {
2685 ret= Xorriso__wait_chunk_md5(state, 10000, 0);
2686 if(ret <= 0)
2687 return(ret);
2688 state->chunk_state[state->chunk_w_idx]= 3;
2689 state->chunk_w_idx= (state->chunk_w_idx + 1) % state->num_chunks;
2690 }
2691 /* Wait for slave to end */
2692 ret= Xorriso__wait_slave_md5_end(state, 10000, 0);
2693 if(ret <= 0)
2694 return(ret);
2695 return(1);
2696 }
2697
2698
2699 /* @param flag bit0= this is a follow-up session (i.e. on CD: TAO)
2700 bit1= no pacifier messages
2701 bit2= compute stream MD5 and look out for checksum tag
2702 @return <=0 error, 1= done, 2= aborted due to limit
2703 */
Xorriso_check_interval(struct XorrisO * xorriso,struct SpotlisT * spotlist,struct CheckmediajoB * job,int from_lba,int block_count,int read_chunk,int md5_start,int flag)2704 int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist,
2705 struct CheckmediajoB *job,
2706 int from_lba, int block_count, int read_chunk,
2707 int md5_start, int flag)
2708 {
2709 int i, j, ret, total_count= 0, sectors= -1, sector_size= -1, skip_reading;
2710 int prev_quality= -1, quality= -1, retry= 0, profile_no, is_cd= 0;
2711 int eccb_size= 16;
2712 int start_sec, end_sec, first_value, fret, suspect_tao_end= 0;
2713 char profile_name[80];
2714 int start_lba= 0;
2715 struct burn_drive *drive;
2716 struct burn_drive_info *dinfo;
2717 char *data= NULL, *data_pt;
2718 off_t data_count, to_read, read_count= 0, write_amount, skipped_to_read;
2719 double pre_read_time, post_read_time, time_diff, total_time_diff= 0;
2720 double last_abort_file_time= 0;
2721 void *ctx= NULL;
2722 char md5[16];
2723 size_t data_size;
2724 struct xorriso_md5_state state;
2725 int num_chunks, async_md5;
2726 static off_t chunks_limit= 256 * 1024 * 1024;
2727
2728 memset(&state, 0, sizeof(state));
2729 state.chunk= NULL;
2730 state.chunk_state= NULL;
2731 state.chunk_fill= NULL;
2732 state.chunk_lba= NULL;
2733 state.spotlist= spotlist;
2734
2735 if(read_chunk > 1024)
2736 read_chunk= 1024;
2737 else if(read_chunk < 1)
2738 read_chunk= 1;
2739
2740 num_chunks= job->async_chunks;
2741 if(((off_t) num_chunks) * ((off_t) read_chunk) > chunks_limit)
2742 num_chunks= chunks_limit / read_chunk;
2743 async_md5= (num_chunks >= 2);
2744
2745 if(async_md5)
2746 data_size= num_chunks * read_chunk * 2048;
2747 else
2748 data_size= read_chunk * 2048;
2749 Xorriso_alloc_meM(data, char, data_size);
2750 data_pt= data;
2751
2752 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
2753 "on attempt to check media readability",
2754 2 * !!job->use_dev);
2755 if(ret<=0)
2756 goto ex;
2757 ret= burn_disc_get_profile(drive, &profile_no, profile_name);
2758 if(ret > 0) {
2759 if(profile_no >= 0x08 && profile_no <= 0x0a) {
2760 is_cd= 1;
2761 eccb_size= 1;
2762 } else if(profile_no >= 0x40 && profile_no <= 0x43) {
2763 eccb_size= 32;
2764 } else if(burn_drive_get_drive_role(drive) != 1) {
2765 eccb_size= 1;
2766 }
2767 }
2768
2769 if(job->sector_map != NULL) {
2770 Sectorbitmap_get_layout(job->sector_map, §ors, §or_size, 0);
2771 sector_size/= 2048;
2772 }
2773
2774 if(job->retry > 0)
2775 retry= 1;
2776 else if(job->retry == 0 && is_cd)
2777 retry= 1;
2778
2779 if(flag & 4) {
2780 ret= iso_md5_start(&ctx);
2781 if(ret < 0) {
2782 Xorriso_no_malloc_memory(xorriso, NULL, 0);
2783 ret= -1; goto ex;
2784 }
2785 }
2786
2787 state.xorriso= xorriso;
2788 state.ctx= ctx;
2789 state.spotlist= spotlist;
2790 state.md5_start= md5_start;
2791 state.next_tag= 0;
2792 state.chain_broken= 0;
2793 state.in_track_gap= 0;
2794 state.was_sb_tag= 0;
2795 state.md5_spot_value= Xorriso_read_quality_untesteD;
2796 state.md5_spot_lba= 0;
2797 state.slave_state= 0;
2798 state.chunk_size= read_chunk;
2799 if(async_md5) {
2800 state.num_chunks= num_chunks;
2801 Xorriso_alloc_meM(state.chunk, char *, num_chunks);
2802 Xorriso_alloc_meM(state.chunk_state, int, num_chunks);
2803 Xorriso_alloc_meM(state.chunk_fill, int, num_chunks);
2804 Xorriso_alloc_meM(state.chunk_lba, uint32_t, num_chunks);
2805 for(i= 0; i < state.num_chunks; i++) {
2806 state.chunk[i]= data + read_chunk * i * 2048;
2807 state.chunk_state[i]= 0;
2808 state.chunk_fill[i]= 0;
2809 state.chunk_lba[i]= 0;
2810 }
2811 ret= pthread_mutex_init(&(state.spot_mutex), NULL);
2812 if(ret != 0) {
2813 sprintf(xorriso->info_text,
2814 "-check_media: Cannot initialize thread mutex");
2815 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
2816 goto ex;
2817 }
2818 } else
2819 state.num_chunks= 0;
2820 state.chunk_w_idx= 0;
2821 state.chunk_r_idx= 0;
2822 state.w_sleeps= 0;
2823 state.r_sleeps= 0;
2824
2825 if(async_md5) {
2826 ret= Xorriso_start_chunk_md5(xorriso, &state, 0);
2827 if(ret <= 0)
2828 goto ex;
2829 }
2830
2831 if(xorriso->read_speed != -2)
2832 burn_drive_set_speed(drive, xorriso->read_speed, 0);
2833 Xorriso_process_msg_queues(xorriso,0);
2834 start_lba= from_lba;
2835 to_read= read_chunk;
2836 post_read_time= Sfile_microtime(0);
2837 for(i= 0; i < block_count; i+= to_read) {
2838 skip_reading= 0;
2839 ret= Xorriso_check_for_abort(xorriso, job->abort_file_path, post_read_time,
2840 &last_abort_file_time, 0);
2841 if(ret == 1)
2842 goto abort_check;
2843 if(job->item_limit > 0 &&
2844 Spotlist_count(spotlist, 0) + 2 >= job->item_limit) {
2845 sprintf(xorriso->info_text, "-check_media: Reached item_limit=%d",
2846 job->item_limit);
2847 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
2848 goto abort_check;
2849 }
2850 pre_read_time= Sfile_microtime(0);
2851 if(job->time_limit > 0
2852 && job->start_time + job->time_limit < pre_read_time) {
2853 sprintf(xorriso->info_text, "-check_media: Reached time_limit=%d",
2854 job->time_limit);
2855 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
2856 abort_check:;
2857 if(prev_quality >= 0) {
2858 ret= Xorriso__add_spot(&state, start_lba, i + from_lba - start_lba,
2859 prev_quality, 0);
2860 if(ret <= 0)
2861 goto ex;
2862 }
2863 ret= Xorriso__add_spot(&state, i + from_lba, block_count - i,
2864 Xorriso_read_quality_untesteD, 0);
2865 if(ret > 0)
2866 ret= 2;
2867 goto ex;
2868 }
2869
2870 to_read= read_chunk;
2871 skipped_to_read= 0;
2872 suspect_tao_end= 0;
2873 if(i + to_read > block_count)
2874 to_read= block_count - i;
2875 if(is_cd && i + to_read + 2 >= block_count) {
2876 /* Read last 2 blocks of CD track separately, because with TAO tracks
2877 they are always unreadable but with SAO tracks they contain data.
2878 */
2879 if(to_read > 2) {
2880 to_read-= 2;
2881 } else {
2882 if(to_read > 1)
2883 to_read--;
2884 suspect_tao_end= 1;
2885 }
2886 }
2887
2888 if(sector_size == read_chunk && from_lba % read_chunk == 0
2889 && !skip_reading) {
2890 if(Sectorbitmap_is_set(job->sector_map, (i + from_lba) / sector_size, 0)){
2891 quality= Xorriso_read_quality_valiD;
2892 skip_reading= 1;
2893 }
2894 } else if(sector_size > 0 && !skip_reading) {
2895 start_sec= (i + from_lba) / sector_size;
2896 end_sec= (i + to_read + from_lba) / sector_size;
2897 first_value= Sectorbitmap_is_set(job->sector_map, start_sec, 0);
2898 for(j= start_sec; j < end_sec; j++)
2899 if(Sectorbitmap_is_set(job->sector_map, j, 0) != first_value)
2900 break;
2901 to_read= j * sector_size - i - from_lba;
2902 skip_reading= !!first_value;
2903 if(skip_reading)
2904 quality= Xorriso_read_quality_valiD;
2905 }
2906
2907 if(skip_reading) {
2908 pre_read_time= post_read_time= Sfile_microtime(0);
2909 skipped_to_read= to_read;
2910 } else {
2911 data_count= 0;
2912 pre_read_time= Sfile_microtime(0);
2913
2914 if(async_md5) {
2915 ret= Xorriso__wait_chunk_md5(&state, 1, 0);
2916 if(ret <= 0)
2917 goto ex;
2918 data_pt= state.chunk[state.chunk_w_idx];
2919 }
2920 ret= burn_read_data(drive, ((off_t) (i + from_lba)) * (off_t) 2048,
2921 data_pt, to_read * (off_t) 2048, &data_count,
2922 (4 * !retry) | (16 * !!suspect_tao_end));
2923 post_read_time= Sfile_microtime(0);
2924 time_diff= post_read_time - pre_read_time;
2925 total_time_diff+= time_diff;
2926 total_count++;
2927 if(ret <= 0) {
2928 Xorriso_process_msg_queues(xorriso,0);
2929 if(data_count / 2048 < to_read) {
2930 if(data_count > 0 && retry) {
2931 if(prev_quality >= 0) {
2932 ret= Xorriso__add_spot(&state, start_lba,
2933 i + from_lba - start_lba, prev_quality, 0);
2934 if(ret <= 0)
2935 goto ex;
2936 }
2937 ret= Xorriso__add_spot(&state, i + from_lba, data_count / 2048,
2938 Xorriso_read_quality_partiaL, 0);
2939 if(ret <= 0)
2940 goto ex;
2941 start_lba= i + from_lba + data_count / 2048;
2942 if(suspect_tao_end && ret == -3)
2943 prev_quality= Xorriso_read_quality_tao_enD;
2944 else
2945 prev_quality= Xorriso_read_quality_unreadablE;
2946 }
2947 if(suspect_tao_end && ret == -3)
2948 quality= Xorriso_read_quality_tao_enD;
2949 else
2950 quality= Xorriso_read_quality_unreadablE;
2951 if(retry) /* skip one eccb_size */
2952 to_read= data_count / 2048 + eccb_size;
2953
2954 } else { /* (can hardly happen) */
2955 quality= Xorriso_read_quality_partiaL;
2956 }
2957 fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
2958 if(fret<0)
2959 goto ex;
2960 } else {
2961 quality= Xorriso_read_quality_gooD;
2962 if(time_diff > job->slow_threshold_seq && job->slow_threshold_seq > 0 &&
2963 i > 0)
2964 quality= Xorriso_read_quality_sloW;
2965 }
2966
2967 /* MD5 checksumming */
2968 if(ctx != NULL) {
2969 if(async_md5) {
2970 state.chunk_fill[state.chunk_w_idx]= to_read;
2971 state.chunk_lba[state.chunk_w_idx]= i + from_lba;
2972 state.chunk_state[state.chunk_w_idx]= 1;
2973 /* The MD5 thread will call Xorriso_chunk_md5() */
2974
2975 state.chunk_w_idx= (state.chunk_w_idx + 1) % state.num_chunks;
2976 } else {
2977 ret= Xorriso_chunk_md5(xorriso, data_pt, to_read,
2978 (uint32_t) (i + from_lba), &state, 0);
2979 if(ret <= 0)
2980 goto ex;
2981 }
2982 }
2983
2984 write_amount= data_count;
2985 if(data_count > 0) {
2986 read_count+= data_count;
2987 if(job->data_to_limit >= 0 && read_count > job->data_to_limit)
2988 write_amount-= (read_count - job->data_to_limit);
2989 }
2990 if(write_amount > 0) {
2991 if(job->data_to_fd >= 0) {
2992 ret= lseek(job->data_to_fd,
2993 ((off_t) (i + from_lba)) * (off_t) 2048 + job->data_to_offset,
2994 SEEK_SET);
2995 if(ret == -1) {
2996 failed_to_write:;
2997 sprintf(xorriso->info_text, "Cannot write %d bytes to lba %d of ",
2998 (int) data_count, i + from_lba);
2999 Text_shellsafe(job->data_to_path, xorriso->info_text, 1);
3000 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno,
3001 "FAILURE", 0);
3002 {ret= 0; goto ex;}
3003 }
3004 ret= write(job->data_to_fd, data_pt, write_amount);
3005 if(ret == -1)
3006 goto failed_to_write;
3007 }
3008 }
3009 }
3010 if(quality != prev_quality) {
3011 if(prev_quality >= 0) {
3012 ret= Xorriso__add_spot(&state, start_lba,
3013 i + from_lba - start_lba, prev_quality, 0);
3014 if(ret <= 0)
3015 goto ex;
3016 }
3017 start_lba= i + from_lba;
3018 prev_quality= quality;
3019 }
3020 if(!(flag & 2)) {
3021 xorriso->pacifier_count+= to_read - skipped_to_read;
3022 if(post_read_time - xorriso->last_update_time >=
3023 xorriso->pacifier_interval)
3024 Xorriso_pacifier_callback(xorriso, "blocks read",
3025 xorriso->pacifier_count, xorriso->pacifier_total, "",
3026 8 | 16 | (128 * (job->use_dev == 1)));
3027 }
3028 }
3029 if(prev_quality >= 0) {
3030 ret= Xorriso__add_spot(&state, start_lba,
3031 block_count + from_lba - start_lba, prev_quality, 0);
3032 if(ret <= 0)
3033 goto ex;
3034 }
3035
3036 /* <<< for calibration of quality */
3037 if(total_count > 0) {
3038 sprintf(xorriso->info_text, "Xorriso_check_interval: %.1f s / %d = %f",
3039 total_time_diff, total_count, total_time_diff / total_count);
3040 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
3041 }
3042
3043
3044 /* MD5 checksumming : register result */
3045 if(async_md5) {
3046 ret= Xorriso__end_slave_md5(&state, 10000, 0);
3047 if(ret <= 0)
3048 goto ex;
3049 }
3050
3051 /* >>> ??? allow chain_broken to be a match ? */
3052
3053 if(state.next_tag > 0) {
3054 sprintf(xorriso->info_text, "Missing announced MD5 tag: start=%d pos=%d",
3055 state.md5_start, state.next_tag);
3056 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
3057 state.md5_spot_value= Xorriso_read_quality_md5_mismatcH;
3058 state.md5_spot_lba= state.next_tag;
3059 }
3060 if(state.md5_spot_value != Xorriso_read_quality_untesteD) {
3061 ret= Xorriso__add_spot(&state, state.md5_start,
3062 state.md5_spot_lba - state.md5_start, state.md5_spot_value, 0);
3063 if(ret <= 0)
3064 goto ex;
3065 }
3066
3067 ret= 1;
3068 ex:;
3069 if(async_md5) {
3070 Xorriso__end_slave_md5(&state, 10000, 0);
3071 sprintf(xorriso->info_text,
3072 "async_chunks=%d , chunk_size=%ds , w_sleeps: %.f , r_sleeps: %.f",
3073 state.num_chunks, read_chunk, (double) state.w_sleeps,
3074 (double) state.r_sleeps);
3075 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
3076 if(state.chunk != NULL)
3077 pthread_mutex_destroy(&(state.spot_mutex));
3078 Xorriso_free_meM(state.chunk);
3079 Xorriso_free_meM(state.chunk_state);
3080 Xorriso_free_meM(state.chunk_fill);
3081 Xorriso_free_meM(state.chunk_lba);
3082 }
3083 Xorriso_free_meM(data);
3084 if(state.ctx != NULL)
3085 iso_md5_end(&(state.ctx), md5);
3086
3087 return(ret);
3088 }
3089
3090
Xorriso_check_media(struct XorrisO * xorriso,struct SpotlisT ** spotlist,struct CheckmediajoB * job,int flag)3091 int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,
3092 struct CheckmediajoB *job, int flag)
3093 {
3094 int media_blocks= 0, read_chunk= 32, ret, mode, start_lba= 0;
3095 int blocks, os_errno, i, j, last_track_end= -1, track_blocks, track_lba;
3096 int num_sessions, num_tracks, declare_untested= 0, md5_start;
3097 int read_capacity= -1, end_lba, hret, count, quality, profile_no;
3098 int track_bad_claim= 0;
3099 char *toc_info= NULL, profile_name[80], msg[160];
3100 struct burn_drive *drive;
3101 struct burn_drive_info *dinfo;
3102 enum burn_disc_status s;
3103 struct isoburn_toc_disc *isoburn_disc= NULL;
3104 struct isoburn_toc_session **isoburn_sessions;
3105 struct isoburn_toc_track **iso_burn_tracks;
3106 struct burn_toc_entry isoburn_entry;
3107 struct stat stbuf;
3108 struct burn_multi_caps *caps= NULL;
3109
3110 *spotlist= NULL;
3111
3112 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
3113 "on attempt to check media readability",
3114 2 * !!job->use_dev);
3115 if(ret<=0)
3116 goto ex;
3117
3118 ret = burn_disc_get_profile(drive, &profile_no, profile_name);
3119 if(ret <= 0)
3120 profile_no= 0;
3121
3122 if(job->min_block_size != 0)
3123 read_chunk= job->min_block_size;
3124
3125 ret= Spotlist_new(spotlist, 0);
3126 if(ret <= 0)
3127 {ret= -1; goto ex;}
3128
3129 if(job->sector_map_path[0]) {
3130 Sectorbitmap_destroy(&(job->sector_map), 0);
3131 if(stat(job->sector_map_path, &stbuf) != -1) {
3132 ret= Sectorbitmap_from_file(&(job->sector_map), job->sector_map_path,
3133 xorriso->info_text, &os_errno, 0);
3134 if(ret <= 0) {
3135 if(xorriso->info_text[0])
3136 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, os_errno,
3137 "FAILURE", 0);
3138 goto ex;
3139 }
3140 }
3141 Xorriso_toc_to_string(xorriso, &toc_info,
3142 (2 * !!job->use_dev) | (4 * !job->map_with_volid));
3143 }
3144 ret= Xorriso_open_job_data_to(xorriso, job, 0);
3145 if(ret <= 0)
3146 goto ex;
3147 Xorriso_pacifier_reset(xorriso, 0);
3148 job->start_time= time(NULL);
3149 mode= job->mode;
3150 if(job->min_lba > 0) {
3151 start_lba= job->min_lba;
3152 ret= Spotlist_add_item(*spotlist, 0, job->min_lba,
3153 Xorriso_read_quality_untesteD, 0);
3154 if(ret <= 0)
3155 goto ex;
3156 }
3157
3158 s= isoburn_disc_get_status(drive);
3159 if(s != BURN_DISC_APPENDABLE && s != BURN_DISC_FULL) {
3160 Xorriso_msgs_submit(xorriso, 0, "-check_media: No readable medium found",
3161 0, "SORRY", 0);
3162 ret= 0; goto ex;
3163 }
3164
3165 ret= burn_get_read_capacity(drive, &read_capacity, 0);
3166 if(ret <= 0)
3167 read_capacity= -1;
3168
3169 if(job->max_lba >= 0) {
3170 blocks= job->max_lba + 1 - start_lba;
3171 xorriso->pacifier_total= blocks;
3172 ret= Xorriso_check_interval(xorriso, *spotlist, job, start_lba, blocks,
3173 read_chunk, 0, 0);
3174 if(ret <= 0)
3175 goto ex;
3176
3177 } else if(mode == 0) { /* track by track */
3178 isoburn_disc= isoburn_toc_drive_get_disc(drive);
3179 if(isoburn_disc == NULL)
3180 goto libburn_whole_disc;
3181 isoburn_sessions=
3182 isoburn_toc_disc_get_sessions(isoburn_disc, &num_sessions);
3183 for(i= 0; i < num_sessions; i++) {
3184 iso_burn_tracks= isoburn_toc_session_get_tracks(isoburn_sessions[i],
3185 &num_tracks);
3186 for(j= 0; j < num_tracks; j++) {
3187 isoburn_toc_track_get_entry(iso_burn_tracks[j], &isoburn_entry);
3188 if(!(isoburn_entry.extensions_valid & 1)) /* should not happen */
3189 continue;
3190 track_lba= isoburn_entry.start_lba;
3191 track_blocks= isoburn_entry.track_blocks;
3192
3193 /* The last track of an appendable BD-R reports more blocks than the
3194 read capacity allows. All BD-R track sizes are multiple of 64 kB.
3195 */
3196 if (i == num_sessions - 1 &&
3197 (track_lba + track_blocks > read_capacity &&
3198 track_lba + track_blocks < read_capacity + 32 &&
3199 (profile_no == 0x41 || profile_no == 0x40)))
3200 track_blocks= read_capacity - track_lba;
3201 if(track_lba + track_blocks > read_capacity) {
3202 if(track_bad_claim < track_lba + track_blocks)
3203 track_bad_claim= track_lba + track_blocks;
3204 if(track_lba >= read_capacity) {
3205 sprintf(msg, "-check_media: Track %d of session %d begins after end of readable medium area.",
3206 j + 1, i + 1);
3207 Xorriso_msgs_submit(xorriso, 0, msg, 0, "WARNING", 0);
3208 continue;
3209 } else {
3210
3211 if(profile_no >= 0x08 && profile_no <= 0x0a &&
3212 track_lba + track_blocks == read_capacity + 2 &&
3213 i == num_sessions - 1 && j == num_tracks - 1) {
3214 sprintf(msg, "-check_media: Last CD track exceeds readable area by 2 blocks. Assuming TAO.");
3215 Xorriso_msgs_submit(xorriso, 0, msg, 0, "DEBUG", 0);
3216 } else {
3217 sprintf(msg, "-check_media: Track %d of session %d extends over the end of readable medium area.",
3218 j + 1, i + 1);
3219 Xorriso_msgs_submit(xorriso, 0, msg, 0, "WARNING", 0);
3220 }
3221 track_blocks= read_capacity - track_lba;
3222 }
3223 }
3224 md5_start= track_lba;
3225 if(i == 0 && j == 0) {
3226 if(track_lba == 32) {
3227 ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
3228 if(ret > 0) {
3229 if(caps->start_adr) {
3230 /* block 0 to 31 are the overall mount entry of overwriteable */
3231 track_lba= 0;
3232 track_blocks+= 32;
3233 }
3234 }
3235 }
3236 }
3237 if(last_track_end >= 0 && last_track_end < track_lba &&
3238 last_track_end >= start_lba) {
3239 ret= Spotlist_add_item(*spotlist, last_track_end,
3240 track_lba - last_track_end,
3241 Xorriso_read_quality_off_tracK, 0);
3242 if(ret <= 0)
3243 goto ex;
3244 }
3245 last_track_end= track_lba + track_blocks;
3246
3247 if(track_lba < start_lba) {
3248 track_blocks-= start_lba - track_lba;
3249 track_lba= start_lba;
3250 }
3251 if(track_blocks <= 0)
3252 continue;
3253 if(declare_untested) {
3254 ret= Spotlist_add_item(*spotlist, track_lba, track_blocks,
3255 Xorriso_read_quality_untesteD, 0);
3256 if(ret <= 0)
3257 goto ex;
3258 } else {
3259 ret= Xorriso_check_interval(xorriso, *spotlist, job, track_lba,
3260 track_blocks, read_chunk, md5_start,
3261 (i > 0) | (4 * (xorriso->do_md5 & 1)));
3262 if(ret <= 0)
3263 goto ex;
3264 if(ret == 2)
3265 declare_untested= 1;
3266 }
3267 }
3268 }
3269
3270 if(track_bad_claim > read_capacity) {
3271 count= Spotlist_count(*spotlist, 0);
3272 Spotlist_get_item(*spotlist, count - 1, &track_lba, &blocks, &quality, 0);
3273 if(profile_no >= 0x08 && profile_no <= 0x0a &&
3274 track_bad_claim - read_capacity == 2 &&
3275 quality != Xorriso_read_quality_tao_enD)
3276 quality= Xorriso_read_quality_tao_enD;
3277 else
3278 quality= Xorriso_read_quality_unreadablE;
3279 ret= Spotlist_add_item(*spotlist, read_capacity,
3280 track_bad_claim - read_capacity, quality, 0);
3281 if(ret <= 0)
3282 goto ex;
3283 }
3284
3285 } else if(mode == 1) { /* Image range */
3286 /* Default is the emulated disc capacity.
3287 */
3288 isoburn_disc= isoburn_toc_drive_get_disc(drive);
3289 if(isoburn_disc == NULL)
3290 goto libburn_whole_disc;
3291 blocks= media_blocks= isoburn_toc_disc_get_sectors(isoburn_disc);
3292
3293 /* If possible, determine the end address of the loaded ISO image.
3294 */
3295 track_lba= isoburn_get_attached_start_lba(drive);
3296 if(track_lba >= 0) {
3297 ret= isoburn_read_iso_head(drive, track_lba, &track_blocks, NULL, 0);
3298 if(ret > 0) {
3299 blocks= media_blocks= track_lba + track_blocks;
3300 }
3301 }
3302
3303 if(start_lba >= 0)
3304 blocks-= start_lba;
3305 if(media_blocks <= 0)
3306 goto libburn_whole_disc;
3307 xorriso->pacifier_total= blocks;
3308 ret= Xorriso_check_interval(xorriso, *spotlist, job, start_lba, blocks,
3309 read_chunk, 0, (4 * (xorriso->do_md5 & 1)));
3310 if(ret <= 0)
3311 goto ex;
3312 } else if(mode == 2) {
3313 libburn_whole_disc:;
3314 /* single sweep over libburn medium capacity */
3315 ret= burn_get_read_capacity(drive, &blocks, 0);
3316 if(ret <= 0) {
3317 Xorriso_process_msg_queues(xorriso,0);
3318 sprintf(xorriso->info_text, "No content detected on media");
3319 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
3320 {ret= 0; goto ex;}
3321 }
3322 blocks-= start_lba;
3323 xorriso->pacifier_total= blocks;
3324 ret= Xorriso_check_interval(xorriso, *spotlist, job, start_lba, blocks,
3325 read_chunk, 0, (4 * (xorriso->do_md5 & 1)));
3326 if(ret <= 0)
3327 goto ex;
3328 }
3329
3330 Xorriso_pacifier_callback(xorriso, "blocks read",
3331 xorriso->pacifier_count, xorriso->pacifier_total, "",
3332 1 | 8 | 16 | 32 | (128 * (job->use_dev == 1)));
3333 ret= 1;
3334 ex:;
3335
3336 if(job->data_to_fd != -1)
3337 close(job->data_to_fd);
3338 job->data_to_fd= -1;
3339
3340 if(read_capacity >= 0) {
3341 count= Spotlist_count(*spotlist, 0);
3342 end_lba= 0;
3343 for(i= 0; i < count; i++) {
3344 Spotlist_get_item(*spotlist, i, &start_lba, &blocks, &quality, 0);
3345 if(start_lba + blocks > end_lba)
3346 end_lba= start_lba + blocks;
3347 }
3348 if(read_capacity > end_lba) {
3349 hret= Spotlist_add_item(*spotlist, end_lba, read_capacity - end_lba,
3350 Xorriso_read_quality_untesteD, 0);
3351 if(hret < ret)
3352 ret= hret;
3353 }
3354 }
3355
3356 if(ret > 0)
3357 ret= Xorriso_update_in_sector_map(xorriso, *spotlist, read_chunk, job, 0);
3358
3359 if(ret > 0) {
3360 ret= Xorriso_spotlist_to_sectormap(xorriso, *spotlist, read_chunk,
3361 &(job->sector_map), 2);
3362 if(ret > 0 && job->sector_map_path[0]) {
3363 ret= Sectorbitmap_to_file(job->sector_map, job->sector_map_path, toc_info,
3364 xorriso->info_text, &os_errno, 0);
3365 if(ret <= 0) {
3366 if(xorriso->info_text[0])
3367 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, os_errno,
3368 "FAILURE", 0);
3369 }
3370 }
3371 }
3372 if(toc_info != NULL)
3373 free(toc_info);
3374 if(ret <= 0)
3375 Spotlist_destroy(spotlist, 0);
3376 if(caps!=NULL)
3377 burn_disc_free_multi_caps(&caps);
3378 if(isoburn_disc != NULL)
3379 isoburn_toc_disc_free(isoburn_disc);
3380 return(ret);
3381 }
3382
3383
3384 /* @param flag
3385 bit0= if not MMC drive print NOTE and return 2
3386 bit1= obtain outdrive, else indrive
3387 bit4= do not report failure
3388 */
Xorriso_get_drive_handles(struct XorrisO * xorriso,struct burn_drive_info ** dinfo,struct burn_drive ** drive,char * attempt,int flag)3389 int Xorriso_get_drive_handles(struct XorrisO *xorriso,
3390 struct burn_drive_info **dinfo,
3391 struct burn_drive **drive,
3392 char *attempt, int flag)
3393 {
3394 int ret;
3395
3396 if(flag&2)
3397 *dinfo= (struct burn_drive_info *) xorriso->out_drive_handle;
3398 else
3399 *dinfo= (struct burn_drive_info *) xorriso->in_drive_handle;
3400 if(*dinfo==NULL && !(flag & 16)) {
3401 Xorriso_process_msg_queues(xorriso,0);
3402 sprintf(xorriso->info_text, "No %s drive acquired %s",
3403 (flag&2 ? "output" : "input"), attempt);
3404 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
3405 }
3406 if(*dinfo==NULL)
3407 return(0);
3408 *drive= (*dinfo)[0].drive;
3409 if(flag & 1) {
3410 ret= burn_drive_get_drive_role(*drive);
3411 if(ret != 1) {
3412 sprintf(xorriso->info_text,
3413 "Output device is not an MMC drive. Desired operation does not apply.");
3414 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
3415 return(2);
3416 }
3417 }
3418 return((*drive)!=NULL);
3419 }
3420
3421
Xorriso_pretend_full_disc(struct XorrisO * xorriso,int flag)3422 int Xorriso_pretend_full_disc(struct XorrisO *xorriso, int flag)
3423 {
3424 int ret;
3425 struct burn_drive_info *dinfo;
3426 struct burn_drive *drive;
3427
3428 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
3429 "on attempt to let libburn pretend having a closed medium", 2);
3430 if(ret<=0)
3431 return(ret);
3432
3433 ret= isoburn_disc_pretend_full_uncond(drive);
3434 Xorriso_process_msg_queues(xorriso,0);
3435 if(ret <= 0) {
3436 sprintf(xorriso->info_text,
3437 "Failed to let libburn pretend having a closed medium");
3438 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
3439 return(0);
3440 }
3441 return(1);
3442 }
3443
3444
Xorriso_scsi_dev_family(struct XorrisO * xorriso,int flag)3445 int Xorriso_scsi_dev_family(struct XorrisO *xorriso, int flag)
3446 {
3447 burn_preset_device_open(xorriso->drives_exclusive | (xorriso->linux_scsi_dev_family << 2), 0, 0);
3448 return(1);
3449 }
3450
3451
Xorriso_use_immed_bit(struct XorrisO * xorriso,int flag)3452 int Xorriso_use_immed_bit(struct XorrisO *xorriso, int flag)
3453 {
3454 int enable= 1, ret;
3455 struct burn_drive_info *dinfo;
3456 struct burn_drive *drive;
3457
3458 /* It is not an error if no drive is acquired.
3459 Xorriso_drive_aquire() will apply use_immed_bit.
3460 */
3461 ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
3462 "on attempt to control use of Immed bit", 2 | 16);
3463 if(ret<0)
3464 return(ret);
3465 if(ret == 0)
3466 return(1);
3467
3468 if(xorriso->use_immed_bit == -1) {
3469 enable= 0;
3470 } else if(xorriso->use_immed_bit == 1) {
3471 enable= 1;
3472 } else if(xorriso->use_immed_bit == 0) {
3473 /* obtain default value as determined after drive aquiration */
3474 if(xorriso->use_immed_bit_default == 0)
3475 return(1);
3476 enable= (xorriso->use_immed_bit_default > 0);
3477 }
3478 burn_drive_set_immed(drive, enable);
3479 Xorriso_process_msg_queues(xorriso,0);
3480 return(1);
3481 }
3482
3483
3484