1 /* $NetBSD: hashhl.c,v 1.7 2014/09/24 13:18:52 christos 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 /* 13 * Modified September 24, 2005 by Elad Efrat <elad@NetBSD.org> 14 * Modified April 29, 1997 by Jason R. Thorpe <thorpej@NetBSD.org> 15 */ 16 17 #ifdef HASH_ALGORITHM 18 19 #if HAVE_NBTOOL_CONFIG_H 20 #include "nbtool_config.h" 21 #endif 22 23 /* 24 * Do all the name mangling before we include "namespace.h" 25 */ 26 #define CONCAT(x,y) __CONCAT(x,y) 27 28 #ifndef HASH_FNPREFIX 29 #define HASH_FNPREFIX HASH_ALGORITHM 30 #endif /* !HASH_FNPREFIX */ 31 32 #define FNPREFIX(x) CONCAT(HASH_FNPREFIX,x) 33 #define HASH_CTX CONCAT(HASH_ALGORITHM,_CTX) 34 #define HASH_LEN CONCAT(HASH_ALGORITHM,_DIGEST_LENGTH) 35 #define HASH_STRLEN CONCAT(HASH_ALGORITHM,_DIGEST_STRING_LENGTH) 36 37 #if !defined(_KERNEL) && defined(__weak_alias) && !defined(HAVE_NBTOOL_CONFIG_H) 38 #define WA(a,b) __weak_alias(a,b) 39 WA(FNPREFIX(End),CONCAT(_,FNPREFIX(End))) 40 WA(FNPREFIX(FileChunk),CONCAT(_,FNPREFIX(FileChunk))) 41 WA(FNPREFIX(File),CONCAT(_,FNPREFIX(File))) 42 WA(FNPREFIX(Data),CONCAT(_,FNPREFIX(Data))) 43 #undef WA 44 #endif 45 46 #include "namespace.h" 47 #include HASH_INCLUDE 48 49 #include <sys/types.h> 50 #include <sys/stat.h> 51 52 #include <assert.h> 53 #include <fcntl.h> 54 #include <errno.h> 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <unistd.h> 58 59 #ifndef MIN 60 #define MIN(x,y) ((x)<(y)?(x):(y)) 61 #endif /* !MIN */ 62 63 char * 64 FNPREFIX(End)(HASH_CTX *ctx, char *buf) 65 { 66 int i; 67 unsigned char digest[HASH_LEN]; 68 static const char hex[]="0123456789abcdef"; 69 70 _DIAGASSERT(ctx != 0); 71 72 if (buf == NULL) 73 buf = malloc((size_t)HASH_STRLEN); 74 if (buf == NULL) 75 return (NULL); 76 77 FNPREFIX(Final)(digest, ctx); 78 79 for (i = 0; i < HASH_LEN; i++) { 80 buf[i+i] = hex[(u_int32_t)digest[i] >> 4]; 81 buf[i+i+1] = hex[digest[i] & 0x0f]; 82 } 83 84 buf[i+i] = '\0'; 85 return (buf); 86 } 87 88 char * 89 FNPREFIX(FileChunk)(const char *filename, char *buf, off_t off, off_t len) 90 { 91 struct stat sb; 92 u_char buffer[BUFSIZ]; 93 HASH_CTX ctx; 94 int fd, save_errno; 95 ssize_t nr; 96 97 FNPREFIX(Init)(&ctx); 98 99 if ((fd = open(filename, O_RDONLY | O_CLOEXEC)) < 0) 100 return (NULL); 101 if (len == 0) { 102 if (fstat(fd, &sb) == -1) { 103 close(fd); 104 return (NULL); 105 } 106 len = sb.st_size; 107 } 108 if (off > 0 && lseek(fd, off, SEEK_SET) < 0) { 109 close(fd); 110 return (NULL); 111 } 112 113 while ((nr = read(fd, buffer, (size_t) MIN((off_t)sizeof(buffer), len))) 114 > 0) { 115 FNPREFIX(Update)(&ctx, buffer, (unsigned int)nr); 116 if (len > 0 && (len -= nr) == 0) 117 break; 118 } 119 120 save_errno = errno; 121 close(fd); 122 errno = save_errno; 123 return (nr < 0 ? NULL : FNPREFIX(End)(&ctx, buf)); 124 } 125 126 char * 127 FNPREFIX(File)(const char *filename, char *buf) 128 { 129 return (FNPREFIX(FileChunk)(filename, buf, (off_t)0, (off_t)0)); 130 } 131 132 char * 133 FNPREFIX(Data)(const unsigned char *data, size_t len, char *buf) 134 { 135 HASH_CTX ctx; 136 137 _DIAGASSERT(data != 0); 138 139 FNPREFIX(Init)(&ctx); 140 FNPREFIX(Update)(&ctx, data, (unsigned int)len); 141 return (FNPREFIX(End)(&ctx, buf)); 142 } 143 144 #endif /* HASH_ALGORITHM */ 145