"Fossies" - the Fresh Open Source Software Archive

Member "libisoburn-1.5.4/libisoburn/burn_wrap.c" (8 Jul 2020, 64039 Bytes) of package /linux/misc/libisoburn-1.5.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "burn_wrap.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.4.8_vs_1.5.0.

    1 
    2 /*
    3    cc -g -c \
    4       -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \
    5       burn_wrap.c
    6 */
    7 /* libburn wrappers for libisoburn 
    8 
    9    Copyright 2007 - 2017  Thomas Schmitt, <scdbackup@gmx.net> 
   10    Provided under GPL version 2 or later.
   11 */
   12 
   13 #ifdef HAVE_CONFIG_H
   14 #include "../config.h"
   15 #endif
   16 
   17 /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo 
   18 #define Hardcoded_cd_rW 1
   19 #define Hardcoded_cd_rw_c1     12999
   20 #define Hardcoded_cd_rw_nwA   152660 
   21 */
   22 
   23 #include <stdio.h>
   24 #include <ctype.h>
   25 #include <sys/types.h>
   26 #include <unistd.h>
   27 #include <string.h>
   28 #include <stdlib.h>
   29 #include <sys/stat.h>
   30 #include <fcntl.h>
   31 #include <time.h>
   32 #include <regex.h>
   33 
   34 #ifndef Xorriso_standalonE
   35 
   36 #include <libburn/libburn.h>
   37 #include <libisofs/libisofs.h>
   38 #ifdef Xorriso_with_libjtE
   39 #include <libjte/libjte.h>
   40 #endif
   41 
   42 #else /* ! Xorriso_standalonE */
   43 
   44 #include "../libisofs/libisofs.h"
   45 #include "../libburn/libburn.h"
   46 #ifdef Xorriso_with_libjtE
   47 #include "../libjte/libjte.h"
   48 #endif
   49 
   50 #endif /* Xorriso_standalonE */
   51 
   52 
   53 #include "libisoburn.h"
   54 #include "isoburn.h"
   55 
   56 
   57 /* The global list of isoburn objects. Usually there is only one. */
   58 extern struct isoburn *isoburn_list_start; /* in isoburn.c */
   59 
   60 /* Default values for application provided msgs_submit methods.
   61    To be attached to newly acquired drives.
   62    Storage location is isoburn.c
   63 */
   64 extern int (*libisoburn_default_msgs_submit)
   65     (void *handle, int error_code, char msg_text[],
   66                  int os_errno, char severity[], int flag);
   67 extern void *libisoburn_default_msgs_submit_handle;
   68 extern int libisoburn_default_msgs_submit_flag;
   69 
   70 
   71 static int isoburn_emulate_toc(struct burn_drive *d, int flag);
   72 
   73 
   74 int isoburn_initialize(char msg[1024], int flag)
   75 {
   76  int major, minor, micro, bad_match= 0, no_iso_init= 0;
   77 
   78 
   79 /* First the ugly compile time checks for header version compatibility.
   80    If everything matches, then they produce no C code. In case of mismatch,
   81    intentionally faulty C code will be inserted.
   82 */
   83 
   84 #ifdef iso_lib_header_version_major
   85 /* The minimum requirement of libisoburn towards the libisofs header
   86    at compile time is defined in libisoburn/libisoburn.h :
   87      isoburn_libisofs_req_major
   88      isoburn_libisofs_req_minor
   89      isoburn_libisofs_req_micro
   90    It gets compared against the version macros in libisofs/libisofs.h :
   91      iso_lib_header_version_major
   92      iso_lib_header_version_minor
   93      iso_lib_header_version_micro
   94    If the header is too old then the following code shall cause failure of
   95    libisoburn compilation rather than to allow production of a program with
   96    unpredictable bugs or memory corruption.
   97    The compiler messages supposed to appear in this case are:
   98       error: 'LIBISOFS_MISCONFIGURATION' undeclared (first use in this function)
   99       error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisofs_dot_h_TOO_OLD__SEE_libisoburn_dot_h_AND_burn_wrap_dot_h' undeclared (first use in this function)
  100       error: 'LIBISOFS_MISCONFIGURATION_' undeclared (first use in this function)
  101 */
  102 /* The indentation is an advise of man gcc to help old compilers ignoring */
  103  #if isoburn_libisofs_req_major > iso_lib_header_version_major
  104  #define Isoburn_libisofs_dot_h_too_olD 1
  105  #endif
  106  #if isoburn_libisofs_req_major == iso_lib_header_version_major && isoburn_libisofs_req_minor > iso_lib_header_version_minor
  107  #define Isoburn_libisofs_dot_h_too_olD 1
  108  #endif
  109  #if isoburn_libisofs_req_minor == iso_lib_header_version_minor && isoburn_libisofs_req_micro > iso_lib_header_version_micro
  110  #define Isoburn_libisofs_dot_h_too_olD 1
  111  #endif
  112 
  113 #ifdef Isoburn_libisofs_dot_h_too_olD
  114 LIBISOFS_MISCONFIGURATION = 0;
  115 INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisofs_dot_h_TOO_OLD__SEE_libisoburn_dot_h_AND_burn_wrap_dot_c = 0;
  116 LIBISOFS_MISCONFIGURATION_ = 0;
  117 #endif
  118 
  119 #endif /* iso_lib_header_version_major */
  120 
  121 /* The minimum requirement of libisoburn towards the libburn header
  122    at compile time is defined in libisoburn/libisoburn.h :
  123      isoburn_libburn_req_major
  124      isoburn_libburn_req_minor
  125      isoburn_libburn_req_micro
  126    It gets compared against the version macros in libburn/libburn.h :
  127      burn_header_version_major
  128      burn_header_version_minor
  129      burn_header_version_micro
  130    If the header is too old then the following code shall cause failure of
  131    cdrskin compilation rather than to allow production of a program with
  132    unpredictable bugs or memory corruption.
  133    The compiler messages supposed to appear in this case are:
  134       error: 'LIBBURN_MISCONFIGURATION' undeclared (first use in this function)
  135       error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h' undeclared (first use in this function)
  136       error: 'LIBBURN_MISCONFIGURATION_' undeclared (first use in this function)
  137 */
  138 
  139 /* The indentation is an advise of man gcc to help old compilers ignoring */
  140  #if isoburn_libburn_req_major > burn_header_version_major
  141  #define Isoburn_libburn_dot_h_too_olD 1
  142  #endif
  143  #if isoburn_libburn_req_major == burn_header_version_major && isoburn_libburn_req_minor > burn_header_version_minor
  144  #define Isoburn_libburn_dot_h_too_olD 1
  145  #endif
  146  #if isoburn_libburn_req_minor == burn_header_version_minor && isoburn_libburn_req_micro > burn_header_version_micro
  147  #define Isoburn_libburn_dot_h_too_olD 1
  148  #endif
  149 
  150 #ifdef Isoburn_libburn_dot_h_too_olD
  151 LIBBURN_MISCONFIGURATION = 0;
  152 INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h = 0;
  153 LIBBURN_MISCONFIGURATION_ = 0;
  154 #endif
  155 
  156 
  157 #ifdef Xorriso_with_libjtE
  158 
  159 /* The minimum requirement of libisoburn towards the libjte header
  160    at compile time is the same as the one of a usable libisofs towards libjte.
  161    So the requirement is defined in libisofs/libisofs.h :
  162      iso_libjte_req_major , iso_libjte_req_minor , iso_libjte_req_micro
  163 */
  164  /* The indentation is an advise of man gcc to help old compilers ignoring */
  165  #if iso_libjte_req_major > LIBJTE_VERSION_MAJOR
  166  #define Libisofs_libjte_dot_h_too_olD 1
  167  #endif
  168  #if iso_libjte_req_major == LIBJTE_VERSION_MAJOR && iso_libjte_req_minor > LIBJTE_VERSION_MINOR
  169  #define Libisofs_libjte_dot_h_too_olD 1
  170  #endif
  171  #if iso_libjte_req_minor == LIBJTE_VERSION_MINOR && iso_libjte_req_micro > LIBJTE_VERSION_MICRO
  172  #define Libisofs_libjte_dot_h_too_olD 1
  173  #endif
  174 
  175 #ifdef Libisofs_libjte_dot_h_too_olD
  176 LIBJTE_MISCONFIGURATION = 0;
  177 INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libjte_dot_h_TOO_OLD__SEE_libisofs_dot_h_AND_burn_wrap.c_c = 0;
  178 LIBJTE_MISCONFIGURATION_ = 0;
  179 #endif
  180 
  181 #endif /* Xorriso_with_libjtE */
  182 
  183 
  184 /* End of ugly compile time tests (scroll up for explanation) */
  185 
  186 
  187  msg[0]= 0;
  188 
  189 #ifdef Xorriso_with_libjtE
  190 
  191  libjte__version(&major, &minor, &micro);
  192  sprintf(msg + strlen(msg), "libjte-%d.%d.%d ", major, minor, micro);
  193  if (libjte__is_compatible(LIBJTE_VERSION_MAJOR, LIBJTE_VERSION_MINOR,
  194                                 LIBJTE_VERSION_MICRO, 0)) {
  195    sprintf(msg+strlen(msg), "ok, ");
  196  } else {
  197    sprintf(msg + strlen(msg),
  198            "- TOO OLD -, need at least libjte-%d.%d.%d ,\n",
  199            LIBJTE_VERSION_MAJOR, LIBJTE_VERSION_MINOR,
  200            LIBJTE_VERSION_MICRO);
  201    bad_match= 1;
  202    no_iso_init= 1; /* iso_init() will fail anyway */
  203  }
  204 
  205 #endif /* Xorriso_with_libjtE */
  206 
  207  if(!no_iso_init) {
  208    if(iso_init()<0) {
  209      sprintf(msg+strlen(msg), "Cannot initialize libisofs\n");
  210      return(0);
  211    }
  212  }
  213  iso_lib_version(&major, &minor, &micro);
  214  sprintf(msg+strlen(msg), "libisofs-%d.%d.%d ", major, minor, micro);
  215 #ifdef iso_lib_header_version_major
  216  if(iso_lib_is_compatible(iso_lib_header_version_major,
  217                           iso_lib_header_version_minor,
  218                           iso_lib_header_version_micro)) {
  219    sprintf(msg+strlen(msg), "ok, ");
  220  } else {
  221    sprintf(msg+strlen(msg),"- TOO OLD -, need at least libisofs-%d.%d.%d ,\n",
  222            iso_lib_header_version_major, iso_lib_header_version_minor,
  223            iso_lib_header_version_micro);
  224    bad_match= 1;
  225  }
  226 #else
  227  if(iso_lib_is_compatible(isoburn_libisofs_req_major,
  228                           isoburn_libisofs_req_minor,
  229                           isoburn_libisofs_req_micro)) {
  230    sprintf(msg+strlen(msg), "suspicious, ");
  231  } else {
  232    sprintf(msg+strlen(msg),"- TOO OLD -, need at least libisofs-%d.%d.%d ,\n",
  233            isoburn_libisofs_req_major, isoburn_libisofs_req_minor,
  234            isoburn_libisofs_req_micro);
  235    bad_match= 1;
  236  }
  237 #endif /* ! iso_lib_header_version_major */
  238 
  239  if(!burn_initialize()) {
  240    sprintf(msg+strlen(msg), "Cannot initialize libburn\n");
  241    return(0);
  242  }
  243 
  244  burn_version(&major, &minor, &micro);
  245  sprintf(msg+strlen(msg), "libburn-%d.%d.%d ", major, minor, micro);
  246  if(major > burn_header_version_major
  247     || (major == burn_header_version_major
  248         && (minor > burn_header_version_minor
  249             || (minor == burn_header_version_minor
  250                 && micro >= burn_header_version_micro)))) {
  251    sprintf(msg+strlen(msg), "ok, ");
  252  } else {
  253    sprintf(msg+strlen(msg), "- TOO OLD -, need at least libburn-%d.%d.%d ,\n",
  254            burn_header_version_major, burn_header_version_minor,
  255            burn_header_version_micro);
  256    bad_match= 1;
  257  }
  258 
  259  isoburn_version(&major, &minor, &micro);
  260  sprintf(msg+strlen(msg), "for libisoburn-%d.%d.%d", major, minor, micro);
  261  if(bad_match)
  262    return(0);
  263 
  264  isoburn_destroy_all(&isoburn_list_start, 0); /* isoburn_list_start= NULL */
  265  return(1);
  266 }
  267 
  268 
  269 /* API @since 0.1.0 */
  270 int isoburn_libisofs_req(int *major, int *minor, int *micro)
  271 {
  272  *major= iso_lib_header_version_major;
  273  *minor= iso_lib_header_version_minor;
  274  *micro= iso_lib_header_version_micro;
  275  return(1);
  276 }
  277 
  278 
  279 /* API @since 0.1.0 */
  280 int isoburn_libburn_req(int *major, int *minor, int *micro)
  281 {
  282  *major= burn_header_version_major;
  283  *minor= burn_header_version_minor;
  284  *micro= burn_header_version_micro;
  285  return(1);
  286 }
  287 
  288 
  289 /* API @since 0.6.4 */
  290 int isoburn_libjte_req(int *major, int *minor, int *micro)
  291 {
  292 #ifdef Xorriso_with_libjtE
  293  *major= LIBJTE_VERSION_MAJOR;
  294  *minor= LIBJTE_VERSION_MINOR;
  295  *micro= LIBJTE_VERSION_MICRO;
  296 #else
  297  *major= *minor= *micro= 0;
  298 #endif /* ! Xorriso_with_libjtE */
  299  return(1);
  300 }
  301 
  302 
  303 int isoburn_set_msgs_submit(int (*msgs_submit)(void *handle, int error_code,
  304                                                char msg_text[], int os_errno,
  305                                                char severity[], int flag),
  306                                void *submit_handle, int submit_flag, int flag)
  307 {
  308  libisoburn_default_msgs_submit= msgs_submit;
  309  libisoburn_default_msgs_submit_handle= submit_handle;
  310  libisoburn_default_msgs_submit_flag= submit_flag;
  311  return(1);
  312 }
  313 
  314 
  315 int isoburn_is_intermediate_dvd_rw(struct burn_drive *d, int flag)
  316 {
  317  int profile, ret= 0, format_status, num_formats;
  318  char profile_name[80];
  319  enum burn_disc_status s;
  320  off_t format_size= -1;
  321  unsigned bl_sas;
  322 
  323  s= isoburn_disc_get_status(d);
  324  ret= burn_disc_get_profile(d, &profile, profile_name);
  325  if(ret>0 && profile==0x13)
  326    ret= burn_disc_get_formats(d, &format_status, &format_size,
  327                               &bl_sas, &num_formats);
  328  if(ret>0 && profile==0x13 && s==BURN_DISC_BLANK &&
  329     format_status==BURN_FORMAT_IS_UNKNOWN)
  330    return(1);
  331  return(0);
  332 }
  333 
  334 
  335 /** Examines the medium and sets appropriate emulation if needed.
  336     @param flag bit0= pretent blank on overwritable media
  337                 bit3= if the drive reports a -ROM profile then try to read 
  338                       table of content by scanning for ISO image headers.
  339                 bit4= do not emulate TOC on overwritable media
  340                 bit5= ignore ACL from external filesystems
  341                 bit6= ignore POSIX Extended Attributes from external filesystems
  342                 bit7= pretend -ROM and scan for table of content
  343                 bit9= when scanning for ISO 9660 sessions on overwritable
  344                       media: Do not demand a valid superblock at LBA 0
  345                       and scan until end of medium.
  346                bit10= if not bit6: accept all xattr namespaces from external 
  347                                    filesystems, not only "user.".
  348 */ 
  349 static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d,
  350                                  int flag)
  351 {
  352  int ret, profile, readonly= 0, role, random_access;
  353  int emulation_started= 0;
  354  struct burn_multi_caps *caps= NULL;
  355  struct isoburn_toc_entry *t;
  356  char profile_name[80];
  357  struct isoburn_toc_disc *disc= NULL;
  358  struct isoburn_toc_session **sessions;
  359  struct isoburn_toc_track **tracks;
  360  int num_sessions= 0, num_tracks= 0, track_count= 0, session_no= 0;
  361  char msg[80];
  362  enum burn_disc_status s;
  363 
  364 #ifndef Hardcoded_cd_rW
  365  int lba, nwa;
  366 #endif
  367 
  368  s= burn_disc_get_status(d);
  369  profile_name[0]= 0;
  370  ret= burn_disc_get_profile(d, &profile, profile_name);
  371  if(ret<=0)
  372    profile= 0x00;
  373  ret= burn_disc_get_multi_caps(d, BURN_WRITE_NONE, &caps, 0);
  374  if(ret<0) /*== 0 is read-only medium, but it is too early to reject it here */
  375    goto ex;
  376  if(ret==0 || (flag & 128))
  377    readonly= 1;
  378  if(flag & 128)
  379    flag = (flag & ~ 16) | 8;
  380 
  381  ret= isoburn_find_emulator(o, d, 0);
  382  if(ret >= 0 && *o != NULL)
  383    isoburn_destroy(o, 0);
  384  ret= isoburn_new(o, 0);
  385  if(ret<=0)
  386    goto ex;
  387  (*o)->drive= d;
  388  (*o)->msgs_submit= libisoburn_default_msgs_submit;
  389  (*o)->msgs_submit_handle= libisoburn_default_msgs_submit_handle;
  390  (*o)->msgs_submit_flag= libisoburn_default_msgs_submit_flag;
  391  iso_image_set_ignore_aclea((*o)->image,
  392                             ((flag >> 5 ) & 3) | ((!!(flag & 1024)) << 3));
  393 
  394 #ifdef Hardcoded_cd_rW
  395  /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
  396  caps->start_adr= 0;
  397  (*o)->fabricated_disc_status= BURN_DISC_APPENDABLE;
  398 #endif
  399 
  400  role= burn_drive_get_drive_role(d);
  401  random_access= caps->start_adr || role == 4;
  402  if(random_access)
  403    (*o)->emulation_mode= 1;
  404  if(random_access && !readonly) {       /* set emulation to overwritable */
  405    ret= isoburn_is_intermediate_dvd_rw(d, 0);
  406    if(ret>0) {
  407      (*o)->min_start_byte= 0;
  408      (*o)->nwa= 0;
  409      (*o)->zero_nwa= 0;
  410    }
  411    if((flag & 1) && role != 4 && role != 5) {
  412      (*o)->nwa= (*o)->zero_nwa;
  413      (*o)->fabricated_disc_status= BURN_DISC_BLANK;
  414    } else {
  415      ret= isoburn_start_emulation(*o, 0);
  416      if(ret<=0) {
  417        (*o)->emulation_mode= -1;
  418        goto ex;
  419      }
  420      emulation_started= 1;
  421      /* try to read emulated toc */
  422      ret= isoburn_emulate_toc(d, (flag & 16) | ((!!(flag & 512)) << 1));
  423      if(ret<0) {
  424        (*o)->emulation_mode= -1;
  425        goto ex;
  426      }
  427    }
  428  } else {
  429 
  430     /* >>> recognize unsuitable media (but allow read-only media) */;
  431 
  432    if(readonly && s != BURN_DISC_EMPTY) {
  433 
  434      /* >>> ts B10712: This maps BURN_DISC_UNSUITABLE to BURN_DISC_FULL
  435                        which can hardly be correct in general.
  436         ??? What reason does this have ?
  437      */
  438      (*o)->fabricated_disc_status= BURN_DISC_FULL;
  439 
  440      /* This might be an overwritable medium in a -ROM drive.
  441         Pitfall:
  442         Multi-session media which bear a xorriso image for overwritables
  443         in their first session would get a TOC of that first image rather
  444         than of the medium.
  445         It is not possible to distinguish a BD-RE from a single session
  446         BD-R with an image for overwritables. But as soon as the medium
  447         bears 2 logical tracks it cannot be overwritable.
  448         So count the number of tracks first.
  449      */
  450      disc= isoburn_toc_drive_get_disc(d);
  451      if(disc != NULL) {
  452        sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions);
  453        for(session_no= 0; session_no < num_sessions; session_no++) {
  454          tracks= isoburn_toc_session_get_tracks(sessions[session_no],
  455                                                 &num_tracks);
  456          if(tracks != NULL)
  457            track_count+= num_tracks;
  458        }
  459        isoburn_toc_disc_free(disc);
  460      }
  461 
  462      sprintf(msg, "ROM medium has libburn track count = %d", track_count);
  463      isoburn_msgs_submit(*o, 0x00060000, msg, 0, "DEBUG", 0);
  464 
  465      if((flag & 16) || track_count >= 2) {
  466        ret= 0; /* toc emulation off, or not overwritable */
  467      } else {
  468        ret= isoburn_start_emulation(*o, 1);
  469        if(ret<=0) {
  470          (*o)->emulation_mode= -1;
  471          goto ex;
  472        }
  473        emulation_started= 1;
  474        ret= isoburn_emulate_toc(d, 1 | ((!!(flag & 512)) << 1));
  475        if(ret<0)
  476          goto ex;
  477        else if(ret > 0)
  478          (*o)->emulation_mode= 1;
  479      }
  480      if(ret == 0 && (profile != 0x08 || (flag & 128)) && (flag & 8)) {
  481        /* This might also be multi-session media which do not
  482           get shown with a decent TOC.
  483           CD-R TOC (profile 0x08) can be trusted. Others not.
  484           Do a scan search of ISO headers.
  485        */
  486        if(!emulation_started) {
  487          ret= isoburn_start_emulation(*o, 1);
  488          if(ret<=0) {
  489            (*o)->emulation_mode= -1;
  490            goto ex;
  491          }
  492        }
  493        ret= isoburn_emulate_toc(d, 1 | 2);
  494        if(ret<0)
  495          goto ex;
  496        if(ret>0) { /* point msc1 to last session */
  497          if((*o)->toc!=NULL) {
  498            for(t= (*o)->toc; t->next!=NULL; t= t->next)
  499              ; /* clang wants newline in empty loops */
  500            (*o)->fabricated_msc1= t->start_lba;
  501          }
  502        }
  503      }
  504    }
  505 #ifdef Hardcoded_cd_rW
  506    (*o)->nwa= Hardcoded_cd_rw_nwA;
  507 #else
  508    ret= burn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa);
  509    if(ret>0)
  510      (*o)->nwa= nwa;
  511    if((*o)->nwa < (*o)->zero_nwa)
  512      (*o)->zero_nwa= 0;
  513 #endif
  514 
  515  }
  516 
  517  ret= 1;
  518 ex:
  519  if(caps!=NULL)
  520    burn_disc_free_multi_caps(&caps);
  521  return(ret);
  522 }
  523 
  524 
  525 /**
  526     @param flag bit0= load
  527                 bit1= regard overwritable media as blank
  528                 bit2= if the drive is a regular disk file: truncate it to
  529                       the write start address
  530                 bit3= if the drive reports a -ROM profile then try to read 
  531                       table of content by scanning for ISO image headers.
  532                       (depending on media type and drive state this might 
  533                        help or it might make the resulting toc even worse)
  534                 bit4= do not emulate TOC on overwritable media
  535                 bit5= ignore ACL from external filesystems
  536                 bit6= ignore POSIX Extended Attributes from external filesystems
  537                 bit7= pretend -ROM profile and scan for table of content
  538                 bit8= re-assess (*drive_infos)[0] rather than acquiring adr
  539                 bit9= when scanning for ISO 9660 sessions on overwritable
  540                       media: Do not demand a valid superblock at LBA 0
  541                       and scan until end of medium.
  542                bit10= if not bit6: accept all xattr namespaces from external
  543                                    filesystems, not only "user.".
  544 */
  545 int isoburn_drive_aquire(struct burn_drive_info *drive_infos[],
  546                          char *adr, int flag)
  547 {
  548  int ret, drive_grabbed= 0;
  549  struct isoburn *o= NULL;
  550  int conv_ret;
  551  char *libburn_drive_adr= NULL;
  552 
  553  /* Should be obsolete by new drive addressing of libburn-0.5.2 */
  554  /* but helps with kernel 2.4 to use /dev/sr */
  555  libburn_drive_adr= calloc(1, BURN_DRIVE_ADR_LEN);
  556  if(libburn_drive_adr == NULL)
  557    {ret= -1; goto ex;}
  558  conv_ret= burn_drive_convert_fs_adr(adr, libburn_drive_adr);
  559  if(conv_ret<=0)
  560    strcpy(libburn_drive_adr, adr);
  561 
  562  if(flag & 256)
  563    ret= burn_drive_re_assess((*drive_infos)[0].drive, 0);
  564  else
  565    ret= burn_drive_scan_and_grab(drive_infos, libburn_drive_adr, flag&1);
  566  if(ret<=0)
  567    goto ex;
  568  drive_grabbed= 1;
  569  ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive,
  570                             (flag & (8 | 16 | 32 | 64 | 128 | 512 | 1024)) |
  571                             !!(flag&2));
  572  if(ret<=0)
  573    goto ex;
  574 
  575  if(flag&4) {
  576    ret= isoburn_find_emulator(&o, (*drive_infos)[0].drive, 0);
  577    if(ret>0 && o!=NULL)
  578      o->truncate= 1;
  579  }
  580 
  581  ret= 1;
  582 ex:
  583  if(ret<=0) {
  584    if(drive_grabbed)
  585      burn_drive_release((*drive_infos)[0].drive, 0);
  586    isoburn_destroy(&o, 0);
  587  }
  588  if(libburn_drive_adr != NULL)
  589    free(libburn_drive_adr);
  590  return(ret);
  591 }
  592 
  593 
  594 int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[],
  595                                 char *adr, int load)
  596 {
  597  int ret;
  598 
  599  ret= isoburn_drive_aquire(drive_infos, adr, !!load);
  600  return(ret);
  601 }
  602 
  603 
  604 int isoburn_drive_grab(struct burn_drive *drive, int load)
  605 {
  606  int ret;
  607  struct isoburn *o= NULL;
  608 
  609  ret= burn_drive_grab(drive, load);
  610  if(ret<=0)
  611    goto ex;
  612  ret= isoburn_welcome_media(&o, drive, 0);
  613  if(ret<=0)
  614    goto ex;
  615  
  616  ret= 1;
  617 ex:
  618  if(ret<=0)
  619    isoburn_destroy(&o,0);
  620  return(ret);
  621 }
  622 
  623 
  624 /** Retrieve medium emulation and eventual isoburn emulator of drive.
  625     @return -1 unsuitable medium, 0 generic medium, 1 emulated medium.
  626 */
  627 int isoburn_find_emulator(struct isoburn **pt,
  628                                  struct burn_drive *drive, int flag)
  629 {
  630  int ret;
  631 
  632  ret= isoburn_find_by_drive(pt, drive, 0);
  633  if(ret<=0)
  634    return(0);
  635  if((*pt)->emulation_mode==-1) {
  636    isoburn_msgs_submit(*pt, 0x00060000,
  637                     "Unsuitable drive and medium state", 0, "FAILURE", 0);
  638    return(-1);
  639  }
  640  if((*pt)->emulation_mode==0)
  641    return(0);
  642  return(1);
  643 } 
  644 
  645 
  646 enum burn_disc_status isoburn_disc_get_status(struct burn_drive *drive)
  647 {
  648  int ret;
  649  struct isoburn *o;
  650 
  651  ret= isoburn_find_emulator(&o, drive, 0);
  652  if(ret<0)
  653    return(BURN_DISC_UNSUITABLE);
  654  if(o!=NULL)
  655    if(o->fabricated_disc_status!=BURN_DISC_UNREADY)
  656      return(o->fabricated_disc_status);
  657  if(ret==0)
  658    return(burn_disc_get_status(drive));
  659 
  660  /* emulated status */
  661  if(o->emulation_mode==-1)
  662    return(BURN_DISC_UNSUITABLE);
  663  if(o->nwa>o->zero_nwa)
  664    return(BURN_DISC_APPENDABLE);
  665  return(BURN_DISC_BLANK);
  666 }
  667 
  668 
  669 int isoburn_disc_pretend_full_uncond(struct burn_drive *drive)
  670 {
  671  int ret;
  672  struct isoburn *o;
  673 
  674  ret= isoburn_find_emulator(&o, drive, 0);
  675  if(ret > 0 && o != NULL)
  676    o->fabricated_disc_status= BURN_DISC_FULL;
  677  ret= burn_disc_pretend_full_uncond(drive);
  678  return(ret);
  679 }
  680 
  681 
  682 int isoburn_disc_erasable(struct burn_drive *d)
  683 {
  684  int ret;
  685  struct isoburn *o;
  686 
  687  ret= isoburn_find_emulator(&o, d, 0);
  688  if(ret>0)
  689    if(o->emulation_mode==1)
  690      return(1);
  691  return burn_disc_erasable(d);
  692 }
  693 
  694 
  695 static int isoburn_is_overwritable(struct burn_drive *drive, int flag)
  696 {
  697  char name[80];
  698  int profile, ret;
  699  
  700  ret= burn_disc_get_profile(drive, &profile, name);
  701  if(ret <= 0)
  702    return(0);
  703  if(profile == 0x12 || profile == 0x13 || profile == 0x1a || profile == 0x43)
  704    return(1);
  705  return(0);
  706  
  707 }
  708 
  709 
  710 void isoburn_disc_erase(struct burn_drive *drive, int fast)
  711 {
  712  int ret, do_pseudo_blank= 0, role;
  713  struct isoburn *o;
  714  enum burn_disc_status s;
  715  char *zero_buffer= NULL;
  716  struct burn_multi_caps *caps= NULL;
  717 
  718  zero_buffer= calloc(1, Libisoburn_target_head_sizE);
  719  if(zero_buffer == NULL) {
  720    /* To cause a negative reply with burn_drive_wrote_well() */
  721    burn_drive_cancel(drive);
  722    goto ex;
  723  }
  724 
  725  ret= isoburn_find_emulator(&o, drive, 0);
  726  if(ret>0) {
  727    if(o->emulation_mode==-1) {
  728      /* To cause a negative reply with burn_drive_wrote_well() */
  729      burn_drive_cancel(drive);
  730      goto ex;
  731    }
  732    role = burn_drive_get_drive_role(drive);
  733    if (role == 5) {
  734      /* libburn will truncate the random-access write-only file
  735         to zero size and change its state */
  736      burn_disc_erase(drive, fast);
  737      o->fabricated_disc_status= burn_disc_get_status(drive);
  738      o->nwa= o->zero_nwa= 0;
  739      goto ex;
  740    }
  741    if(o->emulation_mode > 0) { /* might be readonly with emulated sessions */
  742      ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
  743      if(ret <= 0) /* Maybe because of burn_disc_pretend_full() */
  744        do_pseudo_blank= isoburn_is_overwritable(drive, 0); /* known profiles */
  745      else if(caps->start_adr)
  746        do_pseudo_blank= 1;
  747    }
  748    if(do_pseudo_blank) {
  749      s= isoburn_disc_get_status(drive);
  750      if(s==BURN_DISC_FULL) { /* unknown data format in first 64 kB */
  751        memset(zero_buffer, 0, Libisoburn_target_head_sizE);
  752        ret= burn_random_access_write(drive, (off_t) 0, zero_buffer,
  753                                      (off_t) Libisoburn_target_head_sizE, 1);
  754      } else {
  755        ret= isoburn_invalidate_iso(o, 0);
  756      }
  757      if(ret<=0)
  758        burn_drive_cancel(drive); /* mark run as failure */
  759      goto ex;
  760    }
  761  }
  762  burn_disc_erase(drive, fast);
  763 ex:;
  764  if(caps!=NULL)
  765    burn_disc_free_multi_caps(&caps);
  766  if(zero_buffer != NULL)
  767    free(zero_buffer);
  768 }
  769 
  770 
  771 off_t isoburn_disc_available_space(struct burn_drive *d,
  772                                    struct burn_write_opts *opts)
  773 {
  774  int ret;
  775  struct isoburn *o;
  776  struct burn_write_opts *eff_opts= NULL, *local_opts= NULL;
  777  enum burn_disc_status s;
  778  off_t avail;
  779 
  780  eff_opts= opts;
  781  ret= isoburn_find_emulator(&o, d, 0);
  782  if(ret>0 && o!=NULL)
  783    if(o->emulation_mode!=0) {
  784      s= isoburn_disc_get_status(d);
  785      if(s==BURN_DISC_FULL) /* unknown data format in first 64 kB */
  786        return((off_t) 0);
  787      local_opts= burn_write_opts_new(d);
  788      eff_opts= local_opts;
  789      burn_write_opts_set_start_byte(eff_opts, ((off_t) o->nwa) * (off_t) 2048);
  790    }
  791  avail= burn_disc_available_space(d, eff_opts);
  792  if(local_opts!=NULL)
  793    burn_write_opts_free(local_opts);
  794  local_opts= NULL;
  795  return(avail);
  796 }
  797 
  798 
  799 int isoburn_disc_get_msc1(struct burn_drive *d, int *start_lba)
  800 {
  801  int ret;
  802  struct isoburn *o;
  803 
  804 #ifdef Hardcoded_cd_rW
  805  /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
  806  *start_lba= Hardcoded_cd_rw_c1;
  807  return(1);
  808 #endif
  809 
  810  if(isoburn_disc_get_status(d)!=BURN_DISC_APPENDABLE &&
  811     isoburn_disc_get_status(d)!=BURN_DISC_FULL) {
  812    isoburn_msgs_submit(NULL, 0x00060000,
  813                        "Medium contains no recognizable data", 0, "SORRY", 0);
  814    return(0);
  815  }
  816  ret= isoburn_find_emulator(&o, d, 0);
  817  if(ret<0)
  818    return(0);
  819  if(o->fabricated_msc1>=0) {
  820    *start_lba= o->fabricated_msc1;
  821    return(1);
  822  }
  823  if(ret>0) if(o->emulation_mode>0) {
  824    *start_lba= 0;
  825    return(1);
  826  }
  827  return(burn_disc_get_msc1(d, start_lba));
  828 }
  829 
  830 
  831 int isoburn_disc_track_lba_nwa(struct burn_drive *d,
  832                                struct burn_write_opts *opts,
  833                                int trackno, int *lba, int *nwa)
  834 {
  835  int ret;
  836  struct isoburn *o;
  837  enum burn_disc_status s;
  838 
  839 #ifdef Hardcoded_cd_rW
  840  /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
  841  *lba= Hardcoded_cd_rw_c1;
  842  *nwa= Hardcoded_cd_rw_nwA;
  843  return(1);
  844 #endif
  845 
  846  *nwa= *lba= 0;
  847  ret= isoburn_find_emulator(&o, d, 0);
  848  if(ret<0)
  849    return(0);
  850  if(ret>0) if(o->emulation_mode>0) {
  851    *lba= 0;
  852    *nwa= o->nwa;
  853    return(1);
  854  }
  855  if(burn_drive_get_drive_role(d) != 1)
  856    return(1);
  857 
  858  s= isoburn_disc_get_status(d);
  859  if(s == BURN_DISC_BLANK) /* We do not believe in anything but nwa = lba = 0 */
  860    return(1);
  861  return(burn_disc_track_lba_nwa(d, opts, trackno, lba, nwa));
  862 }
  863 
  864 
  865 int isoburn_get_msc2(struct isoburn *o,
  866                      struct burn_write_opts *opts, int *msc2, int flag)
  867 {
  868  int ret, lba, nwa;
  869 
  870  if(o->fabricated_msc2>=0)
  871    *msc2= o->fabricated_msc2;
  872  else {
  873    ret= isoburn_disc_track_lba_nwa(o->drive, opts, 0, &lba, &nwa);
  874    if(ret<=0)
  875      return(ret);
  876    *msc2= nwa;
  877  }
  878  return(1);
  879 }
  880 
  881 /* @param flag bit0= truncate (else do not truncate)
  882                bit1= do not warn if call is inappropriate to drive 
  883                bit2= only set if truncation is currently enabled
  884 */
  885 int isoburn_set_truncate(struct burn_drive *drive, int flag)
  886 {
  887  int ret;
  888  struct isoburn *o;
  889 
  890  ret= isoburn_find_emulator(&o, drive, 0);
  891  if(ret < 0)
  892    return ret;
  893  if(o == NULL) {
  894    if(!(flag & (2 | 4)))
  895      isoburn_msgs_submit(o, 0x00060000,
  896         "Drive type or role is inappropriate for truncation", 0, "WARNING", 0);
  897    return(0);
  898  }
  899  if(o->truncate || !(flag & 4))
  900    o->truncate= flag & 1;
  901  return(1);
  902 }
  903 
  904 
  905 void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
  906 {
  907  int ret;
  908  off_t nwa= 0;
  909  struct isoburn *o;
  910  struct burn_drive *drive;
  911  char *reasons= NULL, *msg= NULL, *adr= NULL;
  912  struct stat stbuf;
  913  enum burn_write_types write_type;
  914 
  915  drive= burn_write_opts_get_drive(opts);
  916 
  917  reasons= calloc(1, BURN_REASONS_LEN);
  918  msg= calloc(1, 160+BURN_REASONS_LEN);
  919  adr= calloc(1, BURN_DRIVE_ADR_LEN);
  920  if(reasons == NULL || msg == NULL || adr == NULL) {
  921    /* To cause a negative reply with burn_drive_wrote_well() */
  922    burn_drive_cancel(drive);
  923    goto ex;
  924  }
  925 
  926  ret= isoburn_find_emulator(&o, drive, 0);
  927  if(ret<0)
  928    goto ex;
  929  if(o == NULL) {
  930    sprintf(msg,
  931           "Program error: Cannot find isoburn object associated to the drive");
  932    isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
  933    burn_drive_cancel(drive);
  934    goto ex;
  935  }
  936  o->wrote_well= -1;
  937  if(o->emulation_mode!=0) {
  938    burn_write_opts_set_multi(opts, 0);
  939    if(o->emulation_mode>0 && o->nwa >= 0) {
  940      nwa= o->nwa;
  941 
  942      /* This caters for unwritten formatted DVD-RW. They need to be written
  943         sequentially on the first use. Only written areas are random access.
  944         If the first session is not written to LBA 0, then re-opening of
  945         formatting and padding is needed. 
  946         This can be done. But when the track gets closed after padding,
  947         this lasts a long time. There is a high risk that an app will not
  948         poll the message queue while waiting for  isoburn_disc_write()  to
  949         return. The pacifier loop usually happens only afterwards.
  950         So automatic formatting might cause a nervous clueless user.
  951      */
  952      ret= isoburn_is_intermediate_dvd_rw(drive, 0);
  953      if(ret>0 && nwa>0 && nwa <= o->zero_nwa) {
  954        /* actually this should not happen since such media get recognized
  955           by isoburn_welcome_media and o->zero_nwa gets set to 0
  956        */
  957        sprintf(msg,
  958       "DVD-RW insufficiently formatted. (Intermediate State, size unknown)");
  959        isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
  960        sprintf(msg,
  961               "It might help to first deformat it and then format it again");
  962        isoburn_msgs_submit(o, 0x00060000, msg, 0, "HINT", 0);
  963        burn_drive_cancel(drive); /* mark run as failure */
  964        goto ex;
  965      }
  966      /* end of DVD-RW oriented check */
  967      burn_write_opts_set_start_byte(opts, nwa * (off_t) 2048);
  968    }
  969  }
  970 
  971  if(o->do_tao) {
  972    if (o->do_tao > 0)
  973      burn_write_opts_set_write_type(opts, BURN_WRITE_TAO, BURN_BLOCK_MODE1);
  974    else
  975      burn_write_opts_set_write_type(opts, BURN_WRITE_SAO, BURN_BLOCK_SAO);
  976 
  977    ret = burn_precheck_write(opts, disc, reasons, 0);
  978    if(ret <= 0) {
  979      sprintf(msg, "Cannot set write type %s for this medium.",
  980              o->do_tao > 0 ? "TAO" : "SAO");
  981      sprintf(msg + strlen(msg), "Reasons given:\n   %s", reasons);
  982      goto no_write_type;
  983    }
  984    sprintf(msg, "Explicitly chosen write type: %s",
  985            o->do_tao > 0 ? "TAO" : "SAO");
  986    isoburn_msgs_submit(o, 0x00060000, msg, 0, "NOTE", 0);
  987  } else {
  988    write_type= burn_write_opts_auto_write_type(opts, disc, reasons, 0);
  989    if (write_type == BURN_WRITE_NONE) {
  990       sprintf(msg, "Failed to find a suitable write type:\n%s", reasons);
  991 no_write_type:;
  992       isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
  993       if(o!=NULL)
  994         o->wrote_well= 0;
  995       /* To cause a negative reply with burn_drive_wrote_well() */
  996       burn_drive_cancel(drive);
  997       goto ex;
  998    }
  999 
 1000    sprintf(reasons, "%d", (int) write_type);
 1001    sprintf(msg, "Write_type = %s\n",
 1002                 (write_type == BURN_WRITE_SAO ? "SAO" :
 1003                 (write_type == BURN_WRITE_TAO ? "TAO" : reasons)));
 1004    isoburn_msgs_submit(o, 0x00060000, msg, 0, "DEBUG", 0);
 1005  }
 1006 
 1007 #ifdef Hardcoded_cd_rW
 1008  /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
 1009  fprintf(stderr, "Setting write address to LBA %d\n", Hardcoded_cd_rw_nwA);
 1010  burn_write_opts_set_start_byte(opts,
 1011                  ((off_t) Hardcoded_cd_rw_nwA) * (off_t) 2048);
 1012 #endif
 1013 
 1014  if(o->truncate) {
 1015    ret= burn_drive_get_drive_role(drive);
 1016    if(ret == 2 || ret == 5) {
 1017      ret= burn_drive_d_get_adr(drive, adr);
 1018      if(ret>0) {
 1019        ret= lstat(adr, &stbuf);
 1020        if(ret!=-1)
 1021          if(S_ISREG(stbuf.st_mode))
 1022            ret= truncate(adr, nwa * (off_t) 2048);
 1023            /* (result of truncate intentionally ignored) */
 1024      }
 1025    }
 1026  }
 1027 
 1028  burn_disc_write(opts, disc);
 1029 ex:;
 1030  if(reasons != NULL)
 1031    free(reasons);
 1032  if(msg != NULL)
 1033    free(msg);
 1034  if(adr != NULL)
 1035    free(adr);
 1036 }
 1037 
 1038 
 1039 void isoburn_drive_release(struct burn_drive *drive, int eject)
 1040 {
 1041  int ret;
 1042  struct isoburn *o;
 1043 
 1044  ret= isoburn_find_emulator(&o, drive, 0);
 1045  if(ret<0)
 1046    return;
 1047  if(o!=NULL) {
 1048    isoburn_destroy(&o, 0);
 1049  }
 1050  burn_drive_release(drive, eject);
 1051 }
 1052 
 1053 
 1054 void isoburn_finish(void)
 1055 {
 1056  isoburn_destroy_all(&isoburn_list_start, 0);
 1057  burn_finish();
 1058  iso_finish();
 1059 }
 1060 
 1061 
 1062 int isoburn_needs_emulation(struct burn_drive *drive)
 1063 {
 1064  int ret;
 1065  struct isoburn *o;
 1066  enum burn_disc_status s;
 1067 
 1068  s= isoburn_disc_get_status(drive);
 1069  if(s!=BURN_DISC_BLANK && s!=BURN_DISC_APPENDABLE)
 1070    return(-1);
 1071  ret= isoburn_find_emulator(&o, drive, 0);
 1072  if(ret<0)
 1073    return(-1);
 1074  if(ret>0)
 1075    if(o->emulation_mode>0)
 1076      return(1);
 1077  return(0);  
 1078 }
 1079 
 1080 
 1081 int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag)
 1082 {
 1083  int ret;
 1084  struct burn_drive *drive = o->drive;
 1085  struct burn_multi_caps *caps= NULL;
 1086  
 1087  ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
 1088  if(ret<=0)
 1089    goto ex;
 1090  if(!caps->start_adr) {
 1091    isoburn_msgs_submit(o, 0x00060000,
 1092                        "Cannot set start byte address with this type of media",
 1093                        0, "FAILURE", 0);
 1094    {ret= 0; goto ex;}
 1095  }
 1096  o->min_start_byte= value;
 1097  if(value % caps->start_alignment)
 1098    value+= caps->start_alignment - (value % caps->start_alignment);
 1099  o->nwa= value/2048;
 1100  if(o->nwa < o->zero_nwa)
 1101    o->zero_nwa= 0;
 1102  /* If suitable for media alignment, round up to Libisoburn_nwa_alignemenT */
 1103  if((o->nwa % Libisoburn_nwa_alignemenT) &&
 1104      ((Libisoburn_nwa_alignemenT*2048) % caps->start_alignment)==0 )
 1105    o->nwa+= Libisoburn_nwa_alignemenT - (o->nwa % Libisoburn_nwa_alignemenT);
 1106  ret= 1;
 1107 ex:
 1108  if(caps!=NULL)
 1109    burn_disc_free_multi_caps(&caps);
 1110  return(ret);
 1111 }
 1112 
 1113 
 1114 int isoburn_get_min_start_byte(struct burn_drive *d, off_t *start_byte,
 1115                                int flag)
 1116 {
 1117  int ret;
 1118  struct isoburn *o;
 1119 
 1120  ret= isoburn_find_emulator(&o, d, 0);
 1121  if(ret<0)
 1122    return(-1);
 1123  if(ret==0) 
 1124    return(0);
 1125  *start_byte= o->min_start_byte;
 1126  if(o->min_start_byte<=0)
 1127    return(0);
 1128  return(1);
 1129 }
 1130 
 1131 
 1132 int isoburn_drive_wrote_well(struct burn_drive *d)
 1133 {
 1134  int ret;
 1135  struct isoburn *o;
 1136  
 1137  ret= isoburn_find_emulator(&o, d, 0);
 1138  if(ret<0)
 1139    return(-1);
 1140  if(o!=NULL)
 1141    if(o->wrote_well>=0)
 1142      return(o->wrote_well);
 1143  ret= burn_drive_wrote_well(d);
 1144  return ret;
 1145 }
 1146 
 1147 
 1148 int isoburn_get_fifo_status(struct burn_drive *d, int *size, int *free_bytes,
 1149                 char **status_text)
 1150 {
 1151  int ret;
 1152  struct isoburn *o;
 1153  size_t hsize= 0, hfree_bytes= 0;
 1154 
 1155  ret= isoburn_find_emulator(&o, d, 0);
 1156  if(ret<0)
 1157    return(-1);
 1158 
 1159  if(o==NULL)
 1160    return(-1);
 1161  if(o->iso_source==NULL)
 1162    return(-1);
 1163  ret= iso_ring_buffer_get_status(o->iso_source, &hsize, &hfree_bytes);
 1164  if(hsize > 1024*1024*1024)
 1165    *size= 1024*1024*1024;
 1166  else
 1167    *size= hsize;
 1168  if(hfree_bytes > 1024*1024*1024)
 1169    *free_bytes= 1024*1024*1024;
 1170  else
 1171    *free_bytes= hfree_bytes;
 1172  *status_text= "";
 1173  if(ret==0)
 1174    *status_text= "standby";
 1175  else if(ret==1)
 1176    *status_text= "active";
 1177  else if(ret==2)
 1178    *status_text= "ending";
 1179  else if(ret==3)
 1180    *status_text= "failing";
 1181  else if(ret==4)
 1182    *status_text= "unused";
 1183  else if(ret==5)
 1184    *status_text= "abandoned";
 1185  else if(ret==6)
 1186    *status_text= "ended";
 1187  else if(ret==7)
 1188    *status_text= "aborted";
 1189  return(ret);
 1190 }
 1191 
 1192 
 1193 /* @param flag bit0= -reserved-
 1194                bit1= this is a libburn severity
 1195 */
 1196 int isoburn__sev_to_text(int severity, char **severity_name,
 1197                          int flag)
 1198 {
 1199  int ret;
 1200    
 1201  ret= iso_sev_to_text(severity, severity_name);
 1202  if(ret>0)
 1203    return(ret);
 1204  ret= burn_sev_to_text(severity, severity_name, 0);
 1205  return(ret);
 1206 }
 1207 
 1208 
 1209 int isoburn__text_to_sev(char *severity_name, int *severity_number, int flag)
 1210 {
 1211  int ret= 1;
 1212 
 1213  ret= iso_text_to_sev(severity_name, severity_number);
 1214  if(ret>0)
 1215    return(ret);
 1216  ret= burn_text_to_sev(severity_name, severity_number, 0);
 1217  return(ret);
 1218 }
 1219 
 1220 
 1221 int isoburn_report_iso_error(int iso_error_code, char msg_text[], int os_errno,
 1222                              char min_severity[], int flag)
 1223 {
 1224  int error_code, iso_sev, min_sev, ret;
 1225  char *sev_text_pt, *msg_text_pt= NULL;
 1226 
 1227  error_code= iso_error_get_code(iso_error_code);
 1228  if(error_code < 0x00030000 || error_code >= 0x00040000)
 1229    error_code= (error_code & 0xffff) | 0x00050000;
 1230 
 1231  if(iso_error_code<0)
 1232    msg_text_pt= (char *) iso_error_to_msg(iso_error_code);
 1233  if(msg_text_pt==NULL)
 1234    msg_text_pt= msg_text;
 1235  iso_sev= iso_error_get_severity(iso_error_code);
 1236  sev_text_pt= min_severity;
 1237  isoburn__text_to_sev(min_severity, &min_sev, 0);
 1238  if(min_sev < iso_sev) 
 1239    isoburn__sev_to_text(iso_sev, &sev_text_pt, 0);
 1240  ret= iso_msgs_submit(error_code, msg_text_pt, os_errno, sev_text_pt, 0);
 1241  return(ret);
 1242 }
 1243 
 1244 
 1245 /* @param flag bit0-7: info return mode
 1246                  0= do not return anything in info (do not even touch it)
 1247                  1= copy volume id to info (info needs 33 bytes)
 1248                  2= do not touch info (caller will copy 64 kB header to it)
 1249                bit14= -reserved -
 1250                bit15= -reserved-
 1251    @return 1 seems to be a valid ISO image , 0 format not recognized, <0 error
 1252 */
 1253 int isoburn_read_iso_head_parse(unsigned char *data,
 1254                                 int *image_blocks, char *info, int flag)
 1255 {
 1256  int i, info_mode;
 1257 
 1258  /* is this an ISO image ? */
 1259  if(data[0]!=1)
 1260    return(0);
 1261  if(strncmp((char *) (data+1),"CD001",5)!=0)
 1262    return(0);
 1263  /* believe so */
 1264 
 1265  *image_blocks= data[80] | (data[81]<<8) | (data[82]<<16) | (data[83]<<24);
 1266  info_mode= flag&255;
 1267  if(info_mode==0) {
 1268    ;
 1269  } else if(info_mode==1) {
 1270    strncpy(info, (char *) (data+40), 32);
 1271    info[32]= 0;
 1272    for(i= strlen(info)-1; i>=0; i--)
 1273      if(info[i]!=' ')
 1274    break;
 1275      else
 1276        info[i]= 0;
 1277  } else if(info_mode==2) {
 1278    ;
 1279  } else {
 1280    isoburn_msgs_submit(NULL, 0x00060000,
 1281                "Program error: Unknown info mode with isoburn_read_iso_head()",
 1282                0, "FATAL", 0);
 1283    return(-1);
 1284  }
 1285  return(1);
 1286 }
 1287                          
 1288 
 1289 /* API
 1290    @param flag bit0-7: info return mode
 1291                  0= do not return anything in info (do not even touch it)
 1292                  1= copy volume id to info (info needs 33 bytes)
 1293                  2= copy 64 kB header to info (needs 65536 bytes)
 1294                bit13= do not read head from media but use first 64 kB from info
 1295                bit14= check both half buffers (not only second)
 1296                       return 2 if found in first block
 1297                bit15= return-1 on read error
 1298    @return 1 seems to be a valid ISO image , 2 found in first half buffer,
 1299            0 format not recognized, <0 error
 1300 */
 1301 int isoburn_read_iso_head(struct burn_drive *d, int lba,
 1302                           int *image_blocks, char *info, int flag)
 1303 {
 1304  unsigned char *buffer= NULL;
 1305  int ret, info_mode, capacity, role;
 1306  off_t data_count, to_read;
 1307  struct isoburn *o;
 1308 
 1309  buffer= calloc(1, 64 * 1024);
 1310  if(buffer == NULL)
 1311    {ret= -1; goto ex;}
 1312 
 1313  info_mode= flag&255;
 1314  *image_blocks= 0;
 1315  if(flag&(1<<13)) {
 1316    memcpy(buffer, info, 64*1024);
 1317  } else {
 1318    memset(buffer, 0, 64 * 1024);
 1319    role = burn_drive_get_drive_role(d);
 1320    if (role == 3 || role == 5)
 1321 
 1322      /* >>> ??? return always 0 ? */
 1323      {ret= (-1*!!(flag&(1<<15))); goto ex;}
 1324 
 1325    ret = burn_get_read_capacity(d, &capacity, 0);
 1326    if (ret <= 0 && (role == 2 || role == 4)) {
 1327      /* Might be a block device on a system where libburn cannot determine its
 1328         size.  Try to read anyway. */
 1329      capacity = 0x7ffffff0;
 1330      ret = 1;
 1331    }
 1332    to_read= (off_t) capacity * ((off_t) 2048);
 1333    if(ret > 0 && to_read >= (off_t) (36 * 1024)) {
 1334      ret= isoburn_find_emulator(&o, d, 0);
 1335      if(ret > 0)
 1336        if(o->media_read_error)
 1337          {ret= (-1 * !!(flag & (1 << 15))); goto ex;}
 1338      if(to_read >= (off_t) (64 * 1024))
 1339        to_read= 64 * 1024;
 1340      ret = burn_read_data(d, ((off_t) lba) * (off_t) 2048, (char *) buffer,
 1341                       to_read, &data_count, 32); /* error messages as DEBUG */
 1342    } else
 1343      ret= 0;
 1344    if(ret<=0)
 1345      {ret= (-1*!!(flag&(1<<15))); goto ex;}
 1346    if(info_mode==2)
 1347      memcpy(info, buffer, 64*1024);
 1348  }
 1349 
 1350  if(flag&(1<<14)) {
 1351    ret= isoburn_read_iso_head_parse(buffer, image_blocks, info, info_mode);
 1352    if(ret<0)
 1353      goto ex;
 1354    if(ret>0)
 1355      {ret= 2; goto ex;}
 1356  }
 1357  ret= isoburn_read_iso_head_parse(buffer+32*1024, image_blocks, info,
 1358                                   info_mode);
 1359  if(ret<=0)
 1360    goto ex;
 1361  ret= 1;
 1362 ex:;
 1363  if(buffer != NULL)
 1364    free(buffer);
 1365  return(ret);
 1366 }
 1367 
 1368 
 1369 int isoburn_make_toc_entry(struct isoburn *o, int *session_count, int lba,
 1370                            int track_blocks, char *volid, int flag)
 1371 {
 1372  int ret;
 1373  struct isoburn_toc_entry *item;
 1374 
 1375  ret= isoburn_toc_entry_new(&item, o->toc, 0);
 1376  if(ret<=0) {
 1377 no_memory:;
 1378    isoburn_msgs_submit(o, 0x00060000,
 1379                        "Not enough memory for emulated TOC entry object",
 1380                        0, "FATAL", 0);
 1381    return(-1);
 1382  }
 1383  if(o->toc==NULL)
 1384    o->toc= item;
 1385  (*session_count)++;
 1386  item->session= *session_count;
 1387  item->track_no= *session_count;
 1388  item->start_lba= lba;
 1389  item->track_blocks= track_blocks;
 1390  if(volid != NULL) {
 1391    item->volid= strdup(volid);
 1392    if(item->volid == NULL)
 1393      goto no_memory;
 1394  }
 1395  return(1);
 1396 }
 1397 
 1398 
 1399 /* @param flag bit0= allow unemulated media
 1400                bit1= free scanning without enclosing LBA-0-header 
 1401                bit4= represent emulated media as one single session
 1402                      (not with bit1)
 1403    @return -1 severe error, 0= no neat header chain, 1= credible chain read
 1404 */
 1405 int isoburn_emulate_toc(struct burn_drive *d, int flag)
 1406 {
 1407  int ret, image_size= 0, lba, track_blocks, session_count= 0, read_flag= 0;
 1408  int scan_start= 0, scan_count= 0, probe_minus_16= 0, growisofs_nwa, role;
 1409  int with_enclosure= 0, readable_blocks= -1;
 1410  struct isoburn *o;
 1411  char *msg= NULL, *size_text= NULL, *sev, volid[33], *volid_pt= NULL;
 1412  time_t start_time, last_pacifier, now;
 1413 
 1414  msg= calloc(1, 160);
 1415  size_text= calloc(1, 80);
 1416  if(msg == NULL || size_text == NULL)
 1417    {ret= -1; goto ex;}
 1418  
 1419  /* is the medium emulated multi-session ? */
 1420  ret= isoburn_find_emulator(&o, d, 0);
 1421  if(ret<0)
 1422    {ret= -1; goto ex;}
 1423  if(o==NULL)
 1424    {ret= -1; goto ex;}
 1425  if(o->emulation_mode<=0 && !(flag&1))
 1426    {ret= 0; goto ex;}
 1427 
 1428  ret= burn_get_read_capacity(d, &readable_blocks, 0);
 1429  if(ret <= 0) {
 1430    role = burn_drive_get_drive_role(d);
 1431    if (role == 2 || role == 4)
 1432      /* Might be a block device on a system where libburn cannot determine its
 1433         size.  Try to read anyway. */
 1434      readable_blocks= 0x7ffffff0; /* try to read anyway */
 1435    else
 1436      readable_blocks= -1;
 1437  }
 1438  if(o->fabricated_disc_status == BURN_DISC_BLANK)
 1439    {ret= 0; goto failure;}
 1440 
 1441  start_time= last_pacifier= time(NULL);
 1442  lba= 0;
 1443  if(flag & 2) {
 1444    /* If there is a PVD at LBA 32 then this is an image with emulated TOC */
 1445    ret= isoburn_read_iso_head(d, 32, &image_size, NULL, 0);
 1446    if(ret > 0)
 1447      lba= 32;
 1448  } else {
 1449    ret= isoburn_read_iso_head(d, lba, &image_size, NULL, 0);
 1450    if(ret<=0)
 1451      {ret= 0; goto failure;}
 1452    lba= o->target_iso_head_size / 2048;
 1453    with_enclosure= 1;
 1454    if((flag & 16) && o->emulation_mode == 1) {
 1455      ret= 1;
 1456      goto failure; /* This will represent the medium as single session */
 1457    }
 1458  }
 1459  while(lba<image_size || (flag&2)) {
 1460    now= time(NULL);
 1461    if(now - last_pacifier >= 5) {
 1462      last_pacifier= now;
 1463      if(scan_count>=10*512)
 1464        sprintf(size_text, "%.f MB", ((double) scan_count) / 512.0);
 1465      else
 1466        sprintf(size_text, "%.f kB", 2 * (double) scan_count);
 1467      sprintf(msg, "Found %d ISO sessions by scanning %s in %.f seconds",
 1468              session_count, size_text, (double) (now - start_time));
 1469      isoburn_msgs_submit(o, 0x00060000, msg, 0, "UPDATE", 0);
 1470    }
 1471    read_flag= 1;
 1472    if(flag&2)
 1473      read_flag|= (1<<15)|((session_count>0)<<14);
 1474    else {
 1475 
 1476      /* growisofs aligns to 16 rather than 32. Overwritable TOC emulation
 1477         relies on not accidentally seeing inter-session trash data.
 1478         But one can safely access 16 blocks earlier because a xorriso header
 1479         would have been overwritten with the unused 16 blocks at its start.
 1480         If libisoburn alignment would increase, then this would not be
 1481         possible any more.
 1482      */
 1483 
 1484      if(probe_minus_16)
 1485        read_flag|= (1<<14);
 1486      probe_minus_16= 0;
 1487    }
 1488 
 1489    ret= isoburn_read_iso_head(d, lba, &track_blocks, volid, read_flag);
 1490    if(ret > 0) {
 1491      volid_pt= volid;
 1492    } else {
 1493      volid_pt= NULL;
 1494      if(session_count>0) {
 1495        if(flag&2) {
 1496          if(ret==0) {
 1497            /* try at next 64 k block (check both 32 k halves) */
 1498            lba+= 32;
 1499            scan_count+= 32;
 1500            if(lba-scan_start <= Libisoburn_toc_scan_max_gaP)
 1501  continue;
 1502          }
 1503  break;
 1504        }
 1505        sprintf(msg,
 1506                "Chain of ISO session headers broken at #%d, LBA %ds",
 1507                session_count+1, lba);
 1508        isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0);
 1509 
 1510        if(with_enclosure) {
 1511          ret= isoburn_make_toc_entry(o, &session_count, 0, image_size, NULL,0);
 1512          if(ret<=0)
 1513            goto failure;
 1514        }
 1515  break; /* do not return failure */
 1516 
 1517      }
 1518      {ret= 0; goto failure;}
 1519    }
 1520    if(ret==2) /* ISO header was found in first half block */
 1521      lba-= 16;
 1522 
 1523    if(readable_blocks >= 0 && lba + track_blocks > readable_blocks) {
 1524      sprintf(msg, "ISO image size %ds larger than readable size %ds",
 1525                   lba + track_blocks, readable_blocks);
 1526      isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0);
 1527      track_blocks= readable_blocks - lba;
 1528    }
 1529    ret= isoburn_make_toc_entry(o, &session_count, lba, track_blocks, volid_pt,
 1530                                0);
 1531    if(ret<=0)
 1532      goto failure;
 1533    lba+= track_blocks;
 1534    scan_count+= 32;
 1535 
 1536    /* growisofs aligns to 16 rather than 32 */
 1537    growisofs_nwa= lba;
 1538    if(growisofs_nwa % 16)
 1539      growisofs_nwa+= 16 - (growisofs_nwa % 16);
 1540    if(lba % Libisoburn_nwa_alignemenT)
 1541      lba+= Libisoburn_nwa_alignemenT - (lba % Libisoburn_nwa_alignemenT);
 1542    scan_start= lba;
 1543    if(lba - growisofs_nwa == 16)
 1544      probe_minus_16= 1;
 1545  }
 1546  if(last_pacifier != start_time)
 1547    sev= "UPDATE";
 1548  else
 1549    sev= "DEBUG";
 1550  now= time(NULL);
 1551  if(scan_count>=10*512)
 1552    sprintf(size_text, "%.f MB", ((double) scan_count) / 512.0);
 1553  else
 1554    sprintf(size_text, "%.f kB", 2 * (double) scan_count);
 1555  sprintf(msg, "Found %d ISO sessions by scanning %s in %.f seconds",
 1556          session_count, size_text, (double) (now - start_time));
 1557  isoburn_msgs_submit(o, 0x00060000, msg, 0, sev, 0);
 1558  {ret= 1; goto ex;}
 1559 failure:;
 1560  isoburn_toc_entry_destroy(&(o->toc), 1);
 1561  if(with_enclosure && o->emulation_mode == 1) {
 1562    if(readable_blocks >= 0 && image_size > readable_blocks) {
 1563      sprintf(msg, "ISO image size %ds larger than readable size %ds",
 1564                   image_size, readable_blocks);
 1565      isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0);
 1566      image_size= readable_blocks;
 1567    }
 1568    session_count= 0;
 1569    ret= isoburn_make_toc_entry(o, &session_count, 0, image_size, NULL, 0);
 1570  }
 1571 ex:;
 1572  if(msg != NULL)
 1573    free(msg);
 1574  if(size_text != NULL)
 1575    free(size_text);
 1576  return(ret);
 1577 }
 1578 
 1579 
 1580 int isoburn_toc_new_arrays(struct isoburn_toc_disc *o,
 1581                            int session_count, int track_count, int flag)
 1582 {
 1583  int i;
 1584  int isoburn_toc_destroy_arrays(struct isoburn_toc_disc *o, int flag);
 1585 
 1586  o->sessions= calloc(session_count, sizeof(struct isoburn_toc_session));
 1587  o->session_pointers=
 1588                    calloc(session_count, sizeof(struct isoburn_toc_session *));
 1589  o->tracks= calloc(track_count, sizeof(struct isoburn_toc_track));
 1590  o->track_pointers= calloc(track_count, sizeof(struct isoburn_toc_track *));
 1591  if(o->sessions!=NULL && o->session_pointers!=NULL &&
 1592     o->tracks!=NULL && o->track_pointers!=NULL) {
 1593    for(i= 0; i<session_count; i++) {
 1594      o->sessions[i].session= NULL;
 1595      o->sessions[i].track_pointers= NULL;
 1596      o->sessions[i].track_count= 0;
 1597      o->sessions[i].toc_entry= NULL;
 1598      o->session_pointers[i]= NULL;
 1599    }
 1600    for(i= 0; i<track_count; i++) {
 1601      o->tracks[i].track= NULL;
 1602      o->tracks[i].toc_entry= NULL;
 1603      o->track_pointers[i]= NULL;
 1604    }
 1605    return(1);
 1606  }
 1607  /* failed */
 1608  isoburn_toc_destroy_arrays(o, 0);
 1609  return(-1);
 1610 }
 1611 
 1612 
 1613 int isoburn_toc_destroy_arrays(struct isoburn_toc_disc *o, int flag)
 1614 {
 1615  if(o->sessions!=NULL)
 1616    free((char *) o->sessions);
 1617  o->sessions= NULL;
 1618  if(o->session_pointers!=NULL)
 1619    free((char *) o->session_pointers);
 1620  o->session_pointers= NULL;
 1621  if(o->tracks!=NULL)
 1622    free((char *) o->tracks);
 1623  o->tracks= NULL;
 1624  if(o->track_pointers!=NULL)
 1625    free((char *) o->track_pointers);
 1626  o->track_pointers= NULL;
 1627  return(1);
 1628 }
 1629 
 1630 
 1631 struct isoburn_toc_disc *isoburn_toc_drive_get_disc(struct burn_drive *d)
 1632 {
 1633  int ret, session_count= 0, track_count= 0, num_tracks= 0, i, j;
 1634  int open_sessions= 0;
 1635  struct isoburn *o;
 1636  struct isoburn_toc_entry *t;
 1637  struct isoburn_toc_disc *toc_disc= NULL;
 1638  struct burn_session **s;
 1639  struct burn_track **tracks;
 1640 
 1641  toc_disc= calloc(1, sizeof(struct isoburn_toc_disc));
 1642  if(toc_disc==NULL)
 1643    return(NULL);
 1644  toc_disc->disc= NULL;
 1645  toc_disc->sessions= NULL;
 1646  toc_disc->session_pointers= NULL;
 1647  toc_disc->tracks= NULL;
 1648  toc_disc->track_pointers= NULL;
 1649  toc_disc->session_count= 0;
 1650  toc_disc->incomplete_session_count= 0;
 1651  toc_disc->track_count= 0;
 1652  toc_disc->toc= NULL; 
 1653 
 1654  /* is the medium emulated multi-session ? */
 1655  ret= isoburn_find_emulator(&o, d, 0);
 1656  if(ret<0)
 1657    goto libburn;
 1658  if(o->toc==NULL)
 1659    goto libburn;
 1660 
 1661  /* This is an emulated TOC */
 1662  toc_disc->toc= o->toc;
 1663  for(t= toc_disc->toc; t!=NULL; t= t->next)
 1664    session_count++;
 1665  ret= isoburn_toc_new_arrays(toc_disc, session_count, session_count, 0);
 1666  if(ret<=0)
 1667    goto failure;
 1668  t= toc_disc->toc;
 1669  for(i= 0; i<session_count; i++) {
 1670    toc_disc->sessions[i].track_pointers= toc_disc->track_pointers+i;
 1671    toc_disc->sessions[i].track_count= 1;
 1672    toc_disc->sessions[i].toc_entry= t;
 1673    toc_disc->session_pointers[i]= toc_disc->sessions+i;
 1674    toc_disc->tracks[i].toc_entry= t;
 1675    toc_disc->track_pointers[i]= toc_disc->tracks+i;
 1676    t= t->next;
 1677  }
 1678  toc_disc->session_count= session_count;
 1679  toc_disc->track_count= session_count;
 1680  return(toc_disc);
 1681 
 1682 libburn:;
 1683  /* This is a libburn provided TOC */
 1684  toc_disc->disc= burn_drive_get_disc(d);
 1685  if(toc_disc->disc == NULL) {
 1686 failure:;
 1687    free((char *) toc_disc);
 1688    return(NULL);
 1689  }
 1690  s= burn_disc_get_sessions(toc_disc->disc, &session_count);
 1691  open_sessions= burn_disc_get_incomplete_sessions(toc_disc->disc);
 1692  for(i= 0; i < session_count + open_sessions; i++) {
 1693    tracks = burn_session_get_tracks(s[i], &num_tracks);
 1694    if(i == session_count + open_sessions - 1 && open_sessions > 0) {
 1695      /* Do not count the invisible track of the last incomplete session */
 1696      num_tracks--;
 1697    }
 1698    track_count+= num_tracks;
 1699  }
 1700  if(session_count + open_sessions <= 0 || track_count <= 0)
 1701    goto failure;
 1702  ret= isoburn_toc_new_arrays(toc_disc, session_count + open_sessions,
 1703                              track_count, 0);
 1704  if(ret<=0)
 1705    goto failure;
 1706  track_count= 0;
 1707  for(i= 0; i < session_count + open_sessions; i++) {
 1708    tracks = burn_session_get_tracks(s[i], &num_tracks);
 1709    if(i == session_count + open_sessions - 1 && open_sessions > 0)
 1710      num_tracks--;
 1711    toc_disc->sessions[i].session= s[i];
 1712    toc_disc->sessions[i].track_pointers= toc_disc->track_pointers+track_count;
 1713    toc_disc->sessions[i].track_count= num_tracks;
 1714    toc_disc->session_pointers[i]= toc_disc->sessions+i;
 1715    for(j= 0; j<num_tracks; j++) {
 1716      toc_disc->tracks[track_count+j].track= tracks[j];
 1717      toc_disc->track_pointers[track_count+j]= toc_disc->tracks+(track_count+j);
 1718    }
 1719    track_count+= num_tracks;
 1720  }
 1721  toc_disc->session_count= session_count;
 1722  toc_disc->incomplete_session_count= open_sessions;
 1723  toc_disc->track_count= track_count;
 1724  return(toc_disc);
 1725 }
 1726 
 1727 
 1728 int isoburn_toc_disc_get_sectors(struct isoburn_toc_disc *disc)
 1729 {
 1730  struct isoburn_toc_entry *t;
 1731  int ret= 0, num_sessions, num_tracks, open_sessions= 0, session_idx= -1;
 1732  struct burn_session **sessions;
 1733  struct burn_track **tracks;
 1734  struct burn_toc_entry entry;
 1735 
 1736  if(disc==NULL)
 1737    return(0);
 1738  if(disc->toc!=NULL) {
 1739    for(t= disc->toc; t!=NULL; t= t->next)
 1740      ret= t->start_lba + t->track_blocks;
 1741  } else if(disc->disc!=NULL) {
 1742    sessions= burn_disc_get_sessions(disc->disc, &num_sessions);
 1743    open_sessions= burn_disc_get_incomplete_sessions(disc->disc);
 1744    if(num_sessions + open_sessions > 0) {
 1745      session_idx= num_sessions + open_sessions - 1;
 1746      tracks = burn_session_get_tracks(sessions[session_idx], &num_tracks);
 1747      if(open_sessions > 0) {
 1748        /* Do not count the invisible track of the last incomplete session */
 1749        num_tracks--;
 1750      }
 1751      if(num_tracks <= 0)
 1752        session_idx--;
 1753    }
 1754    if(session_idx >= 0) {
 1755      tracks = burn_session_get_tracks(sessions[session_idx], &num_tracks);
 1756      if(session_idx == num_sessions + open_sessions - 1 && open_sessions > 0) {
 1757        /* Do not count the invisible track of the last incomplete session */
 1758        num_tracks--;
 1759      }
 1760      if(num_tracks > 0) {
 1761        burn_track_get_entry(tracks[num_tracks - 1], &entry);
 1762        if(entry.extensions_valid & 1)
 1763          ret= entry.start_lba + entry.track_blocks;
 1764      }
 1765    }
 1766 /*
 1767    ret= burn_disc_get_sectors(disc->disc);
 1768 */
 1769  }
 1770  return(ret);
 1771 }
 1772 
 1773 
 1774 struct isoburn_toc_session **isoburn_toc_disc_get_sessions(
 1775                                       struct isoburn_toc_disc *disc, int *num)
 1776 {
 1777  *num= disc->session_count;
 1778  return(disc->session_pointers);
 1779 }
 1780 
 1781 
 1782 int isoburn_toc_disc_get_incmpl_sess(struct isoburn_toc_disc *disc)
 1783 {
 1784  return(disc->incomplete_session_count);
 1785 }
 1786 
 1787 
 1788 int isoburn_toc_session_get_sectors(struct isoburn_toc_session *s)
 1789 {
 1790  struct isoburn_toc_entry *t;
 1791  int count= 0, i;
 1792 
 1793  if(s==NULL)
 1794    return(0);
 1795  if(s->toc_entry!=NULL) {
 1796    t= s->toc_entry;
 1797    for(i= 0; i<s->track_count; i++) {
 1798      count+= t->track_blocks;
 1799      t= t->next;
 1800    }
 1801  } else if(s->session!=NULL)
 1802    count= burn_session_get_sectors(s->session);
 1803  return(count);
 1804 }
 1805 
 1806 
 1807 int isoburn_toc_entry_finish(struct burn_toc_entry *entry,
 1808                              int session_no, int track_no, int flag)
 1809 {
 1810  int pmin, psec, pframe;
 1811 
 1812  entry->extensions_valid= 1;
 1813  entry->adr= 1;
 1814  entry->control= 4;
 1815  entry->session= session_no & 255;
 1816  entry->session_msb= (session_no >> 8) & 255;
 1817  entry->point= track_no & 255;
 1818  entry->point_msb= (track_no >> 8) & 255;
 1819 
 1820  burn_lba_to_msf(entry->start_lba, &pmin, &psec, &pframe);
 1821  if(pmin<=255)
 1822    entry->pmin= pmin;
 1823  else
 1824    entry->pmin= 255;
 1825  entry->psec= psec;
 1826  entry->pframe= pframe; 
 1827  return(1);
 1828 }
 1829 
 1830 
 1831 void isoburn_toc_session_get_leadout_entry(struct isoburn_toc_session *s,
 1832                                        struct burn_toc_entry *entry)
 1833 {
 1834  struct isoburn_toc_track *t;
 1835 
 1836  if(s==NULL)
 1837    return;
 1838  if(s->session!=NULL && s->toc_entry==NULL) {
 1839    burn_session_get_leadout_entry(s->session, entry);
 1840    return;
 1841  }
 1842  if(s->track_count<=0 || s->track_pointers==NULL || s->toc_entry==NULL)
 1843    return;
 1844  t= s->track_pointers[s->track_count-1];
 1845  entry->start_lba= t->toc_entry->start_lba + t->toc_entry->track_blocks;
 1846  entry->track_blocks= 0;
 1847  isoburn_toc_entry_finish(entry, s->toc_entry->session, t->toc_entry->track_no,
 1848                           0);
 1849 }
 1850 
 1851 
 1852 struct isoburn_toc_track **isoburn_toc_session_get_tracks(
 1853                                       struct isoburn_toc_session *s, int *num)
 1854 {
 1855  *num= s->track_count;
 1856  return(s->track_pointers);
 1857 }
 1858 
 1859 
 1860 void isoburn_toc_track_get_entry(struct isoburn_toc_track *t,
 1861                                  struct burn_toc_entry *entry)
 1862 {
 1863  if(t==0)
 1864    return;
 1865  if(t->track!=NULL && t->toc_entry==NULL) {
 1866    burn_track_get_entry(t->track, entry);
 1867    return;
 1868  }
 1869  if(t->toc_entry==NULL)
 1870    return;
 1871  entry->start_lba= t->toc_entry->start_lba;
 1872  entry->track_blocks= t->toc_entry->track_blocks;
 1873  isoburn_toc_entry_finish(entry, t->toc_entry->session, t->toc_entry->track_no,
 1874                           0);
 1875 }
 1876 
 1877 
 1878 int isoburn_toc_track_get_emul(struct isoburn_toc_track *t, int *start_lba,
 1879                                int *image_blocks, char volid[33], int flag)
 1880 {
 1881  if(t->toc_entry == NULL)
 1882    return(0);
 1883  if(t->toc_entry->volid == NULL)
 1884    return(0);
 1885  *start_lba= t->toc_entry->start_lba;
 1886  *image_blocks= t->toc_entry->track_blocks;
 1887  strncpy(volid, t->toc_entry->volid, 32);
 1888  volid[32]= 0;
 1889  return(1);
 1890 }
 1891 
 1892 
 1893 void isoburn_toc_disc_free(struct isoburn_toc_disc *d)
 1894 {
 1895  if(d->disc!=NULL)
 1896    burn_disc_free(d->disc);
 1897  isoburn_toc_destroy_arrays(d, 0);
 1898  free((char *) d);
 1899 }
 1900 
 1901 
 1902 int isoburn_get_track_lba(struct isoburn_toc_track *track, int *lba, int flag)
 1903 {
 1904  struct burn_toc_entry entry;
 1905 
 1906  isoburn_toc_track_get_entry(track, &entry);
 1907  if (entry.extensions_valid & 1)
 1908    *lba= entry.start_lba;
 1909  else
 1910    *lba= burn_msf_to_lba(entry.pmin, entry.psec, entry.pframe);
 1911  return(1);
 1912 }
 1913 
 1914 
 1915 int isoburn_drive_set_msgs_submit(struct burn_drive *d,
 1916                             int (*msgs_submit)(void *handle, int error_code, 
 1917                                                char msg_text[], int os_errno, 
 1918                                                char severity[], int flag),
 1919                             void *submit_handle, int submit_flag, int flag)
 1920 {
 1921  struct isoburn *o;
 1922  int ret;
 1923 
 1924  ret= isoburn_find_emulator(&o, d, 0);
 1925  if(ret<0 || o==NULL)
 1926    return(-1);
 1927  o->msgs_submit= msgs_submit;
 1928  o->msgs_submit_handle= submit_handle;
 1929  o->msgs_submit_flag= submit_flag;
 1930  return(1);
 1931 }
 1932 
 1933  
 1934 /* @param flag bit0= with adr_mode 3: adr_value might be 16 blocks too high
 1935                bit1= insist in seeing a disc object with at least one session
 1936                bit2= with adr_mode 4: use adr_value as regular expression
 1937 */
 1938 int isoburn_set_msc1(struct burn_drive *d, int adr_mode, char *adr_value,
 1939                      int flag)
 1940 {
 1941  int ret, num_sessions= 0, num_tracks, adr_num, i, j, total_tracks;
 1942  int lba, best_lba, size, re_valid= 0, track_count= 0;
 1943  time_t start_time= 0, last_pacifier= 0, now;
 1944  char volid[33], *msg= NULL;
 1945  struct isoburn *o;
 1946  struct isoburn_toc_disc *disc= NULL;
 1947  struct isoburn_toc_session **sessions= NULL;
 1948  struct isoburn_toc_track **tracks= NULL;
 1949  static char mode_names[][20]= {"auto", "session", "track", "lba", "volid"};
 1950  static int max_mode_names= 4;
 1951  regex_t re;
 1952  regmatch_t match[1];
 1953  enum burn_disc_status s;
 1954 
 1955  ret= isoburn_find_emulator(&o, d, 0);
 1956  if(ret<0)
 1957    return(-1);
 1958  if(o==NULL)
 1959    return(-1);
 1960 
 1961  msg= calloc(1, 160);
 1962  if(msg == NULL)
 1963    {ret= -1; goto ex;}
 1964 
 1965  start_time= last_pacifier= time(NULL);
 1966  adr_num= atoi(adr_value);
 1967  if(adr_mode!=3 || (flag & 2)) {
 1968    disc= isoburn_toc_drive_get_disc(d);
 1969    if(disc==NULL) {
 1970 not_found:;
 1971      if(adr_mode<0 || adr_mode>max_mode_names)
 1972        goto unknown_mode;
 1973      sprintf(msg, "Failed to find %s %s", mode_names[adr_mode],
 1974                   strlen(adr_value)<=80 ?  adr_value : "-oversized-string-");
 1975      isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
 1976      ret= 0; goto ex;
 1977    }
 1978    sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions);
 1979    if(sessions==NULL || num_sessions<=0)
 1980      goto not_found;
 1981  }
 1982  if(adr_mode==0) {
 1983    /* Set fabricated_msc1 to last session in TOC */
 1984    tracks= isoburn_toc_session_get_tracks(sessions[num_sessions-1],
 1985                                           &num_tracks);
 1986    if(tracks==NULL || num_tracks<=0)
 1987      goto not_found;
 1988    isoburn_get_track_lba(tracks[0], &(o->fabricated_msc1), 0);
 1989 
 1990  } else if(adr_mode==1) {
 1991    /* Use adr_num as session index (first session is 1, not 0) */
 1992    if(adr_num<1 || adr_num>num_sessions)
 1993      goto not_found;
 1994    tracks= isoburn_toc_session_get_tracks(sessions[adr_num-1], &num_tracks);
 1995    if(tracks==NULL || num_tracks<=0)
 1996      goto not_found;
 1997    isoburn_get_track_lba(tracks[0], &(o->fabricated_msc1), 0);
 1998 
 1999  } else if(adr_mode==2) {
 2000    /* use adr_num as track index */
 2001    total_tracks= 0;
 2002    for(i=0; i<num_sessions; i++) {
 2003      tracks= isoburn_toc_session_get_tracks(sessions[i], &num_tracks);
 2004      if(tracks==NULL)
 2005    continue;
 2006      for(j= 0; j<num_tracks; j++) {
 2007        total_tracks++;
 2008        if(total_tracks==adr_num) {
 2009          isoburn_get_track_lba(tracks[j], &(o->fabricated_msc1), 0);
 2010          ret= 1; goto ex;
 2011        }
 2012      }
 2013    }
 2014    goto not_found;
 2015 
 2016  } else if(adr_mode==3) {
 2017    o->fabricated_msc1= adr_num;
 2018    s= isoburn_disc_get_status(d);
 2019    if(o->fabricated_msc1 > 0 && s != BURN_DISC_FULL
 2020       && s != BURN_DISC_APPENDABLE) {
 2021      isoburn_msgs_submit(o, 0x00060000,
 2022                          "Non-zero load offset given with blank input media",
 2023                          0, "FAILURE", 0);
 2024      ret= 0; goto ex;
 2025    }
 2026    if((flag & 1) && o->fabricated_msc1 >= 16) {
 2027      /* adr_num is possibly 16 blocks too high */
 2028      ret= isoburn_read_iso_head(d, o->fabricated_msc1, &size,volid, 1|(1<<14));
 2029      if(ret==2)
 2030        o->fabricated_msc1-= 16;
 2031    }
 2032  } else if(adr_mode==4) {
 2033    /* search for volume id that is equal to adr_value */
 2034    if(flag & 4) {
 2035      ret= regcomp(&re, adr_value, 0);
 2036      if(ret != 0)
 2037        flag&= ~4;
 2038      else
 2039        re_valid= 1;
 2040    }
 2041    best_lba= -1;
 2042    for(i=0; i<num_sessions; i++) {
 2043      tracks= isoburn_toc_session_get_tracks(sessions[i], &num_tracks);
 2044      if(tracks==NULL)
 2045    continue;
 2046      for(j= 0; j<num_tracks; j++) {
 2047        now= time(NULL);
 2048        if(now - last_pacifier >= 5 && track_count > 0) {
 2049          last_pacifier= now;
 2050          sprintf(msg,
 2051                  "Scanned %d tracks for matching volid in %.f seconds",
 2052                  track_count, (double) (now - start_time));
 2053          isoburn_msgs_submit(o, 0x00060000, msg, 0, "UPDATE", 0);
 2054        }
 2055        track_count++;
 2056        ret= isoburn_toc_track_get_emul(tracks[0], &lba, &size, volid, 0);
 2057        if(ret < 0)
 2058      continue;
 2059        if(ret == 0) {
 2060          isoburn_get_track_lba(tracks[0], &lba, 0);
 2061          ret= isoburn_read_iso_head(d, lba, &size, volid, 1);
 2062          if(ret<=0)
 2063      continue;
 2064        }
 2065        if(flag & 4) {
 2066          ret= regexec(&re, volid, 1, match, 0);
 2067          if(ret != 0)
 2068      continue;
 2069        } else {
 2070          if(strcmp(volid, adr_value)!=0)
 2071      continue;
 2072        }
 2073        best_lba= lba;
 2074      }
 2075    }
 2076    if(best_lba<0)
 2077      goto not_found;
 2078    o->fabricated_msc1= best_lba;
 2079 
 2080  } else {
 2081 unknown_mode:;
 2082    sprintf(msg, "Program error: Unknown msc1 address mode %d", adr_mode);
 2083    isoburn_msgs_submit(o, 0x00060000, msg, 0, "FATAL", 0);
 2084    ret= 0; goto ex;
 2085  }
 2086  ret= 1;
 2087 ex:;
 2088  if(start_time != last_pacifier && track_count > 0) {
 2089    now= time(NULL);
 2090    sprintf(msg,
 2091            "Scanned %d tracks for matching volid in %.f seconds",
 2092            track_count, (double) (now - start_time));
 2093    isoburn_msgs_submit(o, 0x00060000, msg, 0, "UPDATE", 0);
 2094  }
 2095  if(disc!=NULL)
 2096    isoburn_toc_disc_free(disc);
 2097  if((flag & 4) && re_valid)
 2098    regfree(&re);
 2099  if(msg != NULL)
 2100    free(msg);
 2101  return(ret);
 2102 }
 2103 
 2104 
 2105 int isoburn_get_mount_params(struct burn_drive *d,
 2106                              int adr_mode, char *adr_value,
 2107                              int *lba, int *track, int *session,
 2108                              char volid[33], int flag)
 2109 {
 2110  int msc1_mem, ret, total_tracks, num_sessions, num_tracks, i, j, track_lba;
 2111  int size, is_iso= 0;
 2112  struct isoburn *o;
 2113  struct isoburn_toc_disc *disc= NULL;
 2114  struct isoburn_toc_session **sessions= NULL;
 2115  struct isoburn_toc_track **tracks= NULL;
 2116 
 2117  *lba= *track= *session= -1;
 2118  volid[0]= 0;
 2119  ret= isoburn_find_emulator(&o, d, 0);
 2120  if(ret < 0 || o == NULL)
 2121    return(-1);
 2122  msc1_mem= o->fabricated_msc1;
 2123  ret= isoburn_set_msc1(d, adr_mode, adr_value, 2 | (flag & 4));
 2124  if(ret <= 0)
 2125    return(ret);
 2126  *lba= o->fabricated_msc1;
 2127 
 2128  disc= isoburn_toc_drive_get_disc(d);
 2129  if(disc==NULL) 
 2130    {ret= -1; goto ex;} /* cannot happen because checked by isoburn_set_msc1 */
 2131  sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions);
 2132  if(sessions==NULL || num_sessions<=0)
 2133    {ret= -1; goto ex;} /* cannot happen because checked by isoburn_set_msc1 */
 2134  total_tracks= 0;
 2135  for(i=0; i<num_sessions && *session < 0; i++) {
 2136    tracks= isoburn_toc_session_get_tracks(sessions[i], &num_tracks);
 2137    if(tracks==NULL)
 2138  continue;
 2139    for(j= 0; j<num_tracks && *track < 0; j++) {
 2140      total_tracks++;
 2141      isoburn_get_track_lba(tracks[j], &track_lba, 0);
 2142      if(track_lba == *lba) {
 2143        *track= total_tracks;
 2144        *session= i + 1;
 2145      }
 2146    }
 2147  }
 2148  ret= isoburn_read_iso_head(d, *lba, &size, volid, 1);
 2149  if(ret <= 0)
 2150    volid[0]= 0;
 2151  else
 2152    is_iso= 1;
 2153 
 2154 ex:;
 2155  o->fabricated_msc1= msc1_mem;
 2156  if(disc != NULL)
 2157    isoburn_toc_disc_free(disc);
 2158  return(2 - is_iso); 
 2159 }
 2160 
 2161