diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index 21079486..7f6d670b 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -2,7 +2,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH XORRISO 1 "Aug 12, 2009" +.TH XORRISO 1 "Aug 14, 2009" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -758,8 +758,8 @@ each single data file. If enabled then MD5 checksums get loaded from the image if there are any. At image generation time they are computed for each file which gets its data written into the new session. The checksums of files which have their data in older sessions get copied into the new session. -Checksums can be exploited via options -check_md5, -check_md5_r, and via find -actions get_md5, check_md5. +Checksums can be exploited via options -check_md5, -check_md5_r, via find +actions get_md5, check_md5, and via -check_media. .TP \fB\-rom_toc_scan\fR "on"|"off"[:"emul_on"|"emul_off"] Read-only drives do not tell the actual media type but show any media as @@ -2548,9 +2548,16 @@ description of options. .br The result list tells intervals of 2 KiB blocks with start address, number of blocks and quality. Qualities which begin with "+" are -supposed to be valid readable data. Qualities with "-" are no valid data. +supposed to be valid readable data. Qualities with "-" are unreadable or +corrupted data. +"0" indicates qualities which are covered by the check run or are regularly +allowed to to be unreadable (e.g. gaps between tracks). .br Alternatively it is possible to report damaged files rather than blocks. +.br +If -md5 is on then the default mode what=tracks looks out for libisofs +checksum tags for the ISO session data and and eventually checks them +against the checksums computed from the data stream. .TP \fB\-check_media_defaults\fR [option [option ...]] -- Preset options for runs of -check_media, -extract_cut and best_effort diff --git a/xorriso/xorriso.c b/xorriso/xorriso.c index 8aeb1f3b..953e7ad9 100644 --- a/xorriso/xorriso.c +++ b/xorriso/xorriso.c @@ -4199,9 +4199,9 @@ int Spotlist_get_item(struct SpotlisT *o, int idx, if(idx < 0 || idx > o->list_count) return(0); - if(idx == o->current_idx) + if(idx == o->current_idx && o->current_item != NULL) li= o->current_item; - else if(idx == o->current_idx) { + else if(idx == o->current_idx + 1 && o->current_item != NULL) { li= o->current_item->next; } else { li= o->list_start; @@ -4221,6 +4221,8 @@ char *Spotlist__quality_name(int quality, char name[80], int flag) { if(quality == Xorriso_read_quality_gooD) strcpy(name, "+ good"); + else if(quality == Xorriso_read_quality_md5_matcH) + strcpy(name, "+ md5_match"); else if(quality == Xorriso_read_quality_sloW) strcpy(name, "+ slow"); else if(quality == Xorriso_read_quality_partiaL) @@ -4232,9 +4234,11 @@ char *Spotlist__quality_name(int quality, char name[80], int flag) else if(quality == Xorriso_read_quality_invaliD) strcpy(name, "- invalid"); else if(quality == Xorriso_read_quality_tao_enD) - strcpy(name, "- tao end"); + strcpy(name, "0 tao end"); else if(quality == Xorriso_read_quality_off_tracK) - strcpy(name, "- off track"); + strcpy(name, "0 off track"); + else if(quality == Xorriso_read_quality_md5_mismatcH) + strcpy(name, "- md5_mismatch"); else if(quality == Xorriso_read_quality_unreadablE) strcpy(name, "- unreadable"); else @@ -11589,7 +11593,7 @@ int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso, struct SectorbitmaP *m; int map_sectors= -1, map_sector_size= -1; int list_sectors, list_blocks, sector_size, sector_blocks; - int replace_map= 0, count, i, lba, blocks, quality, ret; + int replace_map= 0, count, i, lba, blocks, quality, ret, pass; sector_size= Spotlist_sector_size(spotlist, read_chunk, 0); sector_blocks= sector_size / 2048; @@ -11629,14 +11633,21 @@ int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso, } count= Spotlist_count(spotlist, 0); - for(i= 0; i < count; i++) { - ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0); - if(ret <= 0) - continue; - if(quality == Xorriso_read_quality_untesteD && !(flag & 1)) - continue; - Sectorbitmap_set_range(m, lba / sector_blocks, blocks / sector_blocks, - quality >= Xorriso_read_quality_untesteD); + /* first set good bits, then eventueally override by bad bits */ + for(pass= 0; pass < 2; pass++) { + for(i= 0; i < count; i++) { + ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0); + if(ret <= 0) + continue; + if(quality == Xorriso_read_quality_untesteD && !(flag & 1)) + continue; + if(pass == 0 && quality < Xorriso_read_quality_untesteD) + continue; + else if(pass == 1 && quality >= Xorriso_read_quality_untesteD) + continue; + Sectorbitmap_set_range(m, lba / sector_blocks, blocks / sector_blocks, + quality >= Xorriso_read_quality_untesteD); + } } if(replace_map) { Sectorbitmap_destroy(map, 0); @@ -13346,13 +13357,13 @@ int Xorriso_option_charset(struct XorrisO *xorriso, char *name, int flag) /* Options -check_md5 and -check_md5_r @param flag bit0= issue summary message bit1= do not reset pacifier, no final pacifier message - bit2= do not issue pacifier messages at all + >>> bit2= do not issue pacifier messages at all bit3= recursive: -check_md5_r */ int Xorriso_option_check_md5(struct XorrisO *xorriso, int argc, char **argv, int *idx, int flag) { - int ret, i, mem_pci, end_idx, fret, sev; + int ret, i, mem_pci, end_idx, fret, sev, do_report= 0; int optc= 0; char **optv= NULL, *cpt, *severity; struct FindjoB *job= NULL; @@ -13388,7 +13399,7 @@ int Xorriso_option_check_md5(struct XorrisO *xorriso, ret= -1; goto ex; } - if(!(flag&2)) { + if(!(flag & (2 | 4))) { Xorriso_pacifier_reset(xorriso, 0); mem_lut= xorriso->last_update_time; } @@ -13399,6 +13410,7 @@ int Xorriso_option_check_md5(struct XorrisO *xorriso, if(optc == 0) { ret= Xorriso_check_session_md5(xorriso, severity, 0); + do_report= 1; goto ex; } @@ -13439,14 +13451,35 @@ int Xorriso_option_check_md5(struct XorrisO *xorriso, } ret= 1; - xorriso->pacifier_interval= mem_pci; - if(mem_lut!=xorriso->last_update_time && !(flag&2)) - Xorriso_pacifier_callback(xorriso, "content bytes read", - xorriso->pacifier_count, 0, "", 1); report_outcome:; - Xorriso_report_md5_outcome(xorriso, severity, 0); + do_report= 1; ex:; + if(!(flag & (2 | 4))) { + xorriso->pacifier_interval= mem_pci; + if(mem_lut!=xorriso->last_update_time && !(flag&2)) + Xorriso_pacifier_callback(xorriso, "content bytes read", + xorriso->pacifier_count, 0, "", 1); + } + if(do_report) { + if(optc == 0) { + if(ret <= 0) { + sprintf(xorriso->result_line, + "MD5 MISMATCH WITH DATA OF LOADED SESSION !\n"); + Xorriso_result(xorriso,0); + if(strcmp(severity, "ALL") != 0) { + sprintf(xorriso->info_text, + "Event triggered by MD5 comparison mismatch"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, severity, 0); + } + } else { + sprintf(xorriso->result_line, "Ok, session data match recorded md5.\n"); + Xorriso_result(xorriso,0); + } + } else { + Xorriso_report_md5_outcome(xorriso, severity, 0); + } + } (*idx)= end_idx; Xorriso_opt_args(xorriso, "-getfacl", argc, argv, *idx, &end_idx, &optc, &optv, 256); @@ -13461,7 +13494,7 @@ ex:; int Xorriso_option_check_media(struct XorrisO *xorriso, int argc, char **argv, int *idx, int flag) { - int ret, i, count, lba, blocks, quality; + int ret, i, count, lba, blocks, quality, pass, was_md5= 0; int end_idx, old_idx, os_errno; char quality_name[80], head_buffer[64*1024]; struct SpotlisT *spotlist= NULL; @@ -13536,17 +13569,35 @@ int Xorriso_option_check_media(struct XorrisO *xorriso, } if(job->report_mode == 0 || job->report_mode == 2) { /* report blocks */ - sprintf(xorriso->result_line, - "MCL layout : lba , size , quality\n"); - Xorriso_result(xorriso,0); - count= Spotlist_count(spotlist, 0); - for(i= 0; i < count; i++) { - ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0); - if(ret <= 0) - continue; - sprintf(xorriso->result_line, "MCL item : %10d , %10d , %s\n", - lba, blocks, Spotlist__quality_name(quality, quality_name, 0)); + for(pass= 0; pass < 2; pass++) { + if(pass == 0) { + sprintf(xorriso->result_line, + "Media checks : lba , size , quality\n"); + } else { + if(!was_md5) + break; + sprintf(xorriso->result_line, + "MD5 checks : lba , size , result\n"); + } Xorriso_result(xorriso,0); + count= Spotlist_count(spotlist, 0); + for(i= 0; i < count; i++) { + ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0); + if(ret <= 0) + continue; + if(pass == 0 && (quality == Xorriso_read_quality_md5_matcH || + quality == Xorriso_read_quality_md5_mismatcH)) { + was_md5= 1; + continue; + } + else if(pass == 1 && !(quality == Xorriso_read_quality_md5_matcH || + quality == Xorriso_read_quality_md5_mismatcH)) + continue; + sprintf(xorriso->result_line, "%s: %10d , %10d , %s\n", + pass == 0 ? "Media region " : "MD5 tag range", + lba, blocks, Spotlist__quality_name(quality, quality_name, 0)); + Xorriso_result(xorriso,0); + } } } if(job->report_mode == 1 || job->report_mode == 2) { /* report files */ diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 87402f4f..9094bbb8 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2009.08.14.102355" +#define Xorriso_timestamP "2009.08.14.211648" diff --git a/xorriso/xorrisoburn.c b/xorriso/xorrisoburn.c index 07fef584..3de1e3d6 100644 --- a/xorriso/xorrisoburn.c +++ b/xorriso/xorrisoburn.c @@ -9195,14 +9195,15 @@ int Xorriso_msinfo(struct XorrisO *xorriso, int *msc1, int *msc2, int flag) /* @param flag bit0= this is a follow-up session (i.e. on CD: TAO) bit1= no pacifier messages + bit2= compute stream MD5 and look out for checksum tag @return <=0 error, 1= done, 2= aborted due to limit */ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist, struct CheckmediajoB *job, int from_lba, int block_count, int read_chunk, - int flag) + int md5_start, int flag) { - int i, j, ret, total_count= 0, sectors= -1, sector_size= -1, skip_reading; + int i, j, k, ret, total_count= 0, sectors= -1, sector_size= -1, skip_reading; int prev_quality= -1, quality= -1, retry= 0, profile_no, is_cd= 0; int start_sec, end_sec, first_value, fret; char profile_name[80]; @@ -9214,6 +9215,9 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist, double pre_read_time, post_read_time, time_diff, total_time_diff= 0; double last_abort_file_time= 0; struct stat stbuf; + void *ctx= NULL; + char md5[16], tag_md5[16]; + uint32_t pos, range_start, range_size; ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to check media readability", @@ -9235,6 +9239,14 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist, else if(job->retry == 0 && is_cd) retry= 1; + if(flag & 4) { + ret= iso_md5_start(&ctx); + if(ret < 0) { + Xorriso_no_malloc_memory(xorriso, NULL, 0); + ret= -1; goto ex; + } + } + start_lba= from_lba; to_read= read_chunk; post_read_time= Sfile_microtime(0); @@ -9364,6 +9376,54 @@ abort_check:; quality= Xorriso_read_quality_sloW; } + if(ctx != NULL) { + for(j= 0; j < to_read; j++) { + ret= iso_util_decode_md5_tag(data + j * 2048, &pos, &range_start, + &range_size, tag_md5, 0); + if(ret == 1 && pos == i + j + from_lba) { + if(range_start != md5_start) { + sprintf(xorriso->info_text, + "Found MD5 checksum tag which covers different data range"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0); + sprintf(xorriso->info_text, + " Expected: %u Found: %u", + (unsigned int) md5_start, range_start); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0); + } else { + iso_md5_end(&ctx, md5); + for(k= 0; k < 16; k++) + if(tag_md5[k] != md5[k]) + break; + if(k < 16 ) { + ret= Spotlist_add_item(spotlist, md5_start, + i + j + from_lba - md5_start, + Xorriso_read_quality_md5_mismatcH, 0); + sprintf(xorriso->info_text, + "Found NON-MATCHING MD5 checksum tag: start=%d size=%d", + md5_start, i + j + from_lba - md5_start); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, + "WARNING", 0); + } else { + ret= Spotlist_add_item(spotlist, md5_start, + i + j + from_lba - md5_start, + Xorriso_read_quality_md5_matcH, 0); + sprintf(xorriso->info_text, + "Found matching MD5 checksum tag: start=%d size=%d", + md5_start, i + j + from_lba - md5_start); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", + 0); + } + } + } else { + + /* >>> ??? warn if ret == ISO_MD5_AREA_CORRUPTED */; + + if(from_lba + i + j >= md5_start) + iso_md5_compute(ctx, data + j * 2048, 2048); + } + } + } + write_amount= data_count; if(data_count > 0) { read_count+= data_count; @@ -9424,6 +9484,8 @@ failed_to_write:; ret= 1; ex: + if(ctx != NULL) + iso_md5_end(&ctx, md5); return(ret); } @@ -9433,7 +9495,7 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, { int media_blocks= 0, read_chunk= 16, ret, mode, start_lba= 0; int blocks, os_errno, i, j, last_track_end= -1, track_blocks, track_lba; - int num_sessions, num_tracks, declare_untested= 0; + int num_sessions, num_tracks, declare_untested= 0, md5_start; char *toc_info= NULL; struct burn_drive *drive; struct burn_drive_info *dinfo; @@ -9492,7 +9554,7 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, blocks= job->max_lba + 1 - start_lba; xorriso->pacifier_total= blocks; ret= Xorriso_check_interval(xorriso, *spotlist, job, start_lba, blocks, - read_chunk, 0); + read_chunk, 0, 0); if(ret <= 0) goto ex; @@ -9511,6 +9573,7 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, continue; track_lba= isoburn_entry.start_lba; track_blocks= isoburn_entry.track_blocks; + md5_start= track_lba; if(i == 0 && j == 0) { if(track_lba == 32) { ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0); @@ -9547,7 +9610,8 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, goto ex; } else { ret= Xorriso_check_interval(xorriso, *spotlist, job, track_lba, - track_blocks, read_chunk, i > 0); + track_blocks, read_chunk, md5_start, + (i > 0) | (4 * (xorriso->do_md5 & 1))); if(ret <= 0) goto ex; if(ret == 2) @@ -9572,7 +9636,7 @@ no_content_visible:; goto no_content_visible; xorriso->pacifier_total= blocks; ret= Xorriso_check_interval(xorriso, *spotlist, job, start_lba, blocks, - read_chunk, 0); + read_chunk, 0, 0); if(ret <= 0) goto ex; } else if(mode == 2) { @@ -9701,7 +9765,7 @@ int Xorriso_read_file_data(struct XorrisO *xorriso, IsoNode *node, file_processed_bytes+= ((off_t) count) * (off_t) 2048; ret= Xorriso_check_interval(xorriso, spotlist, job, lba, count, read_chunk, - (flag & 2)); + 0, (flag & 2)); if(ret <= 0) goto ex; if (ret == 2) { @@ -12310,18 +12374,6 @@ int Xorriso_check_session_md5(struct XorrisO *xorriso, char *severity, Xorriso_result(xorriso,0); ret= Xorriso_check_md5_range(xorriso, (off_t) start_lba, (off_t) end_lba, md5, 0); - if(ret <= 0) { - sprintf(xorriso->result_line, - "MD5 MISMATCH WITH DATA OF LOADED SESSION !\n"); - Xorriso_result(xorriso,0); - if(strcmp(severity, "ALL") != 0) { - sprintf(xorriso->info_text, "Event triggered by MD5 comparison mismatch"); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, severity, 0); - } - } else { - sprintf(xorriso->result_line, "Ok, session data match recorded md5.\n"); - Xorriso_result(xorriso,0); - } return(ret); }