Skip to content

Instantly share code, notes, and snippets.

@ti-kamlesh
Last active August 25, 2023 15:33
Show Gist options
  • Save ti-kamlesh/5be75dbde292e122135ddf795fad9f21 to your computer and use it in GitHub Desktop.
Save ti-kamlesh/5be75dbde292e122135ddf795fad9f21 to your computer and use it in GitHub Desktop.
crc splice based
#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;
#define BUFSIZE 1024*1024
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;
/* printf("diff = %lf\r\n", accum); */
}
static int obj_hash(const char *object, uint8_t *out, size_t len)
{
uint8_t buf[BUFSIZE];
struct sockaddr_alg alg = {
.salg_family = AF_ALG,
.salg_type = "hash",
.salg_name = "crc32",
};
int ret, cfd, ofd, ffd;
struct stat stbuff;
size_t size = 0;
off_t offset = 0;
int pipes[2];
pipe(pipes);
if (!object || len != 4)
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;
}
int crc = ~0;
if (setsockopt(cfd, SOL_ALG, ALG_SET_KEY, &crc, 4) != 0) {
fprintf(stderr, "Error in setkey: %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;
}
clock_gettime(CLOCK_MONOTONIC, &start);
size_t file_size = stbuff.st_size;
while(stbuff.st_size) {
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[4] = {};
if (ac != 2) {
fprintf(stderr, "%s file\n", av[0]);
return 1;
}
obj_hash(av[1], hash, sizeof(hash));
printf("hash %x\n", ~(*(unsigned int *)hash));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment