Hi!

In my program I have to calculate the Adler32 checksum of a file, but I've a problem in using this algorithm.

The function prototype is:

unsigned long adler32(unsigned long adler, const char *buf, unsigned int len);

I know how to calculate the Adler32 checksum of a string, but in this prototype data are "unsigned long" and there are also a buffer and a length. How can I calculate the checksum of a generic file with this function? And the buffer or the length?

FILE *fp;
fp = fopen("file.txt", "r"); //--> ???

Thanks in advance!

Edited 4 Years Ago by Simone Z.

I'm not sure the first parameter is needed unless it refers to the modulus, but that's a fixed number, IIRC. What library are you using? Do you have the source code? If so, what does the body of that function look like?

Thanks for your reply, Deceptikon. I'm using adler32.c from zlib. I think the first parameter is the content of the file, but the type is unsigned long... The second parameter is the buffer and the third is the length (of ???). The code is

#define BASE 65521 // Modulo
#define NMAX 5552

...

unsigned long adler32(unsigned long adler, const unsigned char *buf, unsigned int len)
{
    unsigned long sum2;
    unsigned n;

    /* split Adler-32 into component sums */
    sum2 = (adler >> 16) & 0xffff;
    adler &= 0xffff;

    /* in case user likes doing a byte at a time, keep it fast */
    if (len == 1) {
        adler += buf[0];
        if (adler >= BASE)
            adler -= BASE;
        sum2 += adler;
        if (sum2 >= BASE)
            sum2 -= BASE;
        return adler | (sum2 << 16);
    }

    /* initial Adler-32 value (deferred check for len == 1 speed) */
    if (buf == 0)
        return 1L;

    /* in case short lengths are provided, keep it somewhat fast */
    if (len < 16) {
        while (len--) {
            adler += *buf++;
            sum2 += adler;
        }
        if (adler >= BASE)
            adler -= BASE;
        MOD28(sum2);            /* only added so many BASE's */
        return adler | (sum2 << 16);
    }

    /* do length NMAX blocks -- requires just one modulo operation */
    while (len >= NMAX) {
        len -= NMAX;
        n = NMAX / 16;          /* NMAX is divisible by 16 */
        do {
            DO16(buf);          /* 16 sums unrolled */
            buf += 16;
        } while (--n);
        MOD(adler);
        MOD(sum2);
    }

    /* do remaining bytes (less than NMAX, still just one modulo) */
    if (len) {                  /* avoid modulos if none remaining */
        while (len >= 16) {
            len -= 16;
            DO16(buf);
            buf += 16;
        }
        while (len--) {
            adler += *buf++;
            sum2 += adler;
        }
        MOD(adler);
        MOD(sum2);
    }

    /* return recombined sums */
    return adler | (sum2 << 16);
}

Edited 4 Years Ago by Simone Z.

According to the documentation, the first parameter represents the previous result of the function. In the case of the first call, you'd seed it to "null":

unsigned long checksum = /* Saved checksum */
FILE* fp = fopen("file.txt", "r");

if (fp)
{
    unsigned long sum = adler32(0, 0, 0);
    char buf[BUFSIZ];

    while (fgets(buf, sizeof buf, fp))
    {
        sum = adler32(sum, buf, strlen(buf));
    }

    fclose(fp);

    if (sum != checksum)
    {
        panic("Invalid checksum");
    }
}

Everything is clear now! Thanks for the explanation

Edited 4 Years Ago by Simone Z.

This question has already been answered. Start a new discussion instead.