2 Copyright (C) Andrew Tridgell 1996
3 Copyright (C) Paul Mackerras 1996
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.
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.
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.
22 int csum_length
=2; /* initial value */
26 int checksum_seed
= 0;
27 extern int remote_version
;
30 a simple 32 bit checksum that can be upadted from either end
31 (inspired by Mark Adler's Adler-32 checksum)
33 uint32
get_checksum1(char *buf1
,int len
)
37 schar
*buf
= (schar
*)buf1
;
40 for (i
= 0; i
< (len
-4); i
+=4) {
41 s2
+= 4*(s1
+ buf
[i
]) + 3*buf
[i
+1] + 2*buf
[i
+2] + buf
[i
+3] +
43 s1
+= (buf
[i
+0] + buf
[i
+1] + buf
[i
+2] + buf
[i
+3] + 4*CHAR_OFFSET
);
45 for (; i
< len
; i
++) {
46 s1
+= (buf
[i
]+CHAR_OFFSET
); s2
+= s1
;
48 return (s1
& 0xffff) + (s2
<< 16);
52 void get_checksum2(char *buf
,int len
,char *sum
)
61 buf1
= (char *)malloc(len
+4);
63 if (!buf1
) out_of_memory("get_checksum2");
70 SIVAL(buf1
,len
,checksum_seed
);
74 for(i
= 0; i
+ CSUM_CHUNK
<= len
; i
+= CSUM_CHUNK
) {
75 mdfour_update(&m
, (uchar
*)(buf1
+i
), CSUM_CHUNK
);
78 * Prior to version 27 an incorrect MD4 checksum was computed
79 * by failing to call mdfour_tail() for block sizes that
80 * are multiples of 64. This is fixed by calling mdfour_update()
81 * even when there are no more bytes.
83 if (len
- i
> 0 || remote_version
>= 27) {
84 mdfour_update(&m
, (uchar
*)(buf1
+i
), (len
-i
));
87 mdfour_result(&m
, (uchar
*)sum
);
91 void file_checksum(char *fname
,char *sum
,OFF_T size
)
94 struct map_struct
*buf
;
97 char tmpchunk
[CSUM_CHUNK
];
100 memset(sum
,0,MD4_SUM_LENGTH
);
102 fd
= do_open(fname
, O_RDONLY
, 0);
103 if (fd
== -1) return;
105 buf
= map_file(fd
,size
);
109 for(i
= 0; i
+ CSUM_CHUNK
<= len
; i
+= CSUM_CHUNK
) {
110 memcpy(tmpchunk
, map_ptr(buf
,i
,CSUM_CHUNK
), CSUM_CHUNK
);
111 mdfour_update(&m
, (uchar
*)tmpchunk
, CSUM_CHUNK
);
115 * Prior to version 27 an incorrect MD4 checksum was computed
116 * by failing to call mdfour_tail() for block sizes that
117 * are multiples of 64. This is fixed by calling mdfour_update()
118 * even when there are no more bytes.
121 memcpy(tmpchunk
, map_ptr(buf
,i
,len
-i
), len
-i
);
123 if (len
- i
> 0 || remote_version
>= 27) {
124 mdfour_update(&m
, (uchar
*)tmpchunk
, (len
-i
));
127 mdfour_result(&m
, (uchar
*)sum
);
134 static int sumresidue
;
135 static char sumrbuf
[CSUM_CHUNK
];
136 static struct mdfour md
;
143 SIVAL(s
,0,checksum_seed
);
148 * Feed data into an MD4 accumulator, md. The results may be
149 * retrieved using sum_end(). md is used for different purposes at
150 * different points during execution.
152 * @todo Perhaps get rid of md and just pass in the address each time.
153 * Very slightly clearer and slower.
155 void sum_update(char *p
, int len
)
158 if (len
+ sumresidue
< CSUM_CHUNK
) {
159 memcpy(sumrbuf
+sumresidue
, p
, len
);
165 i
= MIN(CSUM_CHUNK
-sumresidue
,len
);
166 memcpy(sumrbuf
+sumresidue
,p
,i
);
167 mdfour_update(&md
, (uchar
*)sumrbuf
, (i
+sumresidue
));
172 for(i
= 0; i
+ CSUM_CHUNK
<= len
; i
+= CSUM_CHUNK
) {
173 memcpy(sumrbuf
,p
+i
,CSUM_CHUNK
);
174 mdfour_update(&md
, (uchar
*)sumrbuf
, CSUM_CHUNK
);
179 memcpy(sumrbuf
,p
+i
,sumresidue
);
185 void sum_end(char *sum
)
187 if (sumresidue
|| remote_version
>= 27) {
188 mdfour_update(&md
, (uchar
*)sumrbuf
, sumresidue
);
191 mdfour_result(&md
, (uchar
*)sum
);