/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images. Copyright 2007-2024 Thomas Schmitt, Provided under GPL version 2 or later. This file contains functions which are needed to write sessions. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_STDINT_H #include #else #ifdef HAVE_INTTYPES_H #include #endif #endif /* O_BINARY is needed for Cygwin but undefined elsewhere */ #ifndef O_BINARY #define O_BINARY 0 #endif #ifdef Xorriso_standalonE #ifdef Xorriso_with_libjtE #include "../libjte/libjte.h" #endif #else #ifdef Xorriso_with_libjtE #include #endif #endif /* ! Xorriso_standalonE */ #include "xorriso.h" #include "xorriso_private.h" #include "lib_mgt.h" #include "drive_mgt.h" #include "iso_img.h" #include "iso_tree.h" #include "write_run.h" /* @param flag bit0= talk of -as cdrecord -multi rather than of -close */ int Xorriso_check_multi(struct XorrisO *xorriso, struct burn_drive *drive, int flag) { int profile_no= 0, ret; struct burn_multi_caps *caps= NULL; char profile_name[80]; if(xorriso->auto_close) xorriso->do_close= 0; if(!xorriso->do_close) { burn_disc_get_profile(drive, &profile_no, profile_name); if(profile_no == 0x14) { /* DVD-RW sequential */ ret= burn_disc_get_multi_caps(drive, BURN_WRITE_TAO, &caps, 0); if(caps != NULL) burn_disc_free_multi_caps(&caps); if(ret == 0) { if(xorriso->auto_close) { sprintf(xorriso->info_text, "-close \"as_needed\" triggered -close \"on\""); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); xorriso->do_close= 1; } else if(flag & 1) { sprintf(xorriso->info_text, "This DVD-RW media can only be written without option -multi"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); sprintf(xorriso->info_text, "Possibly it was blanked by blank=deformat_quickest"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); sprintf(xorriso->info_text, "After writing a session without -multi, apply blank=all"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); return(0); } else { sprintf(xorriso->info_text, "This DVD-RW media can only be written with -close \"on\""); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); sprintf(xorriso->info_text, "Possibly it was blanked by -blank \"deformat_quickest\""); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); sprintf(xorriso->info_text, "After writing a session with -close \"on\", apply -blank \"all\""); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); return(0); } } } else if(profile_no == 0x15) { /* DVD-RW DL */ if(xorriso->auto_close) { sprintf(xorriso->info_text, "-close \"as_needed\" triggered -close \"on\""); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); xorriso->do_close= 1; } else if(flag & 1) { sprintf(xorriso->info_text, "DVD-R DL media can only be written without option -multi"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } else { sprintf(xorriso->info_text, "DVD-R DL media can only be written with -close \"on\""); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } } } return(1); } int Xorriso_make_write_options( struct XorrisO *xorriso, struct burn_drive *drive, struct burn_write_opts **burn_options, int flag) { int drive_role, stream_mode= 0, ret, profile; char profile_name[80]; enum burn_disc_status s; *burn_options= burn_write_opts_new(drive); if(*burn_options==NULL) { Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text,"Cannot allocate option set"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } burn_write_opts_set_simulate(*burn_options, !!xorriso->do_dummy); drive_role= burn_drive_get_drive_role(drive); burn_write_opts_set_multi(*burn_options, !(xorriso->do_close || drive_role==0 || drive_role==3)); ret= burn_disc_get_profile(drive, &profile, profile_name); if(ret > 0) { s= isoburn_disc_get_status(drive); if(xorriso->auto_close && xorriso->do_close == 0 && profile == 0x14 && s == BURN_DISC_BLANK) /* Prepare for missing feature 21h despite drive's announcement */ burn_write_opts_set_fail21h_sev(*burn_options, "NOTE"); } if(xorriso->write_speed != -2) burn_drive_set_speed(drive, 0, xorriso->write_speed); burn_drive_set_buffer_waiting(drive, xorriso->modesty_on_drive, xorriso->min_buffer_usec, xorriso->max_buffer_usec, xorriso->buffer_timeout_sec, xorriso->min_buffer_percent, xorriso->max_buffer_percent); if(xorriso->do_stream_recording == 1) stream_mode= 1; else if(xorriso->do_stream_recording == 2) stream_mode= 51200; /* 100 MB */ else if(xorriso->do_stream_recording >= 16) stream_mode= xorriso->do_stream_recording; burn_write_opts_set_stream_recording(*burn_options, stream_mode); #ifdef Xorriso_dvd_obs_default_64K if(xorriso->dvd_obs == 0) burn_write_opts_set_dvd_obs(*burn_options, 64 * 1024); else #endif burn_write_opts_set_dvd_obs(*burn_options, xorriso->dvd_obs); burn_write_opts_set_obs_pad(*burn_options, !!xorriso->do_obs_pad); burn_write_opts_set_bdr_obs_exempt(*burn_options, !!xorriso->bdr_obs_exempt); burn_write_opts_set_stdio_fsync(*burn_options, xorriso->stdio_sync); burn_write_opts_set_underrun_proof(*burn_options, 1); return(1); } /* @param flag bit0= do not write but only prepare and return size in sectors bit1= do not use isoburn wrappers, do not assume libisofs bit2= no_emul_toc : do not pad random access media to full 64 KB */ off_t Xorriso_sanitize_image_size(struct XorrisO *xorriso, struct burn_drive *drive, struct burn_disc *disc, struct burn_write_opts *burn_options, int flag) { int num_sessions= 0, num_tracks= 0, padding= 0, profile; off_t media_space, ret, img_sectors, lba, nwa, multi_emul_blocks= 0; char profile_name[80]; struct burn_session **sessions; struct burn_track **tracks; enum burn_disc_status s; img_sectors= burn_disc_get_sectors_v2(disc); sessions= burn_disc_get_sessions(disc, &num_sessions); if(sessions==NULL || num_sessions < 1) { no_track:; Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text,"Program error : no track in prepared disc"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); {ret= -1; goto ex;} } tracks= burn_session_get_tracks(sessions[0], &num_tracks); if(tracks==NULL || num_tracks < 1) goto no_track; padding= 0; ret= burn_disc_get_profile(drive, &profile, profile_name); padding= xorriso->padding / 2048; if(xorriso->padding > padding * 2048) padding++; if(img_sectors>0 && ret>0 && (profile==0x09 || profile==0x0a)) { /* CD-R , CD-RW */ if(img_sectors + padding < Xorriso_cd_min_track_sizE) { padding= Xorriso_cd_min_track_sizE - img_sectors; sprintf(xorriso->info_text, "Expanded track to minimum size of %d sectors", Xorriso_cd_min_track_sizE); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); } } if(xorriso->alignment == 0 && !((xorriso->no_emul_toc & 1) || flag & 4)) { ret= isoburn_needs_emulation(drive); if(ret > 0) { /* Take care that the session is padded up to the future NWA. Else with padding < 32 it could happen that PVDs from older sessions survive and confuse -rom_toc_scan. */ xorriso->alignment= 32; s= isoburn_disc_get_status(drive); if(s == BURN_DISC_BLANK) { /* Count blocks before nwa as part of the image */; ret= isoburn_disc_track_lba_nwa_v2(drive, burn_options, 0, &lba, &nwa); if(ret <= 0) nwa= 0; multi_emul_blocks= nwa; } } } if(!(flag & 2)) { #ifdef Xorriso_with_libjtE /* JTE : no multi-session, no_emul_toc, padding in libisofs */ if(xorriso->libjte_handle != NULL) padding= 0; #endif /* ! Xorriso_with_libjtE */ if(xorriso->do_padding_by_libisofs) padding= 0; } if(xorriso->alignment > 0) { if(img_sectors > 0) { ret= isoburn_disc_track_lba_nwa_v2(drive, burn_options, 0, &lba, &nwa); if(ret <= 0) nwa= 0; lba= (nwa + img_sectors + padding) % xorriso->alignment; if(lba > 0) padding+= xorriso->alignment - lba; } } burn_track_define_data(tracks[0], 0, padding * 2048, 0, BURN_MODE1); Xorriso_process_msg_queues(xorriso,0); if(flag&2) media_space= burn_disc_available_space(drive, burn_options) / (off_t) 2048; else media_space= isoburn_disc_available_space(drive, burn_options) / (off_t) 2048; if(media_space < img_sectors + padding) { Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text, "Image size %.fs exceeds free space on media %.fs", (double) (img_sectors + padding), (double) media_space); if(flag & 1) { Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); } else { Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } } if(flag&1) { ret= multi_emul_blocks + img_sectors + padding; } else ret= 1; ex:; return(ret); } int Xorriso_auto_format(struct XorrisO *xorriso, int flag) { int ret, profile, status, num_formats; char profile_name[80]; struct burn_drive_info *dinfo; struct burn_drive *drive; off_t size; unsigned dummy; ret= Xorriso_may_burn(xorriso, 0); if(ret <= 0) return(0); ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to autoformat", 2); if(ret<=0) return(0); ret= burn_disc_get_profile(drive, &profile, profile_name); if(ret>0 && (profile==0x12 || profile==0x43)) { /* DVD-RAM or BD-RE */ ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats); if(ret>0 && status==BURN_FORMAT_IS_UNFORMATTED) { sprintf(xorriso->info_text, "Unformatted %s medium detected. Trying -format fast.", profile_name); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); ret= Xorriso_format_media(xorriso, (off_t) 0, 1 | 4); if(ret<=0) { sprintf(xorriso->info_text, "Automatic formatting of %s failed", profile_name); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(ret); } burn_drive_re_assess(drive, 0); } } return(1); } /* @param flag bit0= fail on indev == outdev with "imported_iso" bit1= fail on indev == NULL with "imported_iso" */ int Xorriso_check_intvl_string(struct XorrisO *xorriso, char **part_image, int flag) { char *cpt, *ipt, *orig; orig= *part_image; if(strncmp(*part_image, "--interval:", 11) != 0) return(0); if(strchr(*part_image + 11, ':') == NULL) return(0); (*part_image)+= 11; if(!(flag & 3)) return(1); cpt= strchr(*part_image, ':'); ipt= strstr(*part_image, "imported_iso"); if(ipt == NULL || ipt > cpt) return(1); if((flag & 2) && xorriso->in_drive_handle == NULL) { sprintf(xorriso->info_text, "Interval reader lacks of -indev to read from \"imported_iso\""); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); goto failure; } if(!(flag & 1)) return(1); if(xorriso->out_drive_handle != xorriso->in_drive_handle) return(1); sprintf(xorriso->info_text, "Interval reader may not read from \"imported_iso\" during write run to same drive"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); failure:; sprintf(xorriso->info_text, "Rejected: "); Text_shellsafe(orig, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(-1); } int Xorriso_set_system_area(struct XorrisO *xorriso, struct burn_drive *in_drive, struct burn_drive *out_drive, IsoImage *img, struct isoburn_imgen_opts *sopts, int flag) { int ret, options, system_area_options; int sa_loaded, read_count, i, read_sum= 0; off_t iso_lba= -1, start_lba, image_blocks; char volid[33]; FILE *fp= NULL; char *buf= NULL, *bufpt= NULL, *intvl; uint8_t *intvl_buf; off_t hd_lba, byte_count; unsigned char *ub; ElToritoBootImage *bootimg; IsoFile *bootimg_node; IsoNode *sparc_core_node; uint32_t offst; enum burn_disc_status state; struct iso_interval_reader *ivr = NULL; if(xorriso->grub2_sparc_core[0]) { ret= Xorriso_node_from_path(xorriso, img, xorriso->grub2_sparc_core, &sparc_core_node, 1); if(ret <= 0) { sprintf(xorriso->info_text, "Cannot find in ISO image: -boot_image grub grub2_sparc_core="); Text_shellsafe(xorriso->grub2_sparc_core, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } if(!ISO_NODE_IS_FILE(sparc_core_node)) { sprintf(xorriso->info_text, "Not a data file: -boot_image grub grub2_sparc_core="); Text_shellsafe(xorriso->grub2_sparc_core, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } ret = iso_image_set_sparc_core(img, (IsoFile *) sparc_core_node, 0); if(ret < 0) { Xorriso_process_msg_queues(xorriso,0); Xorriso_report_iso_error(xorriso, "", ret, "Error when setting up -boot_image grub grub2_sparc_core=", 0, "FAILURE", 1); {ret= 0; goto ex;} } } Xorriso_alloc_meM(buf, char, 32768); memset(buf, 0, 32768); system_area_options= xorriso->system_area_options; if(xorriso->system_area_clear_loaded || (in_drive != out_drive && in_drive != NULL)) sa_loaded= 0; else sa_loaded= iso_image_get_system_area(img, buf, &options, 0); if(sa_loaded < 0) { Xorriso_process_msg_queues(xorriso,0); Xorriso_report_iso_error(xorriso, "", sa_loaded, "Error when inquiring System Area data of ISO 9660 image", 0, "FAILURE", 1); {ret= 0; goto ex;} } bufpt= buf; if(xorriso->system_area_disk_path[0] == 0) { if(xorriso->patch_system_area && xorriso->system_area_options == 0 && sa_loaded > 0) { system_area_options= xorriso->patch_system_area; /* Check whether partition 1 ends at image end */; ub= (unsigned char *) buf; hd_lba= (ub[454] | (ub[455] << 8) | (ub[456] << 16) | (((unsigned int) ub[457]) << 24)) + (ub[458] | (ub[459] << 8) | (ub[460] << 16) | (((unsigned int) ub[461]) << 24)); iso_lba= -1; ret= isoburn_disc_get_msc1_v2(in_drive, &start_lba); if(ret > 0) { ret= isoburn_read_iso_head_v2(in_drive, start_lba, &image_blocks, volid, 1); if(ret > 0) iso_lba= start_lba + image_blocks; } if(iso_lba * (off_t) 4 > hd_lba) { system_area_options= 0; } else if((xorriso->patch_system_area & 1) && iso_lba * (off_t) 4 != hd_lba) { system_area_options= 0; } else if((xorriso->patch_system_area & 2) && iso_lba * (off_t) 4 + (off_t) (63 * 256) < hd_lba) { system_area_options= 0; } else if(xorriso->patch_system_area & 2) { /* isohybrid patching */ /* Check whether bytes 432-345 point to ElTorito LBA */ hd_lba= ub[432] | (ub[433] << 8) | (ub[434] << 16) | (((unsigned int) ub[435]) << 24); ret= iso_image_get_boot_image(img, &bootimg, &bootimg_node, NULL); if(ret != 1) { system_area_options= 0; } else if(bootimg_node != NULL) { Xorriso__file_start_lba((IsoNode *) bootimg_node, &(iso_lba), 0); if(iso_lba * (off_t) 4 != hd_lba) system_area_options= 0; } } if(system_area_options == 0) { Xorriso_msgs_submit(xorriso, 0, "Loaded System Area data are not suitable for MBR patching.", 0, "DEBUG", 0); } } {ret= 1; goto do_set;} } bufpt= buf; if(strcmp(xorriso->system_area_disk_path, "/dev/zero") == 0) { memset(buf, 0, 32768); {ret= 1; goto do_set;} } intvl= xorriso->system_area_disk_path; ret= Xorriso_check_intvl_string(xorriso, &intvl, 2); if(ret < 0) { {ret= 0; goto ex;} } else if(ret > 0) { ret= iso_interval_reader_new(img, intvl, &ivr, &byte_count, 0); Xorriso_process_msg_queues(xorriso, 0); if(ret < 0) { intvl_reader_err:; sprintf(xorriso->info_text, "Error when reading -boot_image system_area="); Text_shellsafe(xorriso->system_area_disk_path, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); {ret= 0; goto ex;} } for(i= 0; i < 16; i++) { intvl_buf= (uint8_t *) (buf + 2048 * i); ret= iso_interval_reader_read(ivr, intvl_buf, &read_count, 0); Xorriso_process_msg_queues(xorriso, 0); if(ret == 0) break; if(ret < 0) goto intvl_reader_err; read_sum+= read_count; } ret= read_sum; } else { ret= Xorriso_afile_fopen(xorriso, xorriso->system_area_disk_path, "rb", &fp, 2); if(ret <= 0) {ret= 0; goto ex;} ret= fread(buf, 1, 32768, fp); if(ret < 32768) { if(ferror(fp)) { sprintf(xorriso->info_text, "Error when reading -boot_image system_area="); Text_shellsafe(xorriso->system_area_disk_path, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); {ret= 0; goto ex;} } } } do_set:; if(ret > 0 && xorriso->system_area_disk_path[0]) { sprintf(xorriso->info_text, "Copying to System Area: %d bytes from file ", ret); Text_shellsafe(xorriso->system_area_disk_path, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); } ret= isoburn_igopt_set_system_area(sopts, bufpt, system_area_options); if(ret != ISO_SUCCESS) { Xorriso_process_msg_queues(xorriso,0); Xorriso_report_iso_error(xorriso, "", ret, "Error when attaching System Area data to ISO 9660 image", 0, "FAILURE", 1); {ret= 0; goto ex;} } offst= xorriso->partition_offset; state= isoburn_disc_get_status(out_drive); if(state == BURN_DISC_APPENDABLE) { ret= isoburn_get_img_partition_offset(out_drive, &offst); if(ret == 1) { sprintf(xorriso->info_text, "Preserving in ISO image: -boot_image any partition_offset=%lu", (unsigned long) offst); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); } else offst= xorriso->partition_offset; } ret= isoburn_igopt_set_part_offset(sopts, offst, xorriso->partition_secs_per_head, xorriso->partition_heads_per_cyl); if(ret != ISO_SUCCESS) { Xorriso_process_msg_queues(xorriso,0); Xorriso_report_iso_error(xorriso, "", ret, "Error when setting partition offset", 0, "FAILURE", 1); {ret= 0; goto ex;} } ret= 1; ex:; if(fp != NULL && fp != stdin) fclose(fp); iso_interval_reader_destroy(&ivr, 0); Xorriso_free_meM(buf); return(ret); } /* @param flag bit0= do not increment boot_count and do not reset boot parameters bit1= dispose attached boot images */ int Xorriso_attach_boot_image(struct XorrisO *xorriso, int flag) { int ret; char *cpt; struct burn_drive_info *source_dinfo; struct burn_drive *source_drive; IsoImage *image= NULL; IsoNode *node= NULL; ElToritoBootImage *bootimg; enum eltorito_boot_media_type emul_type= ELTORITO_NO_EMUL; char *bin_path; int emul, platform_id; off_t load_size; struct stat stbuf; int hflag= 0, is_interval= 0, cat_tries; if(xorriso->boot_image_bin_path[0] == 0 && !(flag & 2)) { /* >>> no boot image path given : no op */; ret= 2; goto ex; } if(xorriso->in_drive_handle == NULL) hflag= 2; ret= Xorriso_get_drive_handles(xorriso, &source_dinfo, &source_drive, "on attempt to attach boot image", hflag); if(ret<=0) goto ex; image= isoburn_get_attached_image(source_drive); if(image == NULL) { /* (should not happen) */ sprintf(xorriso->info_text, "No ISO image present on attempt to attach boot image"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } if(flag & 2) { iso_image_remove_boot_image(image); xorriso->boot_count= 0; ret= 1; goto ex; } bin_path= xorriso->boot_image_bin_path; emul= xorriso->boot_image_emul; platform_id= xorriso->boot_platform_id; load_size= xorriso->boot_image_load_size; if(strncmp(bin_path, "--interval:appended_partition_", 30) == 0) { is_interval= 1; if(load_size <= 0) load_size= 512; } if(xorriso->boot_efi_default) { emul= 0; platform_id= 0xef; xorriso->patch_isolinux_image= (xorriso->patch_isolinux_image & ~3) | 0; } if((platform_id == 0xef || load_size < 0) && !is_interval) { ret= Xorriso_iso_lstat(xorriso, bin_path, &stbuf, 2 | 4); if(ret != 0) {ret= 0; goto ex;} load_size= ((stbuf.st_size / (off_t) 512) + !!(stbuf.st_size % (off_t) 512)) * 512; } sprintf(xorriso->info_text, "Adding boot image "); Text_shellsafe(bin_path, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); if(emul == 0) emul_type= ELTORITO_NO_EMUL; else if(emul == 1) emul_type= ELTORITO_HARD_DISC_EMUL; else if(emul == 2) emul_type= ELTORITO_FLOPPY_EMUL; if (!is_interval) { ret= Xorriso_node_from_path(xorriso, image, bin_path, &node, 1); if(ret <= 0) { sprintf(xorriso->info_text, "Cannot find in ISO image: -boot_image ... bin_path="); Text_shellsafe(bin_path, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } } if(xorriso->boot_count == 0) { if(xorriso->boot_image_cat_path[0] == 0) { strcpy(xorriso->boot_image_cat_path, bin_path); cpt= strrchr(xorriso->boot_image_cat_path, '/'); if(cpt == NULL) { strcpy(xorriso->boot_image_cat_path, "/"); cpt= xorriso->boot_image_cat_path + 1; } else { cpt++; } strcpy(cpt, "boot.cat"); if(xorriso->boot_image_cat_hidden & 1) { /* Find a name which does not yet exist */ ret= 1; for(cat_tries= 1; ret > 0 && cat_tries < 1000000; cat_tries++) { ret= Xorriso_node_from_path(xorriso, image, xorriso->boot_image_cat_path, &node, 1); if(ret > 0) sprintf(cpt, "real%d_boot.cat", cat_tries); } } } ret= Xorriso_node_from_path(xorriso, image, xorriso->boot_image_cat_path, &node, 1); if(ret > 0) { if(!xorriso->do_overwrite) { sprintf(xorriso->info_text, "May not overwrite existing -boot_image ... cat_path="); Text_shellsafe(xorriso->boot_image_cat_path, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, xorriso->boot_image_cat_path, 8 | (xorriso->do_overwrite == 1)); if(ret != 1) { sprintf(xorriso->info_text, "Could not remove existing -boot_image cat_path="); Text_shellsafe(xorriso->boot_image_cat_path, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } } /* Discard old boot image, set new one */ ret= iso_image_get_boot_image(image, &bootimg, NULL, NULL); if(ret == 1) iso_image_remove_boot_image(image); ret= iso_image_set_boot_image(image, bin_path, emul_type, xorriso->boot_image_cat_path, &bootimg); if(ret > 0) iso_image_set_boot_catalog_weight(image, 1000000000); } else { ret= iso_image_add_boot_image(image, bin_path, emul_type, 0, &bootimg); } if(ret < 0) { Xorriso_process_msg_queues(xorriso,0); Xorriso_report_iso_error(xorriso, "", ret, "Error when attaching El-Torito boot image to ISO 9660 image", 0, "FAILURE", 1); sprintf(xorriso->info_text, "Could not attach El-Torito boot image to ISO 9660 image"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } el_torito_set_boot_platform_id(bootimg, (uint8_t) platform_id); if(load_size / 512 > 65535) { sprintf(xorriso->info_text, "Boot image load size exceeds 65535 blocks of 512 bytes. "); if(platform_id == 0xef) { strcat(xorriso->info_text, "Will record 0 in El Torito to extend ESP to end-of-medium."); load_size= 0; } else { strcat(xorriso->info_text, "Will record 65535 in El Torito."); load_size= 65535 * 512; } Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); } if(xorriso->boot_img_full_size) { el_torito_set_full_load(bootimg, 1); } else { /* The function will understand negative short as positive unsigned */ el_torito_set_load_size(bootimg, (short) (load_size / 512)); } el_torito_set_id_string(bootimg, xorriso->boot_id_string); el_torito_set_selection_crit(bootimg, xorriso->boot_selection_crit); ret= Xorriso_set_isolinux_options(xorriso, image, 1); if(!(flag & 1)) { /* Register attachment and reset even in case of error return */ xorriso->boot_count++; xorriso->boot_platform_id= 0; xorriso->patch_isolinux_image= 0; xorriso->boot_image_bin_path[0]= 0; xorriso->boot_image_bin_form[0]= 0; xorriso->boot_image_emul= 0; xorriso->boot_emul_default= 1; xorriso->boot_image_load_size= 4 * 512; xorriso->boot_img_size_default= 1; xorriso->boot_img_full_size= 0; memset(xorriso->boot_id_string, 0, sizeof(xorriso->boot_id_string)); memset(xorriso->boot_selection_crit, 0, sizeof(xorriso->boot_selection_crit)); xorriso->boot_efi_default= 0; } if(ret <= 0) goto ex; ret= 1; ex:; if(image != NULL) iso_image_unref(image); return(ret); } int Xorriso_write_application_use(struct XorrisO *xorriso, IsoImage *image, int flag) { int l, ret, count= 512; unsigned int byte= 0; char *path, data[512]; FILE *fp= NULL; path= xorriso->application_use; l= strlen(path); if(l <= 1) { memset(data, path[0], 512); } else if(l == 4 && path[0] == '0' && path[1] == 'x' && isxdigit(path[2]) && isxdigit(path[3])) { sscanf(path + 2, "%x", &byte); memset(data, (int) byte, 512); } else { /* Read up to 512 bytes from file path */ ret= Xorriso_afile_fopen(xorriso, path, "rb", &fp, 0); if(ret <= 0) {ret= 0; goto ex;} ret= fread(data, 1, 512, fp); if(ret < 512) { if(ferror(fp)) { sprintf(xorriso->info_text, "-application_use: Error while reading file "); Text_shellsafe(path, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); ret= 0; goto ex; } } if(ret < 0) count= 0; else count= ret; } iso_image_set_app_use(image, data, count); ret= 1; ex: if(fp != NULL && fp != stdin) fclose(fp); return(ret); } int Xorriso_retry_write_session(struct XorrisO *xorriso, int flag) { int ret, auto_close_mem, do_close_mem; if(xorriso->do_tao == 1) { Xorriso_msgs_submit(xorriso, 0, "There is no hope for a re-try with -close \"on\" as long as -write_type is \"tao\"", 0, "FAILURE", 0); return(0); } Xorriso_msgs_submit(xorriso, 0, "Re-trying with -close \"on\"", 0, "NOTE", 0); do_close_mem= xorriso->do_close; auto_close_mem= xorriso->auto_close; xorriso->do_close= 1; xorriso->auto_close= 0; ret= Xorriso_write_session(xorriso, 0); xorriso->do_close= do_close_mem; xorriso->auto_close= auto_close_mem; return(ret); } int Xorriso_make_iso_write_opts(struct XorrisO *xorriso, IsoImage *image, struct isoburn_imgen_opts *sopts, int flag) { int ext, i, ret, pad_by_libisofs= 0, is_bootable= 0, relax, intvl_string= 0; int intvl_check= 2; /* 3 forbids "imported_iso" */ int with_appended_partition= 0; char *out_cs, *part_image; IsoNode *root_node; uint32_t padding; relax= xorriso->relax_compliance; if(image != NULL) is_bootable= iso_image_get_boot_image(image, NULL, NULL, NULL); /* xorriso->patch_isolinux_image gets reset in Xorriso_attach_boot_image() So this applies only to -boot_image ... "patch" or "keep". >>> Better would be to analyze and keep the relaxations of the loaded image. */ if((xorriso->patch_isolinux_image & 1) && is_bootable == 1) relax|= isoburn_igopt_allow_full_ascii; out_cs= xorriso->out_charset; if(out_cs == NULL) Xorriso_get_local_charset(xorriso, &out_cs, 0); isoburn_igopt_set_level(sopts, xorriso->iso_level); ext= ((!!xorriso->do_rockridge) * isoburn_igopt_rockridge) | ((!!xorriso->do_joliet) * isoburn_igopt_joliet) | ((!!xorriso->do_hfsplus) * isoburn_igopt_hfsplus) | ((!!xorriso->do_fat) * isoburn_igopt_fat) | ((!!xorriso->do_iso1999) * isoburn_igopt_iso1999) | (( !(xorriso->ino_behavior & 2)) * isoburn_igopt_hardlinks) | (( (!(xorriso->ino_behavior & 2)) || (xorriso->do_aaip & (2 | 8 | 16 | 256 | (1 << 11) | (1 << 17))) || (xorriso->do_md5 & (2 | 4)) || xorriso->do_hfsplus ) * isoburn_igopt_aaip) | ((!!(xorriso->do_md5 & 2)) * isoburn_igopt_session_md5) | ((!!(xorriso->do_md5 & 4)) * isoburn_igopt_file_md5) | ((!!(xorriso->do_md5 & 8)) * isoburn_igopt_file_stability) | ((!!xorriso->do_old_empty) * isoburn_igopt_old_empty) | ((flag & 1) * isoburn_igopt_will_cancel); if(xorriso->no_emul_toc & 1) ext|= isoburn_igopt_no_emul_toc; isoburn_igopt_set_extensions(sopts, ext); isoburn_igopt_set_relaxed(sopts, relax); ret = isoburn_igopt_set_rr_reloc(sopts, xorriso->rr_reloc_dir, xorriso->rr_reloc_flags); if(ret <= 0) {ret= 0; goto ex;} ret= isoburn_igopt_set_untranslated_name_len(sopts, xorriso->untranslated_name_len); if(ret <= 0) {ret= 0; goto ex;} isoburn_igopt_set_sort_files(sopts, 1); isoburn_igopt_set_over_mode(sopts, 0, 0, (mode_t) 0, (mode_t) 0); isoburn_igopt_set_over_ugid(sopts, 2 * !!xorriso->do_global_uid, 2 * !!xorriso->do_global_gid, (uid_t) xorriso->global_uid, (gid_t) xorriso->global_gid); isoburn_igopt_set_out_charset(sopts, out_cs); isoburn_igopt_set_fifo_size(sopts, xorriso->fs * 2048); Ftimetxt(time(NULL), xorriso->scdbackup_tag_time, 8); isoburn_igopt_set_scdbackup_tag(sopts, xorriso->scdbackup_tag_name, xorriso->scdbackup_tag_time, xorriso->scdbackup_tag_written); if(xorriso->prep_partition[0]) { part_image= xorriso->prep_partition; intvl_string= Xorriso_check_intvl_string(xorriso, &part_image, intvl_check); if(intvl_string < 0) {ret= 0; goto ex;} ret= isoburn_igopt_set_prep_partition(sopts, part_image, intvl_string); if(ret <= 0) {ret= 0; goto ex;} } if(xorriso->efi_boot_partition[0]) { part_image= xorriso->efi_boot_partition; intvl_string= Xorriso_check_intvl_string(xorriso, &part_image, intvl_check); if(intvl_string < 0) {ret= 0; goto ex;} ret= isoburn_igopt_set_efi_bootp(sopts, part_image, intvl_string); if(ret <= 0) {ret= 0; goto ex;} } for(i= 0; i < Xorriso_max_appended_partitionS; i++) { if(xorriso->appended_partitions[i] == NULL) continue; if(xorriso->appended_partitions[i][0] == 0) continue; if(strcmp(xorriso->appended_partitions[i], ".") == 0) part_image= ""; else part_image= xorriso->appended_partitions[i]; intvl_string= Xorriso_check_intvl_string(xorriso, &part_image, intvl_check); if(intvl_string < 0) {ret= 0; goto ex;} isoburn_igopt_set_partition_img(sopts, i + 1, xorriso->appended_part_types[i], part_image); isoburn_igopt_set_part_flag(sopts, i + 1, intvl_string); isoburn_igopt_set_part_type_guid(sopts, i + 1, xorriso->appended_part_type_guids[i], xorriso->appended_part_gpt_flags[i] & 1); with_appended_partition= 1; } isoburn_igopt_set_appended_as_gpt(sopts, xorriso->appended_as_gpt); isoburn_igopt_set_appended_as_apm(sopts, xorriso->appended_as_apm); isoburn_igopt_set_part_like_isohybrid(sopts, xorriso->part_like_isohybrid); isoburn_igopt_set_iso_mbr_part_type(sopts, xorriso->iso_mbr_part_type); isoburn_igopt_set_iso_type_guid(sopts, xorriso->iso_gpt_type_guid, xorriso->iso_mbr_part_flag & 1); isoburn_igopt_set_gpt_guid(sopts, xorriso->gpt_guid, xorriso->gpt_guid_mode); /* GPT with gaps only if partitions get appended */ if(with_appended_partition && xorriso->appended_as_gpt) isoburn_igopt_set_gpt_with_gaps(sopts, !!(xorriso->iso_mbr_part_flag & 2), !!(xorriso->iso_mbr_part_flag & 4), !!(xorriso->iso_mbr_part_flag & 8)); ret= isoburn_igopt_set_max_ce_entries(sopts, xorriso->max_ce_entries, xorriso->max_ce_entries_flag); if(ret <= 0) {ret= 0; goto ex;} isoburn_igopt_set_disc_label(sopts, xorriso->ascii_disc_label); isoburn_igopt_set_hfsp_serial_number(sopts, xorriso->hfsp_serial_number); isoburn_igopt_set_hfsp_block_size(sopts, xorriso->hfsp_block_size, xorriso->apm_block_size); isoburn_igopt_set_pvd_times(sopts, xorriso->vol_creation_time, xorriso->vol_modification_time, xorriso->vol_expiration_time, xorriso->vol_effective_time, xorriso->vol_uuid); #ifdef Xorriso_with_libjtE if(xorriso->libjte_handle && (xorriso->libjte_params_given & (4 | 8))) { /* >>> Check whether the mandatory parameters are set */; ret= libjte_set_outfile(xorriso->libjte_handle, xorriso->outdev); Xorriso_process_msg_queues(xorriso, 0); if(ret <= 0) goto ex; isoburn_igopt_attach_jte(sopts, xorriso->libjte_handle); pad_by_libisofs= 1; } #endif /* Xorriso_with_libjtE */ if(xorriso->do_padding_by_libisofs || pad_by_libisofs) { /* Padding to be done by libisofs, not by libburn. */ padding= xorriso->padding / 2048; if((uint32_t) xorriso->padding > padding * 2048) padding++; /* fprintf(stderr, "XORRISO_DEBUG: isoburn_igopt_set_tail_blocks(%d)\n", (int) padding); */ isoburn_igopt_set_tail_blocks(sopts, padding); } /* Make final abort check before starting expensive activities */ ret= Xorriso_eval_problem_status(xorriso, 1, 0); if(ret<0) {ret= 0; goto ex;} if(xorriso->zisofs_by_magic && image != NULL) { sprintf(xorriso->info_text, "Checking disk file content for zisofs compression headers."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); root_node= (IsoNode *) iso_image_get_root(image); ret= iso_node_zf_by_magic(root_node, (xorriso->out_drive_handle == xorriso->in_drive_handle) | 2 | 16 | (xorriso->zisofs_by_magic << 8)); if(ret<0) { Xorriso_report_iso_error(xorriso, "", ret, "Error when examining file content for zisofs headers", 0, "FAILURE", 1); } ret= Xorriso_eval_problem_status(xorriso, 1, 0); if(ret<0) {ret= 0; goto ex;} sprintf(xorriso->info_text, "Check for zisofs compression headers done."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); } ret = isoburn_igopt_set_write_type(sopts, xorriso->do_tao); if(ret <= 0) goto ex; ret = isoburn_igopt_set_stdio_endsync(sopts, xorriso->stdio_sync >= 0); if(ret <= 0) goto ex; ret= 1; ex:; Xorriso_process_msg_queues(xorriso, 0); return(ret); } int Xorriso_set_all_file_dates(struct XorrisO *xorriso, int flag) { int idx, ret, was_failure= 0; char *hargv[4]; if(xorriso->all_file_dates[0] == 0) return(2); if(strcmp(xorriso->all_file_dates, "set_to_mtime") == 0) { hargv[0]= "/"; hargv[1]= "-exec"; hargv[2]= "set_to_mtime"; hargv[3]= "--"; idx= 0; ret= Xorriso_option_find(xorriso, 4, hargv, &idx, 0); if(ret <= 0) was_failure= 1; } else { hargv[0]= "/"; idx= 0; ret= Xorriso_option_alter_date(xorriso, "b", xorriso->all_file_dates, 1, hargv, &idx, 1); if(ret <= 0) was_failure= 1; idx= 0; ret= Xorriso_option_alter_date(xorriso, "c", xorriso->all_file_dates, 1, hargv, &idx, 1); if(ret <= 0) was_failure= 1; } Xorriso_relax_compliance(xorriso, "always_gmt", 0); return(!was_failure); } /* @return 0= no EFI , 1= EFI but no warning needed , 2= warning was issued */ int Xorriso_warn_efi_boot_dir(struct XorrisO *xorriso, IsoImage *image, int flag) { int ret, num_boots, i, filec= 0; off_t mem= 0; char *patterns[1], **filev= NULL; ElToritoBootImage **boots = NULL; IsoFile **bootnodes = NULL; IsoNode *node; /* Check El Torito images for EFI */ ret= iso_image_get_all_boot_imgs(image, &num_boots, &boots, &bootnodes, 0); Xorriso_process_msg_queues(xorriso,0); if(ret == 1) { for(i= 0; i appended_partitions[i] == NULL) continue; if(xorriso->appended_partitions[i][0] == 0) continue; if(xorriso->appended_part_types[i] == 0xef) goto has_efi; } /* No EFI found */ ret= 0; goto ex; has_efi:; /* Check for /[Ee][Ff][Ii]/[Bb][Oo][Oo][Tt]/ in ISO tree */ patterns[0]= "/[Ee][Ff][Ii]/[Bb][Oo][Oo][Tt]"; ret= Xorriso_expand_pattern(xorriso, 1, patterns, 0, &filec, &filev, &mem, 0); if(ret > 0 && filec > 0) { ret= Xorriso_node_from_path(xorriso, image, filev[0], &node, 1); if(ret > 0) { if(LIBISO_ISDIR(node)) { ret= 1; goto ex; } } } Xorriso_msgs_submit(xorriso, 0, "EFI boot equipment is provided but no directory /EFI/BOOT", 0, "WARNING", 0); Xorriso_msgs_submit(xorriso, 0, "will emerge in the ISO filesystem. A popular method to", 0, "WARNING", 0); Xorriso_msgs_submit(xorriso, 0, "prepare a USB stick on MS-Windows relies on having in the", 0, "WARNING", 0); Xorriso_msgs_submit(xorriso, 0, "ISO filesystem a copy of the EFI System Partition tree.", 0, "WARNING", 0); ret= 2; ex:; Sfile_destroy_argv(&filec, &filev, 0); if(boots != NULL) free(boots); if(bootnodes != NULL) free(bootnodes); return(ret); } /* @param flag bit0= do not write but only prepare and return size in sectors @return <=0 error , 1= success 2= failure with DVD-RW, please call Xorriso_retry_write_session() */ off_t Xorriso_write_session(struct XorrisO *xorriso, int flag) { int ret, i, pacifier_speed= 0, is_bootable= 0; off_t data_lba; int freshly_bootable= 0, hide_attr, signal_mode, role, is_bdr_pow= 0; char *xorriso_id= NULL, *img_id, *sfe= NULL, *out_cs; struct isoburn_imgen_opts *sopts= NULL; struct burn_drive_info *dinfo, *source_dinfo; struct burn_drive *drive, *source_drive; struct burn_disc *disc= NULL; struct burn_write_opts *burn_options= NULL; off_t readcounter= 0,writecounter= 0; int num_sessions= 0, num_tracks= 0; struct burn_session **sessions; struct burn_track **tracks; enum burn_disc_status s; IsoImage *image= NULL; int profile_number; char *profile_name= NULL, *reasons= NULL; IsoBoot *bootcat_node; Xorriso_alloc_meM(sfe, char, 5 * SfileadrL); Xorriso_alloc_meM(xorriso_id, char, 256); Xorriso_alloc_meM(profile_name, char, 80); Xorriso_alloc_meM(reasons, char, BURN_REASONS_LEN); ret= Xorriso_finish_hl_update(xorriso, 0); if(ret <= 0) goto ex; ret= Xorriso_set_all_file_dates(xorriso, 1); if(ret <= 0) goto ex; out_cs= xorriso->out_charset; if(out_cs == NULL) Xorriso_get_local_charset(xorriso, &out_cs, 0); ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to write", 2); if(ret<=0) goto ex; if(!(flag & 1)) { ret= Xorriso_auto_format(xorriso, 0); if(ret <=0 ) {ret= 0; goto ex;} } is_bdr_pow= burn_drive_get_bd_r_pow(drive); if(is_bdr_pow) { sprintf(xorriso->info_text, "May not write to Pseudo Overwrite formatted BD-R medium"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } s= isoburn_disc_get_status(drive); if (xorriso->do_hfsplus && ( (xorriso->grow_blindly_msc2 >= 0 && xorriso->out_drive_handle != xorriso->in_drive_handle) || (xorriso->out_drive_handle == xorriso->in_drive_handle && s != BURN_DISC_BLANK) )) { sprintf(xorriso->info_text, "May not grow ISO image while -hfsplus is enabled"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } if(xorriso->out_drive_handle == xorriso->in_drive_handle) { if(abs(xorriso->displacement_sign) == 1 && xorriso->displacement != 0 && s != BURN_DISC_BLANK) { sprintf(xorriso->info_text, "May not grow ISO image while -displacement is non-zero"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } source_drive= drive; } else { if(xorriso->in_drive_handle == NULL) { source_drive= drive; } else { ret= Xorriso_get_drive_handles(xorriso, &source_dinfo, &source_drive, "on attempt to get source for write", 0); if(ret<=0) goto ex; } if(s!=BURN_DISC_BLANK) { s= burn_disc_get_status(drive); if(s!=BURN_DISC_BLANK) sprintf(xorriso->info_text, "-indev differs from -outdev and -outdev media is not blank"); else sprintf(xorriso->info_text, "-indev differs from -outdev and -outdev media holds non-zero data"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } } ret= Xorriso_get_profile(xorriso, &profile_number, profile_name, 2); if(ret == 2) pacifier_speed= 1; else if(ret == 3) pacifier_speed= 2; ret= Xorriso_check_multi(xorriso, drive, 0); if(ret<=0) goto ex; ret= isoburn_igopt_new(&sopts, 0); if(ret<=0) { Xorriso_process_msg_queues(xorriso, 0); goto ex; } xorriso->alignment= 0; image= isoburn_get_attached_image(source_drive); if(image != NULL) { iso_image_set_application_id(image, xorriso->application_id); iso_image_set_publisher_id(image, xorriso->publisher); iso_image_set_system_id(image, xorriso->system_id); iso_image_set_volset_id(image, xorriso->volset_id); iso_image_set_copyright_file_id(image, xorriso->copyright_file); iso_image_set_biblio_file_id(image, xorriso->biblio_file); iso_image_set_abstract_file_id(image, xorriso->abstract_file); Xorriso_write_application_use(xorriso, image, 0); Xorriso_process_msg_queues(xorriso,0); } if((xorriso->do_aaip & 256) && out_cs != NULL) { static char *names = "isofs.cs"; size_t value_lengths[1]; value_lengths[0]= strlen(out_cs); ret= Xorriso_setfattr(xorriso, NULL, "/", (size_t) 1, &names, value_lengths, &out_cs, 2 | 8); if(ret<=0) goto ex; } if(iso_image_was_blind_attrs(image, 0)) Xorriso_msgs_submit(xorriso, 0, "Some file xattr namespace could not be explored", 0, "WARNING", 0); if(image!=NULL && 12+strlen(Xorriso_timestamP)<80) { strcpy(xorriso_id, xorriso->preparer_id); img_id= (char *) iso_image_get_data_preparer_id(image); if(img_id!=NULL) { for(i= strlen(img_id)-1; i>=0 && img_id[i]==' '; i--); if(i>0) { sprintf(xorriso->info_text, "Overwrote previous preparer id '%s'", img_id); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); } } iso_image_set_data_preparer_id(image, xorriso_id); } ret= Xorriso_set_system_area(xorriso, source_drive, drive, image, sopts, 0); if(ret <= 0) goto ex; /* Activate, adjust or discard boot image */ if(image!=NULL) { if(xorriso->boot_image_bin_path[0]) { ret= Xorriso_attach_boot_image(xorriso, xorriso->boot_count == 0); if(ret <= 0) goto ex; freshly_bootable= 1; } is_bootable= iso_image_get_boot_image(image, NULL, NULL, &bootcat_node); } if(image!=NULL && !(flag&1)) { if(xorriso->boot_count > 0 || freshly_bootable) { /* Eventually rename boot catalog node to changed boot_image_cat_path */ if(is_bootable > 0) { ret= Xorriso_path_from_node(xorriso, (IsoNode *) bootcat_node, sfe, 0); if(ret > 0) { if(strcmp(sfe, xorriso->boot_image_cat_path) != 0) { ret= Xorriso_rename(xorriso, NULL, sfe, xorriso->boot_image_cat_path, 1); if(ret <= 0) goto ex; } } } hide_attr= !!(xorriso->boot_image_cat_hidden); if(xorriso->boot_image_cat_hidden & 1) hide_attr|= LIBISO_HIDE_ON_RR; if(xorriso->boot_image_cat_hidden & 2) hide_attr|= LIBISO_HIDE_ON_JOLIET; if(xorriso->boot_image_cat_hidden & 4) hide_attr|= LIBISO_HIDE_ON_HFSPLUS; iso_image_set_boot_catalog_hidden(image, hide_attr); } else if(xorriso->patch_isolinux_image & 1) { if(is_bootable == 1) { /* will imply isoburn_igopt_allow_full_ascii */ sprintf(xorriso->info_text, "Patching boot info table"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); ret= Xorriso_path_from_lba(xorriso, NULL, (off_t) xorriso->loaded_boot_bin_lba, sfe, 1); if(ret < 0) goto ex; if(ret == 0) { sprintf(xorriso->info_text, "Cannot patch boot image: no file found for its LBA."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); sprintf(xorriso->info_text, "Probably the loaded boot image file was deleted in this session."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); sprintf(xorriso->info_text, "Use -boot_image \"any\" \"discard\" or set new boot image"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); goto ex; } ret= Xorriso_set_isolinux_options(xorriso, image, 0); if(ret <= 0) goto ex; } else if(!freshly_bootable) { sprintf(xorriso->info_text, "Could not find any boot image for -boot_image patching"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); } } else if(xorriso->keep_boot_image && is_bootable == 1) { /* will imply isoburn_igopt_allow_full_ascii */ sprintf(xorriso->info_text, "Keeping boot image unchanged"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); } else if(is_bootable == 1) { iso_image_remove_boot_image(image); sprintf(xorriso->info_text, "Discarded boot image from old session"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); } /* hardcoded and regardless whether a catalog will get written */ iso_image_set_boot_catalog_weight(image, 1000000000); } if((xorriso->do_aaip & 16) || !(xorriso->ino_behavior & 2)) { /* Overwrite isofs.st of root node by xorriso->isofs_st_out */ char *name= "isofs.st"; char timestamp[16], *value= timestamp; size_t value_length; sprintf(timestamp, "%.f", (double) xorriso->isofs_st_out); value_length= strlen(timestamp); Xorriso_setfattr(xorriso, NULL, "/", (size_t) 1, &name, &value_length, &value, 2 | 8); } Xorriso_warn_efi_boot_dir(xorriso, image, 0); ret= Xorriso_make_iso_write_opts(xorriso, image, sopts, flag & 1); if(ret <= 0) goto ex; /* >>> omit iso_image_update_sizes if the image was filled up very quickly */; ret= iso_image_update_sizes(image); if(ret < 0) { Xorriso_process_msg_queues(xorriso, 0); if(ret<0) { Xorriso_report_iso_error(xorriso, "", ret, "Error when updating file sizes", 0, "FAILURE", 1); } ret= Xorriso_eval_problem_status(xorriso, 1, 0); if(ret<0) {ret= 0; goto ex;} } Xorriso_set_abort_severity(xorriso, 1); if (xorriso->grow_blindly_msc2 >= 0 && xorriso->out_drive_handle != xorriso->in_drive_handle) { ret= isoburn_prepare_blind_grow_v2(source_drive, &disc, sopts, drive, xorriso->grow_blindly_msc2); if(ret>0) { /* Allow the consumer of output to access the input drive */ source_drive= NULL; ret= Xorriso_give_up_drive(xorriso, 1|8); if(ret<=0) goto ex; } } else if(xorriso->out_drive_handle == xorriso->in_drive_handle || xorriso->in_drive_handle == NULL) { ret= isoburn_prepare_disc(source_drive, &disc, sopts); } else { ret= isoburn_prepare_new_image(source_drive, &disc, sopts, drive); } if(ret <= 0) { Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text,"Failed to prepare session write run"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0); if(ret<=0) goto cancel_iso; isoburn_igopt_get_effective_lba_v2(sopts, &(xorriso->session_lba)); if(xorriso->do_stream_recording == 2) { ret= isoburn_igopt_get_data_start_v2(sopts, &data_lba); if(ret > 0 && data_lba >= 16 && data_lba < (int) 0x7fffffff) burn_write_opts_set_stream_recording(burn_options, (int) data_lba); } ret= Xorriso_sanitize_image_size(xorriso, drive, disc, burn_options, flag&1); if(ret<=0 || (flag&1)) { Xorriso_process_msg_queues(xorriso,0); if(flag&1) /* set queue severity to FAILURE */ Xorriso_set_image_severities(xorriso, 2); if(flag&1) /* reset queue severity */ Xorriso_set_image_severities(xorriso, 0); if(flag & 1) xorriso->print_size_counter++; goto cancel_iso; } ret= Xorriso_may_burn(xorriso, 0); if(ret <= 0) goto cancel_iso; role= burn_drive_get_drive_role(drive); /* Important: do not return until burn_is_aborting() was checked */ signal_mode= 1; if(role == 1) signal_mode|= 2; Xorriso_set_signal_handling(xorriso, signal_mode); /* De-activate eventual target file truncation in dummy mode */ ret= isoburn_set_truncate(drive, (!xorriso->do_dummy) | 2 | 4); if(ret < 0) goto cancel_iso; xorriso->run_state= 1; /* Indicate that burning has started */ isoburn_disc_write(burn_options, disc); burn_write_opts_free(burn_options); burn_options= NULL; ret= Xorriso_pacifier_loop(xorriso, drive, pacifier_speed << 4); if(burn_is_aborting(0)) Xorriso_abort(xorriso, 0); /* Never comes back */ Xorriso_set_signal_handling(xorriso, 0); if(ret<=0) goto ex; if(!isoburn_drive_wrote_well(drive)) { isoburn_cancel_prepared_write(source_drive, drive, 0); Xorriso_process_msg_queues(xorriso,0); if(xorriso->auto_close && xorriso->do_close == 0) { if(burn_drive_was_feat21_failure(drive)) { sprintf(xorriso->info_text, "libburn indicates failure with writing DVD-RW to appendable state."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); /* Urge caller to call Xorriso_retry_write_session() */ ret= 2; goto ex; } } sprintf(xorriso->info_text, "libburn indicates failure with writing."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } Xorriso_process_msg_queues(xorriso,0); sessions= burn_disc_get_sessions(disc, &num_sessions); if(num_sessions>0) { tracks= burn_session_get_tracks(sessions[0], &num_tracks); if(tracks!=NULL && num_tracks>0) { burn_track_get_counters(tracks[0],&readcounter,&writecounter); xorriso->session_blocks= writecounter / 2048.0; sprintf(xorriso->info_text, "ISO image produced: %.f sectors\nWritten to medium : %.f sectors at LBA %.f\n", ((double) readcounter) / 2048.0, (double) xorriso->session_blocks, (double) xorriso->session_lba); Xorriso_info(xorriso, 0); } } ret= isoburn_activate_session(drive); Xorriso_process_msg_queues(xorriso,0); if(ret<=0) { sprintf(xorriso->info_text, "Could not write new set of volume descriptors"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); goto ex; } /* Done early to free any reference to the libisofs resources via disc */ if(disc!=NULL) burn_disc_free(disc); disc= NULL; /* To wait for the end of the libisofs threads and their messages. */ isoburn_sync_after_write(source_drive, drive, 0); Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text, "Writing to %s completed successfully.\n\n", Text_shellsafe(xorriso->outdev,sfe,0)); Xorriso_info(xorriso, 0); xorriso->write_session_counter++; ret= 1; ex:; xorriso->run_state= 0; /* Indicate that burning has ended */ Xorriso_set_abort_severity(xorriso, 0); if(ret<=0) { /* >>> ??? revive discarded boot image */; /* suppress automatic -commit at program end */ xorriso->volset_change_pending= 3; } if(disc!=NULL) burn_disc_free(disc); if(image != NULL) iso_image_unref(image); isoburn_igopt_destroy(&sopts, 0); if(burn_options != NULL) burn_write_opts_free(burn_options); Xorriso_process_msg_queues(xorriso,0); Xorriso_append_scdbackup_record(xorriso, 0); Xorriso_free_meM(sfe); Xorriso_free_meM(xorriso_id); Xorriso_free_meM(profile_name); Xorriso_free_meM(reasons); return(ret); cancel_iso:; isoburn_cancel_prepared_write(source_drive, drive, 0); goto ex; } int Xorriso_check_burn_abort(struct XorrisO *xorriso, int flag) { int ret; struct burn_drive_info *dinfo; struct burn_drive *drive; if(burn_is_aborting(0)) return(2); if(xorriso->run_state!=1) return(0); ret= Xorriso_eval_problem_status(xorriso, 1, 1); if(ret>=0) return(0); sprintf(xorriso->info_text, "-abort_on '%s' encountered '%s' during image writing", xorriso->abort_on_text, xorriso->problem_status_text); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, xorriso->problem_status_text, 0); ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to abort burn run", 2); if(ret<=0) return(0); burn_drive_cancel(drive); sprintf(xorriso->info_text, "libburn has now been urged to cancel its operation"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); return(1); } /* This loop watches burn runs until they end. It issues pacifying update messages to the user. @param flag bit0-3 = emulation mode 0= xorriso 1= mkisofs 2= cdrecord bit4= report speed in CD units bit5= report speed in BD units */ int Xorriso_pacifier_loop(struct XorrisO *xorriso, struct burn_drive *drive, int flag) { int ret, size, free_bytes, i, aborting= 0, emul, buffer_fill= 50; int iso_wait_counter= 0, iso_cancel_limit= 5; struct burn_progress_v2 progress; off_t last_sector; char *status_text, date_text[80], *speed_unit, mem_text[8]; enum burn_drive_status drive_status; double start_time, current_time, last_time, base_time= 0.0, base_count= 0.0; double next_base_time= 0.0, next_base_count= 0.0, first_base_time= 0.0; double first_base_count= 0.0, norm= 0.0, now_time, fract_offset= 0.0; double measured_speed, speed_factor= 1385000, quot, speed_min_time; double tdiff, now_fract; time_t time_prediction; IsoImage *image= NULL; image= isoburn_get_attached_image(drive); start_time= Sfile_microtime(0); while(burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING) usleep(100002); emul= flag&15; if(emul==0) emul= xorriso->pacifier_style; fract_offset= 1.0 / 3.0 * (double) emul - ((int) (1.0 / 3.0 * (double) emul)); speed_min_time= 0.2 * xorriso->pacifier_interval; speed_unit= "D"; if(flag&16) { speed_factor= 150.0*1024; speed_unit= "C"; } else if(flag & 32) { speed_factor= 4495625; speed_unit= "B"; } progress.sector= 0; current_time= Sfile_microtime(0); measured_speed= 0.0; while(1) { last_time= current_time; last_sector= progress.sector; drive_status= burn_drive_get_status_v2(drive, &progress); if(drive_status == BURN_DRIVE_IDLE) { /* To avoid a race condition between burn_source and libisofs writer thread: Wait for ISO generator thread to have finished. After some seconds kick it by isoburn_cancel_prepared_write() which waits for the write thread to end. */ if(image == NULL) break; if(!iso_image_generator_is_running(image)) break; iso_wait_counter++; if(iso_wait_counter > iso_cancel_limit) { isoburn_cancel_prepared_write(drive, NULL, 0); break; } } current_time= Sfile_microtime(0); if(drive_status == BURN_DRIVE_WRITING && progress.sectors > 0) { if(current_time-last_time > speed_min_time) measured_speed= (progress.sector - last_sector) * 2048.0 / (current_time - last_time); buffer_fill= 50; if(progress.buffer_capacity>0) buffer_fill= (double) (progress.buffer_capacity - progress.buffer_available) * 100.0 / (double) progress.buffer_capacity; if(emul==2) { if(progress.sector<=progress.sectors) sprintf(xorriso->info_text, "%4.f of %4.f MB written", (double) (progress.sector / 512), (double) ( progress.sectors / 512)); else sprintf(xorriso->info_text, "%4.f MB written", (double) (progress.sector / 512)); if(xorriso->pacifier_fifo!=NULL) ret= burn_fifo_inquire_status(xorriso->pacifier_fifo, &size, &free_bytes, &status_text); else ret= isoburn_get_fifo_status(drive, &size, &free_bytes, &status_text); if(ret>0 ) sprintf(xorriso->info_text+strlen(xorriso->info_text), " (fifo %2d%%)", (int) (100.0-100.0*((double) free_bytes)/(double) size)); sprintf(xorriso->info_text+strlen(xorriso->info_text), " [buf %3d%%]", buffer_fill); if(current_time-last_time > speed_min_time) sprintf(xorriso->info_text+strlen(xorriso->info_text), " %4.1fx.", measured_speed/speed_factor); } else if(emul == 1 && progress.sectors > 0 && progress.sector <= progress.sectors) { /* "37.87% done, estimate finish Tue Jul 15 18:55:07 2008" */ quot= ((double) progress.sector) / ((double) progress.sectors); sprintf(xorriso->info_text, " %2.2f%% done", quot*100.0); if(current_time - start_time >= 2 && quot > 0.0 && (quot >= 0.02 || progress.sector >= 5*1024)) { if(base_time == 0.0 && progress.sector >= 16*1024) { first_base_time= base_time= next_base_time= current_time; first_base_count= next_base_count= progress.sector; } else if(next_base_time > 0 && current_time - next_base_time >= 10) { base_time= next_base_time; base_count= next_base_count; next_base_time= current_time; next_base_count= progress.sector; } if(first_base_time > 0 && current_time - first_base_time >= 10 && progress.sectors > first_base_count && progress.sector > first_base_count) { norm= (1.0 - quot); if(norm < 0.0001) norm= 0.0001; quot= ((double) progress.sector - first_base_count) / ((double) progress.sectors - first_base_count); time_prediction= norm * (1.0 - quot) / quot * (current_time - first_base_time); } else { time_prediction= (1.0 - quot) / quot * (current_time - start_time); norm= 1.0; } if(base_time > 0 && current_time - base_time >= 10 && progress.sectors > base_count) { quot= ((double) progress.sector - base_count) / ((double) progress.sectors - base_count); time_prediction+= (1.0 - quot) / quot * (current_time - base_time); norm+= 1.0; } time_prediction/= norm; if(time_prediction < 30*86400 && time_prediction > 0) { time_prediction+= current_time + 1; Ftimetxt(time_prediction, date_text, 4); sprintf(xorriso->info_text+strlen(xorriso->info_text), ", estimate finish %s", date_text); } } } else { if(progress.sector<=progress.sectors) { if(progress.sectors <= 0) strcpy(mem_text, " 99.9"); else sprintf(mem_text, "%5.1f", 100.0 * ((double) progress.sector) / ((double) progress.sectors)); mem_text[5]= 0; sprintf(xorriso->info_text, "Writing: %10.fs %s%% ", (double) progress.sector, mem_text); } else { Sfile_scale(2048.0 * (double) progress.sector, mem_text, 5, 1e4, 1); sprintf(xorriso->info_text, "Writing: %10.fs %s ", (double) progress.sector, mem_text); } ret= isoburn_get_fifo_status(drive, &size, &free_bytes, &status_text); if(ret>0 ) sprintf(xorriso->info_text+strlen(xorriso->info_text), " fifo %3d%% buf %3d%%", (int) (100.0-100.0*((double) free_bytes)/(double) size), buffer_fill); if(current_time - last_time > speed_min_time) sprintf(xorriso->info_text+strlen(xorriso->info_text), " %5.1fx%s ", measured_speed/speed_factor, speed_unit); } } else if(drive_status == BURN_DRIVE_CLOSING_SESSION || drive_status == BURN_DRIVE_CLOSING_TRACK) sprintf(xorriso->info_text, "Closing track/session. Working since %.f seconds", current_time-start_time); else if(drive_status == BURN_DRIVE_FORMATTING) sprintf(xorriso->info_text, "Formatting. Working since %.f seconds", current_time-start_time); else sprintf(xorriso->info_text, "Thank you for being patient. Working since %.f seconds.", current_time-start_time); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); for(i= 0; i < 20; i++) { /* 10 usleeps more than supposed to be needed */ Xorriso_process_msg_queues(xorriso, 0); if(aborting<=0) aborting= Xorriso_check_burn_abort(xorriso, 0); usleep((unsigned long) (100000.0 * xorriso->pacifier_interval)); now_time= Sfile_microtime(0); tdiff= ((off_t)(now_time / xorriso->pacifier_interval)) - (off_t)(current_time / xorriso->pacifier_interval); now_fract= (now_time / xorriso->pacifier_interval - (off_t)(now_time / xorriso->pacifier_interval)); if(tdiff < 1.0) continue; if(fract_offset <= 0.0) /* "xorriso" pacifier shall not wait for slot */ break; if((now_fract >= fract_offset && now_fract < fract_offset + 0.3) || tdiff >= 2.0) break; } } iso_image_unref(image); return(1); } /* @param flag bit0= fast bit1= deformat bit2= do not re-aquire drive @return 0=failure, did not touch medium , -1=failure, altered medium 1=success, altered medium , 2=success, did not touch medium */ int Xorriso_blank_media(struct XorrisO *xorriso, int flag) { int ret, do_deformat= 0, signal_mode, using_immed; struct burn_drive_info *dinfo; struct burn_drive *drive; enum burn_disc_status disc_state; struct burn_progress_v2 p; double percent = 1.0; int current_profile; char current_profile_name[80]; time_t start_time; char mode_names[4][80]= {"all", "fast", "deformat", "deformat_quickest"}; char progress_text[40]; ret= Xorriso_may_burn(xorriso, 0); if(ret <= 0) return(0); ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to -blank", 2); if(ret<=0) return(0); burn_disc_get_profile(drive, ¤t_profile, current_profile_name); disc_state = isoburn_disc_get_status(drive); if(current_profile == 0x13) { /* overwritable DVD-RW */ /* Depending on flag bit1 formatted DVD-RW will get blanked to sequential state or pseudo blanked by invalidating an eventual ISO image. */ if(flag&2) do_deformat= 1; } else if(current_profile == 0x14) { /* sequential DVD-RW */ if((flag&1) && !(flag&2)) { sprintf(xorriso->info_text, "-blank: DVD-RW present. Mode 'fast' defaulted to mode 'all'."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); sprintf(xorriso->info_text, "Mode 'deformat_quickest' produces single-session-only media."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); flag&= ~1; } } if(disc_state == BURN_DISC_BLANK) { if(!do_deformat) { sprintf(xorriso->info_text, "Blank medium detected. Will leave it untouched"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); return 2; } } else if(disc_state==BURN_DISC_FULL || disc_state==BURN_DISC_APPENDABLE) { ; } else if(disc_state == BURN_DISC_EMPTY) { sprintf(xorriso->info_text,"No media detected in drive"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return 0; } else { sprintf(xorriso->info_text, "Unsuitable drive and media state"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return 0; } if(!isoburn_disc_erasable(drive)) { sprintf(xorriso->info_text, "Media is not of erasable type"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return 0; } if(xorriso->do_dummy) { sprintf(xorriso->info_text, "-dummy mode prevents blanking of medium in mode '%s'.", mode_names[flag&3]); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); return(1); } using_immed= burn_drive_get_immed(drive); sprintf(xorriso->info_text, "Beginning to blank medium in mode '%s'.\n", mode_names[flag&3]); Xorriso_info(xorriso,0); /* Important: do not return until burn_is_aborting() was checked */ signal_mode= 1; ret= burn_drive_get_drive_role(drive); if(ret == 1) signal_mode|= 2; Xorriso_set_signal_handling(xorriso, signal_mode); if(do_deformat) burn_disc_erase(drive, (flag&1)); else isoburn_disc_erase(drive, (flag&1)); start_time= time(0); usleep(1000000); if(!using_immed) sprintf(progress_text, "synchronously since"); while (burn_drive_get_status_v2(drive, &p) != BURN_DRIVE_IDLE) { Xorriso_process_msg_queues(xorriso,0); if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */ percent = 1.0 + ((double) p.sector+1.0) / ((double) p.sectors) * 98.0; if(using_immed) sprintf(progress_text, "%.1f%% done in", percent); sprintf(xorriso->info_text, "Blanking ( %s %d seconds )", progress_text, (int) (time(0) - start_time)); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); usleep(1000000); } Xorriso_process_msg_queues(xorriso,0); if(burn_is_aborting(0)) Xorriso_abort(xorriso, 0); /* Never comes back */ Xorriso_set_signal_handling(xorriso, 0); if(burn_drive_wrote_well(drive)) { sprintf(xorriso->info_text, "Blanking done\n"); Xorriso_info(xorriso,0); } else { sprintf(xorriso->info_text, "Blanking failed."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); } if(!(flag & 4)) { ret= Xorriso_reaquire_outdev(xorriso, 2 + (xorriso->in_drive_handle == xorriso->out_drive_handle)); if(ret <= 0) return(-1); } return(1); } /* @param flag bit0= try to achieve faster formatting bit1= use parameter size (else use default size) bit2= do not re-aquire drive bit5= try to disable Defect Management bit7= by_index mode: bit8 to bit15 contain the index of the format to use. @return 0=failure, did not touch medium , -1=failure, altered medium 1=success, altered medium , 2=success, did not touch medium */ int Xorriso_format_media(struct XorrisO *xorriso, off_t in_size, int flag) { int ret, mode_flag= 0, index, status, num_formats, signal_mode, using_immed; unsigned dummy; struct burn_drive_info *dinfo; struct burn_drive *drive; struct burn_progress_v2 p; double percent = 1.0; int current_profile; char current_profile_name[80], progress_text[40]; off_t size= 0; time_t start_time; enum burn_disc_status disc_state; ret= Xorriso_may_burn(xorriso, 0); if(ret <= 0) return(0); ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to -format", 2); if(ret<=0) return(0); if(flag & 2) { mode_flag= 0; /* format to given size */ } else { mode_flag= 4; /* format to full size */ } if(flag & 32) mode_flag|= 32; /* try to disable Defect Management */ burn_disc_get_profile(drive, ¤t_profile, current_profile_name); if(flag&128) { /* by_index */ index= (flag>>8) & 0xff; ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats); if(ret<=0) num_formats= 0; if(ret<=0 || index<0 || index>=num_formats) { if(num_formats>0) sprintf(xorriso->info_text, "-format by_index_%d: format descriptors range from index 0 to %d", index, num_formats-1); else sprintf(xorriso->info_text, "-format by_index_%d: no format descriptors available", index); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } mode_flag|= (flag & 0xff80); if(flag&1) mode_flag|= (1<<6); } else if(current_profile == 0x12) { /* DVD+RAM */ if(!(flag & 2)) mode_flag= 6; /* format to default payload size */ if(flag&1) mode_flag|= (1<<6); } else if(current_profile == 0x13) { /* DVD-RW */ if(flag&1) { sprintf(xorriso->info_text, "Detected formatted DVD-RW. Thus omitting desired fast format run."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); return(2); } } else if(current_profile == 0x14) { /* DVD-RW sequential */ if(flag & 1) { size= 128*1024*1024; mode_flag= 1; /* format to size, then write size of zeros */ } else mode_flag= 4; } else if(current_profile == 0x1a) { /* DVD+RW */ if(flag&1) { sprintf(xorriso->info_text, "Detected DVD+RW. Thus omitting desired fast format run."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); return(2); } } else if(current_profile == 0x41) { /* BD-R SRM */ if(!(flag & 2)) mode_flag= 6; /* format to default payload size */ if(flag&1) mode_flag|= (1<<6); } else if(current_profile == 0x43) { /* BD-RE */ if(!(flag & (2 | 32))) mode_flag= 6; /* format to default payload size */ if(flag&1) mode_flag|= (1<<6); } else { sprintf(xorriso->info_text, "-format: Unsuitable media detected."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); sprintf(xorriso->info_text,"Media current: %s (%4.4xh)", current_profile_name, current_profile); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); return(0); } if(!(flag & 1)) mode_flag|= 16; /* enable re-formatting */ if(xorriso->do_dummy) { sprintf(xorriso->info_text, "-dummy mode prevents formatting of medium."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); return(1); } using_immed= burn_drive_get_immed(drive); sprintf(xorriso->info_text, "Beginning to format medium.\n"); Xorriso_info(xorriso, 0); if(flag & 2) size= in_size; /* Important: do not return until burn_is_aborting() was checked */ signal_mode= 1; ret= burn_drive_get_drive_role(drive); if(ret == 1) signal_mode|= 2; Xorriso_set_signal_handling(xorriso, signal_mode); burn_disc_format(drive, size, mode_flag); start_time= time(0); usleep(1000000); if(!using_immed) sprintf(progress_text, "synchronously since"); while (burn_drive_get_status_v2(drive, &p) != BURN_DRIVE_IDLE) { Xorriso_process_msg_queues(xorriso,0); if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */ percent = 1.0 + ((double) p.sector+1.0) / ((double) p.sectors) * 98.0; if(using_immed) sprintf(progress_text, "%.1f%% done in", percent); sprintf(xorriso->info_text, "Formatting ( %s %d seconds )", progress_text, (int) (time(0) - start_time)); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); usleep(1000000); } Xorriso_process_msg_queues(xorriso,0); if(burn_is_aborting(0)) Xorriso_abort(xorriso, 0); /* Never comes back */ Xorriso_set_signal_handling(xorriso, 0); if(burn_drive_wrote_well(drive)) { sprintf(xorriso->info_text, "Formatting done\n"); Xorriso_info(xorriso,0); } else { sprintf(xorriso->info_text, "libburn indicates failure with formatting."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(-1); } if(!(flag & 4)) { ret= Xorriso_reaquire_outdev(xorriso, 2 + (xorriso->in_drive_handle == xorriso->out_drive_handle)); if(ret <= 0) return(-1); } disc_state = isoburn_disc_get_status(drive); if(disc_state==BURN_DISC_FULL && !(flag&1)) { /* Blank because full format certification pattern might be non-zero */ ret= Xorriso_blank_media(xorriso, 1); if(ret <= 0) return(0); } return(1); } /* @param flag bit2= formatting rather than blanking @return 0=failure, did not touch medium , -1=failure, altered medium 1=success, altered medium , 2=success, did not touch medium */ int Xorriso_blank_as_needed(struct XorrisO *xorriso, int flag) { int ret, is_formatted= -1, status, num_formats, did_work= 0; struct burn_drive_info *dinfo; struct burn_drive *drive; enum burn_disc_status disc_state; unsigned dummy; int current_profile; char current_profile_name[80]; off_t size; ret= Xorriso_may_burn(xorriso, 0); if(ret <= 0) return(0); ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to blank or format", 2); if(ret<=0) return(0); burn_disc_get_profile(drive, ¤t_profile, current_profile_name); ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats); if(ret>0) { if(status==BURN_FORMAT_IS_FORMATTED) is_formatted= 1; else if(status == BURN_FORMAT_IS_UNFORMATTED) is_formatted= 0; } if(current_profile == 0x12 || current_profile == 0x43) { /* DVD+RAM , BD-RE */ if(is_formatted<0) { sprintf(xorriso->info_text, "-blank or -format: Unclear formatting status of %s", current_profile_name); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } if(!is_formatted) { ret= Xorriso_format_media(xorriso, (off_t) 0, (current_profile == 0x43)); if(ret <= 0) return(ret); did_work= (ret == 1); } } else if(current_profile == 0x14 && (flag&4)) { /* DVD-RW sequential */ ret= Xorriso_format_media(xorriso, (off_t) 0, 0); if(ret <= 0) return(ret); did_work= (ret == 1); } else if(current_profile == 0x41) { /* BD-R SRM */ if((flag & 4) && !is_formatted) { ret= Xorriso_format_media(xorriso, (off_t) 0, 1); if(ret <= 0) return(ret); did_work= (ret == 1); } } disc_state = isoburn_disc_get_status(drive); if(disc_state != BURN_DISC_BLANK && !(flag&4)) { ret= Xorriso_blank_media(xorriso, 1); return(ret); } if(did_work) return(1); sprintf(xorriso->info_text, "%s as_needed: no need for action detected", (flag&4) ? "-format" : "-blank"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); return(2); } int Xorriso_retry_burn_track(struct XorrisO *xorriso, off_t write_start_address, char *track_source, off_t tsize, int flag) { int ret, auto_close_mem, do_close_mem; if(xorriso->do_tao == 1) { Xorriso_msgs_submit(xorriso, 0, "There is no hope for a re-try with -close \"on\" as long as -write_type is \"tao\"", 0, "FAILURE", 0); return(0); } Xorriso_msgs_submit(xorriso, 0, "Re-trying with -close \"on\"", 0, "NOTE", 0); do_close_mem= xorriso->do_close; auto_close_mem= xorriso->auto_close; xorriso->do_close= 1; xorriso->auto_close= 0; ret= Xorriso_burn_track(xorriso, write_start_address, track_source, tsize, flag); xorriso->do_close= do_close_mem; xorriso->auto_close= auto_close_mem; return(ret); } /* @param write_start_address is valid if >=0 @param tsize is valid if >0 @param flag bit0= grow_overwriteable_iso bit1= do_isosize bit2= do_xa1 conversion @return <=0 error , 1= success 2= failure with DVD-RW, please call Xorriso_retry_burn_track() */ int Xorriso_burn_track(struct XorrisO *xorriso, off_t write_start_address, char *track_source, off_t tsize, int flag) { int ret, fd, profile_number, is_cd= 0, do_isosize, is_bd= 0, signal_mode; off_t dummy, nwa= -1, isosize= -1; struct burn_drive_info *dinfo; struct burn_drive *drive; struct burn_write_opts *burn_options= NULL; struct burn_disc *disc= NULL; struct burn_session *session= NULL; struct burn_track *track= NULL; struct stat stbuf; off_t fixed_size= 0; struct burn_source *data_src= NULL, *fifo_src= NULL; enum burn_disc_status disc_state; char *reasons= NULL, *profile_name= NULL; char *head_buffer= NULL; Xorriso_alloc_meM(reasons, char, BURN_REASONS_LEN); Xorriso_alloc_meM(profile_name, char, 80); Xorriso_alloc_meM(head_buffer, char, 64 * 1024); ret= Xorriso_may_burn(xorriso, 0); if(ret <= 0) {ret= 0; goto ex;} ret= Xorriso_auto_format(xorriso, 0); if(ret <=0 ) {ret= 0; goto ex;} do_isosize= !!(flag&2); ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to burn track", 2); if(ret<=0) {ret= 0; goto ex;} ret= Xorriso_check_multi(xorriso, drive, 1); if(ret<=0) goto ex; ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0); if(ret<=0) goto ex; disc= burn_disc_create(); session= burn_session_create(); ret= burn_disc_add_session(disc,session,BURN_POS_END); if(ret==0) { sprintf(xorriso->info_text, "Cannot add session object to disc object."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); goto ex; } track= burn_track_create(); if(track_source[0] == '-' && track_source[1] == 0) { fd= 0; } else { if(xorriso->fs >= 64) fd= burn_os_open_track_src(track_source, O_RDONLY, 0); else fd= open(track_source, O_RDONLY | O_BINARY); if(fd>=0) if(fstat(fd,&stbuf)!=-1) if((stbuf.st_mode&S_IFMT)==S_IFREG) fixed_size= stbuf.st_size; } if(fd>=0) data_src= burn_fd_source_new(fd, -1, fixed_size); if(data_src==NULL) { sprintf(xorriso->info_text, "Could not open data source "); Text_shellsafe(track_source, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); ret= 0; goto ex; } if((do_isosize || xorriso->fs != 0) && xorriso->fs < 64) xorriso->fs= 64; if(xorriso->fs > 0) { fifo_src= burn_fifo_source_new(data_src, 2048 + 8 * !!(flag & 4), xorriso->fs, 1); if(fifo_src == NULL) { sprintf(xorriso->info_text, "Could not create fifo object of %.f MB", ((double) xorriso->fs) / 1024.0 / 1024.0); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); ret= 0; goto ex; } } xorriso->pacifier_fifo= fifo_src; if(burn_track_set_source(track, fifo_src == NULL ? data_src : fifo_src) != BURN_SOURCE_OK) { sprintf(xorriso->info_text, "Cannot attach source object to track object"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); ret= 0; goto ex; } burn_track_set_cdxa_conv(track, !!(flag & 4)); burn_session_add_track(session, track, BURN_POS_END); burn_source_free(data_src); if(flag&1) /* consider overwriteables with ISO as appendable */ disc_state= isoburn_disc_get_status(drive); else /* handle overwriteables as always blank */ disc_state= burn_disc_get_status(drive); if(disc_state == BURN_DISC_BLANK || disc_state == BURN_DISC_APPENDABLE) { /* ok */; } else { if(disc_state == BURN_DISC_FULL) { sprintf(xorriso->info_text, "Closed media with data detected. Need blank or appendable media."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); if(burn_disc_erasable(drive)) { sprintf(xorriso->info_text, "Try -blank as_needed\n"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); } } else if(disc_state == BURN_DISC_EMPTY) { sprintf(xorriso->info_text, "No media detected in drive"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); } else { sprintf(xorriso->info_text, "Cannot recognize state of drive and media"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); } ret= 0; goto ex; } if(isoburn_needs_emulation(drive)) burn_write_opts_set_multi(burn_options, 0); if(tsize > 0) { fixed_size= tsize; burn_track_set_size(track, fixed_size); } if(do_isosize) { ret= burn_fifo_peek_data(xorriso->pacifier_fifo, head_buffer, 64*1024, 0); if(ret<=0) { Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text, "Cannot obtain first 64 kB from input stream."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } /* read isosize from head_buffer, not from medium */ ret= isoburn_read_iso_head_v2(drive, 0, &isosize, head_buffer, (1 << 13)); if(ret<=0) { Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text, "Option -isosize given but data stream seems not to be ISO 9660"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } sprintf(xorriso->info_text, "Size of ISO 9660 image: %.fs", (double) isosize); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); fixed_size= isosize * (off_t) 2048; burn_track_set_size(track, fixed_size); } ret= Xorriso_get_profile(xorriso, &profile_number, profile_name, 2); is_cd= (ret==2); is_bd= (ret == 3); if(isoburn_needs_emulation(drive)) { if(flag&1) { ret= isoburn_disc_track_lba_nwa_v2(drive, burn_options, 0, &dummy, &nwa); Xorriso_process_msg_queues(xorriso,0); if(ret<=0) { sprintf(xorriso->info_text, "Cannot obtain next writeable address of emulated multi-session media\n"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } if(nwa == 32 && disc_state != BURN_DISC_APPENDABLE) nwa= 0; /* No automatic toc emulation. Formatter might not be aware. */ } else { nwa= 0; if (disc_state == BURN_DISC_APPENDABLE) { ret= isoburn_disc_track_lba_nwa_v2(drive, burn_options, 0, &dummy, &nwa); Xorriso_process_msg_queues(xorriso,0); if(ret<=0) { sprintf(xorriso->info_text, "Cannot obtain next writeable address of emulated appendable media\n"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } } } burn_write_opts_set_start_byte(burn_options, nwa * (off_t) 2048); } if(write_start_address>=0) { nwa= write_start_address / (off_t) 2048; if(nwa * (off_t) 2048 < write_start_address ) nwa++; burn_write_opts_set_start_byte(burn_options, nwa * (off_t) 2048); } if(xorriso->do_tao) { if (xorriso->do_tao > 0) burn_write_opts_set_write_type(burn_options, BURN_WRITE_TAO, BURN_BLOCK_MODE1); else burn_write_opts_set_write_type(burn_options, BURN_WRITE_SAO, BURN_BLOCK_SAO); ret = burn_precheck_write(burn_options, disc, reasons, 0); if(ret<=0) { sprintf(xorriso->info_text, "Cannot set write type %s for this medium.\n", xorriso->do_tao > 0 ? "TAO" : "SAO"); sprintf(xorriso->info_text+strlen(xorriso->info_text), "Reasons given:\n%s", reasons); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } sprintf(xorriso->info_text, "Explicitly chosen write type: %s", xorriso->do_tao > 0 ? "TAO" : "SAO"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); } else { if(burn_write_opts_auto_write_type(burn_options, disc, reasons, 0) == BURN_WRITE_NONE) { sprintf(xorriso->info_text, "Failed to find a suitable write mode with this media.\n"); sprintf(xorriso->info_text+strlen(xorriso->info_text), "Reasons given:\n%s", reasons); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } } ret= Xorriso_sanitize_image_size(xorriso, drive, disc, burn_options, 2 | 4); if(ret<=0) goto ex; sprintf(xorriso->info_text, "Beginning to write data track.\n"); Xorriso_info(xorriso,0); /* Important: do not return until burn_is_aborting() was checked */ signal_mode= 1; ret= burn_drive_get_drive_role(drive); if(ret == 1) signal_mode|= 2; Xorriso_set_signal_handling(xorriso, signal_mode); xorriso->run_state= 1; /* Indicate that burning has started */ burn_disc_write(burn_options, disc); ret= Xorriso_pacifier_loop(xorriso, drive, 2 | (is_cd << 4) | (is_bd << 5)); if(burn_is_aborting(0)) Xorriso_abort(xorriso, 0); /* Never comes back */ Xorriso_set_signal_handling(xorriso, 0); if(ret<=0) goto ex; if(!burn_drive_wrote_well(drive)) { Xorriso_process_msg_queues(xorriso,0); if(xorriso->auto_close && xorriso->do_close == 0) { if(burn_drive_was_feat21_failure(drive)) { sprintf(xorriso->info_text, "libburn indicates failure with writing DVD-RW to appendable state."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); /* Urge caller to call Xorriso_retry_burn_rack() */ ret= 2; goto ex; } } sprintf(xorriso->info_text, "libburn indicates failure with writing."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } if(flag & 1) { ret= Xorriso_update_iso_lba0(xorriso, nwa, isosize, head_buffer, NULL, flag & 2); if(ret <= 0) goto ex; } sprintf(xorriso->info_text, "Writing to "); Text_shellsafe(xorriso->outdev, xorriso->info_text, 1); strcat(xorriso->info_text, " completed successfully.\n\n"); Xorriso_info(xorriso, 0); ret= 1; ex:; Xorriso_process_msg_queues(xorriso,0); if(disc!=NULL) burn_disc_free(disc); if(session != NULL) burn_session_free(session); if(track != NULL) burn_track_free(track); if(burn_options != NULL) burn_write_opts_free(burn_options); if(xorriso->pacifier_fifo!=NULL) burn_source_free(xorriso->pacifier_fifo); xorriso->pacifier_fifo= NULL; xorriso->run_state= 0; /* Indicate that burning has ended */ Xorriso_free_meM(reasons); Xorriso_free_meM(profile_name); Xorriso_free_meM(head_buffer); return(ret); } int Xorriso_relax_compliance(struct XorrisO *xorriso, char *mode, int flag) { char *npt, *cpt; int l, was, value, ret, endl; struct isoburn_imgen_opts *opts= NULL; char *msg= NULL; char submode[41], *endpt; off_t limit; was= xorriso->relax_compliance; npt= cpt= mode; for(; npt!=NULL; cpt= npt+1) { npt= strchr(cpt,':'); if(npt==NULL) l= strlen(cpt); else l= npt-cpt; if(l == 0) continue; if((l == 6 && strncmp(cpt, "strict", l) == 0) || (l == 5 && strncmp(cpt, "clear", l) == 0)) { xorriso->relax_compliance= 0; } else if(l == 7 && strncmp(cpt, "default", l) == 0) { xorriso->relax_compliance= Xorriso_relax_compliance_defaulT; } else if((l == 18 && strncmp(cpt, "untranslated_names", l) == 0) || (l == 21 && strncmp(cpt, "untranslated_names_on", l) == 0) ) { xorriso->untranslated_name_len = -1; } else if((l == 22 && strncmp(cpt, "untranslated_names_off", l) == 0)) { xorriso->untranslated_name_len = 0; } else if((l >= 22 && strncmp(cpt, "untranslated_name_len=", 22) == 0)) { value= -1; sscanf(cpt + 22, "%d", &value); /* Let libisoburn check the value */ ret= isoburn_igopt_new(&opts, 0); if(ret != 1) return(-1); ret= isoburn_igopt_set_untranslated_name_len(opts, value); isoburn_igopt_destroy(&opts, 0); if(ret <= 0) { /* Not a tasty value */ xorriso->relax_compliance= was; return(0); } xorriso->untranslated_name_len = value; } else if((l == 16 && strncmp(cpt, "allow_dir_id_ext", l) == 0) || (l == 19 && strncmp(cpt, "allow_dir_id_ext_on", l) == 0) ) { xorriso->relax_compliance|= isoburn_igopt_allow_dir_id_ext; xorriso->allow_dir_id_ext_dflt= 0; } else if((l == 20 && strncmp(cpt, "allow_dir_id_ext_off", l) == 0)) { xorriso->relax_compliance&= ~isoburn_igopt_allow_dir_id_ext; xorriso->allow_dir_id_ext_dflt= 0; } else if((l == 12 && strncmp(cpt, "omit_version", l) == 0) || (l == 15 && strncmp(cpt, "omit_version_on", l) == 0) ) { xorriso->relax_compliance|= isoburn_igopt_omit_version_numbers; } else if((l == 16 && strncmp(cpt, "omit_version_off", l) == 0)) { xorriso->relax_compliance&= ~isoburn_igopt_omit_version_numbers; } else if((l == 16 && strncmp(cpt, "only_iso_version", l) == 0) || (l == 19 && strncmp(cpt, "only_iso_version_on", l) == 0) ) { xorriso->relax_compliance|= isoburn_igopt_only_iso_versions; } else if((l == 20 && strncmp(cpt, "only_iso_version_off", l) == 0)) { xorriso->relax_compliance&= ~isoburn_igopt_only_iso_versions; } else if((l == 10 && strncmp(cpt, "deep_paths", l) == 0) || (l == 13 && strncmp(cpt, "deep_paths_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_allow_deep_paths; } else if(l == 14 && strncmp(cpt, "deep_paths_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_allow_deep_paths; } else if((l == 10 && strncmp(cpt, "long_paths", l) == 0) || (l == 13 && strncmp(cpt, "long_paths_on", l) == 0) ) { xorriso->relax_compliance|= isoburn_igopt_allow_longer_paths; } else if(l == 14 && strncmp(cpt, "long_paths_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_allow_longer_paths; } else if((l == 10 && strncmp(cpt, "long_names", l) == 0) || (l == 13 && strncmp(cpt, "long_names_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_max_37_char_filenames; } else if(l == 14 && strncmp(cpt, "long_names_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_max_37_char_filenames; } else if((l == 13 && strncmp(cpt, "no_force_dots", l) == 0) || (l == 16 && strncmp(cpt, "no_force_dots_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_no_force_dots; } else if(l == 17 && strncmp(cpt, "no_force_dots_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_no_force_dots; } else if((l == 15 && strncmp(cpt, "no_j_force_dots", l) == 0) || (l == 18 && strncmp(cpt, "no_j_force_dots_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_no_j_force_dots; } else if(l == 19 && strncmp(cpt, "no_j_force_dots_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_no_j_force_dots; } else if((l == 9 && strncmp(cpt, "lowercase", l) == 0) || (l == 12 && strncmp(cpt, "lowercase_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_allow_lowercase; } else if(l == 13 && strncmp(cpt, "lowercase_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_allow_lowercase; } else if((l == 10 && strncmp(cpt, "full_ascii", l) == 0) || (l == 13 && strncmp(cpt, "full_ascii_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_allow_full_ascii; } else if(l == 14 && strncmp(cpt, "full_ascii_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_allow_full_ascii; } else if((l == 10 && strncmp(cpt, "7bit_ascii", l) == 0) || (l == 13 && strncmp(cpt, "7bit_ascii_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_allow_7bit_ascii; } else if(l == 14 && strncmp(cpt, "7bit_ascii_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_allow_7bit_ascii; } else if((l == 17 && strncmp(cpt, "joliet_long_paths", l) == 0) || (l == 20 && strncmp(cpt, "joliet_long_paths_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_joliet_longer_paths; } else if(l == 21 && strncmp(cpt, "joliet_long_paths_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_joliet_longer_paths; } else if((l == 17 && strncmp(cpt, "joliet_long_names", l) == 0) || (l == 20 && strncmp(cpt, "joliet_long_names_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_joliet_long_names; } else if(l == 21 && strncmp(cpt, "joliet_long_names_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_joliet_long_names; } else if((l == 12 && strncmp(cpt, "joliet_utf16", l) == 0) || (l == 15 && strncmp(cpt, "joliet_utf16_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_joliet_utf16; } else if(l == 16 && strncmp(cpt, "joliet_utf16_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_joliet_utf16; } else if((l == 10 && strncmp(cpt, "always_gmt", l) == 0) || (l == 13 && strncmp(cpt, "always_gmt_on", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_always_gmt; } else if(l == 14 && strncmp(cpt, "always_gmt_off", l) == 0) { xorriso->relax_compliance&= ~isoburn_igopt_always_gmt; } else if((l == 9 && strncmp(cpt, "rec_mtime", l) == 0) || (l == 12 && strncmp(cpt, "rec_mtime_on", l) == 0)) { xorriso->relax_compliance|= (isoburn_igopt_dir_rec_mtime | isoburn_igopt_joliet_rec_mtime | isoburn_igopt_iso1999_rec_mtime); } else if(l == 13 && strncmp(cpt, "rec_mtime_off", l) == 0) { xorriso->relax_compliance&= ~(isoburn_igopt_dir_rec_mtime | isoburn_igopt_joliet_rec_mtime | isoburn_igopt_iso1999_rec_mtime); } else if((l == 6 && strncmp(cpt, "old_rr", l) == 0) || (l == 9 && strncmp(cpt, "old_rr_on", l) == 0) || (l == 10 && strncmp(cpt, "new_rr_off", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_rrip_version_1_10 | isoburn_igopt_aaip_susp_1_10; } else if((l == 10 && strncmp(cpt, "old_rr_off", l) == 0) || (l == 9 && strncmp(cpt, "new_rr_on", l) == 0) || (l == 6 && strncmp(cpt, "new_rr", l) == 0)) { xorriso->relax_compliance&= ~(isoburn_igopt_rrip_version_1_10 | isoburn_igopt_aaip_susp_1_10); } else if((l == 14 && strncmp(cpt, "aaip_susp_1_10", l) == 0) || (l == 17 && strncmp(cpt, "aaip_susp_1_10_on", l) == 0) || (l == 18 && strncmp(cpt, "aaip_susp_1_12_off", l) == 0)) { xorriso->relax_compliance|= isoburn_igopt_aaip_susp_1_10; } else if((l == 18 && strncmp(cpt, "aaip_susp_1_10_off", l) == 0) || (l == 17 && strncmp(cpt, "aaip_susp_1_12_on", l) == 0) || (l == 14 && strncmp(cpt, "aaip_susp_1_12", l) == 0)) { xorriso->relax_compliance&= ~isoburn_igopt_aaip_susp_1_10; } else if((l == 11 && strncmp(cpt, "no_emul_toc", l) == 0) || (l == 14 && strncmp(cpt, "no_emul_toc_on", l) == 0)) { xorriso->no_emul_toc|= 1; } else if((l == 15 && strncmp(cpt, "no_emul_toc_off", l) == 0) || (l == 8 && strncmp(cpt, "emul_toc", l) == 0)) { xorriso->no_emul_toc&= ~1; } else if((l == 13 && strncmp(cpt, "iso_9660_1999", l) == 0) || (l == 16 && strncmp(cpt, "iso_9660_1999_on", l) == 0)) { xorriso->do_iso1999= 1; } else if(l == 17 && strncmp(cpt, "iso_9660_1999_off", l) == 0) { xorriso->do_iso1999= 0; } else if((l >= 15 && strncmp(cpt, "iso_9660_level=", 15) == 0)) { value= 0; sscanf(cpt + 15, "%d", &value); if(value == 1 || value == 2) { limit= ((off_t) 4) * ((off_t) 1024*1024*1024) - ((off_t) 1); xorriso->iso_level= value; xorriso->iso_level_is_default= 0; if(xorriso->file_size_limit > limit) xorriso->file_size_limit= limit; } else if(value == 3) { xorriso->iso_level= value; xorriso->iso_level_is_default= 0; if(xorriso->file_size_limit < Xorriso_default_file_size_limiT) xorriso->file_size_limit= Xorriso_default_file_size_limiT; } else { Xorriso_alloc_meM(msg, char, 160); sprintf(msg, "-compliance iso_9660_level=%d : Only 1, 2, or 3 are permissible", value); Xorriso_msgs_submit(xorriso, 0, msg, 0, "FAILURE", 0); Xorriso_free_meM(msg); msg= NULL; xorriso->relax_compliance= was; return(0); } } else if((l == 8 && strncmp(cpt, "iso_9660", l) == 0) || (l == 11 && strncmp(cpt, "iso_9660_on", l) == 0)) { /* may have a meaning in future */; } else if(l == 12 && strncmp(cpt, "iso_9660_off", l) == 0) { /* may have a meaning in future */; Xorriso_msgs_submit(xorriso, 0, "-compliance -iso_9660_off : Cannot do anything else but ISO 9660", 0, "FAILURE", 0); xorriso->relax_compliance= was; return(0); } else if((l == 9 && strncmp(cpt, "old_empty", l) == 0) || (l == 12 && strncmp(cpt, "old_empty_on", l) == 0)) { xorriso->do_old_empty= 1; } else if(l == 13 && strncmp(cpt, "old_empty_off", l) == 0) { xorriso->do_old_empty= 0; } else if(l >= 15 && strncmp(cpt, "max_ce_entries=", 15) == 0) { value= 0; sscanf(cpt + 15, "%d", &value); if(value < 1 || value > 100000) { if(msg == NULL) Xorriso_alloc_meM(msg, char, 160); sprintf(msg, "-compliance max_ce_entries=%d : Permissible is 1 to 100000", value); Xorriso_msgs_submit(xorriso, 0, msg, 0, "FAILURE", 0); xorriso->relax_compliance= was; ret= 0; goto ex; } else { xorriso->max_ce_entries= value; } } else if(l >= 12 && strncmp(cpt, "max_ce_drop=", 12) == 0) { endl= sizeof(submode) - 1; endpt= strchr(cpt + 12, ':'); if(endpt != NULL) if(endl > endpt - (cpt + 12)) endl= endpt - (cpt + 12); strncpy(submode, cpt + 12, endl); submode[endl]= 0; if(strcmp(submode, "off") == 0) { xorriso->max_ce_entries_flag&= ~15; } else if(strcmp(submode, "xattr") == 0) { xorriso->max_ce_entries_flag= (xorriso->max_ce_entries_flag & ~15) | 1; } else if(strcmp(submode, "xattr_acl") == 0) { xorriso->max_ce_entries_flag= (xorriso->max_ce_entries_flag & ~15) | 2; } else { sprintf(xorriso->info_text, "-compliance: unknown mode in max_ce_drop='%s'", submode); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } } else { if(linfo_text, "-compliance: unknown rule '%s'", cpt); else sprintf(xorriso->info_text, "-compliance: oversized rule parameter (%d)", l); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); xorriso->relax_compliance= was; return(0); } } return(1); ex:; Xorriso_free_meM(msg); return(ret); } /* @return 1=ok 2=ok, is default setting */ int Xorriso_get_relax_text(struct XorrisO *xorriso, char mode[1024], int flag) { int r, drop; r= xorriso->relax_compliance; if(r == 0) { strcpy(mode, "strict"); return(1); } strcpy(mode, "clear"); sprintf(mode + strlen(mode), ":iso_9660_level=%d", xorriso->iso_level); if(r & isoburn_igopt_allow_dir_id_ext) strcat(mode, ":allow_dir_id_ext"); if(r & isoburn_igopt_omit_version_numbers) strcat(mode, ":omit_version"); if(r & isoburn_igopt_only_iso_versions) strcat(mode, ":only_iso_version"); if(r & isoburn_igopt_allow_deep_paths) strcat(mode, ":deep_paths"); if(r & isoburn_igopt_allow_longer_paths) strcat(mode, ":long_paths"); if(r & isoburn_igopt_max_37_char_filenames) strcat(mode, ":long_names"); if(r & isoburn_igopt_no_force_dots) strcat(mode, ":no_force_dots"); if(r & isoburn_igopt_no_j_force_dots) strcat(mode, ":no_j_force_dots"); if(r & isoburn_igopt_allow_lowercase) strcat(mode, ":lowercase"); if(r & isoburn_igopt_allow_full_ascii) strcat(mode, ":full_ascii"); else if(r & isoburn_igopt_allow_7bit_ascii) strcat(mode, ":7bit_ascii"); if(r & isoburn_igopt_joliet_longer_paths) strcat(mode, ":joliet_long_paths"); if(r & isoburn_igopt_joliet_long_names) strcat(mode, ":joliet_long_names"); if(r & isoburn_igopt_joliet_utf16) strcat(mode, ":joliet_utf16"); if(r & isoburn_igopt_always_gmt) strcat(mode, ":always_gmt"); if(r & isoburn_igopt_dir_rec_mtime) strcat(mode, ":rec_mtime"); if(r & isoburn_igopt_rrip_version_1_10) { strcat(mode, ":old_rr"); if(!(r & isoburn_igopt_aaip_susp_1_10)) strcat(mode, ":aaip_susp_1_10_off"); } else { strcat(mode, ":new_rr"); if(r & isoburn_igopt_aaip_susp_1_10) strcat(mode, ":aaip_susp_1_10"); } if(xorriso->no_emul_toc & 1) strcat(mode, ":no_emul_toc"); if(xorriso->untranslated_name_len != 0) sprintf(mode + strlen(mode), ":untranslated_name_len=%d", xorriso->untranslated_name_len); if(xorriso->do_iso1999) sprintf(mode + strlen(mode), ":iso_9660_1999"); if(xorriso->do_old_empty) sprintf(mode + strlen(mode), ":old_empty"); sprintf(mode + strlen(mode), ":max_ce_entries=%u", xorriso->max_ce_entries); drop= xorriso->max_ce_entries_flag & 15; sprintf(mode + strlen(mode), ":max_ce_drop=%s", drop == 0 ? "off" : drop == 1 ? "xattr" : "xattr_acl"); return(1 + (r == Xorriso_relax_compliance_defaulT && !(xorriso->no_emul_toc & 1) && xorriso->untranslated_name_len == 0 && !xorriso->do_iso1999 && xorriso->iso_level == 3 && xorriso->max_ce_entries == 31 && drop == 2)); } /* @param flag bit0= operating on newly attached boot image */ int Xorriso_set_isolinux_options(struct XorrisO *xorriso, IsoImage *image, int flag) { int make_isohybrid_mbr= 0, ret, patch_table= 0, num_boots, i; ElToritoBootImage *bootimg, **boots = NULL; IsoFile *bootimg_node, **bootnodes = NULL; ret= iso_image_get_boot_image(image, &bootimg, &bootimg_node, NULL); Xorriso_process_msg_queues(xorriso,0); if(ret != 1) { sprintf(xorriso->info_text, "Programming error: No boot image available in Xorriso_set_isolinux_options()"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); ret= -1; goto ex; } ret= iso_image_get_all_boot_imgs(image, &num_boots, &boots, &bootnodes, 0); Xorriso_process_msg_queues(xorriso,0); if(ret != 1) { Xorriso_report_iso_error(xorriso, "", ret, "Cannot inquire boot images", 0, "FATAL", 1); ret= -1; goto ex; } /* bit0 : 1=boot-info-table , bit2-7 : 1=EFI , 2=HFS+ , bit8 : 1=APM */ patch_table = xorriso->patch_isolinux_image & 0x3fd; if((flag & 1) && num_boots > 1) { ret= el_torito_set_isolinux_options(boots[num_boots - 1], patch_table, 0); ret= (ret == 1); goto ex; } /* Handle patching of first attached boot image or of imported boot images */ for(i= 0; i < num_boots; i++) { patch_table = xorriso->patch_isolinux_image & 0x3fd; if(patch_table && !(flag & 1)) { if(!el_torito_seems_boot_info_table(boots[i], 0)) patch_table&= ~1; else if((xorriso->patch_isolinux_image & 2) && el_torito_get_boot_platform_id(boots[i]) == 0xef) patch_table&= ~1; } if(i > 0 || xorriso->boot_image_isohybrid == 0) { ret= el_torito_set_isolinux_options(boots[i], patch_table, 0); if(ret != 1) {ret= 0; goto ex;} continue; } /* <<< From here on only with first boot image and deprecated builtin isohybrid MBR */ if(xorriso->boot_image_isohybrid == 3) { make_isohybrid_mbr= 1; } else { ret= Xorriso_is_isohybrid(xorriso, bootimg_node, 0); if(ret < 0) {ret= 0; goto ex;} if(ret > 0) make_isohybrid_mbr= 1; } if(xorriso->boot_image_isohybrid == 2 && !make_isohybrid_mbr) { sprintf(xorriso->info_text, "Isohybrid signature is demanded but not found in boot image file."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } if(make_isohybrid_mbr) { sprintf(xorriso->info_text, "Will write isohybrid MBR."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); } ret= el_torito_set_isolinux_options(bootimg, patch_table | (make_isohybrid_mbr << 1),0); if(ret != 1) {ret= 0; goto ex;} } ex: Xorriso_process_msg_queues(xorriso,0); if(boots != NULL) free(boots); if(bootnodes != NULL) free(bootnodes); return(ret); } int Xorriso_overwrite_iso_head(struct XorrisO *xorriso, struct burn_drive *drive, char *head_buffer, off_t lba, int flag) { int ret; off_t to_write; to_write= 64 * 1024; burn_drive_reset_simulate(drive, xorriso->do_dummy); ret= burn_random_access_write(drive, lba * (off_t) 2048, head_buffer, to_write, 1); if(ret <= 0) { Xorriso_process_msg_queues(xorriso, 0); sprintf(xorriso->info_text, "Cannot write new ISO image head to LBA %.f", (double) lba); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } return(1); } /* @param flag bit0= insist on tag_type 4 (relocated superblock tag) bit1= accept tag with ISO_MD5_AREA_CORRUPTED */ int Xorriso_find_sb_checksum(struct XorrisO *xorriso, char *head_buffer, int *vd_end, int flag) { int i, tag_type, ret; uint32_t pos, range_start, range_size, next_tag; char md5[16]; *vd_end= 0; /* Look for volume descriptor end */ for(i= 16; i < 32; i++) if(((unsigned char *) head_buffer)[i * 2048] == 0xff && strncmp(head_buffer + i * 2048 + 1, "CD001", 5) == 0) break; /* Check whether the next one is a libisofs checksum tag */ if(i < 32) { *vd_end= i; i++; ret= iso_util_decode_md5_tag(head_buffer + i * 2048, &tag_type, &pos, &range_start, &range_size, &next_tag, md5, 0); if(((unsigned int) ret) != ISO_MD5_AREA_CORRUPTED || !(flag & 2)) if(ret <= 0) return(ret); if((flag & 1) && tag_type != 4) return(0); /* No other tag type is supposed to occur before type 4 */ } return(i + 1); } /* @param field_head Example: " md5=" */ int Xorriso__set_iso_check_tag_md5(char *tag_data, char *field_head, void **ctx, int *field_end, int flag) { char md5_bin[16], m32, *cpt; int i; iso_md5_end(ctx, md5_bin); cpt= strstr(tag_data, field_head); if(cpt == NULL) return(0); cpt+= strlen(field_head); m32= cpt[32]; for(i= 0; i < 16; i++) sprintf(cpt + 2 * i, "%2.2x", ((unsigned char *) md5_bin)[i]); cpt[32]= m32; *field_end= (cpt - tag_data) + 32; return(1); } int Xorriso_verify_sb_tag(struct XorrisO *xorriso, char *head_buffer, int checksum_block, int flag) { int tag_type, ret; uint32_t pos, range_start, range_size, next_tag; char md5_rec[16], md5_comp[16]; void *ctx= NULL; /* Obtain checksum */ iso_util_decode_md5_tag(head_buffer + checksum_block * 2048, &tag_type, &pos, &range_start, &range_size, &next_tag, md5_rec, 0); /* Verify checksum */ ret= iso_md5_start(&ctx); if(ret <= 0) { Xorriso_process_msg_queues(xorriso,0); Xorriso_no_malloc_memory(xorriso, NULL, 0); return(0); } ret= iso_md5_compute(ctx, head_buffer, checksum_block * 2048); iso_md5_end(&ctx, md5_comp); if(ret <= 0) { Xorriso_process_msg_queues(xorriso,0); return(0); } if(iso_md5_match(md5_rec, md5_comp)) return(1); Xorriso_msgs_submit(xorriso, 0, "Superblock data do not match superblock checksum tag", 0, "WARNING", 0); return(0); } int Xorriso_refresh_sb_tag(struct XorrisO *xorriso, char *head_buffer, int checksum_block, int flag) { int ret, field_end; char md5_bin[16]; void *ctx= NULL; /* Recompute checksum and update found checksum tag */; ret= iso_md5_start(&ctx); if(ret <= 0) { no_md5_ctx:; Xorriso_process_msg_queues(xorriso,0); Xorriso_no_malloc_memory(xorriso, NULL, 0); return(0); } ret= iso_md5_compute(ctx, head_buffer, checksum_block * 2048); if(ret <= 0) { md5_comp_failed:; iso_md5_end(&ctx, md5_bin); return(0); } Xorriso__set_iso_check_tag_md5(head_buffer + checksum_block * 2048, " md5=", &ctx, &field_end, 0); if(ret <= 0) return(2); ret= iso_md5_start(&ctx); if(ret <= 0) goto no_md5_ctx; ret= iso_md5_compute(ctx, head_buffer + checksum_block * 2048, field_end); if(ret <= 0) goto md5_comp_failed; Xorriso__set_iso_check_tag_md5(head_buffer + checksum_block * 2048, " self=", &ctx, &field_end, 0); return(1); } /* @param flag bit0= obtain iso_lba from indev bit1= head_buffer already contains a valid head bit2= issue message about success bit3= check whether source blocks are banned by in_sector_map bit4= refresh relocated sb checksum tag bit5= bit1 for Xorriso_find_sb_checksum: accept tag with ISO_MD5_AREA_CORRUPTED */ int Xorriso_update_iso_lba0(struct XorrisO *xorriso, off_t iso_lba, off_t isosize, char *head_buffer, struct CheckmediajoB *job, int flag) { int ret, i, checksum_block= -1, vd_end; uint32_t full_size; char *headpt; struct burn_drive_info *dinfo; struct burn_drive *drive = NULL; off_t seek_ret, to_write; ret= Xorriso_may_burn(xorriso, 0); if(ret <= 0) return(0); if(flag & 1) { ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to learn current session lba", 0); if(ret<=0) return(0); ret= isoburn_disc_get_msc1_v2(drive, &iso_lba); if(ret<=0) return(0); drive= NULL; /* indev will not be used furtherly */ } if(job == NULL) { ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to update at lba 0 to 31", 2); if(ret<=0) return(0); } if(iso_lba < 32) return(2); if(!(flag & 2)) { /* head_buffer was not filled yet. Read it from output media. */ if(drive != NULL) if(burn_drive_get_drive_role(drive) == 5) /* write-only */ return(2); if(job != NULL && job->data_to_fd >= 0) { if((flag & 8) && job->sector_map != NULL) { ret= Sectorbitmap_bytes_are_set(job->sector_map, iso_lba * (off_t) 2048, (iso_lba + 32) * ((off_t) 2048) - (off_t) 1, 0); if(ret <= 0) { sprintf(xorriso->info_text, "ISO image head at lba %.f is marked as invalid blocks in file copy", (double) iso_lba); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); return(0); } } seek_ret= lseek(job->data_to_fd, ((off_t) 2048) * iso_lba, SEEK_SET); if(seek_ret == -1) ret= 0; else ret= read(job->data_to_fd, head_buffer, 64 * 1024); if(ret < 64 * 1024) { Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text, "Cannot read ISO image head from file copy"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); return(0); } ret= isoburn_read_iso_head_v2(NULL, (off_t) 0, &isosize, head_buffer, 1 << 13); if(ret<=0) { Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text, "Alleged session start does not look like ISO 9660."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); return(0); } } else { ret= 0; if(drive != NULL) ret= isoburn_read_iso_head_v2(drive, iso_lba, &isosize, head_buffer, 2); if(ret<=0) { Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text, "Cannot read freshly written ISO image head"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } } } /* patch ISO header */ if(iso_lba + isosize > (off_t) 0xffffffff) { sprintf(xorriso->info_text, "The total ISO filesystem size would exceed 8 TiB"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } full_size= iso_lba + isosize; headpt= head_buffer + 32*1024; for(i=0;i<4;i++) headpt[87-i]= headpt[80+i]= (full_size >> (8*i)) & 0xff; /* >>> What about Joliet et.al. ? */; if(flag & 16) { /* Find relocated sb checksum tag */ ret= Xorriso_find_sb_checksum(xorriso, head_buffer, &vd_end, 1 | ((flag >> 4) & 2)); if(ret > 0) { /* If it is recognizable then it matched in Xorriso_adjust_relocated_sb */ checksum_block= ret - 1; ret= Xorriso_refresh_sb_tag(xorriso, head_buffer, checksum_block, 0); if(ret <= 0) return(0); } } if(job != NULL) { /* This is a check_media superblock relocation: Invalidate eventual libisofs checksum tags. Write only up to PVD end plus eventual invalidated tag. */ to_write= 2048 * 32; ret= Xorriso_find_sb_checksum(xorriso, head_buffer, &i, ((flag >> 4) & 2)); if(ret > 0) { if(!(flag & 16)) /* invalidate */ memset(head_buffer + (ret - 1) * 2048, 0, 8); to_write= 2048 * ret; } else if(i > 0) { to_write= 2048 * (i + 1); } seek_ret= lseek(job->data_to_fd, (off_t) 0, SEEK_SET); if(seek_ret == -1) ret= 0; else ret= write(job->data_to_fd, head_buffer, to_write); if(ret < to_write) { Xorriso_process_msg_queues(xorriso,0); sprintf(xorriso->info_text, "Cannot write ISO image head to file copy"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); return(0); } } else { /* This is a regular superblock relocation. Write full 64 kB. */ ret= Xorriso_overwrite_iso_head(xorriso, drive, head_buffer, (off_t) 0, 0); if(ret <= 0) return(ret); } if(flag & 4) { sprintf(xorriso->info_text, "Overwrote LBA 0 to 31 by 64 KiB from LBA %.f", (double) iso_lba); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); } return(1); } /* @return 1= ok, 0= no match, -1= MD5 computation error, -2= MD5 clone or start error */ int Xorriso_migrate_checksum_tag(struct XorrisO *xorriso, char *buffer, int buf_base, int start, int checksum_block, char md5_rec[16], void *ctx_unch, void *ctx_chng, int flag) { int ret, to_compute; char *headpt, md5_clone[16]; void *ctx_clone= NULL; int field_end; /* Checksum both up to before checksum tag */ headpt= buffer + start * 2048; to_compute= (checksum_block - start) * 2048; if(to_compute > 0) { ret= iso_md5_compute(ctx_unch, headpt, to_compute); if(ret <= 0) {ret= -1; goto ex;} ret= iso_md5_compute(ctx_chng, headpt, to_compute); if(ret <= 0) {ret= -1; goto ex;} } /* Verify with unchanged checksum */ ret= iso_md5_clone(ctx_unch, &ctx_clone); if(ret <= 0) {ret= -2; goto ex;} iso_md5_end(&ctx_clone, md5_clone); if(!iso_md5_match(md5_rec, md5_clone)) {ret= 0; goto ex;} /* Compute unchanged rest of block range */ headpt= buffer + checksum_block * 2048; to_compute= 2048; ret= iso_md5_compute(ctx_unch, headpt, to_compute); if(ret <= 0) {ret= -1; goto ex;} /* Replace checksum in tag by changed checksum */ ret= iso_md5_clone(ctx_chng, &ctx_clone); if(ret <= 0) {ret= -2; goto ex;} Xorriso__set_iso_check_tag_md5(headpt, " md5=", &ctx_clone, &field_end, 0); /* Recompute and write self= checksum */ ret= iso_md5_start(&ctx_clone); if(ret <= 0) {ret= -2; goto ex;} ret= iso_md5_compute(ctx_clone, headpt, field_end); if(ret <= 0) {ret= -1; goto ex;} Xorriso__set_iso_check_tag_md5(headpt, " self=", &ctx_clone, &field_end, 0); /* Add rest of head_buffer to changed checksum */ ret= iso_md5_compute(ctx_chng, headpt, to_compute); if(ret <= 0) {ret= -1; goto ex;} ret= 1; ex:; if(ctx_clone != NULL) iso_md5_end(&ctx_clone, md5_clone); return(ret); } /* Verify and re-compute tree and session checksum tag */ int Xorriso_refresh_ts_tags(struct XorrisO *xorriso, struct burn_drive *drive, void *ctx_unch, void *ctx_chng, off_t iso_lba, off_t session_size, int checksum_block, int flag) { int i, ret, tag_type, look_for_tag, check_start, look_from_block, was_change; off_t read_pos, to_read, data_count; uint32_t pos, range_start, range_size, next_tag; char md5_rec[16]; char *buf= NULL; look_for_tag= 3; /* tree tag */ look_from_block= checksum_block + 1; /* first buffer is already partly done */ Xorriso_alloc_meM(buf, char, 32 * 2048); for(read_pos= iso_lba; read_pos < iso_lba + session_size; read_pos+= 32) { was_change= 0; to_read= 32; if(read_pos + to_read > iso_lba + session_size) to_read= iso_lba + session_size - read_pos; ret= burn_read_data(drive, read_pos * (off_t) 2048, buf, to_read * (off_t) 2048, &data_count, 0); if(ret <= 0) {ret= 0; goto ex;} check_start= look_from_block; for(i= look_from_block; i < to_read; i++) { /* Watch out for tag */ ret= iso_util_decode_md5_tag(buf + i * 2048, &tag_type, &pos, &range_start, &range_size, &next_tag, md5_rec, look_for_tag); if(ret < 0 ) { ret= 0; goto ex; } else if(ret == 1) { if(tag_type != look_for_tag) { sprintf(xorriso->info_text, "Encountered checksum tag type %d while looking for %d", tag_type, look_for_tag); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "MISHAP", 0); ret= 2; goto ex; } /* Checksum up to before tag, verify, if match replace checksum and write */ ret= Xorriso_migrate_checksum_tag(xorriso, buf, read_pos, check_start, i, md5_rec, ctx_unch, ctx_chng, 0); if(ret == -2) goto ex; if(ret < 0) {ret= 0; goto ex;} if(ret == 0) { sprintf(xorriso->info_text, "Checksum tag MD5 mismatch in old session state"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "MISHAP", 0); ret= 2; goto ex; } was_change= 1; if(look_for_tag == 3) { look_for_tag= 1; /* session tag */ } else { look_for_tag= -1; break; } check_start= i + 1; } } look_from_block= 0; /* all following buffer need processing from start */ if(was_change) { ret= burn_random_access_write(drive, (off_t) read_pos * (off_t) 2048, buf, to_read * (off_t) 2048, 1); if(ret <= 0) { Xorriso_process_msg_queues(xorriso, 0); sprintf(xorriso->info_text, "Cannot write new checksum tag data to LBA %d", (int) read_pos); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } } if(look_for_tag < 0) {ret= 1; goto ex;} /* Checksum what was not checksummed yet */ if(to_read - check_start > 0) { ret= iso_md5_compute(ctx_unch, buf + 2048 * check_start, (to_read - check_start) * 2048); if(ret <= 0) {ret= 0; goto ex;} ret= iso_md5_compute(ctx_chng, buf + 2048 * check_start, (to_read - check_start) * 2048); if(ret <= 0) {ret= 0; goto ex;} } } ret= 1; ex:; Xorriso_free_meM(buf); return(ret); } int Xorriso_adjust_session_size(struct XorrisO *xorriso, struct burn_drive *drive, char *head_buffer, off_t iso_lba, off_t iso_size, int checksum_block, off_t session_size, int flag) { int i, ret, tag_type; uint32_t pos, range_start, range_size, next_tag; char *headpt, md5_unch[16], md5_chng[16], md5_clone[16], md5_rec[16]; void *ctx_unch= NULL, *ctx_chng= NULL, *ctx_clone= NULL; if(checksum_block > 0) { /* Obtain recorded superblock MD5 */ ret= iso_util_decode_md5_tag(head_buffer + checksum_block * 2048, &tag_type, &pos, &range_start, &range_size, &next_tag, md5_rec, 0); if(ret <= 0 || tag_type != 2) { sprintf(xorriso->info_text, "Encountered checksum tag type %d while looking for 2", tag_type); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "MISHAP", 0); checksum_block= 0; } } if(checksum_block > 0) { /* Create md5 context for unchanged state */ ret= iso_md5_start(&ctx_unch); if(ret <= 0) { no_ctx:; Xorriso_process_msg_queues(xorriso, 0); Xorriso_no_malloc_memory(xorriso, NULL, 0); goto ex; } /* Checksum up to before PVD */ ret= iso_md5_compute(ctx_unch, head_buffer, 32768); if(ret <= 0) goto ex; /* Before the first change: obtain md5 object for changed state */ ret= iso_md5_clone(ctx_unch, &ctx_chng); if(ret <= 0) goto no_ctx; /* Add PVD to unchanged checksum */ ret= iso_md5_compute(ctx_unch, head_buffer + 32768, 2048); if(ret <= 0) goto ex; } /* Update session PVD at iso_lba+16 to iso_size */ headpt= head_buffer + 32 * 1024; if(iso_size > (off_t) 0xffffffff) { sprintf(xorriso->info_text, "The total ISO filesystem size exceeds 8 TiB"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } for(i= 0; i < 4; i++) headpt[87 - i]= headpt[80 + i]= (iso_size >> (8 * i)) & 0xff; if(checksum_block > 0) { /* Add changed PVD to changed checksum */ ret= iso_md5_compute(ctx_chng, head_buffer + 32768, 2048); if(ret <= 0) goto ex; ret= Xorriso_migrate_checksum_tag(xorriso, head_buffer, (int) iso_lba, 17, checksum_block, md5_rec, ctx_unch, ctx_chng, 0); if(ret == -2) goto no_ctx; if(ret < 0) {ret= 0; goto ex;} if(ret == 0) { sprintf(xorriso->info_text, "Superblock MD5 mismatch in old session state"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "MISHAP", 0); checksum_block= 0; } } ret= Xorriso_overwrite_iso_head(xorriso, drive, head_buffer, iso_lba, 0); if(ret <= 0) goto ex; if(checksum_block > 0) { /* Verify and re-compute existing checksum tree and session tag */ ret= Xorriso_refresh_ts_tags(xorriso, drive, ctx_unch, ctx_chng, iso_lba, session_size, checksum_block, 0); if(ret == -2) goto no_ctx; if(ret <= 0) goto ex; } ret= 1; ex:; Xorriso_process_msg_queues(xorriso, 0); if(ctx_unch != NULL) iso_md5_end(&ctx_unch, md5_unch); if(ctx_chng != NULL) iso_md5_end(&ctx_chng, md5_chng); if(ctx_clone != NULL) iso_md5_end(&ctx_clone, md5_clone); return(ret); } /* Read relocated superblock and patch in the VDs of the session superblock */ int Xorriso_adjust_relocated_sb(struct XorrisO *xorriso, struct burn_drive *drive, char *head_buffer, char **sb_buffer, int flag) { int ret, i, vd_end, checksum_block= -1; off_t old_size; char *buffer, *checksum= NULL; *sb_buffer= NULL; Xorriso_alloc_meM(*sb_buffer, char, 32 * 2048); buffer= *sb_buffer; Xorriso_alloc_meM(checksum, char, 2048); ret= isoburn_read_iso_head_v2(drive, 0, &old_size, buffer, 2); if(ret <= 0) goto ex; ret= Xorriso_find_sb_checksum(xorriso, buffer, &vd_end, 0); if(ret < 0) goto ex; if(ret > 0) { checksum_block= ret - 1; memcpy(checksum, buffer + checksum_block * 2048, 2048); ret= Xorriso_verify_sb_tag(xorriso, buffer, checksum_block, 0); if(ret <= 0) { checksum_block= -1; memset(checksum, 0, 8); } } for(i= 16; i < 32; i++) { memcpy(buffer + i * 2048, head_buffer + i * 2048, 2048); if(((unsigned char *) head_buffer)[i * 2048] == 0xff && strncmp(head_buffer + i * 2048 + 1, "CD001", 5) == 0) { i++; break; } } if(checksum_block >= 0 && i < 32) memcpy(buffer + i * 2048, checksum, 2048); ret= 1; ex: if(ret <= 0) Xorriso_free_meM(*sb_buffer); Xorriso_free_meM(checksum); return(ret); } int Xorriso_truncate_overwritable(struct XorrisO *xorriso, char *adr_mode, char *adr_value, char *adjust, int flag) { int ret, iso_session, iso_track, image_start_mode= 0; int was_indev= 0, checksum_block= 0, vd_end, headless_mode= 0, i; int params_flag; off_t iso_lba= 0, iso_size= 0, old_size, new_size, blocks, readable_blocks; char image_start_value[81], *head_buffer= NULL, iso_volid[33]; char *sb_buffer= NULL, *checksum_pt, *adr_data= NULL; struct burn_drive_info *dinfo; struct burn_drive *drive = NULL, *in_drive = NULL; struct burn_multi_caps *caps= NULL; Xorriso_alloc_meM(head_buffer, char, 32 * 2048); Xorriso_alloc_meM(adr_data, char, 163); if(Xorriso_change_is_pending(xorriso, 0)) { sprintf(xorriso->info_text, "-truncate_overwritable: Image changes pending. -commit or -rollback first"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } ret= Xorriso_may_burn(xorriso, 0); if(ret <= 0) goto ex; ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to activate an older session", 2); if(ret <= 0) goto ex; /* Is it overwritable ? */ ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0); if(ret > 0) { if(caps->start_adr == 0) ret= 0; } if(ret <= 0) { sprintf(xorriso->info_text, "-truncate_overwritable: Loaded medium is not random-access overwritable"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); goto ex; } ret= Xorriso_reassure(xorriso, "-truncate_overwritable", "activates an older session and destroys newer ones", 0); if(ret <= 0) {ret= 2; goto ex;} /* Learn old size */ ret= isoburn_read_iso_head_v2(drive, 0, &old_size, iso_volid, 0); if(ret <= 0) { sprintf(xorriso->info_text, "-truncate_overwritable: Cannot read ISO 9660 Volume Descriptor from LBA 0"); if((strcmp(adr_mode, "lba") == 0 || strcmp(adr_mode, "sbsector") == 0) && strcmp(adjust, "new") == 0) { Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); ret= burn_get_read_capacity_v2(drive, &old_size, 0); if(ret <= 0) goto ex; headless_mode= 1; } else { Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); goto ex; } } if(headless_mode) { iso_lba= Scanf_io_size(adr_value, 0); ret= isoburn_read_iso_head_v2(drive, iso_lba, &new_size, head_buffer, 2 | (1 << 12)); if(ret <= 0) goto not_iso_9660; } else { /* Check for PVD at image_start_value and learn new size */ ret= Xorriso_decode_load_adr(xorriso, "-truncate_overwritable", adr_mode, adr_value, &image_start_mode, image_start_value, 0); if(ret <= 0) goto ex; ret= Xorriso_prepare_load_search(xorriso, "-truncate_overwritable", image_start_mode, image_start_value, adr_data, ¶ms_flag, 0); if(ret <= 0) goto ex; ret= isoburn_get_mount_params_v2(drive, image_start_mode, adr_data, &iso_lba, &iso_track, &iso_session, iso_volid, params_flag); if(ret <= 0) goto ex; if(ret != 1) { not_iso_9660:; sprintf(xorriso->info_text, "-truncate_overwritable: Given address does not lead to ISO 9660 Volume Descriptor"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } if(iso_lba >= old_size) { sprintf(xorriso->info_text, "-truncate_overwritable: Given address is larger than current ISO size"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } ret= isoburn_read_iso_head_v2(drive, iso_lba, &new_size, head_buffer, 2); if(ret <= 0) goto ex; } ret= Xorriso_find_sb_checksum(xorriso, head_buffer, &vd_end, 0); if(ret > 0) checksum_block= ret - 1; /* Default is "new" */ iso_size= new_size; if(strcmp(adjust, "old") == 0) { /* ISO size before truncation */ iso_size= old_size - iso_lba; } else if(adjust[0] == '+') { /* Add-on size to new */ blocks= Scanf_io_size(adjust + 1, 0) / 2048; if(blocks < 0) goto wrong_adjust; iso_size+= blocks; } else if(adjust[0] >= '0' && adjust[0] <= '9') { /* Add-on size to new */ blocks= Scanf_io_size(adjust, 0) / 2048; if(blocks < iso_lba + iso_size) { wrong_adjust:; sprintf(xorriso->info_text, "-truncate_overwritable: Given total filesystem size is smaller than new session size"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } iso_size= blocks - iso_lba; } ret= burn_get_read_capacity_v2(drive, &readable_blocks, 0); Xorriso_process_msg_queues(xorriso, 0); if(ret > 0) { if(iso_lba + iso_size > readable_blocks) { sprintf(xorriso->info_text, "-truncate_overwritable: Given total filesystem size is larger than formatted medium size"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } } /* Give up possible input drive */ ret= Xorriso_get_drive_handles(xorriso, &dinfo, &in_drive, "", 16); if(ret < 0) goto ex; if(ret == 1) { ret= Xorriso_give_up_drive(xorriso, 1); if(ret<=0) goto ex; was_indev= 1; } if(iso_size != new_size) { ret=Xorriso_adjust_session_size(xorriso, drive, head_buffer, iso_lba, iso_size, checksum_block, new_size, 0); if(ret <= 0) goto ex; } /* Load first 64 kB and transfer VDs from head_buffer */ if(headless_mode) { Xorriso_alloc_meM(sb_buffer, char, 32 * 2048); memcpy(sb_buffer, head_buffer, 32 * 2048); for(i= 17; i < 32; i++) if(strncmp(sb_buffer + i * 2048, "libisofs_sb_checksum_tag_v1", 27) == 0) break; if(i < 32) { /* Convert superblock tag to provisory relocated superblock tag */ checksum_pt= sb_buffer + i * 2048; memset(checksum_pt, 0, 2048); sprintf(checksum_pt, "libisofs_rlsb32_checksum_tag_v1 pos=%d range_start=0 range_size=%d", i, i); sprintf(checksum_pt + strlen(checksum_pt), " session_start=%.f md5=0123456789abcdef0123456789abcdef self=0123456789abcdef0123456789abcdef\n", (double) iso_lba); } } else { ret= Xorriso_adjust_relocated_sb(xorriso, drive, head_buffer, &sb_buffer, 0); if(ret <= 0) goto ex; } /* Patch the size and write back */ ret= Xorriso_update_iso_lba0(xorriso, iso_lba, iso_size, sb_buffer, NULL, 2 | 16 | ((!!headless_mode) << 5)); if(ret <= 0) goto ex; ret= Xorriso_reaquire_outdev(xorriso, 2 + was_indev); if(ret <= 0) goto ex; ret= 1; ex: if(caps!=NULL) burn_disc_free_multi_caps(&caps); Xorriso_free_meM(adr_data); Xorriso_free_meM(head_buffer); Xorriso_free_meM(sb_buffer); Xorriso_process_msg_queues(xorriso,0); return(ret); } int Xorriso_set_system_area_path(struct XorrisO *xorriso, char *path, int flag) { int ret; char *eff_src= NULL, *intvl; struct iso_interval_reader *ivr= NULL; off_t byte_count; IsoImage *img= NULL; struct burn_drive_info *source_dinfo; struct burn_drive *source_drive; if(path[0] == 0) { xorriso->system_area_disk_path[0]= 0; {ret= 1; goto ex;} } Xorriso_alloc_meM(eff_src, char, SfileadrL); intvl = path; ret = Xorriso_check_intvl_string(xorriso, &intvl, 0); if(ret > 0) { /* Check for syntactical correctness */ if(xorriso->in_drive_handle != NULL) { ret= Xorriso_get_drive_handles(xorriso, &source_dinfo, &source_drive, "on attempt to verify interval reader string", 0); if(ret<=0) goto ex; img= isoburn_get_attached_image(source_drive); } ret= iso_interval_reader_new(img, intvl, &ivr, &byte_count, 1); Xorriso_process_msg_queues(xorriso, 0); if(ret < 0) { sprintf(xorriso->info_text, "Given path for system area is not accepted by interval reader"); Text_shellsafe(eff_src, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } iso_interval_reader_destroy(&ivr, 0); ret= Sfile_str(xorriso->system_area_disk_path, path, 0); if(ret <= 0) {ret= -1; goto ex;} ret= 1; goto ex; } ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, path, eff_src, 2|4|16); if(ret < 0) goto ex; if(ret == 0) { sprintf(xorriso->info_text, "Given path does not exist on disk: -boot_image system_area="); Text_shellsafe(eff_src, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); } if(ret == 2) { sprintf(xorriso->info_text, "Given path leads to a directory: -boot_image system_area="); Text_shellsafe(eff_src, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); {ret= 0; goto ex;} } ret= Sfile_str(xorriso->system_area_disk_path, eff_src, 0); if(ret <= 0) {ret= -1; goto ex;} ret= 1; ex: Xorriso_free_meM(eff_src); if(img != NULL) iso_image_unref(img); return(ret); } /* @param flag bit0=force burn_disc_close_damaged() */ int Xorriso_close_damaged(struct XorrisO *xorriso, int flag) { int ret; struct burn_drive_info *dinfo; struct burn_drive *drive; struct burn_write_opts *burn_options= NULL; if(Xorriso_change_is_pending(xorriso, 0)) { sprintf(xorriso->info_text, "Image changes pending. -commit or -rollback first"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to close damaged session", 2); if(ret<=0) goto ex; ret= Xorriso_check_multi(xorriso, drive, 0); if(ret<=0) goto ex; ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0); if(ret <= 0) goto ex; ret= burn_disc_close_damaged(burn_options, flag & 1); Xorriso_process_msg_queues(xorriso, 0); Xorriso_option_dev(xorriso, "", 3 | 4); /* Give up drives */ if(ret <= 0) goto ex; ret= 1; ex:; Xorriso_process_msg_queues(xorriso, 0); if(burn_options != NULL) burn_write_opts_free(burn_options); return(ret); } /* @param flag bit0= no error message */ int Xorriso_parse_guid(struct XorrisO *xorriso, char *text, uint8_t guid[16], int flag) { int bin_count= 0, ret; uint8_t u[16], tr; /* Try RFC 4122 : big endian XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX Translate to UEFI: first three components to little-endian */ if(strlen(text) == 36) { if(text[8] == '-' && text[13] == '-' && text[18] == '-' && text[23] == '-'){ ret= Hex_to_bin(text, 4, &bin_count, u, 0); if(ret < 0 || bin_count != 4) goto malformed; tr= u[0]; u[0]= u[3]; u[3]= tr; tr= u[1]; u[1]= u[2]; u[2]= tr; ret= Hex_to_bin(text + 9, 2, &bin_count, u + 4, 0); if(ret < 0 || bin_count != 2) goto malformed; tr= u[4]; u[4]= u[5]; u[5]= tr; ret= Hex_to_bin(text + 14, 2, &bin_count, u + 6, 0); if(ret < 0 || bin_count != 2) goto malformed; tr= u[6]; u[6]= u[7]; u[7]= tr; ret= Hex_to_bin(text + 19, 2, &bin_count, u + 8, 0); if(ret < 0 || bin_count != 2) goto malformed; ret= Hex_to_bin(text + 24, 6, &bin_count, u + 10, 0); if(ret < 0 || bin_count != 6) goto malformed; memcpy(guid, u, 16); return(1); } } if(strlen(text) == 32) { ret= Hex_to_bin(text, 16, &bin_count, u, 0); if(ret < 0 || bin_count != 16) goto malformed; memcpy(guid, u, 16); return(1); } malformed:; if(!(flag & 1)) { sprintf(xorriso->info_text, "Malformed GUID string: "); Text_shellsafe(text, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); } return(0); } int Xorriso_parse_gpt_guid(struct XorrisO *xorriso, char *text, int flag) { int ret; if(strcmp(text, "random") == 0) { xorriso->gpt_guid_mode= 0; return(1); } if(strcmp(text, "modification-date") == 0 || strcmp(text, "volume_date_uuid") == 0) { xorriso->gpt_guid_mode= 2; return(1); } ret= Xorriso_parse_guid(xorriso, text, xorriso->gpt_guid, 0); if(ret <= 0) return(ret); xorriso->gpt_guid_mode= 1; return(1); } /* @return Tells the recognition status 0= not recognized as GUID 1= non-EFI type GUID 2= EFI type GUID */ int Xorriso_parse_type_guid(struct XorrisO *xorriso, char *text, uint8_t guid[16], int *mbr_type, int flag) { int j, ret; static uint8_t efi_sys_uuid[16] = { 0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b }; ret= Xorriso_parse_guid(xorriso, text, guid, 1); if(ret > 0) { for(j= 0; j < 16; j++) if(guid[j] != efi_sys_uuid[j]) break; if(j >= 16) { *mbr_type= 0xef; return(2); } else { *mbr_type= 0x83; return(1); } } return(0); }