Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

checksum.c

Go to the documentation of this file.
00001 /* 
00002    Copyright (C) Andrew Tridgell 1996
00003    Copyright (C) Paul Mackerras 1996
00004    
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2 of the License, or
00008    (at your option) any later version.
00009    
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014    
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 #include "rsync.h"
00021 
00022 int csum_length=2; /* initial value */
00023 
00024 #define CSUM_CHUNK 64
00025 
00026 int checksum_seed = 0;
00027 extern int remote_version;
00028 
00029 /*
00030   a simple 32 bit checksum that can be upadted from either end
00031   (inspired by Mark Adler's Adler-32 checksum)
00032   */
00033 uint32 get_checksum1(char *buf1,int len)
00034 {
00035     int i;
00036     uint32 s1, s2;
00037     schar *buf = (schar *)buf1;
00038 
00039     s1 = s2 = 0;
00040     for (i = 0; i < (len-4); i+=4) {
00041         s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3] + 
00042           10*CHAR_OFFSET;
00043         s1 += (buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3] + 4*CHAR_OFFSET); 
00044     }
00045     for (; i < len; i++) {
00046         s1 += (buf[i]+CHAR_OFFSET); s2 += s1;
00047     }
00048     return (s1 & 0xffff) + (s2 << 16);
00049 }
00050 
00051 
00052 void get_checksum2(char *buf,int len,char *sum)
00053 {
00054         int i;
00055         static char *buf1;
00056         static int len1;
00057         struct mdfour m;
00058 
00059         if (len > len1) {
00060                 if (buf1) free(buf1);
00061                 buf1 = (char *)malloc(len+4);
00062                 len1 = len;
00063                 if (!buf1) out_of_memory("get_checksum2");
00064         }
00065         
00066         mdfour_begin(&m);
00067         
00068         memcpy(buf1,buf,len);
00069         if (checksum_seed) {
00070                 SIVAL(buf1,len,checksum_seed);
00071                 len += 4;
00072         }
00073         
00074         for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
00075                 mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
00076         }
00077         if (len - i > 0) {
00078                 mdfour_update(&m, (uchar *)(buf1+i), (len-i));
00079         }
00080         
00081         mdfour_result(&m, (uchar *)sum);
00082 }
00083 
00084 
00085 void file_checksum(char *fname,char *sum,OFF_T size)
00086 {
00087         OFF_T i;
00088         struct map_struct *buf;
00089         int fd;
00090         OFF_T len = size;
00091         char tmpchunk[CSUM_CHUNK];
00092         struct mdfour m;
00093         
00094         memset(sum,0,MD4_SUM_LENGTH);
00095         
00096         fd = do_open(fname, O_RDONLY, 0);
00097         if (fd == -1) return;
00098         
00099         buf = map_file(fd,size);
00100         
00101         mdfour_begin(&m);
00102 
00103         for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
00104                 memcpy(tmpchunk, map_ptr(buf,i,CSUM_CHUNK), CSUM_CHUNK);
00105                 mdfour_update(&m, (uchar *)tmpchunk, CSUM_CHUNK);
00106         }
00107 
00108         if (len - i > 0) {
00109                 memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
00110                 mdfour_update(&m, (uchar *)tmpchunk, (len-i));
00111         }
00112 
00113         mdfour_result(&m, (uchar *)sum);
00114 
00115         close(fd);
00116         unmap_file(buf);
00117 }
00118 
00119 
00120 void checksum_init(void)
00121 {
00122   if (remote_version >= 14)
00123     csum_length = 2; /* adaptive */
00124   else
00125     csum_length = SUM_LENGTH;
00126 }
00127 
00128 
00129 
00130 static int sumresidue;
00131 static char sumrbuf[CSUM_CHUNK];
00132 static struct mdfour md;
00133 
00134 void sum_init(void)
00135 {
00136         char s[4];
00137         mdfour_begin(&md);
00138         sumresidue=0;
00139         SIVAL(s,0,checksum_seed);
00140         sum_update(s,4);
00141 }
00142 
00143 /**
00144  * Feed data into an MD4 accumulator, md.  The results may be
00145  * retrieved using sum_end().  md is used for different purposes at
00146  * different points during execution.
00147  *
00148  * @todo Perhaps get rid of md and just pass in the address each time.
00149  * Very slightly clearer and slower.
00150  **/
00151 void sum_update(char *p, int len)
00152 {
00153         int i;
00154         if (len + sumresidue < CSUM_CHUNK) {
00155                 memcpy(sumrbuf+sumresidue, p, len);
00156                 sumresidue += len;
00157                 return;
00158         }
00159 
00160         if (sumresidue) {
00161                 i = MIN(CSUM_CHUNK-sumresidue,len);
00162                 memcpy(sumrbuf+sumresidue,p,i);
00163                 mdfour_update(&md, (uchar *)sumrbuf, (i+sumresidue));
00164                 len -= i;
00165                 p += i;
00166         }
00167 
00168         for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
00169                 memcpy(sumrbuf,p+i,CSUM_CHUNK);
00170                 mdfour_update(&md, (uchar *)sumrbuf, CSUM_CHUNK);
00171         }
00172 
00173         if (len - i > 0) {
00174                 sumresidue = len-i;
00175                 memcpy(sumrbuf,p+i,sumresidue);
00176         } else {
00177                 sumresidue = 0;    
00178         }
00179 }
00180 
00181 void sum_end(char *sum)
00182 {
00183         if (sumresidue) {
00184                 mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
00185         }
00186 
00187         mdfour_result(&md, (uchar *)sum);
00188 }

Generated on Tue Apr 16 12:37:36 2002 for rsync by doxygen1.2.15