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