Re: PATCH - Optimization to isomd5sum media check

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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);

[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux