checksum.c

説明を見る。
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 extern int checksum_seed;
00027 extern int protocol_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, int32 len)
00034 {
00035     int32 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, int32 len, char *sum)
00053 {
00054         int32 i;
00055         static char *buf1;
00056         static int32 len1;
00057         struct mdfour m;
00058 
00059         if (len > len1) {
00060                 if (buf1)
00061                         free(buf1);
00062                 buf1 = new_array(char, len+4);
00063                 len1 = len;
00064                 if (!buf1)
00065                         out_of_memory("get_checksum2");
00066         }
00067 
00068         mdfour_begin(&m);
00069 
00070         memcpy(buf1,buf,len);
00071         if (checksum_seed) {
00072                 SIVAL(buf1,len,checksum_seed);
00073                 len += 4;
00074         }
00075 
00076         for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
00077                 mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
00078         }
00079         /*
00080          * Prior to version 27 an incorrect MD4 checksum was computed
00081          * by failing to call mdfour_tail() for block sizes that
00082          * are multiples of 64.  This is fixed by calling mdfour_update()
00083          * even when there are no more bytes.
00084          */
00085         if (len - i > 0 || protocol_version >= 27) {
00086                 mdfour_update(&m, (uchar *)(buf1+i), (len-i));
00087         }
00088 
00089         mdfour_result(&m, (uchar *)sum);
00090 }
00091 
00092 
00093 void file_checksum(char *fname,char *sum,OFF_T size)
00094 {
00095         OFF_T i;
00096         struct map_struct *buf;
00097         int fd;
00098         OFF_T len = size;
00099         struct mdfour m;
00100 
00101         memset(sum,0,MD4_SUM_LENGTH);
00102 
00103         fd = do_open(fname, O_RDONLY, 0);
00104         if (fd == -1)
00105                 return;
00106 
00107         buf = map_file(fd, size, MAX_MAP_SIZE, CSUM_CHUNK);
00108 
00109         mdfour_begin(&m);
00110 
00111         for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
00112                 mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
00113                               CSUM_CHUNK);
00114         }
00115 
00116         /* Prior to version 27 an incorrect MD4 checksum was computed
00117          * by failing to call mdfour_tail() for block sizes that
00118          * are multiples of 64.  This is fixed by calling mdfour_update()
00119          * even when there are no more bytes. */
00120         if (len - i > 0 || protocol_version >= 27)
00121                 mdfour_update(&m, (uchar *)map_ptr(buf, i, len-i), len-i);
00122 
00123         mdfour_result(&m, (uchar *)sum);
00124 
00125         close(fd);
00126         unmap_file(buf);
00127 }
00128 
00129 
00130 static int32 sumresidue;
00131 static char sumrbuf[CSUM_CHUNK];
00132 static struct mdfour md;
00133 
00134 void sum_init(int seed)
00135 {
00136         char s[4];
00137         mdfour_begin(&md);
00138         sumresidue = 0;
00139         SIVAL(s, 0, 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, int32 len)
00152 {
00153         if (len + sumresidue < CSUM_CHUNK) {
00154                 memcpy(sumrbuf + sumresidue, p, len);
00155                 sumresidue += len;
00156                 return;
00157         }
00158 
00159         if (sumresidue) {
00160                 int32 i = CSUM_CHUNK - sumresidue;
00161                 memcpy(sumrbuf + sumresidue, p, i);
00162                 mdfour_update(&md, (uchar *)sumrbuf, CSUM_CHUNK);
00163                 len -= i;
00164                 p += i;
00165         }
00166 
00167         while (len >= CSUM_CHUNK) {
00168                 mdfour_update(&md, (uchar *)p, CSUM_CHUNK);
00169                 len -= CSUM_CHUNK;
00170                 p += CSUM_CHUNK;
00171         }
00172 
00173         sumresidue = len;
00174         if (sumresidue)
00175                 memcpy(sumrbuf, p, sumresidue);
00176 }
00177 
00178 void sum_end(char *sum)
00179 {
00180         if (sumresidue || protocol_version >= 27)
00181                 mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
00182 
00183         mdfour_result(&md, (uchar *)sum);
00184 }

rsyncに対してSat Dec 5 19:45:40 2009に生成されました。  doxygen 1.4.7