1 /* $NetBSD: hashhl.c,v 1.1 2005/09/28 16:31:45 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 /* 20 * Do all the name mangling before we include "namespace.h" 21 */ 22 #define CONCAT(x,y) __CONCAT(x,y) 23 24 #ifndef HASH_FNPREFIX 25 #define HASH_FNPREFIX HASH_ALGORITHM 26 #endif /* !HASH_FNPREFIX */ 27 28 #define FNPREFIX(x) CONCAT(HASH_FNPREFIX,x) 29 #define HASH_CTX CONCAT(HASH_ALGORITHM,_CTX) 30 #define HASH_LEN CONCAT(HASH_ALGORITHM,_DIGEST_LENGTH) 31 #define HASH_STRLEN CONCAT(HASH_ALGORITHM,_DIGEST_STRING_LENGTH) 32 33 #if !defined(_KERNEL) && defined(__weak_alias) 34 #define WA(a,b) __weak_alias(a,b) 35 WA(FNPREFIX(End),CONCAT(_,FNPREFIX(End))) 36 WA(FNPREFIX(FileChunk),CONCAT(_,FNPREFIX(FileChunk))) 37 WA(FNPREFIX(File),CONCAT(_,FNPREFIX(File))) 38 WA(FNPREFIX(Data),CONCAT(_,FNPREFIX(Data))) 39 #undef WA 40 #endif 41 42 #include "namespace.h" 43 #include HASH_INCLUDE 44 45 #include <sys/types.h> 46 #include <sys/stat.h> 47 48 #include <assert.h> 49 #include <fcntl.h> 50 #include <errno.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <unistd.h> 54 55 #if HAVE_NBTOOL_CONFIG_H 56 #include "nbtool_config.h" 57 #endif 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 return (NULL); 111 112 while ((nr = read(fd, buffer, (size_t) MIN(sizeof(buffer), len))) 113 > 0) { 114 FNPREFIX(Update)(&ctx, buffer, (unsigned int)nr); 115 if (len > 0 && (len -= nr) == 0) 116 break; 117 } 118 119 save_errno = errno; 120 close(fd); 121 errno = save_errno; 122 return (nr < 0 ? NULL : FNPREFIX(End)(&ctx, buf)); 123 } 124 125 char * 126 FNPREFIX(File)(const char *filename, char *buf) 127 { 128 return (FNPREFIX(FileChunk)(filename, buf, (off_t)0, (off_t)0)); 129 } 130 131 char * 132 FNPREFIX(Data)(const unsigned char *data, size_t len, char *buf) 133 { 134 HASH_CTX ctx; 135 136 _DIAGASSERT(data != 0); 137 138 FNPREFIX(Init)(&ctx); 139 FNPREFIX(Update)(&ctx, data, (unsigned int)len); 140 return (FNPREFIX(End)(&ctx, buf)); 141 } 142 143 #endif /* HASH_ALGORITHM */ 144