91 lines
1.8 KiB
C
91 lines
1.8 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <openssl/evp.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#define BUF_SIZE 4096
|
|
|
|
void print_usage (void) {
|
|
dprintf(STDERR_FILENO, "Usage:\n"
|
|
"\n"
|
|
" hash-pipe ALGORITHM FILENAME LOGFILE\n"
|
|
"\n"
|
|
"where\n"
|
|
" ALGORITHM is an openssl Digest name, e.g. sha512\n"
|
|
" FILENAME is the name to display within the logfile\n"
|
|
" LOGFILE is a text file into which sha*sum-compatible hashes are to be appended\n");
|
|
}
|
|
|
|
int main (int argc, char **argv) {
|
|
if (argc != 4) {
|
|
print_usage();
|
|
exit(1);
|
|
}
|
|
|
|
const char *algo_name = argv[1];
|
|
const char *file_name = argv[2];
|
|
const char *log_name = argv[3];
|
|
|
|
/*
|
|
* determine the algorithm
|
|
*/
|
|
const EVP_MD *md = EVP_get_digestbyname(algo_name);
|
|
if (md == NULL) {
|
|
dprintf(STDERR_FILENO, "Unknown algorithm: %s\n", algo_name);
|
|
exit(1);
|
|
}
|
|
|
|
/*
|
|
* open the file for appending, create if necessary
|
|
*/
|
|
int fd = open(log_name, O_WRONLY | O_APPEND | O_CREAT, 0644);
|
|
if (fd == -1) {
|
|
dprintf(STDERR_FILENO, "Unable to open file for writing: %s\n", log_name);
|
|
}
|
|
|
|
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
|
|
EVP_DigestInit_ex(mdctx, md, NULL);
|
|
|
|
uint8_t buf[BUF_SIZE];
|
|
ssize_t s;
|
|
|
|
while (true) {
|
|
s = read(STDIN_FILENO, buf, BUF_SIZE);
|
|
|
|
if (s == -1) {
|
|
dprintf(STDERR_FILENO, "Unknown error.\n");
|
|
exit(1);
|
|
} else if (s == 0) {
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* add the chunk to the digest and transparently pass
|
|
* it to stdout
|
|
*/
|
|
EVP_DigestUpdate(mdctx, buf, s);
|
|
write(STDOUT_FILENO, buf, s);
|
|
}
|
|
|
|
/*
|
|
* convert to an ascii representation
|
|
*/
|
|
unsigned char md_value[EVP_MAX_MD_SIZE];
|
|
unsigned int md_len;
|
|
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
|
|
EVP_MD_CTX_free(mdctx);
|
|
|
|
for (int i = 0; i < md_len; i++) {
|
|
dprintf(fd, "%02x", md_value[i]);
|
|
}
|
|
|
|
dprintf(fd, " %s\n", file_name);
|
|
|
|
close(fd);
|
|
|
|
return 0;
|
|
}
|