Re: PATCH - Optimization to isomd5sum media check

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

 



On 3/25/05, Luciano Miguel Ferreira Rocha <strange@xxxxxxxxxxxxx> wrote:
> I like it! Just one question: why aren't you using the intermediate
> values of the full MD5?

I've worked with this a little more, taking Luciano's suggestion to
use the running context rather than maintaining a separate fragmd5ctx.
 I have it working (attached), but there's a side effect of doing it
this way.

This version calls MD5_Final() on the md5ctx variable periodically (I
assume that's what you meant--that's the only way I can see to
actually extract a sum string out of a context variable).  Each call
to this function will fill a string with an md5 sum, but it also
modifies the md5ctx value in the process.  This ultimately results in
a different md5 sum of the whole disc when compared to the original
method where MD5_Final() is only called at the very end of the
computing.

Thus, a certain degree of backward compatibility is lost, and I do not
like this patch as much as my original patch.  That is, if you implant
the data in an ISO using the patch attached, the main md5sum implanted
is different, and thus if you checked this ISO with an old version of
checkisomd5 it would fail the disk.  On the other hand, the previous
patch I attached is both backward and forward compatible, at the
expense of an extra variable, a couple of lines of code, and a few
additional calculations.

If anyone has a cleaner way to do this, please let me know and I'll
rework this.  But at this time, I recommend my original patch (not the
one attached).

Dustin
diff -Naur anaconda-10.1.0.2/isomd5sum/libcheckisomd5.c anaconda-10.1.0.2.dustin.2/isomd5sum/libcheckisomd5.c
--- anaconda-10.1.0.2/isomd5sum/libcheckisomd5.c	2005-03-25 13:42:57.000000000 -0500
+++ anaconda-10.1.0.2.dustin.2/isomd5sum/libcheckisomd5.c	2005-04-13 20:04:14.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;                */
+/*	Exit 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,25 @@
 /* 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;
     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;
+    char fragmentsums[FRAGMENT_SUM_LENGTH];
+    char thisfragsum[FRAGMENT_SUM_LENGTH];
+    long long fragmentcount = 0;
     MD5_CTX md5ctx;
 
-    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); */
@@ -178,7 +226,31 @@
 	    memset(buf+appdata_start_offset, ' ', len);
 	}
 
+	/* update overall md5ctx */
 	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 ) {
+                MD5_Final(fragmd5sum, &md5ctx);
+                *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';
+                /*  printf("\nFragment [%i]: %s ?= %s\n", previous_fragment, computedsum, thisfragsum);   */
+                previous_fragment = current_fragment;
+                /* Exit immediatiately if current fragment sum is incorrect */
+                if (strcmp(thisfragsum, computedsum) != 0) {
+                    free(buf);
+                    return 0;
+                }
+            }
+        }
 	offset = offset + nread;
 	
 	if (!quiet) {
@@ -201,7 +273,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 +282,7 @@
 	return 0;
     else
 	return 1;
-    }
+}
 
 
 #if 0
@@ -233,8 +305,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 +364,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 +376,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 +388,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 -Naur anaconda-10.1.0.2/isomd5sum/libimplantisomd5.c anaconda-10.1.0.2.dustin.2/isomd5sum/libimplantisomd5.c
--- anaconda-10.1.0.2/isomd5sum/libimplantisomd5.c	2005-03-25 09:34:34.000000000 -0500
+++ anaconda-10.1.0.2.dustin.2/isomd5sum/libimplantisomd5.c	2005-04-13 20:04:42.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;                */
+/*	Exit media check as soon as 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,14 +97,20 @@
     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];
+    char fragstr[FRAGMENT_SUM_LENGTH+1];
     MD5_CTX md5ctx;
 
     isofd = open(fname, O_RDWR);
@@ -138,18 +154,37 @@
     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 ) {
+            MD5_Final(fragmd5sum, &md5ctx);
+            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 +192,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 +209,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 +228,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