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 signed char *buf
= (signed char *)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 static void sum_put(MDstruct
*md
,char *sum
)
54 SIVAL(sum
,0,md
->buffer
[0]);
55 if (csum_length
<= 4) return;
56 SIVAL(sum
,4,md
->buffer
[1]);
57 if (csum_length
<= 8) return;
58 SIVAL(sum
,8,md
->buffer
[2]);
59 if (csum_length
<= 12) return;
60 SIVAL(sum
,12,md
->buffer
[3]);
64 void get_checksum2(char *buf
,int len
,char *sum
)
68 static char *buf1
= NULL
;
73 buf1
= (char *)malloc(len
+4);
75 if (!buf1
) out_of_memory("get_checksum2");
82 SIVAL(buf1
,len
,checksum_seed
);
86 for(i
= 0; i
+ CSUM_CHUNK
<= len
; i
+= CSUM_CHUNK
) {
87 MDupdate(&MD
, buf1
+i
, CSUM_CHUNK
*8);
90 MDupdate(&MD
, buf1
+i
, (len
-i
)*8);
96 void file_checksum(char *fname
,char *sum
,off_t size
)
100 struct map_struct
*buf
;
103 char tmpchunk
[CSUM_CHUNK
];
105 bzero(sum
,csum_length
);
107 fd
= open(fname
,O_RDONLY
);
108 if (fd
== -1) return;
110 buf
= map_file(fd
,size
);
114 for(i
= 0; i
+ CSUM_CHUNK
<= len
; i
+= CSUM_CHUNK
) {
115 bcopy(map_ptr(buf
,i
,CSUM_CHUNK
),tmpchunk
,CSUM_CHUNK
);
116 MDupdate(&MD
, tmpchunk
, CSUM_CHUNK
*8);
120 bcopy(map_ptr(buf
,i
,len
-i
),tmpchunk
,len
-i
);
121 MDupdate(&MD
, tmpchunk
, (len
-i
)*8);
131 void checksum_init(void)
133 if (remote_version
>= 14)
134 csum_length
= 2; /* adaptive */
136 csum_length
= SUM_LENGTH
;
141 static MDstruct sumMD
;
142 static int sumresidue
;
143 static char sumrbuf
[CSUM_CHUNK
];
150 SIVAL(s
,0,checksum_seed
);
154 void sum_update(char *p
,int len
)
157 if (len
+ sumresidue
< CSUM_CHUNK
) {
158 bcopy(p
,sumrbuf
+sumresidue
,len
);
164 i
= MIN(CSUM_CHUNK
-sumresidue
,len
);
165 bcopy(p
,sumrbuf
+sumresidue
,i
);
166 MDupdate(&sumMD
, sumrbuf
, (i
+sumresidue
)*8);
171 for(i
= 0; i
+ CSUM_CHUNK
<= len
; i
+= CSUM_CHUNK
) {
172 bcopy(p
+i
,sumrbuf
,CSUM_CHUNK
);
173 MDupdate(&sumMD
, sumrbuf
, CSUM_CHUNK
*8);
178 bcopy(p
+i
,sumrbuf
,sumresidue
);
184 void sum_end(char *sum
)
187 MDupdate(&sumMD
, sumrbuf
, sumresidue
*8);
189 SIVAL(sum
,0,sumMD
.buffer
[0]);
190 SIVAL(sum
,4,sumMD
.buffer
[1]);
191 SIVAL(sum
,8,sumMD
.buffer
[2]);
192 SIVAL(sum
,12,sumMD
.buffer
[3]);