"Fossies" - the Fresh Open Source Software Archive

Member "libisoburn-1.5.4/xorriso/write_run.c" (7 Nov 2020, 133140 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 "write_run.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.5.0_vs_1.5.2.

    1 
    2 
    3 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
    4 
    5    Copyright 2007-2020 Thomas Schmitt, <scdbackup@gmx.net>
    6 
    7    Provided under GPL version 2 or later.
    8 
    9    This file contains functions which are needed to write sessions.
   10 */
   11 
   12 #ifdef HAVE_CONFIG_H
   13 #include "../config.h"
   14 #endif
   15 
   16 #include <ctype.h>
   17 #include <sys/types.h>
   18 #include <unistd.h>
   19 #include <stdlib.h>
   20 #include <stdio.h>
   21 #include <string.h>
   22 #include <sys/stat.h>
   23 #include <sys/time.h>
   24 #include <time.h>
   25 #include <errno.h>
   26 
   27 #include <fcntl.h>
   28 
   29 #ifdef HAVE_STDINT_H
   30 #include <stdint.h>
   31 #else
   32 #ifdef HAVE_INTTYPES_H
   33 #include <inttypes.h>
   34 #endif
   35 #endif
   36 
   37 /* O_BINARY is needed for Cygwin but undefined elsewhere */
   38 #ifndef O_BINARY
   39 #define O_BINARY 0
   40 #endif
   41 
   42 
   43 #ifdef Xorriso_standalonE
   44 
   45 #ifdef Xorriso_with_libjtE
   46 #include "../libjte/libjte.h"
   47 #endif
   48 
   49 #else
   50 
   51 #ifdef Xorriso_with_libjtE
   52 #include <libjte/libjte.h>
   53 #endif
   54 
   55 #endif /* ! Xorriso_standalonE */
   56 
   57 #include "xorriso.h"
   58 #include "xorriso_private.h"
   59 
   60 #include "lib_mgt.h"
   61 #include "drive_mgt.h"
   62 #include "iso_img.h"
   63 #include "iso_tree.h"
   64 #include "write_run.h"
   65 
   66 
   67 /* @param flag bit0= talk of -as cdrecord -multi rather than of -close
   68 */
   69 int Xorriso_check_multi(struct XorrisO *xorriso, struct burn_drive *drive,
   70                         int flag)
   71 {
   72  int profile_no= 0, ret;
   73  struct burn_multi_caps *caps= NULL;
   74  char profile_name[80];
   75 
   76  if(xorriso->auto_close)
   77    xorriso->do_close= 0;
   78  if(!xorriso->do_close) {
   79    burn_disc_get_profile(drive, &profile_no, profile_name);
   80    if(profile_no == 0x14) { /* DVD-RW sequential */
   81      ret= burn_disc_get_multi_caps(drive, BURN_WRITE_TAO, &caps, 0);
   82      if(caps != NULL)
   83        burn_disc_free_multi_caps(&caps);
   84      if(ret == 0) {
   85        if(xorriso->auto_close) {
   86          sprintf(xorriso->info_text,
   87                  "-close \"as_needed\" triggered -close \"on\"");
   88          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
   89          xorriso->do_close= 1;
   90        } else if(flag & 1) {
   91          sprintf(xorriso->info_text,
   92                 "This DVD-RW media can only be written without option -multi");
   93          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
   94          sprintf(xorriso->info_text,
   95                  "Possibly it was blanked by blank=deformat_quickest");
   96          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
   97          sprintf(xorriso->info_text,
   98                  "After writing a session without -multi, apply blank=all");
   99          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
  100          return(0);
  101        } else {
  102          sprintf(xorriso->info_text,
  103                  "This DVD-RW media can only be written with -close \"on\"");
  104          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  105          sprintf(xorriso->info_text,
  106                  "Possibly it was blanked by -blank \"deformat_quickest\"");
  107          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
  108          sprintf(xorriso->info_text,
  109           "After writing a session with -close \"on\", apply -blank \"all\"");
  110          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
  111          return(0);
  112        }
  113      }
  114    } else if(profile_no == 0x15) { /* DVD-RW DL */
  115      if(xorriso->auto_close) {
  116        sprintf(xorriso->info_text,
  117                "-close \"as_needed\" triggered -close \"on\"");
  118        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
  119        xorriso->do_close= 1;
  120      } else if(flag & 1) {
  121        sprintf(xorriso->info_text,
  122                "DVD-R DL media can only be written without option -multi");
  123        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  124        return(0);
  125      } else {
  126        sprintf(xorriso->info_text,
  127                "DVD-R DL media can only be written with -close \"on\"");
  128        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  129        return(0);
  130      }
  131    }
  132  }
  133  return(1);
  134 }
  135 
  136 
  137 int Xorriso_make_write_options(
  138         struct XorrisO *xorriso, struct burn_drive *drive,
  139         struct burn_write_opts **burn_options, int flag)
  140 {
  141  int drive_role, stream_mode= 0, ret, profile;
  142  char profile_name[80];
  143  enum burn_disc_status s;
  144  
  145  *burn_options= burn_write_opts_new(drive);
  146  if(*burn_options==NULL) {
  147    Xorriso_process_msg_queues(xorriso,0);
  148    sprintf(xorriso->info_text,"Cannot allocate option set");
  149    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  150    return(0);
  151  }
  152  burn_write_opts_set_simulate(*burn_options, !!xorriso->do_dummy);
  153  drive_role= burn_drive_get_drive_role(drive);
  154  burn_write_opts_set_multi(*burn_options,
  155                        !(xorriso->do_close || drive_role==0 || drive_role==3));
  156 
  157  ret= burn_disc_get_profile(drive, &profile, profile_name);
  158  if(ret > 0) {
  159    s= isoburn_disc_get_status(drive);
  160    if(xorriso->auto_close && xorriso->do_close == 0 &&
  161       profile == 0x14 && s == BURN_DISC_BLANK)
  162      /* Prepare for missing feature 21h despite drive's announcement */
  163      burn_write_opts_set_fail21h_sev(*burn_options, "NOTE");
  164  }
  165 
  166  if(xorriso->write_speed != -2)
  167    burn_drive_set_speed(drive, 0, xorriso->write_speed);
  168  burn_drive_set_buffer_waiting(drive, xorriso->modesty_on_drive,
  169                                xorriso->min_buffer_usec,
  170                                xorriso->max_buffer_usec,
  171                                xorriso->buffer_timeout_sec,
  172                                xorriso->min_buffer_percent,
  173                                xorriso->max_buffer_percent);
  174  if(xorriso->do_stream_recording == 1)
  175    stream_mode= 1;
  176  else if(xorriso->do_stream_recording == 2)
  177    stream_mode= 51200; /* 100 MB */
  178  else if(xorriso->do_stream_recording >= 16)
  179    stream_mode= xorriso->do_stream_recording;
  180  burn_write_opts_set_stream_recording(*burn_options, stream_mode);
  181 
  182 #ifdef Xorriso_dvd_obs_default_64K
  183  if(xorriso->dvd_obs == 0)
  184    burn_write_opts_set_dvd_obs(*burn_options, 64 * 1024);
  185  else  
  186 #endif
  187    burn_write_opts_set_dvd_obs(*burn_options, xorriso->dvd_obs);
  188 
  189  burn_write_opts_set_stdio_fsync(*burn_options, xorriso->stdio_sync);
  190  burn_write_opts_set_underrun_proof(*burn_options, 1);
  191  return(1);
  192 }
  193 
  194 
  195 /* @param flag bit0= do not write but only prepare and return size in sectors
  196                bit1= do not use isoburn wrappers, do not assume libisofs
  197 */
  198 int Xorriso_sanitize_image_size(struct XorrisO *xorriso,
  199                     struct burn_drive *drive, struct burn_disc *disc,
  200                     struct burn_write_opts *burn_options, int flag)
  201 {
  202  int ret, img_sectors, num_sessions= 0, num_tracks= 0, padding= 0, profile;
  203  off_t media_space;
  204  int lba, nwa, multi_emul_blocks= 0;
  205  char profile_name[80];
  206  struct burn_session **sessions;
  207  struct burn_track **tracks;
  208  enum burn_disc_status s;
  209 
  210  img_sectors= burn_disc_get_sectors(disc);
  211 
  212  sessions= burn_disc_get_sessions(disc, &num_sessions);
  213  if(sessions==NULL || num_sessions < 1) {
  214 no_track:;
  215    Xorriso_process_msg_queues(xorriso,0);
  216    sprintf(xorriso->info_text,"Program error : no track in prepared disc");
  217    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
  218    {ret= -1; goto ex;}
  219  }
  220  tracks= burn_session_get_tracks(sessions[0], &num_tracks);
  221  if(tracks==NULL || num_tracks < 1)
  222    goto no_track;
  223 
  224  padding= 0;
  225  ret= burn_disc_get_profile(drive, &profile, profile_name);
  226  padding= xorriso->padding / 2048;
  227  if(xorriso->padding > padding * 2048)
  228    padding++;
  229  if(img_sectors>0 && ret>0 && 
  230     (profile==0x09 || profile==0x0a)) { /* CD-R , CD-RW */
  231    if(img_sectors + padding < Xorriso_cd_min_track_sizE) {
  232      padding= Xorriso_cd_min_track_sizE - img_sectors;
  233      sprintf(xorriso->info_text,
  234              "Expanded track to minimum size of %d sectors",
  235              Xorriso_cd_min_track_sizE);
  236      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
  237    }
  238  }
  239  if(xorriso->alignment == 0 && ! (xorriso->no_emul_toc & 1)) {
  240    ret= isoburn_needs_emulation(drive);
  241    if(ret > 0) {
  242      /* Take care that the session is padded up to the future NWA.
  243         Else with padding < 32 it could happen that PVDs from older
  244         sessions survive and confuse -rom_toc_scan.
  245       */
  246      xorriso->alignment= 32;
  247      s= isoburn_disc_get_status(drive);
  248      if(s == BURN_DISC_BLANK) {
  249        /* Count blocks before nwa as part of the image */;
  250        ret= isoburn_disc_track_lba_nwa(drive, burn_options, 0, &lba, &nwa);
  251        if(ret <= 0)
  252          nwa= 0;
  253        multi_emul_blocks= nwa;
  254      }
  255    }
  256  }
  257 
  258  if(!(flag & 2)) {
  259 
  260 #ifdef Xorriso_with_libjtE
  261    /* JTE : no multi-session, no_emul_toc, padding in libisofs */
  262    if(xorriso->libjte_handle != NULL)
  263      padding= 0;
  264 #endif /* ! Xorriso_with_libjtE */
  265 
  266    if(xorriso->do_padding_by_libisofs)
  267      padding= 0;
  268  }
  269 
  270  if(xorriso->alignment > 0) {
  271    if(img_sectors > 0) {
  272      ret= isoburn_disc_track_lba_nwa(drive, burn_options, 0, &lba, &nwa);
  273      if(ret <= 0)
  274        nwa= 0;
  275      lba= (nwa + img_sectors + padding) % xorriso->alignment;
  276      if(lba > 0)
  277        padding+= xorriso->alignment - lba;
  278    }
  279  }
  280 
  281  burn_track_define_data(tracks[0], 0, padding * 2048, 0, BURN_MODE1);
  282  Xorriso_process_msg_queues(xorriso,0);
  283 
  284  if(flag&2)
  285    media_space= burn_disc_available_space(drive, burn_options) /
  286                 (off_t) 2048;
  287  else
  288    media_space= isoburn_disc_available_space(drive, burn_options) /
  289                 (off_t) 2048;
  290  if(media_space < img_sectors + padding) {
  291    Xorriso_process_msg_queues(xorriso,0);
  292    sprintf(xorriso->info_text,
  293            "Image size %ds exceeds free space on media %.fs",
  294            img_sectors + padding, (double) media_space);
  295    if(flag & 1) {
  296      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
  297    } else {
  298      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  299      {ret= 0; goto ex;}
  300    }
  301  }
  302  if(flag&1) {
  303    ret= multi_emul_blocks + img_sectors + padding;
  304  } else
  305    ret= 1;
  306 ex:;
  307  return(ret);
  308 }
  309 
  310 
  311 int Xorriso_auto_format(struct XorrisO *xorriso, int flag)
  312 {
  313  int ret, profile, status, num_formats;
  314  char profile_name[80];
  315  struct burn_drive_info *dinfo;
  316  struct burn_drive *drive;
  317  off_t size;
  318  unsigned dummy;
  319 
  320  ret= Xorriso_may_burn(xorriso, 0);
  321  if(ret <= 0)
  322    return(0);
  323 
  324  ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
  325                                 "on attempt to autoformat", 2);
  326  if(ret<=0)
  327    return(0);
  328  ret= burn_disc_get_profile(drive, &profile, profile_name);
  329  if(ret>0 && (profile==0x12 || profile==0x43)) { /* DVD-RAM or BD-RE */
  330    ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats);
  331    if(ret>0 && status==BURN_FORMAT_IS_UNFORMATTED) {
  332      sprintf(xorriso->info_text,
  333              "Unformatted %s medium detected. Trying -format fast.",
  334              profile_name);
  335      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
  336      ret= Xorriso_format_media(xorriso, (off_t) 0, 1 | 4);
  337      if(ret<=0) {
  338        sprintf(xorriso->info_text, "Automatic formatting of %s failed",
  339                profile_name);
  340        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  341        return(ret);
  342      }
  343      burn_drive_re_assess(drive, 0);
  344    }
  345  }
  346  return(1);
  347 }
  348 
  349 
  350 /* @param flag bit0= fail on indev == outdev with "imported_iso"
  351                bit1= fail on indev == NULL with "imported_iso"
  352 */
  353 int Xorriso_check_intvl_string(struct XorrisO *xorriso, char **part_image,
  354                                int flag)
  355 {
  356  char *cpt, *ipt, *orig;
  357 
  358  orig= *part_image;
  359  if(strncmp(*part_image, "--interval:", 11) != 0)
  360    return(0);
  361  if(strchr(*part_image + 11, ':') == NULL)
  362    return(0);
  363  (*part_image)+= 11;
  364  if(!(flag & 3))
  365    return(1);
  366 
  367  cpt= strchr(*part_image, ':');
  368  ipt= strstr(*part_image, "imported_iso");
  369  if(ipt == NULL || ipt > cpt)
  370    return(1);
  371  
  372  if((flag & 2) && xorriso->in_drive_handle == NULL) {
  373    sprintf(xorriso->info_text,
  374          "Interval reader lacks of -indev to read from \"imported_iso\"");
  375    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  376    goto failure;
  377  }
  378 
  379  if(!(flag & 1))
  380    return(1);
  381  if(xorriso->out_drive_handle != xorriso->in_drive_handle)
  382    return(1);
  383  sprintf(xorriso->info_text,
  384          "Interval reader may not read from \"imported_iso\" during write run to same drive");
  385  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  386 
  387 failure:;
  388  sprintf(xorriso->info_text, "Rejected: ");
  389  Text_shellsafe(orig, xorriso->info_text, 1);
  390  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  391  return(-1);
  392 }
  393 
  394 
  395 int Xorriso_set_system_area(struct XorrisO *xorriso, struct burn_drive *drive,
  396                             IsoImage *img, struct isoburn_imgen_opts *sopts,
  397                             int flag)
  398 {
  399  int ret, options, system_area_options, iso_lba= -1, start_lba, image_blocks;
  400  int sa_loaded, read_count, i, read_sum= 0;
  401  char volid[33];
  402  FILE *fp= NULL;
  403  char *buf= NULL, *bufpt= NULL, *intvl;
  404  uint8_t *intvl_buf;
  405  off_t hd_lba, byte_count;
  406  unsigned char *ub;
  407  ElToritoBootImage *bootimg;
  408  IsoFile *bootimg_node;
  409  IsoNode *sparc_core_node;
  410  uint32_t offst;
  411  enum burn_disc_status state;
  412  struct iso_interval_reader *ivr = NULL;
  413 
  414  if(xorriso->grub2_sparc_core[0]) {
  415    ret= Xorriso_node_from_path(xorriso, img, xorriso->grub2_sparc_core,
  416                                &sparc_core_node, 1);
  417    if(ret <= 0) {
  418      sprintf(xorriso->info_text,
  419              "Cannot find in ISO image: -boot_image grub grub2_sparc_core=");
  420      Text_shellsafe(xorriso->grub2_sparc_core, xorriso->info_text, 1);
  421      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  422      {ret= 0; goto ex;}
  423    }
  424    if(!ISO_NODE_IS_FILE(sparc_core_node)) {
  425      sprintf(xorriso->info_text,
  426              "Not a data file: -boot_image grub grub2_sparc_core=");
  427      Text_shellsafe(xorriso->grub2_sparc_core, xorriso->info_text, 1);
  428      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  429      {ret= 0; goto ex;}
  430    }
  431    ret = iso_image_set_sparc_core(img, (IsoFile *) sparc_core_node, 0);
  432    if(ret < 0) {
  433      Xorriso_process_msg_queues(xorriso,0);
  434      Xorriso_report_iso_error(xorriso, "", ret,
  435                     "Error when setting up -boot_image grub grub2_sparc_core=",
  436                      0, "FAILURE", 1);
  437      {ret= 0; goto ex;}
  438    }
  439  }
  440 
  441  Xorriso_alloc_meM(buf, char, 32768);
  442  memset(buf, 0, 32768);
  443  system_area_options= xorriso->system_area_options;
  444  if(xorriso->system_area_clear_loaded)
  445    sa_loaded= 0;
  446  else
  447    sa_loaded= iso_image_get_system_area(img, buf, &options, 0);
  448  if(sa_loaded < 0) {
  449    Xorriso_process_msg_queues(xorriso,0);
  450    Xorriso_report_iso_error(xorriso, "", sa_loaded,
  451                      "Error when inquiring System Area data of ISO 9660 image",
  452                      0, "FAILURE", 1);
  453    {ret= 0; goto ex;}
  454  } if(sa_loaded > 0)
  455    bufpt= buf;
  456  if(xorriso->system_area_disk_path[0] == 0) {
  457    if(xorriso->patch_system_area && xorriso->system_area_options == 0 &&
  458       sa_loaded > 0) {
  459      system_area_options= xorriso->patch_system_area;
  460      /* Check whether partition 1 ends at image end */;
  461      ub= (unsigned char *) buf;
  462      hd_lba= (ub[454] | (ub[455] << 8) | (ub[456] << 16) |
  463               (((unsigned int) ub[457]) << 24)) +
  464              (ub[458] | (ub[459] << 8) | (ub[460] << 16) |
  465               (((unsigned int) ub[461]) << 24));
  466 
  467      iso_lba= -1;
  468      ret= isoburn_disc_get_msc1(drive, &start_lba);
  469      if(ret > 0) {
  470         ret= isoburn_read_iso_head(drive, start_lba, &image_blocks,
  471                                    volid, 1);
  472         if(ret > 0)
  473           iso_lba= start_lba + image_blocks;
  474      }
  475      if(((off_t) iso_lba) * (off_t) 4 > hd_lba) {
  476        system_area_options= 0;
  477      } else if((xorriso->patch_system_area & 1) &&
  478                ((off_t) iso_lba) * (off_t) 4 != hd_lba) {
  479        system_area_options= 0;
  480      } else if((xorriso->patch_system_area & 2) &&
  481                ((off_t) iso_lba) * (off_t) 4 + (off_t) (63 * 256) < hd_lba) {
  482        system_area_options= 0;
  483      } else if(xorriso->patch_system_area & 2) { /* isohybrid patching */
  484        /* Check whether bytes 432-345 point to ElTorito LBA */
  485        hd_lba= ub[432] | (ub[433] << 8) | (ub[434] << 16) |
  486                (((unsigned int) ub[435]) << 24);
  487        ret= iso_image_get_boot_image(img, &bootimg, &bootimg_node, NULL);
  488        if(ret != 1) {
  489          system_area_options= 0;
  490        } else if(bootimg_node != NULL) {
  491          Xorriso__file_start_lba((IsoNode *) bootimg_node, &(iso_lba), 0);
  492          if(((off_t) iso_lba) * (off_t) 4 != hd_lba)
  493            system_area_options= 0;
  494        }
  495      }
  496      if(system_area_options == 0) {
  497        Xorriso_msgs_submit(xorriso, 0,
  498                   "Loaded System Area data are not suitable for MBR patching.",
  499                   0, "DEBUG", 0);
  500      }
  501    }
  502    {ret= 1; goto do_set;}
  503  }
  504 
  505  bufpt= buf;
  506  if(strcmp(xorriso->system_area_disk_path, "/dev/zero") == 0) {
  507    memset(buf, 0, 32768);
  508    {ret= 1; goto do_set;}
  509  }
  510 
  511  intvl= xorriso->system_area_disk_path;
  512  ret= Xorriso_check_intvl_string(xorriso, &intvl, 2);
  513  if(ret < 0) {
  514    {ret= 0; goto ex;}
  515  } else if(ret > 0) {
  516    ret= iso_interval_reader_new(img, intvl, &ivr, &byte_count, 0);
  517    Xorriso_process_msg_queues(xorriso, 0);
  518    if(ret < 0) {
  519 intvl_reader_err:;
  520      sprintf(xorriso->info_text,
  521              "Error when reading -boot_image system_area=");
  522      Text_shellsafe(xorriso->system_area_disk_path, xorriso->info_text, 1);
  523      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
  524      {ret= 0; goto ex;}
  525    }
  526    for(i= 0; i < 16; i++) {
  527      intvl_buf= (uint8_t *) (buf + 2048 * i);
  528      ret= iso_interval_reader_read(ivr, intvl_buf, &read_count, 0);
  529      Xorriso_process_msg_queues(xorriso, 0);
  530      if(ret == 0)
  531    break;
  532      if(ret < 0)
  533        goto intvl_reader_err;
  534      read_sum+= read_count;
  535    }
  536    ret= read_sum;
  537  } else {
  538    ret= Xorriso_afile_fopen(xorriso, xorriso->system_area_disk_path,
  539                             "rb", &fp, 2);
  540    if(ret <= 0)
  541      {ret= 0; goto ex;}
  542    ret= fread(buf, 1, 32768, fp);
  543    if(ret < 32768) {
  544      if(ferror(fp)) {
  545        sprintf(xorriso->info_text,
  546                "Error when reading -boot_image system_area=");
  547        Text_shellsafe(xorriso->system_area_disk_path, xorriso->info_text, 1);
  548        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
  549        {ret= 0; goto ex;}
  550      }
  551    }
  552  }
  553 
  554 do_set:;
  555  if(ret > 0 && xorriso->system_area_disk_path[0]) {
  556    sprintf(xorriso->info_text, "Copying to System Area: %d bytes from file ",
  557            ret);
  558    Text_shellsafe(xorriso->system_area_disk_path, xorriso->info_text, 1);
  559    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
  560  }
  561  ret= isoburn_igopt_set_system_area(sopts, bufpt, system_area_options);
  562  if(ret != ISO_SUCCESS) {
  563    Xorriso_process_msg_queues(xorriso,0);
  564    Xorriso_report_iso_error(xorriso, "", ret,
  565                      "Error when attaching System Area data to ISO 9660 image",
  566                       0, "FAILURE", 1);
  567    {ret= 0; goto ex;}
  568  }
  569  offst= xorriso->partition_offset;
  570  state= isoburn_disc_get_status(drive);
  571  if(state == BURN_DISC_APPENDABLE) {
  572    ret= isoburn_get_img_partition_offset(drive, &offst);
  573    if(ret == 1) {
  574      sprintf(xorriso->info_text,
  575              "Preserving in ISO image: -boot_image any partition_offset=%lu",
  576              (unsigned long) offst);
  577      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
  578    } else
  579      offst= xorriso->partition_offset;
  580  }
  581  ret= isoburn_igopt_set_part_offset(sopts, offst,
  582                                     xorriso->partition_secs_per_head,
  583                                     xorriso->partition_heads_per_cyl);
  584  if(ret != ISO_SUCCESS) {
  585    Xorriso_process_msg_queues(xorriso,0);
  586    Xorriso_report_iso_error(xorriso, "", ret,
  587                        "Error when setting partition offset", 0, "FAILURE", 1);
  588    {ret= 0; goto ex;}
  589  }
  590  ret= 1;
  591 ex:;
  592  if(fp != NULL && fp != stdin)
  593    fclose(fp);
  594  iso_interval_reader_destroy(&ivr, 0);
  595  Xorriso_free_meM(buf);
  596  return(ret);
  597 } 
  598 
  599 
  600 /* @param flag bit0= do not increment boot_count
  601                      and do not reset boot parameters
  602            bit1= dispose attached boot images
  603 */
  604 int Xorriso_attach_boot_image(struct XorrisO *xorriso, int flag)
  605 {
  606  int ret;
  607  char *cpt;
  608  struct burn_drive_info *source_dinfo;
  609  struct burn_drive *source_drive;
  610  IsoImage *image= NULL;
  611  IsoNode *node= NULL;
  612  ElToritoBootImage *bootimg;
  613  enum eltorito_boot_media_type emul_type= ELTORITO_NO_EMUL;
  614  char *bin_path;
  615  int emul, platform_id;
  616  off_t load_size;
  617  struct stat stbuf;
  618  int hflag= 0, is_interval= 0;
  619 
  620  if(xorriso->boot_image_bin_path[0] == 0 && !(flag & 2)) {
  621 
  622    /* >>> no boot image path given : no op */;
  623 
  624    ret= 2; goto ex;
  625  }
  626 
  627  if(xorriso->in_drive_handle == NULL)
  628    hflag= 2;
  629  ret= Xorriso_get_drive_handles(xorriso, &source_dinfo, &source_drive,
  630                                 "on attempt to attach boot image", hflag);
  631  if(ret<=0)
  632    goto ex;
  633  image= isoburn_get_attached_image(source_drive);
  634  if(image == NULL) {
  635    /* (should not happen) */
  636    sprintf(xorriso->info_text,
  637            "No ISO image present on attempt to attach boot image");
  638    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  639    ret= 0; goto ex;
  640  }
  641  if(flag & 2) {
  642    iso_image_remove_boot_image(image);
  643    xorriso->boot_count= 0;
  644    ret= 1; goto ex;
  645  }
  646 
  647  bin_path= xorriso->boot_image_bin_path;
  648  emul= xorriso->boot_image_emul;
  649  platform_id= xorriso->boot_platform_id;
  650  load_size= xorriso->boot_image_load_size;
  651  if(strncmp(bin_path, "--interval:appended_partition_", 30) == 0) {
  652    is_interval= 1;
  653    if(load_size <= 0)
  654      load_size= 512;
  655  }
  656 
  657  if(xorriso->boot_efi_default) {
  658    emul= 0;
  659    platform_id= 0xef;
  660    xorriso->patch_isolinux_image= (xorriso->patch_isolinux_image & ~3) | 0;
  661  }
  662  if((platform_id == 0xef || load_size < 0) && !is_interval) {
  663    ret= Xorriso_iso_lstat(xorriso, bin_path, &stbuf, 2 | 4);
  664    if(ret != 0)
  665      {ret= 0; goto ex;}
  666    load_size= ((stbuf.st_size / (off_t) 512) +
  667               !!(stbuf.st_size % (off_t) 512)) * 512;
  668  }
  669  sprintf(xorriso->info_text, "Adding boot image ");
  670  Text_shellsafe(bin_path, xorriso->info_text, 1);
  671  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
  672 
  673  if(emul == 0)
  674    emul_type= ELTORITO_NO_EMUL;
  675  else if(emul == 1)
  676    emul_type= ELTORITO_HARD_DISC_EMUL;
  677  else if(emul == 2)
  678    emul_type= ELTORITO_FLOPPY_EMUL;
  679 
  680  if (!is_interval) {
  681    ret= Xorriso_node_from_path(xorriso, image, bin_path, &node, 1);
  682    if(ret <= 0) {
  683      sprintf(xorriso->info_text,
  684              "Cannot find in ISO image: -boot_image ... bin_path=");
  685      Text_shellsafe(bin_path, xorriso->info_text, 1);
  686      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  687      {ret= 0; goto ex;}
  688    }
  689  }
  690 
  691  if(xorriso->boot_count == 0) {
  692    if(xorriso->boot_image_cat_path[0] == 0) {
  693      strcpy(xorriso->boot_image_cat_path, bin_path);
  694      cpt= strrchr(xorriso->boot_image_cat_path, '/');
  695      if(cpt == NULL) {
  696        strcpy(xorriso->boot_image_cat_path, "/");
  697        cpt= xorriso->boot_image_cat_path + 1;
  698      } else {
  699        cpt++;
  700      }
  701      strcpy(cpt, "boot.cat");
  702    }
  703    ret= Xorriso_node_from_path(xorriso, image, xorriso->boot_image_cat_path,
  704                                 &node, 1);
  705    if(ret > 0) {
  706      if(!xorriso->do_overwrite) {
  707        sprintf(xorriso->info_text,
  708                "May not overwrite existing -boot_image ... cat_path=");
  709        Text_shellsafe(xorriso->boot_image_cat_path, xorriso->info_text, 1);
  710        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  711        {ret= 0; goto ex;}
  712      }
  713      ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, xorriso->boot_image_cat_path,
  714                       8 | (xorriso->do_overwrite == 1));
  715      if(ret != 1) {
  716        sprintf(xorriso->info_text,
  717                "Could not remove existing -boot_image cat_path=");
  718        Text_shellsafe(xorriso->boot_image_cat_path, xorriso->info_text, 1);
  719        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  720        {ret= 0; goto ex;}
  721      }
  722    }
  723 
  724    /* Discard old boot image, set new one */
  725    ret= iso_image_get_boot_image(image, &bootimg, NULL, NULL);
  726    if(ret == 1)
  727      iso_image_remove_boot_image(image);
  728    ret= iso_image_set_boot_image(image, bin_path, emul_type,
  729                                  xorriso->boot_image_cat_path, &bootimg);
  730    if(ret > 0)
  731      iso_image_set_boot_catalog_weight(image, 1000000000);
  732  } else {
  733    ret= iso_image_add_boot_image(image, bin_path, emul_type, 0, &bootimg);
  734  }
  735  if(ret < 0) {
  736    Xorriso_process_msg_queues(xorriso,0);
  737    Xorriso_report_iso_error(xorriso, "", ret,
  738                  "Error when attaching El-Torito boot image to ISO 9660 image",
  739                  0, "FAILURE", 1);
  740    sprintf(xorriso->info_text,
  741            "Could not attach El-Torito boot image to ISO 9660 image");
  742    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
  743    {ret= 0; goto ex;}
  744  }
  745  el_torito_set_boot_platform_id(bootimg, (uint8_t) platform_id);
  746  if(load_size / 512 > 65535) {
  747    sprintf(xorriso->info_text,
  748            "Boot image load size exceeds 65535 blocks of 512 bytes. ");
  749    if(platform_id == 0xef) {
  750      strcat(xorriso->info_text,
  751             "Will record 0 in El Torito to extend ESP to end-of-medium.");
  752      load_size= 0;
  753    } else {
  754      strcat(xorriso->info_text, "Will record 65535 in El Torito.");
  755      load_size= 65535 * 512;
  756    }
  757    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
  758  }
  759 
  760  if(xorriso->boot_img_full_size) {
  761    el_torito_set_full_load(bootimg, 1);
  762  } else {
  763    /* The function will understand negative short as positive unsigned */
  764    el_torito_set_load_size(bootimg, (short) (load_size / 512)); 
  765  }
  766 
  767  el_torito_set_id_string(bootimg, xorriso->boot_id_string);
  768  el_torito_set_selection_crit(bootimg, xorriso->boot_selection_crit);
  769  ret= Xorriso_set_isolinux_options(xorriso, image, 1);
  770  if(!(flag & 1)) {
  771    /* Register attachment and reset even in case of error return */
  772    xorriso->boot_count++;
  773    xorriso->boot_platform_id= 0;
  774    xorriso->patch_isolinux_image= 0;
  775    xorriso->boot_image_bin_path[0]= 0;
  776    xorriso->boot_image_bin_form[0]= 0;
  777    xorriso->boot_image_emul= 0;
  778    xorriso->boot_emul_default= 1;
  779    xorriso->boot_image_load_size= 4 * 512;
  780    xorriso->boot_img_size_default= 1;
  781    xorriso->boot_img_full_size= 0;
  782    memset(xorriso->boot_id_string, 0, sizeof(xorriso->boot_id_string));
  783    memset(xorriso->boot_selection_crit, 0,
  784           sizeof(xorriso->boot_selection_crit));
  785    xorriso->boot_efi_default= 0;
  786  }
  787  if(ret <= 0)
  788    goto ex;
  789 
  790  ret= 1;
  791 ex:;
  792  if(image != NULL)
  793    iso_image_unref(image);
  794  return(ret);
  795 }
  796 
  797 
  798 int Xorriso_write_application_use(struct XorrisO *xorriso,
  799                                   IsoImage *image, int flag)
  800 {
  801  int l, ret, count= 512;
  802  unsigned int byte= 0;
  803  char *path, data[512];
  804  FILE *fp= NULL;
  805 
  806  path= xorriso->application_use;
  807  l= strlen(path);
  808  if(l <= 1) {
  809    memset(data, path[0], 512);
  810  } else if(l == 4 && path[0] == '0' && path[1] == 'x' &&
  811            isxdigit(path[2]) && isxdigit(path[3])) {
  812    sscanf(path + 2, "%x", &byte);
  813    memset(data, (int) byte, 512);
  814  } else {
  815    /* Read up to 512 bytes from file path */
  816    ret= Xorriso_afile_fopen(xorriso, path, "rb", &fp, 0);
  817    if(ret <= 0)
  818      {ret= 0; goto ex;}
  819    ret= fread(data, 1, 512, fp);
  820    if(ret < 512) {
  821      if(ferror(fp)) {
  822        sprintf(xorriso->info_text,
  823                "-application_use: Error while reading file ");
  824        Text_shellsafe(path, xorriso->info_text, 1);
  825        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text,
  826                            errno, "FAILURE", 0);
  827        ret= 0; goto ex;
  828      }
  829    }
  830    if(ret < 0)
  831      count= 0;
  832    else
  833      count= ret;
  834  }
  835  iso_image_set_app_use(image, data, count);
  836  ret= 1;
  837 ex:
  838  if(fp != NULL && fp != stdin)
  839    fclose(fp);
  840  return(ret);
  841 }
  842 
  843 
  844 int Xorriso_retry_write_session(struct XorrisO *xorriso, int flag)
  845 {
  846  int ret, auto_close_mem, do_close_mem;
  847 
  848  if(xorriso->do_tao == 1) {
  849    Xorriso_msgs_submit(xorriso, 0,
  850     "There is no hope for a re-try with -close \"on\" as long as -write_type is \"tao\"",
  851                        0, "FAILURE", 0);
  852    return(0);
  853  }
  854  Xorriso_msgs_submit(xorriso, 0, "Re-trying with -close \"on\"", 0, "NOTE", 0);
  855  do_close_mem= xorriso->do_close;
  856  auto_close_mem= xorriso->auto_close;
  857  xorriso->do_close= 1;
  858  xorriso->auto_close= 0;
  859  ret= Xorriso_write_session(xorriso, 0);
  860  xorriso->do_close= do_close_mem;
  861  xorriso->auto_close= auto_close_mem;
  862  return(ret);
  863 }
  864 
  865 
  866 int Xorriso_make_iso_write_opts(struct XorrisO *xorriso, IsoImage *image,
  867                                 struct isoburn_imgen_opts *sopts, int flag)
  868 {
  869  int ext, i, ret, pad_by_libisofs= 0, is_bootable= 0, relax, intvl_string= 0;
  870  int intvl_check= 2; /* 3 forbids "imported_iso" */
  871  char *out_cs, *part_image;
  872  IsoNode *root_node;
  873  uint32_t padding;
  874 
  875  relax= xorriso->relax_compliance;
  876  if(image != NULL)
  877    is_bootable= iso_image_get_boot_image(image, NULL, NULL, NULL);
  878 
  879  /* xorriso->patch_isolinux_image gets reset in Xorriso_attach_boot_image()
  880     So this applies only to -boot_image ... "patch" or "keep".
  881     >>> Better would be to analyze and keep the relaxations of the loaded image.
  882   */
  883  if((xorriso->patch_isolinux_image & 1) && is_bootable == 1)
  884    relax|= isoburn_igopt_allow_full_ascii;
  885 
  886  out_cs= xorriso->out_charset;
  887  if(out_cs == NULL)
  888    Xorriso_get_local_charset(xorriso, &out_cs, 0);
  889 
  890  isoburn_igopt_set_level(sopts, xorriso->iso_level);
  891  ext= ((!!xorriso->do_rockridge) * isoburn_igopt_rockridge) |
  892       ((!!xorriso->do_joliet) * isoburn_igopt_joliet) |
  893       ((!!xorriso->do_hfsplus) * isoburn_igopt_hfsplus) |
  894       ((!!xorriso->do_fat) * isoburn_igopt_fat) |
  895       ((!!xorriso->do_iso1999) * isoburn_igopt_iso1999) |
  896       (( !(xorriso->ino_behavior & 2)) * isoburn_igopt_hardlinks) |
  897       (( (!(xorriso->ino_behavior & 2)) ||
  898          (xorriso->do_aaip & (2 | 8 | 16 | 256)) ||
  899          (xorriso->do_md5 & (2 | 4)) ||
  900          xorriso->do_hfsplus
  901        ) * isoburn_igopt_aaip) |
  902       ((!!(xorriso->do_md5 & 2)) * isoburn_igopt_session_md5) |
  903       ((!!(xorriso->do_md5 & 4)) * isoburn_igopt_file_md5) |
  904       ((!!(xorriso->do_md5 & 8)) * isoburn_igopt_file_stability) |
  905       ((!!xorriso->do_old_empty) * isoburn_igopt_old_empty) |
  906       ((flag & 1) * isoburn_igopt_will_cancel);
  907  if(xorriso->no_emul_toc & 1)
  908    ext|= isoburn_igopt_no_emul_toc;
  909  isoburn_igopt_set_extensions(sopts, ext);
  910  isoburn_igopt_set_relaxed(sopts, relax);
  911  ret = isoburn_igopt_set_rr_reloc(sopts, xorriso->rr_reloc_dir,
  912                                   xorriso->rr_reloc_flags);
  913  if(ret <= 0)
  914    {ret= 0; goto ex;}
  915  ret= isoburn_igopt_set_untranslated_name_len(sopts,
  916                                               xorriso->untranslated_name_len);
  917  if(ret <= 0)
  918    {ret= 0; goto ex;}
  919  isoburn_igopt_set_sort_files(sopts, 1);
  920  isoburn_igopt_set_over_mode(sopts, 0, 0, (mode_t) 0, (mode_t) 0);
  921  isoburn_igopt_set_over_ugid(sopts, 2 * !!xorriso->do_global_uid,
  922                              2 * !!xorriso->do_global_gid,
  923                              (uid_t) xorriso->global_uid,
  924                              (gid_t) xorriso->global_gid);
  925  isoburn_igopt_set_out_charset(sopts, out_cs);
  926  isoburn_igopt_set_fifo_size(sopts, xorriso->fs * 2048);
  927  Ftimetxt(time(NULL), xorriso->scdbackup_tag_time, 8);
  928  isoburn_igopt_set_scdbackup_tag(sopts, xorriso->scdbackup_tag_name,
  929                                  xorriso->scdbackup_tag_time,
  930                                  xorriso->scdbackup_tag_written);
  931  if(xorriso->prep_partition[0]) {
  932    part_image= xorriso->prep_partition;
  933    intvl_string= Xorriso_check_intvl_string(xorriso, &part_image, intvl_check);
  934    if(intvl_string < 0)
  935      {ret= 0; goto ex;}
  936    ret= isoburn_igopt_set_prep_partition(sopts, part_image, intvl_string);
  937    if(ret <= 0)
  938      {ret= 0; goto ex;}
  939  }
  940  if(xorriso->efi_boot_partition[0]) {
  941    part_image= xorriso->efi_boot_partition;
  942    intvl_string= Xorriso_check_intvl_string(xorriso, &part_image, intvl_check);
  943    if(intvl_string < 0)
  944      {ret= 0; goto ex;}
  945    ret= isoburn_igopt_set_efi_bootp(sopts, part_image, intvl_string);
  946    if(ret <= 0)
  947      {ret= 0; goto ex;}
  948  }
  949  for(i= 0; i < Xorriso_max_appended_partitionS; i++) {
  950    if(xorriso->appended_partitions[i] == NULL)
  951  continue;
  952    if(xorriso->appended_partitions[i][0] == 0)
  953  continue;
  954    if(strcmp(xorriso->appended_partitions[i], ".") == 0)
  955      part_image= "";
  956    else
  957      part_image= xorriso->appended_partitions[i];
  958    intvl_string= Xorriso_check_intvl_string(xorriso, &part_image, intvl_check);
  959    if(intvl_string < 0)
  960      {ret= 0; goto ex;}
  961    isoburn_igopt_set_partition_img(sopts, i + 1,
  962                                   xorriso->appended_part_types[i], part_image);
  963    isoburn_igopt_set_part_flag(sopts, i + 1, intvl_string);
  964    isoburn_igopt_set_part_type_guid(sopts, i + 1,
  965                                     xorriso->appended_part_type_guids[i],
  966                                     xorriso->appended_part_gpt_flags[i] & 1);
  967  }
  968  isoburn_igopt_set_appended_as_gpt(sopts, xorriso->appended_as_gpt);
  969  isoburn_igopt_set_appended_as_apm(sopts, xorriso->appended_as_apm);
  970  isoburn_igopt_set_part_like_isohybrid(sopts, xorriso->part_like_isohybrid);
  971  isoburn_igopt_set_iso_mbr_part_type(sopts, xorriso->iso_mbr_part_type);
  972  isoburn_igopt_set_iso_type_guid(sopts, xorriso->iso_gpt_type_guid,
  973                                         xorriso->iso_mbr_part_flag & 1);
  974  isoburn_igopt_set_gpt_guid(sopts, xorriso->gpt_guid, xorriso->gpt_guid_mode);
  975  isoburn_igopt_set_disc_label(sopts, xorriso->ascii_disc_label); 
  976  isoburn_igopt_set_hfsp_serial_number(sopts, xorriso->hfsp_serial_number);
  977  isoburn_igopt_set_hfsp_block_size(sopts, xorriso->hfsp_block_size,
  978                                           xorriso->apm_block_size);
  979  isoburn_igopt_set_pvd_times(sopts,
  980                     xorriso->vol_creation_time, xorriso->vol_modification_time,
  981                     xorriso->vol_expiration_time, xorriso->vol_effective_time,
  982                     xorriso->vol_uuid);
  983 
  984 #ifdef Xorriso_with_libjtE
  985  if(xorriso->libjte_handle && (xorriso->libjte_params_given & (4 | 8))) {
  986 
  987    /* >>> Check whether the mandatory parameters are set */;
  988 
  989    ret= libjte_set_outfile(xorriso->libjte_handle, xorriso->outdev);
  990    Xorriso_process_msg_queues(xorriso, 0);
  991    if(ret <= 0)
  992      goto ex;
  993    isoburn_igopt_attach_jte(sopts, xorriso->libjte_handle);
  994    pad_by_libisofs= 1;
  995  }
  996 #endif /* Xorriso_with_libjtE */
  997 
  998  if(xorriso->do_padding_by_libisofs || pad_by_libisofs) {
  999    /* Padding to be done by libisofs, not by libburn.
 1000    */
 1001    padding= xorriso->padding / 2048;
 1002    if((uint32_t) xorriso->padding > padding * 2048)
 1003      padding++;
 1004 /*
 1005 fprintf(stderr, "XORRISO_DEBUG: isoburn_igopt_set_tail_blocks(%d)\n",
 1006         (int) padding);
 1007 */
 1008    isoburn_igopt_set_tail_blocks(sopts, padding);
 1009  }
 1010 
 1011  /* Make final abort check before starting expensive activities */
 1012  ret= Xorriso_eval_problem_status(xorriso, 1, 0);
 1013  if(ret<0)
 1014    {ret= 0; goto ex;}
 1015 
 1016  if(xorriso->zisofs_by_magic && image != NULL) {
 1017    sprintf(xorriso->info_text,
 1018            "Checking disk file content for zisofs compression headers.");
 1019    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
 1020    root_node= (IsoNode *) iso_image_get_root(image);
 1021    ret= iso_node_zf_by_magic(root_node,
 1022                       (xorriso->out_drive_handle == xorriso->in_drive_handle) |
 1023                       2 | 16 | (xorriso->zisofs_by_magic << 8));
 1024    if(ret<0) {
 1025      Xorriso_report_iso_error(xorriso, "", ret,
 1026               "Error when examining file content for zisofs headers",
 1027               0, "FAILURE", 1);
 1028    }
 1029    ret= Xorriso_eval_problem_status(xorriso, 1, 0);
 1030    if(ret<0)
 1031      {ret= 0; goto ex;}
 1032    sprintf(xorriso->info_text,
 1033            "Check for zisofs compression headers done.");
 1034    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
 1035  }
 1036 
 1037  ret = isoburn_igopt_set_write_type(sopts, xorriso->do_tao);
 1038  if(ret <= 0)
 1039    goto ex;
 1040  ret = isoburn_igopt_set_stdio_endsync(sopts, xorriso->stdio_sync >= 0);
 1041  if(ret <= 0)
 1042    goto ex;
 1043 
 1044  ret= 1;
 1045 ex:;
 1046  return(ret);
 1047 }
 1048 
 1049 
 1050 int Xorriso_set_all_file_dates(struct XorrisO *xorriso, int flag)
 1051 {
 1052  int idx, ret, was_failure= 0;
 1053  char *hargv[4];
 1054 
 1055  if(xorriso->all_file_dates[0] == 0)
 1056    return(2);
 1057  if(strcmp(xorriso->all_file_dates, "set_to_mtime") == 0) {
 1058    hargv[0]= "/";
 1059    hargv[1]= "-exec";
 1060    hargv[2]= "set_to_mtime";
 1061    hargv[3]= "--";
 1062    idx= 0;
 1063    ret= Xorriso_option_find(xorriso, 4, hargv, &idx, 0);
 1064    if(ret <= 0)
 1065      was_failure= 1;
 1066  } else {
 1067    hargv[0]= "/";
 1068    idx= 0;
 1069    ret= Xorriso_option_alter_date(xorriso, "b", xorriso->all_file_dates,
 1070                                   1, hargv, &idx, 1);
 1071    if(ret <= 0)
 1072      was_failure= 1;
 1073    idx= 0;
 1074    ret= Xorriso_option_alter_date(xorriso, "c", xorriso->all_file_dates,
 1075                                   1, hargv, &idx, 1);
 1076    if(ret <= 0)
 1077      was_failure= 1;
 1078  }
 1079  Xorriso_relax_compliance(xorriso, "always_gmt", 0);
 1080  return(!was_failure);
 1081 }
 1082 
 1083 
 1084 /* @param flag bit0= do not write but only prepare and return size in sectors
 1085    @return <=0 error , 1= success
 1086            2= failure with DVD-RW, please call Xorriso_retry_write_session()
 1087 */
 1088 int Xorriso_write_session(struct XorrisO *xorriso, int flag)
 1089 {
 1090  int ret, i, pacifier_speed= 0, data_lba, is_bootable= 0;
 1091  int freshly_bootable= 0, hide_attr, signal_mode, role, is_bdr_pow= 0;
 1092  char *xorriso_id= NULL, *img_id, *sfe= NULL, *out_cs;
 1093  struct isoburn_imgen_opts *sopts= NULL;
 1094  struct burn_drive_info *dinfo, *source_dinfo;
 1095  struct burn_drive *drive, *source_drive;
 1096  struct burn_disc *disc= NULL;
 1097  struct burn_write_opts *burn_options= NULL;
 1098  off_t readcounter= 0,writecounter= 0;
 1099  int num_sessions= 0, num_tracks= 0;
 1100  struct burn_session **sessions;
 1101  struct burn_track **tracks;
 1102  enum burn_disc_status s;
 1103  IsoImage *image= NULL;
 1104  int profile_number;
 1105  char *profile_name= NULL, *reasons= NULL;
 1106  IsoBoot *bootcat_node;
 1107 
 1108  Xorriso_alloc_meM(sfe, char, 5 * SfileadrL);
 1109  Xorriso_alloc_meM(xorriso_id, char, 256);
 1110  Xorriso_alloc_meM(profile_name, char, 80);
 1111  Xorriso_alloc_meM(reasons, char, BURN_REASONS_LEN);
 1112 
 1113  ret= Xorriso_finish_hl_update(xorriso, 0);
 1114  if(ret <= 0)
 1115    goto ex;
 1116 
 1117  ret= Xorriso_set_all_file_dates(xorriso, 1);
 1118  if(ret <= 0)
 1119    goto ex;
 1120 
 1121  out_cs= xorriso->out_charset;
 1122  if(out_cs == NULL)
 1123    Xorriso_get_local_charset(xorriso, &out_cs, 0);
 1124 
 1125  ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
 1126                                 "on attempt to write", 2);
 1127  if(ret<=0)
 1128    goto ex;
 1129  if(!(flag & 1)) {
 1130    ret= Xorriso_auto_format(xorriso, 0);
 1131    if(ret <=0 )
 1132      {ret= 0; goto ex;}
 1133  }
 1134 
 1135  is_bdr_pow= burn_drive_get_bd_r_pow(drive);
 1136  if(is_bdr_pow) {
 1137    sprintf(xorriso->info_text,
 1138            "May not write to Pseudo Overwrite formatted BD-R medium");
 1139    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1140    {ret= 0; goto ex;}
 1141  }
 1142 
 1143  s= isoburn_disc_get_status(drive);
 1144  if (xorriso->do_hfsplus && (
 1145      (xorriso->grow_blindly_msc2 >= 0 &&
 1146        xorriso->out_drive_handle != xorriso->in_drive_handle)
 1147      ||
 1148      (xorriso->out_drive_handle == xorriso->in_drive_handle && 
 1149       s != BURN_DISC_BLANK)
 1150     )) {
 1151    sprintf(xorriso->info_text,
 1152            "May not grow ISO image while -hfsplus is enabled");
 1153    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1154    {ret= 0; goto ex;}
 1155  }
 1156  if(xorriso->out_drive_handle == xorriso->in_drive_handle) {
 1157    if(abs(xorriso->displacement_sign) == 1 && xorriso->displacement != 0 &&
 1158       s != BURN_DISC_BLANK) {
 1159      sprintf(xorriso->info_text,
 1160              "May not grow ISO image while -displacement is non-zero");
 1161      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1162      {ret= 0; goto ex;}
 1163    }
 1164    source_drive= drive;
 1165  } else {
 1166    if(xorriso->in_drive_handle == NULL) {
 1167      source_drive= drive;
 1168    } else {
 1169      ret= Xorriso_get_drive_handles(xorriso, &source_dinfo, &source_drive,
 1170                                     "on attempt to get source for write", 0);
 1171      if(ret<=0)
 1172        goto ex;
 1173    }
 1174    if(s!=BURN_DISC_BLANK) {
 1175      s= burn_disc_get_status(drive);
 1176      if(s!=BURN_DISC_BLANK)
 1177        sprintf(xorriso->info_text,
 1178                "-indev differs from -outdev and -outdev media is not blank");
 1179      else
 1180        sprintf(xorriso->info_text,
 1181           "-indev differs from -outdev and -outdev media holds non-zero data");
 1182      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1183      {ret= 0; goto ex;}
 1184    }
 1185  }
 1186  ret= Xorriso_get_profile(xorriso, &profile_number, profile_name, 2);
 1187  if(ret == 2)
 1188    pacifier_speed= 1;
 1189  else if(ret == 3)
 1190    pacifier_speed= 2;
 1191 
 1192  ret= Xorriso_check_multi(xorriso, drive, 0);
 1193  if(ret<=0) 
 1194    goto ex;
 1195 
 1196  ret= isoburn_igopt_new(&sopts, 0);
 1197  if(ret<=0) {
 1198    Xorriso_process_msg_queues(xorriso, 0);
 1199    goto ex;
 1200  }
 1201 
 1202  xorriso->alignment= 0;
 1203  image= isoburn_get_attached_image(source_drive);
 1204  if(image != NULL) {
 1205    iso_image_set_application_id(image, xorriso->application_id);
 1206    iso_image_set_publisher_id(image, xorriso->publisher);
 1207    iso_image_set_system_id(image, xorriso->system_id);
 1208    iso_image_set_volset_id(image, xorriso->volset_id);
 1209    iso_image_set_copyright_file_id(image, xorriso->copyright_file);
 1210    iso_image_set_biblio_file_id(image, xorriso->biblio_file);
 1211    iso_image_set_abstract_file_id(image, xorriso->abstract_file);
 1212    Xorriso_write_application_use(xorriso, image, 0);
 1213    Xorriso_process_msg_queues(xorriso,0);
 1214  }
 1215 
 1216  if((xorriso->do_aaip & 256) && out_cs != NULL) {
 1217    static char *names = "isofs.cs";
 1218    size_t value_lengths[1];
 1219 
 1220    value_lengths[0]= strlen(out_cs);
 1221    ret= Xorriso_setfattr(xorriso, NULL, "/",
 1222                          (size_t) 1, &names, value_lengths, &out_cs, 2 | 8);
 1223    if(ret<=0)
 1224      goto ex;
 1225  }
 1226  if(iso_image_was_blind_attrs(image, 0))
 1227    Xorriso_msgs_submit(xorriso, 0,
 1228                        "Some file xattr namespace could not be explored",
 1229                        0, "WARNING", 0);
 1230  
 1231  if(image!=NULL && 12+strlen(Xorriso_timestamP)<80) {
 1232    strcpy(xorriso_id, xorriso->preparer_id);
 1233    img_id= (char *) iso_image_get_data_preparer_id(image);
 1234    if(img_id!=NULL) {
 1235      for(i= strlen(img_id)-1; i>=0 && img_id[i]==' '; i--);
 1236      if(i>0) {
 1237        sprintf(xorriso->info_text, "Overwrote previous preparer id '%s'",
 1238                img_id);
 1239        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
 1240      }
 1241    }
 1242    iso_image_set_data_preparer_id(image, xorriso_id);
 1243  }
 1244  ret= Xorriso_set_system_area(xorriso, source_drive, image, sopts, 0);
 1245  if(ret <= 0)
 1246    goto ex;
 1247 
 1248  /* Activate, adjust or discard boot image */
 1249  if(image!=NULL) {
 1250    if(xorriso->boot_image_bin_path[0]) {
 1251      ret= Xorriso_attach_boot_image(xorriso, xorriso->boot_count == 0);
 1252      if(ret <= 0)
 1253        goto ex;
 1254      freshly_bootable= 1;
 1255    }
 1256    is_bootable= iso_image_get_boot_image(image, NULL, NULL, &bootcat_node);
 1257  }
 1258  if(image!=NULL && !(flag&1)) {
 1259    if(xorriso->boot_count > 0 || freshly_bootable) {
 1260      /* Eventually rename boot catalog node to changed boot_image_cat_path */
 1261      if(is_bootable > 0) {
 1262        ret= Xorriso_path_from_node(xorriso, (IsoNode *) bootcat_node, sfe, 0);
 1263        if(ret > 0) {
 1264          if(strcmp(sfe, xorriso->boot_image_cat_path) != 0) {
 1265            ret= Xorriso_rename(xorriso, NULL, sfe,
 1266                                xorriso->boot_image_cat_path, 1);
 1267            if(ret <= 0)
 1268              goto ex;
 1269          }
 1270        }
 1271      }
 1272      hide_attr= !!(xorriso->boot_image_cat_hidden);
 1273      if(xorriso->boot_image_cat_hidden & 1)
 1274        hide_attr|= LIBISO_HIDE_ON_RR;
 1275      if(xorriso->boot_image_cat_hidden & 2)
 1276        hide_attr|= LIBISO_HIDE_ON_JOLIET;
 1277      if(xorriso->boot_image_cat_hidden & 4)
 1278        hide_attr|= LIBISO_HIDE_ON_HFSPLUS;
 1279      iso_image_set_boot_catalog_hidden(image, hide_attr);
 1280    } else if(xorriso->patch_isolinux_image & 1) {
 1281      if(is_bootable == 1) {
 1282        /* will imply isoburn_igopt_allow_full_ascii */
 1283        sprintf(xorriso->info_text, "Patching boot info table");
 1284        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1285 
 1286        ret= Xorriso_path_from_lba(xorriso, NULL, xorriso->loaded_boot_bin_lba,
 1287                                    sfe, 1);
 1288        if(ret < 0)
 1289          goto ex;
 1290        if(ret == 0) {
 1291          sprintf(xorriso->info_text,
 1292                  "Cannot patch boot image: no file found for its LBA.");
 1293          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1294          sprintf(xorriso->info_text,
 1295            "Probably the loaded boot image file was deleted in this session.");
 1296          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1297          sprintf(xorriso->info_text,
 1298            "Use -boot_image \"any\" \"discard\" or set new boot image");
 1299          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
 1300          goto ex;
 1301        }
 1302        ret= Xorriso_set_isolinux_options(xorriso, image, 0);
 1303        if(ret <= 0)
 1304          goto ex;
 1305      } else if(!freshly_bootable) {
 1306        sprintf(xorriso->info_text,
 1307                "Could not find any boot image for -boot_image patching");
 1308        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
 1309      }
 1310    } else if(xorriso->keep_boot_image && is_bootable == 1) {
 1311      /* will imply isoburn_igopt_allow_full_ascii */
 1312      sprintf(xorriso->info_text, "Keeping boot image unchanged");
 1313      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1314    } else if(is_bootable == 1) {
 1315      iso_image_remove_boot_image(image);
 1316      sprintf(xorriso->info_text, "Discarded boot image from old session");
 1317      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1318    }
 1319    /* hardcoded and regardless whether a catalog will get written */
 1320    iso_image_set_boot_catalog_weight(image, 1000000000);
 1321  }
 1322  
 1323  if((xorriso->do_aaip & 16) || !(xorriso->ino_behavior & 2)) {
 1324    /* Overwrite isofs.st of root node by xorriso->isofs_st_out */
 1325    char *name= "isofs.st";
 1326    char timestamp[16], *value= timestamp;
 1327    size_t value_length;
 1328 
 1329    sprintf(timestamp, "%.f", (double) xorriso->isofs_st_out);
 1330    value_length= strlen(timestamp);
 1331    Xorriso_setfattr(xorriso, NULL, "/", (size_t) 1, &name,
 1332                     &value_length, &value, 2 | 8);
 1333  }
 1334 
 1335  ret= Xorriso_make_iso_write_opts(xorriso, image, sopts, flag & 1);
 1336  if(ret <= 0)
 1337    goto ex;
 1338 
 1339  /* >>> omit iso_image_update_sizes if the image was filled up very quickly */;
 1340 
 1341  ret= iso_image_update_sizes(image);
 1342  if(ret < 0) {
 1343    Xorriso_process_msg_queues(xorriso, 0);
 1344    if(ret<0) {
 1345      Xorriso_report_iso_error(xorriso, "", ret,
 1346               "Error when updating file sizes",
 1347               0, "FAILURE", 1);
 1348    }
 1349    ret= Xorriso_eval_problem_status(xorriso, 1, 0);
 1350    if(ret<0)
 1351      {ret= 0; goto ex;}
 1352  }
 1353 
 1354  Xorriso_set_abort_severity(xorriso, 1);
 1355  if (xorriso->grow_blindly_msc2 >= 0 &&
 1356      xorriso->out_drive_handle != xorriso->in_drive_handle) {
 1357    ret= isoburn_prepare_blind_grow(source_drive, &disc, sopts, drive,
 1358                                    xorriso->grow_blindly_msc2);
 1359    if(ret>0) {
 1360      /* Allow the consumer of output to access the input drive */
 1361      source_drive= NULL;
 1362      ret= Xorriso_give_up_drive(xorriso, 1|8); 
 1363      if(ret<=0)
 1364        goto ex;
 1365    }
 1366  } else if(xorriso->out_drive_handle == xorriso->in_drive_handle ||
 1367            xorriso->in_drive_handle == NULL) {
 1368    ret= isoburn_prepare_disc(source_drive, &disc, sopts);
 1369  } else {
 1370    ret= isoburn_prepare_new_image(source_drive, &disc, sopts, drive);
 1371  }
 1372  if(ret <= 0) {
 1373    Xorriso_process_msg_queues(xorriso,0);
 1374    sprintf(xorriso->info_text,"Failed to prepare session write run");
 1375    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1376    {ret= 0; goto ex;}
 1377  }
 1378 
 1379  ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0);
 1380  if(ret<=0)
 1381    goto cancel_iso;
 1382  isoburn_igopt_get_effective_lba(sopts, &(xorriso->session_lba));
 1383  if(xorriso->do_stream_recording == 2) {
 1384    ret= isoburn_igopt_get_data_start(sopts, &data_lba);
 1385    if(ret > 0 && data_lba >= 16)
 1386      burn_write_opts_set_stream_recording(burn_options, data_lba);
 1387  }
 1388 
 1389  ret= Xorriso_sanitize_image_size(xorriso, drive, disc, burn_options, flag&1);
 1390  if(ret<=0 || (flag&1)) {
 1391    Xorriso_process_msg_queues(xorriso,0);
 1392    if(flag&1) /* set queue severity to FAILURE */
 1393      Xorriso_set_image_severities(xorriso, 2);
 1394    if(flag&1) /* reset queue severity */
 1395      Xorriso_set_image_severities(xorriso, 0);
 1396    goto cancel_iso;
 1397  }
 1398 
 1399  ret= Xorriso_may_burn(xorriso, 0);
 1400  if(ret <= 0)
 1401    goto cancel_iso;
 1402 
 1403  role= burn_drive_get_drive_role(drive);
 1404 
 1405  /* Important: do not return until burn_is_aborting() was checked */
 1406 
 1407  signal_mode= 1;
 1408  if(role == 1)
 1409    signal_mode|= 2;
 1410  Xorriso_set_signal_handling(xorriso, signal_mode);
 1411 
 1412  /* De-activate eventual target file truncation in dummy mode */
 1413  ret= isoburn_set_truncate(drive, (!xorriso->do_dummy) | 2 | 4);
 1414  if(ret < 0)
 1415    goto cancel_iso;
 1416 
 1417  xorriso->run_state= 1; /* Indicate that burning has started */
 1418  isoburn_disc_write(burn_options, disc);
 1419  burn_write_opts_free(burn_options);
 1420  burn_options= NULL;
 1421 
 1422  ret= Xorriso_pacifier_loop(xorriso, drive, pacifier_speed << 4);
 1423  if(burn_is_aborting(0))
 1424    Xorriso_abort(xorriso, 0); /* Never comes back */
 1425  Xorriso_set_signal_handling(xorriso, 0);
 1426  if(ret<=0)
 1427    goto ex;
 1428  if(!isoburn_drive_wrote_well(drive)) {
 1429    isoburn_cancel_prepared_write(source_drive, drive, 0);
 1430    Xorriso_process_msg_queues(xorriso,0);
 1431    if(xorriso->auto_close && xorriso->do_close == 0) {
 1432      if(burn_drive_was_feat21_failure(drive)) {
 1433        sprintf(xorriso->info_text,
 1434          "libburn indicates failure with writing DVD-RW to appendable state.");
 1435        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1436        /* Urge caller to call Xorriso_retry_write_session() */
 1437        ret= 2; goto ex;
 1438      }
 1439    }
 1440    sprintf(xorriso->info_text,
 1441            "libburn indicates failure with writing.");
 1442    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1443    ret= 0; goto ex;
 1444  }
 1445  Xorriso_process_msg_queues(xorriso,0);
 1446 
 1447  sessions= burn_disc_get_sessions(disc, &num_sessions);
 1448  if(num_sessions>0) {
 1449    tracks= burn_session_get_tracks(sessions[0], &num_tracks);
 1450    if(tracks!=NULL && num_tracks>0) {
 1451      burn_track_get_counters(tracks[0],&readcounter,&writecounter);
 1452      xorriso->session_blocks= (int) (writecounter/ (off_t) 2048);
 1453      sprintf(xorriso->info_text,
 1454   "ISO image produced: %d sectors\nWritten to medium : %d sectors at LBA %d\n",
 1455         (int) (readcounter/ (off_t) 2048),
 1456         xorriso->session_blocks, xorriso->session_lba);
 1457      Xorriso_info(xorriso, 0);
 1458    }
 1459  }
 1460  ret= isoburn_activate_session(drive);
 1461  Xorriso_process_msg_queues(xorriso,0);
 1462  if(ret<=0) {
 1463    sprintf(xorriso->info_text,
 1464            "Could not write new set of volume descriptors");
 1465    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 1466    goto ex;
 1467  }
 1468  /* Done early to free any reference to the libisofs resources via disc */
 1469  if(disc!=NULL)
 1470    burn_disc_free(disc);
 1471  disc= NULL;
 1472  /* To wait for the end of the libisofs threads and their messages. */
 1473  isoburn_sync_after_write(source_drive, drive, 0);
 1474  Xorriso_process_msg_queues(xorriso,0);
 1475 
 1476  sprintf(xorriso->info_text, "Writing to %s completed successfully.\n\n",
 1477          Text_shellsafe(xorriso->outdev,sfe,0));
 1478  Xorriso_info(xorriso, 0);
 1479  ret= 1;
 1480 ex:;
 1481  xorriso->run_state= 0; /* Indicate that burning has ended */
 1482  Xorriso_set_abort_severity(xorriso, 0);
 1483 
 1484  if(ret<=0) {
 1485 
 1486    /* >>> ??? revive discarded boot image */;
 1487 
 1488    /* suppress automatic -commit at program end */
 1489    xorriso->volset_change_pending= 3;
 1490  }
 1491  if(disc!=NULL)
 1492    burn_disc_free(disc);
 1493  if(image != NULL)
 1494    iso_image_unref(image);
 1495  isoburn_igopt_destroy(&sopts, 0);
 1496  if(burn_options != NULL)
 1497    burn_write_opts_free(burn_options);
 1498  Xorriso_process_msg_queues(xorriso,0);
 1499  Xorriso_append_scdbackup_record(xorriso, 0);
 1500  Xorriso_free_meM(sfe);
 1501  Xorriso_free_meM(xorriso_id);
 1502  Xorriso_free_meM(profile_name);
 1503  Xorriso_free_meM(reasons);
 1504  return(ret);
 1505 
 1506 cancel_iso:;
 1507  isoburn_cancel_prepared_write(source_drive, drive, 0);
 1508  goto ex;
 1509 } 
 1510 
 1511 
 1512 int Xorriso_check_burn_abort(struct XorrisO *xorriso, int flag)
 1513 {
 1514  int ret;
 1515  struct burn_drive_info *dinfo;
 1516  struct burn_drive *drive;
 1517 
 1518  if(burn_is_aborting(0))
 1519    return(2);
 1520  if(xorriso->run_state!=1)
 1521    return(0);
 1522  ret= Xorriso_eval_problem_status(xorriso, 1, 1);
 1523  if(ret>=0)
 1524    return(0);
 1525  sprintf(xorriso->info_text,
 1526          "-abort_on '%s' encountered '%s' during image writing",
 1527          xorriso->abort_on_text, xorriso->problem_status_text);
 1528  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
 1529                      xorriso->problem_status_text, 0);
 1530 
 1531  ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
 1532                                 "on attempt to abort burn run", 2);
 1533  if(ret<=0)
 1534    return(0);
 1535 
 1536  burn_drive_cancel(drive);
 1537  sprintf(xorriso->info_text,
 1538          "libburn has now been urged to cancel its operation");
 1539  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1540  return(1);
 1541 }
 1542 
 1543 
 1544 /* This loop watches burn runs until they end.
 1545    It issues pacifying update messages to the user.
 1546    @param flag bit0-3 = emulation mode
 1547                         0= xorriso
 1548                         1= mkisofs
 1549                         2= cdrecord
 1550                bit4= report speed in CD units
 1551                bit5= report speed in BD units
 1552 */
 1553 int Xorriso_pacifier_loop(struct XorrisO *xorriso, struct burn_drive *drive,
 1554                           int flag)
 1555 {
 1556  int ret, size, free_bytes, i, aborting= 0, emul, buffer_fill= 50, last_sector;
 1557  int iso_wait_counter= 0, iso_cancel_limit= 5;
 1558  struct burn_progress progress;
 1559  char *status_text, date_text[80], *speed_unit, mem_text[8];
 1560  enum burn_drive_status drive_status;
 1561  double start_time, current_time, last_time, base_time= 0.0, base_count= 0.0;
 1562  double next_base_time= 0.0, next_base_count= 0.0, first_base_time= 0.0;
 1563  double first_base_count= 0.0, norm= 0.0, now_time, fract_offset= 0.0;
 1564  double measured_speed, speed_factor= 1385000, quot, speed_min_time;
 1565  double tdiff, now_fract;
 1566  time_t time_prediction;
 1567  IsoImage *image= NULL;
 1568 
 1569  image= isoburn_get_attached_image(drive);
 1570 
 1571  start_time= Sfile_microtime(0);
 1572  while(burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)
 1573    usleep(100002);
 1574 
 1575  emul= flag&15;
 1576  if(emul==0)
 1577    emul= xorriso->pacifier_style;
 1578  fract_offset= 1.0 / 3.0 * (double) emul - ((int) (1.0 / 3.0 * (double) emul));
 1579  speed_min_time= 0.2 * xorriso->pacifier_interval;
 1580  speed_unit= "D";
 1581  if(flag&16) {
 1582    speed_factor= 150.0*1024;
 1583    speed_unit= "C";
 1584  } else if(flag & 32) {
 1585    speed_factor= 4495625;
 1586    speed_unit= "B";
 1587  }
 1588  progress.sector= 0;
 1589  current_time= Sfile_microtime(0);
 1590  measured_speed= 0.0;
 1591  while(1) {
 1592    last_time= current_time;
 1593    last_sector= progress.sector;
 1594    drive_status= burn_drive_get_status(drive, &progress);
 1595 
 1596    if(drive_status == BURN_DRIVE_IDLE) {
 1597      /* To avoid a race condition between burn_source and libisofs
 1598         writer thread: Wait for ISO generator thread to have finished.
 1599         After some seconds kick it by isoburn_cancel_prepared_write()
 1600         which waits for the write thread to end.
 1601      */
 1602      if(image == NULL)
 1603  break;
 1604      if(!iso_image_generator_is_running(image))
 1605  break;
 1606      iso_wait_counter++;
 1607      if(iso_wait_counter > iso_cancel_limit) {
 1608        isoburn_cancel_prepared_write(drive, NULL, 0);
 1609  break;
 1610      }
 1611    }
 1612    current_time= Sfile_microtime(0);
 1613    if(drive_status == BURN_DRIVE_WRITING && progress.sectors > 0) {
 1614      if(current_time-last_time > speed_min_time)
 1615        measured_speed= (progress.sector - last_sector) * 2048.0 /
 1616                        (current_time - last_time);
 1617      buffer_fill= 50;
 1618      if(progress.buffer_capacity>0)
 1619        buffer_fill= (double) (progress.buffer_capacity
 1620                               - progress.buffer_available) * 100.0
 1621                     / (double) progress.buffer_capacity;
 1622      if(emul==2) {
 1623        if(progress.sector<=progress.sectors)
 1624          sprintf(xorriso->info_text, "%4d of %4d MB written",
 1625                  progress.sector / 512, progress.sectors / 512);
 1626        else
 1627          sprintf(xorriso->info_text, "%4d MB written",
 1628                  progress.sector / 512);
 1629 
 1630        if(xorriso->pacifier_fifo!=NULL)
 1631          ret= burn_fifo_inquire_status(xorriso->pacifier_fifo,
 1632                                        &size, &free_bytes, &status_text);
 1633        else
 1634          ret= isoburn_get_fifo_status(drive, &size, &free_bytes, &status_text);
 1635        if(ret>0 )
 1636          sprintf(xorriso->info_text+strlen(xorriso->info_text),
 1637                  " (fifo %2d%%)", 
 1638                  (int) (100.0-100.0*((double) free_bytes)/(double) size));
 1639 
 1640        sprintf(xorriso->info_text+strlen(xorriso->info_text), " [buf %3d%%]",
 1641                buffer_fill);
 1642 
 1643        if(current_time-last_time > speed_min_time)
 1644          sprintf(xorriso->info_text+strlen(xorriso->info_text), "  %4.1fx.",
 1645                  measured_speed/speed_factor);
 1646 
 1647      } else if(emul == 1 &&
 1648                progress.sectors > 0 && progress.sector <= progress.sectors) {
 1649        /* "37.87% done, estimate finish Tue Jul 15 18:55:07 2008" */
 1650 
 1651        quot= ((double) progress.sector) / ((double) progress.sectors);
 1652        sprintf(xorriso->info_text, " %2.2f%% done", quot*100.0);
 1653        if(current_time - start_time >= 2 && quot > 0.0 &&
 1654           (quot >= 0.02 || progress.sector >= 5*1024)) {
 1655          if(base_time == 0.0 && progress.sector >= 16*1024) {
 1656            first_base_time= base_time= next_base_time= current_time;
 1657            first_base_count= next_base_count= progress.sector;
 1658          } else if(next_base_time > 0 && current_time - next_base_time >= 10) {
 1659            base_time= next_base_time;
 1660            base_count= next_base_count;
 1661            next_base_time= current_time;
 1662            next_base_count= progress.sector;
 1663          }
 1664          if(first_base_time > 0 &&
 1665             current_time - first_base_time >= 10 &&
 1666             progress.sectors > first_base_count &&
 1667             progress.sector > first_base_count) {
 1668            norm= (1.0 - quot);
 1669            if(norm < 0.0001)
 1670              norm= 0.0001;
 1671            quot= ((double) progress.sector - first_base_count)
 1672                   / ((double) progress.sectors - first_base_count);
 1673            time_prediction= norm * (1.0 - quot) / quot
 1674                             * (current_time - first_base_time);
 1675          } else {
 1676            time_prediction= (1.0 - quot) / quot * (current_time - start_time);
 1677            norm= 1.0;
 1678          }
 1679          if(base_time > 0 && 
 1680             current_time - base_time >= 10 && progress.sectors > base_count) {
 1681            quot= ((double) progress.sector - base_count)
 1682                   / ((double) progress.sectors - base_count);
 1683            time_prediction+= (1.0 - quot) / quot * (current_time - base_time);
 1684            norm+= 1.0;
 1685          }
 1686          time_prediction/= norm;
 1687          if(time_prediction < 30*86400 && time_prediction > 0) {
 1688            time_prediction+= current_time + 1;
 1689            Ftimetxt(time_prediction, date_text, 4);
 1690            sprintf(xorriso->info_text+strlen(xorriso->info_text),
 1691                    ", estimate finish %s", date_text);
 1692          }
 1693        }
 1694      } else {
 1695        if(progress.sector<=progress.sectors) {
 1696          if(progress.sectors <= 0)
 1697            strcpy(mem_text, " 99.9");
 1698          else
 1699            sprintf(mem_text, "%5.1f",
 1700              100.0 * ((double) progress.sector) / ((double) progress.sectors));
 1701          mem_text[5]= 0;
 1702          sprintf(xorriso->info_text, "Writing: %10ds  %s%% ",
 1703                  progress.sector, mem_text);
 1704        } else {
 1705          Sfile_scale(2048.0 * (double) progress.sector, mem_text, 5, 1e4, 1);
 1706          sprintf(xorriso->info_text, "Writing: %10ds   %s ",
 1707                  progress.sector, mem_text);
 1708        }
 1709        ret= isoburn_get_fifo_status(drive, &size, &free_bytes, &status_text);
 1710        if(ret>0 )
 1711          sprintf(xorriso->info_text+strlen(xorriso->info_text),
 1712                  "  fifo %3d%%  buf %3d%%",
 1713                  (int) (100.0-100.0*((double) free_bytes)/(double) size),
 1714                  buffer_fill);
 1715        if(current_time - last_time > speed_min_time)
 1716          sprintf(xorriso->info_text+strlen(xorriso->info_text), "  %5.1fx%s ",
 1717                  measured_speed/speed_factor, speed_unit);
 1718      }
 1719    } else if(drive_status == BURN_DRIVE_CLOSING_SESSION ||
 1720              drive_status == BURN_DRIVE_CLOSING_TRACK)
 1721      sprintf(xorriso->info_text,
 1722              "Closing track/session. Working since %.f seconds",
 1723              current_time-start_time);
 1724    else if(drive_status == BURN_DRIVE_FORMATTING)
 1725      sprintf(xorriso->info_text, "Formatting. Working since %.f seconds",
 1726              current_time-start_time);
 1727    else
 1728      sprintf(xorriso->info_text,
 1729              "Thank you for being patient. Working since %.f seconds.",
 1730              current_time-start_time);
 1731    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
 1732 
 1733    for(i= 0; i < 20; i++) { /* 10 usleeps more than supposed to be needed */
 1734      Xorriso_process_msg_queues(xorriso, 0);
 1735      if(aborting<=0)
 1736        aborting= Xorriso_check_burn_abort(xorriso, 0);
 1737      usleep((unsigned long) (100000.0 * xorriso->pacifier_interval));
 1738      now_time= Sfile_microtime(0);
 1739      tdiff= ((off_t)(now_time / xorriso->pacifier_interval)) -
 1740             (off_t)(current_time / xorriso->pacifier_interval);
 1741      now_fract= (now_time / xorriso->pacifier_interval -
 1742                  (off_t)(now_time / xorriso->pacifier_interval));
 1743      if(tdiff < 1.0)
 1744    continue; 
 1745      if(fract_offset <= 0.0) /* "xorriso" pacifier shall not wait for slot */
 1746    break;
 1747      if((now_fract >= fract_offset && now_fract < fract_offset + 0.3) ||
 1748         tdiff >= 2.0)
 1749    break;
 1750    }
 1751  }
 1752  iso_image_unref(image);
 1753  return(1);
 1754 }
 1755 
 1756 
 1757 /* @param flag bit0= fast
 1758                bit1= deformat
 1759                bit2= do not re-aquire drive
 1760    @return 0=failure, did not touch medium , -1=failure, altered medium
 1761            1=success, altered medium       ,  2=success, did not touch medium
 1762 */
 1763 int Xorriso_blank_media(struct XorrisO *xorriso, int flag)
 1764 {
 1765  int ret, do_deformat= 0, signal_mode, using_immed;
 1766  struct burn_drive_info *dinfo;
 1767  struct burn_drive *drive;
 1768  enum burn_disc_status disc_state;
 1769  struct burn_progress p;
 1770  double percent = 1.0;
 1771  int current_profile;
 1772  char current_profile_name[80];
 1773  time_t start_time;
 1774  char mode_names[4][80]= {"all", "fast", "deformat", "deformat_quickest"};
 1775  char progress_text[40];
 1776 
 1777  ret= Xorriso_may_burn(xorriso, 0);
 1778  if(ret <= 0)
 1779    return(0);
 1780  ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
 1781                                 "on attempt to -blank", 2);
 1782  if(ret<=0)
 1783    return(0);
 1784 
 1785  burn_disc_get_profile(drive, &current_profile, current_profile_name);
 1786 
 1787  disc_state = isoburn_disc_get_status(drive);
 1788  if(current_profile == 0x13) { /* overwritable DVD-RW */
 1789    /* Depending on flag bit1 formatted DVD-RW will get blanked to sequential
 1790       state or pseudo blanked by invalidating an eventual ISO image. */
 1791    if(flag&2)
 1792      do_deformat= 1;
 1793  } else if(current_profile == 0x14) { /* sequential DVD-RW */
 1794    if((flag&1) && !(flag&2)) {
 1795      sprintf(xorriso->info_text,
 1796              "-blank: DVD-RW present. Mode 'fast' defaulted to mode 'all'.");
 1797      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1798      sprintf(xorriso->info_text,
 1799              "Mode 'deformat_quickest' produces single-session-only media.");
 1800      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
 1801      flag&= ~1;
 1802    }
 1803  }
 1804  if(disc_state == BURN_DISC_BLANK) {
 1805    if(!do_deformat) {
 1806      sprintf(xorriso->info_text,
 1807              "Blank medium detected. Will leave it untouched");
 1808      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1809      return 2;
 1810    }
 1811  } else if(disc_state==BURN_DISC_FULL || disc_state==BURN_DISC_APPENDABLE) {
 1812    ;
 1813  } else if(disc_state == BURN_DISC_EMPTY) {
 1814    sprintf(xorriso->info_text,"No media detected in drive");
 1815    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1816    return 0;
 1817  } else {
 1818    sprintf(xorriso->info_text, "Unsuitable drive and media state");
 1819    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1820    return 0;
 1821  }
 1822  if(!isoburn_disc_erasable(drive)) {
 1823    sprintf(xorriso->info_text, "Media is not of erasable type");
 1824    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1825    return 0;
 1826  }
 1827  if(xorriso->do_dummy) {
 1828    sprintf(xorriso->info_text,
 1829            "-dummy mode prevents blanking of medium in mode '%s'.",
 1830            mode_names[flag&3]);
 1831    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1832    return(1);
 1833  }
 1834  using_immed= burn_drive_get_immed(drive);
 1835  sprintf(xorriso->info_text, "Beginning to blank medium in mode '%s'.\n",
 1836          mode_names[flag&3]);
 1837  Xorriso_info(xorriso,0);
 1838 
 1839  /* Important: do not return until burn_is_aborting() was checked */
 1840  signal_mode= 1;
 1841  ret= burn_drive_get_drive_role(drive);
 1842  if(ret == 1)
 1843    signal_mode|= 2;
 1844  Xorriso_set_signal_handling(xorriso, signal_mode);
 1845 
 1846  if(do_deformat)
 1847    burn_disc_erase(drive, (flag&1));
 1848  else
 1849    isoburn_disc_erase(drive, (flag&1));
 1850  start_time= time(0);
 1851  usleep(1000000);
 1852  if(!using_immed)
 1853    sprintf(progress_text, "synchronously since");
 1854  while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
 1855    Xorriso_process_msg_queues(xorriso,0);
 1856    if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
 1857      percent = 1.0 + ((double) p.sector+1.0) / ((double) p.sectors) * 98.0;
 1858    if(using_immed)
 1859      sprintf(progress_text, "%.1f%% done in", percent);
 1860    sprintf(xorriso->info_text, "Blanking  ( %s %d seconds )",
 1861            progress_text, (int) (time(0) - start_time));
 1862    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
 1863    usleep(1000000);
 1864  }
 1865  Xorriso_process_msg_queues(xorriso,0);
 1866  if(burn_is_aborting(0))
 1867    Xorriso_abort(xorriso, 0); /* Never comes back */
 1868  Xorriso_set_signal_handling(xorriso, 0);
 1869  if(burn_drive_wrote_well(drive)) {
 1870    sprintf(xorriso->info_text, "Blanking done\n");
 1871    Xorriso_info(xorriso,0);
 1872  } else {
 1873    sprintf(xorriso->info_text, "Blanking failed.");
 1874    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1875  }
 1876  if(!(flag & 4)) {
 1877    ret= Xorriso_reaquire_outdev(xorriso, 
 1878                   2 + (xorriso->in_drive_handle == xorriso->out_drive_handle));
 1879    if(ret <= 0)
 1880      return(-1);
 1881  }
 1882  return(1);
 1883 }
 1884 
 1885 
 1886 /* @param flag bit0= try to achieve faster formatting
 1887                bit1= use parameter size (else use default size)
 1888                bit2= do not re-aquire drive
 1889                bit5= try to disable Defect Management
 1890                bit7= by_index mode:
 1891                      bit8 to bit15 contain the index of the format to use.
 1892    @return 0=failure, did not touch medium , -1=failure, altered medium
 1893            1=success, altered medium       ,  2=success, did not touch medium
 1894 */
 1895 int Xorriso_format_media(struct XorrisO *xorriso, off_t in_size, int flag)
 1896 {
 1897  int ret, mode_flag= 0, index, status, num_formats, signal_mode, using_immed;
 1898  unsigned dummy;
 1899  struct burn_drive_info *dinfo;
 1900  struct burn_drive *drive;
 1901  struct burn_progress p;
 1902  double percent = 1.0;
 1903  int current_profile;
 1904  char current_profile_name[80], progress_text[40];
 1905  off_t size= 0;
 1906  time_t start_time;
 1907  enum burn_disc_status disc_state;
 1908 
 1909  ret= Xorriso_may_burn(xorriso, 0);
 1910  if(ret <= 0)
 1911    return(0);
 1912  ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
 1913                                 "on attempt to -format", 2);
 1914  if(ret<=0)
 1915    return(0);
 1916 
 1917  if(flag & 2) {
 1918    mode_flag= 0; /* format to given size */
 1919  } else {
 1920    mode_flag= 4; /* format to full size */
 1921  }
 1922  if(flag & 32)
 1923    mode_flag|= 32; /* try to disable Defect Management */
 1924  
 1925  burn_disc_get_profile(drive, &current_profile, current_profile_name);
 1926 
 1927  if(flag&128) { /* by_index */
 1928    index= (flag>>8) & 0xff;
 1929    ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats);
 1930    if(ret<=0)
 1931      num_formats= 0;
 1932    if(ret<=0 || index<0 || index>=num_formats) {
 1933      if(num_formats>0)
 1934        sprintf(xorriso->info_text,
 1935             "-format by_index_%d: format descriptors range from index 0 to %d",
 1936             index, num_formats-1);
 1937      else
 1938        sprintf(xorriso->info_text,
 1939                "-format by_index_%d: no format descriptors available", index);
 1940      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1941      return(0);
 1942    }
 1943    mode_flag|= (flag & 0xff80);
 1944    if(flag&1)
 1945      mode_flag|= (1<<6);
 1946 
 1947  } else if(current_profile == 0x12) { /* DVD+RAM */
 1948    if(!(flag & 2))
 1949      mode_flag= 6; /* format to default payload size */
 1950    if(flag&1)
 1951      mode_flag|= (1<<6);
 1952 
 1953  } else if(current_profile == 0x13) { /* DVD-RW */
 1954    if(flag&1) {
 1955      sprintf(xorriso->info_text,
 1956           "Detected formatted DVD-RW. Thus omitting desired fast format run.");
 1957      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1958      return(2);
 1959    }
 1960 
 1961  } else if(current_profile == 0x14) { /* DVD-RW sequential */
 1962    if(flag & 1) {
 1963      size= 128*1024*1024;
 1964      mode_flag= 1; /* format to size, then write size of zeros */
 1965    } else
 1966      mode_flag= 4;
 1967 
 1968  } else if(current_profile == 0x1a) { /* DVD+RW */
 1969    if(flag&1) {
 1970      sprintf(xorriso->info_text,
 1971              "Detected DVD+RW. Thus omitting desired fast format run.");
 1972      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1973      return(2);
 1974    }
 1975 
 1976  } else if(current_profile == 0x41) { /* BD-R SRM */
 1977    if(!(flag & 2))
 1978      mode_flag= 6; /* format to default payload size */
 1979    if(flag&1)
 1980      mode_flag|= (1<<6);
 1981 
 1982  } else if(current_profile == 0x43) { /* BD-RE */
 1983    if(!(flag & (2 | 32)))
 1984      mode_flag= 6; /* format to default payload size */
 1985    if(flag&1)
 1986      mode_flag|= (1<<6);
 1987 
 1988  } else {
 1989    sprintf(xorriso->info_text,
 1990           "-format: Unsuitable media detected.");
 1991    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 1992    sprintf(xorriso->info_text,"Media current: %s (%4.4xh)",
 1993            current_profile_name, current_profile);
 1994    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 1995    return(0);
 1996  }
 1997  if(!(flag & 1))
 1998    mode_flag|= 16; /* enable re-formatting */
 1999 
 2000  if(xorriso->do_dummy) {
 2001    sprintf(xorriso->info_text, "-dummy mode prevents formatting of medium.");
 2002    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 2003    return(1);
 2004  }
 2005  using_immed= burn_drive_get_immed(drive);
 2006  sprintf(xorriso->info_text, "Beginning to format medium.\n");
 2007  Xorriso_info(xorriso, 0);
 2008  if(flag & 2)
 2009    size= in_size;
 2010 
 2011  /* Important: do not return until burn_is_aborting() was checked */
 2012  signal_mode= 1;
 2013  ret= burn_drive_get_drive_role(drive);
 2014  if(ret == 1)
 2015    signal_mode|= 2;
 2016  Xorriso_set_signal_handling(xorriso, signal_mode);
 2017 
 2018  burn_disc_format(drive, size, mode_flag);
 2019 
 2020  start_time= time(0);
 2021  usleep(1000000);
 2022  if(!using_immed)
 2023    sprintf(progress_text, "synchronously since");
 2024  while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
 2025    Xorriso_process_msg_queues(xorriso,0);
 2026    if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
 2027      percent = 1.0 + ((double) p.sector+1.0) / ((double) p.sectors) * 98.0;
 2028    if(using_immed)
 2029      sprintf(progress_text, "%.1f%% done in", percent);
 2030    sprintf(xorriso->info_text, "Formatting  ( %s %d seconds )",
 2031            progress_text, (int) (time(0) - start_time));
 2032    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
 2033    usleep(1000000);
 2034  }
 2035  Xorriso_process_msg_queues(xorriso,0);
 2036  if(burn_is_aborting(0))
 2037    Xorriso_abort(xorriso, 0); /* Never comes back */
 2038  Xorriso_set_signal_handling(xorriso, 0);
 2039  
 2040  if(burn_drive_wrote_well(drive)) {
 2041    sprintf(xorriso->info_text, "Formatting done\n");
 2042    Xorriso_info(xorriso,0);
 2043  } else {
 2044    sprintf(xorriso->info_text,
 2045            "libburn indicates failure with formatting."); 
 2046    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2047    return(-1);
 2048  }
 2049 
 2050  if(!(flag & 4)) {
 2051    ret= Xorriso_reaquire_outdev(xorriso, 
 2052                   2 + (xorriso->in_drive_handle == xorriso->out_drive_handle));
 2053    if(ret <= 0)
 2054      return(-1);
 2055  }
 2056  disc_state = isoburn_disc_get_status(drive);
 2057  if(disc_state==BURN_DISC_FULL && !(flag&1)) {
 2058    /* Blank because full format certification pattern might be non-zero */
 2059    ret= Xorriso_blank_media(xorriso, 1);
 2060    if(ret <= 0)
 2061      return(0);
 2062  }
 2063  return(1);
 2064 }
 2065 
 2066 
 2067 /* @param flag bit2= formatting rather than blanking
 2068    @return 0=failure, did not touch medium , -1=failure, altered medium
 2069            1=success, altered medium       ,  2=success, did not touch medium
 2070 */
 2071 int Xorriso_blank_as_needed(struct XorrisO *xorriso, int flag)
 2072 {
 2073  int ret, is_formatted= -1, status, num_formats, did_work= 0;
 2074  struct burn_drive_info *dinfo;
 2075  struct burn_drive *drive;
 2076  enum burn_disc_status disc_state;
 2077  unsigned dummy;
 2078  int current_profile;
 2079  char current_profile_name[80];
 2080  off_t size;
 2081 
 2082  ret= Xorriso_may_burn(xorriso, 0);
 2083  if(ret <= 0)
 2084    return(0);
 2085  ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
 2086                                 "on attempt to blank or format", 2);
 2087  if(ret<=0)
 2088    return(0);
 2089 
 2090  burn_disc_get_profile(drive, &current_profile, current_profile_name);
 2091 
 2092  ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats);
 2093  if(ret>0) {
 2094    if(status==BURN_FORMAT_IS_FORMATTED)
 2095      is_formatted= 1;
 2096    else if(status == BURN_FORMAT_IS_UNFORMATTED)
 2097      is_formatted= 0;
 2098  }
 2099  if(current_profile == 0x12 || current_profile == 0x43) { /* DVD+RAM , BD-RE */
 2100    if(is_formatted<0) {
 2101      sprintf(xorriso->info_text,
 2102              "-blank or -format: Unclear formatting status of %s",
 2103              current_profile_name);
 2104      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2105      return(0);
 2106    }
 2107    if(!is_formatted) {
 2108      ret= Xorriso_format_media(xorriso, (off_t) 0, (current_profile == 0x43));
 2109      if(ret <= 0)
 2110        return(ret);
 2111      did_work= (ret == 1);
 2112    }
 2113  } else if(current_profile == 0x14 && (flag&4)) { /* DVD-RW sequential */
 2114    ret= Xorriso_format_media(xorriso, (off_t) 0, 0);
 2115    if(ret <= 0)
 2116      return(ret);
 2117    did_work= (ret == 1);
 2118  } else if(current_profile == 0x41) { /* BD-R SRM */
 2119    if((flag & 4) && !is_formatted) {
 2120      ret= Xorriso_format_media(xorriso, (off_t) 0, 1);
 2121      if(ret <= 0)
 2122        return(ret);
 2123      did_work= (ret == 1);
 2124    }
 2125  }
 2126 
 2127  disc_state = isoburn_disc_get_status(drive);
 2128  if(disc_state != BURN_DISC_BLANK && !(flag&4)) {
 2129    ret= Xorriso_blank_media(xorriso, 1);
 2130    return(ret);
 2131  }
 2132  if(did_work)
 2133    return(1);
 2134  sprintf(xorriso->info_text, "%s as_needed: no need for action detected",
 2135          (flag&4) ? "-format" : "-blank");
 2136  Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 2137  return(2);
 2138 }
 2139 
 2140 
 2141 int Xorriso_retry_burn_track(struct XorrisO *xorriso,
 2142                              off_t write_start_address,
 2143                              char *track_source, off_t tsize, int flag)
 2144 {
 2145  int ret, auto_close_mem, do_close_mem;
 2146 
 2147  if(xorriso->do_tao == 1) {
 2148    Xorriso_msgs_submit(xorriso, 0,
 2149     "There is no hope for a re-try with -close \"on\" as long as -write_type is \"tao\"",
 2150                        0, "FAILURE", 0);
 2151    return(0);
 2152  }
 2153  Xorriso_msgs_submit(xorriso, 0, "Re-trying with -close \"on\"", 0, "NOTE", 0);
 2154  do_close_mem= xorriso->do_close;
 2155  auto_close_mem= xorriso->auto_close;
 2156  xorriso->do_close= 1;
 2157  xorriso->auto_close= 0;
 2158  ret= Xorriso_burn_track(xorriso, write_start_address, track_source, tsize,
 2159                          flag);
 2160  xorriso->do_close= do_close_mem;
 2161  xorriso->auto_close= auto_close_mem;
 2162  return(ret);
 2163 }
 2164 
 2165 
 2166 /* @param write_start_address  is valid if >=0    
 2167    @param tsize                is valid if >0
 2168    @param flag bit0= grow_overwriteable_iso
 2169                bit1= do_isosize
 2170                bit2= do_xa1 conversion
 2171    @return <=0 error , 1= success
 2172             2= failure with DVD-RW, please call Xorriso_retry_burn_track()
 2173 */
 2174 int Xorriso_burn_track(struct XorrisO *xorriso, off_t write_start_address,
 2175                        char *track_source, off_t tsize, int flag)
 2176 {
 2177  int ret, fd, profile_number, is_cd= 0, dummy, nwa= -1;
 2178  int isosize= -1, do_isosize, is_bd= 0, signal_mode;
 2179  struct burn_drive_info *dinfo;
 2180  struct burn_drive *drive;
 2181  struct burn_write_opts *burn_options= NULL;
 2182  struct burn_disc *disc= NULL;
 2183  struct burn_session *session= NULL;
 2184  struct burn_track *track= NULL;
 2185  struct stat stbuf; 
 2186  off_t fixed_size= 0;
 2187  struct burn_source *data_src= NULL, *fifo_src= NULL;
 2188  enum burn_disc_status disc_state;
 2189  char *reasons= NULL, *profile_name= NULL;
 2190  char *head_buffer= NULL;
 2191 
 2192  Xorriso_alloc_meM(reasons, char, BURN_REASONS_LEN);
 2193  Xorriso_alloc_meM(profile_name, char, 80);
 2194  Xorriso_alloc_meM(head_buffer, char, 64 * 1024);
 2195 
 2196  ret= Xorriso_may_burn(xorriso, 0);
 2197  if(ret <= 0)
 2198    {ret= 0; goto ex;}
 2199  ret= Xorriso_auto_format(xorriso, 0);
 2200  if(ret <=0 )
 2201    {ret= 0; goto ex;}
 2202 
 2203  do_isosize= !!(flag&2);
 2204  ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
 2205                                 "on attempt to burn track", 2);
 2206  if(ret<=0)
 2207    {ret= 0; goto ex;}
 2208 
 2209  ret= Xorriso_check_multi(xorriso, drive, 1);
 2210  if(ret<=0) 
 2211    goto ex;
 2212  ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0);
 2213  if(ret<=0)
 2214    goto ex;
 2215 
 2216  disc= burn_disc_create();
 2217  session= burn_session_create();
 2218  ret= burn_disc_add_session(disc,session,BURN_POS_END);
 2219  if(ret==0) {
 2220    sprintf(xorriso->info_text, "Cannot add session object to disc object.");
 2221    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 2222    goto ex;
 2223  }
 2224  track= burn_track_create();
 2225  if(track_source[0] == '-' && track_source[1] == 0) {
 2226    fd= 0;
 2227  } else {
 2228    if(xorriso->fs >= 64)
 2229      fd= burn_os_open_track_src(track_source, O_RDONLY, 0);
 2230    else
 2231      fd= open(track_source, O_RDONLY | O_BINARY);
 2232    if(fd>=0)
 2233      if(fstat(fd,&stbuf)!=-1)
 2234        if((stbuf.st_mode&S_IFMT)==S_IFREG)
 2235          fixed_size= stbuf.st_size;
 2236  }
 2237 
 2238  if(fd>=0)
 2239    data_src= burn_fd_source_new(fd, -1, fixed_size);
 2240  if(data_src==NULL) {
 2241    sprintf(xorriso->info_text, "Could not open data source ");
 2242    Text_shellsafe(track_source, xorriso->info_text, 1);
 2243    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 2244    ret= 0; goto ex;
 2245  }
 2246  if((do_isosize || xorriso->fs != 0) && xorriso->fs < 64)
 2247    xorriso->fs= 64;
 2248  if(xorriso->fs > 0) {
 2249    fifo_src= burn_fifo_source_new(data_src, 2048 + 8 * !!(flag & 4),
 2250                                   xorriso->fs, 1);
 2251    if(fifo_src == NULL) {
 2252      sprintf(xorriso->info_text, "Could not create fifo object of %.f MB",
 2253              ((double) xorriso->fs) / 1024.0 / 1024.0);
 2254      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 2255      ret= 0; goto ex;
 2256    }
 2257  } 
 2258  xorriso->pacifier_fifo= fifo_src;
 2259  if(burn_track_set_source(track, fifo_src == NULL ? data_src : fifo_src)
 2260     != BURN_SOURCE_OK) {
 2261    sprintf(xorriso->info_text,
 2262            "Cannot attach source object to track object");
 2263    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 2264    ret= 0; goto ex;
 2265  }
 2266  burn_track_set_cdxa_conv(track, !!(flag & 4));
 2267  burn_session_add_track(session, track, BURN_POS_END);
 2268  burn_source_free(data_src);
 2269 
 2270  if(flag&1)
 2271    /* consider overwriteables with ISO as appendable */
 2272    disc_state= isoburn_disc_get_status(drive);
 2273  else
 2274    /* handle overwriteables as always blank */
 2275    disc_state= burn_disc_get_status(drive);
 2276 
 2277  if(disc_state == BURN_DISC_BLANK || disc_state == BURN_DISC_APPENDABLE) {
 2278    /* ok */;
 2279  } else {
 2280    if(disc_state == BURN_DISC_FULL) {
 2281      sprintf(xorriso->info_text,
 2282           "Closed media with data detected. Need blank or appendable media.");
 2283      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2284      if(burn_disc_erasable(drive)) {
 2285        sprintf(xorriso->info_text, "Try -blank as_needed\n");
 2286        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
 2287      }
 2288    } else if(disc_state == BURN_DISC_EMPTY) {
 2289      sprintf(xorriso->info_text, "No media detected in drive");
 2290      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2291    } else {
 2292      sprintf(xorriso->info_text,
 2293              "Cannot recognize state of drive and media");
 2294      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2295    }
 2296    ret= 0; goto ex;
 2297  }
 2298  if(isoburn_needs_emulation(drive))
 2299    burn_write_opts_set_multi(burn_options, 0);
 2300 
 2301  if(tsize > 0) {
 2302    fixed_size= tsize;
 2303    burn_track_set_size(track, fixed_size);
 2304  }
 2305  if(do_isosize) {
 2306    ret= burn_fifo_peek_data(xorriso->pacifier_fifo, head_buffer, 64*1024, 0);
 2307    if(ret<=0) {
 2308      Xorriso_process_msg_queues(xorriso,0);
 2309      sprintf(xorriso->info_text,
 2310              "Cannot obtain first 64 kB from input stream."); 
 2311      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2312      ret= 0; goto ex;
 2313    }
 2314    /* read isosize from head_buffer, not from medium */
 2315    ret= isoburn_read_iso_head(drive, 0, &isosize, head_buffer, (1<<13));
 2316    if(ret<=0) {
 2317      Xorriso_process_msg_queues(xorriso,0);
 2318      sprintf(xorriso->info_text,
 2319              "Option -isosize given but data stream seems not to be ISO 9660"); 
 2320      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2321      ret= 0; goto ex;
 2322    }
 2323    sprintf(xorriso->info_text, "Size of ISO 9660 image: %ds", isosize);
 2324    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 2325    fixed_size= ((off_t) (isosize)) * (off_t) 2048;
 2326    burn_track_set_size(track, fixed_size);
 2327  }
 2328 
 2329  ret= Xorriso_get_profile(xorriso, &profile_number, profile_name, 2);
 2330  is_cd= (ret==2);
 2331  is_bd= (ret == 3);
 2332 
 2333  if(isoburn_needs_emulation(drive)) {
 2334    if(flag&1) {
 2335      ret= isoburn_disc_track_lba_nwa(drive, burn_options, 0, &dummy, &nwa);
 2336      Xorriso_process_msg_queues(xorriso,0);
 2337      if(ret<=0) {
 2338        sprintf(xorriso->info_text,
 2339      "Cannot obtain next writeable address of emulated multi-session media\n");
 2340        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2341        ret= 0; goto ex;
 2342      }
 2343      if(nwa == 32 && disc_state != BURN_DISC_APPENDABLE)
 2344        nwa= 0; /* No automatic toc emulation. Formatter might not be aware. */
 2345    } else {
 2346      nwa= 0;
 2347      if (disc_state == BURN_DISC_APPENDABLE) {
 2348        ret= isoburn_disc_track_lba_nwa(drive, burn_options, 0, &dummy, &nwa);
 2349        Xorriso_process_msg_queues(xorriso,0);
 2350        if(ret<=0) {
 2351          sprintf(xorriso->info_text,
 2352         "Cannot obtain next writeable address of emulated appendable media\n");
 2353          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2354          ret= 0; goto ex;
 2355        }
 2356      }
 2357    }
 2358    burn_write_opts_set_start_byte(burn_options,((off_t) nwa) * (off_t) 2048);
 2359  }
 2360 
 2361  if(write_start_address>=0) {
 2362    nwa= write_start_address / (off_t) 2048;
 2363    if(((off_t) nwa) * (off_t) 2048 < write_start_address )
 2364      nwa++;
 2365    burn_write_opts_set_start_byte(burn_options, ((off_t) nwa) * (off_t) 2048);
 2366  }
 2367 
 2368  if(xorriso->do_tao) {
 2369    if (xorriso->do_tao > 0)
 2370      burn_write_opts_set_write_type(burn_options,
 2371                                     BURN_WRITE_TAO, BURN_BLOCK_MODE1);
 2372    else
 2373      burn_write_opts_set_write_type(burn_options,
 2374                                     BURN_WRITE_SAO, BURN_BLOCK_SAO);
 2375                                     
 2376    ret = burn_precheck_write(burn_options, disc, reasons, 0);
 2377    if(ret<=0) {
 2378      sprintf(xorriso->info_text,
 2379              "Cannot set write type %s for this medium.\n",
 2380              xorriso->do_tao > 0 ? "TAO" : "SAO");
 2381      sprintf(xorriso->info_text+strlen(xorriso->info_text),
 2382              "Reasons given:\n%s", reasons);
 2383      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2384      ret= 0; goto ex;
 2385    }
 2386    sprintf(xorriso->info_text, "Explicitly chosen write type: %s",
 2387            xorriso->do_tao > 0 ? "TAO" : "SAO");
 2388    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
 2389  } else {
 2390    if(burn_write_opts_auto_write_type(burn_options, disc, reasons, 0) ==
 2391       BURN_WRITE_NONE) {
 2392      sprintf(xorriso->info_text,
 2393              "Failed to find a suitable write mode with this media.\n");
 2394      sprintf(xorriso->info_text+strlen(xorriso->info_text),
 2395              "Reasons given:\n%s", reasons);
 2396      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2397      ret= 0; goto ex;
 2398    }
 2399  }
 2400 
 2401  ret= Xorriso_sanitize_image_size(xorriso, drive, disc, burn_options, 2);
 2402  if(ret<=0) 
 2403    goto ex;
 2404 
 2405  sprintf(xorriso->info_text, "Beginning to write data track.\n");
 2406  Xorriso_info(xorriso,0);
 2407 
 2408  /* Important: do not return until burn_is_aborting() was checked */
 2409  signal_mode= 1;
 2410  ret= burn_drive_get_drive_role(drive);
 2411  if(ret == 1)
 2412    signal_mode|= 2;
 2413  Xorriso_set_signal_handling(xorriso, signal_mode);
 2414 
 2415  xorriso->run_state= 1; /* Indicate that burning has started */
 2416  burn_disc_write(burn_options, disc);
 2417 
 2418  ret= Xorriso_pacifier_loop(xorriso, drive, 2 | (is_cd << 4) | (is_bd << 5));
 2419  if(burn_is_aborting(0))
 2420    Xorriso_abort(xorriso, 0); /* Never comes back */
 2421  Xorriso_set_signal_handling(xorriso, 0);
 2422  if(ret<=0)
 2423    goto ex;
 2424  if(!burn_drive_wrote_well(drive)) {
 2425    Xorriso_process_msg_queues(xorriso,0);
 2426    if(xorriso->auto_close && xorriso->do_close == 0) {
 2427      if(burn_drive_was_feat21_failure(drive)) {
 2428        sprintf(xorriso->info_text,
 2429          "libburn indicates failure with writing DVD-RW to appendable state.");
 2430        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 2431        /* Urge caller to call Xorriso_retry_burn_rack() */
 2432        ret= 2; goto ex;
 2433      }
 2434    }
 2435    sprintf(xorriso->info_text,
 2436            "libburn indicates failure with writing."); 
 2437    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2438    ret= 0; goto ex;
 2439  }
 2440 
 2441  if(flag & 1) {
 2442    ret= Xorriso_update_iso_lba0(xorriso, nwa, isosize, head_buffer, NULL,
 2443                                 flag & 2);
 2444    if(ret <= 0)
 2445      goto ex;
 2446  }
 2447  sprintf(xorriso->info_text, "Writing to ");
 2448  Text_shellsafe(xorriso->outdev, xorriso->info_text, 1);
 2449  strcat(xorriso->info_text, " completed successfully.\n\n");
 2450  Xorriso_info(xorriso, 0);
 2451  ret= 1;
 2452 ex:;
 2453  Xorriso_process_msg_queues(xorriso,0);
 2454  if(disc!=NULL)
 2455    burn_disc_free(disc);
 2456  if(session != NULL)
 2457    burn_session_free(session);
 2458  if(track != NULL)
 2459    burn_track_free(track);
 2460  if(burn_options != NULL)
 2461    burn_write_opts_free(burn_options);
 2462  if(xorriso->pacifier_fifo!=NULL)
 2463    burn_source_free(xorriso->pacifier_fifo);
 2464  xorriso->pacifier_fifo= NULL;
 2465  xorriso->run_state= 0; /* Indicate that burning has ended */
 2466  Xorriso_free_meM(reasons);
 2467  Xorriso_free_meM(profile_name);
 2468  Xorriso_free_meM(head_buffer);
 2469  return(ret);
 2470 }
 2471 
 2472 
 2473 int Xorriso_relax_compliance(struct XorrisO *xorriso, char *mode,
 2474                                     int flag)
 2475 {
 2476  char *npt, *cpt;
 2477  int l, was, value, ret;
 2478  struct isoburn_imgen_opts *opts= NULL;
 2479  char *msg= NULL;
 2480  off_t limit;
 2481 
 2482  was= xorriso->relax_compliance;
 2483  npt= cpt= mode;
 2484  for(; npt!=NULL; cpt= npt+1) {
 2485    npt= strchr(cpt,':');
 2486    if(npt==NULL)
 2487      l= strlen(cpt);
 2488    else
 2489      l= npt-cpt;
 2490    if(l == 0)
 2491  continue;
 2492    if((l == 6 && strncmp(cpt, "strict", l) == 0) ||
 2493       (l == 5 && strncmp(cpt, "clear", l) == 0)) {
 2494      xorriso->relax_compliance= 0;
 2495    } else if(l == 7 && strncmp(cpt, "default", l) == 0) {
 2496      xorriso->relax_compliance= Xorriso_relax_compliance_defaulT;
 2497 
 2498    } else if((l == 18 && strncmp(cpt, "untranslated_names", l) == 0) ||
 2499              (l == 21 && strncmp(cpt, "untranslated_names_on", l) == 0) ) {
 2500      xorriso->untranslated_name_len = -1;
 2501    } else if((l == 22 && strncmp(cpt, "untranslated_names_off", l) == 0)) {
 2502      xorriso->untranslated_name_len = 0;
 2503    } else if((l >= 22 && strncmp(cpt, "untranslated_name_len=", 22) == 0)) {
 2504      value= -1;
 2505      sscanf(cpt + 22, "%d", &value);
 2506      /* Let libisoburn check the value */
 2507      ret= isoburn_igopt_new(&opts, 0);
 2508      if(ret != 1)
 2509        return(-1);
 2510      ret= isoburn_igopt_set_untranslated_name_len(opts, value);
 2511      isoburn_igopt_destroy(&opts, 0);
 2512      if(ret <= 0) { /* Not a tasty value */
 2513        xorriso->relax_compliance= was;
 2514        return(0);
 2515      }
 2516      xorriso->untranslated_name_len = value;
 2517 
 2518    } else if((l == 16 && strncmp(cpt, "allow_dir_id_ext", l) == 0) ||
 2519              (l == 19 && strncmp(cpt, "allow_dir_id_ext_on", l) == 0) ) {
 2520      xorriso->relax_compliance|= isoburn_igopt_allow_dir_id_ext;
 2521      xorriso->allow_dir_id_ext_dflt= 0;
 2522    } else if((l == 20 && strncmp(cpt, "allow_dir_id_ext_off", l) == 0)) {
 2523      xorriso->relax_compliance&= ~isoburn_igopt_allow_dir_id_ext;
 2524      xorriso->allow_dir_id_ext_dflt= 0;
 2525 
 2526    } else if((l == 12 && strncmp(cpt, "omit_version", l) == 0) ||
 2527              (l == 15 && strncmp(cpt, "omit_version_on", l) == 0) ) {
 2528      xorriso->relax_compliance|= isoburn_igopt_omit_version_numbers;
 2529    } else if((l == 16 && strncmp(cpt, "omit_version_off", l) == 0)) {
 2530      xorriso->relax_compliance&= ~isoburn_igopt_omit_version_numbers;
 2531 
 2532    } else if((l == 16 && strncmp(cpt, "only_iso_version", l) == 0) ||
 2533              (l == 19 && strncmp(cpt, "only_iso_version_on", l) == 0) ) {
 2534      xorriso->relax_compliance|= isoburn_igopt_only_iso_versions;
 2535    } else if((l == 20 && strncmp(cpt, "only_iso_version_off", l) == 0)) {
 2536      xorriso->relax_compliance&= ~isoburn_igopt_only_iso_versions;
 2537 
 2538    } else if((l == 10 && strncmp(cpt, "deep_paths", l) == 0) ||
 2539              (l == 13 && strncmp(cpt, "deep_paths_on", l) == 0)) {
 2540      xorriso->relax_compliance|= isoburn_igopt_allow_deep_paths;
 2541    } else if(l == 14 && strncmp(cpt, "deep_paths_off", l) == 0) {
 2542      xorriso->relax_compliance&= ~isoburn_igopt_allow_deep_paths;
 2543 
 2544    } else if((l == 10 && strncmp(cpt, "long_paths", l) == 0) ||
 2545              (l == 13 && strncmp(cpt, "long_paths_on", l) == 0) ) {
 2546      xorriso->relax_compliance|= isoburn_igopt_allow_longer_paths;
 2547    } else if(l == 14 && strncmp(cpt, "long_paths_off", l) == 0) {
 2548      xorriso->relax_compliance&= ~isoburn_igopt_allow_longer_paths;
 2549 
 2550    } else if((l == 10 && strncmp(cpt, "long_names", l) == 0) ||
 2551              (l == 13 && strncmp(cpt, "long_names_on", l) == 0)) {
 2552      xorriso->relax_compliance|= isoburn_igopt_max_37_char_filenames;
 2553    } else if(l == 14 && strncmp(cpt, "long_names_off", l) == 0) {
 2554      xorriso->relax_compliance&= ~isoburn_igopt_max_37_char_filenames;
 2555 
 2556    } else if((l == 13 && strncmp(cpt, "no_force_dots", l) == 0) ||
 2557              (l == 16 && strncmp(cpt, "no_force_dots_on", l) == 0)) {
 2558      xorriso->relax_compliance|= isoburn_igopt_no_force_dots;
 2559    } else if(l == 17 && strncmp(cpt, "no_force_dots_off", l) == 0) {
 2560      xorriso->relax_compliance&= ~isoburn_igopt_no_force_dots;
 2561 
 2562    } else if((l == 15 && strncmp(cpt, "no_j_force_dots", l) == 0) ||
 2563              (l == 18 && strncmp(cpt, "no_j_force_dots_on", l) == 0)) {
 2564      xorriso->relax_compliance|= isoburn_igopt_no_j_force_dots;
 2565    } else if(l == 19 && strncmp(cpt, "no_j_force_dots_off", l) == 0) {
 2566      xorriso->relax_compliance&= ~isoburn_igopt_no_j_force_dots;
 2567 
 2568    } else if((l ==  9 && strncmp(cpt, "lowercase", l) == 0) ||
 2569              (l == 12 && strncmp(cpt, "lowercase_on", l) == 0)) {
 2570      xorriso->relax_compliance|= isoburn_igopt_allow_lowercase;
 2571    } else if(l == 13 && strncmp(cpt, "lowercase_off", l) == 0) {
 2572      xorriso->relax_compliance&= ~isoburn_igopt_allow_lowercase;
 2573 
 2574    } else if((l == 10 && strncmp(cpt, "full_ascii", l) == 0) ||
 2575              (l == 13 && strncmp(cpt, "full_ascii_on", l) == 0)) {
 2576      xorriso->relax_compliance|= isoburn_igopt_allow_full_ascii;
 2577    } else if(l == 14 && strncmp(cpt, "full_ascii_off", l) == 0) {
 2578      xorriso->relax_compliance&= ~isoburn_igopt_allow_full_ascii;
 2579 
 2580    } else if((l == 10 && strncmp(cpt, "7bit_ascii", l) == 0) ||
 2581              (l == 13 && strncmp(cpt, "7bit_ascii_on", l) == 0)) {
 2582      xorriso->relax_compliance|= isoburn_igopt_allow_7bit_ascii;
 2583    } else if(l == 14 && strncmp(cpt, "7bit_ascii_off", l) == 0) {
 2584      xorriso->relax_compliance&= ~isoburn_igopt_allow_7bit_ascii;
 2585 
 2586    } else if((l == 17 && strncmp(cpt, "joliet_long_paths", l) == 0) ||
 2587              (l == 20 && strncmp(cpt, "joliet_long_paths_on", l) == 0)) {
 2588      xorriso->relax_compliance|= isoburn_igopt_joliet_longer_paths;
 2589    } else if(l == 21 && strncmp(cpt, "joliet_long_paths_off", l) == 0) {
 2590      xorriso->relax_compliance&= ~isoburn_igopt_joliet_longer_paths;
 2591 
 2592    } else if((l == 17 && strncmp(cpt, "joliet_long_names", l) == 0) ||
 2593              (l == 20 && strncmp(cpt, "joliet_long_names_on", l) == 0)) {
 2594      xorriso->relax_compliance|= isoburn_igopt_joliet_long_names;
 2595    } else if(l == 21 && strncmp(cpt, "joliet_long_names_off", l) == 0) {
 2596      xorriso->relax_compliance&= ~isoburn_igopt_joliet_long_names;
 2597 
 2598    } else if((l == 12 && strncmp(cpt, "joliet_utf16", l) == 0) ||
 2599              (l == 15 && strncmp(cpt, "joliet_utf16_on", l) == 0)) {
 2600      xorriso->relax_compliance|= isoburn_igopt_joliet_utf16;
 2601    } else if(l == 16 && strncmp(cpt, "joliet_utf16_off", l) == 0) {
 2602      xorriso->relax_compliance&= ~isoburn_igopt_joliet_utf16;
 2603 
 2604    } else if((l == 10 && strncmp(cpt, "always_gmt", l) == 0) ||
 2605              (l == 13 && strncmp(cpt, "always_gmt_on", l) == 0)) {
 2606      xorriso->relax_compliance|= isoburn_igopt_always_gmt;
 2607    } else if(l == 14 && strncmp(cpt, "always_gmt_off", l) == 0) {
 2608      xorriso->relax_compliance&= ~isoburn_igopt_always_gmt;
 2609 
 2610    } else if((l ==  9 && strncmp(cpt, "rec_mtime", l) == 0) ||
 2611              (l == 12 && strncmp(cpt, "rec_mtime_on", l) == 0)) {
 2612      xorriso->relax_compliance|= (isoburn_igopt_dir_rec_mtime |
 2613                                   isoburn_igopt_joliet_rec_mtime |
 2614                                   isoburn_igopt_iso1999_rec_mtime);
 2615    } else if(l == 13 && strncmp(cpt, "rec_mtime_off", l) == 0) {
 2616      xorriso->relax_compliance&= ~(isoburn_igopt_dir_rec_mtime | 
 2617                                   isoburn_igopt_joliet_rec_mtime |
 2618                                   isoburn_igopt_iso1999_rec_mtime);
 2619 
 2620    } else if((l ==  6 && strncmp(cpt, "old_rr", l) == 0) ||
 2621              (l ==  9 && strncmp(cpt, "old_rr_on", l) == 0) ||
 2622              (l == 10 && strncmp(cpt, "new_rr_off", l) == 0)) {
 2623      xorriso->relax_compliance|=
 2624                 isoburn_igopt_rrip_version_1_10 | isoburn_igopt_aaip_susp_1_10;
 2625    } else if((l == 10 && strncmp(cpt, "old_rr_off", l) == 0) ||
 2626              (l ==  9 && strncmp(cpt, "new_rr_on", l) == 0) ||
 2627              (l ==  6 && strncmp(cpt, "new_rr", l) == 0)) {
 2628      xorriso->relax_compliance&=
 2629              ~(isoburn_igopt_rrip_version_1_10 | isoburn_igopt_aaip_susp_1_10);
 2630 
 2631    } else if((l == 14 && strncmp(cpt, "aaip_susp_1_10", l) == 0) ||
 2632              (l == 17 && strncmp(cpt, "aaip_susp_1_10_on", l) == 0) ||
 2633              (l == 18 && strncmp(cpt, "aaip_susp_1_12_off", l) == 0)) {
 2634      xorriso->relax_compliance|= isoburn_igopt_aaip_susp_1_10;
 2635    } else if((l == 18 && strncmp(cpt, "aaip_susp_1_10_off", l) == 0) ||
 2636              (l == 17 && strncmp(cpt, "aaip_susp_1_12_on", l) == 0) ||
 2637              (l == 14 && strncmp(cpt, "aaip_susp_1_12", l) == 0)) {
 2638      xorriso->relax_compliance&= ~isoburn_igopt_aaip_susp_1_10;
 2639 
 2640    } else if((l == 11 && strncmp(cpt, "no_emul_toc", l) == 0) ||
 2641              (l == 14 && strncmp(cpt, "no_emul_toc_on", l) == 0)) {
 2642      xorriso->no_emul_toc|= 1;
 2643    } else if((l == 15 && strncmp(cpt, "no_emul_toc_off", l) == 0) ||
 2644              (l ==  8 && strncmp(cpt, "emul_toc", l) == 0)) {
 2645      xorriso->no_emul_toc&= ~1;
 2646 
 2647    } else if((l == 13 && strncmp(cpt, "iso_9660_1999", l) == 0) ||
 2648              (l == 16 && strncmp(cpt, "iso_9660_1999_on", l) == 0)) {
 2649      xorriso->do_iso1999= 1;
 2650    } else if(l == 17 && strncmp(cpt, "iso_9660_1999_off", l) == 0) {
 2651      xorriso->do_iso1999= 0;
 2652 
 2653    } else if((l >= 15 && strncmp(cpt, "iso_9660_level=", 15) == 0)) {
 2654      value= 0;
 2655      sscanf(cpt + 15, "%d", &value);
 2656      if(value == 1 || value == 2) {
 2657        limit= ((off_t) 4) * ((off_t) 1024*1024*1024) - ((off_t) 1);
 2658        xorriso->iso_level= value;
 2659        xorriso->iso_level_is_default= 0;
 2660        if(xorriso->file_size_limit > limit)
 2661          xorriso->file_size_limit= limit;
 2662      } else if(value == 3) {
 2663        xorriso->iso_level= value;
 2664        xorriso->iso_level_is_default= 0;
 2665        if(xorriso->file_size_limit < Xorriso_default_file_size_limiT)
 2666          xorriso->file_size_limit= Xorriso_default_file_size_limiT;
 2667      } else {
 2668        Xorriso_alloc_meM(msg, char, 160); 
 2669        sprintf(msg,
 2670              "-compliance iso_9660_level=%d : Only 1, 2, or 3 are permissible",
 2671              value);
 2672        Xorriso_msgs_submit(xorriso, 0, msg, 0, "FAILURE", 0);
 2673        Xorriso_free_meM(msg);
 2674        msg= NULL;
 2675        xorriso->relax_compliance= was;
 2676        return(0);
 2677      }
 2678 
 2679    } else if((l ==  8 && strncmp(cpt, "iso_9660", l) == 0) ||
 2680              (l == 11 && strncmp(cpt, "iso_9660_on", l) == 0)) {
 2681      /* may have a meaning in future */;
 2682    } else if(l == 12 && strncmp(cpt, "iso_9660_off", l) == 0) {
 2683      /* may have a meaning in future */;
 2684      Xorriso_msgs_submit(xorriso, 0,
 2685             "-compliance -iso_9660_off : Cannot do anything else but ISO 9660",
 2686             0, "FAILURE", 0);
 2687      xorriso->relax_compliance= was;
 2688      return(0);
 2689 
 2690    } else if((l ==  9 && strncmp(cpt, "old_empty", l) == 0) ||
 2691              (l == 12 && strncmp(cpt, "old_empty_on", l) == 0)) {
 2692      xorriso->do_old_empty= 1;
 2693    } else if(l == 13 && strncmp(cpt, "old_empty_off", l) == 0) {
 2694      xorriso->do_old_empty= 0;
 2695 
 2696    } else {
 2697      if(l<SfileadrL)
 2698        sprintf(xorriso->info_text, "-compliance: unknown rule '%s'",
 2699                cpt);
 2700      else
 2701        sprintf(xorriso->info_text,
 2702                "-compliance: oversized rule parameter (%d)", l);
 2703      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2704      xorriso->relax_compliance= was;
 2705      return(0);
 2706    }
 2707  }
 2708  return(1);
 2709 ex:;
 2710  Xorriso_free_meM(msg);
 2711  return(ret);
 2712 }
 2713 
 2714 
 2715 /* @return 1=ok  2=ok, is default setting */
 2716 int Xorriso_get_relax_text(struct XorrisO *xorriso, char mode[1024],
 2717                            int flag)
 2718 {
 2719  int r;
 2720 
 2721  r= xorriso->relax_compliance;
 2722  if(r == 0) {
 2723    strcpy(mode, "strict");
 2724    return(1);
 2725  }
 2726  strcpy(mode, "clear");
 2727  sprintf(mode + strlen(mode), ":iso_9660_level=%d",  xorriso->iso_level);
 2728  if(r & isoburn_igopt_allow_dir_id_ext)
 2729    strcat(mode, ":allow_dir_id_ext");
 2730  if(r & isoburn_igopt_omit_version_numbers)
 2731    strcat(mode, ":omit_version");
 2732  if(r & isoburn_igopt_only_iso_versions)
 2733    strcat(mode, ":only_iso_version");
 2734  if(r & isoburn_igopt_allow_deep_paths)
 2735    strcat(mode, ":deep_paths");
 2736  if(r & isoburn_igopt_allow_longer_paths)
 2737    strcat(mode, ":long_paths");
 2738  if(r & isoburn_igopt_max_37_char_filenames)
 2739    strcat(mode, ":long_names");
 2740  if(r & isoburn_igopt_no_force_dots)
 2741    strcat(mode, ":no_force_dots");
 2742  if(r & isoburn_igopt_no_j_force_dots)
 2743    strcat(mode, ":no_j_force_dots");
 2744  if(r & isoburn_igopt_allow_lowercase)
 2745    strcat(mode, ":lowercase");
 2746  if(r & isoburn_igopt_allow_full_ascii)
 2747    strcat(mode, ":full_ascii");
 2748  else if(r & isoburn_igopt_allow_7bit_ascii)
 2749    strcat(mode, ":7bit_ascii");
 2750  if(r & isoburn_igopt_joliet_longer_paths)
 2751    strcat(mode, ":joliet_long_paths");
 2752  if(r & isoburn_igopt_joliet_long_names)
 2753    strcat(mode, ":joliet_long_names");
 2754  if(r & isoburn_igopt_joliet_utf16)
 2755    strcat(mode, ":joliet_utf16");
 2756  if(r & isoburn_igopt_always_gmt)
 2757    strcat(mode, ":always_gmt");
 2758  if(r & isoburn_igopt_dir_rec_mtime)
 2759    strcat(mode, ":rec_mtime");
 2760  if(r & isoburn_igopt_rrip_version_1_10) {
 2761    strcat(mode, ":old_rr");
 2762    if(!(r & isoburn_igopt_aaip_susp_1_10))
 2763      strcat(mode, ":aaip_susp_1_10_off");
 2764  } else {
 2765    strcat(mode, ":new_rr");
 2766    if(r & isoburn_igopt_aaip_susp_1_10) 
 2767      strcat(mode, ":aaip_susp_1_10");
 2768  }
 2769  if(xorriso->no_emul_toc & 1)
 2770    strcat(mode, ":no_emul_toc");
 2771  if(xorriso->untranslated_name_len != 0)
 2772    sprintf(mode + strlen(mode), ":untranslated_name_len=%d",
 2773            xorriso->untranslated_name_len);
 2774  if(xorriso->do_iso1999)
 2775    sprintf(mode + strlen(mode), ":iso_9660_1999");
 2776  if(xorriso->do_old_empty)
 2777    sprintf(mode + strlen(mode), ":old_empty");
 2778  return(1 +
 2779        (r == Xorriso_relax_compliance_defaulT && !(xorriso->no_emul_toc & 1)
 2780         && xorriso->untranslated_name_len == 0 && !xorriso->do_iso1999 &&
 2781         xorriso->iso_level == 3));
 2782 }
 2783 
 2784 
 2785 /* @param flag bit0= operating on newly attached boot image
 2786 */
 2787 int Xorriso_set_isolinux_options(struct XorrisO *xorriso,
 2788                                  IsoImage *image, int flag)
 2789 {
 2790  int make_isohybrid_mbr= 0, ret, patch_table= 0, num_boots, i;
 2791  ElToritoBootImage *bootimg, **boots = NULL;
 2792  IsoFile *bootimg_node, **bootnodes = NULL;
 2793 
 2794  ret= iso_image_get_boot_image(image, &bootimg, &bootimg_node, NULL);
 2795  Xorriso_process_msg_queues(xorriso,0);
 2796  if(ret != 1) {
 2797    sprintf(xorriso->info_text, "Programming error: No boot image available in Xorriso_set_isolinux_options()");
 2798    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 2799    ret= -1; goto ex;
 2800  }
 2801  ret= iso_image_get_all_boot_imgs(image, &num_boots, &boots, &bootnodes, 0);
 2802  Xorriso_process_msg_queues(xorriso,0);
 2803  if(ret != 1) {
 2804    Xorriso_report_iso_error(xorriso, "", ret, "Cannot inquire boot images", 0,
 2805                             "FATAL", 1);
 2806    ret= -1; goto ex;
 2807  }
 2808 
 2809  /* bit0 : 1=boot-info-table , bit2-7 : 1=EFI , 2=HFS+ , bit8 : 1=APM */
 2810  patch_table = xorriso->patch_isolinux_image & 0x3fd;
 2811  if((flag & 1) && num_boots > 1) {
 2812    ret= el_torito_set_isolinux_options(boots[num_boots - 1], patch_table, 0);
 2813    ret= (ret == 1); goto ex;
 2814  }
 2815 
 2816  /* Handle patching of first attached boot image or of imported boot images 
 2817  */
 2818  for(i= 0; i < num_boots; i++) {
 2819    patch_table = xorriso->patch_isolinux_image & 0x3fd;
 2820    if(patch_table && !(flag & 1)) {
 2821      if(!el_torito_seems_boot_info_table(boots[i], 0))
 2822        patch_table&= ~1;
 2823      else if((xorriso->patch_isolinux_image & 2) &&
 2824              el_torito_get_boot_platform_id(boots[i]) == 0xef)
 2825        patch_table&= ~1;
 2826    }
 2827    if(i > 0 || xorriso->boot_image_isohybrid == 0) {
 2828      ret= el_torito_set_isolinux_options(boots[i], patch_table, 0);
 2829      if(ret != 1)
 2830        {ret= 0; goto ex;}
 2831  continue;
 2832    }
 2833 
 2834    /* <<< From here on only with first boot image and
 2835           deprecated builtin isohybrid MBR */
 2836 
 2837    if(xorriso->boot_image_isohybrid == 3) {
 2838      make_isohybrid_mbr= 1;
 2839    } else {
 2840      ret= Xorriso_is_isohybrid(xorriso, bootimg_node, 0);
 2841      if(ret < 0)
 2842        {ret= 0; goto ex;}
 2843      if(ret > 0)
 2844        make_isohybrid_mbr= 1;
 2845    }
 2846 
 2847    if(xorriso->boot_image_isohybrid == 2 && !make_isohybrid_mbr) {
 2848      sprintf(xorriso->info_text,
 2849           "Isohybrid signature is demanded but not found in boot image file.");
 2850      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2851      {ret= 0; goto ex;}
 2852    }
 2853    if(make_isohybrid_mbr) {
 2854      sprintf(xorriso->info_text, "Will write isohybrid MBR.");
 2855      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 2856    }
 2857    ret= el_torito_set_isolinux_options(bootimg,
 2858                                     patch_table | (make_isohybrid_mbr << 1),0);
 2859    if(ret != 1)
 2860      {ret= 0; goto ex;}
 2861  }
 2862 ex:
 2863  Xorriso_process_msg_queues(xorriso,0);
 2864  if(boots != NULL)
 2865    free(boots);
 2866  if(bootnodes != NULL)
 2867    free(bootnodes);
 2868  return(ret);
 2869 }
 2870 
 2871 
 2872 int Xorriso_overwrite_iso_head(struct XorrisO *xorriso,
 2873                                struct burn_drive *drive, char *head_buffer,
 2874                                int lba, int flag)
 2875 {
 2876  int ret;
 2877  off_t to_write;
 2878 
 2879  to_write= 64 * 1024;
 2880  burn_drive_reset_simulate(drive, xorriso->do_dummy);
 2881  ret= burn_random_access_write(drive, (off_t) lba * (off_t) 2048,
 2882                                head_buffer, to_write, 1);
 2883  if(ret <= 0) {
 2884    Xorriso_process_msg_queues(xorriso, 0);
 2885    sprintf(xorriso->info_text,
 2886            "Cannot write new ISO image head to LBA %d", lba);
 2887    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 2888    return(0);
 2889  }
 2890  return(1);
 2891 }
 2892 
 2893 
 2894 /* @param flag bit0= insist on tag_type 4 (relocated superblock tag)
 2895 */
 2896 int Xorriso_find_sb_checksum(struct XorrisO *xorriso,
 2897                              char *head_buffer, int *vd_end, int flag)
 2898 {
 2899  int i, tag_type, ret;
 2900  uint32_t pos, range_start, range_size, next_tag;
 2901  char md5[16];
 2902 
 2903  *vd_end= 0;
 2904 
 2905  /* Look for volume descriptor end */
 2906  for(i= 16; i < 32; i++)
 2907    if(((unsigned char *) head_buffer)[i * 2048] == 0xff &&
 2908      strncmp(head_buffer + i * 2048 + 1, "CD001", 5) == 0)
 2909  break;
 2910  /* Check whether the next one is a libisofs checksum tag */
 2911  if(i < 32) {
 2912    *vd_end= i;
 2913    i++;
 2914    ret= iso_util_decode_md5_tag(head_buffer + i * 2048, &tag_type, &pos,
 2915                                 &range_start, &range_size, &next_tag, md5, 0);
 2916    if(ret <= 0)
 2917      return(ret);
 2918    if((flag & 1) && tag_type != 4)
 2919      return(0); /* No other tag type is supposed to occur before type 4 */
 2920  }
 2921  return(i + 1);
 2922 }
 2923 
 2924 
 2925 /* @param field_head Example: " md5="
 2926 */
 2927 int Xorriso__set_iso_check_tag_md5(char *tag_data, char *field_head,
 2928                                    void **ctx, int *field_end, int flag)
 2929 {
 2930  char md5_bin[16], m32, *cpt;
 2931  int i;
 2932 
 2933  iso_md5_end(ctx, md5_bin);
 2934  cpt= strstr(tag_data, field_head);
 2935  if(cpt == NULL)
 2936    return(0);
 2937  cpt+= strlen(field_head);
 2938  m32= cpt[32];
 2939  for(i= 0; i < 16; i++)
 2940    sprintf(cpt + 2 * i, "%2.2x", ((unsigned char *) md5_bin)[i]);
 2941  cpt[32]= m32;
 2942  *field_end= (cpt - tag_data) + 32;
 2943  return(1);
 2944 }
 2945 
 2946 
 2947 int Xorriso_verify_sb_tag(struct XorrisO *xorriso, char *head_buffer,
 2948                           int checksum_block, int flag)
 2949 {
 2950  int tag_type, ret;
 2951  uint32_t pos, range_start, range_size, next_tag;
 2952  char md5_rec[16], md5_comp[16];
 2953  void *ctx= NULL;
 2954 
 2955  /* Obtain checksum */
 2956  iso_util_decode_md5_tag(head_buffer + checksum_block * 2048,
 2957                          &tag_type, &pos, &range_start, &range_size,
 2958                          &next_tag, md5_rec, 0);
 2959  /* Verify checksum */
 2960  ret= iso_md5_start(&ctx);
 2961  if(ret <= 0) {
 2962    Xorriso_process_msg_queues(xorriso,0);
 2963    Xorriso_no_malloc_memory(xorriso, NULL, 0);
 2964    return(0);
 2965  }
 2966  ret= iso_md5_compute(ctx, head_buffer, checksum_block * 2048);
 2967  iso_md5_end(&ctx, md5_comp);
 2968  if(ret <= 0) {
 2969    Xorriso_process_msg_queues(xorriso,0);
 2970    return(0);
 2971  }
 2972  if(iso_md5_match(md5_rec, md5_comp))
 2973    return(1);
 2974  Xorriso_msgs_submit(xorriso, 0,
 2975                      "Superblock data do not match superblock checksum tag",
 2976                      0, "WARNING", 0);
 2977  return(0);
 2978 }
 2979 
 2980 
 2981 int Xorriso_refresh_sb_tag(struct XorrisO *xorriso, char *head_buffer,
 2982                            int checksum_block, int flag)
 2983 {
 2984  int ret, field_end;
 2985  char md5_bin[16];
 2986  void *ctx= NULL;
 2987 
 2988  /* Recompute checksum and update found checksum tag */;
 2989  ret= iso_md5_start(&ctx);
 2990  if(ret <= 0) {
 2991 no_md5_ctx:;
 2992    Xorriso_process_msg_queues(xorriso,0);
 2993    Xorriso_no_malloc_memory(xorriso, NULL, 0);
 2994    return(0);
 2995  }
 2996  ret= iso_md5_compute(ctx, head_buffer, checksum_block * 2048);
 2997  if(ret <= 0) {
 2998 md5_comp_failed:;
 2999    iso_md5_end(&ctx, md5_bin);
 3000    return(0);
 3001  }
 3002  Xorriso__set_iso_check_tag_md5(head_buffer + checksum_block * 2048,
 3003                                 " md5=", &ctx, &field_end, 0);
 3004  if(ret <= 0)
 3005    return(2);
 3006  ret= iso_md5_start(&ctx);
 3007  if(ret <= 0)
 3008    goto no_md5_ctx;
 3009  ret= iso_md5_compute(ctx, head_buffer + checksum_block * 2048,
 3010                       field_end);
 3011  if(ret <= 0)
 3012    goto md5_comp_failed;
 3013  Xorriso__set_iso_check_tag_md5(head_buffer + checksum_block * 2048,
 3014                                 " self=", &ctx, &field_end, 0);
 3015  return(1);
 3016 }
 3017  
 3018 
 3019 /*
 3020    @param flag bit0= obtain iso_lba from indev
 3021                bit1= head_buffer already contains a valid head
 3022                bit2= issue message about success
 3023                bit3= check whether source blocks are banned by in_sector_map
 3024                bit4= refresh relocated sb checksum tag
 3025 */
 3026 int Xorriso_update_iso_lba0(struct XorrisO *xorriso, int iso_lba, int isosize,
 3027                             char *head_buffer, struct CheckmediajoB *job,
 3028                             int flag)
 3029 {
 3030  int ret, full_size, i, checksum_block= -1, vd_end;
 3031  char *headpt;
 3032  struct burn_drive_info *dinfo;
 3033  struct burn_drive *drive = NULL;
 3034  off_t seek_ret, to_write;
 3035 
 3036  ret= Xorriso_may_burn(xorriso, 0);
 3037  if(ret <= 0)
 3038    return(0);
 3039  if(flag & 1) {
 3040    ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
 3041                                  "on attempt to learn current session lba", 0);
 3042    if(ret<=0)
 3043      return(0);
 3044    ret= isoburn_disc_get_msc1(drive, &iso_lba);
 3045    if(ret<=0)
 3046      return(0);
 3047    drive= NULL; /* indev will not be used furtherly */
 3048  }
 3049  if(job == NULL) { 
 3050    ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
 3051                                   "on attempt to update at lba 0 to 31", 2);
 3052    if(ret<=0)
 3053      return(0);
 3054  }
 3055  if(iso_lba < 32)
 3056    return(2);
 3057 
 3058  if(!(flag & 2)) {
 3059    /* head_buffer was not filled yet. Read it from output media. */
 3060    if(drive != NULL)
 3061      if(burn_drive_get_drive_role(drive) == 5) /* write-only */
 3062        return(2);
 3063    if(job != NULL && job->data_to_fd >= 0) {
 3064      if((flag & 8) && job->sector_map != NULL) {
 3065        ret= Sectorbitmap_bytes_are_set(job->sector_map,
 3066                      ((off_t) iso_lba) * (off_t) 2048,
 3067                      ((off_t) (iso_lba + 32)) * ((off_t) 2048) - (off_t) 1, 0);
 3068        if(ret <= 0) {
 3069          sprintf(xorriso->info_text,
 3070            "ISO image head at lba %d is marked as invalid blocks in file copy",
 3071            iso_lba); 
 3072          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",
 3073                              0);
 3074           return(0);
 3075        }
 3076      }
 3077      seek_ret= lseek(job->data_to_fd, ((off_t) 2048) * (off_t) iso_lba,
 3078                      SEEK_SET);
 3079      if(seek_ret == -1)
 3080        ret= 0;
 3081      else
 3082        ret= read(job->data_to_fd, head_buffer, 64 * 1024); 
 3083      if(ret < 64 * 1024) {
 3084        Xorriso_process_msg_queues(xorriso,0);
 3085        sprintf(xorriso->info_text,
 3086                "Cannot read ISO image head from file copy"); 
 3087        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
 3088        return(0);
 3089      }
 3090      ret= isoburn_read_iso_head(NULL, 0, &isosize, head_buffer, 1 << 13);
 3091      if(ret<=0) {
 3092        Xorriso_process_msg_queues(xorriso,0);
 3093        sprintf(xorriso->info_text,
 3094                "Alleged session start does not look like ISO 9660.");
 3095        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
 3096        return(0);
 3097      }
 3098    } else {
 3099      ret= 0;
 3100      if(drive != NULL)
 3101        ret= isoburn_read_iso_head(drive, iso_lba, &isosize, head_buffer, 2);
 3102      if(ret<=0) {
 3103        Xorriso_process_msg_queues(xorriso,0);
 3104        sprintf(xorriso->info_text,
 3105                "Cannot read freshly written ISO image head"); 
 3106        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3107        return(0);
 3108      }
 3109    }
 3110  }
 3111 
 3112  /* patch ISO header */
 3113  full_size= iso_lba + isosize;
 3114  headpt= head_buffer + 32*1024;
 3115  for(i=0;i<4;i++)
 3116    headpt[87-i]= headpt[80+i]= (full_size >> (8*i)) & 0xff;
 3117 
 3118  /* >>> What about Joliet et.al. ? */;
 3119 
 3120  if(flag & 16) {
 3121    /* Find relocated sb checksum tag */
 3122    ret= Xorriso_find_sb_checksum(xorriso, head_buffer, &vd_end, 1);
 3123    if(ret > 0) {
 3124      /* If it is recognizable then it matched in Xorriso_adjust_relocated_sb */
 3125      checksum_block= ret - 1;
 3126      ret= Xorriso_refresh_sb_tag(xorriso, head_buffer, checksum_block, 0);
 3127      if(ret <= 0)
 3128        return(0);
 3129    }
 3130  }
 3131 
 3132  if(job != NULL) {
 3133    /* This is a check_media superblock relocation:
 3134       Invalidate eventual libisofs checksum tags.
 3135       Write only up to PVD end plus eventual invalidated tag.
 3136    */
 3137    to_write= 2048 * 32;
 3138    ret= Xorriso_find_sb_checksum(xorriso, head_buffer, &i, 0);
 3139    if(ret > 0) {
 3140      if(!(flag & 16)) /* invalidate */
 3141        memset(head_buffer + (ret - 1) * 2048, 0, 8);
 3142      to_write= 2048 * ret;
 3143    } else if(i > 0) {
 3144      to_write= 2048 * (i + 1);
 3145    }
 3146    seek_ret= lseek(job->data_to_fd, (off_t) 0, SEEK_SET);
 3147    if(seek_ret == -1)
 3148      ret= 0;
 3149    else
 3150      ret= write(job->data_to_fd, head_buffer, to_write); 
 3151    if(ret < to_write) {
 3152      Xorriso_process_msg_queues(xorriso,0);
 3153      sprintf(xorriso->info_text,
 3154              "Cannot write ISO image head to file copy"); 
 3155      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
 3156      return(0);
 3157    }
 3158  } else {
 3159    /* This is a regular superblock relocation. Write full 64 kB. */
 3160    ret= Xorriso_overwrite_iso_head(xorriso, drive, head_buffer, 0, 0);
 3161    if(ret <= 0)
 3162      return(ret);
 3163  }
 3164  if(flag & 4) {
 3165    sprintf(xorriso->info_text,
 3166            "Overwrote LBA 0 to 31 by 64 KiB from LBA %d", iso_lba); 
 3167    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 3168  }
 3169  return(1);
 3170 }
 3171 
 3172 
 3173 /* @return 1= ok, 0= no match, -1= MD5 computation error,
 3174            -2= MD5 clone or start error
 3175 */
 3176 int Xorriso_migrate_checksum_tag(struct XorrisO *xorriso, char *buffer,
 3177                                  int buf_base, int start,
 3178                                  int checksum_block, char md5_rec[16],
 3179                                  void *ctx_unch, void *ctx_chng, int flag)
 3180 {
 3181  int ret, to_compute;
 3182  char *headpt, md5_clone[16];
 3183  void *ctx_clone= NULL;
 3184  int field_end;
 3185 
 3186  /* Checksum both up to before checksum tag */
 3187  headpt= buffer + start * 2048;
 3188  to_compute= (checksum_block - start) * 2048;
 3189  if(to_compute > 0) {
 3190    ret= iso_md5_compute(ctx_unch, headpt, to_compute);
 3191    if(ret <= 0)
 3192      {ret= -1; goto ex;}
 3193    ret= iso_md5_compute(ctx_chng, headpt, to_compute);
 3194    if(ret <= 0)
 3195      {ret= -1; goto ex;}
 3196  }
 3197  /* Verify with unchanged checksum */
 3198  ret= iso_md5_clone(ctx_unch, &ctx_clone);
 3199  if(ret <= 0)
 3200    {ret= -2; goto ex;}
 3201  iso_md5_end(&ctx_clone, md5_clone);
 3202  if(!iso_md5_match(md5_rec, md5_clone))
 3203    {ret= 0; goto ex;}
 3204  /* Compute unchanged rest of block range */
 3205  headpt= buffer + checksum_block * 2048;
 3206  to_compute= 2048;
 3207  ret= iso_md5_compute(ctx_unch, headpt, to_compute);
 3208  if(ret <= 0)
 3209    {ret= -1; goto ex;}
 3210  /* Replace checksum in tag by changed checksum */
 3211  ret= iso_md5_clone(ctx_chng, &ctx_clone);
 3212  if(ret <= 0)
 3213    {ret= -2; goto ex;}
 3214  Xorriso__set_iso_check_tag_md5(headpt, " md5=", &ctx_clone, &field_end, 0);
 3215  /* Recompute and write self= checksum */
 3216  ret= iso_md5_start(&ctx_clone);
 3217  if(ret <= 0)
 3218    {ret= -2; goto ex;}
 3219  ret= iso_md5_compute(ctx_clone, headpt, field_end);
 3220  if(ret <= 0)
 3221    {ret= -1; goto ex;}
 3222  Xorriso__set_iso_check_tag_md5(headpt, " self=", &ctx_clone, &field_end, 0);
 3223  /* Add rest of head_buffer to changed checksum */
 3224  ret= iso_md5_compute(ctx_chng, headpt, to_compute);
 3225  if(ret <= 0)
 3226    {ret= -1; goto ex;}
 3227  ret= 1;
 3228 ex:;
 3229  if(ctx_clone != NULL)
 3230    iso_md5_end(&ctx_clone, md5_clone);
 3231  return(ret);
 3232 }
 3233 
 3234 
 3235 /* Verify and re-compute tree and session checksum tag */
 3236 int Xorriso_refresh_ts_tags(struct XorrisO *xorriso,
 3237                             struct burn_drive *drive,
 3238                             void *ctx_unch, void *ctx_chng,
 3239                             int iso_lba, int session_size,
 3240                             int checksum_block, int flag)
 3241 {
 3242  int i, ret, tag_type, look_for_tag, check_start, look_from_block, was_change;
 3243  off_t read_pos, to_read, data_count;
 3244  uint32_t pos, range_start, range_size, next_tag;
 3245  char md5_rec[16];
 3246  char *buf= NULL;
 3247 
 3248  look_for_tag= 3; /* tree tag */
 3249  look_from_block= checksum_block + 1; /* first buffer is already partly done */
 3250  Xorriso_alloc_meM(buf, char, 32 * 2048);
 3251  for(read_pos= iso_lba; read_pos < iso_lba + session_size; read_pos+= 32) {
 3252    was_change= 0;
 3253    to_read= 32;
 3254    if(read_pos + to_read > iso_lba + session_size)
 3255      to_read= iso_lba + session_size - read_pos;
 3256    ret=  burn_read_data(drive, read_pos * (off_t) 2048, buf,
 3257                         to_read * (off_t) 2048, &data_count, 0);
 3258    if(ret <= 0)
 3259      {ret= 0; goto ex;}
 3260    check_start= look_from_block;
 3261    for(i= look_from_block; i < to_read; i++) {
 3262      /* Watch out for tag */
 3263      ret= iso_util_decode_md5_tag(buf + i * 2048,
 3264                                   &tag_type, &pos, &range_start, &range_size,
 3265                                   &next_tag, md5_rec, look_for_tag);
 3266      if(ret < 0 ) {
 3267        ret= 0; goto ex;
 3268      } else if(ret == 1) {
 3269        if(tag_type != look_for_tag) {
 3270          sprintf(xorriso->info_text,
 3271                 "Encountered checksum tag type %d while looking for %d",
 3272                 tag_type, look_for_tag);
 3273          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "MISHAP", 0);
 3274          ret= 2; goto ex;
 3275        }
 3276        /* Checksum up to before tag, verify,
 3277           if match replace checksum and write */
 3278        ret= Xorriso_migrate_checksum_tag(xorriso, buf, read_pos, check_start, 
 3279                                          i, md5_rec, ctx_unch, ctx_chng, 0);
 3280        if(ret == -2)
 3281          goto ex;
 3282        if(ret < 0)
 3283          {ret= 0; goto ex;}
 3284        if(ret == 0) {
 3285          sprintf(xorriso->info_text,
 3286                  "Checksum tag MD5 mismatch in old session state");
 3287          Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "MISHAP", 0);
 3288          ret= 2; goto ex;
 3289        }
 3290 
 3291        was_change= 1;
 3292        if(look_for_tag == 3) {
 3293          look_for_tag= 1; /* session tag */
 3294        } else {
 3295          look_for_tag= -1;
 3296    break;
 3297        }
 3298        check_start= i + 1;
 3299      }
 3300    }
 3301 
 3302    look_from_block= 0; /* all following buffer need processing from start */
 3303 
 3304    if(was_change) {
 3305      ret= burn_random_access_write(drive, (off_t) read_pos * (off_t) 2048,
 3306                                    buf, to_read * (off_t) 2048, 1);
 3307      if(ret <= 0) {
 3308        Xorriso_process_msg_queues(xorriso, 0);
 3309        sprintf(xorriso->info_text,
 3310              "Cannot write new checksum tag data to LBA %d", (int) read_pos);
 3311        Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3312        ret= 0; goto ex;
 3313      }
 3314    }
 3315 
 3316    if(look_for_tag < 0)
 3317      {ret= 1; goto ex;}
 3318 
 3319    /* Checksum what was not checksummed yet */
 3320    if(to_read - check_start > 0) {
 3321      ret= iso_md5_compute(ctx_unch, buf + 2048 * check_start,
 3322                           (to_read - check_start) * 2048);
 3323      if(ret <= 0)
 3324        {ret= 0; goto ex;}
 3325      ret= iso_md5_compute(ctx_chng, buf + 2048 * check_start,
 3326                           (to_read - check_start) * 2048);
 3327      if(ret <= 0)
 3328        {ret= 0; goto ex;}
 3329    }
 3330  }
 3331  ret= 1;
 3332 ex:;
 3333  Xorriso_free_meM(buf);
 3334  return(ret);
 3335 }
 3336  
 3337 
 3338 int Xorriso_adjust_session_size(struct XorrisO *xorriso,
 3339                                 struct burn_drive *drive,
 3340                                 char *head_buffer,
 3341                                 int iso_lba, int iso_size,
 3342                                 int checksum_block, int session_size, int flag)
 3343 {
 3344  int i, ret, tag_type;
 3345  uint32_t pos, range_start, range_size, next_tag;
 3346  char *headpt, md5_unch[16], md5_chng[16], md5_clone[16], md5_rec[16];
 3347  void *ctx_unch= NULL, *ctx_chng= NULL, *ctx_clone= NULL;
 3348 
 3349  if(checksum_block > 0) {
 3350    /* Obtain recorded superblock MD5 */
 3351    ret= iso_util_decode_md5_tag(head_buffer + checksum_block * 2048,
 3352                                 &tag_type, &pos, &range_start, &range_size,
 3353                                 &next_tag, md5_rec, 0);
 3354    if(ret <= 0 || tag_type != 2) {
 3355      sprintf(xorriso->info_text,
 3356              "Encountered checksum tag type %d while looking for 2", tag_type);
 3357      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "MISHAP", 0);
 3358      checksum_block= 0;
 3359    }
 3360  }
 3361  if(checksum_block > 0) {
 3362    /* Create md5 context for unchanged state */
 3363    ret= iso_md5_start(&ctx_unch);
 3364    if(ret <= 0) {
 3365 no_ctx:;
 3366      Xorriso_process_msg_queues(xorriso, 0);
 3367      Xorriso_no_malloc_memory(xorriso, NULL, 0);
 3368      goto ex;
 3369    }
 3370    /* Checksum up to before PVD */
 3371    ret= iso_md5_compute(ctx_unch, head_buffer, 32768);
 3372    if(ret <= 0)
 3373      goto ex;
 3374    /* Before the first change: obtain md5 object for changed state */
 3375    ret= iso_md5_clone(ctx_unch, &ctx_chng);
 3376    if(ret <= 0)
 3377      goto no_ctx;
 3378    /* Add PVD to unchanged checksum */
 3379    ret= iso_md5_compute(ctx_unch, head_buffer + 32768, 2048);
 3380    if(ret <= 0)
 3381      goto ex;
 3382  }
 3383 
 3384  /* Update session PVD at iso_lba+16 to iso_size */
 3385  headpt= head_buffer + 32 * 1024;
 3386  for(i= 0; i < 4; i++)
 3387    headpt[87 - i]= headpt[80 + i]= (iso_size >> (8 * i)) & 0xff;
 3388 
 3389  if(checksum_block > 0) {
 3390    /* Add changed PVD to changed checksum */
 3391    ret= iso_md5_compute(ctx_chng, head_buffer + 32768, 2048);
 3392    if(ret <= 0)
 3393      goto ex;
 3394    ret= Xorriso_migrate_checksum_tag(xorriso, head_buffer, iso_lba, 17,
 3395                                      checksum_block, md5_rec,
 3396                                      ctx_unch, ctx_chng, 0);
 3397    if(ret == -2)
 3398      goto no_ctx;
 3399    if(ret < 0)
 3400      {ret= 0; goto ex;}
 3401    if(ret == 0) {
 3402      sprintf(xorriso->info_text,
 3403              "Superblock MD5 mismatch in old session state");
 3404      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "MISHAP", 0);
 3405      checksum_block= 0;
 3406    }
 3407  }
 3408 
 3409  ret= Xorriso_overwrite_iso_head(xorriso, drive, head_buffer, iso_lba, 0);
 3410  if(ret <= 0)
 3411    goto ex;
 3412 
 3413  if(checksum_block > 0) {
 3414    /* Verify and re-compute existing checksum tree and session tag */
 3415    ret= Xorriso_refresh_ts_tags(xorriso, drive, ctx_unch, ctx_chng,
 3416                                 iso_lba, session_size, checksum_block, 0);
 3417    if(ret == -2)
 3418      goto no_ctx;
 3419    if(ret <= 0)
 3420      goto ex;
 3421  }
 3422 
 3423  ret= 1;
 3424 ex:;
 3425  Xorriso_process_msg_queues(xorriso, 0);
 3426  if(ctx_unch != NULL)
 3427    iso_md5_end(&ctx_unch, md5_unch);
 3428  if(ctx_chng != NULL)
 3429    iso_md5_end(&ctx_chng, md5_chng);
 3430  if(ctx_clone != NULL)
 3431    iso_md5_end(&ctx_clone, md5_clone);
 3432  return(ret);
 3433 }
 3434 
 3435 
 3436 /* Read relocated superblock and patch in the VDs of the session superblock */
 3437 int Xorriso_adjust_relocated_sb(struct XorrisO *xorriso,
 3438                                 struct burn_drive *drive,
 3439                                 char *head_buffer,
 3440                                 char **sb_buffer,
 3441                                 int flag)
 3442 {
 3443  int ret, old_size, i, vd_end, checksum_block= -1;
 3444  char *buffer, *checksum= NULL;
 3445 
 3446  *sb_buffer= NULL;
 3447  Xorriso_alloc_meM(*sb_buffer, char, 32 * 2048);
 3448  buffer= *sb_buffer;
 3449  Xorriso_alloc_meM(checksum, char, 2048);
 3450 
 3451  ret= isoburn_read_iso_head(drive, 0, &old_size, buffer, 2);
 3452  if(ret <= 0)
 3453    goto ex;
 3454  ret= Xorriso_find_sb_checksum(xorriso, buffer, &vd_end, 0);
 3455  if(ret <= 0)
 3456    goto ex;
 3457  if(ret > 0) {
 3458    checksum_block= ret - 1;
 3459    memcpy(checksum, buffer + checksum_block * 2048, 2048);
 3460    ret= Xorriso_verify_sb_tag(xorriso, buffer, checksum_block, 0);
 3461    if(ret <= 0) {
 3462      checksum_block= -1;
 3463      memset(checksum, 0, 8);
 3464    }
 3465  }
 3466  
 3467  for(i= 16; i < 32; i++) {
 3468    memcpy(buffer + i * 2048, head_buffer + i * 2048, 2048);
 3469    if(((unsigned char *) head_buffer)[i * 2048] == 0xff &&
 3470      strncmp(head_buffer + i * 2048 + 1, "CD001", 5) == 0) {
 3471      i++;
 3472  break;
 3473    }
 3474  }
 3475  if(checksum_block >= 0 && i < 32)
 3476    memcpy(buffer + i * 2048, checksum, 2048);
 3477 
 3478  ret= 1;
 3479 ex:
 3480  if(ret <= 0)
 3481    Xorriso_free_meM(*sb_buffer);
 3482  Xorriso_free_meM(checksum);
 3483  return(ret);
 3484 }
 3485 
 3486 
 3487 int Xorriso_truncate_overwritable(struct XorrisO *xorriso, char *adr_mode,
 3488                                   char *adr_value, char *adjust, int flag)
 3489 {
 3490  int ret, iso_lba= 0, iso_session, iso_track, iso_size= 0, image_start_mode= 0;
 3491  int old_size, new_size, blocks, was_indev= 0, checksum_block= 0, vd_end;
 3492  int readable_blocks;
 3493  char image_start_value[81], *head_buffer= NULL, iso_volid[33];
 3494  char *sb_buffer= NULL;
 3495  struct burn_drive_info *dinfo;
 3496  struct burn_drive *drive = NULL, *in_drive = NULL;
 3497  struct burn_multi_caps *caps= NULL;
 3498  
 3499  Xorriso_alloc_meM(head_buffer, char, 32 * 2048);
 3500  
 3501  if(Xorriso_change_is_pending(xorriso, 0)) {
 3502    sprintf(xorriso->info_text,
 3503   "-truncate_overwritable: Image changes pending. -commit or -rollback first");
 3504    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3505    ret= 0; goto ex;
 3506  }
 3507  ret= Xorriso_may_burn(xorriso, 0);
 3508  if(ret <= 0)
 3509    goto ex;
 3510  ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
 3511                                 "on attempt to activate an older session", 2);
 3512  if(ret <= 0)
 3513    goto ex;
 3514  
 3515  /* Is it overwritable ? */
 3516  ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
 3517  if(ret > 0) {
 3518    if(caps->start_adr == 0)
 3519      ret= 0;
 3520  }
 3521  if(ret <= 0) {
 3522    sprintf(xorriso->info_text,
 3523     "-truncate_overwritable: Loaded medium is not random-access overwritable");
 3524    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3525    goto ex;
 3526  }
 3527 
 3528  ret= Xorriso_reassure(xorriso, "-truncate_overwritable",
 3529                       "activates an older session and destroys newer ones", 0);
 3530  if(ret <= 0)
 3531    {ret= 2; goto ex;}
 3532 
 3533  /* Learn old size */
 3534  ret= isoburn_read_iso_head(drive, 0, &old_size, iso_volid, 0);
 3535  if(ret <= 0) {
 3536    sprintf(xorriso->info_text,
 3537   "-truncate_overwritable: Cannot read ISO 9660 Volume Descriptor from LBA 0");
 3538    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3539    goto ex;
 3540  }
 3541 
 3542  /* Check for PVD at image_start_value and learn new size */
 3543  ret= Xorriso_decode_load_adr(xorriso, "-truncate_overwritable",
 3544                               adr_mode, adr_value, &image_start_mode,
 3545                               image_start_value, 0);
 3546  if(ret <= 0)
 3547    goto ex;
 3548  ret= isoburn_get_mount_params(drive, image_start_mode, image_start_value,
 3549                                &iso_lba, &iso_track, &iso_session, iso_volid,
 3550                                0);
 3551  if(ret <= 0)
 3552    goto ex;
 3553  if(ret != 1) {
 3554    sprintf(xorriso->info_text,
 3555     "-truncate_overwritable: Given address does not lead to ISO 9660 Volume Descriptor");
 3556    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3557    ret= 0; goto ex;
 3558  }
 3559  if(iso_lba >= old_size) {
 3560    sprintf(xorriso->info_text,
 3561       "-truncate_overwritable: Given address is larger than current ISO size");
 3562    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3563    ret= 0; goto ex;
 3564  }
 3565  ret= isoburn_read_iso_head(drive, iso_lba, &new_size, head_buffer, 2);
 3566  if(ret <= 0)
 3567    goto ex;
 3568 
 3569  ret= Xorriso_find_sb_checksum(xorriso, head_buffer, &vd_end, 0);
 3570  if(ret > 0)
 3571    checksum_block= ret - 1;
 3572 
 3573  /* Default is "new" */
 3574  iso_size= new_size;
 3575  if(strcmp(adjust, "old") == 0) {
 3576    /* ISO size before truncation */
 3577    iso_size= old_size - iso_lba;
 3578  } else if(adjust[0] == '+') {
 3579    /* Add-on size to new */
 3580    blocks= Scanf_io_size(adjust + 1, 0) / 2048;
 3581    if(blocks < 0)
 3582      goto wrong_adjust;
 3583    iso_size+= blocks;
 3584  } else if(adjust[0] >= '0' && adjust[0] <= '9') {
 3585    /* Add-on size to new */
 3586    blocks= Scanf_io_size(adjust, 0) / 2048;
 3587    if(blocks < iso_lba + iso_size) {
 3588 wrong_adjust:;
 3589      sprintf(xorriso->info_text,
 3590              "-truncate_overwritable: Given total filesystem size is smaller than new session size");
 3591      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3592      ret= 0; goto ex;
 3593    }
 3594    iso_size= blocks - iso_lba;
 3595  }
 3596 
 3597  ret= burn_get_read_capacity(drive, &readable_blocks, 0);
 3598  Xorriso_process_msg_queues(xorriso, 0);
 3599  if(ret > 0) {
 3600    if(iso_lba + iso_size > readable_blocks) {
 3601      sprintf(xorriso->info_text, "-truncate_overwritable: Given total filesystem size is larger than formatted medium size");
 3602      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3603      ret= 0; goto ex;
 3604    }
 3605  }
 3606 
 3607  /* Give up possible input drive */
 3608  ret= Xorriso_get_drive_handles(xorriso, &dinfo, &in_drive, "", 16);
 3609  if(ret < 0)
 3610    goto ex;
 3611  if(ret == 1) {
 3612    ret= Xorriso_give_up_drive(xorriso, 1);
 3613    if(ret<=0)
 3614      goto ex;
 3615    was_indev= 1;
 3616  }
 3617 
 3618  if(iso_size != new_size) {
 3619    ret=Xorriso_adjust_session_size(xorriso, drive, head_buffer,
 3620                                    iso_lba, iso_size, checksum_block,
 3621                                    new_size, 0);
 3622    if(ret <= 0)
 3623      goto ex;
 3624  }
 3625 
 3626  /* Load first 64 kB and transfer VDs from head_buffer */
 3627  ret= Xorriso_adjust_relocated_sb(xorriso, drive, head_buffer, &sb_buffer, 0);
 3628  if(ret <= 0)
 3629    goto ex;
 3630 
 3631  /* Patch the size and write back */
 3632  ret= Xorriso_update_iso_lba0(xorriso, iso_lba, iso_size, sb_buffer,
 3633                                 NULL, 2 | 16);
 3634  if(ret <= 0)
 3635    goto ex;
 3636 
 3637  ret= Xorriso_reaquire_outdev(xorriso, 2 + was_indev);
 3638  if(ret <= 0)
 3639    goto ex;
 3640 
 3641  ret= 1;
 3642 ex:
 3643  if(caps!=NULL)
 3644    burn_disc_free_multi_caps(&caps);
 3645  Xorriso_free_meM(head_buffer);
 3646  Xorriso_free_meM(sb_buffer);
 3647  Xorriso_process_msg_queues(xorriso,0);
 3648  return(ret);
 3649 }
 3650 
 3651 
 3652 int Xorriso_set_system_area_path(struct XorrisO *xorriso, char *path, int flag)
 3653 {
 3654  int ret;
 3655  char *eff_src= NULL, *intvl;
 3656  struct iso_interval_reader *ivr= NULL;
 3657  off_t byte_count;
 3658  IsoImage *img= NULL;
 3659  struct burn_drive_info *source_dinfo;
 3660  struct burn_drive *source_drive;
 3661 
 3662  if(path[0] == 0) {
 3663    xorriso->system_area_disk_path[0]= 0;
 3664    {ret= 1; goto ex;}
 3665  }
 3666  Xorriso_alloc_meM(eff_src, char, SfileadrL);
 3667 
 3668  intvl = path;
 3669  ret = Xorriso_check_intvl_string(xorriso, &intvl, 0);
 3670  if(ret > 0) {
 3671    /* Check for syntactical correctness */
 3672    if(xorriso->in_drive_handle != NULL) {
 3673      ret= Xorriso_get_drive_handles(xorriso, &source_dinfo, &source_drive,
 3674                              "on attempt to verify interval reader string", 0);
 3675      if(ret<=0)
 3676        goto ex;
 3677      img= isoburn_get_attached_image(source_drive);
 3678    }
 3679    ret= iso_interval_reader_new(img, intvl, &ivr, &byte_count, 1);
 3680    Xorriso_process_msg_queues(xorriso, 0);
 3681    if(ret < 0) {
 3682      sprintf(xorriso->info_text,
 3683             "Given path for system area is not accepted by interval reader");
 3684      Text_shellsafe(eff_src, xorriso->info_text, 1);
 3685      Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3686      {ret= 0; goto ex;}
 3687    }
 3688    iso_interval_reader_destroy(&ivr, 0);
 3689    ret= Sfile_str(xorriso->system_area_disk_path, path, 0);
 3690    if(ret <= 0)
 3691      {ret= -1; goto ex;}
 3692     ret= 1; goto ex;
 3693  }
 3694  ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, path, eff_src, 2|4|16);
 3695  if(ret < 0)
 3696    goto ex;
 3697  if(ret == 0) {
 3698    sprintf(xorriso->info_text,
 3699            "Given path does not exist on disk: -boot_image system_area=");
 3700    Text_shellsafe(eff_src, xorriso->info_text, 1);
 3701    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3702  }
 3703  if(ret == 2) {
 3704    sprintf(xorriso->info_text,
 3705            "Given path leads to a directory: -boot_image system_area=");
 3706    Text_shellsafe(eff_src, xorriso->info_text, 1);
 3707    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3708    {ret= 0; goto ex;}
 3709  }
 3710  ret= Sfile_str(xorriso->system_area_disk_path, eff_src, 0);
 3711  if(ret <= 0)
 3712    {ret= -1; goto ex;}
 3713  ret= 1;
 3714 ex:
 3715  Xorriso_free_meM(eff_src);
 3716  if(img != NULL)
 3717    iso_image_unref(img);
 3718  return(ret);
 3719 }
 3720 
 3721 
 3722 /* @param flag bit0=force burn_disc_close_damaged()
 3723 */
 3724 int Xorriso_close_damaged(struct XorrisO *xorriso, int flag)
 3725 {
 3726  int ret;
 3727  struct burn_drive_info *dinfo;
 3728  struct burn_drive *drive;
 3729  struct burn_write_opts *burn_options= NULL;
 3730 
 3731  if(Xorriso_change_is_pending(xorriso, 0)) {
 3732    sprintf(xorriso->info_text,
 3733            "Image changes pending. -commit or -rollback first");
 3734    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3735    ret= 0; goto ex;
 3736  }
 3737  ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
 3738                                 "on attempt to close damaged session", 2);
 3739  if(ret<=0)
 3740    goto ex;
 3741  ret= Xorriso_check_multi(xorriso, drive, 0);
 3742  if(ret<=0) 
 3743    goto ex;
 3744  ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0);
 3745  if(ret <= 0)
 3746    goto ex;
 3747  ret= burn_disc_close_damaged(burn_options, flag & 1);
 3748  Xorriso_process_msg_queues(xorriso, 0);
 3749  Xorriso_option_dev(xorriso, "", 3 | 4); /* Give up drives */
 3750  if(ret <= 0)
 3751    goto ex;
 3752 
 3753  ret= 1;
 3754 ex:;
 3755  Xorriso_process_msg_queues(xorriso, 0);
 3756  if(burn_options != NULL)
 3757    burn_write_opts_free(burn_options);
 3758  return(ret); 
 3759 }
 3760 
 3761 
 3762 /* @param flag bit0= no error message
 3763 */
 3764 int Xorriso_parse_guid(struct XorrisO *xorriso, char *text,
 3765                        uint8_t guid[16], int flag)
 3766 {
 3767  int bin_count= 0, ret;
 3768  uint8_t u[16], tr;
 3769 
 3770  /* Try RFC 4122 : big endian XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
 3771     Translate to UEFI: first three components to little-endian
 3772   */
 3773  if(strlen(text) == 36) {
 3774    if(text[8] == '-' && text[13] == '-' && text[18] == '-' && text[23] == '-'){
 3775      ret= Hex_to_bin(text, 4, &bin_count, u, 0);
 3776      if(ret < 0 || bin_count != 4)
 3777        goto malformed;
 3778      tr= u[0]; u[0]= u[3]; u[3]= tr;
 3779      tr= u[1]; u[1]= u[2]; u[2]= tr;
 3780      ret= Hex_to_bin(text + 9, 2, &bin_count, u + 4, 0);
 3781      if(ret < 0 || bin_count != 2)
 3782        goto malformed;
 3783      tr= u[4]; u[4]= u[5]; u[5]= tr;
 3784      ret= Hex_to_bin(text + 14, 2, &bin_count, u + 6, 0);
 3785      if(ret < 0 || bin_count != 2)
 3786        goto malformed;
 3787      tr= u[6]; u[6]= u[7]; u[7]= tr;
 3788      ret= Hex_to_bin(text + 19, 2, &bin_count, u + 8, 0);
 3789      if(ret < 0 || bin_count != 2)
 3790        goto malformed;
 3791      ret= Hex_to_bin(text + 24, 6, &bin_count, u + 10, 0);
 3792      if(ret < 0 || bin_count != 6)
 3793        goto malformed;
 3794      memcpy(guid, u, 16);
 3795      return(1);
 3796    }
 3797  }
 3798  if(strlen(text) == 32) {
 3799    ret= Hex_to_bin(text, 16, &bin_count, u, 0);
 3800    if(ret < 0 || bin_count != 16)
 3801      goto malformed;
 3802    memcpy(guid, u, 16);
 3803    return(1);
 3804  }
 3805 
 3806 malformed:;
 3807  if(!(flag & 1)) {
 3808    sprintf(xorriso->info_text, "Malformed GUID string: ");
 3809    Text_shellsafe(text, xorriso->info_text, 1);
 3810    Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 3811  }
 3812  return(0);
 3813 }
 3814 
 3815 
 3816 int Xorriso_parse_gpt_guid(struct XorrisO *xorriso, char *text, int flag)
 3817 {
 3818  int ret;
 3819 
 3820  if(strcmp(text, "random") == 0) {
 3821    xorriso->gpt_guid_mode= 0;
 3822    return(1);
 3823  }
 3824  if(strcmp(text, "modification-date") == 0 ||
 3825     strcmp(text, "volume_date_uuid") == 0) {
 3826    xorriso->gpt_guid_mode= 2;
 3827    return(1);
 3828  }
 3829  ret= Xorriso_parse_guid(xorriso, text, xorriso->gpt_guid, 0);
 3830  if(ret <= 0)
 3831    return(ret);
 3832  xorriso->gpt_guid_mode= 1;
 3833  return(1);
 3834 }
 3835 
 3836 /* @return Tells the recognition status
 3837            0= not recognized as GUID
 3838            1= non-EFI type GUID
 3839            2= EFI type GUID
 3840 */
 3841 int Xorriso_parse_type_guid(struct XorrisO *xorriso, char *text,
 3842                             uint8_t guid[16], int *mbr_type, int flag)
 3843 {
 3844  int j, ret;
 3845  static uint8_t efi_sys_uuid[16] = {
 3846     0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11,
 3847     0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b
 3848  };
 3849 
 3850  ret= Xorriso_parse_guid(xorriso, text, guid, 1);
 3851  if(ret > 0) {
 3852    for(j= 0; j < 16; j++)
 3853      if(guid[j] != efi_sys_uuid[j])
 3854    break;
 3855    if(j >= 16) {
 3856      *mbr_type= 0xef;
 3857      return(2);
 3858    } else {
 3859      *mbr_type= 0x83;
 3860      return(1);
 3861    }
 3862  }
 3863  return(0);
 3864 }
 3865