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

1.1       misho       1: /*
                      2:  * Routines to support checksumming of bytes.
                      3:  *
                      4:  * Copyright (C) 1996 Andrew Tridgell
                      5:  * Copyright (C) 1996 Paul Mackerras
1.1.1.3 ! misho       6:  * Copyright (C) 2004-2015 Wayne Davison
1.1       misho       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;
1.1.1.3 ! misho      26: extern int proper_seed_order;
1.1       misho      27: 
                     28: /*
                     29:   a simple 32 bit checksum that can be upadted from either end
                     30:   (inspired by Mark Adler's Adler-32 checksum)
                     31:   */
                     32: uint32 get_checksum1(char *buf1, int32 len)
                     33: {
                     34:     int32 i;
                     35:     uint32 s1, s2;
                     36:     schar *buf = (schar *)buf1;
                     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: void get_checksum2(char *buf, int32 len, char *sum)
                     52: {
                     53:        md_context m;
                     54: 
                     55:        if (protocol_version >= 30) {
                     56:                uchar seedbuf[4];
                     57:                md5_begin(&m);
1.1.1.3 ! misho      58:                if (proper_seed_order) {
        !            59:                        if (checksum_seed) {
        !            60:                                SIVALu(seedbuf, 0, checksum_seed);
        !            61:                                md5_update(&m, seedbuf, 4);
        !            62:                        }
        !            63:                        md5_update(&m, (uchar *)buf, len);
        !            64:                } else {
        !            65:                        md5_update(&m, (uchar *)buf, len);
        !            66:                        if (checksum_seed) {
        !            67:                                SIVALu(seedbuf, 0, checksum_seed);
        !            68:                                md5_update(&m, seedbuf, 4);
        !            69:                        }
1.1       misho      70:                }
                     71:                md5_result(&m, (uchar *)sum);
                     72:        } else {
                     73:                int32 i;
                     74:                static char *buf1;
                     75:                static int32 len1;
                     76: 
                     77:                mdfour_begin(&m);
                     78: 
                     79:                if (len > len1) {
                     80:                        if (buf1)
                     81:                                free(buf1);
                     82:                        buf1 = new_array(char, len+4);
                     83:                        len1 = len;
                     84:                        if (!buf1)
                     85:                                out_of_memory("get_checksum2");
                     86:                }
                     87: 
                     88:                memcpy(buf1, buf, len);
                     89:                if (checksum_seed) {
                     90:                        SIVAL(buf1,len,checksum_seed);
                     91:                        len += 4;
                     92:                }
                     93: 
                     94:                for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK)
                     95:                        mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
                     96: 
                     97:                /*
                     98:                 * Prior to version 27 an incorrect MD4 checksum was computed
                     99:                 * by failing to call mdfour_tail() for block sizes that
                    100:                 * are multiples of 64.  This is fixed by calling mdfour_update()
                    101:                 * even when there are no more bytes.
                    102:                 */
                    103:                if (len - i > 0 || protocol_version >= 27)
                    104:                        mdfour_update(&m, (uchar *)(buf1+i), len-i);
                    105: 
                    106:                mdfour_result(&m, (uchar *)sum);
                    107:        }
                    108: }
                    109: 
1.1.1.3 ! misho     110: void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
1.1       misho     111: {
                    112:        struct map_struct *buf;
1.1.1.3 ! misho     113:        OFF_T i, len = st_p->st_size;
1.1       misho     114:        md_context m;
                    115:        int32 remainder;
                    116:        int fd;
                    117: 
                    118:        memset(sum, 0, MAX_DIGEST_LEN);
                    119: 
                    120:        fd = do_open(fname, O_RDONLY, 0);
                    121:        if (fd == -1)
                    122:                return;
                    123: 
1.1.1.3 ! misho     124:        buf = map_file(fd, len, MAX_MAP_SIZE, CSUM_CHUNK);
1.1       misho     125: 
                    126:        if (protocol_version >= 30) {
                    127:                md5_begin(&m);
                    128: 
                    129:                for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
                    130:                        md5_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
                    131:                                   CSUM_CHUNK);
                    132:                }
                    133: 
                    134:                remainder = (int32)(len - i);
                    135:                if (remainder > 0)
                    136:                        md5_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
                    137: 
                    138:                md5_result(&m, (uchar *)sum);
                    139:        } else {
                    140:                mdfour_begin(&m);
                    141: 
                    142:                for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
                    143:                        mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
                    144:                                      CSUM_CHUNK);
                    145:                }
                    146: 
                    147:                /* Prior to version 27 an incorrect MD4 checksum was computed
                    148:                 * by failing to call mdfour_tail() for block sizes that
                    149:                 * are multiples of 64.  This is fixed by calling mdfour_update()
                    150:                 * even when there are no more bytes. */
                    151:                remainder = (int32)(len - i);
                    152:                if (remainder > 0 || protocol_version >= 27)
                    153:                        mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
                    154: 
                    155:                mdfour_result(&m, (uchar *)sum);
                    156:        }
                    157: 
                    158:        close(fd);
                    159:        unmap_file(buf);
                    160: }
                    161: 
                    162: static int32 sumresidue;
                    163: static md_context md;
                    164: 
                    165: void sum_init(int seed)
                    166: {
                    167:        char s[4];
                    168: 
                    169:        if (protocol_version >= 30)
                    170:                md5_begin(&md);
                    171:        else {
                    172:                mdfour_begin(&md);
                    173:                sumresidue = 0;
                    174:                SIVAL(s, 0, seed);
                    175:                sum_update(s, 4);
                    176:        }
                    177: }
                    178: 
                    179: /**
                    180:  * Feed data into an MD4 accumulator, md.  The results may be
                    181:  * retrieved using sum_end().  md is used for different purposes at
                    182:  * different points during execution.
                    183:  *
                    184:  * @todo Perhaps get rid of md and just pass in the address each time.
                    185:  * Very slightly clearer and slower.
                    186:  **/
                    187: void sum_update(const char *p, int32 len)
                    188: {
                    189:        if (protocol_version >= 30) {
                    190:                md5_update(&md, (uchar *)p, len);
                    191:                return;
                    192:        }
                    193: 
                    194:        if (len + sumresidue < CSUM_CHUNK) {
                    195:                memcpy(md.buffer + sumresidue, p, len);
                    196:                sumresidue += len;
                    197:                return;
                    198:        }
                    199: 
                    200:        if (sumresidue) {
                    201:                int32 i = CSUM_CHUNK - sumresidue;
                    202:                memcpy(md.buffer + sumresidue, p, i);
                    203:                mdfour_update(&md, (uchar *)md.buffer, CSUM_CHUNK);
                    204:                len -= i;
                    205:                p += i;
                    206:        }
                    207: 
                    208:        while (len >= CSUM_CHUNK) {
                    209:                mdfour_update(&md, (uchar *)p, CSUM_CHUNK);
                    210:                len -= CSUM_CHUNK;
                    211:                p += CSUM_CHUNK;
                    212:        }
                    213: 
                    214:        sumresidue = len;
                    215:        if (sumresidue)
                    216:                memcpy(md.buffer, p, sumresidue);
                    217: }
                    218: 
                    219: int sum_end(char *sum)
                    220: {
                    221:        if (protocol_version >= 30) {
                    222:                md5_result(&md, (uchar *)sum);
                    223:                return MD5_DIGEST_LEN;
                    224:        }
                    225: 
                    226:        if (sumresidue || protocol_version >= 27)
                    227:                mdfour_update(&md, (uchar *)md.buffer, sumresidue);
                    228: 
                    229:        mdfour_result(&md, (uchar *)sum);
                    230: 
                    231:        return MD4_DIGEST_LEN;
                    232: }

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