#include <endian.h>
#include "unittest.h"
#include "util.h"
#include <inttypes.h>
static uint64_t
fletcher64(void *addr, size_t len)
{
UT_ASSERT(len % 4 == 0);
uint32_t *p32 = addr;
uint32_t *p32end = (uint32_t *)((char *)addr + len);
uint32_t lo32 = 0;
uint32_t hi32 = 0;
while (p32 < p32end) {
lo32 += le32toh(*p32);
p32++;
hi32 += lo32;
}
return htole64((uint64_t)hi32 << 32 | lo32);
}
int
main(int argc, char *argv[])
{
START(argc, argv, "checksum");
if (argc < 2)
UT_FATAL("usage: %s files...", argv[0]);
for (int arg = 1; arg < argc; arg++) {
int fd = OPEN(argv[arg], O_RDONLY);
os_stat_t stbuf;
FSTAT(fd, &stbuf);
void *addr =
MMAP(NULL, stbuf.st_size, PROT_READ|PROT_WRITE,
MAP_PRIVATE, fd, 0);
CLOSE(fd);
uint64_t *ptr = addr;
while ((char *)(ptr + 1) < (char *)addr + stbuf.st_size) {
uint64_t oldval = *ptr;
*ptr = htole64(0x123);
util_checksum(addr, stbuf.st_size, ptr, 1);
uint64_t csum = *ptr;
UT_ASSERT(util_checksum(addr, stbuf.st_size, ptr, 0));
*ptr = 0;
uint64_t gold_csum = fletcher64(addr, stbuf.st_size);
*ptr = oldval;
UT_ASSERT(!util_checksum(addr, stbuf.st_size, ptr, 0));
UT_ASSERTeq(csum, gold_csum);
UT_OUT("%s:%" PRIu64 " 0x%" PRIx64, argv[arg],
(char *)ptr - (char *)addr, csum);
ptr++;
}
MUNMAP(addr, stbuf.st_size);
}
DONE(NULL);
}