write_run.c (xorriso-1.5.2) | : | write_run.c (xorriso-1.5.4) | ||
---|---|---|---|---|
/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images. | /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images. | |||
Copyright 2007-2017 Thomas Schmitt, <scdbackup@gmx.net> | Copyright 2007-2020 Thomas Schmitt, <scdbackup@gmx.net> | |||
Provided under GPL version 2 or later. | Provided under GPL version 2 or later. | |||
This file contains functions which are needed to write sessions. | This file contains functions which are needed to write sessions. | |||
*/ | */ | |||
#ifdef HAVE_CONFIG_H | #ifdef HAVE_CONFIG_H | |||
#include "../config.h" | #include "../config.h" | |||
#endif | #endif | |||
skipping to change at line 686 | skipping to change at line 686 | |||
Text_shellsafe(bin_path, xorriso->info_text, 1); | Text_shellsafe(bin_path, xorriso->info_text, 1); | |||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); | Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); | |||
{ret= 0; goto ex;} | {ret= 0; goto ex;} | |||
} | } | |||
} | } | |||
if(xorriso->boot_count == 0) { | if(xorriso->boot_count == 0) { | |||
if(xorriso->boot_image_cat_path[0] == 0) { | if(xorriso->boot_image_cat_path[0] == 0) { | |||
strcpy(xorriso->boot_image_cat_path, bin_path); | strcpy(xorriso->boot_image_cat_path, bin_path); | |||
cpt= strrchr(xorriso->boot_image_cat_path, '/'); | cpt= strrchr(xorriso->boot_image_cat_path, '/'); | |||
if(cpt == NULL) | if(cpt == NULL) { | |||
cpt= xorriso->boot_image_cat_path; | strcpy(xorriso->boot_image_cat_path, "/"); | |||
else | cpt= xorriso->boot_image_cat_path + 1; | |||
} else { | ||||
cpt++; | cpt++; | |||
} | ||||
strcpy(cpt, "boot.cat"); | strcpy(cpt, "boot.cat"); | |||
} | } | |||
ret= Xorriso_node_from_path(xorriso, image, xorriso->boot_image_cat_path, | ret= Xorriso_node_from_path(xorriso, image, xorriso->boot_image_cat_path, | |||
&node, 1); | &node, 1); | |||
if(ret > 0) { | if(ret > 0) { | |||
if(!xorriso->do_overwrite) { | if(!xorriso->do_overwrite) { | |||
sprintf(xorriso->info_text, | sprintf(xorriso->info_text, | |||
"May not overwrite existing -boot_image ... cat_path="); | "May not overwrite existing -boot_image ... cat_path="); | |||
Text_shellsafe(xorriso->boot_image_cat_path, xorriso->info_text, 1); | Text_shellsafe(xorriso->boot_image_cat_path, xorriso->info_text, 1); | |||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); | Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); | |||
skipping to change at line 1008 | skipping to change at line 1010 | |||
ret= Xorriso_eval_problem_status(xorriso, 1, 0); | ret= Xorriso_eval_problem_status(xorriso, 1, 0); | |||
if(ret<0) | if(ret<0) | |||
{ret= 0; goto ex;} | {ret= 0; goto ex;} | |||
if(xorriso->zisofs_by_magic && image != NULL) { | if(xorriso->zisofs_by_magic && image != NULL) { | |||
sprintf(xorriso->info_text, | sprintf(xorriso->info_text, | |||
"Checking disk file content for zisofs compression headers."); | "Checking disk file content for zisofs compression headers."); | |||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); | Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); | |||
root_node= (IsoNode *) iso_image_get_root(image); | root_node= (IsoNode *) iso_image_get_root(image); | |||
ret= iso_node_zf_by_magic(root_node, | ret= iso_node_zf_by_magic(root_node, | |||
(xorriso->out_drive_handle == xorriso->in_drive_handle) | 2 | 16); | (xorriso->out_drive_handle == xorriso->in_drive_handle) | | |||
2 | 16 | (xorriso->zisofs_by_magic << 8)); | ||||
if(ret<0) { | if(ret<0) { | |||
Xorriso_report_iso_error(xorriso, "", ret, | Xorriso_report_iso_error(xorriso, "", ret, | |||
"Error when examining file content for zisofs headers", | "Error when examining file content for zisofs headers", | |||
0, "FAILURE", 1); | 0, "FAILURE", 1); | |||
} | } | |||
ret= Xorriso_eval_problem_status(xorriso, 1, 0); | ret= Xorriso_eval_problem_status(xorriso, 1, 0); | |||
if(ret<0) | if(ret<0) | |||
{ret= 0; goto ex;} | {ret= 0; goto ex;} | |||
sprintf(xorriso->info_text, | sprintf(xorriso->info_text, | |||
"Check for zisofs compression headers done."); | "Check for zisofs compression headers done."); | |||
skipping to change at line 1249 | skipping to change at line 1252 | |||
is_bootable= iso_image_get_boot_image(image, NULL, NULL, &bootcat_node); | is_bootable= iso_image_get_boot_image(image, NULL, NULL, &bootcat_node); | |||
} | } | |||
if(image!=NULL && !(flag&1)) { | if(image!=NULL && !(flag&1)) { | |||
if(xorriso->boot_count > 0 || freshly_bootable) { | if(xorriso->boot_count > 0 || freshly_bootable) { | |||
/* Eventually rename boot catalog node to changed boot_image_cat_path */ | /* Eventually rename boot catalog node to changed boot_image_cat_path */ | |||
if(is_bootable > 0) { | if(is_bootable > 0) { | |||
ret= Xorriso_path_from_node(xorriso, (IsoNode *) bootcat_node, sfe, 0); | ret= Xorriso_path_from_node(xorriso, (IsoNode *) bootcat_node, sfe, 0); | |||
if(ret > 0) { | if(ret > 0) { | |||
if(strcmp(sfe, xorriso->boot_image_cat_path) != 0) { | if(strcmp(sfe, xorriso->boot_image_cat_path) != 0) { | |||
ret= Xorriso_rename(xorriso, NULL, sfe, | ret= Xorriso_rename(xorriso, NULL, sfe, | |||
xorriso->boot_image_cat_path, 0); | xorriso->boot_image_cat_path, 1); | |||
if(ret <= 0) | if(ret <= 0) | |||
goto ex; | goto ex; | |||
} | } | |||
} | } | |||
} | } | |||
hide_attr= !!(xorriso->boot_image_cat_hidden); | hide_attr= !!(xorriso->boot_image_cat_hidden); | |||
if(xorriso->boot_image_cat_hidden & 1) | if(xorriso->boot_image_cat_hidden & 1) | |||
hide_attr|= LIBISO_HIDE_ON_RR; | hide_attr|= LIBISO_HIDE_ON_RR; | |||
if(xorriso->boot_image_cat_hidden & 2) | if(xorriso->boot_image_cat_hidden & 2) | |||
hide_attr|= LIBISO_HIDE_ON_JOLIET; | hide_attr|= LIBISO_HIDE_ON_JOLIET; | |||
skipping to change at line 1768 | skipping to change at line 1771 | |||
if(ret <= 0) | if(ret <= 0) | |||
return(0); | return(0); | |||
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, | ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, | |||
"on attempt to -blank", 2); | "on attempt to -blank", 2); | |||
if(ret<=0) | if(ret<=0) | |||
return(0); | return(0); | |||
burn_disc_get_profile(drive, ¤t_profile, current_profile_name); | burn_disc_get_profile(drive, ¤t_profile, current_profile_name); | |||
disc_state = isoburn_disc_get_status(drive); | disc_state = isoburn_disc_get_status(drive); | |||
if(current_profile == 0x13) { /* overwriteable DVD-RW */ | if(current_profile == 0x13) { /* overwritable DVD-RW */ | |||
/* Depending on flag bit1 formatted DVD-RW will get blanked to sequential | /* Depending on flag bit1 formatted DVD-RW will get blanked to sequential | |||
state or pseudo blanked by invalidating an eventual ISO image. */ | state or pseudo blanked by invalidating an eventual ISO image. */ | |||
if(flag&2) | if(flag&2) | |||
do_deformat= 1; | do_deformat= 1; | |||
} else if(current_profile == 0x14) { /* sequential DVD-RW */ | } else if(current_profile == 0x14) { /* sequential DVD-RW */ | |||
if((flag&1) && !(flag&2)) { | if((flag&1) && !(flag&2)) { | |||
sprintf(xorriso->info_text, | sprintf(xorriso->info_text, | |||
"-blank: DVD-RW present. Mode 'fast' defaulted to mode 'all'."); | "-blank: DVD-RW present. Mode 'fast' defaulted to mode 'all'."); | |||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); | Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); | |||
sprintf(xorriso->info_text, | sprintf(xorriso->info_text, | |||
skipping to change at line 2844 | skipping to change at line 2847 | |||
} | } | |||
ex: | ex: | |||
Xorriso_process_msg_queues(xorriso,0); | Xorriso_process_msg_queues(xorriso,0); | |||
if(boots != NULL) | if(boots != NULL) | |||
free(boots); | free(boots); | |||
if(bootnodes != NULL) | if(bootnodes != NULL) | |||
free(bootnodes); | free(bootnodes); | |||
return(ret); | return(ret); | |||
} | } | |||
int Xorriso_overwrite_iso_head(struct XorrisO *xorriso, | ||||
struct burn_drive *drive, char *head_buffer, | ||||
int 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, (off_t) 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 %d", 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) | ||||
*/ | ||||
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(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 | @param flag bit0= obtain iso_lba from indev | |||
bit1= head_buffer already contains a valid head | bit1= head_buffer already contains a valid head | |||
bit2= issue message about success | bit2= issue message about success | |||
bit3= check whether source blocks are banned by in_sector_map | bit3= check whether source blocks are banned by in_sector_map | |||
bit4= refresh relocated sb checksum tag | ||||
*/ | */ | |||
int Xorriso_update_iso_lba0(struct XorrisO *xorriso, int iso_lba, int isosize, | int Xorriso_update_iso_lba0(struct XorrisO *xorriso, int iso_lba, int isosize, | |||
char *head_buffer, struct CheckmediajoB *job, | char *head_buffer, struct CheckmediajoB *job, | |||
int flag) | int flag) | |||
{ | { | |||
int ret, full_size, i; | int ret, full_size, i, checksum_block= -1, vd_end; | |||
char *headpt; | char *headpt; | |||
struct burn_drive_info *dinfo; | struct burn_drive_info *dinfo; | |||
struct burn_drive *drive = NULL; | struct burn_drive *drive = NULL; | |||
off_t seek_ret, to_write; | off_t seek_ret, to_write; | |||
int tag_type; | ||||
uint32_t pos, range_start, range_size, next_tag; | ||||
char md5[16]; | ||||
ret= Xorriso_may_burn(xorriso, 0); | ret= Xorriso_may_burn(xorriso, 0); | |||
if(ret <= 0) | if(ret <= 0) | |||
return(0); | return(0); | |||
if(flag & 1) { | if(flag & 1) { | |||
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, | ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, | |||
"on attempt to learn current session lba", 1); | "on attempt to learn current session lba", 0); | |||
if(ret<=0) | if(ret<=0) | |||
return(0); | return(0); | |||
ret= isoburn_disc_get_msc1(drive, &iso_lba); | ret= isoburn_disc_get_msc1(drive, &iso_lba); | |||
if(ret<=0) | if(ret<=0) | |||
return(0); | return(0); | |||
drive= NULL; /* indev will not be used furtherly */ | drive= NULL; /* indev will not be used furtherly */ | |||
} | } | |||
if(job == NULL) { | if(job == NULL) { | |||
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, | ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, | |||
"on attempt to update at lba 0 to 31", 2); | "on attempt to update at lba 0 to 31", 2); | |||
skipping to change at line 2938 | skipping to change at line 3081 | |||
ret= isoburn_read_iso_head(drive, iso_lba, &isosize, head_buffer, 2); | ret= isoburn_read_iso_head(drive, iso_lba, &isosize, head_buffer, 2); | |||
if(ret<=0) { | if(ret<=0) { | |||
Xorriso_process_msg_queues(xorriso,0); | Xorriso_process_msg_queues(xorriso,0); | |||
sprintf(xorriso->info_text, | sprintf(xorriso->info_text, | |||
"Cannot read freshly written ISO image head"); | "Cannot read freshly written ISO image head"); | |||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); | Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); | |||
return(0); | return(0); | |||
} | } | |||
} | } | |||
} | } | |||
/* patch ISO header */ | /* patch ISO header */ | |||
full_size= iso_lba + isosize; | full_size= iso_lba + isosize; | |||
headpt= head_buffer + 32*1024; | headpt= head_buffer + 32*1024; | |||
for(i=0;i<4;i++) | for(i=0;i<4;i++) | |||
headpt[87-i]= headpt[80+i]= (full_size >> (8*i)) & 0xff; | 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); | ||||
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) { | if(job != NULL) { | |||
/* This is a check_media superblock relocation: | /* This is a check_media superblock relocation: | |||
Invalidate eventual libisofs checksum tags. | Invalidate eventual libisofs checksum tags. | |||
Write only up to PVD end plus eventual invalidated tag. | Write only up to PVD end plus eventual invalidated tag. | |||
*/ | */ | |||
/* Look for volume descriptor end */ | to_write= 2048 * 32; | |||
for(i= 16; i < 32; i++) | ret= Xorriso_find_sb_checksum(xorriso, head_buffer, &i, 0); | |||
if(((unsigned char *) head_buffer)[i * 2048] == 0xff && | if(ret > 0) { | |||
strncmp(head_buffer + i * 2048 + 1, "CD001", 5) == 0) | if(!(flag & 16)) /* invalidate */ | |||
break; | memset(head_buffer + (ret - 1) * 2048, 0, 8); | |||
/* Check whether the next one is a libisofs checksum tag */ | to_write= 2048 * ret; | |||
if(i < 32) { | } else if(i > 0) { | |||
i++; | to_write= 2048 * (i + 1); | |||
ret= iso_util_decode_md5_tag(head_buffer + i * 2048, &tag_type, &pos, | ||||
&range_start, &range_size, &next_tag, md5, 0); | ||||
if(ret != 0) /* corrupted or not: invalidate */ | ||||
memset(head_buffer + i * 2048, 0, 8); | ||||
} | } | |||
to_write= 2048 * (i + 1); | ||||
seek_ret= lseek(job->data_to_fd, (off_t) 0, SEEK_SET); | seek_ret= lseek(job->data_to_fd, (off_t) 0, SEEK_SET); | |||
if(seek_ret == -1) | if(seek_ret == -1) | |||
ret= 0; | ret= 0; | |||
else | else | |||
ret= write(job->data_to_fd, head_buffer, to_write); | ret= write(job->data_to_fd, head_buffer, to_write); | |||
if(ret < to_write) { | if(ret < to_write) { | |||
Xorriso_process_msg_queues(xorriso,0); | Xorriso_process_msg_queues(xorriso,0); | |||
sprintf(xorriso->info_text, | sprintf(xorriso->info_text, | |||
"Cannot write ISO image head to file copy"); | "Cannot write ISO image head to file copy"); | |||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); | Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); | |||
return(0); | return(0); | |||
} | } | |||
} else { | } else { | |||
/* This is a regular superblock relocation. Write full 64 kB. */ | /* This is a regular superblock relocation. Write full 64 kB. */ | |||
to_write= 64 * 1024; | ret= Xorriso_overwrite_iso_head(xorriso, drive, head_buffer, 0, 0); | |||
burn_drive_reset_simulate(drive, xorriso->do_dummy); | if(ret <= 0) | |||
ret= burn_random_access_write(drive, (off_t) 0, head_buffer, to_write, 1); | return(ret); | |||
if(ret<=0) { | ||||
Xorriso_process_msg_queues(xorriso,0); | ||||
sprintf(xorriso->info_text, | ||||
"Cannot write new ISO image head to LBA 0"); | ||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); | ||||
return(0); | ||||
} | ||||
} | } | |||
if(flag & 4) { | if(flag & 4) { | |||
sprintf(xorriso->info_text, | sprintf(xorriso->info_text, | |||
"Overwrote LBA 0 to 31 by 64 KiB from LBA %d", iso_lba); | "Overwrote LBA 0 to 31 by 64 KiB from LBA %d", iso_lba); | |||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); | Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); | |||
} | } | |||
return(1); | 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, | ||||
int iso_lba, int 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, | ||||
int iso_lba, int iso_size, | ||||
int checksum_block, int 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; | ||||
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, 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, old_size, i, vd_end, checksum_block= -1; | ||||
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(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_lba= 0, iso_session, iso_track, iso_size= 0, image_start_mode= 0; | ||||
int old_size, new_size, blocks, was_indev= 0, checksum_block= 0, vd_end; | ||||
int readable_blocks; | ||||
char image_start_value[81], *head_buffer= NULL, iso_volid[33]; | ||||
char *sb_buffer= 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); | ||||
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(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"); | ||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); | ||||
goto ex; | ||||
} | ||||
/* 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= isoburn_get_mount_params(drive, image_start_mode, image_start_value, | ||||
&iso_lba, &iso_track, &iso_session, iso_volid, | ||||
0); | ||||
if(ret <= 0) | ||||
goto ex; | ||||
if(ret != 1) { | ||||
sprintf(xorriso->info_text, | ||||
"-truncate_overwritable: Given address does not lead to ISO 9660 Volume Desc | ||||
riptor"); | ||||
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(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 tha | ||||
n 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(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 */ | ||||
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); | ||||
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(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 Xorriso_set_system_area_path(struct XorrisO *xorriso, char *path, int flag) | |||
{ | { | |||
int ret; | int ret; | |||
char *eff_src= NULL, *intvl; | char *eff_src= NULL, *intvl; | |||
struct iso_interval_reader *ivr= NULL; | struct iso_interval_reader *ivr= NULL; | |||
off_t byte_count; | off_t byte_count; | |||
IsoImage *img= NULL; | IsoImage *img= NULL; | |||
struct burn_drive_info *source_dinfo; | struct burn_drive_info *source_dinfo; | |||
struct burn_drive *source_drive; | struct burn_drive *source_drive; | |||
End of changes. 17 change blocks. | ||||
36 lines changed or deleted | 658 lines changed or added |