1 /* 2 * Copyright (c) 2019 The DragonFly Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 16 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 17 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 21 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <errno.h> 30 #include <fcntl.h> 31 #include <unistd.h> 32 #include <openssl/md5.h> 33 34 #include <stdio.h> /* for FILE in extern.h */ 35 #include <netinet/in.h> /* for struct sockaddr_in */ 36 #include "extern.h" 37 38 char * 39 sitemd5(const char *filename, char * const buf) 40 { 41 unsigned char digest[MD5_DIGEST_LENGTH]; 42 static const char hex[]="0123456789abcdef"; 43 MD5_CTX ctx; 44 unsigned char buffer[4096]; 45 struct stat st; 46 off_t size; 47 int fd, bytes, i, saved_errno; 48 49 if (!buf) 50 return NULL; 51 52 fd = open(filename, O_RDONLY); 53 if (fd < 0) 54 return NULL; 55 if (fstat(fd, &st) < 0) { 56 bytes = -1; 57 goto err; 58 } 59 60 MD5_Init(&ctx); 61 size = st.st_size; 62 bytes = 0; 63 while (size > 0) { 64 if ((size_t)size > sizeof(buffer)) 65 bytes = read(fd, buffer, sizeof(buffer)); 66 else 67 bytes = read(fd, buffer, size); 68 if (bytes < 0) 69 break; 70 MD5_Update(&ctx, buffer, bytes); 71 size -= bytes; 72 } 73 74 err: 75 saved_errno = errno; 76 close(fd); 77 errno = saved_errno; 78 79 if (bytes < 0) 80 return NULL; 81 82 MD5_Final(digest, &ctx); 83 for (i = 0; i < MD5_DIGEST_LENGTH; i++) { 84 buf[2*i] = hex[digest[i] >> 4]; 85 buf[2*i+1] = hex[digest[i] & 0x0f]; 86 } 87 buf[MD5_DIGEST_LENGTH * 2] = '\0'; 88 89 return buf; 90 } 91