#include #include #include #include #include #include #include #include #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; }