1 /* $NetBSD: hashhl.c,v 1.4 2010/01/17 23:10:20 wiz 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 64 char * 65 FNPREFIX(End)(HASH_CTX *ctx, char *buf) 66 { 67 int i; 68 unsigned char digest[HASH_LEN]; 69 static const char hex[]="0123456789abcdef"; 70 71 _DIAGASSERT(ctx != 0); 72 73 if (buf == NULL) 74 buf = malloc((size_t)HASH_STRLEN); 75 if (buf == NULL) 76 return (NULL); 77 78 FNPREFIX(Final)(digest, ctx); 79 80 for (i = 0; i < HASH_LEN; i++) { 81 buf[i+i] = hex[(u_int32_t)digest[i] >> 4]; 82 buf[i+i+1] = hex[digest[i] & 0x0f]; 83 } 84 85 buf[i+i] = '\0'; 86 return (buf); 87 } 88 89 char * 90 FNPREFIX(FileChunk)(const char *filename, char *buf, off_t off, off_t len) 91 { 92 struct stat sb; 93 u_char buffer[BUFSIZ]; 94 HASH_CTX ctx; 95 int fd, save_errno; 96 ssize_t nr; 97 98 FNPREFIX(Init)(&ctx); 99 100 if ((fd = open(filename, O_RDONLY)) < 0) 101 return (NULL); 102 if (len == 0) { 103 if (fstat(fd, &sb) == -1) { 104 close(fd); 105 return (NULL); 106 } 107 len = sb.st_size; 108 } 109 if (off > 0 && lseek(fd, off, SEEK_SET) < 0) { 110 close(fd); 111 return (NULL); 112 } 113 114 while ((nr = read(fd, buffer, (size_t) MIN((off_t)sizeof(buffer), len))) 115 > 0) { 116 FNPREFIX(Update)(&ctx, buffer, (unsigned int)nr); 117 if (len > 0 && (len -= nr) == 0) 118 break; 119 } 120 121 save_errno = errno; 122 close(fd); 123 errno = save_errno; 124 return (nr < 0 ? NULL : FNPREFIX(End)(&ctx, buf)); 125 } 126 127 char * 128 FNPREFIX(File)(const char *filename, char *buf) 129 { 130 return (FNPREFIX(FileChunk)(filename, buf, (off_t)0, (off_t)0)); 131 } 132 133 char * 134 FNPREFIX(Data)(const unsigned char *data, size_t len, char *buf) 135 { 136 HASH_CTX ctx; 137 138 _DIAGASSERT(data != 0); 139 140 FNPREFIX(Init)(&ctx); 141 FNPREFIX(Update)(&ctx, data, (unsigned int)len); 142 return (FNPREFIX(End)(&ctx, buf)); 143 } 144 145 #endif /* HASH_ALGORITHM */ 146