|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef CRCTAB |
|
|
# include <config.h> |
|
|
#endif |
|
|
|
|
|
#ifdef CRCTAB |
|
|
|
|
|
# include <stdio.h> |
|
|
|
|
|
# define BIT(x) (1u << (x)) |
|
|
# define SBIT BIT (31) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# define GEN (BIT (26) | BIT (23) | BIT (22) | BIT (16) | BIT (12) \ |
|
|
| BIT (11) | BIT (10) | BIT (8) | BIT (7) | BIT (5) \ |
|
|
| BIT (4) | BIT (2) | BIT (1) | BIT (0)) |
|
|
|
|
|
static unsigned int r[8]; |
|
|
|
|
|
static void |
|
|
fill_r (void) |
|
|
{ |
|
|
r[0] = GEN; |
|
|
for (int i = 1; i < 8; i++) |
|
|
r[i] = (r[i - 1] << 1) ^ ((r[i - 1] & SBIT) ? GEN : 0); |
|
|
} |
|
|
|
|
|
static unsigned int |
|
|
crc_remainder (int m) |
|
|
{ |
|
|
unsigned int rem = 0; |
|
|
|
|
|
for (int i = 0; i < 8; i++) |
|
|
if (BIT (i) & m) |
|
|
rem ^= r[i]; |
|
|
|
|
|
return rem & 0xFFFFFFFF; |
|
|
} |
|
|
|
|
|
int |
|
|
main (void) |
|
|
{ |
|
|
static unsigned int crctab[8][256]; |
|
|
|
|
|
fill_r (); |
|
|
|
|
|
for (int i = 0; i < 256; i++) |
|
|
crctab[0][i] = crc_remainder (i); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 256; i++) |
|
|
{ |
|
|
unsigned int crc = 0; |
|
|
|
|
|
crc = (crc << 8) ^ crctab[0][((crc >> 24) ^ i) & 0xFF]; |
|
|
for (int offset = 1; offset < 8; offset++) |
|
|
{ |
|
|
crc = (crc << 8) ^ crctab[0][((crc >> 24) ^ 0) & 0xFF]; |
|
|
crctab[offset][i] = crc & 0xFFFFFFFF; |
|
|
} |
|
|
} |
|
|
|
|
|
printf ("#include <config.h>\n"); |
|
|
printf ("#include \"cksum.h\"\n"); |
|
|
printf ("\n"); |
|
|
printf ("uint_fast32_t const crctab[8][256] = {\n"); |
|
|
for (int y = 0; y < 8; y++) |
|
|
{ |
|
|
printf ("{\n 0x%08x", crctab[y][0]); |
|
|
for (int i = 0; i < 51; i++) |
|
|
{ |
|
|
printf (",\n 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x", |
|
|
crctab[y][i * 5 + 1], crctab[y][i * 5 + 2], |
|
|
crctab[y][i * 5 + 3], crctab[y][i * 5 + 4], |
|
|
crctab[y][i * 5 + 5]); |
|
|
} |
|
|
printf ("\n},\n"); |
|
|
} |
|
|
printf ("};\n"); |
|
|
} |
|
|
|
|
|
#else |
|
|
|
|
|
# include "cksum.h" |
|
|
# include <sys/types.h> |
|
|
# include <endian.h> |
|
|
# include "system.h" |
|
|
|
|
|
# ifdef USE_VMULL_CRC32 |
|
|
# include <sys/auxv.h> |
|
|
# include <asm/hwcap.h> |
|
|
# endif |
|
|
|
|
|
# include "crc.h" |
|
|
# include "cpu-supports.h" |
|
|
|
|
|
|
|
|
# define BUFLEN (1 << 16) |
|
|
|
|
|
typedef bool (*cksum_fp_t) (FILE *, uint_fast32_t *, uintmax_t *); |
|
|
|
|
|
static cksum_fp_t |
|
|
pclmul_supported (void) |
|
|
{ |
|
|
# if USE_PCLMUL_CRC32 || GL_CRC_X86_64_PCLMUL |
|
|
bool pclmul_enabled = (cpu_supports ("avx") |
|
|
&& cpu_supports ("pclmul")); |
|
|
if (cksum_debug) |
|
|
error (0, 0, "%s", |
|
|
(pclmul_enabled |
|
|
? _("using pclmul hardware support") |
|
|
: _("pclmul support not detected"))); |
|
|
# if USE_PCLMUL_CRC32 |
|
|
if (pclmul_enabled) |
|
|
return cksum_pclmul; |
|
|
# endif |
|
|
# endif |
|
|
|
|
|
return nullptr; |
|
|
} |
|
|
|
|
|
static cksum_fp_t |
|
|
avx2_supported (void) |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
# if USE_AVX2_CRC32 |
|
|
bool avx2_enabled = (cpu_supports ("avx2") |
|
|
&& cpu_supports ("vpclmulqdq")); |
|
|
if (cksum_debug) |
|
|
error (0, 0, "%s", |
|
|
(avx2_enabled |
|
|
? _("using avx2 hardware support") |
|
|
: _("avx2 support not detected"))); |
|
|
if (avx2_enabled) |
|
|
return cksum_avx2; |
|
|
# endif |
|
|
|
|
|
return nullptr; |
|
|
} |
|
|
|
|
|
static cksum_fp_t |
|
|
avx512_supported (void) |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
# if USE_AVX512_CRC32 |
|
|
bool avx512_enabled = (cpu_supports ("avx512f") |
|
|
&& cpu_supports ("avx512bw") |
|
|
&& cpu_supports ("vpclmulqdq")); |
|
|
|
|
|
if (cksum_debug) |
|
|
error (0, 0, "%s", |
|
|
(avx512_enabled |
|
|
? _("using avx512 hardware support") |
|
|
: _("avx512 support not detected"))); |
|
|
if (avx512_enabled) |
|
|
return cksum_avx512; |
|
|
# endif |
|
|
|
|
|
return nullptr; |
|
|
} |
|
|
|
|
|
static cksum_fp_t |
|
|
vmull_supported (void) |
|
|
{ |
|
|
|
|
|
# if USE_VMULL_CRC32 |
|
|
bool vmull_enabled = (cpu_may_support ("pmull") |
|
|
&& (getauxval (AT_HWCAP) & HWCAP_PMULL) > 0); |
|
|
if (cksum_debug) |
|
|
error (0, 0, "%s", |
|
|
(vmull_enabled |
|
|
? _("using vmull hardware support") |
|
|
: _("vmull support not detected"))); |
|
|
if (vmull_enabled) |
|
|
return cksum_vmull; |
|
|
# endif |
|
|
|
|
|
return nullptr; |
|
|
} |
|
|
|
|
|
static bool |
|
|
cksum_slice8 (FILE *fp, uint_fast32_t *crc_out, uintmax_t *length_out) |
|
|
{ |
|
|
uint32_t buf[BUFLEN / sizeof (uint32_t)]; |
|
|
uint_fast32_t crc = 0; |
|
|
uintmax_t length = 0; |
|
|
size_t bytes_read; |
|
|
|
|
|
if (!fp || !crc_out || !length_out) |
|
|
return false; |
|
|
|
|
|
while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0) |
|
|
{ |
|
|
uint32_t *datap; |
|
|
|
|
|
if (length + bytes_read < length) |
|
|
{ |
|
|
errno = EOVERFLOW; |
|
|
return false; |
|
|
} |
|
|
length += bytes_read; |
|
|
|
|
|
|
|
|
datap = (uint32_t *)buf; |
|
|
while (bytes_read >= 8) |
|
|
{ |
|
|
uint32_t first = *datap++, second = *datap++; |
|
|
crc ^= htobe32 (first); |
|
|
second = htobe32 (second); |
|
|
crc = (crctab[7][(crc >> 24) & 0xFF] |
|
|
^ crctab[6][(crc >> 16) & 0xFF] |
|
|
^ crctab[5][(crc >> 8) & 0xFF] |
|
|
^ crctab[4][(crc) & 0xFF] |
|
|
^ crctab[3][(second >> 24) & 0xFF] |
|
|
^ crctab[2][(second >> 16) & 0xFF] |
|
|
^ crctab[1][(second >> 8) & 0xFF] |
|
|
^ crctab[0][(second) & 0xFF]); |
|
|
bytes_read -= 8; |
|
|
} |
|
|
|
|
|
|
|
|
unsigned char *cp = (unsigned char *)datap; |
|
|
while (bytes_read--) |
|
|
crc = (crc << 8) ^ crctab[0][((crc >> 24) ^ *cp++) & 0xFF]; |
|
|
if (feof (fp)) |
|
|
break; |
|
|
} |
|
|
|
|
|
*crc_out = crc; |
|
|
*length_out = length; |
|
|
|
|
|
return !ferror (fp); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int |
|
|
crc_sum_stream (FILE *stream, void *resstream, uintmax_t *length) |
|
|
{ |
|
|
uintmax_t total_bytes = 0; |
|
|
uint_fast32_t crc = 0; |
|
|
|
|
|
static cksum_fp_t cksum_fp; |
|
|
if (! cksum_fp) |
|
|
cksum_fp = avx512_supported (); |
|
|
if (! cksum_fp) |
|
|
cksum_fp = avx2_supported (); |
|
|
if (! cksum_fp) |
|
|
cksum_fp = pclmul_supported (); |
|
|
if (! cksum_fp) |
|
|
cksum_fp = vmull_supported (); |
|
|
if (! cksum_fp) |
|
|
cksum_fp = cksum_slice8; |
|
|
|
|
|
if (! cksum_fp (stream, &crc, &total_bytes)) |
|
|
return -1; |
|
|
|
|
|
*length = total_bytes; |
|
|
|
|
|
for (; total_bytes; total_bytes >>= 8) |
|
|
crc = (crc << 8) ^ crctab[0][((crc >> 24) ^ total_bytes) & 0xFF]; |
|
|
crc = ~crc & 0xFFFFFFFF; |
|
|
|
|
|
unsigned int crc_out = crc; |
|
|
memcpy (resstream, &crc_out, sizeof crc_out); |
|
|
|
|
|
return 0; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int |
|
|
crc32b_sum_stream (FILE *stream, void *resstream, uintmax_t *reslen) |
|
|
{ |
|
|
uint32_t buf[BUFLEN / sizeof (uint32_t)]; |
|
|
uint32_t crc = 0; |
|
|
uintmax_t len = 0; |
|
|
size_t bytes_read; |
|
|
|
|
|
if (!stream || !resstream || !reslen) |
|
|
return -1; |
|
|
|
|
|
# if GL_CRC_X86_64_PCLMUL |
|
|
if (cksum_debug) |
|
|
(void) pclmul_supported (); |
|
|
# endif |
|
|
|
|
|
while ((bytes_read = fread (buf, 1, BUFLEN, stream)) > 0) |
|
|
{ |
|
|
if (len + bytes_read < len) |
|
|
{ |
|
|
errno = EOVERFLOW; |
|
|
return -1; |
|
|
} |
|
|
len += bytes_read; |
|
|
|
|
|
crc = crc32_update (crc, (char const *)buf, bytes_read); |
|
|
|
|
|
if (feof (stream)) |
|
|
break; |
|
|
} |
|
|
|
|
|
unsigned int crc_out = crc; |
|
|
memcpy (resstream, &crc_out, sizeof crc_out); |
|
|
|
|
|
*reslen = len; |
|
|
|
|
|
return ferror (stream) ? -1 : 0; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
output_crc (char const *file, MAYBE_UNUSED int binary_file, |
|
|
void const *digest, bool raw, MAYBE_UNUSED bool tagged, |
|
|
unsigned char delim, bool args, uintmax_t length) |
|
|
{ |
|
|
if (raw) |
|
|
{ |
|
|
|
|
|
uint32_t out_int = htobe32 (*(uint32_t *)digest); |
|
|
fwrite (&out_int, 1, 32/8, stdout); |
|
|
return; |
|
|
} |
|
|
|
|
|
printf ("%u %ju", *(unsigned int *)digest, length); |
|
|
if (args) |
|
|
printf (" %s", file); |
|
|
putchar (delim); |
|
|
} |
|
|
|
|
|
#endif |
|
|
|