home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / OPENSTEP / UNIX / Utilities / rsync-1.6.3-MIH / src / checksum.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-11  |  4.0 KB  |  195 lines

  1. /* 
  2.    Copyright (C) Andrew Tridgell 1996
  3.    Copyright (C) Paul Mackerras 1996
  4.    
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2 of the License, or
  8.    (at your option) any later version.
  9.    
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.    
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. #include "rsync.h"
  21.  
  22. int csum_length=2; /* initial value */
  23.  
  24. #define CSUM_CHUNK 64
  25.  
  26. int checksum_seed = 0;
  27. extern int remote_version;
  28.  
  29. /*
  30.   a simple 32 bit checksum that can be upadted from either end
  31.   (inspired by Mark Adler's Adler-32 checksum)
  32.   */
  33. uint32 get_checksum1(char *buf,int len)
  34. {
  35.     int i;
  36.     uint32 s1, s2;
  37.  
  38.     s1 = s2 = 0;
  39.     for (i = 0; i < (len-4); i+=4) {
  40.     s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3] + 
  41.       10*CHAR_OFFSET;
  42.     s1 += (buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3] + 4*CHAR_OFFSET); 
  43.     }
  44.     for (; i < len; i++) {
  45.     s1 += (buf[i]+CHAR_OFFSET); s2 += s1;
  46.     }
  47.     return (s1 & 0xffff) + (s2 << 16);
  48. }
  49.  
  50.  
  51. static void sum_put(MDstruct *md,char *sum)
  52. {
  53.   SIVAL(sum,0,md->buffer[0]);
  54.   if (csum_length <= 4) return;
  55.   SIVAL(sum,4,md->buffer[1]);
  56.   if (csum_length <= 8) return;
  57.   SIVAL(sum,8,md->buffer[2]);
  58.   if (csum_length <= 12) return;
  59.   SIVAL(sum,12,md->buffer[3]);
  60. }
  61.  
  62.  
  63. void get_checksum2(char *buf,int len,char *sum)
  64. {
  65.   int i;
  66.   MDstruct MD;
  67.   static char *buf1 = NULL;
  68.   static int len1 = 0;
  69.  
  70.   if (len > len1) {
  71.     if (buf1) free(buf1);
  72.     buf1 = (char *)malloc(len+4);
  73.     len1 = len;
  74.     if (!buf1) out_of_memory("get_checksum2");
  75.   }
  76.  
  77.   MDbegin(&MD);
  78.  
  79.   bcopy(buf,buf1,len);
  80.   if (checksum_seed) {
  81.     SIVAL(buf1,len,checksum_seed);
  82.     len += 4;
  83.   }
  84.  
  85.   for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
  86.     MDupdate(&MD, buf1+i, CSUM_CHUNK*8);
  87.   }
  88.   if (len - i > 0)
  89.     MDupdate(&MD, buf1+i, (len-i)*8);
  90.  
  91.   sum_put(&MD,sum);
  92. }
  93.  
  94.  
  95. void file_checksum(char *fname,char *sum,off_t size)
  96. {
  97.   int i;
  98.   MDstruct MD;
  99.   struct map_struct *buf;
  100.   int fd;
  101.   int len = size;
  102.   char tmpchunk[CSUM_CHUNK];
  103.  
  104.   bzero(sum,csum_length);
  105.  
  106.   fd = open(fname,O_RDONLY);
  107.   if (fd == -1) return;
  108.  
  109.   buf = map_file(fd,size);
  110.  
  111.   MDbegin(&MD);
  112.  
  113.   for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
  114.     bcopy(map_ptr(buf,i,CSUM_CHUNK),tmpchunk,CSUM_CHUNK);
  115.     MDupdate(&MD, tmpchunk, CSUM_CHUNK*8);
  116.   }
  117.  
  118.   if (len - i > 0) {
  119.     bcopy(map_ptr(buf,i,len-i),tmpchunk,len-i);
  120.     MDupdate(&MD, tmpchunk, (len-i)*8);
  121.   }
  122.  
  123.   sum_put(&MD,sum);
  124.  
  125.   close(fd);
  126.   unmap_file(buf);
  127. }
  128.  
  129.  
  130. void checksum_init(void)
  131. {
  132.   if (remote_version >= 14)
  133.     csum_length = 2; /* adaptive */
  134.   else
  135.     csum_length = SUM_LENGTH;
  136. }
  137.  
  138.  
  139.  
  140. static MDstruct sumMD;
  141. static int sumresidue;
  142. static char sumrbuf[CSUM_CHUNK];
  143.  
  144. void sum_init(void)
  145. {
  146.   char s[4];
  147.   MDbegin(&sumMD);  
  148.   sumresidue=0;
  149.   SIVAL(s,0,checksum_seed);
  150.   sum_update(s,4);
  151. }
  152.  
  153. void sum_update(char *p,int len)
  154. {
  155.   int i;
  156.   if (len + sumresidue < CSUM_CHUNK) {
  157.     bcopy(p,sumrbuf+sumresidue,len);
  158.     sumresidue += len;
  159.     return;
  160.   }
  161.  
  162.   if (sumresidue) {
  163.     i = MIN(CSUM_CHUNK-sumresidue,len);
  164.     bcopy(p,sumrbuf+sumresidue,i);
  165.     MDupdate(&sumMD, sumrbuf, (i+sumresidue)*8);
  166.     len -= i;
  167.     p += i;
  168.   }
  169.  
  170.   for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
  171.     bcopy(p+i,sumrbuf,CSUM_CHUNK);
  172.     MDupdate(&sumMD, sumrbuf, CSUM_CHUNK*8);
  173.   }
  174.  
  175.   if (len - i > 0) {
  176.     sumresidue = len-i;
  177.     bcopy(p+i,sumrbuf,sumresidue);
  178.   } else {
  179.     sumresidue = 0;    
  180.   }
  181. }
  182.  
  183. void sum_end(char *sum)
  184. {
  185.   if (sumresidue)
  186.     MDupdate(&sumMD, sumrbuf, sumresidue*8);
  187.  
  188.   SIVAL(sum,0,sumMD.buffer[0]);
  189.   SIVAL(sum,4,sumMD.buffer[1]);
  190.   SIVAL(sum,8,sumMD.buffer[2]);
  191.   SIVAL(sum,12,sumMD.buffer[3]);  
  192. }
  193.  
  194.  
  195.