Created
August 25, 2023 15:34
-
-
Save ti-kamlesh/98b1fc36c9a7c3defcc2dced4136b8a0 to your computer and use it in GitHub Desktop.
crc64.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE /* See feature_test_macros(7) */ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <stdbool.h> | |
#include <stdint.h> | |
#include <errno.h> | |
#include <stdarg.h> | |
#include <limits.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <sys/un.h> | |
#include <sys/vfs.h> | |
#include <sys/mount.h> | |
#include <sys/syscall.h> | |
#include <sys/sendfile.h> | |
#include <sys/resource.h> | |
#include <time.h> | |
#include <linux/if_alg.h> | |
#include <arpa/inet.h> | |
#include <fcntl.h> | |
ssize_t splice(int fd_in, loff_t *off_in, int fd_out, | |
loff_t *off_out, size_t len, unsigned int flags); | |
ssize_t vmsplice(int fd, const struct iovec *iov, | |
size_t nr_segs, unsigned int flags); | |
struct timespec start, end; | |
struct timespec timetest; | |
double accum; | |
static void time_diff(struct timespec *res, const struct timespec *start, const struct timespec *end) | |
{ | |
res->tv_sec = end->tv_sec - start->tv_sec; | |
res->tv_nsec = end->tv_nsec - start->tv_nsec; | |
if (res->tv_nsec < 0) { | |
res->tv_sec--; | |
res->tv_nsec += 1000000000; | |
} | |
accum = (res->tv_sec) + (double)(res->tv_nsec) / (double)1000000000L; | |
} | |
static int obj_hash(const char *object, uint8_t *out, size_t len) | |
{ | |
struct sockaddr_alg alg = { | |
.salg_family = AF_ALG, | |
.salg_type = "hash", | |
.salg_name = "crc64-iso", | |
}; | |
int ret, cfd, ofd, ffd; | |
struct stat stbuff; | |
size_t size = 0; | |
off_t offset = 0; | |
int pipes[2]; | |
pipe(pipes); | |
if (!object || len != 8) | |
return -EINVAL; | |
/* Number from cat /proc/sys/fs/pipe-max-size */ | |
ret = fcntl(pipes[0], F_SETPIPE_SZ, 1048576); | |
if (ret < 0) { | |
perror("set pipe size failed."); | |
} | |
cfd = socket(AF_ALG, SOCK_SEQPACKET, 0); | |
if (cfd < 0) { | |
fprintf(stderr, "Cannot get AF_ALG socket: %s\n", | |
strerror(errno)); | |
return cfd; | |
} | |
ret = bind(cfd, (struct sockaddr *)&alg, sizeof(alg)); | |
if (ret < 0) { | |
fprintf(stderr, "Error binding socket: %s\n", strerror(errno)); | |
goto out_cfd; | |
} | |
ofd = accept(cfd, NULL, 0); | |
if (ofd < 0) { | |
fprintf(stderr, "Error accepting socket: %s\n", | |
strerror(errno)); | |
ret = ofd; | |
goto out_cfd; | |
} | |
ffd = open(object, O_RDONLY); | |
if (ffd < 0) { | |
fprintf(stderr, "Error opening object %s: %s\n", | |
object, strerror(errno)); | |
ret = ffd; | |
goto out_ofd; | |
} | |
ret = fstat(ffd, &stbuff); | |
if (ret < 0) { | |
fprintf(stderr, "Error doing fstat: %s\n", | |
strerror(errno)); | |
goto out_ffd; | |
} | |
accum = (timetest.tv_sec) + (double)(timetest.tv_nsec) / (double)1000000000L; | |
clock_gettime(CLOCK_MONOTONIC, &start); | |
size_t file_size = stbuff.st_size; | |
while(stbuff.st_size) { | |
/* printf("size=%lld, offset=%lld\n",size,offset); */ | |
size = splice(ffd, NULL, pipes[1] ,NULL, stbuff.st_size , 0x04|0x01); | |
splice(pipes[0], NULL, ofd, NULL, size, 0x04|0x01); | |
stbuff.st_size -= size; | |
if( size < 0) { | |
fprintf(stderr, "Error from sendfile (%zd vs %zu bytes): %s\n", | |
size, stbuff.st_size, strerror(errno)); | |
ret = -1; | |
goto out_ffd; | |
} | |
} | |
size = read(ofd, out, len); | |
if (size != len) { | |
fprintf(stderr, "Error from read (%zd vs %zu bytes): %s\n", | |
size, len, strerror(errno)); | |
ret = -1; | |
} else { | |
ret = 0; | |
} | |
ret = clock_gettime(CLOCK_MONOTONIC, &end); | |
struct timespec diff; | |
time_diff(&diff, &start, &end); | |
double t_hash = ((double)file_size) / (diff.tv_sec + (diff.tv_nsec * 0.000000001 )); | |
printf("Speed: %.02f Mb/s\n", t_hash / (1024 * 1024)); | |
out_ffd: | |
close(ffd); | |
out_ofd: | |
close(ofd); | |
out_cfd: | |
close(cfd); | |
return ret; | |
} | |
int main(int ac, char **av) | |
{ | |
uint8_t hash[8] = {}; | |
if (ac != 2) { | |
fprintf(stderr, "%s file\n", av[0]); | |
return 1; | |
} | |
obj_hash(av[1], hash, sizeof(hash)); | |
printf("hash %llx\n", *(long long *)hash); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment