| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  Copyright (C) 2002 Nigel Horne <njh@bandsman.co.uk> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |  *  it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |  *  the Free Software Foundation; either version 2 of the License, or | 
					
						
							|  |  |  |  *  (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  *  GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  *  along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2005-03-16 14:47:26 +00:00
										 |  |  | static	char	const	rcsid[] = "$Id: blob.c,v 1.37 2005/03/16 14:44:40 nigelhorne Exp $"; | 
					
						
							| 
									
										
										
										
											2004-02-06 13:46:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if HAVE_CONFIG_H
 | 
					
						
							|  |  |  | #include "clamav-config.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | #include <errno.h>
 | 
					
						
							| 
									
										
										
										
											2004-08-30 11:37:47 +00:00
										 |  |  | #include <fcntl.h>
 | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-10-01 13:50:47 +00:00
										 |  |  | #include <sys/param.h>	/* for NAME_MAX */
 | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-04 17:05:56 +00:00
										 |  |  | #ifdef	C_DARWIN
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | #include "mbox.h"
 | 
					
						
							|  |  |  | #include "blob.h"
 | 
					
						
							|  |  |  | #include "others.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef	CL_DEBUG
 | 
					
						
							|  |  |  | #define	NDEBUG	/* map CLAMAV debug onto standard */
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-23 10:25:57 +00:00
										 |  |  | /* Maximum filenames under various systems */ | 
					
						
							|  |  |  | #ifndef	NAME_MAX	/* e.g. Linux */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef	MAXNAMELEN	/* e.g. Solaris */
 | 
					
						
							|  |  |  | #define	NAME_MAX	MAXNAMELEN
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef	FILENAME_MAX	/* e.g. SCO */
 | 
					
						
							|  |  |  | #define	NAME_MAX	FILENAME_MAX
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef	O_BINARY
 | 
					
						
							|  |  |  | #define	O_BINARY	0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | #include <assert.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | #ifdef	C_MINGW
 | 
					
						
							|  |  |  | #include <windows.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | blob * | 
					
						
							|  |  |  | blobCreate(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef	CL_DEBUG
 | 
					
						
							|  |  |  | 	blob *b = (blob *)cli_calloc(1, sizeof(blob)); | 
					
						
							| 
									
										
										
										
											2004-03-23 10:58:52 +00:00
										 |  |  | 	if(b) | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 		b->magic = BLOBCLASS; | 
					
						
							| 
									
										
										
										
											2003-08-30 19:20:04 +00:00
										 |  |  | 	cli_dbgmsg("blobCreate\n"); | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 	return b; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	return (blob *)cli_calloc(1, sizeof(blob)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | blobDestroy(blob *b) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-08-30 19:20:04 +00:00
										 |  |  | #ifdef	CL_DEBUG
 | 
					
						
							|  |  |  | 	cli_dbgmsg("blobDestroy %d\n", b->magic); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	cli_dbgmsg("blobDestroy\n"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 	assert(b != NULL); | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 	assert(b->magic == BLOBCLASS); | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(b->name) | 
					
						
							|  |  |  | 		free(b->name); | 
					
						
							|  |  |  | 	if(b->data) | 
					
						
							|  |  |  | 		free(b->data); | 
					
						
							|  |  |  | #ifdef	CL_DEBUG
 | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 	b->magic = INVALIDCLASS; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 	free(b); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | blobArrayDestroy(blob *blobList[], int n) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 	assert(blobList != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-08-30 19:20:04 +00:00
										 |  |  | 	while(--n >= 0) { | 
					
						
							|  |  |  | 		cli_dbgmsg("blobArrayDestroy: %d\n", n); | 
					
						
							|  |  |  | 		if(blobList[n]) { | 
					
						
							|  |  |  | 			blobDestroy(blobList[n]); | 
					
						
							|  |  |  | 			blobList[n] = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-22 15:10:32 +00:00
										 |  |  | /*ARGSUSED*/ | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2004-08-22 15:10:32 +00:00
										 |  |  | blobSetFilename(blob *b, const char *dir, const char *filename) | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	assert(b != NULL); | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 	assert(b->magic == BLOBCLASS); | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 	assert(filename != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-09-06 08:34:47 +00:00
										 |  |  | 	cli_dbgmsg("blobSetFilename: %s\n", filename); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 	if(b->name) | 
					
						
							|  |  |  | 		free(b->name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-09-06 08:34:47 +00:00
										 |  |  | 	b->name = strdup(filename); | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-09-06 08:34:47 +00:00
										 |  |  | 	if(b->name) | 
					
						
							|  |  |  | 		sanitiseName(b->name); | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const char * | 
					
						
							|  |  |  | blobGetFilename(const blob *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	assert(b != NULL); | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 	assert(b->magic == BLOBCLASS); | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 	return b->name; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | blobAddData(blob *b, const unsigned char *data, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | #ifdef	HAVE_GETPAGESIZE
 | 
					
						
							| 
									
										
										
										
											2004-12-16 15:29:51 +00:00
										 |  |  | 	static int pagesize; | 
					
						
							|  |  |  | 	int growth; | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 	assert(b != NULL); | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 	assert(b->magic == BLOBCLASS); | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 	assert(data != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(len == 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-02-15 08:49:05 +00:00
										 |  |  | 	if(b->isClosed) { | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * Should be cli_dbgmsg, but I want to see them for now, | 
					
						
							|  |  |  | 		 * and cli_dbgmsg doesn't support debug levels | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		cli_warnmsg("Reopening closed blob\n"); | 
					
						
							|  |  |  | 		b->isClosed = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * The payoff here is between reducing the number of calls to | 
					
						
							|  |  |  | 	 * malloc/realloc and not overallocating memory. A lot of machines | 
					
						
							|  |  |  | 	 * are more tight with memory than one may imagine which is why | 
					
						
							|  |  |  | 	 * we don't just allocate a *huge* amount and be done with it. Closing | 
					
						
							|  |  |  | 	 * the blob helps because that reclaims memory. If you know the maximum | 
					
						
							|  |  |  | 	 * size of a blob before you start adding data, use blobGrow() that's | 
					
						
							|  |  |  | 	 * the most optimum | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | #ifdef	HAVE_GETPAGESIZE
 | 
					
						
							| 
									
										
										
										
											2004-12-16 15:29:51 +00:00
										 |  |  | 	if(pagesize == 0) { | 
					
						
							|  |  |  | 		pagesize = getpagesize(); | 
					
						
							|  |  |  | 		if(pagesize == 0) | 
					
						
							|  |  |  | 			pagesize = 4096; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	growth = pagesize; | 
					
						
							|  |  |  | 	if(len >= pagesize) | 
					
						
							|  |  |  | 		growth = ((len / pagesize) + 1) * pagesize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*printf("len %u, growth = %u\n", len, growth);*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 	if(b->data == NULL) { | 
					
						
							|  |  |  | 		assert(b->len == 0); | 
					
						
							|  |  |  | 		assert(b->size == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-16 15:29:51 +00:00
										 |  |  | 		b->size = growth; | 
					
						
							|  |  |  | 		b->data = cli_malloc(growth); | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 	} else if(b->size < b->len + len) { | 
					
						
							| 
									
										
										
										
											2004-12-16 15:29:51 +00:00
										 |  |  | 		unsigned char *p = cli_realloc(b->data, b->size + growth); | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if(p == NULL) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-16 15:29:51 +00:00
										 |  |  | 		b->size += growth; | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 		b->data = p; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 	if(b->data == NULL) { | 
					
						
							|  |  |  | 		assert(b->len == 0); | 
					
						
							| 
									
										
										
										
											2004-03-25 22:42:00 +00:00
										 |  |  | 		assert(b->size == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 		b->size = len * 4; | 
					
						
							|  |  |  | 		b->data = cli_malloc(b->size); | 
					
						
							|  |  |  | 	} else if(b->size < b->len + len) { | 
					
						
							| 
									
										
										
										
											2004-08-01 08:22:58 +00:00
										 |  |  | 		unsigned char *p = cli_realloc(b->data, b->size + (len * 4)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(p == NULL) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-03-25 22:42:00 +00:00
										 |  |  | 		b->size += len * 4; | 
					
						
							| 
									
										
										
										
											2004-08-01 08:22:58 +00:00
										 |  |  | 		b->data = p; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-03-23 10:58:52 +00:00
										 |  |  | 	if(b->data) { | 
					
						
							|  |  |  | 		memcpy(&b->data[b->len], data, len); | 
					
						
							|  |  |  | 		b->len += len; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-01-14 10:09:59 +00:00
										 |  |  | unsigned char * | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | blobGetData(const blob *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	assert(b != NULL); | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 	assert(b->magic == BLOBCLASS); | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-19 05:30:50 +00:00
										 |  |  | 	if(b->len == 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 	return(b->data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned long | 
					
						
							|  |  |  | blobGetDataSize(const blob *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	assert(b != NULL); | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 	assert(b->magic == BLOBCLASS); | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return(b->len); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2004-02-15 08:49:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | blobClose(blob *b) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 	assert(b != NULL); | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 	assert(b->magic == BLOBCLASS); | 
					
						
							| 
									
										
										
										
											2004-09-21 09:28:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(b->isClosed) { | 
					
						
							|  |  |  | 		cli_dbgmsg("Attempt to close a previously closed blob\n"); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-16 08:07:39 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Nothing more is going to be added to this blob. If it'll save more | 
					
						
							|  |  |  | 	 * than a trivial amount (say 64 bytes) of memory, shrink the allocation | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if((b->size - b->len) >= 64) { | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 		if(b->len == 0) {	/* Not likely */ | 
					
						
							|  |  |  | 			free(b->data); | 
					
						
							|  |  |  | 			b->data = NULL; | 
					
						
							|  |  |  | 			cli_dbgmsg("blobClose: recovered all %u bytes\n", | 
					
						
							|  |  |  | 				b->size); | 
					
						
							|  |  |  | 			b->size = 0; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			unsigned char *ptr = cli_realloc(b->data, b->len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(ptr == NULL) | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			cli_dbgmsg("blobClose: recovered %u bytes from %u\n", | 
					
						
							|  |  |  | 				b->size - b->len, b->size); | 
					
						
							|  |  |  | 			b->size = b->len; | 
					
						
							|  |  |  | 			b->data = ptr; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-02-15 08:49:05 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-05-21 11:33:43 +00:00
										 |  |  | 	b->isClosed = 1; | 
					
						
							| 
									
										
										
										
											2004-02-15 08:49:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Returns 0 if the blobs are the same | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | blobcmp(const blob *b1, const blob *b2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long s1, s2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(b1 != NULL); | 
					
						
							|  |  |  | 	assert(b2 != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(b1 == b2) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s1 = blobGetDataSize(b1); | 
					
						
							|  |  |  | 	s2 = blobGetDataSize(b2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(s1 != s2) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 	if((s1 == 0) && (s2 == 0)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-02-15 08:49:05 +00:00
										 |  |  | 	return memcmp(blobGetData(b1), blobGetData(b2), s1); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2004-03-25 22:42:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | blobGrow(blob *b, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	assert(b != NULL); | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 	assert(b->magic == BLOBCLASS); | 
					
						
							| 
									
										
										
										
											2004-03-25 22:42:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(len == 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(b->isClosed) { | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * Should be cli_dbgmsg, but I want to see them for now, | 
					
						
							|  |  |  | 		 * and cli_dbgmsg doesn't support debug levels | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		cli_warnmsg("Growing closed blob\n"); | 
					
						
							|  |  |  | 		b->isClosed = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(b->data == NULL) { | 
					
						
							|  |  |  | 		assert(b->len == 0); | 
					
						
							|  |  |  | 		assert(b->size == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		b->data = cli_malloc(len); | 
					
						
							| 
									
										
										
										
											2004-05-21 11:33:43 +00:00
										 |  |  | 		if(b->data) | 
					
						
							|  |  |  | 			b->size = len; | 
					
						
							| 
									
										
										
										
											2004-03-25 22:42:00 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2004-05-21 11:33:43 +00:00
										 |  |  | 		unsigned char *ptr = cli_realloc(b->data, b->size + len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(ptr) { | 
					
						
							|  |  |  | 			b->size += len; | 
					
						
							|  |  |  | 			b->data = ptr; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-03-25 22:42:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | fileblob * | 
					
						
							|  |  |  | fileblobCreate(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef	CL_DEBUG
 | 
					
						
							|  |  |  | 	fileblob *fb = (fileblob *)cli_calloc(1, sizeof(fileblob)); | 
					
						
							|  |  |  | 	if(fb) | 
					
						
							| 
									
										
										
										
											2005-02-16 22:25:53 +00:00
										 |  |  | 		fb->b.magic = BLOBCLASS; | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 	cli_dbgmsg("blobCreate\n"); | 
					
						
							|  |  |  | 	return fb; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	return (fileblob *)cli_calloc(1, sizeof(fileblob)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | fileblobDestroy(fileblob *fb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	assert(fb != NULL); | 
					
						
							| 
									
										
										
										
											2005-03-16 14:47:26 +00:00
										 |  |  | 	assert(fb->b.magic == BLOBCLASS); | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-29 13:15:41 +00:00
										 |  |  | 	if(fb->b.name && fb->fp) { | 
					
						
							| 
									
										
										
										
											2005-03-16 14:47:26 +00:00
										 |  |  | 		fclose(fb->fp); | 
					
						
							|  |  |  | 		cli_dbgmsg("fileblobDestroy: %s\n", fb->b.name); | 
					
						
							|  |  |  | 		if(!fb->isNotEmpty) { | 
					
						
							| 
									
										
										
										
											2004-09-18 15:03:15 +00:00
										 |  |  | 			cli_dbgmsg("fileblobDestroy: not saving empty file\n"); | 
					
						
							|  |  |  | 			unlink(fb->b.name); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 		free(fb->b.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		assert(fb->b.data == NULL); | 
					
						
							|  |  |  | 	} else if(fb->b.data) { | 
					
						
							|  |  |  | 		cli_errmsg("fileblobDestroy: file not saved: report to bugs@clamav.net\n"); | 
					
						
							|  |  |  | 		free(fb->b.data); | 
					
						
							| 
									
										
										
										
											2004-11-29 13:15:41 +00:00
										 |  |  | 		if(fb->b.name) | 
					
						
							|  |  |  | 			free(fb->b.name); | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-16 14:47:26 +00:00
										 |  |  | #ifdef	CL_DEBUG
 | 
					
						
							|  |  |  | 	fb->b.magic = INVALIDCLASS; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 	free(fb); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | fileblobSetFilename(fileblob *fb, const char *dir, const char *filename) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int fd; | 
					
						
							|  |  |  | 	char fullname[NAME_MAX + 1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(fb->b.name) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-03-03 09:28:19 +00:00
										 |  |  | 	assert(filename != NULL); | 
					
						
							|  |  |  | 	assert(dir != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-22 15:10:32 +00:00
										 |  |  | 	blobSetFilename(&fb->b, dir, filename); | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Reload the filename, it may be different from the one we've | 
					
						
							|  |  |  | 	 * asked for, e.g. '/'s taken out | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	filename = blobGetFilename(&fb->b); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-03-03 09:28:19 +00:00
										 |  |  | 	assert(filename != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-03-04 14:21:35 +00:00
										 |  |  | #ifdef	C_QNX6
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * QNX6 support from mikep@kaluga.org to fix bug where mkstemp | 
					
						
							|  |  |  | 	 * can return ETOOLONG even when the file name isn't too long | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	snprintf(fullname, sizeof(fullname), "%s/clamavtmpXXXXXXXXXXXXX", dir); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2005-03-16 14:47:26 +00:00
										 |  |  | 	snprintf(fullname, sizeof(fullname) - 1, "%s/%.*sXXXXXX", dir, | 
					
						
							|  |  |  | 		(int)(sizeof(fullname) - 9 - strlen(dir)), filename); | 
					
						
							| 
									
										
										
										
											2005-03-04 14:21:35 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if	defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS) || defined(C_CYGWIN) || defined(C_QNX6)
 | 
					
						
							| 
									
										
										
										
											2004-12-16 15:29:51 +00:00
										 |  |  | 	cli_dbgmsg("fileblobSetFilename: mkstemp(%s)\n", fullname); | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 	fd = mkstemp(fullname); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2005-02-18 20:41:59 +00:00
										 |  |  | 	cli_dbgmsg("fileblobSetFilename: mktemp(%s)\n", fullname); | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 	(void)mktemp(fullname); | 
					
						
							|  |  |  | 	fd = open(fullname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(fd < 0) { | 
					
						
							|  |  |  | 		cli_errmsg("Can't create temporary file %s: %s\n", fullname, strerror(errno)); | 
					
						
							| 
									
										
										
										
											2005-03-16 14:47:26 +00:00
										 |  |  | 		cli_dbgmsg("%d %d\n", sizeof(fullname), strlen(fullname)); | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cli_dbgmsg("Saving attachment as %s\n", fullname); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fb->fp = fdopen(fd, "wb"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(fb->fp == NULL) { | 
					
						
							|  |  |  | 		cli_errmsg("Can't create file %s: %s\n", fullname, strerror(errno)); | 
					
						
							| 
									
										
										
										
											2005-03-16 14:47:26 +00:00
										 |  |  | 		cli_dbgmsg("%d %d\n", sizeof(fullname), strlen(fullname)); | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 		close(fd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(fb->b.data) { | 
					
						
							|  |  |  | 		if(fwrite(fb->b.data, fb->b.len, 1, fb->fp) != 1) | 
					
						
							|  |  |  | 			cli_errmsg("fileblobSetFilename: Can't write to temporary file %s: %s\n", fb->b.name, strerror(errno)); | 
					
						
							| 
									
										
										
										
											2005-03-16 14:47:26 +00:00
										 |  |  | 		else | 
					
						
							|  |  |  | 			fb->isNotEmpty = 1; | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 		free(fb->b.data); | 
					
						
							|  |  |  | 		fb->b.data = NULL; | 
					
						
							|  |  |  | 		fb->b.len = fb->b.size = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | fileblobAddData(fileblob *fb, const unsigned char *data, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(len == 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-03-16 14:47:26 +00:00
										 |  |  | 	assert(data != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 	if(fb->fp) { | 
					
						
							|  |  |  | 		if(fwrite(data, len, 1, fb->fp) != 1) | 
					
						
							|  |  |  | 			cli_errmsg("fileblobAddData: Can't write %u bytes to temporary file %s: %s\n", len, fb->b.name, strerror(errno)); | 
					
						
							| 
									
										
										
										
											2005-03-16 14:47:26 +00:00
										 |  |  | 		else | 
					
						
							|  |  |  | 			fb->isNotEmpty = 1; | 
					
						
							| 
									
										
										
										
											2004-08-22 10:37:32 +00:00
										 |  |  | 	} else | 
					
						
							|  |  |  | 		blobAddData(&(fb->b), data, len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const char * | 
					
						
							|  |  |  | fileblobGetFilename(const fileblob *fb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return blobGetFilename(&(fb->b)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2004-09-06 08:34:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Different operating systems allow different characters in their filenames | 
					
						
							| 
									
										
										
										
											2005-02-18 18:10:39 +00:00
										 |  |  |  * FIXME: What does QNX want? There is no #ifdef C_QNX, but if there were | 
					
						
							|  |  |  |  *	it may be best to treat it like MSDOS | 
					
						
							| 
									
										
										
										
											2004-09-06 08:34:47 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sanitiseName(char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	while(*name) { | 
					
						
							|  |  |  | #ifdef	C_DARWIN
 | 
					
						
							|  |  |  | 		*name &= '\177'; | 
					
						
							| 
									
										
										
										
											2004-12-04 17:05:56 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-02-01 14:45:24 +00:00
										 |  |  | 		/* Also check for tab - "Heinz Martin" <Martin@hemag.ch> */ | 
					
						
							| 
									
										
										
										
											2004-12-21 16:44:49 +00:00
										 |  |  | #if	defined(MSDOS) || defined(C_CYGWIN) || defined(WIN32) || defined(C_OS2)
 | 
					
						
							| 
									
										
										
										
											2005-02-01 14:45:24 +00:00
										 |  |  | 		if(strchr("/*?<>|\\\"+=,;:\t ", *name)) | 
					
						
							| 
									
										
										
										
											2004-09-06 08:34:47 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 		if(*name == '/') | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 			*name = '_'; | 
					
						
							|  |  |  | 		name++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |