1#include <assert.h>
2#include <fcntl.h>
3#include <stdio.h>
4#include <sys/mman.h>
5#include <sys/stat.h>
6#include <sys/time.h>
7#include <unistd.h>
8
9#include <openssl/sha.h>
10
11inline double now()
12{
13  struct timeval tv = { 0, 0 };
14  gettimeofday(&tv, nullptr);
15  return tv.tv_sec + tv.tv_usec / 1000000.0;
16}
17
18int main(int argc, char* argv[])
19{
20  int64_t total = 0;
21  double start = now();
22  SHA_CTX ctx_;
23  SHA1_Init(&ctx_);
24  for (int i = 1; i < argc; ++i)
25  {
26    int fd = open(argv[i], O_RDONLY);
27    struct stat st;
28    fstat(fd, &st);
29    size_t len = st.st_size;
30    total += len;
31    if (len < 1024*1024*1024)
32    {
33    void* mapped = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
34    assert(mapped != MAP_FAILED);
35    SHA1_Update(&ctx_, mapped, len);
36    munmap(mapped, len);
37    }
38    else
39    {
40      char buf[128*1024];
41      ssize_t nr;
42      while ( (nr = read(fd, buf, sizeof buf)) > 0)
43      {
44        SHA1_Update(&ctx_, buf, nr);
45      }
46    }
47    ::close(fd);
48  }
49  unsigned char result[SHA_DIGEST_LENGTH];
50  SHA1_Final(result, &ctx_);
51  for (int i = 0; i < SHA_DIGEST_LENGTH; ++i)
52  {
53    printf("%02x", result[i]);
54  }
55  printf("\n");
56  double sec = now() - start;
57  printf("%ld bytes %.3f sec %.2f MiB/s\n", total, sec, total / sec / 1024 / 1024);
58}
59
60