Peter, Here's what the output looks like now... The percent complete tally will continue to update itself, plus you'll see a running status of the last fragment tested. <screenshot> [dustin@t23 isomd5sum]$ ./checkisomd5 --verbose test.iso test.iso: 1fca2222a947399d5b4a4226629be254 Fragment sums: 67b6bc7835fc4fa898e1af3d7e58d11f29a776167aa2741aacb45a1762f4 Fragment count: 20 Percent complete: 043.0% Fragment[09/20] -> OK </screenshot> --- When there's a failure, it'll looks something like this: <screenshot>[dustin@t23 isomd5sum]$ ./checkisomd5 --verbose bad.iso bad.iso: 1fca2222a947399d5b4a4226629be254 Fragment sums: 67b6bc7835fc4fa898e1af3d7e58d11f29a776167aa2741aacb45a1762f4 Fragment count: 20 Percent complete: 066.7% Fragment[14/20] -> OK Fragment 15 of 20 is BAD! The supported flag value is 0 The media check is complete, the result is: FAIL. It is not recommended to use this media. </screenshot> Jeremy- A full patch of both files is attached. Dustin
diff -Nuar anaconda-10.1.0.2/isomd5sum/libcheckisomd5.c anaconda-10.1.0.2.dustin/isomd5sum/libcheckisomd5.c --- anaconda-10.1.0.2/isomd5sum/libcheckisomd5.c 2005-04-26 16:12:11.000000000 -0400 +++ anaconda-10.1.0.2.dustin/isomd5sum/libcheckisomd5.c 2005-04-26 16:36:55.000000000 -0400 @@ -1,6 +1,10 @@ /* Copyright 2001 Red Hat, Inc. */ /* Michael Fulbright msf@xxxxxxxxxx */ +/* 4/2005 Dustin Kirkland (dustin.kirkland@xxxxxxxxx) */ +/* Added support for checkpoint fragment sums; */ +/* Exits media check as soon as bad fragment md5sum'ed */ + #include <stdio.h> #include <stdlib.h> #include <sys/types.h> @@ -15,16 +19,20 @@ #define APPDATA_OFFSET 883 #define SIZE_OFFSET 84 +/* Length in characters of string used for fragment md5sum checking */ +#define FRAGMENT_SUM_LENGTH 60 + #define MAX(x, y) ((x > y) ? x : y) #define MIN(x, y) ((x < y) ? x : y) /* finds primary volume descriptor and returns info from it */ /* mediasum must be a preallocated buffer at least 33 bytes long */ -static int parsepvd(int isofd, char *mediasum, int *skipsectors, long long *isosize, int *supported) { +/* fragmentsums must be a preallocated buffer at least FRAGMENT_SUM_LENGTH+1 bytes long */ +static int parsepvd(int isofd, char *mediasum, int *skipsectors, long long *isosize, int *supported, char *fragmentsums, long long *fragmentcount) { unsigned char buf[2048]; unsigned char buf2[512]; unsigned char tmpbuf[512]; - int skipfnd, md5fnd, supportedfnd; + int skipfnd, md5fnd, supportedfnd, fragsumfnd, fragcntfnd; unsigned int loc; long long offset; unsigned char *p; @@ -54,6 +62,8 @@ md5fnd = 0; skipfnd = 0; + fragsumfnd = 0; + fragcntfnd = 0; supportedfnd = 0; loc = 0; while (loc < 512) { @@ -92,14 +102,46 @@ } else if (!strncmp(buf2 + loc, "RHLISOSTATUS=1", 14)) { *supported = 1; supportedfnd = 1; + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); } else if (!strncmp(buf2 + loc, "RHLISOSTATUS=0", 14)) { *supported = 0; supportedfnd = 1; - } else { + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else if (!strncmp(buf2 + loc, "FRAGMENT SUMS = ", 16)) { + /* make sure we dont walk off end */ + if ((loc + FRAGMENT_SUM_LENGTH) > 511) + return -1; + + memcpy(fragmentsums, buf2 + loc + 16, FRAGMENT_SUM_LENGTH); + fragmentsums[FRAGMENT_SUM_LENGTH] = '\0'; + fragsumfnd = 1; + loc += FRAGMENT_SUM_LENGTH + 16; + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else if (!strncmp(buf2 + loc, "FRAGMENT COUNT = ", 17)) { + char *errptr; + /* make sure we dont walk off end */ + if ((loc + 17) > 511) + return -1; + + loc = loc + 17; + for (p=tmpbuf; buf2[loc] != ';' && loc < 512; p++, loc++) + *p = buf2[loc]; + + *p = '\0'; + + *fragmentcount = strtol(tmpbuf, &errptr, 10); + if (errptr && *errptr) { + return -1; + } else { + fragcntfnd = 1; + } + + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else { loc++; } - if ((skipfnd & md5fnd) & supportedfnd) + if ((skipfnd & md5fnd & fragsumfnd & fragcntfnd) & supportedfnd) break; } @@ -119,19 +161,26 @@ /* both strings must be pre-allocated at least 33 chars in length */ static int checkmd5sum(int isofd, char *mediasum, char *computedsum, int quiet) { int nread; - int i; + int i, j; int appdata_start_offset, appdata_end_offset; int nattempt; int skipsectors; int supported; + int current_fragment = 0; + int previous_fragment = 0; + int printed_frag_status = 0; unsigned int bufsize = 32768; unsigned char md5sum[16]; + unsigned char fragmd5sum[16]; unsigned int len; unsigned char *buf; long long isosize, offset, pvd_offset, apoff; - MD5_CTX md5ctx; + char fragmentsums[FRAGMENT_SUM_LENGTH]; + char thisfragsum[FRAGMENT_SUM_LENGTH]; + long long fragmentcount = 0; + MD5_CTX md5ctx, fragmd5ctx; - if ((pvd_offset = parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported)) < 0) + if ((pvd_offset = parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported, fragmentsums, &fragmentcount)) < 0) return -1; /* printf("Mediasum = %s\n",mediasum); */ @@ -179,16 +228,50 @@ } MD5_Update(&md5ctx, buf, nread); + if (fragmentcount) { + current_fragment = offset * (fragmentcount+1) / (isosize - skipsectors*2048); + /* if we're onto the next fragment, calculate the previous sum and check */ + if ( current_fragment != previous_fragment ) { + memcpy(&fragmd5ctx, &md5ctx, sizeof(MD5_CTX)); + MD5_Final(fragmd5sum, &fragmd5ctx); + *computedsum = '\0'; + j = (current_fragment-1)*FRAGMENT_SUM_LENGTH/fragmentcount; + for (i=0; i<FRAGMENT_SUM_LENGTH/fragmentcount; i++) { + char tmpstr[2]; + snprintf(tmpstr, 2, "%01x", fragmd5sum[i]); + strncat(computedsum, tmpstr, 2); + thisfragsum[i] = fragmentsums[j++]; + } + thisfragsum[j] = '\0'; + if (!quiet) { + printf(" Fragment[%02i/%02lld] -> OK", previous_fragment+1, fragmentcount); + printed_frag_status = 1; + fflush(stdout); + } + previous_fragment = current_fragment; + /* Exit immediately if current fragment sum is incorrect */ + if (strcmp(thisfragsum, computedsum) != 0) { + if (!quiet) { + printf("\nFragment %02i of %02lld is BAD!\n", previous_fragment+1, fragmentcount); + } + free(buf); + return 0; + } + } + } offset = offset + nread; - if (!quiet) { + if (printed_frag_status) { + printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); + printed_frag_status = 0; + } printf("\b\b\b\b\b\b%05.1f%%", (100.0*offset)/(isosize-skipsectors*2048.0)); fflush(stdout); } } if (!quiet) { - printf("\b\b\b\b\b\b\n%05.1f\n", (100.0*offset)/(isosize-skipsectors*2048.0)); + printf("\b\b\b\b\b\b\n%05.1f\n", (100.0*offset)/(isosize-skipsectors*2048.0)); } sleep(1); @@ -201,7 +284,7 @@ for (i=0; i<16; i++) { char tmpstr[4]; snprintf (tmpstr, 4, "%02x", md5sum[i]); - strcat(computedsum, tmpstr); + strncat(computedsum, tmpstr, 2); } /* printf("mediasum, computedsum = %s %s\n", mediasum, computedsum); */ @@ -210,7 +293,7 @@ return 0; else return 1; - } +} #if 0 @@ -233,8 +316,10 @@ static int doMediaCheck(int isofd, char *mediasum, char *computedsum, long long *isosize, int *supported, int quiet) { int rc; int skipsectors; + long long fragmentcount = 0; + char fragmentsums[FRAGMENT_SUM_LENGTH+1]; - if (parsepvd(isofd, mediasum, &skipsectors, isosize, supported) < 0) { + if (parsepvd(isofd, mediasum, &skipsectors, isosize, supported, fragmentsums, &fragmentcount) < 0) { fprintf(stderr, "Unable to read the disc checksum from the " "primary volume descriptor.\nThis probably " "means the disc was created without adding the " @@ -290,6 +375,8 @@ int isofd; char mediasum[64]; long long isosize; + char fragmentsums[FRAGMENT_SUM_LENGTH+1]; + long long fragmentcount = 0; int supported; int skipsectors; @@ -300,7 +387,7 @@ exit(1); } - if (parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported) < 0) { + if (parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported, fragmentsums, &fragmentcount) < 0) { fprintf(stderr, "%s: Could not get pvd data", file); fprintf(stderr, "\nUnable to read the disc checksum from the " "primary volume descriptor.\nThis probably " @@ -312,4 +399,8 @@ close(isofd); printf("%s: %s\n", file, mediasum); + if ( (strlen(fragmentsums) > 0) && (fragmentcount > 0) ) { + printf("Fragment sums: %s\n", fragmentsums); + printf("Fragment count: %lld\n", fragmentcount); + } } diff -Nuar anaconda-10.1.0.2/isomd5sum/libimplantisomd5.c anaconda-10.1.0.2.dustin/isomd5sum/libimplantisomd5.c --- anaconda-10.1.0.2/isomd5sum/libimplantisomd5.c 2005-04-19 15:34:15.000000000 -0400 +++ anaconda-10.1.0.2.dustin/isomd5sum/libimplantisomd5.c 2005-04-19 16:11:05.000000000 -0400 @@ -1,6 +1,10 @@ /* Copyright 2001 Red Hat, Inc. */ /* Michael Fulbright msf@xxxxxxxxxx */ +/* 4/2005 Dustin Kirkland (dustin.kirkland@xxxxxxxxx) */ +/* Added support for checkpoint fragment sums; */ +/* Allows for exiting media check when bad fragment md5sum'ed */ + #include <stdio.h> #include <stdlib.h> #include <sys/types.h> @@ -15,6 +19,12 @@ #define APPDATA_OFFSET 883 #define SIZE_OFFSET 84 +/* Length in characters of string used for fragment md5sum checking */ +#define FRAGMENT_SUM_LENGTH 60 +/* FRAGMENT_COUNT must be an integral divisor or FRAGMENT_SUM_LENGTH */ +/* 60 => 2, 3, 4, 5, 6, 10, 12, 15, 20, or 30 */ +#define FRAGMENT_COUNT 20 + /* number of sectors to ignore at end of iso when computing sum */ #define SKIPSECTORS 15 @@ -87,15 +97,21 @@ int nread; int dirty; int pvd_offset; + int current_fragment = 0; + int previous_fragment = 0; + int nattempt; long long isosize, total; unsigned char md5sum[16]; + unsigned char fragmd5sum[16]; unsigned int loc; - unsigned char buf[2048]; + unsigned int bufsize = 32768; + unsigned char *buf; unsigned char orig_appdata[512]; unsigned char new_appdata[512]; unsigned char mediasum[33]; char md5str[40]; - MD5_CTX md5ctx; + char fragstr[FRAGMENT_SUM_LENGTH+1]; + MD5_CTX md5ctx, fragmd5ctx; isofd = open(fname, O_RDWR); @@ -138,18 +154,38 @@ lseek(isofd, 0L, SEEK_SET); MD5_Init(&md5ctx); + *fragstr = '\0'; + buf = malloc(bufsize * sizeof(unsigned char)); total = 0; /* read up to 15 sectors from end, due to problems reading last few */ /* sectors on burned CDs */ while (total < isosize - SKIPSECTORS*2048) { - nread = read(isofd, buf, 2048); + nattempt = MIN(isosize - SKIPSECTORS*2048 - total, bufsize); + nread = read(isofd, buf, nattempt); + if (nread <= 0) break; - + MD5_Update(&md5ctx, buf, nread); + + /* if we're onto the next fragment, calculate the previous sum and write */ + current_fragment = total * (FRAGMENT_COUNT+1) / (isosize - SKIPSECTORS*2048); + if ( current_fragment != previous_fragment ) { + memcpy(&fragmd5ctx, &md5ctx, sizeof(MD5_CTX)); + MD5_Final(fragmd5sum, &fragmd5ctx); + for (i=0; i<FRAGMENT_SUM_LENGTH/FRAGMENT_COUNT; i++) { + char tmpstr[2]; + snprintf(tmpstr, 2, "%01x", fragmd5sum[i]); + strncat(fragstr, tmpstr, 2); + } + /* printf("\nFragment [%i]: %s\n", previous_fragment, fragstr); */ + previous_fragment = current_fragment; + } + total = total + nread; } + free(buf); MD5_Final(md5sum, &md5ctx); @@ -157,12 +193,15 @@ for (i=0; i<16; i++) { char tmpstr[4]; snprintf (tmpstr, 4, "%02x", md5sum[i]); - strcat(md5str, tmpstr); + strncat(md5str, tmpstr, 2); } if (!quiet) { printf("Inserting md5sum into iso image...\n"); printf("md5 = %s\n", md5str); + printf("Inserting fragment md5sums into iso image...\n"); + printf("fragmd5 = %s\n", fragstr); + printf("frags = %d\n", FRAGMENT_COUNT); } /* memcpy(new_appdata, orig_appdata, 512); */ memset(new_appdata, ' ', 512); @@ -171,9 +210,12 @@ loc = writeAppData(new_appdata, "ISO MD5SUM = ", loc); loc = writeAppData(new_appdata, md5str, loc); loc = writeAppData(new_appdata, ";", loc); - snprintf(buf, sizeof(buf), "SKIPSECTORS = %d", SKIPSECTORS); + + buf = malloc(512 * sizeof(unsigned char)); + snprintf(buf, 512, "SKIPSECTORS = %d", SKIPSECTORS); loc = writeAppData(new_appdata, buf, loc); loc = writeAppData(new_appdata, ";", loc); + free(buf); if (supported) { if (!quiet) @@ -187,6 +229,16 @@ loc = writeAppData(new_appdata, ";", loc); + loc = writeAppData(new_appdata, "FRAGMENT SUMS = ", loc); + loc = writeAppData(new_appdata, fragstr, loc); + loc = writeAppData(new_appdata, ";", loc); + + buf = malloc(512 * sizeof(unsigned char)); + snprintf(buf, 512, "FRAGMENT COUNT = %d", FRAGMENT_COUNT); + loc = writeAppData(new_appdata, buf, loc); + loc = writeAppData(new_appdata, ";", loc); + free(buf); + loc = writeAppData(new_appdata, "THIS IS NOT THE SAME AS RUNNING MD5SUM ON THIS ISO!!", loc); i = lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET);