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>