1/* $NetBSD: hashhl.c,v 1.3 2009/03/06 18:15:23 apb 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) 39WA(FNPREFIX(End),CONCAT(_,FNPREFIX(End))) 40WA(FNPREFIX(FileChunk),CONCAT(_,FNPREFIX(FileChunk))) 41WA(FNPREFIX(File),CONCAT(_,FNPREFIX(File))) 42WA(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 64char * 65FNPREFIX(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 89char * 90FNPREFIX(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 127char * 128FNPREFIX(File)(const char *filename, char *buf) 129{ 130 return (FNPREFIX(FileChunk)(filename, buf, (off_t)0, (off_t)0)); 131} 132 133char * 134FNPREFIX(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