source: trunk/athena/etc/track/cksum.c @ 8142

Revision 8142, 1.9 KB checked in by cfields, 29 years ago (diff)
Blocksize on SGI was greater than 8192, the hard-coded array size here. But read was reading the larger size, so we lost badly. I a) upped the buffer size to 64K, and b) changed the arg to read so that it will read at most sizeof(buf) into that buffer, but st_blcksize if it's less.
Line 
1#include "mit-copyright.h"
2#include <sys/types.h>
3#include <sys/file.h>
4#include <fcntl.h>
5#include <sys/stat.h>
6#include <netinet/in.h>
7
8#define MIN(a,b) (((a)<(b))?(a):(b))
9
10/*                      I N _ C K S U M
11 *
12 * Checksum routine for Internet Protocol family headers (C Version).
13 * NOTE: this code is taken from 4.3bsd ping, and modified to read a file.
14 *
15 */
16unsigned
17in_cksum( filename, statp) char *filename; struct stat *statp;
18{
19        int fd;
20        struct stat statbuf;
21        static char buf[65536];
22        int readsize;
23        register int nleft;
24        register u_short *w;
25        register unsigned int sum = 0;
26        unsigned int carry = 0;
27
28        fd = open( filename, O_RDONLY);
29
30        /* get the file's optimal blocksize:
31         * we want to call read() as little as possible,
32         * because each call spills the register variables.
33         */
34        if ( ! statp) {
35                statp = &statbuf;
36                fstat( fd, statp);
37        }
38
39        readsize = MIN(sizeof(buf), statp->st_blksize);
40
41        /*
42         * Our algorithm is simple, using a 48 bit accumulator (sum),
43         * we add sequential 16 bit words to it, and at the end, fold
44         * back all the carry bits from the top 32 bits into the lower
45         * 16 bits.
46         * this means we can handle files containing 2**32 16-bit words,
47         * that is, 2**33 bytes, which is a little more than 8 gigabytes.
48         */
49        while ( 0 < ( nleft = read( fd, buf, readsize))) {
50                w = (u_short *) buf;
51                while( nleft > 1 )  {
52                        sum += *w++;
53                        nleft -= 2;
54                }
55
56                /* mop up an odd byte, if necessary */
57                if( nleft == 1 ) {
58                        ((u_char *)w)[ 1] = '\0';
59                        sum += *w;
60                }
61                carry += sum >> 16;
62                sum &= 0xffff;
63        }
64        close( fd);
65
66        /*
67         * add back carry's top 16 bits and low 16 bits.
68         * this makes this checksum byte-order independent.
69         */
70        sum = sum + (carry >> 16) + (carry & 0xffff);
71        sum += (sum >> 16);                     /* add resulting carry */
72        return( htons( 0xffff & ~sum));         /* discard last carry. */
73        /* the ~ (one's complement) isn't really necessary here;
74         * it makes a nonzero checksum for a file of zeroes,
75         * which is useful for network applications of this algorithm.
76         */
77}
Note: See TracBrowser for help on using the repository browser.