Re: PATCH - Optimization to isomd5sum media check

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

 



On 4/15/05, Peter Jones <pjones@xxxxxxxxxx> wrote:
> On Fri, 2005-04-15 at 17:03 +0100, Luciano Miguel Ferreira Rocha wrote:
> 
> > One option is to create a copy of the md5ctx and do the MD5_Final on
> > that one.
> 
> Just having another context structure and copying the data with memcpy
> should get another perfectly valid context to run MD5_Final on.

Ok, you're both very right...  And this fully well addresses all of
the concerns I mentioned in the previous email.  This was quite
simple, I'm sorry I missed.  Basically, two instances of:

            memcpy(&fragmd5ctx, &md5ctx, sizeof(MD5_CTX));
            MD5_Final(fragmd5sum, &fragmd5ctx);

Thus, we can continuously overwrite fragmd5ctx and never actually do
the MD5_Final() on md5ctx until the very end.

So here's the third revision...  


Dustin
--- anaconda-10.1.0.2/isomd5sum/libcheckisomd5.c	2005-04-19 15:34:15.000000000 -0400
+++ anaconda-10.1.0.2.dustin/isomd5sum/libcheckisomd5.c	2005-04-19 16:10:03.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,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;
-    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,6 +227,30 @@
 	}
 
 	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';
+                /*  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); 
+    }
 }

[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