Annotation of embedaddon/rsync/checksum.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Routines to support checksumming of bytes.
        !             3:  *
        !             4:  * Copyright (C) 1996 Andrew Tridgell
        !             5:  * Copyright (C) 1996 Paul Mackerras
        !             6:  * Copyright (C) 2004-2009 Wayne Davison
        !             7:  *
        !             8:  * This program is free software; you can redistribute it and/or modify
        !             9:  * it under the terms of the GNU General Public License as published by
        !            10:  * the Free Software Foundation; either version 3 of the License, or
        !            11:  * (at your option) any later version.
        !            12:  *
        !            13:  * This program is distributed in the hope that it will be useful,
        !            14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            16:  * GNU General Public License for more details.
        !            17:  *
        !            18:  * You should have received a copy of the GNU General Public License along
        !            19:  * with this program; if not, visit the http://fsf.org website.
        !            20:  */
        !            21: 
        !            22: #include "rsync.h"
        !            23: 
        !            24: extern int checksum_seed;
        !            25: extern int protocol_version;
        !            26: 
        !            27: /*
        !            28:   a simple 32 bit checksum that can be upadted from either end
        !            29:   (inspired by Mark Adler's Adler-32 checksum)
        !            30:   */
        !            31: uint32 get_checksum1(char *buf1, int32 len)
        !            32: {
        !            33:     int32 i;
        !            34:     uint32 s1, s2;
        !            35:     schar *buf = (schar *)buf1;
        !            36: 
        !            37:     s1 = s2 = 0;
        !            38:     for (i = 0; i < (len-4); i+=4) {
        !            39:        s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3] +
        !            40:          10*CHAR_OFFSET;
        !            41:        s1 += (buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3] + 4*CHAR_OFFSET);
        !            42:     }
        !            43:     for (; i < len; i++) {
        !            44:        s1 += (buf[i]+CHAR_OFFSET); s2 += s1;
        !            45:     }
        !            46:     return (s1 & 0xffff) + (s2 << 16);
        !            47: }
        !            48: 
        !            49: 
        !            50: void get_checksum2(char *buf, int32 len, char *sum)
        !            51: {
        !            52:        md_context m;
        !            53: 
        !            54:        if (protocol_version >= 30) {
        !            55:                uchar seedbuf[4];
        !            56:                md5_begin(&m);
        !            57:                md5_update(&m, (uchar *)buf, len);
        !            58:                if (checksum_seed) {
        !            59:                        SIVALu(seedbuf, 0, checksum_seed);
        !            60:                        md5_update(&m, seedbuf, 4);
        !            61:                }
        !            62:                md5_result(&m, (uchar *)sum);
        !            63:        } else {
        !            64:                int32 i;
        !            65:                static char *buf1;
        !            66:                static int32 len1;
        !            67: 
        !            68:                mdfour_begin(&m);
        !            69: 
        !            70:                if (len > len1) {
        !            71:                        if (buf1)
        !            72:                                free(buf1);
        !            73:                        buf1 = new_array(char, len+4);
        !            74:                        len1 = len;
        !            75:                        if (!buf1)
        !            76:                                out_of_memory("get_checksum2");
        !            77:                }
        !            78: 
        !            79:                memcpy(buf1, buf, 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:                        mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
        !            87: 
        !            88:                /*
        !            89:                 * Prior to version 27 an incorrect MD4 checksum was computed
        !            90:                 * by failing to call mdfour_tail() for block sizes that
        !            91:                 * are multiples of 64.  This is fixed by calling mdfour_update()
        !            92:                 * even when there are no more bytes.
        !            93:                 */
        !            94:                if (len - i > 0 || protocol_version >= 27)
        !            95:                        mdfour_update(&m, (uchar *)(buf1+i), len-i);
        !            96: 
        !            97:                mdfour_result(&m, (uchar *)sum);
        !            98:        }
        !            99: }
        !           100: 
        !           101: void file_checksum(char *fname, char *sum, OFF_T size)
        !           102: {
        !           103:        struct map_struct *buf;
        !           104:        OFF_T i, len = size;
        !           105:        md_context m;
        !           106:        int32 remainder;
        !           107:        int fd;
        !           108: 
        !           109:        memset(sum, 0, MAX_DIGEST_LEN);
        !           110: 
        !           111:        fd = do_open(fname, O_RDONLY, 0);
        !           112:        if (fd == -1)
        !           113:                return;
        !           114: 
        !           115:        buf = map_file(fd, size, MAX_MAP_SIZE, CSUM_CHUNK);
        !           116: 
        !           117:        if (protocol_version >= 30) {
        !           118:                md5_begin(&m);
        !           119: 
        !           120:                for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
        !           121:                        md5_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
        !           122:                                   CSUM_CHUNK);
        !           123:                }
        !           124: 
        !           125:                remainder = (int32)(len - i);
        !           126:                if (remainder > 0)
        !           127:                        md5_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
        !           128: 
        !           129:                md5_result(&m, (uchar *)sum);
        !           130:        } else {
        !           131:                mdfour_begin(&m);
        !           132: 
        !           133:                for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
        !           134:                        mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
        !           135:                                      CSUM_CHUNK);
        !           136:                }
        !           137: 
        !           138:                /* Prior to version 27 an incorrect MD4 checksum was computed
        !           139:                 * by failing to call mdfour_tail() for block sizes that
        !           140:                 * are multiples of 64.  This is fixed by calling mdfour_update()
        !           141:                 * even when there are no more bytes. */
        !           142:                remainder = (int32)(len - i);
        !           143:                if (remainder > 0 || protocol_version >= 27)
        !           144:                        mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
        !           145: 
        !           146:                mdfour_result(&m, (uchar *)sum);
        !           147:        }
        !           148: 
        !           149:        close(fd);
        !           150:        unmap_file(buf);
        !           151: }
        !           152: 
        !           153: static int32 sumresidue;
        !           154: static md_context md;
        !           155: 
        !           156: void sum_init(int seed)
        !           157: {
        !           158:        char s[4];
        !           159: 
        !           160:        if (protocol_version >= 30)
        !           161:                md5_begin(&md);
        !           162:        else {
        !           163:                mdfour_begin(&md);
        !           164:                sumresidue = 0;
        !           165:                SIVAL(s, 0, seed);
        !           166:                sum_update(s, 4);
        !           167:        }
        !           168: }
        !           169: 
        !           170: /**
        !           171:  * Feed data into an MD4 accumulator, md.  The results may be
        !           172:  * retrieved using sum_end().  md is used for different purposes at
        !           173:  * different points during execution.
        !           174:  *
        !           175:  * @todo Perhaps get rid of md and just pass in the address each time.
        !           176:  * Very slightly clearer and slower.
        !           177:  **/
        !           178: void sum_update(const char *p, int32 len)
        !           179: {
        !           180:        if (protocol_version >= 30) {
        !           181:                md5_update(&md, (uchar *)p, len);
        !           182:                return;
        !           183:        }
        !           184: 
        !           185:        if (len + sumresidue < CSUM_CHUNK) {
        !           186:                memcpy(md.buffer + sumresidue, p, len);
        !           187:                sumresidue += len;
        !           188:                return;
        !           189:        }
        !           190: 
        !           191:        if (sumresidue) {
        !           192:                int32 i = CSUM_CHUNK - sumresidue;
        !           193:                memcpy(md.buffer + sumresidue, p, i);
        !           194:                mdfour_update(&md, (uchar *)md.buffer, CSUM_CHUNK);
        !           195:                len -= i;
        !           196:                p += i;
        !           197:        }
        !           198: 
        !           199:        while (len >= CSUM_CHUNK) {
        !           200:                mdfour_update(&md, (uchar *)p, CSUM_CHUNK);
        !           201:                len -= CSUM_CHUNK;
        !           202:                p += CSUM_CHUNK;
        !           203:        }
        !           204: 
        !           205:        sumresidue = len;
        !           206:        if (sumresidue)
        !           207:                memcpy(md.buffer, p, sumresidue);
        !           208: }
        !           209: 
        !           210: int sum_end(char *sum)
        !           211: {
        !           212:        if (protocol_version >= 30) {
        !           213:                md5_result(&md, (uchar *)sum);
        !           214:                return MD5_DIGEST_LEN;
        !           215:        }
        !           216: 
        !           217:        if (sumresidue || protocol_version >= 27)
        !           218:                mdfour_update(&md, (uchar *)md.buffer, sumresidue);
        !           219: 
        !           220:        mdfour_result(&md, (uchar *)sum);
        !           221: 
        !           222:        return MD4_DIGEST_LEN;
        !           223: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>