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

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