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