1 /* $OpenBSD: helper.c,v 1.9 2010/01/08 13:30:21 oga Exp $ */ 2 3 /* 4 * ---------------------------------------------------------------------------- 5 * "THE BEER-WARE LICENSE" (Revision 42): 6 * <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you 7 * can do whatever you want with this stuff. If we meet some day, and you think 8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 9 * ---------------------------------------------------------------------------- 10 */ 11 12 #include <sys/param.h> 13 #include <sys/stat.h> 14 15 #include <errno.h> 16 #include <fcntl.h> 17 #include <stdlib.h> 18 #include <stdio.h> 19 #include <string.h> 20 #include <unistd.h> 21 22 #include <hashinc> 23 24 /* ARGSUSED */ 25 char * 26 HASHEnd(HASH_CTX *ctx, char *buf) 27 { 28 int i; 29 u_int8_t digest[HASH_DIGEST_LENGTH]; 30 static const char hex[] = "0123456789abcdef"; 31 32 if (buf == NULL && (buf = malloc(HASH_DIGEST_STRING_LENGTH)) == NULL) 33 return (NULL); 34 35 HASHFinal(digest, ctx); 36 for (i = 0; i < HASH_DIGEST_LENGTH; i++) { 37 buf[i + i] = hex[digest[i] >> 4]; 38 buf[i + i + 1] = hex[digest[i] & 0x0f]; 39 } 40 buf[i + i] = '\0'; 41 memset(digest, 0, sizeof(digest)); 42 return (buf); 43 } 44 45 char * 46 HASHFileChunk(const char *filename, char *buf, off_t off, off_t len) 47 { 48 struct stat sb; 49 u_char buffer[BUFSIZ]; 50 HASH_CTX ctx; 51 int fd, save_errno; 52 ssize_t nr; 53 54 HASHInit(&ctx); 55 56 if ((fd = open(filename, O_RDONLY)) < 0) 57 return (NULL); 58 if (len == 0) { 59 if (fstat(fd, &sb) == -1) { 60 close(fd); 61 return (NULL); 62 } 63 len = sb.st_size; 64 } 65 if (off > 0 && lseek(fd, off, SEEK_SET) < 0) { 66 close(fd); 67 return (NULL); 68 } 69 70 while ((nr = read(fd, buffer, MIN(sizeof(buffer), len))) > 0) { 71 HASHUpdate(&ctx, buffer, (size_t)nr); 72 if (len > 0 && (len -= nr) == 0) 73 break; 74 } 75 76 save_errno = errno; 77 close(fd); 78 errno = save_errno; 79 return (nr < 0 ? NULL : HASHEnd(&ctx, buf)); 80 } 81 82 char * 83 HASHFile(const char *filename, char *buf) 84 { 85 return (HASHFileChunk(filename, buf, (off_t)0, (off_t)0)); 86 } 87 88 char * 89 HASHData(const u_char *data, size_t len, char *buf) 90 { 91 HASH_CTX ctx; 92 93 HASHInit(&ctx); 94 HASHUpdate(&ctx, data, len); 95 return (HASHEnd(&ctx, buf)); 96 } 97