I have the code and have to change 0x3B9ACA02432543 to some value that will make the result of this code equal to cksum result.
I tried to change it to cksum default value that is 0x04C11DB7 but the result values were different
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
exit(EXIT_FAILURE);
} else {
FILE *f = NULL;
int c;
f = fopen(argv[1], "rb");
if (f == NULL)
perror("fopen()");
else {
int size = 0;
int crc;
int c;
int i, j;
int crc_table[256];
for (i = 0; i < 256; i++) {
crc = i;
for (j = 0; j < 8; j++)
crc = crc & 1 ? (crc >> 1) ^ 0x3B9ACA02432543 : crc >> 1;
crc_table[i] = crc;
}
crc = 0;
while ((c = fgetc(f)) != EOF) {
++size;
crc = crc_table[(crc ^ c) & 0xFF] ^ (crc >> 8);
}
crc ^= 0xFFFFFFFFUL;
printf("%u\n", crc);
}
}
return 0;
}
You did not say what operating system or source of cksum
you are using. It is different on different systems. On my macOS (BSD-derived) system, cksum -o 3
will compute the standard CRC-32 that you may be referring to.
In that case, you need set the initial CRC to 0xffffffff
, and you need to use the reflection of the polynomial, 0x04c11db7
, which is 0xedb88320
. Also you should use a type assured to be at least 32 bits in length. long
is, int
is not. You also need to use unsigned types for CRC calcuations, so that shifting down doesn't copy the high bit.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
exit(EXIT_FAILURE);
}
else {
FILE *f = NULL;
f = fopen(argv[1], "rb");
if (f == NULL)
perror("fopen()");
else {
unsigned long crc;
int c;
int i, j;
unsigned long crc_table[256];
for (i = 0; i < 256; i++) {
crc = i;
for (j = 0; j < 8; j++)
crc = crc & 1 ? (crc >> 1) ^ 0xedb88320 : crc >> 1;
crc_table[i] = crc;
}
crc = 0xffffffff;
while ((c = fgetc(f)) != EOF)
crc = crc_table[(crc ^ c) & 0xff] ^ (crc >> 8);
crc ^= 0xffffffff;
printf("%lu\n", crc);
}
}
return 0;
}
The POSIX cksum is yet another variant. It uses the non-reflected CRC, starts with 0
instead of 0xffffffff
, and appends the length of the data to the data for the CRC computation. That length is in little-endian order with the least number of bytes needed to represent the length. For convenience, I used the explicitly-sized integers provided by C99:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
exit(EXIT_FAILURE);
}
else {
FILE *f = NULL;
f = fopen(argv[1], "rb");
if (f == NULL)
perror("fopen()");
else {
uint32_t crc;
uint32_t crc_table[256];
for (uint32_t i = 0; i < 256; i++) {
crc = i << 24;
for (int j = 0; j < 8; j++)
crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
crc_table[i] = crc;
}
uint64_t size = 0;
crc = 0;
int c;
while ((c = fgetc(f)) != EOF) {
size++;
crc = crc_table[(crc >> 24) ^ c] ^ (crc << 8);
}
while (size) {
crc = crc_table[(crc >> 24) ^ (size & 0xff)] ^ (crc << 8);
size >>= 8;
}
crc = ~crc;
printf("%lu\n", (unsigned long)crc);
}
}
return 0;
}