[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b

aCaB acab at clamav.net
Sun Apr 4 01:07:25 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit 63979bf21e2c11730fa4f8b74b1694387baad5a7
Merge: e6f5ac515713d048a2a6e028255a58cbe03d83cf b183aa786bcc29084d10239973455513469de3b5
Author: aCaB <acab at clamav.net>
Date:   Fri Oct 9 22:07:33 2009 +0200

    Merge remote branch 'origin/fmap4all'

diff --combined libclamav/Makefile.am
index 9710937,0a976a1..4a27cea
--- a/libclamav/Makefile.am
+++ b/libclamav/Makefile.am
@@@ -309,6 -309,8 +309,8 @@@ libclamav_la_SOURCES = 
  	version.h\
  	mpool.c\
  	mpool.h \
+ 	fmap.c \
+ 	fmap.h \
  	default.h\
  	sha256.c\
  	sha256.h\
@@@ -346,8 -348,8 +348,8 @@@ version.h: version.h.tm
  version.h.tmp:
  	@test -f version.h || touch version.h;\
  	rm -f $@;\
 -	REVISION="$$(LANG=C cd "$(top_srcdir)"; git describe --always 2>/dev/null)";\
 -	if test $$? -ne 0; then\
 +	REVISION="$$(LANG=C cd "$(top_srcdir)"; git describe --always 2>/dev/null || echo "exported")";\
 +	if test "$$REVISION" = "exported"; then\
  	   REVISION="r$$(LANG=C svnversion "$(top_srcdir)" 2>/dev/null || echo exported)";\
  	   if test "$$REVISION" = "rexported"; then\
  	    REVISION="";\
diff --combined libclamav/Makefile.in
index bb018c6,ea34250..7d86e2c
--- a/libclamav/Makefile.in
+++ b/libclamav/Makefile.in
@@@ -145,10 -145,10 +145,10 @@@ am__libclamav_la_SOURCES_DIST = clamav.
  	7z/Archive/7z/7zExtract.c 7z/Archive/7z/7zExtract.h explode.c \
  	explode.h textnorm.c textnorm.h dlp.c dlp.h jsparse/js-norm.c \
  	jsparse/js-norm.h jsparse/lexglobal.h jsparse/textbuf.h uniq.c \
- 	uniq.h version.c version.h mpool.c mpool.h default.h sha256.c \
- 	sha256.h bignum.h bytecode.c bytecode.h bytecode_vm.c \
- 	bytecode_priv.h clambc.h cpio.c cpio.h macho.c macho.h \
- 	ishield.c ishield.h type_desc.h bytecode_api.c \
+ 	uniq.h version.c version.h mpool.c mpool.h fmap.c fmap.h \
+ 	default.h sha256.c sha256.h bignum.h bytecode.c bytecode.h \
+ 	bytecode_vm.c bytecode_priv.h clambc.h cpio.c cpio.h macho.c \
+ 	macho.h ishield.c ishield.h type_desc.h bytecode_api.c \
  	bytecode_api_decl.c bytecode_api.h bignum.c bignum_class.h
  @LINK_TOMMATH_FALSE at am__objects_1 = libclamav_la-bignum.lo
  am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
@@@ -193,11 -193,11 +193,11 @@@
  	libclamav_la-textnorm.lo libclamav_la-dlp.lo \
  	libclamav_la-js-norm.lo libclamav_la-uniq.lo \
  	libclamav_la-version.lo libclamav_la-mpool.lo \
- 	libclamav_la-sha256.lo libclamav_la-bytecode.lo \
- 	libclamav_la-bytecode_vm.lo libclamav_la-cpio.lo \
- 	libclamav_la-macho.lo libclamav_la-ishield.lo \
- 	libclamav_la-bytecode_api.lo libclamav_la-bytecode_api_decl.lo \
- 	$(am__objects_1)
+ 	libclamav_la-fmap.lo libclamav_la-sha256.lo \
+ 	libclamav_la-bytecode.lo libclamav_la-bytecode_vm.lo \
+ 	libclamav_la-cpio.lo libclamav_la-macho.lo \
+ 	libclamav_la-ishield.lo libclamav_la-bytecode_api.lo \
+ 	libclamav_la-bytecode_api_decl.lo $(am__objects_1)
  libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
  AM_V_lt = $(am__v_lt_$(V))
  am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
@@@ -583,10 -583,10 +583,10 @@@ libclamav_la_SOURCES = clamav.h matcher
  	7z/Archive/7z/7zExtract.c 7z/Archive/7z/7zExtract.h explode.c \
  	explode.h textnorm.c textnorm.h dlp.c dlp.h jsparse/js-norm.c \
  	jsparse/js-norm.h jsparse/lexglobal.h jsparse/textbuf.h uniq.c \
- 	uniq.h version.c version.h mpool.c mpool.h default.h sha256.c \
- 	sha256.h bignum.h bytecode.c bytecode.h bytecode_vm.c \
- 	bytecode_priv.h clambc.h cpio.c cpio.h macho.c macho.h \
- 	ishield.c ishield.h type_desc.h bytecode_api.c \
+ 	uniq.h version.c version.h mpool.c mpool.h fmap.c fmap.h \
+ 	default.h sha256.c sha256.h bignum.h bytecode.c bytecode.h \
+ 	bytecode_vm.c bytecode_priv.h clambc.h cpio.c cpio.h macho.c \
+ 	macho.h ishield.c ishield.h type_desc.h bytecode_api.c \
  	bytecode_api_decl.c bytecode_api.h $(am__append_7)
  noinst_LTLIBRARIES = libclamav_internal_utils.la libclamav_internal_utils_nothreads.la
  COMMON_CLEANFILES = version.h version.h.tmp *.gcda *.gcno
@@@ -739,6 -739,7 +739,7 @@@ distclean-compile
  @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-entconv.Plo at am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-explode.Plo at am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-filetypes.Plo at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-fmap.Plo at am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-fsg.Plo at am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-hashtab.Plo at am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-htmlnorm.Plo at am__quote@
@@@ -1510,6 -1511,14 +1511,14 @@@ libclamav_la-mpool.lo: mpool.
  @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
  @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-mpool.lo `test -f 'mpool.c' || echo '$(srcdir)/'`mpool.c
  
+ libclamav_la-fmap.lo: fmap.c
+ @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-fmap.lo -MD -MP -MF $(DEPDIR)/libclamav_la-fmap.Tpo -c -o libclamav_la-fmap.lo `test -f 'fmap.c' || echo '$(srcdir)/'`fmap.c
+ @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-fmap.Tpo $(DEPDIR)/libclamav_la-fmap.Plo
+ @am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@	source='fmap.c' object='libclamav_la-fmap.lo' libtool=yes @AMDEPBACKSLASH@
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-fmap.lo `test -f 'fmap.c' || echo '$(srcdir)/'`fmap.c
+ 
  libclamav_la-sha256.lo: sha256.c
  @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-sha256.lo -MD -MP -MF $(DEPDIR)/libclamav_la-sha256.Tpo -c -o libclamav_la-sha256.lo `test -f 'sha256.c' || echo '$(srcdir)/'`sha256.c
  @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-sha256.Tpo $(DEPDIR)/libclamav_la-sha256.Plo
@@@ -2028,8 -2037,8 +2037,8 @@@ version.h: version.h.tm
  version.h.tmp:
  	@test -f version.h || touch version.h;\
  	rm -f $@;\
 -	REVISION="$$(LANG=C cd "$(top_srcdir)"; git describe --always 2>/dev/null)";\
 -	if test $$? -ne 0; then\
 +	REVISION="$$(LANG=C cd "$(top_srcdir)"; git describe --always 2>/dev/null || echo "exported")";\
 +	if test "$$REVISION" = "exported"; then\
  	   REVISION="r$$(LANG=C svnversion "$(top_srcdir)" 2>/dev/null || echo exported)";\
  	   if test "$$REVISION" = "rexported"; then\
  	    REVISION="";\
diff --combined libclamav/binhex.c
index d3a429a,eb926c3..705f683
--- a/libclamav/binhex.c
+++ b/libclamav/binhex.c
@@@ -103,32 -103,22 +103,25 @@@ static	char	const	rcsid[] = "$Id: binhe
  #include <stdio.h>
  #include <memory.h>
  #include <sys/stat.h>
 -#include "others.h"
 +#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
 +#include <sys/mman.h>
 +#endif
  
 +#include "others.h"
  #include "mbox.h"
  #include "binhex.h"
+ #include "fmap.h"
  
  int
- cli_binhex(const char *dir, int desc)
+ cli_binhex(const char *dir, fmap_t *map)
  {
- #ifndef HAVE_MMAP
- 	cli_warnmsg("File not decoded - binhex decoding needs mmap() (for now)\n");
- 	return CL_CLEAN;
- #else
- 	struct stat statb;
  	char *buf, *start, *line;
  	size_t size;
  	long bytesleft;
  	message *m;
  	fileblob *fb;
  
- 	if(fstat(desc, &statb) < 0)
- 		return CL_EOPEN;
- 
- 	size = (size_t)statb.st_size;
+ 	size = (size_t)map->len;
  
  	if(size == 0)
  		return CL_CLEAN;
@@@ -137,8 -127,8 +130,8 @@@
  	if(m == NULL)
  		return CL_EMEM;
  
- 	start = buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, 0);
- 	if(buf == MAP_FAILED) {
+ 	start = buf = fmap_need_off_once(map, 0, size);
+ 	if(!buf) {
  		messageDestroy(m);
  		return CL_EMAP;
  	}
@@@ -149,16 -139,16 +142,16 @@@
  	line = NULL;
  
  	while(bytesleft > 0) {
- 		int length = 0;
+ 		int length = bytesleft;
  		char *ptr, *newline;
  
  		/*printf("%d: ", bytesleft);*/
  
  		for(ptr = buf; bytesleft && (*ptr != '\n') && (*ptr != '\r'); ptr++) {
  			--bytesleft;
  		}
  
+ 		length -= bytesleft;
  		/*printf("%d: ", length);*/
  
  		newline = cli_realloc(line, (size_t)(length + 1));
@@@ -182,7 -172,6 +175,6 @@@
  		buf = ++ptr;
  		bytesleft--;
  	}
- 	munmap(start, size);
  
  	if(line)
  		free(line);
@@@ -208,5 -197,4 +200,4 @@@
  		return CL_CLEAN;	/* a lie - but it gets things going */
  	/* return CL_EIO; */	/* probably CL_EMEM, but we can't tell at this layer */
  	return CL_EMEM;
- #endif
  }
diff --combined libclamav/chmunpack.c
index 64c582d,47fd17a..3f4a557
--- a/libclamav/chmunpack.c
+++ b/libclamav/chmunpack.c
@@@ -31,11 -31,9 +31,9 @@@
  #ifdef	HAVE_UNISTD_H
  #include <unistd.h>
  #endif
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
  #include <string.h>
  
+ #include "fmap.h"
  #include "others.h"
  #include "mspack.h"
  #include "cltypes.h"
@@@ -54,6 -52,10 +52,6 @@@
  #pragma pack 1
  #endif
  
 -#ifndef	O_BINARY
 -#define	O_BINARY	0
 -#endif
 -
  #define CHM_CHUNK_HDR_LEN (0x14)
  
  #define CHM_CONTROL_LEN (0x18)
@@@ -104,26 -106,12 +102,12 @@@ typedef struct lzx_content_tag 
  #define chm_endian_convert_64(x) le64_to_host(x)
  
  /* Read in a block of data from either the mmap area or the given fd */
- static int chm_read_data(int fd, char *dest, off_t offset, off_t len,
- 			char *m_area, off_t m_length)
+ static int chm_read_data(fmap_t *map, char *dest, off_t offset, off_t len)
  {
- 	if ((offset < 0) || (len < 0) || ((offset+len) < 0)) {
- 		return FALSE;
- 	}
- 	if (m_area != NULL) {
- 		if ((offset+len) > m_length) {
- 			return FALSE;
- 		}
- 		memcpy(dest, m_area+offset, len);
- 	} else {
- 		if (lseek(fd, offset, SEEK_SET) != offset) {
- 			return FALSE;
- 		}
- 		if (cli_readn(fd, dest, len) != len) {
- 			return FALSE;
- 		}
- 	}
- 	return TRUE;
+     void *src = fmap_need_off_once(map, offset, len);
+     if(!src) return FALSE;
+     memcpy(dest, src, len);
+     return TRUE;
  }
  
  static uint64_t chm_copy_file_data(int ifd, int ofd, uint64_t len)
@@@ -169,56 -157,11 +153,11 @@@ static void itsf_print_header(chm_itsf_
  	}
  }
  
- static int itsf_read_header(int fd, chm_itsf_header_t *itsf_hdr, char *m_area, off_t m_length)
+ static int itsf_read_header(chm_metadata_t *metadata)
  {
- #if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
- 	if (!chm_read_data(fd, (char *) itsf_hdr, 0, CHM_ITSF_MIN_LEN,
- 				m_area,	m_length)) {
- 		return FALSE;
- 	}
- #else
- 	if (cli_readn(fd, &itsf_hdr->signature, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->version, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->header_len, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->unknown, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->last_modified, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->lang_id, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->dir_clsid, 16) != 16) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->stream_clsid, 16) != 16) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->sec0_offset, 8) != 8) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->sec0_len, 8) != 8) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->dir_offset, 8) != 8) {
+ 	chm_itsf_header_t *itsf_hdr = &metadata->itsf_hdr;
+ 	if (!chm_read_data(metadata->map, (char *)itsf_hdr, 0, CHM_ITSF_MIN_LEN))
  		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsf_hdr->dir_len, 8) != 8) {
- 		return FALSE;
- 	}
- 	if (itsf_hdr->version > 2) {
- 		if (cli_readn(fd, &itsf_hdr->data_offset, 8) != 8) {
- 			return FALSE;
- 		}
- 	}
- #endif
  	if (memcmp(itsf_hdr->signature, "ITSF", 4) != 0) {
  		cli_dbgmsg("ITSF signature mismatch\n");
  		return FALSE;
@@@ -257,64 -200,11 +196,11 @@@ static void itsp_print_header(chm_itsp_
  	cli_dbgmsg("Lang ID:\t%u\n\n", itsp_hdr->lang_id);
  }
  
- static int itsp_read_header(int fd, chm_itsp_header_t *itsp_hdr, off_t offset,
- 				char *m_area, off_t m_length)
+ static int itsp_read_header(chm_metadata_t *metadata, off_t offset)
  {
- #if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
- 	if (!chm_read_data(fd, (char *) itsp_hdr, offset, CHM_ITSP_LEN,
- 				m_area,	m_length)) {
- 		return FALSE;
- 	}
- #else
- 	if (lseek(fd, offset, SEEK_SET) != offset) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->signature, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->version, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->header_len, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->unknown1, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->block_len, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->blockidx_intvl, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->index_depth, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->index_root, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->index_head, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->index_tail, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->unknown2, 4) != 4) {
+ 	chm_itsp_header_t *itsp_hdr = &metadata->itsp_hdr;
+ 	if (!chm_read_data(metadata->map, (char *)itsp_hdr, offset, CHM_ITSP_LEN))
  		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->num_blocks, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->lang_id, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->system_clsid, 16) != 16) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &itsp_hdr->unknown4, 16) != 16) {
- 		return FALSE;
- 	}
- #endif
  	if (memcmp(itsp_hdr->signature, "ITSP", 4) != 0) {
  		cli_dbgmsg("ITSP signature mismatch\n");
  		return FALSE;
@@@ -404,7 -294,7 +290,7 @@@ static int read_control_entries(chm_met
  	return TRUE;
  }
  
- static int prepare_file(int fd, chm_metadata_t *metadata)
+ static int prepare_file(chm_metadata_t *metadata)
  {
  	uint64_t name_len, section;
  
@@@ -432,7 -322,7 +318,7 @@@
  	return CL_BREAK;
  }
  
- static int read_chunk(chm_metadata_t *metadata, int fd)
+ static int read_chunk(chm_metadata_t *metadata)
  {
  	cli_dbgmsg("in read_chunk\n");
  
@@@ -440,29 -330,15 +326,15 @@@
  		return CL_EFORMAT;
  	}
  
- 	if (metadata->m_area != NULL) {
- 		if (metadata->chunk_offset > metadata->m_length) {
- 			return CL_EFORMAT;
- 		}
- 		if ((metadata->chunk_offset + metadata->itsp_hdr.block_len) > metadata->m_length) {
- 			return CL_EFORMAT;
- 		}
- 		metadata->chunk_data = metadata->m_area + metadata->chunk_offset;
- 
- 	} else {
- 		if (!metadata->chunk_data) {
- 			metadata->chunk_data = (char *) cli_malloc(metadata->itsp_hdr.block_len);
- 			if (!metadata->chunk_data) {
- 				return CL_EMEM;
- 			}
- 		}
-         	if (lseek(fd, metadata->chunk_offset, SEEK_SET) != metadata->chunk_offset) {
-                 	goto abort;
-         	}
-         	if ((uint32_t) cli_readn(fd, metadata->chunk_data, metadata->itsp_hdr.block_len) != metadata->itsp_hdr.block_len) {
-                		goto abort;
-         	}
+ 	if (metadata->chunk_offset > metadata->m_length) {
+ 		return CL_EFORMAT;
+ 	}
+ 	if ((metadata->chunk_offset + metadata->itsp_hdr.block_len) > metadata->m_length) {
+ 		return CL_EFORMAT;
  	}
+ 	metadata->chunk_data = fmap_need_off_once(metadata->map, metadata->chunk_offset, metadata->itsp_hdr.block_len);
+ 	if(!metadata->chunk_data) return CL_EFORMAT;
+ 
  	metadata->chunk_current = metadata->chunk_data + CHM_CHUNK_HDR_LEN;
  	metadata->chunk_end = metadata->chunk_data + metadata->itsp_hdr.block_len;
  
@@@ -470,19 -346,10 +342,10 @@@
  		metadata->chunk_entries = (uint16_t)((((uint8_t const *)(metadata->chunk_data))[metadata->itsp_hdr.block_len-2] << 0)
  					| (((uint8_t const *)(metadata->chunk_data))[metadata->itsp_hdr.block_len-1] << 8));
  	} else if (memcmp(metadata->chunk_data, "PMGI", 4) != 0) {
- 		if (!metadata->m_area && metadata->chunk_data) {
- 			free(metadata->chunk_data);
- 		}
  		return CL_BREAK;
  	}
  
  	return CL_SUCCESS;
- abort:
- 	if (!metadata->m_area && metadata->chunk_data) {
- 		free(metadata->chunk_data);
- 		metadata->chunk_data = NULL;
- 	}
- 	return CL_EFORMAT;
  }
  
  static void print_sys_control(lzx_control_t *lzx_control)
@@@ -501,7 -368,7 +364,7 @@@
  	cli_dbgmsg("Cache Size:\t%d\n\n", lzx_control->cache_size);
  }
  
- static int read_sys_control(int fd, chm_metadata_t *metadata, lzx_control_t *lzx_control)
+ static int read_sys_control(chm_metadata_t *metadata, lzx_control_t *lzx_control)
  {
  	off_t offset;
  	
@@@ -513,34 -380,10 +376,10 @@@
  		return FALSE;
  	}
  
- #if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
- 	if (!chm_read_data(fd, (char *) lzx_control, offset, CHM_CONTROL_LEN,
- 				metadata->m_area, metadata->m_length)) {
- 		return FALSE;
- 	}
- #else
- 	if (lseek(fd, offset, SEEK_SET) != offset) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_control->length, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_control->signature, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_control->version, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_control->reset_interval, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_control->window_size, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_control->cache_size, 4) != 4) {
+ 	if (!chm_read_data(metadata->map, (char *) lzx_control, offset, CHM_CONTROL_LEN)) {
  		return FALSE;
  	}
- #endif
+ 
  	lzx_control->length = chm_endian_convert_32(lzx_control->length);
  	lzx_control->version = chm_endian_convert_32(lzx_control->version);
  	lzx_control->reset_interval = chm_endian_convert_32(lzx_control->reset_interval);
@@@ -578,7 -421,7 +417,7 @@@ static void print_sys_content(lzx_conte
  	cli_dbgmsg("Length:\t%lu\n\n", (unsigned long int) lzx_content->length);
  }
  
- static int read_sys_content(int fd, chm_metadata_t *metadata, lzx_content_t *lzx_content)
+ static int read_sys_content(chm_metadata_t *metadata, lzx_content_t *lzx_content)
  {
  	lzx_content->offset = metadata->itsf_hdr.data_offset + metadata->sys_content.offset;
  	lzx_content->length = metadata->sys_content.length;
@@@ -602,7 -445,7 +441,7 @@@ static void print_sys_reset_table(lzx_r
  	cli_dbgmsg("Frame Len:\t%lu\n\n", (unsigned long int) lzx_reset_table->frame_len);
  }
  
- static int read_sys_reset_table(int fd, chm_metadata_t *metadata, lzx_reset_table_t *lzx_reset_table)
+ static int read_sys_reset_table(chm_metadata_t *metadata, lzx_reset_table_t *lzx_reset_table)
  {
  	off_t offset;
  
@@@ -619,34 -462,10 +458,10 @@@
  	/* Save the entry offset for later use */
  	lzx_reset_table->rt_offset = offset-4;
  
- #if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
- 	if (!chm_read_data(fd, (char *) lzx_reset_table, offset, CHM_RESET_TABLE_LEN,
- 				metadata->m_area, metadata->m_length)) {
- 		return FALSE;
- 	}
- #else	
- 	if (lseek(fd, offset, SEEK_SET) != offset) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_reset_table->num_entries, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_reset_table->entry_size, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_reset_table->table_offset, 4) != 4) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_reset_table->uncom_len, 8) != 8) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_reset_table->com_len, 8) != 8) {
- 		return FALSE;
- 	}
- 	if (cli_readn(fd, &lzx_reset_table->frame_len, 8) != 8) {
+ 	if (!chm_read_data(metadata->map, (char *) lzx_reset_table, offset, CHM_RESET_TABLE_LEN)) {
  		return FALSE;
  	}
- #endif
+ 
  	lzx_reset_table->num_entries = chm_endian_convert_32(lzx_reset_table->num_entries);
  	lzx_reset_table->entry_size = chm_endian_convert_32(lzx_reset_table->entry_size);
  	lzx_reset_table->table_offset = chm_endian_convert_32(lzx_reset_table->table_offset);
@@@ -680,7 -499,7 +495,7 @@@ static int chm_decompress_stream(int fd
  	char filename[1024];
  	struct cab_file file;
  	
 -	snprintf(filename, 1024, "%s/clamav-unchm.bin", dirname);
 +	snprintf(filename, 1024, "%s"PATHSEP"clamav-unchm.bin", dirname);
  	tmpfd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
  	if (tmpfd<0) {
  		cli_dbgmsg("open failed for %s\n", filename);
@@@ -692,13 -511,13 +507,13 @@@
  		goto abort;
  	}
  
- 	if (!read_sys_control(fd, metadata, &lzx_control)) {
+ 	if (!read_sys_control(metadata, &lzx_control)) {
  		goto abort;
  	}
- 	if (!read_sys_content(fd, metadata, &lzx_content)) {
+ 	if (!read_sys_content(metadata, &lzx_content)) {
  		goto abort;
  	}
- 	if (!read_sys_reset_table(fd, metadata, &lzx_reset_table)) {
+ 	if (!read_sys_reset_table(metadata, &lzx_reset_table)) {
  		goto abort;
  	}
  	
@@@ -756,7 -575,7 +571,7 @@@
  	lzx_decompress(stream, length);
  	lzx_free(stream);
  	
 -#ifndef C_WINDOWS
 +#ifndef _WIN32
  	/* Delete the file */
  	if(cli_unlink(filename))
  		retval = -1;
@@@ -780,7 -599,7 +595,7 @@@ static int chm_init_metadata(chm_metada
  	}
  	
  	metadata->sys_control.length = metadata->sys_content.length = metadata->sys_reset.length = 0;
- 	metadata->m_area = NULL;
+ 	metadata->map = NULL;
  	metadata->ufd = -1;
  	metadata->num_chunks = metadata->chunk_entries = 0;
  	metadata->chunk_data = NULL;
@@@ -792,17 -611,10 +607,10 @@@ void cli_chm_close(chm_metadata_t *meta
  	if (metadata->ufd >= 0) {
  		close(metadata->ufd);
  	}
- 	if (!metadata->m_area && metadata->chunk_data) {
- 		free(metadata->chunk_data);
- 	}
- #ifdef HAVE_MMAP
- 	if (metadata->m_area) {
- 		munmap(metadata->m_area, metadata->m_length);
- 	}
- #endif
+ 	funmap(metadata->map);
  }
  
- int cli_chm_extract_file(int fd, char *dirname, chm_metadata_t *metadata, cli_ctx *ctx)
+ int cli_chm_extract_file(char *dirname, chm_metadata_t *metadata, cli_ctx *ctx)
  {
  	char filename[1024];
  	uint64_t len;
@@@ -813,7 -625,7 +621,7 @@@
  		cli_dbgmsg("seek in uncompressed stream failed\n");
  		return CL_EFORMAT;
  	}
 -	snprintf(filename, 1024, "%s/%lu.chm", dirname, (unsigned long int) metadata->file_offset);
 +	snprintf(filename, 1024, "%s"PATHSEP"%lu.chm", dirname, (unsigned long int) metadata->file_offset);
  	metadata->ofd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
  	if (metadata->ofd < 0) {
  		return CL_ECREAT;
@@@ -828,7 -640,7 +636,7 @@@
  	return CL_SUCCESS;
  }	
  
- int cli_chm_prepare_file(int fd, char *dirname, chm_metadata_t *metadata)
+ int cli_chm_prepare_file(chm_metadata_t *metadata)
  {
  	int retval;
  	
@@@ -839,13 -651,13 +647,13 @@@
  			if (metadata->num_chunks == 0) {
  				return CL_BREAK;
  			}
- 			if ((retval = read_chunk(metadata, fd)) != CL_SUCCESS) {
+ 			if ((retval = read_chunk(metadata)) != CL_SUCCESS) {
  				return retval;
  			}
  			metadata->num_chunks--;
  			metadata->chunk_offset += metadata->itsp_hdr.block_len;
  		}
- 		retval = prepare_file(fd, metadata);
+ 		retval = prepare_file(metadata);
  	} while (retval == CL_BREAK); /* Ran out of chunk entries before finding a file */
  	return retval;
  }
@@@ -861,25 -673,23 +669,23 @@@ int cli_chm_open(int fd, const char *di
  		return retval;
  	}
  
- #ifdef HAVE_MMAP
  	if (fstat(fd, &statbuf) == 0) {
  		if (statbuf.st_size < CHM_ITSF_MIN_LEN) {
- 			goto abort;
+ 			return CL_ESTAT;
  		}
  		metadata->m_length = statbuf.st_size;
- 		metadata->m_area = (char *) mmap(NULL, metadata->m_length, PROT_READ, MAP_PRIVATE, fd, 0);
- 		if (metadata->m_area == MAP_FAILED) {
- 			metadata->m_area = NULL;
+ 		metadata->map = fmap(fd, 0, metadata->m_length);
+ 		if (!metadata->map) {
+ 			return CL_EMAP;
  		}
  	}
- #endif
  
- 	if (!itsf_read_header(fd, &metadata->itsf_hdr, metadata->m_area, metadata->m_length)) {
+ 	if (!itsf_read_header(metadata)) {
  		goto abort;
  	}
  	itsf_print_header(&metadata->itsf_hdr);
  
- 	if (!itsp_read_header(fd, &metadata->itsp_hdr, metadata->itsf_hdr.dir_offset, metadata->m_area, metadata->m_length)) {
+ 	if (!itsp_read_header(metadata, metadata->itsf_hdr.dir_offset)) {
  		goto abort;
  	}
  	itsp_print_header(&metadata->itsp_hdr);
@@@ -903,7 -713,7 +709,7 @@@
  	}
  	
  	while (metadata->num_chunks) {
- 		if (read_chunk(metadata, fd) != CL_SUCCESS) {
+ 		if (read_chunk(metadata) != CL_SUCCESS) {
  			cli_dbgmsg("read_chunk failed\n");
  			goto abort;
  		}
@@@ -932,10 -742,6 +738,6 @@@
  	return CL_SUCCESS;
  
  abort:
- #ifdef HAVE_MMAP
- 	if (metadata->m_area) {
- 		munmap(metadata->m_area, metadata->m_length);
- 	}
- #endif
+ 	funmap(metadata->map);
  	return CL_EFORMAT;
  }
diff --combined libclamav/elf.c
index 9239640,f47db3a..3a978c8
--- a/libclamav/elf.c
+++ b/libclamav/elf.c
@@@ -63,7 -63,7 +63,7 @@@ static uint32_t cli_rawaddr(uint32_t va
      return vaddr - EC32(ph[i].p_vaddr, conv) + EC32(ph[i].p_offset, conv);
  }
  
- int cli_scanelf(int desc, cli_ctx *ctx)
+ int cli_scanelf(cli_ctx *ctx)
  {
  	struct elf_file_hdr32 file_hdr;
  	struct elf_section_hdr32 *section_hdr;
@@@ -72,11 -72,12 +72,12 @@@
  	uint32_t entry, fentry, shoff, phoff, i;
  	uint8_t conv = 0, err;
  	unsigned int format;
+ 	fmap_t *map = *ctx->fmap;
  
  
      cli_dbgmsg("in cli_scanelf\n");
  
-     if(read(desc, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
+     if(fmap_readn(map, &file_hdr, 0, sizeof(file_hdr)) != sizeof(file_hdr)) {
  	/* Not an ELF file? */
  	cli_dbgmsg("ELF: Can't read file header\n");
  	return CL_CLEAN;
@@@ -95,8 -96,7 +96,7 @@@
  
      if(format == 2) {
  	    struct elf_file_hdr64 file_hdr64;
- 	lseek(desc, 0, SEEK_SET);
- 	if(read(desc, &file_hdr64, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
+ 	if(fmap_readn(map, &file_hdr64, 0, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
  	    /* Not an ELF file? */
  	    cli_dbgmsg("ELF: Can't read file header\n");
  	    return CL_CLEAN;
@@@ -216,7 -216,7 +216,7 @@@
          if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return CL_VIRUS;
          }
  	return CL_EFORMAT;
      }
@@@ -229,21 -229,13 +229,13 @@@
  	    if(DETECT_BROKEN) {
  		if(ctx->virname)
  		    *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	    return CL_EFORMAT;
  	}
  
  	phoff = EC32(file_hdr.e_phoff, conv);
  	cli_dbgmsg("ELF: Program header table offset: %d\n", phoff);
- 	if((uint32_t) lseek(desc, phoff, SEEK_SET) != phoff) {
- 	    if(DETECT_BROKEN) {
- 		if(ctx->virname)
- 		    *ctx->virname = "Broken.Executable";
- 		return CL_VIRUS;
- 	    }
- 	    return CL_CLEAN;
- 	}
  
  	program_hdr = (struct elf_program_hdr32 *) cli_calloc(phnum, phentsize);
  	if(!program_hdr) {
@@@ -256,12 -248,13 +248,13 @@@
  	for(i = 0; i < phnum; i++) {
  	    err = 0;
  	    if(format == 1) {
- 		if(read(desc, &program_hdr[i], sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
+ 		if(fmap_readn(map, &program_hdr[i], phoff, sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
  		    err = 1;
+ 		phoff += sizeof(struct elf_program_hdr32);
  	    } else {
  		    struct elf_program_hdr64 program_hdr64;
  
- 		if(read(desc, &program_hdr64, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
+ 		if(fmap_readn(map, &program_hdr64, phoff, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
  		    err = 1;
  		} else {
  		    program_hdr[i].p_type = program_hdr64.p_type;
@@@ -273,6 -266,7 +266,7 @@@
  		    program_hdr[i].p_flags = program_hdr64.p_flags;
  		    program_hdr[i].p_align = program_hdr64.p_align;
  		}
+ 		phoff += sizeof(program_hdr64);
  	    }
  
  	    if(err) {
@@@ -282,7 -276,7 +276,7 @@@
  		if(DETECT_BROKEN) {
  		    if(ctx->virname)
  			*ctx->virname = "Broken.Executable";
 -		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		    return CL_VIRUS;
  		}
  		return CL_CLEAN;
  	    }
@@@ -303,7 -297,7 +297,7 @@@
  	    if(DETECT_BROKEN) {
  		if(ctx->virname)
  		    *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	    return CL_EFORMAT;
  	}
@@@ -320,7 -314,7 +314,7 @@@
          if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return CL_VIRUS;
          }
  	return CL_EFORMAT;
      }
@@@ -331,22 -325,13 +325,13 @@@
          if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return CL_VIRUS;
          }
  	return CL_EFORMAT;
      }
  
      shoff = EC32(file_hdr.e_shoff, conv);
      cli_dbgmsg("ELF: Section header table offset: %d\n", shoff);
-     if((uint32_t) lseek(desc, shoff, SEEK_SET) != shoff) {
- 	/* Possibly broken end of file */
-         if(DETECT_BROKEN) {
- 	    if(ctx->virname)
- 		*ctx->virname = "Broken.Executable";
- 	    return CL_VIRUS;
-         }
- 	return CL_CLEAN;
-     }
  
      section_hdr = (struct elf_section_hdr32 *) cli_calloc(shnum, shentsize);
      if(!section_hdr) {
@@@ -359,12 -344,13 +344,13 @@@
      for(i = 0; i < shnum; i++) {
  	err = 0;
  	if(format == 1) {
- 	    if(read(desc, &section_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
+ 	    if(fmap_readn(map, &section_hdr[i], shoff, sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
  		err = 1;
+ 	    shoff += sizeof(struct elf_section_hdr32);
  	} else {
  		struct elf_section_hdr64 section_hdr64;
  
- 	    if(read(desc, &section_hdr64, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
+ 	    if(fmap_readn(map, &section_hdr64, shoff, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
  		err = 1;
  	    } else {
  		section_hdr[i].sh_name = section_hdr64.sh_name;
@@@ -378,6 -364,7 +364,7 @@@
  		section_hdr[i].sh_addralign = section_hdr64.sh_addralign;
  		section_hdr[i].sh_entsize = section_hdr64.sh_entsize;
  	    }
+ 	    shoff += sizeof(section_hdr64);
  	}
  
  	if(err) {
@@@ -387,7 -374,7 +374,7 @@@
              if(DETECT_BROKEN) {
                  if(ctx->virname)
                      *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
              }
              return CL_CLEAN;
          }
@@@ -468,7 -455,7 +455,7 @@@
      return CL_CLEAN;
  }
  
- int cli_elfheader(int desc, struct cli_exe_info *elfinfo)
+ int cli_elfheader(fmap_t *map, struct cli_exe_info *elfinfo)
  {
  	struct elf_file_hdr32 file_hdr;
  	struct elf_section_hdr32 *section_hdr;
@@@ -480,7 -467,7 +467,7 @@@
  
      cli_dbgmsg("in cli_elfheader\n");
  
-     if(read(desc, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
+     if(fmap_readn(map, &file_hdr, 0, sizeof(file_hdr)) != sizeof(file_hdr)) {
  	/* Not an ELF file? */
  	cli_dbgmsg("ELF: Can't read file header\n");
  	return -1;
@@@ -499,8 -486,7 +486,7 @@@
  
      if(format == 2) {
  	    struct elf_file_hdr64 file_hdr64;
- 	lseek(desc, 0, SEEK_SET);
- 	if(read(desc, &file_hdr64, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
+ 	if(!fmap_readn(map, &file_hdr64, 0, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
  	    /* Not an ELF file? */
  	    cli_dbgmsg("ELF: Can't read file header\n");
  	    return -1; 
@@@ -547,9 -533,6 +533,6 @@@
  	}
  
  	phoff = EC32(file_hdr.e_phoff, conv);
- 	if((uint32_t) lseek(desc, phoff, SEEK_SET) != phoff) {
- 	    return -1;
- 	}
  
  	program_hdr = (struct elf_program_hdr32 *) cli_calloc(phnum, phentsize);
  	if(!program_hdr) {
@@@ -560,12 -543,13 +543,13 @@@
  	for(i = 0; i < phnum; i++) {
  	    err = 0;
  	    if(format == 1) {
- 		if(read(desc, &program_hdr[i], sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
+ 		if(fmap_readn(map, &program_hdr[i], phoff, sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
  		    err = 1;
+ 		phoff += sizeof(struct elf_program_hdr32);
  	    } else {
  		    struct elf_program_hdr64 program_hdr64;
  
- 		if(read(desc, &program_hdr64, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
+ 		if(fmap_readn(map, &program_hdr64, phoff, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
  		    err = 1;
  		} else {
  		    program_hdr[i].p_type = program_hdr64.p_type;
@@@ -577,6 -561,7 +561,7 @@@
  		    program_hdr[i].p_flags = program_hdr64.p_flags;
  		    program_hdr[i].p_align = program_hdr64.p_align;
  		}
+ 		phoff += sizeof(program_hdr64);
  	    }
  
  	    if(err) {
@@@ -610,10 -595,6 +595,6 @@@
      }
  
      shoff = EC32(file_hdr.e_shoff, conv);
-     if((uint32_t) lseek(desc, shoff, SEEK_SET) != shoff) {
- 	/* Possibly broken end of file */
- 	return -1;
-     }
  
      elfinfo->section = (struct cli_exe_section *) cli_calloc(elfinfo->nsections, sizeof(struct cli_exe_section));
      if(!elfinfo->section) {
@@@ -632,12 -613,13 +613,13 @@@
      for(i = 0; i < shnum; i++) {
  	err = 0;
  	if(format == 1) {
- 	    if(read(desc, &section_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
+ 	    if(fmap_readn(map, &section_hdr[i], shoff, sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
  		err = 1;
+ 	    shoff += sizeof(struct elf_section_hdr32);
  	} else {
  		struct elf_section_hdr64 section_hdr64;
  
- 	    if(read(desc, &section_hdr64, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
+ 	    if(fmap_readn(map, &section_hdr64, shoff, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
  		err = 1;
  	    } else {
  		section_hdr[i].sh_name = section_hdr64.sh_name;
@@@ -651,6 -633,7 +633,7 @@@
  		section_hdr[i].sh_addralign = section_hdr64.sh_addralign;
  		section_hdr[i].sh_entsize = section_hdr64.sh_entsize;
  	    }
+ 	    shoff += sizeof(section_hdr64);
  	}
  
  	if(err) {
diff --combined libclamav/htmlnorm.c
index b777491,3a270d8..2588698
--- a/libclamav/htmlnorm.c
+++ b/libclamav/htmlnorm.c
@@@ -39,10 -39,8 +39,8 @@@
  #include <errno.h>
  #include <stdio.h>
  #include <ctype.h>
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
  
+ #include "fmap.h"
  #include "others.h"
  #include "htmlnorm.h"
  
@@@ -180,15 -178,23 +178,23 @@@ static unsigned char *cli_readchunk(FIL
  
  	/* Try and use the memory buffer first */
  	if (m_area) {
- 		start = ptr = m_area->buffer + m_area->offset;
- 		end = m_area->buffer + m_area->length;
+ 		/* maximum we can copy into the buffer,
+ 		 * we could have less than max_len bytes available */
+ 		chunk_len = MIN(m_area->length-m_area->offset, max_len-1);
+ 		if(!chunk_len) {
+ 			free(chunk);
+ 			return NULL;
+ 		}
+ 		if(m_area->map)
+ 		    ptr = (unsigned char *)fmap_need_off_once(m_area->map, m_area->offset, chunk_len);
+ 		else
+ 		    ptr = m_area->buffer + m_area->offset;
+ 		start = ptr;
+ 		end = ptr - m_area->offset + m_area->length;
  		if (start >= end) {
  			free(chunk);
  			return NULL;
  		}
- 		/* maximum we can copy into the buffer,
- 		 * we could have less than max_len bytes available */
- 		chunk_len = MIN(end-start, max_len-1);
  
  		/* look for NULL chars */
  		ptr = memchr(start, 0, chunk_len);
@@@ -209,18 -215,20 +215,20 @@@
  				chunk_len = 0;
  				ptr = start;
  			}
+ 			if(m_area->map)
+ 			    ptr = (unsigned char *)fmap_need_ptr_once(m_area->map, ptr, end - ptr);
  			/* we have unknown number of NULL chars,
  			 * copy char-by-char and skip them */
  			while((ptr < end) && (chunk_len < max_len-1)) {
  				const unsigned char c = *ptr++;
+ 				/* we can't use chunk_len to determine how many bytes we read, since
+ 				 * we skipped chars */
  				if(c) {
  					chunk[chunk_len++] = c;
  				}
  			}
+ 			m_area->offset += ptr - start;
  			chunk[chunk_len] = '\0';
- 			/* we can't use chunk_len to determine how many bytes we read, since
- 			 * we skipped chars */
- 			m_area->offset = ptr - m_area->buffer;
  		}
  		if(ptr && ptr < end && !isspace(*ptr)) {
  			/* we hit max_len, rewind to a space */
@@@ -648,7 -656,7 +656,7 @@@ static int cli_html_normalise(int fd, m
  	tag_args.value = NULL;
  	tag_args.contents = NULL;
  	if (dirname) {
 -		snprintf(filename, 1024, "%s/rfc2397", dirname);
 +		snprintf(filename, 1024, "%s"PATHSEP"rfc2397", dirname);
  		if (mkdir(filename, 0700) && errno != EEXIST) {
  			file_buff_o2 = file_buff_text = NULL;
  			goto abort;
@@@ -661,7 -669,7 +669,7 @@@
  		}
  
  		/* this will still contains scripts that are inside comments */
 -		snprintf(filename, 1024, "%s/nocomment.html", dirname);
 +		snprintf(filename, 1024, "%s"PATHSEP"nocomment.html", dirname);
  		file_buff_o2->fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
  		if (file_buff_o2->fd == -1) {
  			cli_dbgmsg("open failed: %s\n", filename);
@@@ -678,7 -686,7 +686,7 @@@
  			goto abort;
  		}
  
 -		snprintf(filename, 1024, "%s/notags.html", dirname);
 +		snprintf(filename, 1024, "%s"PATHSEP"notags.html", dirname);
  		file_buff_text->fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
  		if(file_buff_text->fd == -1) {
  			cli_dbgmsg("open failed: %s\n", filename);
@@@ -1477,7 -1485,7 +1485,7 @@@
  					if (!file_tmp_o1) {
  						goto abort;
  					}
 -					snprintf(filename, 1024, "%s/rfc2397", dirname);
 +					snprintf(filename, 1024, "%s"PATHSEP"rfc2397", dirname);
  					tmp_file = cli_gentemp(filename);
  					if(!tmp_file) {
  						goto abort;
@@@ -1697,37 -1705,21 +1705,21 @@@ int html_normalise_mem(unsigned char *i
  	m_area.buffer = in_buff;
  	m_area.length = in_size;
  	m_area.offset = 0;
+ 	m_area.map = NULL;
  
  	return cli_html_normalise(-1, &m_area, dirname, hrefs, dconf);
  }
  
- int html_normalise_fd(int fd, const char *dirname, tag_arguments_t *hrefs,const struct cli_dconf* dconf)
+ int html_normalise_map(fmap_t *map, const char *dirname, tag_arguments_t *hrefs,const struct cli_dconf* dconf)
  {
- #if HAVE_MMAP
  	int retval=FALSE;
  	m_area_t m_area;
- 	struct stat statbuf;
- 
- 	if (fstat(fd, &statbuf) == 0) {
- 		m_area.length = statbuf.st_size;
- 		m_area.buffer = (unsigned char *) mmap(NULL, m_area.length, PROT_READ, MAP_PRIVATE, fd, 0);
- 		m_area.offset = 0;
- 		if (m_area.buffer == MAP_FAILED) {
- 			cli_dbgmsg("mmap HTML failed\n");
- 			retval = cli_html_normalise(fd, NULL, dirname, hrefs, dconf);
- 		} else {
- 			cli_dbgmsg("mmap'ed file\n");
- 			retval = cli_html_normalise(-1, &m_area, dirname, hrefs, dconf);
- 			munmap(m_area.buffer, m_area.length);
- 		}
- 	} else {
- 		cli_dbgmsg("fstat HTML failed\n");
- 		retval = cli_html_normalise(fd, NULL, dirname, hrefs, dconf);
- 	}
+ 
+ 	m_area.length = map->len;
+ 	m_area.offset = 0;
+ 	m_area.map = map;
+ 	retval = cli_html_normalise(-1, &m_area, dirname, hrefs, dconf);
  	return retval;
- #else
- 	return cli_html_normalise(fd, NULL, dirname, hrefs, dconf);
- #endif
  }
  
  int html_screnc_decode(int fd, const char *dirname)
@@@ -1750,7 -1742,7 +1742,7 @@@
  		return FALSE;
  	}
  
 -	snprintf((char*)filename, 1024, "%s/screnc.html", dirname);
 +	snprintf((char*)filename, 1024, "%s"PATHSEP"screnc.html", dirname);
  	ofd = open((const char*)filename, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
  
  	if (ofd < 0) {
diff --combined libclamav/ishield.c
index 58bbc5e,2346897..fa340b9
--- a/libclamav/ishield.c
+++ b/libclamav/ishield.c
@@@ -24,8 -24,6 +24,6 @@@
  #include "clamav-config.h"
  #endif
  
- #define _XOPEN_SOURCE 500
- 
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
@@@ -39,16 -37,18 +37,17 @@@
  #if HAVE_STRINGS_H
  #include <strings.h>
  #endif
 +#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
 +#include <sys/mman.h>
 +#endif
  #include <zlib.h>
  
  #include "scanners.h"
  #include "cltypes.h"
  #include "others.h"
+ #include "fmap.h"
  #include "ishield.h"
  
 -#ifndef O_BINARY
 -#define O_BINARY 0
 -#endif
 -
  #ifndef LONG_MAX
  #define LONG_MAX ((-1UL)>>1)
  #endif
@@@ -65,6 -65,14 +64,14 @@@
  
  /* PACKED things go here */
  
+ struct IS_HDR {
+     uint32_t magic; 
+     uint32_t unk1; /* version ??? */
+     uint32_t unk2; /* ??? */
+     uint32_t data_off;
+     uint32_t data_sz; /* ??? */
+ } __attribute__((packed));
+ 
  struct IS_FB {
      char fname[0x104]; /* MAX_PATH */
      uint32_t unk1; /* 6 */
@@@ -181,21 -189,22 +188,22 @@@ struct IS_FILEITEM 
  
  
  
- static int is_dump_and_scan(int desc, cli_ctx *ctx, off_t off, size_t fsize);
+ static int is_dump_and_scan(cli_ctx *ctx, off_t off, size_t fsize);
  static const uint8_t skey[] = { 0xec, 0xca, 0x79, 0xf8 }; /* ~0x13, ~0x35, ~0x86, ~0x07 */
  
  /* Extracts the content of MSI based IS */
- int cli_scanishield_msi(int desc, cli_ctx *ctx, off_t off) {
-     uint8_t buf[BUFSIZ];
+ int cli_scanishield_msi(cli_ctx *ctx, off_t off) {
+     uint8_t *buf;
      unsigned int fcount, scanned = 0;
      int ret;
+     fmap_t *map = *ctx->fmap;
  
      cli_dbgmsg("in ishield-msi\n");
-     lseek(desc, off, SEEK_SET);
-     if(cli_readn(desc, buf, 0x20) != 0x20) {
+     if(!(buf = fmap_need_off_once(map, off, 0x20))) {
  	cli_dbgmsg("ishield-msi: short read for header\n");
  	return CL_CLEAN;
      }
+     off += 0x20;
      if(cli_readint32(buf + 8) | cli_readint32(buf + 0xc) | cli_readint32(buf + 0x10) | cli_readint32(buf + 0x14) | cli_readint32(buf + 0x18) | cli_readint32(buf + 0x1c))
  	return CL_CLEAN;
      if(!(fcount = cli_readint32(buf))) {
@@@ -211,16 -220,20 +219,20 @@@
  	uint64_t csize;
  	z_stream z;
  
- 	if(cli_readn(desc, &fb, sizeof(fb)) != sizeof(fb)) {
+ 	if(fmap_readn(map, &fb, off, sizeof(fb)) != sizeof(fb)) {
  	    cli_dbgmsg("ishield-msi: short read for fileblock\n");
  	    return CL_CLEAN;
  	}
+ 	off += sizeof(fb);
  	fb.fname[sizeof(fb.fname)-1] = '\0';
  	csize = le64_to_host(fb.csize);
- 
+ 	if(!CLI_ISCONTAINED(0, map->len, off, csize)) {
+ 	    cli_dbgmsg("ishield-msi: next stream is out of file, giving up\n");
+ 	    return CL_CLEAN;
+ 	}
  	if(ctx->engine->maxfilesize && csize > ctx->engine->maxfilesize) {
  	    cli_dbgmsg("ishield-msi: skipping stream due to size limits (%lu vs %lu)\n", (unsigned long int) csize, (unsigned long int) ctx->engine->maxfilesize);
- 	    lseek(desc, csize, SEEK_CUR);
+ 	    off += csize;
  	    continue;
  	}
  
@@@ -241,20 -254,21 +253,21 @@@
  	inflateInit(&z);
  	ret = CL_SUCCESS;
  	while(csize) {
- 	    unsigned int sz = csize < sizeof(buf) ? csize : sizeof(buf);
- 	    z.avail_in = cli_readn(desc, buf, sz);
- 	    if(z.avail_in <= 0) {
+ 	    uint8_t buf2[BUFSIZ];
+ 	    z.avail_in = MIN(csize, sizeof(buf2));
+ 	    if(fmap_readn(map, buf2, off, z.avail_in) != z.avail_in) {
  		cli_dbgmsg("ishield-msi: premature EOS or read fail\n");
- 		break;    
+ 		break;
  	    }
+ 	    off += z.avail_in;
  	    for(i=0; i<z.avail_in; i++, lameidx++) {
- 		uint8_t c = buf[i];
+ 		uint8_t c = buf2[i];
  		c = (c>>4) | (c<<4);
  		c ^= key[(lameidx & 0x3ff) % keylen];
- 		buf[i] = c;
+ 		buf2[i] = c;
  	    }
  	    csize -= z.avail_in;
- 	    z.next_in = buf;
+ 	    z.next_in = buf2;
  	    do {
  		int inf;
  		z.avail_out = sizeof(obuf);
@@@ -263,7 -277,7 +276,7 @@@
  		if(inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
  		    cli_dbgmsg("ishield-msi: bad stream\n");
  		    csize = 0;
- 		    lseek(desc, csize, SEEK_CUR);
+ 		    off += csize;
  		    break;
  		}
  		if (cli_writen(ofd, obuf, sizeof(obuf) - z.avail_out) < 0) {
@@@ -273,7 -287,7 +286,7 @@@
  		}
  		if(ctx->engine->maxfilesize && z.total_out > ctx->engine->maxfilesize) {
  		    cli_dbgmsg("ishield-msi: trimming output file due to size limits (%lu vs %lu)\n", z.total_out, (unsigned long int) ctx->engine->maxfilesize);
- 		    lseek(desc, csize, SEEK_CUR);
+ 		    off += csize;
  		    csize = 0;
  		    break;
  		}
@@@ -319,55 -333,47 +332,47 @@@ struct IS_CABSTUFF 
  };
  
  static void md5str(uint8_t *sum);
- static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c);
- static int is_extract_cab(int desc, cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize);
+ static int is_parse_hdr(cli_ctx *ctx, struct IS_CABSTUFF *c);
+ static int is_extract_cab(cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize);
  
  /* Extract the content of older (non-MSI) IS */
- int cli_scanishield(int desc, cli_ctx *ctx, off_t off, size_t sz) {
+ int cli_scanishield(cli_ctx *ctx, off_t off, size_t sz) {
      char *fname, *path, *version, *strsz, *eostr, *data;
-     char buf[2048];
-     int rd, ret = CL_CLEAN;
+     int ret = CL_CLEAN;
      long fsize;
      off_t coff = off;
      struct IS_CABSTUFF c = { NULL, -1, 0, 0 };
+     fmap_t *map = *ctx->fmap;
  
      while(ret == CL_CLEAN) {
- 	rd = pread(desc, buf, sizeof(buf), coff);
- 	if(rd <= 0)
- 	    break;
+ 	fname = fmap_need_offstr(map, coff, 2048);
+ 	if(!fname) break;
+ 	coff += strlen(fname) + 1;
  
- 	fname = buf;
- 	if(!*fname) break;
- 	path = memchr(fname, 0, rd);
- 	if(!path)
- 	    break;
+ 	path = fmap_need_offstr(map, coff, 2048);
+ 	if(!path) break;
+ 	coff += strlen(path) + 1;
  
- 	path++;
- 	rd -= (path - buf);
- 	if(rd<=0 || !(version = memchr(path, 0, rd)))
- 	    break;
+ 	version = fmap_need_offstr(map, coff, 2048);
+ 	if(!version) break;
+ 	coff += strlen(version) + 1;
  
- 	version++;
- 	rd -= (version - path);
- 	if(rd<=0 || !(strsz = memchr(version, 0, rd)))
- 	    break;
+ 	strsz = fmap_need_offstr(map, coff, 2048);
+ 	if(!strsz) break;
+ 	coff += strlen(strsz) + 1;
  
- 	strsz++;
- 	rd -= (strsz - version);
- 	if(rd<=0 || !(data = memchr(strsz, 0, rd)))
- 	    break;
+ 	data = &strsz[strlen(strsz) + 1];
  
- 	data++;
  	fsize = strtol(strsz, &eostr, 10);
  	if(fsize < 0 || fsize == LONG_MAX ||
  	   !*strsz || !eostr || eostr == strsz || *eostr ||
  	   (unsigned long)fsize >= sz ||
- 	   data - buf >= sz - fsize
+ 	   data - fname >= sz - fsize
  	) break;
  
  	cli_dbgmsg("ishield: @%lx found file %s (%s) - version %s - size %lu\n", (unsigned long int) coff, fname, path, version, (unsigned long int) fsize);
- 	sz -= (data - buf) + fsize;
- 	coff += (data - buf);
+ 	sz -= (data - fname) + fsize;
+ 
  	if(!strncasecmp(fname, "data", 4)) {
  	    long cabno;
  	    if(!strcasecmp(fname + 4, "1.hdr")) {
@@@ -401,20 -407,21 +406,21 @@@
  	    }
  	}
  
- 	ret = is_dump_and_scan(desc, ctx, coff, fsize);
+ 	fmap_unneed_ptr(map, fname, data-fname);
+ 	ret = is_dump_and_scan(ctx, coff, fsize);
  	coff += fsize;
      }
  
      if(ret == CL_CLEAN && (c.cabcnt || c.hdr != -1)) {
-       if((ret = is_parse_hdr(desc, ctx, &c)) == CL_CLEAN) {
+       if((ret = is_parse_hdr(ctx, &c)) == CL_CLEAN) {
  	    unsigned int i;
  	    if(c.hdr != -1) {
  		cli_dbgmsg("ishield: scanning data1.hdr\n");
- 		ret = is_dump_and_scan(desc, ctx, c.hdr, c.hdrsz);
+ 		ret = is_dump_and_scan(ctx, c.hdr, c.hdrsz);
  	    }
  	    for(i=0; i<c.cabcnt && ret == CL_CLEAN; i++) {
  		cli_dbgmsg("ishield: scanning data%u.cab\n", c.cabs[i].cabno);
- 		ret = is_dump_and_scan(desc, ctx, c.cabs[i].off, c.cabs[i].sz);
+ 		ret = is_dump_and_scan(ctx, c.cabs[i].off, c.cabs[i].sz);
  	    }
        } else if( ret == CL_BREAK ) ret = CL_CLEAN;
      }
@@@ -424,9 -431,10 +430,10 @@@
  
  
  /* Utility func to scan a fd @ a given offset and size */
- static int is_dump_and_scan(int desc, cli_ctx *ctx, off_t off, size_t fsize) {
-     char *fname, buf[BUFSIZ];
+ static int is_dump_and_scan(cli_ctx *ctx, off_t off, size_t fsize) {
+     char *fname, *buf;
      int ofd, ret = CL_CLEAN;
+     fmap_t *map = *ctx->fmap;
  
      if(!fsize) {
  	cli_dbgmsg("ishield: skipping empty file\n");
@@@ -441,19 -449,18 +448,18 @@@
  	return CL_ECREAT;
      }
      while(fsize) {
- 	size_t rd = fsize < sizeof(buf) ? fsize : sizeof(buf);
- 	int got = pread(desc, buf, rd, off);
- 	if(got <= 0) {
+ 	size_t rd = MIN(fsize, map->pgsz);
+ 	if(!(buf = fmap_need_off_once(map, off, rd))) {
  	    cli_dbgmsg("ishield: read error\n");
  	    ret = CL_EREAD;
  	    break;
  	}
- 	if(cli_writen(ofd, buf, got) <= 0) {
+ 	if(cli_writen(ofd, buf, rd) <= 0) {
  	    ret = CL_EWRITE;
  	    break;
  	}
- 	fsize -= got;
- 	off += got;
+ 	fsize -= rd;
+ 	off += rd;
      }
      if(!fsize) {
  	cli_dbgmsg("ishield: extracted to %s\n", fname);
@@@ -467,29 -474,13 +473,13 @@@
      return ret;
  }
  
- 
- struct IS_HDR {
-     uint32_t magic; 
-     uint32_t unk1; /* version ??? */
-     uint32_t unk2; /* ??? */
-     uint32_t data_off;
-     uint32_t data_sz; /* ??? */
- };
- 
- 
- #define IS_FREE_HDR if(map) munmap(map, mp_hdrsz); else free(hdr);
- #if HAVE_MMAP
- #define IS_MAX_NOMAP_SZ 0x100000
- #else
- #define IS_MAX_NOMAP_SZ CLI_MAX_ALLOCATION
- #endif
- 
  /* Process data1.hdr and extracts all the available files from dataX.cab */
- static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) { 
+ static int is_parse_hdr(cli_ctx *ctx, struct IS_CABSTUFF *c) { 
      uint32_t h1_data_off, objs_files_cnt, objs_dirs_off;
      unsigned int off, i, scanned = 0;
      int ret = CL_BREAK;
-     char hash[33], *hdr, *map = NULL;
+     char hash[33], *hdr;
+     fmap_t *map = *ctx->fmap;
      size_t mp_hdrsz;
  
      struct IS_HDR *h1;
@@@ -501,52 -492,29 +491,29 @@@
  	return CL_CLEAN;
      }
  
-     if(c->hdrsz < IS_MAX_NOMAP_SZ) {
- 	if(!(hdr = (char *)cli_malloc(c->hdrsz)))
- 	    return CL_EMEM;
- 	if(pread(desc, hdr, c->hdrsz, c->hdr) < (ssize_t)c->hdrsz) {
- 	    cli_errmsg("is_parse_hdr: short read for header\n");
- 	    free(hdr);
- 	    return CL_EREAD; /* hdr must be within bounds, it's k to hard fail here */
- 	}
-     } else {
- #if defined(HAVE_MMAP) && defined(HAVE_CLI_GETPAGESIZE)
- 	int psz = cli_getpagesize();
- 	off_t mp_hdr = (c->hdr / psz) * psz;
- 	mp_hdrsz = c->hdrsz + c->hdr - mp_hdr;
- 	if((map = mmap(NULL, mp_hdrsz, PROT_READ, MAP_PRIVATE, desc, mp_hdr))==MAP_FAILED) {
- 	    cli_errmsg("is_parse_hdr: mmap failed\n");
- 	    return CL_EMEM;
- 	}
- 	hdr = map + c->hdr - mp_hdr;
- #else
- 	cli_warnmsg("is_parse_hdr: hdr too big and mmap is not usable\n");
- 	return CL_CLEAN;
- #endif
-     }
- 
-     h1 = (struct IS_HDR *)hdr;
-     if(!CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)h1), sizeof(*h1))) {
+     if(!(h1 = fmap_need_off(map, c->hdr, c->hdrsz))) {
  	cli_dbgmsg("is_parse_hdr: not enough room for H1\n");
- 	IS_FREE_HDR;
  	return CL_CLEAN;
      }
+     hdr = (char *)h1;
      h1_data_off = le32_to_host(h1->data_off);
-     objs = (struct IS_OBJECTS *)(hdr + h1_data_off);
-     if(!CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)objs), sizeof(*objs))) {
- 	cli_dbgmsg("is_parse_hdr: not enough room for OBJECTS\n");
- 	IS_FREE_HDR;
- 	return CL_CLEAN;
+     objs = (struct IS_OBJECTS *)fmap_need_ptr(map, hdr + h1_data_off, sizeof(*objs));
+     if(!objs) {
+         cli_dbgmsg("is_parse_hdr: not enough room for OBJECTS\n");
+         funmap(map);
+         return CL_CLEAN;
      }
  
      cli_dbgmsg("is_parse_hdr: magic %x, unk1 %x, unk2 %x, data_off %x, data_sz %x\n",
- 	       h1->magic, h1->unk1, h1->unk2, h1_data_off, h1->data_sz);
+                h1->magic, h1->unk1, h1->unk2, h1_data_off, h1->data_sz);
      if(le32_to_host(h1->magic) != 0x28635349) {
- 	cli_dbgmsg("is_parse_hdr: bad magic. wrong version?\n");
- 	IS_FREE_HDR;
- 	return CL_CLEAN;
+         cli_dbgmsg("is_parse_hdr: bad magic. wrong version?\n");
+         funmap(map);
+         return CL_CLEAN;
      }
  
+     fmap_unneed_ptr(map, h1, sizeof(*h1));
+ 
  /*     cli_errmsg("COMPONENTS\n"); */
  /*     off = le32_to_host(objs->comps_off) + h1_data_off; */
  /*     for(i=1;  ; i++) { */
@@@ -583,11 -551,12 +550,12 @@@
  
      objs_files_cnt = le32_to_host(objs->files_cnt);
      off = h1_data_off + objs_dirs_off + le32_to_host(objs->dir_sz2);
+     fmap_unneed_ptr(map, objs, sizeof(*objs));
      for(i=0; i<objs_files_cnt ;i++) {
- 	struct IS_FILEITEM *file = (struct IS_FILEITEM *)(&hdr[off]);
+ 	struct IS_FILEITEM *file = (struct IS_FILEITEM *)fmap_need_off(map, c->hdr + off, sizeof(*file));
  
- 	if(CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)file), sizeof(*file))) {
- 	    const char *dir_name = "", *file_name = "";
+ 	if(file) {
+ 	    const char *emptyname = "", *dir_name = emptyname, *file_name = emptyname;
  	    uint32_t dir_rel = h1_data_off + objs_dirs_off + 4 * le32_to_host(file->dir_id); /* rel off of dir entry from array of rel ptrs */
  	    uint32_t file_rel = objs_dirs_off + h1_data_off + le32_to_host(file->str_name_off); /* rel off of fname */
  	    uint64_t file_stream_off, file_size, file_csize;
@@@ -595,12 -564,12 +563,12 @@@
  
  	    memcpy(hash, file->md5, 16);
  	    md5str((uint8_t *)hash);
- 	    if(CLI_ISCONTAINED(hdr, c->hdrsz, &hdr[dir_rel], 4)) {
+ 	    if(fmap_need_ptr_once(map, &hdr[dir_rel], 4)) {
  		dir_rel = cli_readint32(&hdr[dir_rel]) + h1_data_off + objs_dirs_off;
- 		if(CLI_ISCONTAINED(hdr, c->hdrsz, &hdr[dir_rel], 1) && memchr(&hdr[dir_rel], 0, c->hdrsz - dir_rel))
+ 		if(fmap_need_str(map, &hdr[dir_rel], c->hdrsz - dir_rel))
  		    dir_name = &hdr[dir_rel];
  	    }
- 	    if(CLI_ISCONTAINED(hdr, c->hdrsz, &hdr[file_rel], 1) && memchr(&hdr[file_rel], 0, c->hdrsz - file_rel))
+ 	    if(fmap_need_str(map, &hdr[file_rel], c->hdrsz - file_rel))
  		file_name = &hdr[file_rel];
  		
  	    file_stream_off = le64_to_host(file->stream_off);
@@@ -640,10 -609,13 +608,13 @@@
  				scanned++;
  				if (ctx->engine->maxfiles && scanned >= ctx->engine->maxfiles) {
  				    cli_dbgmsg("is_parse_hdr: File limit reached (max: %u)\n", ctx->engine->maxfiles);
- 				    IS_FREE_HDR;
+ 				    if(file_name != emptyname)
+ 					fmap_unneed_ptr(map, (void *)file_name, strlen(file_name)+1);
+ 				    if(dir_name != emptyname)
+ 					fmap_unneed_ptr(map, (void *)dir_name, strlen(dir_name)+1);
  				    return CL_EMAXFILES;
  				}
- 				cabret = is_extract_cab(desc, ctx, file_stream_off + c->cabs[j].off, file_size, file_csize);
+ 				cabret = is_extract_cab(ctx, file_stream_off + c->cabs[j].off, file_size, file_csize);
  			    } else {
  				ret = CL_CLEAN;
   				cli_dbgmsg("is_parse_hdr: stream out of file\n");
@@@ -657,7 -629,10 +628,10 @@@
  			    cabret = CL_CLEAN;
  			}
  			if(cabret != CL_CLEAN) {
- 			    IS_FREE_HDR;
+ 			    if(file_name != emptyname)
+ 				fmap_unneed_ptr(map, (void *)file_name, strlen(file_name)+1);
+ 			    if(dir_name != emptyname)
+ 				fmap_unneed_ptr(map, (void *)dir_name, strlen(dir_name)+1);
  			    return cabret;
  			}
  		    } else {
@@@ -668,13 -643,17 +642,17 @@@
  	    default:
  		cli_dbgmsg("is_parse_hdr: skipped unknown file entry %u\n", i);
  	    }
+ 	    if(file_name != emptyname)
+ 		fmap_unneed_ptr(map, (void *)file_name, strlen(file_name)+1);
+ 	    if(dir_name != emptyname)
+ 		fmap_unneed_ptr(map, (void *)dir_name, strlen(dir_name)+1);
+ 	    fmap_unneed_ptr(map, file, sizeof(*file));
  	} else {
  	    ret = CL_CLEAN;
  	    cli_dbgmsg("is_parse_hdr: FILEITEM out of bounds\n");
  	}
  	off += sizeof(*file);
      }
-     IS_FREE_HDR;
      return ret;
  }
  
@@@ -694,55 -673,25 +672,25 @@@ static void md5str(uint8_t *sum) 
  
  #define IS_CABBUFSZ 65536
  
- static int is_extract_cab(int desc, cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize) {
+ static int is_extract_cab(cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize) {
      uint8_t *inbuf, *outbuf;
      char *tempfile;
-     FILE *in;
      int ofd, ret = CL_CLEAN;
      z_stream z;
      uint64_t outsz = 0;
      int success = 0;
+     fmap_t *map = *ctx->fmap;
  
-     if((ofd=dup(desc)) < 0) {
- 	cli_errmsg("is_extract_cab: dup failed\n");
- 	return CL_EDUP;
-     }
-     if(!(in = fdopen(ofd, "rb"))) {
- 	cli_errmsg("is_extract_cab: fdopen failed\n");
- 	close(ofd);
- 	return CL_EOPEN;
-     }
- #if HAVE_FSEEKO
-     if(fseeko(in, (off_t)off, SEEK_SET))
- #else
-     if(fseek(in, (long)off, SEEK_SET))
- #endif
-     {
- 	cli_dbgmsg("is_extract_cab: fseek failed\n");
- 	fclose(in);
- 	return CL_ESEEK;
-     }
-     if(!(inbuf = cli_malloc(IS_CABBUFSZ))) {
- 	fclose(in);
- 	return CL_EMEM;
-     }
-     if(!(outbuf = cli_malloc(IS_CABBUFSZ))) {
- 	free(inbuf);
- 	fclose(in);
+     if(!(outbuf = cli_malloc(IS_CABBUFSZ)))
  	return CL_EMEM;
-     }
+ 
      if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) {
- 	free(inbuf);
  	free(outbuf);
- 	fclose(in);
- 	return CL_EMEM;
      }
      if((ofd = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR)) < 0) {
  	cli_errmsg("is_extract_cab: failed to create file %s\n", tempfile);
  	free(tempfile);
- 	free(inbuf);
  	free(outbuf);
- 	fclose(in);
  	return CL_ECREAT;
      }
  
@@@ -754,11 -703,12 +702,12 @@@
  	    break;
  	}
  	csize -= 2;
- 	if(!fread(outbuf, 2, 1, in)) {
+ 	if(!(inbuf = fmap_need_off_once(map, off, 2))) {
  	    cli_dbgmsg("is_extract_cab: short read for chunk size\n");
  	    break;
  	}
- 	chunksz = outbuf[0] | (outbuf[1] << 8);
+ 	off += 2;
+ 	chunksz = inbuf[0] | (inbuf[1] << 8);
  	if(!chunksz) {
  	    cli_dbgmsg("is_extract_cab: zero sized chunk\n");
  	    continue;
@@@ -768,10 -718,11 +717,11 @@@
  	    break;
  	}
  	csize -= chunksz;
- 	if(!fread(inbuf, chunksz, 1, in)) {
+ 	if(!(inbuf = fmap_need_off_once(map, off, chunksz))) {
  	    cli_dbgmsg("is_extract_cab: short read for chunk\n");
  	    break;
  	}
+ 	off += chunksz;
  	memset(&z, 0, sizeof(z));
  	inflateInit2(&z, -MAX_WBITS);
  	z.next_in = (uint8_t *)inbuf;
@@@ -804,8 -755,6 +754,6 @@@
  	inflateEnd(&z);
  	if(!success) break;
      }
-     fclose(in);
-     free(inbuf);
      free(outbuf);
      if(success) {
  	if (outsz != size)
diff --combined libclamav/libclamav.map
index 0654dbc,dba0127..5da8320
--- a/libclamav/libclamav.map
+++ b/libclamav/libclamav.map
@@@ -32,7 -32,6 +32,7 @@@ CLAMAV_PUBLIC 
  };
  CLAMAV_PRIVATE {
    global:
 +    cli_gettmpdir;
      cli_strtok;
      cli_strtokenize;
      cli_cvdunpack;
@@@ -63,7 -62,7 +63,7 @@@
      cli_str2hex;
      cli_md5file;
      cli_md5stream;
-     html_normalise_fd;
+     html_normalise_map;
      cli_utf16toascii;
  
      cli_malloc;
@@@ -156,6 -155,8 +156,8 @@@
      cli_bytecode_context_setparam_ptr;
      cli_bytecode_context_getresult_int;
      cli_bytecode_context_clear;
+     fmap;
+     funmap;
    local:
      *;
  };
diff --combined libclamav/macho.c
index a158ae9,5caeed6..5a1e43d
--- a/libclamav/macho.c
+++ b/libclamav/macho.c
@@@ -176,7 -176,7 +176,7 @@@ struct macho_fat_arc
      if(DETECT_BROKEN) {					    \
  	if(ctx->virname)				    \
  	    *ctx->virname = "Broken.Executable";	    \
 -	return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;  \
 +	return CL_VIRUS;				    \
      }							    \
      return CL_EFORMAT
  
@@@ -201,7 -201,7 +201,7 @@@ static uint32_t cli_rawaddr(uint32_t va
      return vaddr - sects[i].rva + sects[i].raw;
  }
  
- int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
+ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
  {
  	struct macho_hdr hdr;
  	struct macho_load_cmd load_cmd;
@@@ -213,14 -213,17 +213,17 @@@
  	unsigned int arch = 0, ep = 0, err;
  	struct cli_exe_section *sections = NULL;
  	char name[16];
+ 	fmap_t *map = *ctx->fmap;
+ 	ssize_t at;
  
      if(fileinfo)
  	matcher = 1;
  
-     if(read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+     if(fmap_readn(map, &hdr, 0, sizeof(hdr)) != sizeof(hdr)) {
  	cli_dbgmsg("cli_scanmacho: Can't read header\n");
  	return matcher ? -1 : CL_EFORMAT;
      }
+     at = sizeof(hdr);
  
      if(hdr.magic == 0xfeedface) {
  	conv = 0;
@@@ -311,7 -314,7 +314,7 @@@
      }
  
      if(m64)
- 	lseek(fd, 4, SEEK_CUR);
+ 	at += 4;
  
      hdr.ncmds = EC32(hdr.ncmds, conv);
      if(!hdr.ncmds || hdr.ncmds > 1024) {
@@@ -320,11 -323,12 +323,12 @@@
      }
  
      for(i = 0; i < hdr.ncmds; i++) {
- 	if(read(fd, &load_cmd, sizeof(load_cmd)) != sizeof(load_cmd)) {
+ 	if(fmap_readn(map, &load_cmd, at, sizeof(load_cmd)) != sizeof(load_cmd)) {
  	    cli_dbgmsg("cli_scanmacho: Can't read load command\n");
  	    free(sections);
  	    RETURN_BROKEN;
  	}
+ 	at += sizeof(load_cmd);
  	/*
  	if((m64 && EC32(load_cmd.cmdsize, conv) % 8) || (!m64 && EC32(load_cmd.cmdsize, conv) % 4)) {
  	    cli_dbgmsg("cli_scanmacho: Invalid command size (%u)\n", EC32(load_cmd.cmdsize, conv));
@@@ -335,19 -339,21 +339,21 @@@
  	load_cmd.cmd = EC32(load_cmd.cmd, conv);
  	if((m64 && load_cmd.cmd == 0x19) || (!m64 && load_cmd.cmd == 0x01)) { /* LC_SEGMENT */
  	    if(m64) {
- 		if(read(fd, &segment_cmd64, sizeof(segment_cmd64)) != sizeof(segment_cmd64)) {
+ 		if(fmap_readn(map, &segment_cmd64, at, sizeof(segment_cmd64)) != sizeof(segment_cmd64)) {
  		    cli_dbgmsg("cli_scanmacho: Can't read segment command\n");
  		    free(sections);
  		    RETURN_BROKEN;
  		}
+ 		at += sizeof(segment_cmd64);
  		nsects = EC32(segment_cmd64.nsects, conv);
  		strncpy(name, segment_cmd64.segname, 16);
  	    } else {
- 		if(read(fd, &segment_cmd, sizeof(segment_cmd)) != sizeof(segment_cmd)) {
+ 		if(fmap_readn(map, &segment_cmd, at, sizeof(segment_cmd)) != sizeof(segment_cmd)) {
  		    cli_dbgmsg("cli_scanmacho: Can't read segment command\n");
  		    free(sections);
  		    RETURN_BROKEN;
  		}
+ 		at += sizeof(segment_cmd);
  		nsects = EC32(segment_cmd.nsects, conv);
  		strncpy(name, segment_cmd.segname, 16);
  	    }
@@@ -374,11 -380,12 +380,12 @@@
  
  	    for(j = 0; j < nsects; j++) {
  		if(m64) {
- 		    if(read(fd, &section64, sizeof(section64)) != sizeof(section64)) {
+ 		    if(fmap_readn(map, &section64, at, sizeof(section64)) != sizeof(section64)) {
  			cli_dbgmsg("cli_scanmacho: Can't read section\n");
  			free(sections);
  			RETURN_BROKEN;
  		    }
+ 		    at += sizeof(section64);
  		    sections[sect].rva = EC64(section64.addr, conv);
  		    sections[sect].vsz = EC64(section64.size, conv);
  		    sections[sect].raw = EC32(section64.offset, conv);
@@@ -386,11 -393,12 +393,12 @@@
  		    sections[sect].rsz = sections[sect].vsz + (section64.align - (sections[sect].vsz % section64.align)) % section64.align; /* most likely we can assume it's the same as .vsz */
  		    strncpy(name, section64.sectname, 16);
  		} else {
- 		    if(read(fd, &section, sizeof(section)) != sizeof(section)) {
+ 		    if(fmap_readn(map, &section, at, sizeof(section)) != sizeof(section)) {
  			cli_dbgmsg("cli_scanmacho: Can't read section\n");
  			free(sections);
  			RETURN_BROKEN;
  		    }
+ 		    at += sizeof(section);
  		    sections[sect].rva = EC32(section.addr, conv);
  		    sections[sect].vsz = EC32(section.size, conv);
  		    sections[sect].raw = EC32(section.offset, conv);
@@@ -414,17 -422,18 +422,18 @@@
  		cli_dbgmsg("MACHO: ------------------\n");
  
  	} else if(arch && (load_cmd.cmd == 0x4 || load_cmd.cmd == 0x5)) { /* LC_(UNIX)THREAD */
- 	    lseek(fd, 8, SEEK_CUR);
+ 	    at += 8;
  	    switch(arch) {
  		case 1: /* x86 */
  		{
  			struct macho_thread_state_x86 thread_state_x86;
  
- 		    if(read(fd, &thread_state_x86, sizeof(thread_state_x86)) != sizeof(thread_state_x86)) {
+ 		    if(fmap_readn(map, &thread_state_x86, at, sizeof(thread_state_x86)) != sizeof(thread_state_x86)) {
  			cli_dbgmsg("cli_scanmacho: Can't read thread_state_x86\n");
  			free(sections);
  			RETURN_BROKEN;
  		    }
+ 		    at += sizeof(thread_state_x86);
  		    break;
  		}
  
@@@ -432,11 -441,12 +441,12 @@@
  		{
  			struct macho_thread_state_ppc thread_state_ppc;
  
- 		    if(read(fd, &thread_state_ppc, sizeof(thread_state_ppc)) != sizeof(thread_state_ppc)) {
+ 		    if(fmap_readn(map, &thread_state_ppc, at, sizeof(thread_state_ppc)) != sizeof(thread_state_ppc)) {
  			cli_dbgmsg("cli_scanmacho: Can't read thread_state_ppc\n");
  			free(sections);
  			RETURN_BROKEN;
  		    }
+ 		    at += sizeof(thread_state_ppc);
  		    ep = EC32(thread_state_ppc.srr0, conv);
  		    break;
  		}
@@@ -445,11 -455,12 +455,12 @@@
  		{
  			struct macho_thread_state_ppc64 thread_state_ppc64;
  
- 		    if(read(fd, &thread_state_ppc64, sizeof(thread_state_ppc64)) != sizeof(thread_state_ppc64)) {
+ 		    if(fmap_readn(map, &thread_state_ppc64, at, sizeof(thread_state_ppc64)) != sizeof(thread_state_ppc64)) {
  			cli_dbgmsg("cli_scanmacho: Can't read thread_state_ppc64\n");
  			free(sections);
  			RETURN_BROKEN;
  		    }
+ 		    at += sizeof(thread_state_ppc64);
  		    ep = EC64(thread_state_ppc64.srr0, conv);
  		    break;
  		}
@@@ -460,7 -471,7 +471,7 @@@
  	    }
  	} else {
  	    if(EC32(load_cmd.cmdsize, conv) > sizeof(load_cmd))
- 		lseek(fd, EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd), SEEK_CUR);
+ 		at += EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd);
  	}
      }
  
@@@ -490,12 -501,14 +501,14 @@@
      }
  }
  
- int cli_machoheader(int fd, struct cli_exe_info *fileinfo)
+ int cli_machoheader(fmap_t *map, struct cli_exe_info *fileinfo)
  {
-     return cli_scanmacho(fd, NULL, fileinfo);
+     cli_ctx ctx;
+     ctx.fmap = &map;
+     return cli_scanmacho(&ctx, fileinfo);
  }
  
- int cli_scanmacho_unibin(int fd, cli_ctx *ctx)
+ int cli_scanmacho_unibin(cli_ctx *ctx)
  {
  	struct macho_fat_header fat_header;
  	struct macho_fat_arch fat_arch;
@@@ -503,16 -516,14 +516,14 @@@
  	int ret = CL_CLEAN;
  	struct stat sb;
  	off_t pos;
+ 	fmap_t *map = *ctx->fmap;
+ 	ssize_t at;
  
-     if(fstat(fd, &sb) == -1) {
- 	cli_dbgmsg("cli_scanmacho_unibin: fstat failed for fd %d\n", fd);
- 	return CL_ESTAT;
-     }
- 
-     if(read(fd, &fat_header, sizeof(fat_header)) != sizeof(fat_header)) {
+     if(fmap_readn(map, &fat_header, 0, sizeof(fat_header)) != sizeof(fat_header)) {
  	cli_dbgmsg("cli_scanmacho_unibin: Can't read fat_header\n");
  	return CL_EFORMAT;
      }
+     at = sizeof(fat_header);
  
      if(fat_header.magic == 0xcafebabe) {
  	conv = 0;
@@@ -533,18 -544,17 +544,17 @@@
      }
      cli_dbgmsg("UNIBIN: Number of architectures: %u\n", (unsigned int) fat_header.nfats);
      for(i = 0; i < fat_header.nfats; i++) {
- 	if(read(fd, &fat_arch, sizeof(fat_arch)) != sizeof(fat_arch)) {
+ 	if(fmap_readn(map, &fat_arch, at, sizeof(fat_arch)) != sizeof(fat_arch)) {
  	    cli_dbgmsg("cli_scanmacho_unibin: Can't read fat_arch\n");
  	    RETURN_BROKEN;
  	}
- 	pos = lseek(fd, 0, SEEK_CUR);
+ 	at += sizeof(fat_arch);
  	fat_arch.offset = EC32(fat_arch.offset, conv);
  	fat_arch.size = EC32(fat_arch.size, conv);
  	cli_dbgmsg("UNIBIN: Binary %u of %u\n", i + 1, fat_header.nfats);
  	cli_dbgmsg("UNIBIN: File offset: %u\n", fat_arch.offset);
  	cli_dbgmsg("UNIBIN: File size: %u\n", fat_arch.size);
- 	ret = cli_dumpscan(fd, fat_arch.offset, fat_arch.size, ctx);
- 	lseek(fd, pos, SEEK_SET);
+ 	ret = cli_dumpscan(map->fd, fat_arch.offset, fat_arch.size, ctx);
  	if(ret == CL_VIRUS)
  	    break;
      }
diff --combined libclamav/matcher-ac.c
index f1a2537,5d0f64b..efe859e
--- a/libclamav/matcher-ac.c
+++ b/libclamav/matcher-ac.c
@@@ -47,36 -47,9 +47,36 @@@
  
  #define AC_SPECIAL_ALT_CHAR	1
  #define AC_SPECIAL_ALT_STR	2
 -#define AC_SPECIAL_LINE_START	3
 -#define AC_SPECIAL_LINE_END	4
 -#define AC_SPECIAL_BOUNDARY	5
 +#define AC_SPECIAL_LINE_MARKER	3
 +#define AC_SPECIAL_BOUNDARY	4
 +
 +#define AC_BOUNDARY_LEFT		1
 +#define AC_BOUNDARY_LEFT_NEGATIVE	2
 +#define AC_BOUNDARY_RIGHT		4
 +#define AC_BOUNDARY_RIGHT_NEGATIVE	8
 +#define AC_LINE_MARKER_LEFT		16
 +#define AC_LINE_MARKER_LEFT_NEGATIVE	32
 +#define AC_LINE_MARKER_RIGHT		64
 +#define AC_LINE_MARKER_RIGHT_NEGATIVE	128
 +
 +static char boundary[256] = {
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    3, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 1, 3, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 
 +    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 +};
  
  int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern)
  {
@@@ -724,17 -697,8 +724,17 @@@ int cli_ac_chklsig(const char *expr, co
  		    }									\
  		    break;								\
  											\
 +		case AC_SPECIAL_LINE_MARKER:						\
 +		    if(b == '\n') {							\
 +			match = !special->negative;					\
 +		    } else if(b == '\r' && (bp + 1 < length && buffer[bp + 1] == '\n')) {   \
 +			bp++;								\
 +			match = !special->negative;					\
 +		    }									\
 +		    break;								\
 +											\
  		case AC_SPECIAL_BOUNDARY:						\
 -		    if(memchr("\x22\x27\x20\x2f\x3d\x2d\x5f\x3e\x0a\x0d", b, 10))	\
 +		    if(boundary[b])							\
  			match = !special->negative;					\
  		    break;								\
  											\
@@@ -760,7 -724,7 +760,7 @@@
  	    match = 0;									\
      }
  
 -inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
 +inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t fileoffset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
  {
  	uint32_t bp, match;
  	uint16_t wc, i, j, specialcnt = pattern->special_pattern;
@@@ -781,38 -745,6 +781,38 @@@
      }
      *end = bp;
  
 +    if(pattern->boundary & AC_BOUNDARY_LEFT) {
 +	match = !!(pattern->boundary & AC_BOUNDARY_LEFT_NEGATIVE);
 +	if(!fileoffset || (offset && (boundary[buffer[offset - 1]] == 1 || boundary[buffer[offset - 1]] == 3)))
 +	    match = !match;
 +	if(!match)
 +	    return 0;
 +    }
 +
 +    if(pattern->boundary & AC_BOUNDARY_RIGHT) {
 +	match = !!(pattern->boundary & AC_BOUNDARY_RIGHT_NEGATIVE);
 +	if((length <= SCANBUFF) && (bp == length || boundary[buffer[bp]] >= 2))
 +	    match = !match;
 +	if(!match)
 +	    return 0;
 +    }
 +
 +    if(pattern->boundary & AC_LINE_MARKER_LEFT) {
 +	match = !!(pattern->boundary & AC_LINE_MARKER_LEFT_NEGATIVE);
 +	if(!fileoffset || (offset && (buffer[offset - 1] == '\n')))
 +	    match = !match;
 +	if(!match)
 +	    return 0;
 +    }
 +
 +    if(pattern->boundary & AC_LINE_MARKER_RIGHT) {
 +	match = !!(pattern->boundary & AC_LINE_MARKER_RIGHT_NEGATIVE);
 +	if((length <= SCANBUFF) && (bp == length || buffer[bp] == '\n' || (buffer[bp] == '\r' && bp + 1 < length && buffer[bp + 1] == '\n')))
 +	    match = !match;
 +	if(!match)
 +	    return 0;
 +    }
 +
      if(!(pattern->ch[1] & CLI_MATCH_IGNORE)) {
  	bp += pattern->ch_mindist[1];
  	for(i = pattern->ch_mindist[1]; i <= pattern->ch_maxdist[1]; i++) {
@@@ -922,28 -854,23 +922,23 @@@ int cli_ac_initdata(struct cli_ac_data 
      return CL_SUCCESS;
  }
  
- int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, int fd)
+ int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, fmap_t *map)
  {
  	int ret;
  	unsigned int i;
  	struct cli_ac_patt *patt;
  	struct cli_target_info info;
- 	struct stat sb;
  
-     if(fd != -1) {
+     if(map) {
  	memset(&info, 0, sizeof(info));
- 	if(fstat(fd, &sb) == -1) {
- 	    cli_errmsg("cli_ac_caloff: fstat(%d) failed\n", fd);
- 	    return CL_ESTAT;
- 	}
- 	info.fsize = sb.st_size;
+ 	info.fsize = map->len;
      }
  
      for(i = 0; i < root->ac_reloff_num; i++) {
  	patt = root->ac_reloff[i];
- 	if(fd == -1) {
+ 	if(!map) {
  	    data->offset[patt->offset_min] = CLI_OFF_NONE;
- 	} else if((ret = cli_caloff(NULL, &info, fd, root->type, patt->offdata, &data->offset[patt->offset_min], &data->offset[patt->offset_max]))) {
+ 	} else if((ret = cli_caloff(NULL, &info, map, root->type, patt->offdata, &data->offset[patt->offset_min], &data->offset[patt->offset_max]))) {
  	    cli_errmsg("cli_ac_caloff: Can't calculate relative offset in signature for %s\n", patt->virname);
  	    if(info.exeinfo.section)
  		free(info.exeinfo.section);
@@@ -952,7 -879,7 +947,7 @@@
  	    data->offset[patt->offset_min] = CLI_OFF_NONE;
  	}
      }
-     if(fd != -1 && info.exeinfo.section)
+     if(map && info.exeinfo.section)
  	free(info.exeinfo.section);
  
      return CL_SUCCESS;
@@@ -1032,7 -959,7 +1027,7 @@@ int cli_ac_scanbuff(const unsigned cha
      if(!root->ac_root)
  	return CL_CLEAN;
  
 -    if(!mdata) {
 +    if(!mdata && (root->ac_partsigs || root->ac_lsigs || root->ac_reloff_num)) {
  	cli_errmsg("cli_ac_scanbuff: mdata == NULL\n");
  	return CL_ENULLARG;
      }
@@@ -1069,7 -996,7 +1064,7 @@@
  		    }
  		}
  		pt = patt;
 -		if(ac_findmatch(buffer, bp, length, patt, &matchend)) {
 +		if(ac_findmatch(buffer, bp, offset + bp - patt->prefix_length, length, patt, &matchend)) {
  		    while(pt) {
  			if((pt->type && !(mode & AC_SCAN_FT)) || (!pt->type && !(mode & AC_SCAN_VIR))) {
  			    pt = pt->next_same;
@@@ -1171,7 -1098,7 +1166,7 @@@
  				} else { /* !pt->type */
  				    if(pt->lsigid[0]) {
  					mdata->lsigcnt[pt->lsigid[1]][pt->lsigid[2]]++;
 -					pt = pt->next;
 +					pt = pt->next_same;
  					continue;
  				    }
  
@@@ -1184,7 -1111,7 +1179,7 @@@
  					newres->next = *res;
  					*res = newres;
  
 -					pt = pt->next;
 +					pt = pt->next_same;
  					continue;
  				    } else {
  					if(virname)
@@@ -1213,7 -1140,7 +1208,7 @@@
  			    } else {
  				if(pt->lsigid[0]) {
  				    mdata->lsigcnt[pt->lsigid[1]][pt->lsigid[2]]++;
 -				    pt = pt->next;
 +				    pt = pt->next_same;
  				    continue;
  				}
  
@@@ -1226,7 -1153,7 +1221,7 @@@
  				    newres->next = *res;
  				    *res = newres;
  
 -				    pt = pt->next;
 +				    pt = pt->next_same;
  				    continue;
  				} else {
  				    if(virname)
@@@ -1408,6 -1335,7 +1403,6 @@@ int cli_ac_addsig(struct cli_matcher *r
  		}
  	    }
  	    strcat(hexnew, start);
 -	    strcat(hexnew, "()");
  
  	    if(!(start = strchr(pt, ')'))) {
  		mpool_free(root->mempool, newspecial);
@@@ -1420,37 -1348,6 +1415,37 @@@
  		error = CL_EMALFDB;
  		break;
  	    }
 +
 +	    if(!strcmp(pt, "B")) {
 +		if(!*start) {
 +		    new->boundary |= AC_BOUNDARY_RIGHT;
 +		    if(newspecial->negative)
 +			new->boundary |= AC_BOUNDARY_RIGHT_NEGATIVE;
 +		    mpool_free(root->mempool, newspecial);
 +		    continue;
 +		} else if(pt - 1 == hexcpy) {
 +		    new->boundary |= AC_BOUNDARY_LEFT;
 +		    if(newspecial->negative)
 +			new->boundary |= AC_BOUNDARY_LEFT_NEGATIVE;
 +		    mpool_free(root->mempool, newspecial);
 +		    continue;
 +		}
 +	    } else if(!strcmp(pt, "L")) {
 +		if(!*start) {
 +		    new->boundary |= AC_LINE_MARKER_RIGHT;
 +		    if(newspecial->negative)
 +			new->boundary |= AC_LINE_MARKER_RIGHT_NEGATIVE;
 +		    mpool_free(root->mempool, newspecial);
 +		    continue;
 +		} else if(pt - 1 == hexcpy) {
 +		    new->boundary |= AC_LINE_MARKER_LEFT;
 +		    if(newspecial->negative)
 +			new->boundary |= AC_LINE_MARKER_LEFT_NEGATIVE;
 +		    mpool_free(root->mempool, newspecial);
 +		    continue;
 +		}
 +	    }
 +	    strcat(hexnew, "()");
  	    new->special++;
  	    newtable = (struct cli_ac_special **) mpool_realloc(root->mempool, new->special_table, new->special * sizeof(struct cli_ac_special *));
  	    if(!newtable) {
@@@ -1465,9 -1362,11 +1460,9 @@@
  
  	    if(!strcmp(pt, "B")) {
  		newspecial->type = AC_SPECIAL_BOUNDARY;
 -	    /* TODO
 -	    } else if(strcmp(pt, "S")) {
 -		newspecial->type = AC_SPECIAL_LINE_START;
 -	    } else if(strcmp(pt, "E")) {
 -		newspecial->type = AC_SPECIAL_LINE_END;
 +	    } else if(!strcmp(pt, "L")) {
 +		newspecial->type = AC_SPECIAL_LINE_MARKER;
 +	    /*
  	    } else if(strcmp(pt, "W")) {
  		newspecial->type = AC_SPECIAL_WHITE;
  	    */
@@@ -1638,7 -1537,7 +1633,7 @@@
      if(new->lsigid[0])
  	root->ac_lsigtable[new->lsigid[1]]->virname = new->virname;
  
-     ret = cli_caloff(offset, NULL, -1, root->type, new->offdata, &new->offset_min, &new->offset_max);
+     ret = cli_caloff(offset, NULL, NULL, root->type, new->offdata, &new->offset_min, &new->offset_max);
      if(ret != CL_SUCCESS) {
  	mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
  	mpool_ac_free_special(root->mempool, new);
diff --combined libclamav/matcher-ac.h
index f18f3c6,1bc5bab..c69a701
--- a/libclamav/matcher-ac.h
+++ b/libclamav/matcher-ac.h
@@@ -25,6 -25,7 +25,7 @@@
  
  #include "filetypes.h"
  #include "cltypes.h"
+ #include "fmap.h"
  
  #define AC_CH_MAXDIST 32
  
@@@ -61,7 -62,6 +62,7 @@@ struct cli_ac_patt 
      uint8_t depth;
      uint16_t rtype, type;
      uint32_t offdata[4], offset_min, offset_max;
 +    uint32_t boundary;
  };
  
  struct cli_ac_node {
@@@ -87,7 -87,7 +88,7 @@@ void cli_ac_freedata(struct cli_ac_dat
  int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx);
  int cli_ac_buildtrie(struct cli_matcher *root);
  int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth);
- int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, int fd);
+ int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, fmap_t *map);
  void cli_ac_free(struct cli_matcher *root);
  int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t rtype, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, const uint32_t *lsigid, unsigned int options);
  
diff --combined libclamav/matcher-bm.c
index 05de59d,b32727a..5c42164
--- a/libclamav/matcher-bm.c
+++ b/libclamav/matcher-bm.c
@@@ -51,7 -51,7 +51,7 @@@ int cli_bm_addpatt(struct cli_matcher *
  	return CL_EMALFDB;
      }
  
-     if((ret = cli_caloff(offset, NULL, -1, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
+     if((ret = cli_caloff(offset, NULL, NULL, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
  	cli_errmsg("cli_bm_addpatt: Can't calculate offset for signature %s\n", pattern->virname);
  	return ret;
      }
@@@ -145,26 -145,21 +145,21 @@@ static int qcompare(const void *a, cons
      return *(const uint32_t *)a - *(const uint32_t *)b;
  }
  
- int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, int fd)
+ int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, fmap_t *map)
  {
  	int ret;
  	unsigned int i;
  	struct cli_bm_patt *patt;
  	struct cli_target_info info;
  
  
      if(!root->bm_patterns) {
 -	data->offtab = data->offset = 0;
 +	data->offtab = data->offset = NULL;
  	data->cnt = data->pos = 0;
  	return CL_SUCCESS;
      }
      memset(&info, 0, sizeof(info));
-     if(fstat(fd, &sb) == -1) {
- 	cli_errmsg("cli_bm_initoff: fstat(%d) failed\n", fd);
- 	return CL_ESTAT;
-     }
-     info.fsize = sb.st_size;
+     info.fsize = map->len;
  
      data->cnt = data->pos = 0;
      data->offtab = (uint32_t *) cli_malloc(root->bm_patterns * sizeof(uint32_t));
@@@ -183,7 -178,7 +178,7 @@@
  	if(patt->offdata[0] == CLI_OFF_ABSOLUTE) {
  	    data->offtab[data->cnt] = patt->offset_min + patt->prefix_length;
  	    data->cnt++;
- 	} else if((ret = cli_caloff(NULL, &info, fd, root->type, patt->offdata, &data->offset[patt->offset_min], NULL))) {
+ 	} else if((ret = cli_caloff(NULL, &info, map, root->type, patt->offdata, &data->offset[patt->offset_min], NULL))) {
  	    cli_errmsg("cli_bm_initoff: Can't calculate relative offset in signature for %s\n", patt->virname);
  	    if(info.exeinfo.section)
  		free(info.exeinfo.section);
@@@ -243,7 -238,7 +238,7 @@@ void cli_bm_free(struct cli_matcher *ro
      }
  }
  
- int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, int fd, struct cli_bm_off *offdata)
 -int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, fmap_t *map, struct cli_bm_off *offdata)
++int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, fmap_t *map, struct cli_bm_off *offdata)
  {
  	uint32_t i, j, off, off_min, off_max;
  	uint8_t found, pchain, shift;
@@@ -339,17 -334,10 +334,17 @@@
  		    }
  		}
  
 +		if(found && (p->boundary & BM_BOUNDARY_EOL)) {
 +		    if(off != length) {
 +			p = p->next;
 +			continue;
 +		    }
 +		}
 +
  		if(found && p->length + p->prefix_length == j) {
  		    if(!offdata && (p->offset_min != CLI_OFF_ANY)) {
  			if(p->offdata[0] != CLI_OFF_ABSOLUTE) {
- 			    ret = cli_caloff(NULL, &info, fd, root->type, p->offdata, &off_min, &off_max);
+ 			    ret = cli_caloff(NULL, &info, map, root->type, p->offdata, &off_min, &off_max);
  			    if(ret != CL_SUCCESS) {
  				cli_errmsg("cli_bm_scanbuff: Can't calculate relative offset in signature for %s\n", p->virname);
  				if(info.exeinfo.section)
@@@ -361,15 -349,13 +356,15 @@@
  			    off_max = p->offset_max;
  			}
  			off = offset + i - p->prefix_length - BM_MIN_LENGTH + BM_BLOCK_SIZE;
 -			if(off_max < off || off_min > off) {
 +			if(off_min == CLI_OFF_NONE || off_max < off || off_min > off) {
  			    p = p->next;
  			    continue;
  			}
  		    }
  		    if(virname)
  			*virname = p->virname;
 +		    if(patt)
 +			*patt = p;
  		    if(info.exeinfo.section)
  			free(info.exeinfo.section);
  		    return CL_VIRUS;
diff --combined libclamav/matcher-bm.h
index 3996e98,a1ec133..6fe480f
--- a/libclamav/matcher-bm.h
+++ b/libclamav/matcher-bm.h
@@@ -24,9 -24,8 +24,10 @@@
  #include "matcher.h"
  #include "filetypes.h"
  #include "cltypes.h"
+ #include "fmap.h"
  
 +#define BM_BOUNDARY_EOL	1
 +
  struct cli_bm_patt {
      unsigned char *pattern, *prefix;
      char *virname;
@@@ -35,7 -34,6 +36,7 @@@
      uint16_t length, prefix_length;
      uint16_t cnt;
      unsigned char pattern0;
 +    uint32_t boundary, filesize;
  };
  
  struct cli_bm_off {
@@@ -44,9 -42,9 +45,9 @@@
  
  int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const char *offset);
  int cli_bm_init(struct cli_matcher *root);
- int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, int fd);
+ int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, fmap_t *map);
  void cli_bm_freeoff(struct cli_bm_off *data);
- int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, int fd, struct cli_bm_off *offdata);
 -int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, fmap_t *map, struct cli_bm_off *offdata);
++int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, fmap_t *map, struct cli_bm_off *offdata);
  void cli_bm_free(struct cli_matcher *root);
  
  #endif
diff --combined libclamav/matcher.c
index e0e0008,bd22558..d39dbf7
--- a/libclamav/matcher.c
+++ b/libclamav/matcher.c
@@@ -45,6 -45,7 +45,7 @@@
  #include "cltypes.h"
  #include "default.h"
  #include "macho.h"
+ #include "fmap.h"
  
  int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata)
  {
@@@ -76,7 -77,7 +77,7 @@@
  	if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
  	    return ret;
  
- 	if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, troot, offset, -1, NULL)) != CL_VIRUS)
 -	if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, NULL, NULL)) != CL_VIRUS)
++	if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, troot, offset, NULL, NULL)) != CL_VIRUS)
  	    ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
  
  	if(!acdata)
@@@ -89,7 -90,7 +90,7 @@@
      if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
  	return ret;
  
-     if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, groot, offset, -1, NULL)) != CL_VIRUS)
 -    if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, NULL, NULL)) != CL_VIRUS)
++    if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, groot, offset, NULL, NULL)) != CL_VIRUS)
  	ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
  
      if(!acdata)
@@@ -104,15 -105,12 +105,12 @@@
   * offdata[2]: max shift
   * offdata[3]: section number
   */
- int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
+ int cli_caloff(const char *offstr, struct cli_target_info *info, fmap_t *map, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
  {
- 	int (*einfo)(int, struct cli_exe_info *) = NULL;
+ 	int (*einfo)(fmap_t *, struct cli_exe_info *) = NULL;
  	char offcpy[65];
  	unsigned int n, val;
  	char *pt;
- 	off_t pos;
- 	struct stat sb;
- 
  
      if(!info) { /* decode offset string */
  	if(!offstr) {
@@@ -208,14 -206,8 +206,8 @@@
  	}
  
  	if((offdata[0] == CLI_OFF_EOF_MINUS)) {
- 	    if(!info->fsize) {
- 		if(fstat(fd, &sb) == -1) {
- 		    cli_errmsg("cli_caloff: fstat(%d) failed\n", fd);
- 		    return CL_ESTAT;
- 		}
- 		info->fsize = sb.st_size;
- 	    }
- 
+ 	    if(!info->fsize)
+ 		info->fsize = map->len;
  	} else if(!info->status) {
  	    if(target == 1)
  		einfo = cli_peheader;
@@@ -229,22 -221,14 +221,14 @@@
  		return CL_EMALFDB;
  	    }
  
- 	    if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
- 		cli_errmsg("cli_caloff: lseek(%d) failed\n", fd);
- 		return CL_ESEEK;
- 	    }
- 
- 	    lseek(fd, 0, SEEK_SET);
- 	    if(einfo(fd, &info->exeinfo)) {
+ 	    if(einfo(map, &info->exeinfo)) {
  		/* einfo *may* fail */
- 		lseek(fd, pos, SEEK_SET);
  		info->status = -1;
  		*offset_min = CLI_OFF_NONE;
  		if(offset_max)
  		    *offset_max = CLI_OFF_NONE;
  		return CL_SUCCESS;
  	    }
- 	    lseek(fd, pos, SEEK_SET);
  	    info->status = 1;
  	}
  
@@@ -277,12 -261,8 +261,12 @@@
  		return CL_EARG;
  	}
  
 -	if(offset_max && *offset_min != CLI_OFF_NONE)
 -	    *offset_max = *offset_min + offdata[2];
 +	if(offset_max) {
 +	    if(*offset_min != CLI_OFF_NONE)
 +		*offset_max = *offset_min + offdata[2];
 +	    else
 +		*offset_max = CLI_OFF_NONE;
 +	}
      }
  
      return CL_SUCCESS;
@@@ -291,12 -271,8 +275,12 @@@
  int cli_checkfp(int fd, cli_ctx *ctx)
  {
  	unsigned char *digest;
 +	char md5[33];
 +	unsigned int i;
  	const char *virname;
  	off_t pos;
 +	struct stat sb;
 +	const struct cli_bm_patt *patt = NULL;
  
  
      if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
@@@ -307,30 -283,18 +291,30 @@@
      lseek(fd, 0, SEEK_SET);
  
      if(ctx->engine->md5_fp) {
 +	if(fstat(fd, &sb) == -1) {
 +	    cli_errmsg("cli_checkfp(): fstat(%d) failed\n", fd);
 +	    lseek(fd, pos, SEEK_SET);
 +	    return 0;
 +	}
 +
  	if(!(digest = cli_md5digest(fd))) {
  	    cli_errmsg("cli_checkfp(): Can't generate MD5 checksum\n");
  	    lseek(fd, pos, SEEK_SET);
  	    return 0;
  	}
  
- 	if(cli_bm_scanbuff(digest, 16, &virname, &patt, ctx->engine->md5_fp, 0, -1, NULL) == CL_VIRUS && patt->filesize == sb.st_size) {
 -	if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, NULL, NULL) == CL_VIRUS) {
++	if(cli_bm_scanbuff(digest, 16, &virname, &patt, ctx->engine->md5_fp, 0, NULL, NULL) == CL_VIRUS && patt->filesize == sb.st_size) {
  	    cli_dbgmsg("cli_checkfp(): Found false positive detection (fp sig: %s)\n", virname);
  	    free(digest);
  	    lseek(fd, pos, SEEK_SET);
  	    return 1;
  	}
 +
 +	for(i = 0; i < 16; i++)
 +	    sprintf(md5 + i * 2, "%02x", digest[i]);
 +	md5[32] = 0;
 +	cli_dbgmsg("FP SIGNATURE: %s:%u:%s\n", md5, (unsigned int) sb.st_size, *ctx->virname ? *ctx->virname : "Name");
 +
  	free(digest);
      }
  
@@@ -340,18 -304,31 +324,31 @@@
  
  int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode)
  {
-  	unsigned char *buffer, *buff, *endbl, *upt;
+     int ret = CL_EMEM;
+     fmap_t *map = *ctx->fmap;
+ 
+     if((*ctx->fmap = fmap(desc, 0, 0))) {
+ 	ret = cli_fmap_scandesc(ctx, ftype, ftonly, ftoffset, acmode);
+ 	funmap(*ctx->fmap);
+     }
+     *ctx->fmap = map;
+     return ret;
+ }
+ 
+ 
+ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode)
+ {
+  	unsigned char *buff;
  	int ret = CL_CLEAN, type = CL_CLEAN, bytes;
  	unsigned int i, evalcnt, bm_offmode = 0;
- 	uint32_t buffersize, length, maxpatlen, shift = 0, offset = 0;
+ 	uint32_t maxpatlen, offset = 0;
  	uint64_t evalids;
  	struct cli_ac_data gdata, tdata;
  	struct cli_bm_off toff;
  	cli_md5_ctx md5ctx;
  	unsigned char digest[16];
  	struct cli_matcher *groot = NULL, *troot = NULL;
- 	struct stat sb;
- 
+ 	fmap_t *map = *ctx->fmap;
  
      if(!ctx->engine) {
  	cli_errmsg("cli_scandesc: engine == NULL\n");
@@@ -382,34 -359,25 +379,25 @@@
  	    maxpatlen = groot->maxpatlen;
      }
  
-     /* prepare the buffer */
-     buffersize = maxpatlen + SCANBUFF;
-     if(!(buffer = (unsigned char *) cli_calloc(buffersize, sizeof(unsigned char)))) {
- 	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%u)\n", buffersize);
- 	return CL_EMEM;
-     }
- 
      if(!ftonly)
- 	if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, desc)))
+ 	if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, map)))
  	    return ret;
  
      if(troot) {
- 	if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, desc))) {
+ 	if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, map))) {
  	    if(!ftonly)
  		cli_ac_freedata(&gdata);
  	    return ret;
  	}
  	if(troot->bm_offmode) {
- 	    if(fstat(desc, &sb) != -1) {
- 		if(sb.st_size >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
- 		    if((ret = cli_bm_initoff(troot, &toff, desc))) {
- 			if(!ftonly)
- 			    cli_ac_freedata(&gdata);
- 			cli_ac_freedata(&tdata);
- 			return ret;
- 		    }
- 		    bm_offmode = 1;
+ 	    if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
+ 		if((ret = cli_bm_initoff(troot, &toff, map))) {
+ 		    if(!ftonly)
+ 			cli_ac_freedata(&gdata);
+ 		    cli_ac_freedata(&tdata);
+ 		    return ret;
  		}
+ 		bm_offmode = 1;
  	    }
  	}
      }
@@@ -417,78 -385,58 +405,50 @@@
      if(!ftonly && ctx->engine->md5_hdb)
  	cli_md5_init(&md5ctx);
  
-     buff = buffer;
-     buff += maxpatlen; /* pointer to read data block */
-     endbl = buff + SCANBUFF - maxpatlen; /* pointer to the last block
- 					  * length of maxpatlen
- 					  */
- 
-     upt = buff;
-     while((bytes = cli_readn(desc, buff + shift, SCANBUFF - shift)) > 0) {
- 
+     while(offset < map->len) {
+ 	bytes = MIN(map->len - offset, SCANBUFF);
+ 	if(!(buff = fmap_need_off_once(map, offset, bytes)))
+ 	    break;
  	if(ctx->scanned)
  	    *ctx->scanned += bytes / CL_COUNT_PRECISION;
  
- 	length = shift + bytes;
- 	if(upt == buffer)
- 	    length += maxpatlen;
- 
  	if(troot) {
- 	    if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, NULL, troot, offset, desc, bm_offmode ? &toff : NULL)) != CL_VIRUS)
- 		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, ftoffset, acmode, NULL);
- 
 -	    if(troot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, troot, offset, map, bm_offmode ? &toff : NULL)) != CL_VIRUS)
++	    if(troot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, NULL, troot, offset, map, bm_offmode ? &toff : NULL)) != CL_VIRUS)
+ 		ret = cli_ac_scanbuff(buff, bytes, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, ftoffset, acmode, NULL);
  	    if(ret == CL_VIRUS) {
- 		free(buffer);
  		if(!ftonly)
  		    cli_ac_freedata(&gdata);
  		cli_ac_freedata(&tdata);
  		if(bm_offmode)
  		    cli_bm_freeoff(&toff);
 -
 -		if(cli_checkfp(map->fd, ctx))
 -		    return CL_CLEAN;
 -		else
 -		    return CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	}
  
  	if(!ftonly) {
- 	    if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, NULL, groot, offset, desc, NULL)) != CL_VIRUS)
- 		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, ftoffset, acmode, NULL);
- 
 -	    if(groot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, groot, offset, map, NULL)) != CL_VIRUS)
++	    if(groot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, NULL, groot, offset, map, NULL)) != CL_VIRUS)
+ 		ret = cli_ac_scanbuff(buff, bytes, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, ftoffset, acmode, NULL);
  	    if(ret == CL_VIRUS) {
- 		free(buffer);
  		cli_ac_freedata(&gdata);
  		if(troot) {
  		    cli_ac_freedata(&tdata);
  		    if(bm_offmode)
  			cli_bm_freeoff(&toff);
  		}
 -		if(cli_checkfp(map->fd, ctx))
 -		    return CL_CLEAN;
 -		else
 -		    return CL_VIRUS;
 -
 +		return CL_VIRUS;
- 
  	    } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
  		if(ret > type)
  		    type = ret;
  	    }
  
  	    if(ctx->engine->md5_hdb)
- 		cli_md5_update(&md5ctx, buff + shift, bytes);
+ 		cli_md5_update(&md5ctx, buff + maxpatlen * (offset!=0), bytes - maxpatlen * (offset!=0));
  	}
  
- 	if(bytes + shift == SCANBUFF) {
- 	    memmove(buffer, endbl, maxpatlen);
- 	    offset += SCANBUFF;
- 
- 	    if(upt == buff) {
- 		upt = buffer;
- 		offset -= maxpatlen;
- 	    }
- 
- 	    shift = 0;
- 
- 	} else {
- 	    shift += bytes;
- 	}
+ 	if(bytes < SCANBUFF) break;
+ 	offset += bytes - maxpatlen;
      }
  
-     free(buffer);
- 
      if(troot) {
  	for(i = 0; i < troot->ac_lsigs; i++) {
  	    evalcnt = 0;
@@@ -519,14 -467,17 +479,13 @@@
  	cli_ac_freedata(&gdata);
      }
  
 -    if(ret == CL_VIRUS) {
 -	lseek(map->fd, 0, SEEK_SET);
 -	if(cli_checkfp(map->fd, ctx))
 -	    return CL_CLEAN;
 -	else
 -	    return CL_VIRUS;
 -    }
 +    if(ret == CL_VIRUS)
 +	return CL_VIRUS;
  
      if(!ftonly && ctx->engine->md5_hdb) {
 +	    const struct cli_bm_patt *patt;
  	cli_md5_final(digest, &md5ctx);
- 	fstat(desc, &sb);
- 	if(cli_bm_scanbuff(digest, 16, ctx->virname, &patt, ctx->engine->md5_hdb, 0, -1, NULL) == CL_VIRUS && patt->filesize == sb.st_size && (cli_bm_scanbuff(digest, 16, NULL, &patt, ctx->engine->md5_fp, 0, -1, NULL) != CL_VIRUS || patt->filesize != sb.st_size))
 -	if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, NULL, NULL) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, NULL, NULL) != CL_VIRUS))
++	if(cli_bm_scanbuff(digest, 16, ctx->virname, &patt, ctx->engine->md5_hdb, 0, NULL, NULL) == CL_VIRUS && patt->filesize == map->len && (cli_bm_scanbuff(digest, 16, NULL, &patt, ctx->engine->md5_fp, 0, NULL, NULL) != CL_VIRUS || patt->filesize != map->len))
  	    return CL_VIRUS;
      }
  
diff --combined libclamav/mbox.c
index ce768be,55823c5..e963515
--- a/libclamav/mbox.c
+++ b/libclamav/mbox.c
@@@ -20,6 -20,10 +20,6 @@@
  
  static	char	const	rcsid[] = "$Id: mbox.c,v 1.381 2007/02/15 12:26:44 njh Exp $";
  
 -#ifdef	_MSC_VER
 -#include <winsock.h>	/* only needed in CL_EXPERIMENTAL */
 -#endif
 -
  #if HAVE_CONFIG_H
  #include "clamav-config.h"
  #endif
@@@ -50,7 -54,9 +50,7 @@@
  #include <sys/param.h>
  #endif
  #include "clamav.h"
 -#ifndef	C_WINDOWS
  #include <dirent.h>
 -#endif
  #include <limits.h>
  #include <signal.h>
  
@@@ -72,6 -78,7 +72,7 @@@
  #include "mbox.h"
  #include "dconf.h"
  #include "md5.h"
+ #include "fmap.h"
  
  #define DCONF_PHISHING mctx->ctx->dconf->phishing
  
@@@ -135,8 -142,7 +136,8 @@@ typedef	enum 
  
  #include "phishcheck.h"
  
 -#ifndef	C_WINDOWS
 +#ifndef	_WIN32
 +#include <sys/time.h>
  #include <netdb.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
@@@ -146,7 -152,33 +147,7 @@@
  #endif
  #endif
  
 -#ifndef	C_WINDOWS
 -#define	closesocket(s)	close(s)
 -#define	SOCKET	int
 -#endif
 -
  #include <fcntl.h>
 -#ifndef	C_WINDOWS
 -#include <sys/time.h>
 -#endif
 -
 -#ifndef HAVE_IN_PORT_T
 -typedef	unsigned	short	in_port_t;
 -#endif
 -
 -#ifndef HAVE_IN_ADDR_T
 -typedef	unsigned	int	in_addr_t;
 -#endif
 -
 -#if	(!defined(EALREADY)) && (defined(WSAEALREADY))
 -#define EALREADY	WSAEALREADY
 -#endif
 -#if	(!defined(EINPROGRESS)) && (defined(WSAEINPROGRESS))
 -#define EINPROGRESS	WSAEINPROGRESS
 -#endif
 -#if	(!defined(EISCONN)) && (defined(WSAEISCONN))
 -#define EISCONN	WSAEISCONN
 -#endif
  
  /*
   * Use CL_SCAN_PARTIAL_MESSAGE to handle messages covered by section 7.3.2 of RFC1341.
@@@ -186,7 -218,7 +187,7 @@@ typedef	struct	mbox_ctx 
  #endif
  
  static	int	cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx);
- static	message	*parseEmailFile(FILE *fin, const table_t *rfc821Table, const char *firstLine, const char *dir);
+ static	message	*parseEmailFile(fmap_t *map, size_t *at, const table_t *rfc821Table, const char *firstLine, const char *dir);
  static	message	*parseEmailHeaders(message *m, const table_t *rfc821Table);
  static	int	parseEmailHeader(message *m, const char *line, const table_t *rfc821Table);
  static	mbox_status	parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int recursion_level);
@@@ -201,7 -233,7 +202,7 @@@ static	char	*rfc2047(const char *in)
  static	char	*rfc822comments(const char *in, char *out);
  static	int	rfc1341(message *m, const char *dir);
  static	bool	usefulHeader(int commandNumber, const char *cmd);
- static	char	*getline_from_mbox(char *buffer, size_t len, FILE *fin);
+ static	char	*getline_from_mbox(char *buffer, size_t len, fmap_t *map, size_t *at);
  static	bool	isBounceStart(mbox_ctx *mctx, const char *line);
  static	bool	exportBinhexMessage(mbox_ctx *mctx, message *m);
  static	int	exportBounceMessage(mbox_ctx *ctx, text *start);
@@@ -300,774 -332,10 +301,6 @@@ static	const	struct tableinit 
  static	pthread_mutex_t	tables_mutex = PTHREAD_MUTEX_INITIALIZER;
  #endif
  
- #ifdef	NEW_WORLD
- #include "matcher.h"
- #undef	PARTIAL_DIR
- #endif
- 
- #ifdef	NEW_WORLD
- /*
-  * Files larger than this are scanned with the old method, should be
-  *	StreamMaxLength, I guess
-  * If NW_MAX_FILE_SIZE is not defined, all files go through the
-  *	new method. This definition is for machines very tight on RAM, or
-  *	with large StreamMaxLength values
-  */
- #define	MAX_ALLOCATION	134217728	/* see libclamav/others.c */
- #define	NW_MAX_FILE_SIZE	MAX_ALLOCATION
- 
- struct scanlist {
- 	const	char	*start;
- 	size_t	size;
- 	encoding_type	decoder;	/* only BASE64 and QUOTEDPRINTABLE for now */
- 	struct	scanlist *next;
- };
- 
- static struct map {
- 	const	char	*offset;	/* sorted */
- 	const	char	*word;
- 	struct	map	*next;
- } *map, *tail;
- 
- static	int	save_text(cli_ctx *ctx, const char *dir, const char *start, size_t len);
- static	void	create_map(const char *begin, const char *end);
- static	void	add_to_map(const char *offset, const char *word);
- static	const	char	*find_in_map(const char *offset, const char *word);
- static	void	free_map(void);
- 
- /*
-  * This could be the future. Instead of parsing and decoding it just decodes.
-  *
-  * USE IT AT YOUR PERIL, a large number of viruses are not detected with this
-  * method, possibly because the decoded files must be exact and not have
-  * extra data at the start or end, which this code will produce.
-  *
-  * Currently only supports base64 and quoted-printable
-  *
-  * You may also see a lot of warnings. For the moment it falls back to old
-  *	world mode if it doesn't know what to do - that'll be removed.
-  * The code is untidy...
-  *
-  * FIXME: Some mailbox scans are slower with this method. I suspect that it's
-  * because the scan can proceed to the end of the file rather than the end
-  * of the attachment which can mean than later emails are scanned many times
-  *
-  * FIXME: quoted printable doesn't know when to stop, so size related virus
-  *	matching breaks
-  *
-  * TODO: Fall through to cli_parse_mbox() too often
-  *
-  * TODO: Add support for systems without mmap()
-  *
-  * TODO: partial_dir fall through
-  *
-  * FIXME: Some EICAR gets through
-  */
- int
- cli_mbox(const char *dir, int desc, cli_ctx *ctx)
- {
- 	char *start, *ptr, *line;
- 	const char *last, *p, *q;
- 	size_t size;
- 	struct stat statb;
- 	message *m;
- 	fileblob *fb;
- 	int ret = CL_CLEAN;
- 	int wasAlloced;
- 	struct scanlist *scanlist, *scanelem;
- 
- 	if(dir == NULL) {
- 		cli_dbgmsg("cli_mbox called with NULL dir\n");
- 		return CL_ENULLARG;
- 	}
- 	if(fstat(desc, &statb) < 0)
- 		return CL_EOPEN;
- 
- 	size = statb.st_size;
- 
- 	if(size == 0)
- 		return CL_CLEAN;
- 
- #ifdef	NW_MAX_FILE_SIZE
- 	if(size > NW_MAX_FILE_SIZE)
- 		return cli_parse_mbox(dir, desc, ctx);
- #endif
- 
- 	/*cli_warnmsg("NEW_WORLD is new code - use at your own risk.\n");*/
- #ifdef	PARTIAL_DIR
- 	cli_warnmsg("PARTIAL_DIR doesn't work in the NEW_WORLD yet\n");
- #endif
- 
- 	start = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, 0);
- 	if(start == MAP_FAILED)
- 		return CL_EMAP;
- 
- 	cli_dbgmsg("mmap'ed mbox\n");
- 
- 	ptr = cli_malloc(size);
- 	if(ptr) {
- 		memcpy(ptr, start, size);
- 		munmap(start, size);
- 		start = ptr;
- 		wasAlloced = 1;
- 	} else
- 		wasAlloced = 0;
- 
- 	/* last points to the last *valid* address in the array */
- 	last = &start[size - 1];
- 
- 	create_map(start, last);
- 
- 	scanelem = scanlist = NULL;
- 	q = start;
- 	/*
- 	 * FIXME: mismatch of const char * and char * here and in later calls
- 	 *	to find_in_map()
- 	 */
- 	while((p = find_in_map(q, "base64")) != NULL) {
- 		cli_dbgmsg("Found base64\n");
- 		if(scanelem) {
- 			scanelem->next = cli_malloc(sizeof(struct scanlist));
- 			scanelem = scanelem->next;
- 		} else
- 			scanlist = scanelem = cli_malloc(sizeof(struct scanlist));
- 		scanelem->next = NULL;
- 		scanelem->decoder = BASE64;
- 		q = scanelem->start = &p[6];
- 		if(((p = find_in_map(q, "\nFrom ")) != NULL) ||
- 		   ((p = find_in_map(q, "base64")) != NULL) ||
- 		   ((p = find_in_map(q, "quoted-printable")) != NULL)) {
- 			scanelem->size = (size_t)(p - q);
- 			q = p;
- 		} else {
- 			scanelem->size = (size_t)(last - scanelem->start) + 1;
- 			break;
- 		}
- 		cli_dbgmsg("base64: last %u q %u\n", (unsigned int)last, (unsigned int)q);
- 		assert(scanelem->size <= size);
- 	}
- 
- 	q = start;
- 	while((p = find_in_map(q, "quoted-printable")) != NULL) {
- 		if(p != q)
- 			switch(p[-1]) {
- 				case ' ':
- 				case ':':
- 				case '=':	/* wrong but allow it */
- 					break;
- 				default:
- 					q = &p[16];
- 					cli_dbgmsg("Ignore quoted-printable false positive\n");
- 					continue;	/* false positive */
- 			}
- 
- 		cli_dbgmsg("Found quoted-printable\n");
- #ifdef	notdef
- 		/*
- 		 * The problem with quoted printable is recognising when to stop
- 		 * parsing
- 		 */
- 		if(scanelem) {
- 			scanelem->next = cli_malloc(sizeof(struct scanlist));
- 			scanelem = scanelem->next;
- 		} else
- 			scanlist = scanelem = cli_malloc(sizeof(struct scanlist));
- 		scanelem->next = NULL;
- 		scanelem->decoder = QUOTEDPRINTABLE;
- 		q = scanelem->start = &p[16];
- 		cli_dbgmsg("qp: last %u q %u\n", (unsigned int)last, (unsigned int)q);
- 		if(((p = find_in_map(q, "\nFrom ")) != NULL) ||
- 		   ((p = find_in_map(q, "quoted-printable")) != NULL) ||
- 		   ((p = find_in_map(q, "base64")) != NULL)) {
- 			scanelem->size = (size_t)(p - q);
- 			q = p;
- 			cli_dbgmsg("qp: scanelem->size = %u\n", scanelem->size);
- 		} else {
- 			scanelem->size = (size_t)(last - scanelem->start) + 1;
- 			break;
- 		}
- 		assert(scanelem->size <= size);
- #else
- 		if(wasAlloced)
- 			free(start);
- 		else
- 			munmap(start, size);
- 
- 		free_map();
- 		return cli_parse_mbox(dir, desc, ctx);
- #endif
- 	}
- 
- 	if(scanlist == NULL) {
- 		const struct tableinit *tableinit;
- 		bool anyHeadersFound = FALSE;
- 		bool hasuuencode = FALSE;
- 		cli_file_t type;
- 
- 		/* FIXME: message: There could of course be no decoder needed... */
- 		for(tableinit = rfc821headers; tableinit->key; tableinit++)
- 			if(find_in_map(start, tableinit->key)) {
- 				anyHeadersFound = TRUE;
- 				break;
- 			}
- 
- 		if((!anyHeadersFound) &&
- 		   ((p = find_in_map(start, "\nbegin ")) != NULL) &&
- 		   (isuuencodebegin(++p)))
- 			/* uuencoded part */
- 			hasuuencode = TRUE;
- 		else {
- 			cli_dbgmsg("Nothing encoded, looking for a text part to save\n");
- 			ret = save_text(ctx, dir, start, size);
- 			if(wasAlloced)
- 				free(start);
- 			else
- 				munmap(start, size);
- 
- 			free_map();
- 			if(ret != CL_EFORMAT)
- 				return ret;
- 			ret = CL_CLEAN;
- 		}
- 
- 		free_map();
- 
- 		type = cli_filetype(start, size, ctx->engine);
- 
- 		if((type == CL_TYPE_TEXT_ASCII) &&
- 		   (strncmp(start, "Microsoft Mail Internet Headers", 31) == 0))
- 			type = CL_TYPE_MAIL;
- 
- 		if(wasAlloced)
- 			free(start);
- 		else
- 			munmap(start, size);
- 
- 		if(anyHeadersFound || hasuuencode) {
- 			/* TODO: reduce the number of falls through here */
- 			if(hasuuencode)
- 				/* TODO: fast track visa */
- 				cli_dbgmsg("New world - fall back to old uudecoder\n");
- 			else
- 				cli_dbgmsg("cli_mbox: unknown encoder, type %d\n", type);
- 			if(type == CL_TYPE_MAIL)
- 				return cli_parse_mbox(dir, desc, ctx);
- 			cli_dbgmsg("Unknown filetype %d, return CLEAN\n", type);
- 			return CL_CLEAN;
- 		}
- 
- #if	0	/* I don't believe this is needed any more */
- 		/*
- 		 * The message could be a plain text phish
- 		 * FIXME: Can't get to the option whether we are looking for
- 		 *	phishes or not, so assume we are, this slows things a
- 		 *	lot
- 		 * Should be
- 		 *	if((type == CL_TYPE_MAIL) && (!(no-phishing))
- 		 */
- 		if(type == CL_TYPE_MAIL)
- 			return cli_parse_mbox(dir, desc, ctx);
- #endif
- 		cli_dbgmsg("cli_mbox: I believe it's plain text (type == %d) which must be clean\n",
- 			type);
- 		return CL_CLEAN;
- 	}
- #if	0
- 	if(wasAlloced) {
- 		const char *max = NULL;
- 
- 		for(scanelem = scanlist; scanelem; scanelem = scanelem->next) {
- 			const char *end = &scanelem->start[scanelem->size];
- 
- 			if(end > max)
- 				max = end;
- 		}
- 
- 		if(max < last)
- 			printf("could free %d bytes\n", (int)(last - max));
- 	}
- #endif
- 
- 	for(scanelem = scanlist; scanelem; scanelem = scanelem->next) {
- 		if(scanelem->decoder == BASE64) {
- 			const char *b64start = scanelem->start;
- 			size_t b64size = scanelem->size;
- 
- 			cli_dbgmsg("b64size = %lu\n", b64size);
- 			while((*b64start != '\n') && (*b64start != '\r')) {
- 				b64start++;
- 				b64size--;
- 			}
- 			/*
- 			 * Look for the end of the headers
- 			 */
- 			while(b64start < last) {
- 				if(*b64start == ';') {
- 					b64start++;
- 					b64size--;
- 				} else if((memcmp(b64start, "\n\n", 2) == 0) ||
- 					  (memcmp(b64start, "\r\r", 2) == 0)) {
- 					b64start += 2;
- 					b64size -= 2;
- 					break;
- 				} else if(memcmp(b64start, "\r\n\r\n", 4) == 0) {
- 					b64start += 4;
- 					b64size -= 4;
- 					break;
- 				} else if(memcmp(b64start, "\n \n", 3) == 0) {
- 					/*
- 					 * Some viruses are broken and have
- 					 * one space character at the end of
- 					 * the headers
- 					 */
- 					b64start += 3;
- 					b64size -= 3;
- 					break;
- 				} else if(memcmp(b64start, "\r\n \r\n", 5) == 0) {
- 					/*
- 					 * Some viruses are broken and have
- 					 * one space character at the end of
- 					 * the headers
- 					 */
- 					b64start += 5;
- 					b64size -= 5;
- 					break;
- 				}
- 				b64start++;
- 				b64size--;
- 			}
- 
- 			if(b64size > 0L)
- 				while((!isalnum(*b64start)) && (*b64start != '/')) {
- 					if(b64size-- == 0L)
- 						break;
- 					b64start++;
- 				}
- 
- 			if(b64size > 0L) {
- 				int lastline;
- 				char *tmpfilename;
- 				unsigned char *uptr;
- 
- 				cli_dbgmsg("cli_mbox: decoding %ld base64 bytes\n", b64size);
- 				if((fb = fileblobCreate()) == NULL) {
- 					free_map();
- 					if(wasAlloced)
- 						free(start);
- 					else
- 						munmap(start, size);
- 
- 					return CL_EMEM;
- 				}
- 
- 				tmpfilename = cli_gentemp(dir);
- 				if(tmpfilename == NULL) {
- 					free_map();
- 					if(wasAlloced)
- 						free(start);
- 					else
- 						munmap(start, size);
- 					fileblobDestroy(fb);
- 
- 					return CL_EMEM;
- 				}
- 				fileblobSetFilename(fb, dir, tmpfilename);
- 				free(tmpfilename);
- 
- 				line = NULL;
- 
- 				m = messageCreate();
- 				if(m == NULL) {
- 					free_map();
- 					if(wasAlloced)
- 						free(start);
- 					else
- 						munmap(start, size);
- 					fileblobDestroy(fb);
- 
- 					return CL_EMEM;
- 				}
- 				messageSetEncoding(m, "base64");
- 
- 				messageSetCTX(m, ctx);
- 				fileblobSetCTX(fb, ctx);
- 
- 				lastline = 0;
- 				do {
- 					int length = 0, datalen;
- 					char *newline, *equal;
- 					unsigned char *bigbuf, *data;
- 					unsigned char smallbuf[1024];
- 					const char *cptr;
- 
- 					/*printf("%ld: ", b64size); fflush(stdout);*/
- 
- 					for(cptr = b64start; b64size && (*cptr != '\n') && (*cptr != '\r'); cptr++) {
- 						length++;
- 						--b64size;
- 					}
- 
- 					/*printf("%d: ", length); fflush(stdout);*/
- 
- 					newline = cli_realloc(line, length + 1);
- 					if(newline == NULL)
- 						break;
- 					line = newline;
- 
- 					memcpy(line, b64start, length);
- 					line[length] = '\0';
- 
- 					equal = strchr(line, '=');
- 					if(equal) {
- 						lastline++;
- 						*equal = '\0';
- 					}
- 					/*puts(line);*/
- 
- #if	0
- 					if(messageAddStr(m, line) < 0)
- 						break;
- #endif
- 					if(length >= (int)sizeof(smallbuf)) {
- 						datalen = length + 2;
- 						data = bigbuf = cli_malloc(datalen);
- 						if(data == NULL)
- 							break;
- 					} else {
- 						bigbuf = NULL;
- 						data = smallbuf;
- 						datalen = sizeof(data) - 1;
- 					}
- 					uptr = decodeLine(m, BASE64, line, data, datalen);
- 
- 					if(uptr == NULL) {
- 						if(bigbuf)
- 							free(bigbuf);
- 						break;
- 					}
- 					/*cli_dbgmsg("base64: write %u bytes\n", (size_t)(uptr - data));*/
- 					datalen = fileblobAddData(fb, data, (size_t)(uptr - data));
- 					if(bigbuf)
- 						free(bigbuf);
- 
- 					if(datalen < 0)
- 						break;
- 					if(fileblobContainsVirus(fb))
- 						break;
- 
- 					if((b64size > 0) && (*cptr == '\r')) {
- 						b64start = ++cptr;
- 						--b64size;
- 					}
- 					if((b64size > 0) && (*cptr == '\n')) {
- 						b64start = ++cptr;
- 						--b64size;
- 					}
- 					if(lastline)
- 						break;
- 				} while(b64size > 0L);
- 
- 				if(m->base64chars) {
- 					unsigned char data[4];
- 
- 					uptr = base64Flush(m, data);
- 					if(uptr) {
- 						/*cli_dbgmsg("base64: flush %u bytes\n", (size_t)(uptr - data));*/
- 						(void)fileblobAddData(fb, data, (size_t)(uptr - data));
- 					}
- 				}
- 				if(fb)
- 					fileblobDestroy(fb);
- 				else
- 					ret = -1;
- 
- 				messageDestroy(m);
- 				free(line);
- 			}
- 		} else if(scanelem->decoder == QUOTEDPRINTABLE) {
- 			const char *quotedstart = scanelem->start;
- 			size_t quotedsize = scanelem->size;
- 
- 			cli_dbgmsg("quotedsize = %lu\n", quotedsize);
- 			while(*quotedstart != '\n') {
- 				quotedstart++;
- 				quotedsize--;
- 			}
- 			/*
- 			 * Look for the end of the headers
- 			 */
- 			while(quotedstart < last) {
- 				if(*quotedstart == ';') {
- 					quotedstart++;
- 					quotedsize--;
- 				} else if((*quotedstart == '\n') || (*quotedstart == '\r')) {
- 					quotedstart++;
- 					quotedsize--;
- 					if((*quotedstart == '\n') || (*quotedstart == '\r')) {
- 						quotedstart++;
- 						quotedsize--;
- 						break;
- 					}
- 				}
- 				quotedstart++;
- 				quotedsize--;
- 			}
- 
- 			while(!isalnum(*quotedstart)) {
- 				quotedstart++;
- 				quotedsize--;
- 			}
- 
- 			if(quotedsize > 0L) {
- 				cli_dbgmsg("cli_mbox: decoding %ld quoted-printable bytes\n", quotedsize);
- 
- 				m = messageCreate();
- 				if(m == NULL) {
- 					free_map();
- 					if(wasAlloced)
- 						free(start);
- 					else
- 						munmap(start, size);
- 
- 					return CL_EMEM;
- 				}
- 				messageSetEncoding(m, "quoted-printable");
- 				messageSetCTX(m, ctx);
- 
- 				line = NULL;
- 
- 				do {
- 					int length = 0;
- 					char *newline;
- 					const char *cptr;
- 
- 					/*printf("%ld: ", quotedsize); fflush(stdout);*/
- 
- 					for(cptr = quotedstart; quotedsize && (*cptr != '\n') && (*cptr != '\r'); cptr++) {
- 						length++;
- 						--quotedsize;
- 					}
- 
- 					/*printf("%d: ", length); fflush(stdout);*/
- 
- 					newline = cli_realloc(line, length + 1);
- 					if(newline == NULL)
- 						break;
- 					line = newline;
- 
- 					memcpy(line, quotedstart, length);
- 					line[length] = '\0';
- 
- 					/*puts(line);*/
- 
- 					if(messageAddStr(m, line) < 0)
- 						break;
- 
- 					if((quotedsize > 0) && (*cptr == '\r')) {
- 						quotedstart = ++cptr;
- 						--quotedsize;
- 					}
- 					if((quotedsize > 0) && (*cptr == '\n')) {
- 						quotedstart = ++cptr;
- 						--quotedsize;
- 					}
- 				} while(quotedsize > 0L);
- 
- 				free(line);
- 				fb = messageToFileblob(m, dir, 1);
- 				messageDestroy(m);
- 
- 				if(fb)
- 					fileblobDestroy(fb);
- 				else
- 					ret = -1;
- 			}
- 		}
- 	}
- 	scanelem = scanlist;
- 
- 	/*
- 	 * There could be a phish in the plain text part, so save that
- 	 * FIXME: Can't get to the option whether we are looking for
- 	 *	phishes or not, so assume we are, this slows things a
- 	 *	lot
- 	 * Should be
- 	 *	if((type == CL_TYPE_MAIL) && (!(no-phishing))
- 	 */
- 	ret = save_text(ctx, dir, start, size);
- 
- 	free_map();
- 
- 	while(scanelem) {
- 		struct scanlist *n = scanelem->next;
- 
- 		free(scanelem);
- 		scanelem = n;
- 	}
- 
- 	if(wasAlloced)
- 		free(start);
- 	else
- 		munmap(start, size);
- 
- 	/*
- 	 * FIXME: Need to run cl_scandir() here and return that value
- 	 */
- 	cli_dbgmsg("cli_mbox: ret = %d\n", ret);
- 	if(ret != CL_EFORMAT)
- 		return ret;
- 
- 	cli_dbgmsg("New world - don't know what to do - fall back to old world\n");
- 	/* Fall back for now */
- 	lseek(desc, 0L, SEEK_SET);
- 	return cli_parse_mbox(dir, desc, ctx);
- }
- 
- /*
-  * Save a text part - it could contain phish or jscript
-  */
- static int
- save_text(cli_ctx *ctx, const char *dir, const char *start, size_t len)
- {
- 	const char *p;
- 
- 	if((p = find_in_map(start, "\n\n")) || (p = find_in_map(start, "\r\n\r\n"))) {
- 		const char *q;
- 		fileblob *fb;
- 		char *tmpfilename;
- 
- 		if(((q = find_in_map(start, "base64")) == NULL) &&
- 		   ((q = find_in_map(start, "quoted_printable")) == NULL)) {
- 			cli_dbgmsg("It's all plain text!\n");
- 			if(*p == '\r')
- 				p += 4;
- 			else
- 				p += 2;
- 			len -= (p - start);
- 		} else if(((q = find_in_map(p, "\nFrom ")) == NULL) &&
- 		   ((q = find_in_map(p, "base64")) == NULL) &&
- 		   ((q = find_in_map(p, "quoted-printable")) == NULL))
- 			cli_dbgmsg("Can't find end of plain text - assume it's all\n");
- 		else
- 			len = (size_t)(q - p);
- 
- 		if(len < 5) {
- 			cli_dbgmsg("save_text: Too small\n");
- 			return CL_EFORMAT;
- 		}
- 		if(ctx->scanned)
- 			*ctx->scanned += len / CL_COUNT_PRECISION;
- 
- 		/*
- 		 * This doesn't work, cli_scanbuff isn't designed to be used
- 		 *	in this way. It gets the "filetype" wrong and then
- 		 *	doesn't scan correctly
- 		 */
- 		if(cli_scanbuff((char *)p, len, 0, ctx, CL_TYPE_BINARY_DATA, NULL) == CL_VIRUS) {
- 			cli_dbgmsg("save_text: found %s\n", *ctx->virname);
- 			return CL_VIRUS;
- 		}
- 
- 		fb = fileblobCreate();
- 		if(fb == NULL)
- 			return CL_EMEM;
- 
- 		tmpfilename = cli_gentemp(dir);
- 
- 		if(tmpfilename == NULL) {
- 			fileblobDestroy(fb);
- 			return CL_ETMPFILE;
- 		}
- 		cli_dbgmsg("save plain bit to %s, %u bytes\n",
- 			tmpfilename, len);
- 
- 		fileblobSetFilename(fb, dir, tmpfilename);
- 		free(tmpfilename);
- 
- 		(void)fileblobAddData(fb, (const unsigned char *)p, len);
- 		fileblobDestroy(fb);
- 		return CL_SUCCESS;
- 	}
- 	cli_dbgmsg("No text part found to save\n");
- 	return CL_EFORMAT;
- }
- 
- static void
- create_map(const char *begin, const char *end)
- {
- 	const struct wordlist {
- 		const char *word;
- 		int len;
- 	} wordlist[] = {
- 		{	"base64",		6	},
- 		{	"quoted-printable",	16	},
- 		{	"\nbegin ",		7	},
- 		{	"\nFrom ",		6	},
- 		{	"\n\n",			2	},
- 		{	"\r\n\r\n",		4	},
- 		{	NULL,			0	}
- 	};
- 
- 	if(map) {
- 		cli_dbgmsg("create_map called without free_map\n");
- 		free_map();
- 	}
- 	while(begin < end) {
- 		const struct wordlist *word;
- 
- 		for(word = wordlist; word->word; word++) {
- 			if((end - begin) < word->len)
- 				continue;
- 			if(strncasecmp(begin, word->word, word->len) == 0) {
- 				add_to_map(begin, word->word);
- 				break;
- 			}
- 		}
- 		begin++;
- 	}
- }
- 
- /* To sort map, assume 'offset' is presented in sorted order */
- static void
- add_to_map(const char *offset, const char *word)
- {
- 	if(map) {
- 		tail->next = cli_malloc(sizeof(struct map));	/* FIXME: verify */
- 		tail = tail->next;
- 	} else
- 		map = tail = cli_malloc(sizeof(struct map));	/* FIXME: verify */
- 
- 	tail->offset = offset;
- 	tail->word = word;
- 	tail->next = NULL;
- }
- 
- static const char *
- find_in_map(const char *offset, const char *word)
- {
- 	const struct map *item;
- 
- 	for(item = map; item; item = item->next)
- 		if(item->offset >= offset)
- 			if(strcasecmp(word, item->word) == 0)
- 				return item->offset;
- 
- 	return NULL;
- }
- 
- static void
- free_map(void)
- {
- 	while(map) {
- 		struct map *next = map->next;
- 
- 		free(map);
- 		map = next;
- 	}
- 	map = NULL;
- }
- 
- #else	/*!NEW_WORLD*/
 -#ifndef	O_BINARY
 -#define	O_BINARY	0
 -#endif
 -
  int
  cli_mbox(const char *dir, int desc, cli_ctx *ctx)
  {
@@@ -1077,7 -345,6 +310,6 @@@
  	}
  	return cli_parse_mbox(dir, desc, ctx);
  }
- #endif
  
  /*
   * TODO: when signal handling is added, need to remove temp files when a
@@@ -1099,62 -366,16 +331,16 @@@ cli_parse_mbox(const char *dir, int des
  {
  	int retcode, i;
  	message *body;
- 	FILE *fd;
  	char buffer[RFC2821LENGTH + 1];
  	mbox_ctx mctx;
- #ifdef HAVE_BACKTRACE
- 	void (*segv)(int);
- #endif
  	static table_t *rfc821, *subtype;
- #ifdef	SAVE_TMP
- 	char tmpfilename[16];
- 	int tmpfd;
- #endif
+ 	size_t at = 0;
+ 	fmap_t *map = *ctx->fmap;
  
- #ifdef	NEW_WORLD
- 	cli_dbgmsg("fall back to old world\n");
- #else
  	cli_dbgmsg("in mbox()\n");
- #endif
- 
- 	i = dup(desc);
- 	if((fd = fdopen(i, "rb")) == NULL) {
- 		cli_errmsg("Can't open descriptor %d\n", desc);
- 		close(i);
- 		return CL_EOPEN;
- 	}
- 	rewind(fd);	/* bug 240 */
- #ifdef	SAVE_TMP
- 	/*
- 	 * Copy the incoming mail for debugging, so that if it falls over
- 	 * we have a copy of the offending email. This is debugging code
- 	 * that you shouldn't of course install in a live environment. I am
- 	 * not interested in hearing about security issues with this section
- 	 * of the parser.
- 	 */
- 	strcpy(tmpfilename, "/tmp/mboxXXXXXX");
- 	tmpfd = mkstemp(tmpfilename);
- 	if(tmpfd < 0) {
- 		perror(tmpfilename);
- 		cli_errmsg("Can't make debugging file\n");
- 	} else {
- 		FILE *tmpfp = fdopen(tmpfd, "w");
  
- 		if(tmpfp) {
- 			while(fgets(buffer, sizeof(buffer) - 1, fd) != NULL)
- 				fputs(buffer, tmpfp);
- 			fclose(tmpfp);
- 			rewind(fd);
- 		} else
- 			cli_errmsg("Can't fdopen debugging file\n");
- 	}
- #endif
- 	if(fgets(buffer, sizeof(buffer) - 1, fd) == NULL) {
+ 	if(!fmap_gets(map, buffer, &at, sizeof(buffer) - 1)) {
  		/* empty message */
- 		fclose(fd);
- #ifdef	SAVE_TMP
- 		if (cli_unlink(tmpfilename)) return CL_EUNLINK;
- #endif
  		return CL_CLEAN;
  	}
  #ifdef	CL_THREAD_SAFE
@@@ -1169,10 -390,6 +355,6 @@@
  #ifdef	CL_THREAD_SAFE
  			pthread_mutex_unlock(&tables_mutex);
  #endif
- 			fclose(fd);
- #ifdef	SAVE_TMP
- 			if (cli_unlink(tmpfilename)) return CL_EUNLINK;
- #endif
  			return CL_EMEM;
  		}
  	}
@@@ -1180,10 -397,6 +362,6 @@@
  	pthread_mutex_unlock(&tables_mutex);
  #endif
  
- #ifdef HAVE_BACKTRACE
- 	segv = signal(SIGSEGV, sigsegv);
- #endif
- 
  	retcode = CL_SUCCESS;
  	body = NULL;
  
@@@ -1226,16 -439,8 +404,8 @@@
  		int messagenumber;
  		message *m = messageCreate();
  
- 		if(m == NULL) {
- 			fclose(fd);
- #ifdef HAVE_BACKTRACE
- 			signal(SIGSEGV, segv);
- #endif
- #ifdef	SAVE_TMP
- 			if (cli_unlink(tmpfilename)) return CL_EUNLINK;
- #endif
+ 		if(m == NULL)
  			return CL_EMEM;
- 		}
  
  		lastLineWasEmpty = FALSE;
  		messagenumber = 1;
@@@ -1291,16 -496,14 +461,14 @@@
  				 * Fast track visa to uudecode.
  				 * TODO: binhex, yenc
  				 */
- 				if(uudecodeFile(m, buffer, dir, fd) < 0)
+ 			  if(uudecodeFile(m, buffer, dir, map, &at) < 0)
  					if(messageAddStr(m, buffer) < 0)
  						break;
  			} else
  				/* at this point, the \n has been removed */
  				if(messageAddStr(m, buffer) < 0)
  					break;
- 		} while(fgets(buffer, sizeof(buffer) - 1, fd) != NULL);
- 
- 		fclose(fd);
+ 		} while(fmap_gets(map, buffer, &at, sizeof(buffer) - 1));
  
  		if(retcode == CL_SUCCESS) {
  			cli_dbgmsg("Extract attachments from email %d\n", messagenumber);
@@@ -1317,24 -520,21 +485,21 @@@
  			 * CommuniGate Pro format: ignore headers until
  			 * blank line
  			 */
- 			while((fgets(buffer, sizeof(buffer) - 1, fd) != NULL) &&
+ 			while(fmap_gets(map, buffer, &at, sizeof(buffer) - 1) &&
  				(strchr("\r\n", buffer[0]) == NULL))
  					;
- 		LOCKFILE(fd);
  		/* getline_from_mbox could be using unlocked_stdio(3),
  		 * so lock file here */
  		/*
  		 * Ignore any blank lines at the top of the message
  		 */
  		while(strchr("\r\n", buffer[0]) &&
- 		     (getline_from_mbox(buffer, sizeof(buffer) - 1, fd) != NULL))
+ 		      (getline_from_mbox(buffer, sizeof(buffer) - 1, map, &at) != NULL))
  			;
  
  		buffer[sizeof(buffer) - 1] = '\0';
  
- 		body = parseEmailFile(fd, rfc821, buffer, dir);
- 		UNLOCKFILE(fd);
- 		fclose(fd);
+ 		body = parseEmailFile(map, &at, rfc821, buffer, dir);
  	}
  
  	if(body) {
@@@ -1387,13 -587,6 +552,6 @@@
  
  	cli_dbgmsg("cli_mbox returning %d\n", retcode);
  
- #ifdef HAVE_BACKTRACE
- 	signal(SIGSEGV, segv);
- #endif
- 
- #ifdef	SAVE_TMP
- 	if (cli_unlink(tmpfilename)) return CL_EUNLINK;
- #endif
  	return retcode;
  }
  
@@@ -1404,7 -597,7 +562,7 @@@
   * handled ungracefully...
   */
  static message *
- parseEmailFile(FILE *fin, const table_t *rfc821, const char *firstLine, const char *dir)
+ parseEmailFile(fmap_t *map, size_t *at, const table_t *rfc821, const char *firstLine, const char *dir)
  {
  	bool inHeader = TRUE;
  	bool bodyIsEmpty = TRUE;
@@@ -1498,7 -691,7 +656,7 @@@
  				bodyIsEmpty = TRUE;
  			} else {
  				char *ptr;
- 				int lookahead;
+ 				char *lookahead;
  
  				if(fullline == NULL) {
  					char cmd[RFC2821LENGTH + 1], out[RFC2821LENGTH + 1];
@@@ -1551,10 -744,7 +709,7 @@@
  
  				assert(fullline != NULL);
  
- 				lookahead = GETC(fin);
- 				if(lookahead != EOF) {
- 					ungetc(lookahead, fin);
- 
+ 				if((lookahead = fmap_need_off_once(map, *at, 1))) {
  					/*
  					 * Section B.2 of RFC822 says TAB or
  					 * SPACE means a continuation of the
@@@ -1562,7 -752,7 +717,7 @@@
  					 *
  					 * Add all the arguments on the line
  					 */
- 					if(isblank(lookahead))
+ 					if(isblank(*lookahead))
  						continue;
  				}
  
@@@ -1595,7 -785,7 +750,7 @@@
  			 * TODO: binhex, yenc
  			 */
  			bodyIsEmpty = FALSE;
- 			if(uudecodeFile(ret, line, dir, fin) < 0)
+ 			if(uudecodeFile(ret, line, dir, map, at) < 0)
  				if(messageAddStr(ret, line) < 0)
  					break;
  		} else {
@@@ -1629,7 -819,7 +784,7 @@@
  			if(messageAddStr(ret, line) < 0)
  				break;
  		}
- 	} while(getline_from_mbox(buffer, sizeof(buffer) - 1, fin) != NULL);
+ 	} while(getline_from_mbox(buffer, sizeof(buffer) - 1, map, at) != NULL);
  
  	if(boundary)
  		free(boundary);
@@@ -3639,9 -2829,24 +2794,9 @@@ rfc1341(message *m, const char *dir
  	if(id == NULL)
  		return -1;
  
 -/* do we need this for C_WINDOWS?
 -#ifdef  C_CYGWIN
 -	if((tmpdir = getenv("TEMP")) == (char *)NULL)
 -		if((tmpdir = getenv("TMP")) == (char *)NULL)
 -			if((tmpdir = getenv("TMPDIR")) == (char *)NULL)
 -				tmpdir = "C:\\";
 -#else
 -*/
 -	if((tmpdir = getenv("TMPDIR")) == (char *)NULL)
 -		if((tmpdir = getenv("TMP")) == (char *)NULL)
 -			if((tmpdir = getenv("TEMP")) == (char *)NULL)
 -#ifdef	P_tmpdir
 -				tmpdir = P_tmpdir;
 -#else
 -				tmpdir = "/tmp";
 -#endif
 +	tmpdir = cli_gettmpdir();
  
 -	snprintf(pdir, sizeof(pdir) - 1, "%s/clamav-partial", tmpdir);
 +	snprintf(pdir, sizeof(pdir) - 1, "%s"PATHSEP"clamav-partial", tmpdir);
  
  	if((mkdir(pdir, S_IRWXU) < 0) && (errno != EEXIST)) {
  		cli_errmsg("Can't create the directory '%s'\n", pdir);
@@@ -3725,7 -2930,7 +2880,7 @@@
  
  			sanitiseName(id);
  
 -			snprintf(outname, sizeof(outname) - 1, "%s/%s", dir, id);
 +			snprintf(outname, sizeof(outname) - 1, "%s"PATHSEP"%s", dir, id);
  
  			cli_dbgmsg("outname: %s\n", outname);
  
@@@ -3764,15 -2969,16 +2919,15 @@@
  					int nblanks;
  					struct stat statb;
  					const char *dentry_idpart;
 -#ifndef C_WINDOWS
 +
  					if(dent->d_ino == 0)
  						continue;
 -#endif
  
  					if(!strcmp(".",dent->d_name) ||
  							!strcmp("..", dent->d_name))
  						continue;
  					snprintf(fullname, sizeof(fullname) - 1,
 -						"%s/%s", pdir, dent->d_name);
 +						"%s"PATHSEP"%s", pdir, dent->d_name);
  					dentry_idpart = strchr(dent->d_name, '_');
  
  					if(!dentry_idpart ||
@@@ -4055,63 -3261,65 +3210,65 @@@ usefulHeader(int commandNumber, const c
   * Like fgets but cope with end of line by "\n", "\r\n", "\n\r", "\r"
   */
  static char *
- getline_from_mbox(char *buffer, size_t len, FILE *fin)
+ getline_from_mbox(char *buffer, size_t buffer_len, fmap_t *map, size_t *at)
  {
- 	char *ret;
+     char *src, *cursrc, *curbuf;
+     size_t i;
+     size_t input_len = MIN(map->len - *at, buffer_len + 1);
+     src = cursrc = fmap_need_off_once(map, *at, input_len);
  
  /*	we check for eof from the result of GETC()
   *	if(feof(fin)) 
  		return NULL;*/
+     if(!src) {
+ 	cli_dbgmsg("getline_from_mbox: fmap need failed\n");
+ 	return NULL;
+     }
+     if((buffer_len == 0) || (buffer == NULL)) {
+ 	cli_errmsg("Invalid call to getline_from_mbox(). Refer to http://www.clamav.net/bugs\n");
+ 	return NULL;
+     }
  
- 	if((len == 0) || (buffer == NULL)) {
- 		cli_errmsg("Invalid call to getline_from_mbox(). Refer to http://www.clamav.net/bugs\n");
- 		return NULL;
- 	}
- 
- 	ret = buffer;
- 
- 	do {
- 		int c = GETC(fin);
- 
- 		switch(c) {
- 			default:
- 				*buffer = (char)c;
- 				buffer += (c != 0);
- 				continue;
- 			case '\n':
- 				*buffer++ = '\n';
- 				c = GETC(fin);
- 				if((c != '\r') && !feof(fin))
- 					ungetc(c, fin);
- 				break;
- 			case EOF:
- 				if(ret == buffer || ferror(fin)) {
- 					/* EOF on first char, or error */
- 					return NULL;
- 				}
- 				break;
- 			case '\r':
- 				*buffer++ = '\n';
- 				c = GETC(fin);
- 				if((c != '\n') && !feof(fin))
- 					ungetc(c, fin);
- 				break;
- 		}
- 		break;
- 	} while(--len > 1);
+     curbuf = buffer;
+ 	
+     for(i=0; i<buffer_len-1; i++) {
+ 	char c;
  
- 	if(len == 0) {
- 		/* the email probably breaks RFC821 */
- 		cli_dbgmsg("getline_from_mbox: buffer overflow stopped, line lost\n");
+ 	if(!input_len--) {
+ 	    if(curbuf == buffer) {
+ 		/* EOF on first char */
  		return NULL;
+ 	    }
+ 	    break;
  	}
- 	*buffer = '\0';
- 
- 	if(len == 1)
- 		/* overflows will have appeared on separate lines */
- 		cli_dbgmsg("getline_from_mbox: buffer overflow stopped, line recovered\n");
  
- 	return ret;
+ 	switch((c = *cursrc++)) {
+ 	case '\0':
+ 	    continue;
+ 	case '\n':
+ 	    *curbuf++ = '\n';
+ 	    if(input_len && *cursrc == '\r') {
+ 		i++;
+ 		cursrc++;
+ 	    }
+ 	    break;
+ 	case '\r':
+ 	    *curbuf++ = '\r';
+ 	    if(input_len && *cursrc == '\n') {
+ 		i++;
+ 		cursrc++;
+ 	    }
+ 	    break;
+ 	default:
+ 	    *curbuf++ = c;
+ 	    continue;
+ 	}
+ 	break;
+     }
+     *at += cursrc - src;
+     *curbuf = '\0';
+     
+     return buffer;
  }
  
  /*
diff --combined libclamav/nsis/nulsft.c
index 5ca1441,704121d..96561b7
--- a/libclamav/nsis/nulsft.c
+++ b/libclamav/nsis/nulsft.c
@@@ -30,9 -30,6 +30,6 @@@
  #ifdef HAVE_UNISTD_H
  #include <unistd.h>
  #endif
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
  
  #include "others.h"
  #include "cltypes.h"
@@@ -43,7 -40,12 +40,8 @@@
  #include "matcher.h"
  #include "scanners.h"
  #include "nulsft.h" /* SHUT UP GCC -Wextra */
+ #include "fmap.h"
  
 -#ifndef O_BINARY
 -#define O_BINARY 0
 -#endif
 -
  #define EC32(x) le32_to_host(x)
  
  enum {
@@@ -55,7 -57,7 +53,7 @@@
  };
  
  struct nsis_st {
-   int ifd;
+   size_t curpos;
    int ofd;
    off_t off;
    off_t fullsz;
@@@ -73,6 -75,7 +71,7 @@@
  /*   z_stream z; */
    nsis_z_stream z;
    unsigned char *freeme;
+   fmap_t *map;
    char ofn[1024];
  };
  
@@@ -198,9 -201,9 +197,9 @@@ static int nsis_unpack_next(struct nsis
      return ret;
  
    if (n->fno)
 -    snprintf(n->ofn, 1023, "%s/content.%.3u", n->dir, n->fno);
 +    snprintf(n->ofn, 1023, "%s"PATHSEP"content.%.3u", n->dir, n->fno);
    else
 -    snprintf(n->ofn, 1023, "%s/headers", n->dir);
 +    snprintf(n->ofn, 1023, "%s"PATHSEP"headers", n->dir);
  
    n->fno++;
  
@@@ -210,11 -213,12 +209,12 @@@
    }
  
    if (!n->solid) {
-     if (cli_readn(n->ifd, &size, 4)!=4) {
+     if (fmap_readn(n->map, &size, n->curpos, 4)!=4) {
        cli_dbgmsg("NSIS: reached EOF - extraction complete\n");
        close(n->ofd);
        return CL_BREAK;
      }
+     n->curpos += 4;
      if (n->asz==4) {
        cli_dbgmsg("NSIS: reached CRC - extraction complete\n");
        close(n->ofd);
@@@ -235,31 -239,24 +235,24 @@@
  
      if ((ret=cli_checklimits("NSIS", ctx, size, 0, 0))!=CL_CLEAN) {
        close(n->ofd);
-       if (lseek(n->ifd, size, SEEK_CUR)==-1) return CL_ESEEK;
+       n->curpos += size;
        return ret;
      }
-     if (!(ibuf= (unsigned char *) cli_malloc(size))) {
-       	cli_dbgmsg("NSIS: out of memory"__AT__"\n");
-       close(n->ofd);
-       return CL_EMEM;
-     }
-     if (cli_readn(n->ifd, ibuf, size) != (ssize_t) size) {
+     if (!(ibuf = fmap_need_off_once(n->map, n->curpos, size))) {
        cli_dbgmsg("NSIS: cannot read %u bytes"__AT__"\n", size);
        close(n->ofd);
        return CL_EREAD;
      }
+     n->curpos += size;
      if (loops==size) {
        if (cli_writen(n->ofd, ibuf, size) != (ssize_t) size) {
  	cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
- 	free(ibuf);
  	close(n->ofd);
  	return CL_EWRITE;
        }
      } else {
        if ((ret=nsis_init(n))!=CL_SUCCESS) {
  	cli_dbgmsg("NSIS: decompressor init failed"__AT__"\n");
- 	free(ibuf);
  	close(n->ofd);
  	return ret;
        }
@@@ -275,7 -272,6 +268,6 @@@
  	  gotsome=1;
  	  if (cli_writen(n->ofd, obuf, size) != (ssize_t) size) {
  	    cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
- 	    free(ibuf);
  	    close(n->ofd);
  	    nsis_shutdown(n);
  	    return CL_EWRITE;
@@@ -284,7 -280,6 +276,6 @@@
  	  n->nsis.avail_out = BUFSIZ;
  	  loops=0;
  	  if ((ret=cli_checklimits("NSIS", ctx, size, 0, 0))!=CL_CLEAN) {
- 	    free(ibuf);
  	    close(n->ofd);
  	    nsis_shutdown(n);
  	    return ret;
@@@ -302,7 -297,6 +293,6 @@@
  	gotsome=1;
  	if (cli_writen(n->ofd, obuf, n->nsis.next_out - obuf) != n->nsis.next_out - obuf) {
  	  cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
- 	  free(ibuf);
  	  close(n->ofd);
  	  return CL_EWRITE;
  	}
@@@ -316,13 -310,11 +306,11 @@@
  	  ret = CL_EMAXSIZE;
  	  close(n->ofd);
  	}
- 	free(ibuf);
  	return ret;
        }
  
      }
  
-     free(ibuf);
      return CL_SUCCESS;
  
    } else {
@@@ -332,31 -324,12 +320,12 @@@
  	close(n->ofd);
  	return ret;
        }
- #if HAVE_MMAP
-       if((n->freeme= (unsigned char *)mmap(NULL, n->fullsz, PROT_READ, MAP_PRIVATE, n->ifd, 0))==MAP_FAILED) {
- 	cli_dbgmsg("NSIS: mmap() failed"__AT__"\n");
- 	close(n->ofd);
- 	return CL_EMAP;
-       }
-       n->nsis.next_in = n->freeme+n->off+0x1c;
- #else /* HAVE_MMAP */
-       if(!size || size > CLI_MAX_ALLOCATION) {
- 	cli_dbgmsg("NSIS: mmap() support not compiled in and input file too big\n");
- 	close(n->ofd);
- 	return CL_EMEM;
-       }
-       if (!(n->freeme= (unsigned char *) cli_malloc(n->asz))) {
- 	cli_dbgmsg("NSIS: out of memory"__AT__"\n");
- 	close(n->ofd);
- 	return CL_EMEM;
-       }
-       if (cli_readn(n->ifd, n->freeme, n->asz) != (ssize_t) n->asz) {
+       if(!(n->freeme = fmap_need_off_once(n->map, n->curpos, n->asz))) {
  	cli_dbgmsg("NSIS: cannot read %u bytes"__AT__"\n", n->asz);
  	close(n->ofd);
  	return CL_EREAD;
        }
        n->nsis.next_in = n->freeme;
- #endif /* HAVE_MMAP */
        n->nsis.avail_in = n->asz;
      }
  
@@@ -450,52 -423,52 +419,52 @@@ static uint8_t nsis_detcomp(const char 
  }
  
  static int nsis_headers(struct nsis_st *n, cli_ctx *ctx) {
-   char buf[28];
-   struct stat st;
+   const char *buf;
    uint32_t pos;
    int i;
    uint8_t comps[] = {0, 0, 0, 0}, trunc = 0;
    
-   if (fstat(n->ifd, &st)==-1 ||
-       lseek(n->ifd, n->off, SEEK_SET)==-1 ||
-       cli_readn(n->ifd, buf, 28) != 28)
+   if (!(buf = fmap_need_off_once(n->map, n->off, 0x1c)))
      return CL_EREAD;
  
    n->hsz = (uint32_t)cli_readint32(buf+0x14);
    n->asz = (uint32_t)cli_readint32(buf+0x18);
-   n->fullsz = st.st_size;
+   n->fullsz = n->map->len;
  
    cli_dbgmsg("NSIS: Header info - Flags=%x, Header size=%x, Archive size=%x\n", cli_readint32(buf), n->hsz, n->asz);
  
-   if (st.st_size - n->off < (off_t) n->asz) {
+   if (n->fullsz - n->off < (off_t) n->asz) {
      cli_dbgmsg("NSIS: Possibly truncated file\n");
-     n->asz = st.st_size - n->off;
+     n->asz = n->fullsz - n->off;
      trunc++;
-   } else if (st.st_size - n->off != (off_t) n->asz) {
+   } else if (n->fullsz - n->off != (off_t) n->asz) {
      cli_dbgmsg("NSIS: Overlays found\n");
    }
  
    n->asz -= 0x1c;
+   buf += 0x1c;
  
    /* Guess if solid */
    for (i=0, pos=0;pos < n->asz-4;i++) {
      int32_t nextsz;
-     if (cli_readn(n->ifd, buf+4, 4)!=4) return CL_EREAD;
-     nextsz=cli_readint32(buf+4);
-     if (!i) n->comp = nsis_detcomp(buf+4);
+     if (!(buf = fmap_need_ptr_once(n->map, (void *)buf, 4))) return CL_EREAD;
+     nextsz=cli_readint32(buf);
+     if (!i) n->comp = nsis_detcomp(buf);
+     buf += 4;
      if (nextsz&0x80000000) {
        nextsz&=~0x80000000;
-       if (cli_readn(n->ifd, buf+4, 4)!=4) return CL_EREAD;
-       comps[nsis_detcomp(buf+4)]++;
+       if (!(buf = fmap_need_ptr_once(n->map, (void *)buf, 4))) return CL_EREAD;
+       comps[nsis_detcomp(buf)]++;
        nextsz-=4;
        pos+=4;
+       buf+=4;
      }
      if ((pos+=4+nextsz) > n->asz) {
        n->solid = 1;
        break;
      }
  
-     if (lseek(n->ifd, nextsz, SEEK_CUR)==-1) return CL_ESEEK;
+     buf += nextsz;
    }
    
    if (trunc && i>=2) n->solid=0;
@@@ -508,8 -481,7 +477,7 @@@
      n->comp = (comps[1]<comps[2]) ? (comps[2]<comps[3] ? COMP_ZLIB : COMP_LZMA) : (comps[1]<comps[3] ? COMP_ZLIB : COMP_BZIP2);
    }
  
-   if (lseek(n->ifd, n->off+0x1c, SEEK_SET)==-1) return CL_ESEEK;
- 
+   n->curpos = n->off+0x1c;
    return nsis_unpack_next(n, ctx);
  }
  
@@@ -519,16 -491,6 +487,6 @@@ static int cli_nsis_unpack(struct nsis_
    return (n->fno) ? nsis_unpack_next(n, ctx) : nsis_headers(n, ctx);
  }
  
- static void cli_nsis_free(struct nsis_st *n) {
-   nsis_shutdown(n);
-   if (n->solid && n->freeme) {
- #if HAVE_MMAP
-     munmap(n->freeme, n->fullsz);
- #else
-     free(n->freeme);
- #endif
-   }
- }
  
  int cli_scannulsft(int desc, cli_ctx *ctx, off_t offset) {
          int ret;
@@@ -538,7 -500,6 +496,6 @@@
  
      memset(&nsist, 0, sizeof(struct nsis_st));
  
-     nsist.ifd = desc;
      nsist.off = offset;
      if (!(nsist.dir = cli_gentemp(ctx->engine->tmpdir)))
          return CL_ETMPDIR;
@@@ -547,6 -508,11 +504,11 @@@
  	free(nsist.dir);
  	return CL_ETMPDIR;
      }
+     
+     if(!(nsist.map = fmap(desc, 0, 0))) {
+ 	cli_errmsg("scannulsft: fmap failed\n");
+ 	return CL_EMEM;
+     }
  
      if(ctx->engine->keeptmp) cli_dbgmsg("NSIS: Extracting files to %s\n", nsist.dir);
  
@@@ -570,7 -536,8 +532,8 @@@
      if(ret == CL_BREAK || ret == CL_EMAXFILES)
  	ret = CL_CLEAN;
  
-     cli_nsis_free(&nsist);
+     nsis_shutdown(&nsist);
+     funmap(nsist.map);
  
      if(!ctx->engine->keeptmp)
          cli_rmdirs(nsist.dir);
diff --combined libclamav/ole2_extract.c
index 0952504,71ce49d..f37589a
--- a/libclamav/ole2_extract.c
+++ b/libclamav/ole2_extract.c
@@@ -34,16 -34,13 +34,13 @@@
  #endif
  #include <ctype.h>
  #include <stdlib.h>
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
  #include "clamav.h"
  
  #include "cltypes.h"
  #include "others.h"
  #include "ole2_extract.h"
  #include "scanners.h"
- #include "mbox.h"
+ #include "fmap.h"
  
  #define ole2_endian_convert_16(v) le16_to_host((uint16_t)(v))
  #define ole2_endian_convert_32(v) le32_to_host((uint32_t)(v))
@@@ -60,6 -57,11 +57,6 @@@
  #pragma pack 1
  #endif
  
 -#ifndef	O_BINARY
 -#define	O_BINARY	0
 -#endif
 -
 -
  typedef struct ole2_header_tag
  {
  	unsigned char magic[8];		/* should be: 0xd0cf11e0a1b11ae1 */
@@@ -89,10 -91,10 +86,10 @@@
  	   reading the header */
  	int32_t sbat_root_start __attribute__ ((packed));
  	uint32_t max_block_no;
  	off_t m_length;
  	bitset_t *bitset;
  	struct uniq *U;
+ 	fmap_t *map;
  	int has_vba;
  } ole2_header_t;
  
@@@ -276,9 -278,10 +273,10 @@@ static void print_ole2_header(ole2_head
  	return;
  }
  
- static int ole2_read_block(int fd, ole2_header_t *hdr, void *buff, unsigned int size, int32_t blockno)
+ static int ole2_read_block(ole2_header_t *hdr, void *buff, unsigned int size, int32_t blockno)
  {
  	off_t offset, offend;
+ 	void *pblock;
  
  	if (blockno < 0) {
  		return FALSE;
@@@ -287,24 -290,18 +285,18 @@@
  	/* other methods: (blockno+1) * 512 or (blockno * block_size) + 512; */
  	offset = (blockno << hdr->log2_big_block_size) + MAX(512, 1 << hdr->log2_big_block_size); /* 512 is header size */
  	
- 	if (hdr->m_area == NULL) {
- 		if (lseek(fd, offset, SEEK_SET) != offset) {
- 			return FALSE;
- 		}
- 		if (cli_readn(fd, buff, size) != size) {
- 			return FALSE;
- 		}
- 	} else {
- 		offend = offset + size;
- 		if ((offend <= 0) || (offend > hdr->m_length)) {
- 			return FALSE;
- 		}
- 		memcpy(buff, hdr->m_area+offset, size);
+ 	offend = offset + size;
+ 	if ((offend <= 0) || (offend > hdr->m_length)) {
+ 	    return FALSE;
+ 	}
+ 	if(!(pblock = fmap_need_off_once(hdr->map, offset, size))) {
+ 	    return FALSE;
  	}
+ 	memcpy(buff, pblock, size);
  	return TRUE;
  }
  
- static int32_t ole2_get_next_bat_block(int fd, ole2_header_t *hdr, int32_t current_block)
+ static int32_t ole2_get_next_bat_block(ole2_header_t *hdr, int32_t current_block)
  {
  	int32_t bat_array_index;
  	uint32_t bat[128];
@@@ -318,14 -315,14 +310,14 @@@
  		cli_dbgmsg("bat_array index error\n");
  		return -10;
  	}
- 	if (!ole2_read_block(fd, hdr, &bat, 512,
+ 	if (!ole2_read_block(hdr, &bat, 512,
  			ole2_endian_convert_32(hdr->bat_array[bat_array_index]))) {
  		return -1;
  	}
  	return ole2_endian_convert_32(bat[current_block-(bat_array_index * 128)]);
  }
  
- static int32_t ole2_get_next_xbat_block(int fd, ole2_header_t *hdr, int32_t current_block)
+ static int32_t ole2_get_next_xbat_block(ole2_header_t *hdr, int32_t current_block)
  {
  	int32_t xbat_index, xbat_block_index, bat_index, bat_blockno;
  	uint32_t xbat[128], bat[128];
@@@ -344,40 -341,40 +336,40 @@@
  
  	bat_index = current_block % 128;
  
- 	if (!ole2_read_block(fd, hdr, &xbat, 512, hdr->xbat_start)) {
+ 	if (!ole2_read_block(hdr, &xbat, 512, hdr->xbat_start)) {
  		return -1;
  	}
  
  	/* Follow the chain of XBAT blocks */
  	while (xbat_block_index > 0) {
- 		if (!ole2_read_block(fd, hdr, &xbat, 512,
+ 		if (!ole2_read_block(hdr, &xbat, 512,
  				ole2_endian_convert_32(xbat[127]))) {
  			return -1;
  		}
  		xbat_block_index--;
  	}
  
- 	if (!ole2_read_block(fd, hdr, &bat, 512, ole2_endian_convert_32(xbat[bat_blockno]))) {
+ 	if (!ole2_read_block(hdr, &bat, 512, ole2_endian_convert_32(xbat[bat_blockno]))) {
  		return -1;
  	}
  
  	return ole2_endian_convert_32(bat[bat_index]);
  }
  
- static int32_t ole2_get_next_block_number(int fd, ole2_header_t *hdr, int32_t current_block)
+ static int32_t ole2_get_next_block_number(ole2_header_t *hdr, int32_t current_block)
  {
  	if (current_block < 0) {
  		return -1;
  	}
  
  	if ((current_block / 128) > 108) {
- 		return ole2_get_next_xbat_block(fd, hdr, current_block);
+ 		return ole2_get_next_xbat_block(hdr, current_block);
  	} else {
- 		return ole2_get_next_bat_block(fd, hdr, current_block);
+ 		return ole2_get_next_bat_block(hdr, current_block);
  	}
  }
  
- static int32_t ole2_get_next_sbat_block(int fd, ole2_header_t *hdr, int32_t current_block)
+ static int32_t ole2_get_next_sbat_block(ole2_header_t *hdr, int32_t current_block)
  {
  	int32_t iter, current_bat_block;
  	uint32_t sbat[128];
@@@ -389,17 -386,17 +381,17 @@@
  	current_bat_block = hdr->sbat_start;
  	iter = current_block / 128;
  	while (iter > 0) {
- 		current_bat_block = ole2_get_next_block_number(fd, hdr, current_bat_block);
+ 		current_bat_block = ole2_get_next_block_number(hdr, current_bat_block);
  		iter--;
  	}
- 	if (!ole2_read_block(fd, hdr, &sbat, 512, current_bat_block)) {
+ 	if (!ole2_read_block(hdr, &sbat, 512, current_bat_block)) {
  		return -1;
  	}
  	return ole2_endian_convert_32(sbat[current_block % 128]);
  }
  
  /* Retrieve the block containing the data for the given sbat index */
- static int32_t ole2_get_sbat_data_block(int fd, ole2_header_t *hdr, void *buff, int32_t sbat_index)
+ static int32_t ole2_get_sbat_data_block(ole2_header_t *hdr, void *buff, int32_t sbat_index)
  {
  	int32_t block_count, current_block;
  
@@@ -415,17 -412,17 +407,17 @@@
  	block_count = sbat_index / (1 << (hdr->log2_big_block_size - hdr->log2_small_block_size));
  	current_block = hdr->sbat_root_start;
  	while (block_count > 0) {
- 		current_block = ole2_get_next_block_number(fd, hdr, current_block);
+ 		current_block = ole2_get_next_block_number(hdr, current_block);
  		block_count--;
  	}
  	/* current_block now contains the block number of the sbat array
  	   containing the entry for the required small block */
  
- 	return(ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block));
+ 	return(ole2_read_block(hdr, buff, 1 << hdr->log2_big_block_size, current_block));
  }
  
- static int ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir, int32_t prop_index,
- 				   int (*handler)(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx),
+ static int ole2_walk_property_tree(ole2_header_t *hdr, const char *dir, int32_t prop_index,
+ 				   int (*handler)(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx),
  				   unsigned int rec_level, unsigned int *file_count, cli_ctx *ctx, unsigned long *scansize)
  {
  	property_t prop_block[4];
@@@ -450,13 -447,13 +442,13 @@@
  
  	idx = prop_index / 4;
  	for (i=0 ; i < idx ; i++) {
- 		current_block = ole2_get_next_block_number(fd, hdr, current_block);
+ 		current_block = ole2_get_next_block_number(hdr, current_block);
  		if (current_block < 0) {
  			return CL_SUCCESS;
  		}
  	}
  	idx = prop_index % 4;
- 	if (!ole2_read_block(fd, hdr, prop_block, 512,
+ 	if (!ole2_read_block(hdr, prop_block, 512,
  			current_block)) {
  		return CL_SUCCESS;
  	}	
@@@ -497,11 -494,11 +489,11 @@@
  			}
  			hdr->sbat_root_start = prop_block[idx].start_block;
  			if (
- 				(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ 				(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
  				||
- 				(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ 				(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
  				||
- 				(ret=ole2_walk_property_tree(fd, hdr, dir,prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ 				(ret=ole2_walk_property_tree(hdr, dir,prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
  			) return ret;
  			break;
  		case 2: /* File */
@@@ -512,24 -509,24 +504,24 @@@
  			if (!ctx || !ctx->engine->maxfilesize || prop_block[idx].size <= ctx->engine->maxfilesize || prop_block[idx].size <= *scansize) {
  				(*file_count)++;
  				*scansize-=prop_block[idx].size;
- 				if ((ret=handler(fd, hdr, &prop_block[idx], dir, ctx)) != CL_SUCCESS)
+ 				if ((ret=handler(hdr, &prop_block[idx], dir, ctx)) != CL_SUCCESS)
  					return ret;
  			} else {
  				cli_dbgmsg("OLE2: filesize exceeded\n");
  			}
  			if (
- 				(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].prev, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
+ 				(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].prev, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
  				||
- 				(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].next, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
+ 				(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].next, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
  				||
- 				(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].child, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
+ 				(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].child, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
  			) return ret;
  			break;
  		case 1: /* Directory */
  			if (dir) {
  				dirname = (char *) cli_malloc(strlen(dir)+8);
  				if (!dirname) return CL_BREAK;
 -				snprintf(dirname, strlen(dir)+8, "%s/%.6d", dir, prop_index);
 +				snprintf(dirname, strlen(dir)+8, "%s"PATHSEP"%.6d", dir, prop_index);
  				if (mkdir(dirname, 0700) != 0) {
  					free(dirname);
  					return CL_BREAK;
@@@ -537,11 -534,11 +529,11 @@@
  				cli_dbgmsg("OLE2 dir entry: %s\n",dirname);
  			} else dirname = NULL;
  			if (
- 				(ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ 				(ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
  				||
- 				(ret=ole2_walk_property_tree(fd, hdr, dir,prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ 				(ret=ole2_walk_property_tree(hdr, dir,prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
  				||
- 				(ret=ole2_walk_property_tree(fd, hdr, dirname, prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ 				(ret=ole2_walk_property_tree(hdr, dirname, prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
  			) {} 
  			if (dirname) free(dirname);
  			return ret;
@@@ -553,7 -550,7 +545,7 @@@
  	return CL_SUCCESS;
  }
  /* Write file Handler - write the contents of the entry to a file */
- static int handler_writefile(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
+ static int handler_writefile(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
  {
  	unsigned char *buff;
  	int32_t current_block, ofd, len, offset;
@@@ -575,7 -572,7 +567,7 @@@
  	name = get_property_name2(prop->name, prop->name_size);
  	if (name) cnt = uniq_add(hdr->U, name, strlen(name), &hash);
  	else cnt = uniq_add(hdr->U, NULL, 0, &hash);
 -	snprintf(newname, sizeof(newname), "%s/%s_%u", dir, hash, cnt);
 +	snprintf(newname, sizeof(newname), "%s"PATHSEP"%s_%u", dir, hash, cnt);
  	newname[sizeof(newname)-1]='\0';
  	cli_dbgmsg("OLE2 [handler_writefile]: Dumping '%s' to '%s'\n", name ? name : "<empty>", newname);
  	if (name) free(name);
@@@ -626,7 -623,7 +618,7 @@@
  		}			
  		if (prop->size < (int64_t)hdr->sbat_cutoff) {
  			/* Small block file */
- 			if (!ole2_get_sbat_data_block(fd, hdr, buff, current_block)) {
+ 			if (!ole2_get_sbat_data_block(hdr, buff, current_block)) {
  				cli_dbgmsg("OLE2 [handler_writefile]: ole2_get_sbat_data_block failed\n");
  				close(ofd);
  				free(buff);
@@@ -644,10 -641,10 +636,10 @@@
  			}
  
  			len -= MIN(len,1 << hdr->log2_small_block_size);
- 			current_block = ole2_get_next_sbat_block(fd, hdr, current_block);
+ 			current_block = ole2_get_next_sbat_block(hdr, current_block);
  		} else {
  			/* Big block file */
- 			if (!ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
+ 			if (!ole2_read_block(hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
  				close(ofd);
  				free(buff);
  				cli_bitset_free(blk_bitset);
@@@ -661,7 -658,7 +653,7 @@@
  				return CL_BREAK;
  			}
  
- 			current_block = ole2_get_next_block_number(fd, hdr, current_block);
+ 			current_block = ole2_get_next_block_number(hdr, current_block);
  			len -= MIN(len,(1 << hdr->log2_big_block_size));
  		}
  	}
@@@ -672,7 -669,7 +664,7 @@@
  }
  
  /* enum file Handler - checks for VBA presence */
- static int handler_enum(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
+ static int handler_enum(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
  {
    char *name;
    
@@@ -688,7 -685,7 +680,7 @@@
  }
  
  
- static int handler_otf(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
+ static int handler_otf(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
  {
    char *tempfile;
    unsigned char *buff;
@@@ -753,7 -750,7 +745,7 @@@
      }			
      if (prop->size < (int64_t)hdr->sbat_cutoff) {
        /* Small block file */
-       if (!ole2_get_sbat_data_block(fd, hdr, buff, current_block)) {
+       if (!ole2_get_sbat_data_block(hdr, buff, current_block)) {
  	cli_dbgmsg("ole2_get_sbat_data_block failed\n");
  	break;
        }
@@@ -772,10 -769,10 +764,10 @@@
        }
  
        len -= MIN(len,1 << hdr->log2_small_block_size);
-       current_block = ole2_get_next_sbat_block(fd, hdr, current_block);
+       current_block = ole2_get_next_sbat_block(hdr, current_block);
      } else {
        /* Big block file */
-       if (!ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
+       if (!ole2_read_block(hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
  	break;
        }
        if (cli_writen(ofd, buff, MIN(len,(1 << hdr->log2_big_block_size))) !=
@@@ -791,7 -788,7 +783,7 @@@
  	return CL_EWRITE;
        }
  
-       current_block = ole2_get_next_block_number(fd, hdr, current_block);
+       current_block = ole2_get_next_block_number(hdr, current_block);
        len -= MIN(len,(1 << hdr->log2_big_block_size));
      }
    }
@@@ -874,13 -871,13 +866,13 @@@ static int ole2_read_header(int fd, ole
  }
  #endif
  
- int cli_ole2_extract(int fd, const char *dirname, cli_ctx *ctx, struct uniq **vba)
+ int cli_ole2_extract(const char *dirname, cli_ctx *ctx, struct uniq **vba)
  {
  	ole2_header_t hdr;
  	int hdr_size, ret=CL_CLEAN;
- 	struct stat statbuf;
  	unsigned int file_count=0;
  	unsigned long scansize, scansize2;
+ 	void *phdr;
  
  	cli_dbgmsg("in cli_ole2_extract()\n");
  
@@@ -895,40 -892,22 +887,22 @@@
  	
  	/* size of header - size of other values in struct */
  	hdr_size = sizeof(struct ole2_header_tag) - sizeof(int32_t) - sizeof(uint32_t) -
- 			sizeof(unsigned char *) - sizeof(off_t) - sizeof(bitset_t *) -
- 			sizeof(struct uniq *) - sizeof(int);
+ 			sizeof(off_t) - sizeof(bitset_t *) -
+ 			sizeof(struct uniq *) - sizeof(int) - sizeof(fmap_t *);
  
- 	hdr.m_area = NULL;
- 
- 	if (fstat(fd, &statbuf) == 0) {
- 		if (statbuf.st_size < hdr_size) {
- 			return CL_CLEAN;
- 		}
- #ifdef HAVE_MMAP
- 		hdr.m_length = statbuf.st_size;
- 		hdr.m_area = (unsigned char *) mmap(NULL, hdr.m_length, PROT_READ, MAP_PRIVATE, fd, 0);
- 		if (hdr.m_area == MAP_FAILED) {
- 			hdr.m_area = NULL;
- 		} else {
- 			cli_dbgmsg("mmap'ed file\n");
- 			memcpy(&hdr, hdr.m_area, hdr_size);
- 		}
- #endif
+ 	if((*ctx->fmap)->len < hdr_size) {
+ 	    return CL_CLEAN;
  	}
- 
- 	if (hdr.m_area == NULL) {
- 		hdr.bitset = NULL;
- #if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
- 		if (cli_readn(fd, &hdr, hdr_size) != hdr_size) {
- 			goto abort;
- 		}
- #else
- 		if (!ole2_read_header(fd, &hdr)) {
- 			goto abort;
- 		}
- #endif
+ 	hdr.map = *ctx->fmap;
+ 	hdr.m_length = hdr.map->len;
+ 	phdr = fmap_need_off_once(hdr.map, 0, hdr_size);
+ 	if(phdr) {
+ 	    memcpy(&hdr, phdr, hdr_size);
+ 	} else {
+ 	    cli_dbgmsg("cli_ole2_extract: failed to read header\n");
+ 	    goto abort;
  	}
- 	
+ 
  	hdr.minor_version = ole2_endian_convert_16(hdr.minor_version);
  	hdr.dll_version = ole2_endian_convert_16(hdr.dll_version);
  	hdr.byte_order = ole2_endian_convert_16(hdr.byte_order);
@@@ -970,14 -949,14 +944,14 @@@
  	}
  
  	/* 8 SBAT blocks per file block */
- 	hdr.max_block_no = (statbuf.st_size - MAX(512, 1 << hdr.log2_big_block_size)) / (1 << hdr.log2_small_block_size);
+ 	hdr.max_block_no = (hdr.map->len - MAX(512, 1 << hdr.log2_big_block_size)) / (1 << hdr.log2_small_block_size);
  
  	print_ole2_header(&hdr);
  	cli_dbgmsg("Max block number: %lu\n", (unsigned long int) hdr.max_block_no);
  
  	/* PASS 1 : Count files and check for VBA */
  	hdr.has_vba = 0;
- 	ret = ole2_walk_property_tree(fd, &hdr, NULL, 0, handler_enum, 0, &file_count, ctx, &scansize);
+ 	ret = ole2_walk_property_tree(&hdr, NULL, 0, handler_enum, 0, &file_count, ctx, &scansize);
  	cli_bitset_free(hdr.bitset);
  	hdr.bitset = NULL;
  	if (!file_count || !(hdr.bitset = cli_bitset_init()))
@@@ -993,7 -972,7 +967,7 @@@
  	    goto abort;
  	  }
  	  file_count = 0;
- 	  ole2_walk_property_tree(fd, &hdr, dirname, 0, handler_writefile, 0, &file_count, ctx, &scansize2);
+ 	  ole2_walk_property_tree(&hdr, dirname, 0, handler_writefile, 0, &file_count, ctx, &scansize2);
  	  ret = CL_CLEAN;
  	  *vba = hdr.U;
  	} else {
@@@ -1001,15 -980,10 +975,10 @@@
  	  /* PASS 2/B : OTF scan */
  	  file_count = 0;
  	  if(ctx)
- 	    ret = ole2_walk_property_tree(fd, &hdr, NULL, 0, handler_otf, 0, &file_count, ctx, &scansize2);
+ 	    ret = ole2_walk_property_tree(&hdr, NULL, 0, handler_otf, 0, &file_count, ctx, &scansize2);
  	}
  
  abort:
- #ifdef HAVE_MMAP
- 	if (hdr.m_area != NULL) {
- 		munmap(hdr.m_area, hdr.m_length);
- 	}
- #endif
  	if(hdr.bitset)
  	    cli_bitset_free(hdr.bitset);
  
diff --combined libclamav/others.h
index 9cef29e,b33e104..fb0dfb2
--- a/libclamav/others.h
+++ b/libclamav/others.h
@@@ -38,6 -38,7 +38,7 @@@
  #include "clamav.h"
  #include "dconf.h"
  #include "filetypes.h"
+ #include "fmap.h"
  #include "libclamunrar_iface/unrar_iface.h"
  #include "regex/regex.h"
  
@@@ -50,7 -51,7 +51,7 @@@
   * in re-enabling affected modules.
   */
  
 -#define CL_FLEVEL 47
 +#define CL_FLEVEL 49
  #define CL_FLEVEL_DCONF	CL_FLEVEL
  
  extern uint8_t cli_debug_flag;
@@@ -109,6 -110,7 +110,7 @@@ typedef struct 
      unsigned int found_possibly_unwanted;
      cli_file_t container_type; /* FIXME: to be made into a stack or array - see bb#1579 & bb#1293 */
      struct cli_dconf *dconf;
+     fmap_t **fmap;
  } cli_ctx;
  
  struct cl_engine {
@@@ -170,7 -172,7 +172,7 @@@
      struct cli_ftype *ftypes;
  
      /* Ignored signatures */
 -    struct cli_ignored *ignored;
 +    struct cli_matcher *ignored;
  
      /* PUA categories (to be included or excluded) */
      char *pua_cats;
@@@ -316,6 -318,21 +318,6 @@@ static inline void cli_writeint32(char 
  #endif
  #define CLI_SAR(n,s) n = CLI_SRS(n,s)
  
 -#ifndef	FALSE
 -#define FALSE (0)
 -#endif
 -
 -#ifndef	TRUE
 -#define TRUE (1)
 -#endif
 -
 -#ifndef MIN
 -#define MIN(a, b)	(((a) < (b)) ? (a) : (b))
 -#endif
 -#ifndef MAX
 -#define MAX(a,b)	(((a) > (b)) ? (a) : (b))
 -#endif
 -
  typedef struct bitset_tag
  {
          unsigned char *bitset;
@@@ -382,7 -399,6 +384,7 @@@ char *cli_md5file(const char *filename)
  int cli_unlink(const char *pathname);
  int cli_readn(int fd, void *buff, unsigned int count);
  int cli_writen(int fd, const void *buff, unsigned int count);
 +const char *cli_gettmpdir(void);
  char *cli_gentemp(const char *dir);
  int cli_gentempfd(const char *dir, char **name, int *fd);
  unsigned int cli_rndnum(unsigned int max);
diff --combined libclamav/pdf.c
index b79ec53,95e6a4e..9b2de23
--- a/libclamav/pdf.c
+++ b/libclamav/pdf.c
@@@ -26,7 -26,6 +26,6 @@@ static	char	const	rcsid[] = "$Id: pdf.c
  #include "clamav-config.h"
  #endif
  
- #ifdef	HAVE_MMAP
  #include <stdio.h>
  #include <sys/types.h>
  #include <sys/stat.h>
@@@ -41,18 -40,24 +40,16 @@@
  #ifdef	HAVE_UNISTD_H
  #include <unistd.h>
  #endif
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
  #include <zlib.h>
  
 -#ifdef	C_WINDOWS
 -#include <io.h>
 -#endif
 -
  #include "clamav.h"
  #include "others.h"
  #include "mbox.h"
  #include "pdf.h"
  #include "scanners.h"
+ #include "fmap.h"
  #include "str.h"
  
 -#ifndef	O_BINARY
 -#define	O_BINARY	0
 -#endif
 -
  #ifdef	CL_DEBUG
  /*#define	SAVE_TMP	
   *Save the file being worked on in tmp */
@@@ -65,7 -70,7 +62,7 @@@ static	const	char	*pdf_nextlinestart(co
  static	const	char	*pdf_nextobject(const char *ptr, size_t len);
  
  int
- cli_pdf(const char *dir, int desc, cli_ctx *ctx, off_t offset)
+ cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
  {
  	off_t size;	/* total number of bytes in the file */
  	off_t bytesleft, trailerlength;
@@@ -76,23 -81,18 +73,18 @@@
  	table_t *md5table;
  	int printed_predictor_message, printed_embedded_font_message, rc;
  	unsigned int files;
- 	struct stat statb;
+ 	fmap_t *map = *ctx->fmap;
  	int opt_failed = 0;
  
  	cli_dbgmsg("in cli_pdf(%s)\n", dir);
  
- 	if(fstat(desc, &statb) < 0) {
- 		cli_errmsg("cli_pdf: fstat() failed\n");
- 		return CL_EOPEN;
- 	}
- 
- 	size = statb.st_size - offset;
+ 	size = map->len - offset;
  
  	if(size <= 7)	/* doesn't even include the file header */
  		return CL_CLEAN;
  
- 	p = buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, offset);
- 	if(buf == MAP_FAILED) {
+ 	p = buf = fmap_need_off_once(map, 0, size); /* FIXME: really port to fmap */
+ 	if(!buf) {
  		cli_errmsg("cli_pdf: mmap() failed\n");
  		return CL_EMAP;
  	}
@@@ -112,7 -112,6 +104,6 @@@
  	}
  
  	if(!bytesleft) {
- 	    munmap(buf, size);
  	    cli_dbgmsg("cli_pdf: file header not found\n");
  	    return CL_CLEAN;
  	}
@@@ -123,7 -122,6 +114,6 @@@
  			break;
  
  	if(q <= p) {
- 		munmap(buf, size);
  		cli_dbgmsg("cli_pdf: trailer not found\n");
  		return CL_CLEAN;
  	}
@@@ -142,7 -140,6 +132,6 @@@
  		 * http://www.cs.cmu.edu/~dst/Adobe/Gallery/anon21jul01-pdf-encryption.txt
  		 * http://www.adobe.com/devnet/pdf/
  		 */
- 		munmap(buf, size);
  		cli_dbgmsg("cli_pdf: Encrypted PDF files not yet supported\n");
  		return CL_CLEAN;
  	}
@@@ -165,7 -162,6 +154,6 @@@
  				break;
  
  	if(xrefstart == p) {
- 		munmap(buf, size);
  		cli_dbgmsg("cli_pdf: xref not found\n");
  		return CL_CLEAN;
  	}
@@@ -386,7 -382,7 +374,7 @@@
  			has_cr = 1;
  		} else
  			has_cr = 0;
 -		snprintf(fullname, sizeof(fullname), "%s/pdf%02u", dir, files);
 +		snprintf(fullname, sizeof(fullname), "%s"PATHSEP"pdf%02u", dir, files);
  		fout = open(fullname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
  		if(fout < 0) {
  			char err[128];
@@@ -544,7 -540,6 +532,6 @@@
  		if(rc != CL_CLEAN) break;
  	}
  
- 	munmap(buf, size);
  
  	tableDestroy(md5table);
  
@@@ -840,17 -835,3 +827,3 @@@ pdf_nextobject(const char *ptr, size_t 
  	}
  	return NULL;
  }
- 
- #else	/*!HAVE_MMAP*/
- 
- #include "clamav.h"
- #include "others.h"
- #include "pdf.h"
- 
- int
- cli_pdf(const char *dir, int desc, cli_ctx *ctx, off_t offset)
- {
- 	cli_dbgmsg("File not decoded - PDF decoding needs mmap() (for now)\n");
- 	return CL_CLEAN;
- }
- #endif
diff --combined libclamav/pe.c
index 7aaa26b,870f3fd..d706ca8
--- a/libclamav/pe.c
+++ b/libclamav/pe.c
@@@ -59,6 -59,10 +59,6 @@@
  #include "special.h"
  #include "ishield.h"
  
 -#ifndef	O_BINARY
 -#define	O_BINARY	0
 -#endif
 -
  #define DCONF ctx->dconf->pe
  
  #define IMAGE_DOS_SIGNATURE	    0x5a4d	    /* MZ */
@@@ -286,7 -290,7 +286,7 @@@ static off_t cli_seeksect(int fd, struc
      return ret+1;
  }
  
- static unsigned int cli_md5sect(int fd, struct cli_exe_section *s, unsigned char *digest) {
+ static unsigned int cli_md5sect(fmap_t *map, struct cli_exe_section *s, unsigned char *digest) {
      void *hashme;
      cli_md5_ctx md5;
  
@@@ -295,28 -299,21 +295,21 @@@
  	return 0;
      }
  
-     if(!cli_seeksect(fd, s)) return 0;
- 
-     if(!(hashme=cli_malloc(s->rsz))) {
- 	cli_dbgmsg("cli_md5sect: out of memory\n");
- 	return 0;
-     }
- 
-     if(cli_readn(fd, hashme, s->rsz)!=s->rsz) {
+     if(!s->rsz) return 0;
+     if(!(hashme=fmap_need_off_once(map, s->raw, s->rsz))) {
  	cli_dbgmsg("cli_md5sect: unable to read section data\n");
  	return 0;
      }
  
      cli_md5_init(&md5);
      cli_md5_update(&md5, hashme, s->rsz);
-     free(hashme);
      cli_md5_final(digest, &md5);
      return 1;
  }
  
- static void cli_parseres_special(uint32_t base, uint32_t rva, int srcfd, struct cli_exe_section *exe_sections, uint16_t nsections, size_t fsize, uint32_t hdr_size, unsigned int level, uint32_t type, unsigned int *maxres, struct swizz_stats *stats) {
+ static void cli_parseres_special(uint32_t base, uint32_t rva, fmap_t *map, struct cli_exe_section *exe_sections, uint16_t nsections, size_t fsize, uint32_t hdr_size, unsigned int level, uint32_t type, unsigned int *maxres, struct swizz_stats *stats) {
      unsigned int err = 0, i;
-     uint8_t resdir[16];
+     uint8_t *resdir;
      uint8_t *entry, *oentry;
      uint16_t named, unnamed;
      uint32_t rawaddr = cli_rawaddr(rva, exe_sections, nsections, &err, fsize, hdr_size);
@@@ -324,7 -321,7 +317,7 @@@
  
      if(level>2 || !*maxres) return;
      *maxres-=1;
-     if(err || (pread(srcfd,resdir, sizeof(resdir), rawaddr) != sizeof(resdir)))
+     if(err || !(resdir = fmap_need_off_once(map, rawaddr, 16)))
  	    return;
      named = (uint16_t)cli_readint16(resdir+12);
      unnamed = (uint16_t)cli_readint16(resdir+14);
@@@ -332,18 -329,13 +325,13 @@@
      entries = /*named+*/unnamed;
      if (!entries)
  	    return;
-     oentry = entry = cli_malloc(entries*8);
      rawaddr += named*8; /* skip named */
      /* this is just used in a heuristic detection, so don't give error on failure */
-     if (!entry) {
- 	    cli_dbgmsg("cli_parseres_special: failed to allocate memory for resource directory:%lu\n", (unsigned long)entries);
- 	    return;
-     }
-     if (pread(srcfd, entry, entries*8, rawaddr+16) != entries*8) {
+     if(!(entry = fmap_need_off(map, rawaddr+16, entries*8))) {
  	    cli_dbgmsg("cli_parseres_special: failed to read resource directory at:%lu\n", (unsigned long)rawaddr+16);
- 	    free(oentry);
  	    return;
      }
+     oentry = entry;
      /*for (i=0; i<named; i++) {
  	uint32_t id, offs;
  	id = cli_readint32(entry);
@@@ -385,13 -377,13 +373,13 @@@
  	}
  	offs = cli_readint32(entry+4);
  	if(offs>>31)
- 		cli_parseres_special(base, base + (offs&0x7fffffff), srcfd, exe_sections, nsections, fsize, hdr_size, level+1, type, maxres, stats);
+ 		cli_parseres_special(base, base + (offs&0x7fffffff), map, exe_sections, nsections, fsize, hdr_size, level+1, type, maxres, stats);
  	else {
  			offs = cli_readint32(entry+4);
  			rawaddr = cli_rawaddr(base + offs, exe_sections, nsections, &err, fsize, hdr_size);
- 			if (!err && pread(srcfd, resdir, sizeof(resdir), rawaddr) == sizeof(resdir)) {
+ 			if (!err && (resdir = fmap_need_off_once(map, rawaddr, 16))) {
  				uint32_t isz = cli_readint32(resdir+4);
- 				char *str;
+ 				uint8_t *str;
  				rawaddr = cli_rawaddr(cli_readint32(resdir), exe_sections, nsections, &err, fsize, hdr_size);
  				if (err || !isz || isz >= fsize || rawaddr+isz >= fsize) {
  					cli_dbgmsg("cli_parseres_special: invalid resource table entry: %lu + %lu\n", 
@@@ -400,22 -392,15 +388,15 @@@
  					stats->errors++;
  					continue;
  				}
- 				str = cli_malloc(isz);
- 				if (!str) {
- 					cli_dbgmsg("cli_parseres_special: failed to allocate string mem: %lu\n", (unsigned long)isz);
- 					continue;
- 				}
- 				if(pread(srcfd, str, isz, rawaddr) == isz) {
+ 				if((str = fmap_need_off_once(map, rawaddr, isz)))
  					cli_detect_swizz_str(str, isz, stats, type);
  			}
  	}
      }
-     free (oentry);
+     fmap_unneed_ptr(map, oentry, entries*8);
  }
  
- int cli_scanpe(int desc, cli_ctx *ctx)
+ int cli_scanpe(cli_ctx *ctx)
  {
  	uint16_t e_magic; /* DOS signature ("MZ") */
  	uint16_t nsections;
@@@ -429,10 -414,9 +410,9 @@@
  	    struct pe_image_optional_hdr32 opt32;
  	} pe_opt;
  	struct pe_image_section_hdr *section_hdr;
- 	struct stat sb;
- 	char sname[9], buff[4096], epbuff[4096], *tempfile;
+ 	char sname[9], epbuff[4096], *tempfile;
  	uint32_t epsize;
- 	ssize_t bytes;
+ 	ssize_t bytes, at;
  	unsigned int i, found, upx_success = 0, min = 0, max = 0, err, overlays = 0;
  	unsigned int ssize = 0, dsize = 0, dll = 0, pe_plus = 0;
  	int (*upxfn)(char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t) = NULL;
@@@ -444,6 -428,7 +424,7 @@@
  	struct cli_matcher *md5_sect;
  	char timestr[32];
  	struct pe_image_data_dir *dirs;
+ 	fmap_t *map;
  
  
      if(!ctx) {
@@@ -451,7 -436,8 +432,8 @@@
  	return CL_ENULLARG;
      }
  
-     if(cli_readn(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
+     map = *ctx->fmap;
+     if(fmap_readn(map, &e_magic, 0, sizeof(e_magic)) != sizeof(e_magic)) {
  	cli_dbgmsg("Can't read DOS signature\n");
  	return CL_CLEAN;
      }
@@@ -461,15 -447,13 +443,13 @@@
  	return CL_CLEAN;
      }
  
-     lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
- 
-     if(cli_readn(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
+     if(fmap_readn(map, &e_lfanew, 58 + sizeof(e_magic), sizeof(e_lfanew)) != sizeof(e_lfanew)) {
  	cli_dbgmsg("Can't read new header address\n");
  	/* truncated header? */
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return CL_VIRUS;
  	}
  	return CL_CLEAN;
      }
@@@ -481,13 -465,7 +461,7 @@@
  	return CL_CLEAN;
      }
  
-     if(lseek(desc, e_lfanew, SEEK_SET) < 0) {
- 	/* probably not a PE file */
- 	cli_dbgmsg("Can't lseek to e_lfanew\n");
- 	return CL_CLEAN;
-     }
- 
-     if(cli_readn(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
+     if(fmap_readn(map, &file_hdr, e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
  	/* bad information in e_lfanew - probably not a PE file */
  	cli_dbgmsg("Can't read file header\n");
  	return CL_CLEAN;
@@@ -605,7 -583,7 +579,7 @@@
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return CL_VIRUS;
  	}
  	if(nsections)
  	    cli_warnmsg("PE file contains %d sections\n", nsections);
@@@ -625,20 -603,22 +599,22 @@@
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  	        *ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return CL_VIRUS;
  	}
  	return CL_CLEAN;
      }
  
-     if(cli_readn(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
+     at = e_lfanew + sizeof(struct pe_image_file_hdr);
+     if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
          cli_dbgmsg("Can't read optional file header\n");
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  	        *ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return CL_VIRUS;
  	}
  	return CL_CLEAN;
      }
+     at += sizeof(struct pe_image_optional_hdr32);
  
      /* This will be a chicken and egg problem until we drop 9x */
      if(EC16(optional_hdr64.Magic)==PE32P_SIGNATURE) {
@@@ -648,7 -628,7 +624,7 @@@
  	    if(DETECT_BROKEN) {
  	        if(ctx->virname)
  		    *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	    return CL_CLEAN;
  	}
@@@ -664,7 -644,7 +640,7 @@@
  	    if(DETECT_BROKEN) {
  	        if(ctx->virname)
  		    *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	    cli_dbgmsg("9x compatibility mode\n");
  	}
@@@ -673,7 -653,7 +649,7 @@@
      if(!pe_plus) { /* PE */
  	if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) {
  	    /* Seek to the end of the long header */
- 	    lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR);
+ 	    at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32);
  	}
  
  	if(DCONF & PE_CONF_UPACK)
@@@ -701,16 -681,16 +677,16 @@@
  
      } else { /* PE+ */
          /* read the remaining part of the header */
-         if(cli_readn(desc, &optional_hdr32 + 1, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
+         if(fmap_readn(map, &optional_hdr32 + 1, at, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
  	    cli_dbgmsg("Can't read optional file header\n");
  	    if(DETECT_BROKEN) {
  	        if(ctx->virname)
  		    *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	    return CL_CLEAN;
  	}
- 
+ 	at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
  	vep = EC32(optional_hdr64.AddressOfEntryPoint);
  	hdr_size = EC32(optional_hdr64.SizeOfHeaders);
  	cli_dbgmsg("File format: PE32+\n");
@@@ -787,22 -767,17 +763,17 @@@
          cli_dbgmsg("Bad virtual alignemnt\n");
          if(ctx->virname)
  	    *ctx->virname = "Broken.Executable";
 -	return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	return CL_VIRUS;
      }
  
      if (DETECT_BROKEN && !native && (!(pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment)) || (pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment))%0x200)) {
          cli_dbgmsg("Bad file alignemnt\n");
  	if(ctx->virname)
  	    *ctx->virname = "Broken.Executable";
 -	return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	return CL_VIRUS;
      }
  
-     if(fstat(desc, &sb) == -1) {
- 	cli_dbgmsg("fstat failed\n");
- 	return CL_ESTAT;
-     }
- 
-     fsize = sb.st_size;
+     fsize = map->len;
  
      section_hdr = (struct pe_image_section_hdr *) cli_calloc(nsections, sizeof(struct pe_image_section_hdr));
  
@@@ -822,7 -797,7 +793,7 @@@
      valign = (pe_plus)?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment);
      falign = (pe_plus)?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment);
  
-     if(cli_readn(desc, section_hdr, sizeof(struct pe_image_section_hdr)*nsections) != (int)(nsections*sizeof(struct pe_image_section_hdr))) {
+     if(fmap_readn(map, section_hdr, at, sizeof(struct pe_image_section_hdr)*nsections) != (int)(nsections*sizeof(struct pe_image_section_hdr))) {
          cli_dbgmsg("Can't read section header\n");
  	cli_dbgmsg("Possibly broken PE file\n");
  	free(section_hdr);
@@@ -830,11 -805,12 +801,12 @@@
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return CL_VIRUS;
  	}
  	return CL_CLEAN;
      }
-     
+     at += sizeof(struct pe_image_section_hdr)*nsections;
+ 
      for(i = 0; falign!=0x200 && i<nsections; i++) {
  	/* file alignment fallback mode - blah */
  	if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200)) {
@@@ -899,7 -875,7 +871,7 @@@
  	        *ctx->virname = "Broken.Executable";
  	    free(section_hdr);
  	    free(exe_sections);
 -	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return CL_VIRUS;
  	}
  
  	if (exe_sections[i].rsz) { /* Don't bother with virtual only sections */
@@@ -910,7 -886,7 +882,7 @@@
  		if(DETECT_BROKEN) {
  		    if(ctx->virname)
  		        *ctx->virname = "Broken.Executable";
 -		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		    return CL_VIRUS;
  		}
  		return CL_CLEAN; /* no ninjas to see here! move along! */
  	    }
@@@ -924,13 -900,11 +896,12 @@@
  		for(j = 0; j < md5_sect->soff_len && md5_sect->soff[j] <= exe_sections[i].rsz; j++) {
  		    if(md5_sect->soff[j] == exe_sections[i].rsz) {
  			unsigned char md5_dig[16];
 -			if(cli_md5sect(map, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, NULL, NULL) == CL_VIRUS) {
 -			    if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, NULL, NULL) != CL_VIRUS) {
 +			const struct cli_bm_patt *patt;
- 			if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, &patt, ctx->engine->md5_mdb, 0, -1, NULL) == CL_VIRUS && patt->filesize == exe_sections[i].rsz) {
- 			    if(cli_bm_scanbuff(md5_dig, 16, NULL, &patt, ctx->engine->md5_fp, 0, -1, NULL) != CL_VIRUS || patt->filesize != fsize) {
- 
++			if(cli_md5sect(map, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, &patt, ctx->engine->md5_mdb, 0, NULL, NULL) == CL_VIRUS && patt->filesize == exe_sections[i].rsz) {
++			    if(cli_bm_scanbuff(md5_dig, 16, NULL, &patt, ctx->engine->md5_fp, 0, NULL, NULL) != CL_VIRUS || patt->filesize != fsize) {
  				free(section_hdr);
  				free(exe_sections);
 -				return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +				return CL_VIRUS;
  			    }
  			}
  			break;
@@@ -946,7 -920,7 +917,7 @@@
  	    if(DETECT_BROKEN) {
  	        if(ctx->virname)
  		    *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	    return CL_CLEAN;
  	}
@@@ -958,7 -932,7 +929,7 @@@
  		    *ctx->virname = "Broken.Executable";
  		free(section_hdr);
  		free(exe_sections);
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	    min = exe_sections[i].rva;
  	    max = exe_sections[i].rva + exe_sections[i].rsz;
@@@ -969,7 -943,7 +940,7 @@@
  		    *ctx->virname = "Broken.Executable";
  		free(section_hdr);
  		free(exe_sections);
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	    if(exe_sections[i].rva < min)
  	        min = exe_sections[i].rva;
@@@ -989,7 -963,7 +960,7 @@@
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return CL_VIRUS;
  	}
  	return CL_CLEAN;
      }
@@@ -1001,13 -975,11 +972,11 @@@
  	return CL_CLEAN;
      }
  
-     lseek(desc, ep, SEEK_SET);
-     epsize = cli_readn(desc, epbuff, 4096);
+     epsize = fmap_readn(map, epbuff, ep, 4096);
  
      CLI_UNPTEMP("DISASM",(exe_sections,0));
-     disasmbuf((unsigned char*)epbuff, epsize, ndesc);
-     lseek(ndesc, 0, SEEK_SET);
-     ret = cli_scandesc(ndesc, ctx, CL_TYPE_PE_DISASM, 1, NULL, AC_SCAN_VIR);
+     if(disasmbuf((unsigned char*)epbuff, epsize, ndesc))
+ 	ret = cli_scandesc(ndesc, ctx, CL_TYPE_PE_DISASM, 1, NULL, AC_SCAN_VIR);
      close(ndesc);
      CLI_TMPUNLK();
      free(tempfile);
@@@ -1019,7 -991,7 +988,7 @@@
      if(overlays) {
  	int overlays_sz = fsize - overlays;
  	if(overlays_sz > 0) {
- 	    ret = cli_scanishield(desc, ctx, overlays, overlays_sz);
+ 	    ret = cli_scanishield(ctx, overlays, overlays_sz);
  	    if(ret != CL_CLEAN) {
  		free(exe_sections);
  		return ret;
@@@ -1037,7 -1009,7 +1006,7 @@@
  	    if((((uint32_t)cli_readint32(pt) ^ (uint32_t)cli_readint32(pt + 4)) == 0x505a4f) && (((uint32_t)cli_readint32(pt + 8) ^ (uint32_t)cli_readint32(pt + 12)) == 0xffffb) && (((uint32_t)cli_readint32(pt + 16) ^ (uint32_t)cli_readint32(pt + 20)) == 0xb8)) {
  	        *ctx->virname = "W32.Parite.B";
  		free(exe_sections);
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	}
      }
@@@ -1120,7 -1092,7 +1089,7 @@@
  		if (op==kzdsize+0x48 && *kzcode==0x75 && kzlen-(int8_t)kzcode[1]-3<=kzinitlen && kzlen-(int8_t)kzcode[1]>=kzxorlen) {
  		    *ctx->virname = "W32.Kriz";
  		    free(exe_sections);
 -		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		    return CL_VIRUS;
  		}
  		cli_dbgmsg("kriz: loop out of bounds, corrupted sample?\n");
  		kzstate++;
@@@ -1141,25 -1113,25 +1110,25 @@@
  
  	if(vsize >= 0x612c && rsize >= 0x612c && ((vsize & 0xff) == 0xec)) {
  		int bw = rsize < 0x7000 ? rsize : 0x7000;
+ 		char *tbuff;
  
- 	    lseek(desc, exe_sections[nsections - 1].raw + rsize - bw, SEEK_SET);
- 	    if(cli_readn(desc, buff, 4096) == 4096) {
- 		if(cli_memstr(buff, 4091, "\xe8\x2c\x61\x00\x00", 5)) {
+ 	    if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) {
+ 		if(cli_memstr(tbuff, 4091, "\xe8\x2c\x61\x00\x00", 5)) {
  		    *ctx->virname = dam ? "W32.Magistr.A.dam" : "W32.Magistr.A";
  		    free(exe_sections);
 -		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		    return CL_VIRUS;
  		} 
  	    }
  
  	} else if(rsize >= 0x7000 && vsize >= 0x7000 && ((vsize & 0xff) == 0xed)) {
  		int bw = rsize < 0x8000 ? rsize : 0x8000;
+ 		char *tbuff;
  
- 	    lseek(desc, exe_sections[nsections - 1].raw + rsize - bw, SEEK_SET);
- 	    if(cli_readn(desc, buff, 4096) == 4096) {
- 		if(cli_memstr(buff, 4091, "\xe8\x04\x72\x00\x00", 5)) {
+ 	    if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) {
+ 		if(cli_memstr(tbuff, 4091, "\xe8\x04\x72\x00\x00", 5)) {
  		    *ctx->virname = dam ? "W32.Magistr.B.dam" : "W32.Magistr.B";
  		    free(exe_sections);
 -		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		    return CL_VIRUS;
  		} 
  	    }
  	}
@@@ -1172,15 -1144,9 +1141,9 @@@
  	unsigned int xsjs = 0;
  
  	if(exe_sections[0].rsz > CLI_MAX_ALLOCATION) break;
- 	if(!cli_seeksect(desc, &exe_sections[0])) break;
- 	if(!(code=cli_malloc(exe_sections[0].rsz))) {
- 	    free(exe_sections);
- 	    return CL_EMEM;
- 	}
- 	if(cli_readn(desc, code, exe_sections[0].rsz)!=exe_sections[0].rsz) {
- 	    free(exe_sections);
- 	    return CL_EREAD;
- 	}
+ 
+ 	if(!exe_sections[0].rsz) break;
+ 	if(!(code=fmap_need_off_once(map, exe_sections[0].raw, exe_sections[0].rsz))) break;
  	for(i=0; i<exe_sections[0].rsz - 5; i++) {
  	    if((uint8_t)(code[i]-0xe8) > 1) continue;
  	    jump = cli_rawaddr(exe_sections[0].rva+i+5+cli_readint32(&code[i+1]), exe_sections, nsections, &err, fsize, hdr_size);
@@@ -1188,7 -1154,6 +1151,6 @@@
  	    if(xsjs % 128 == 0) {
  		if(xsjs == 1280) break;
  		if(!(jumps=(uint32_t *)cli_realloc2(jumps, (xsjs+128)*sizeof(uint32_t)))) {
- 		    free(code);
  		    free(exe_sections);
  		    return CL_EMEM;
  		}
@@@ -1207,17 -1172,15 +1169,15 @@@
  	    jumps[j]=jump;
  	    xsjs++;
  	}
  	if(!xsjs) break;
  	cli_dbgmsg("Polipos: Checking %d xsect jump(s)\n", xsjs);
  	for(i=0;i<xsjs;i++) {
- 	    lseek(desc, jumps[i], SEEK_SET);
- 	    if(cli_readn(desc, buff, 9) != 9) continue;
- 	    if((jump=cli_readint32(buff))==0x60ec8b55 || (buff[4]=='\xec' && ((jump==0x83ec8b55 && buff[6]=='\x60') || (jump==0x81ec8b55 && !buff[7] && !buff[8])))) {
+ 	    if(!(code = fmap_need_off_once(map, jumps[i], 9))) continue;
+ 	    if((jump=cli_readint32(code))==0x60ec8b55 || (code[4]==0x0ec && ((jump==0x83ec8b55 && code[6]==0x60) || (jump==0x81ec8b55 && !code[7] && !code[8])))) {
  		*ctx->virname = "W32.Polipos.A";
  		free(jumps);
  		free(exe_sections);
 -		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return CL_VIRUS;
  	    }
  	}
  	free(jumps);
@@@ -1234,7 -1197,7 +1194,7 @@@
  		    if (!stats)
  			    ret = CL_EMEM;
  		    else {
- 			    cli_parseres_special(EC32(dirs[2].VirtualAddress), EC32(dirs[2].VirtualAddress), desc, exe_sections, nsections, fsize, hdr_size, 0, 0, &m, stats);
+ 			    cli_parseres_special(EC32(dirs[2].VirtualAddress), EC32(dirs[2].VirtualAddress), map, exe_sections, nsections, fsize, hdr_size, 0, 0, &m, stats);
  			    if ((ret = cli_detect_swizz(stats)) == CL_VIRUS) {
  				    *ctx->virname = "Trojan.Swizzor.Gen";
  			    }
@@@ -1242,8 -1205,8 +1202,6 @@@
  		    }
  		    if (ret != CL_CLEAN) {
  			    free(exe_sections);
--			    if(ret == CL_VIRUS)
- 				return CL_VIRUS;
 -				return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  			    return ret;
  		    }
  	    }
@@@ -1266,6 -1229,7 +1224,7 @@@
      /* MEW support */
      if (found && (DCONF & PE_CONF_MEW) && epsize>=16 && epbuff[0]=='\xe9') {
  	uint32_t fileoffset;
+ 	char *tbuff;
  
  	fileoffset = (vep + cli_readint32(epbuff + 1) + 5);
  	while (fileoffset == 0x154 || fileoffset == 0x158) {
@@@ -1274,29 -1238,20 +1233,20 @@@
  	    cli_dbgmsg ("MEW: found MEW characteristics %08X + %08X + 5 = %08X\n", 
  			cli_readint32(epbuff + 1), vep, cli_readint32(epbuff + 1) + vep + 5);
  
- 	    if(lseek(desc, fileoffset, SEEK_SET) == -1) {
- 	        cli_dbgmsg("MEW: lseek() failed\n");
- 		free(exe_sections);
- 		return CL_ESEEK;
- 	    }
- 
- 	    if((bytes = read(desc, buff, 0xb0)) != 0xb0) {
- 	        cli_dbgmsg("MEW: Can't read 0xb0 bytes at 0x%x (%d) %lu\n", fileoffset, fileoffset, (unsigned long)bytes);
+ 	    if(!(tbuff = fmap_need_off_once(map, fileoffset, 0xb0)))
  		break;
  	    if (fileoffset == 0x154) cli_dbgmsg("MEW: Win9x compatibility was set!\n");
  	    else cli_dbgmsg("MEW: Win9x compatibility was NOT set!\n");
  
- 	    if((offdiff = cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4) {
+ 	    if((offdiff = cli_readint32(tbuff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4) {
  	        cli_dbgmsg("MEW: ESI is not in proper section\n");
  		break;
  	    }
  	    offdiff -= exe_sections[i + 1].rva;
  
- 	    if(!cli_seeksect(desc, &exe_sections[i + 1])) {
- 		free(exe_sections);
- 		return CL_ESEEK;
+ 	    if(!exe_sections[i + 1].rsz) {
+ 		cli_dbgmsg("MEW: mew section is empty\n");
+ 		break;
  	    }
  	    ssize = exe_sections[i + 1].vsz;
  	    dsize = exe_sections[i].vsz;
@@@ -1306,20 -1261,19 +1256,19 @@@
  	    CLI_UNPSIZELIMITS("MEW", MAX(ssize, dsize));
  	    CLI_UNPSIZELIMITS("MEW", MAX(ssize + dsize, exe_sections[i + 1].rsz));
  
+ 	    if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize) {
+ 	        cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz);
+ 		break;
+ 	    }
+ 
  	    /* allocate needed buffer */
  	    if (!(src = cli_calloc (ssize + dsize, sizeof(char)))) {
  	        free(exe_sections);
  		return CL_EMEM;
  	    }
  
- 	    if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize) {
- 	        cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz);
- 		free(src);
- 		break;
- 	    }
- 
- 	    if((bytes = read(desc, src + dsize, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) {
- 	      cli_dbgmsg("MEW: Can't read %d bytes [read: %lu]\n", exe_sections[i + 1].rsz, (unsigned long)bytes);
+ 	    if((bytes = fmap_readn(map, src + dsize, exe_sections[i + 1].raw, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) {
+ 		cli_dbgmsg("MEW: Can't read %d bytes [read: %lu]\n", exe_sections[i + 1].rsz, (unsigned long)bytes);
  		free(exe_sections);
  		free(src);
  		return CL_EREAD;
@@@ -1327,13 -1281,13 +1276,13 @@@
  	    cli_dbgmsg("MEW: %u (%08x) bytes read\n", (unsigned int)bytes, (unsigned int)bytes);
  
  	    /* count offset to lzma proc, if lzma used, 0xe8 -> call */
- 	    if (buff[0x7b] == '\xe8') {
- 	        if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(buff + 0x7c) + fileoffset + 0x80, 4)) {
+ 	    if (tbuff[0x7b] == '\xe8') {
+ 	        if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(tbuff + 0x7c) + fileoffset + 0x80, 4)) {
  		    cli_dbgmsg("MEW: lzma proc out of bounds!\n");
  		    free(src);
  		    break; /* to next unpacker in chain */
  		}
- 		uselzma = cli_readint32(buff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80);
+ 		uselzma = cli_readint32(tbuff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80);
  	    } else {
  	        uselzma = 0;
  	    }
@@@ -1430,8 -1384,7 +1379,7 @@@
  		return CL_EMEM;
  	    }
  
- 	    lseek(desc, 0, SEEK_SET);
- 	    if(read(desc, dest, ssize) != ssize) {
+ 	    if(fmap_readn(map, dest, 0, ssize) != ssize) {
  	        cli_dbgmsg("Upack: Can't read raw data of section 0\n");
  		free(dest);
  		break;
@@@ -1439,9 -1392,7 +1387,7 @@@
  
  	    if(upack) memmove(dest + exe_sections[2].rva - exe_sections[0].rva, dest, ssize);
  
- 	    lseek(desc, exe_sections[1].uraw, SEEK_SET);
- 
- 	    if(read(desc, dest + exe_sections[1].rva - off, exe_sections[1].ursz) != exe_sections[1].ursz) {
+ 	    if(fmap_readn(map, dest + exe_sections[1].rva - off, exe_sections[1].uraw, exe_sections[1].ursz) != exe_sections[1].ursz) {
  		cli_dbgmsg("Upack: Can't read raw data of section 1\n");
  		free(dest);
  		break;
@@@ -1477,36 -1428,27 +1423,27 @@@
  	    break;
  	}
  	
- 	if((src = (char *) cli_malloc(ssize)) == NULL) {
- 	    free(exe_sections);
- 	    return CL_EMEM;
- 	}
- 
- 	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
+ 	if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
  	    cli_dbgmsg("Can't read raw data of section %d\n", i + 1);
  	    free(exe_sections);
- 	    free(src);
  	    return CL_ESEEK;
  	}
  
  	dest = src + newedx - exe_sections[i + 1].rva;
  	if(newedx < exe_sections[i + 1].rva || !CLI_ISCONTAINED(src, ssize, dest, 4)) {
  	    cli_dbgmsg("FSG: New ESP out of bounds\n");
- 	    free(src);
  	    break;
  	}
  
  	newedx = cli_readint32(dest) - EC32(optional_hdr32.ImageBase);
  	if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) {
  	    cli_dbgmsg("FSG: New ESP (%x) is wrong\n", newedx);
- 	    free(src);
  	    break;
  	}
   
  	dest = src + newedx - exe_sections[i + 1].rva;
  	if(!CLI_ISCONTAINED(src, ssize, dest, 32)) {
  	    cli_dbgmsg("FSG: New stack out of bounds\n");
- 	    free(src);
  	    break;
  	}
  
@@@ -1517,19 -1459,16 +1454,16 @@@
  
  	if(newedi != exe_sections[i].rva) {
  	    cli_dbgmsg("FSG: Bad destination buffer (edi is %x should be %x)\n", newedi, exe_sections[i].rva);
- 	    free(src);
  	    break;
  	}
  
  	if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
  	    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
- 	    free(src);
  	    break;
  	}
  
  	if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newebx, 16)) {
  	    cli_dbgmsg("FSG: Array of functions out of bounds\n");
- 	    free(src);
  	    break;
  	}
  
@@@ -1542,8 -1481,8 +1476,8 @@@
  	    return CL_EMEM;
  	}
  
- 	CLI_UNPTEMP("FSG",(src,dest,exe_sections,0));
- 	CLI_UNPRESULTSFSG2("FSG",(unfsg_200(newesi - exe_sections[i + 1].rva + src, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)),1,(src,dest,0));
+ 	CLI_UNPTEMP("FSG",(dest,exe_sections,0));
+ 	CLI_UNPRESULTSFSG2("FSG",(unfsg_200(newesi - exe_sections[i + 1].rva + src, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)),1,(dest,0));
  	break;
      }
  
@@@ -1568,25 -1507,18 +1502,18 @@@
  	    return CL_CLEAN;
  	}
  
- 	if(!(gp = cli_rawaddr(cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size)) && err ) {
+ 	if(!(t = cli_rawaddr(cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size)) && err ) {
  	    cli_dbgmsg("FSG: Support data out of padding area\n");
  	    break;
  	}
  
- 	lseek(desc, gp, SEEK_SET);
- 	gp = exe_sections[i + 1].raw - gp;
+ 	gp = exe_sections[i + 1].raw - t;
  
- 	CLI_UNPSIZELIMITS("FSG", gp)
- 
- 	if((support = (char *) cli_malloc(gp)) == NULL) {
- 	    free(exe_sections);
- 	    return CL_EMEM;
- 	}
+ 	CLI_UNPSIZELIMITS("FSG", gp);
  
- 	if((int)cli_readn(desc, support, gp) != (int)gp) {
+ 	if(!(support = fmap_need_off_once(map, t, gp))) {
  	    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
  	    free(exe_sections);
- 	    free(support);
  	    return CL_EREAD;
  	}
  
@@@ -1596,13 -1528,11 +1523,11 @@@
  
  	if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
  	    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
- 	    free(support);
  	    break;
  	}
  
  	if(newedi != exe_sections[i].rva) {
  	    cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva);
- 	    free(support);
  	    break;
  	}
  
@@@ -1625,13 -1555,11 +1550,11 @@@
  	}
  
  	if(t >= gp - 4 || cli_readint32(support + t)) {
- 	    free(support);
  	    break;
  	}
  
  	if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) {
  	    free(exe_sections);
- 	    free(support);
  	    return CL_EMEM;
  	}
  
@@@ -1639,25 -1567,15 +1562,15 @@@
  	for(t = 1; t <= (uint32_t)sectcnt; t++)
  	    sections[t].rva = cli_readint32(support + 8 + t * 4) - 1 - EC32(optional_hdr32.ImageBase);
  
- 	free(support);
- 
- 	if((src = (char *) cli_malloc(ssize)) == NULL) {
- 	    free(exe_sections);
- 	    free(sections);
- 	    return CL_EMEM;
- 	}
- 
- 	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
+ 	if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
  	    cli_dbgmsg("Can't read raw data of section %d\n", i);
  	    free(exe_sections);
  	    free(sections);
- 	    free(src);
  	    return CL_EREAD;
  	}
  
  	if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
  	    free(exe_sections);
- 	    free(src);
  	    free(sections);
  	    return CL_EMEM;
  	}
@@@ -1665,8 -1583,8 +1578,8 @@@
  	oldep = vep + 161 + 6 + cli_readint32(epbuff+163);
  	cli_dbgmsg("FSG: found old EP @%x\n", oldep);
  
- 	CLI_UNPTEMP("FSG",(src,dest,sections,exe_sections,0));
- 	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(src,dest,sections,0));
+ 	CLI_UNPTEMP("FSG",(dest,sections,exe_sections,0));
+ 	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(dest,sections,0));
  	break; /* were done with 1.33 */
      }
  
@@@ -1676,8 -1594,7 +1589,7 @@@
  	/* FSG support - v. 1.31 */
  
  	int sectcnt = 0;
- 	uint32_t t;
- 	uint32_t gp = cli_rawaddr(cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size);
+ 	uint32_t gp, t = cli_rawaddr(cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size);
  	char *support;
  	uint32_t newesi = cli_readint32(epbuff+11) - EC32(optional_hdr32.ImageBase);
  	uint32_t newedi = cli_readint32(epbuff+6) - EC32(optional_hdr32.ImageBase);
@@@ -1687,7 -1604,6 +1599,6 @@@
  	ssize = exe_sections[i + 1].rsz;
  	dsize = exe_sections[i].vsz;
  
- 
  	if(err) {
  	    cli_dbgmsg("FSG: Support data out of padding area\n");
  	    break;
@@@ -1711,20 -1627,13 +1622,13 @@@
  	    return CL_CLEAN;
  	}
  
- 	lseek(desc, gp, SEEK_SET);
- 	gp = exe_sections[i + 1].raw - gp;
+ 	gp = exe_sections[i + 1].raw - t;
  
  	CLI_UNPSIZELIMITS("FSG", gp)
  
- 	if((support = (char *) cli_malloc(gp)) == NULL) {
- 	    free(exe_sections);
- 	    return CL_EMEM;
- 	}
- 
- 	if(cli_readn(desc, support, gp) != (int)gp) {
+ 	if(!(support = fmap_need_off_once(map, t, gp))) {
  	    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
  	    free(exe_sections);
- 	    free(support);
  	    return CL_EREAD;
  	}
  
@@@ -1745,13 -1654,11 +1649,11 @@@
  	}
  
  	if(t >= gp-10 || cli_readint32(support + t + 6) != 2) {
- 	    free(support);
  	    break;
  	}
  
  	if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) {
  	    free(exe_sections);
- 	    free(support);
  	    return CL_EMEM;
  	}
  
@@@ -1760,25 -1667,15 +1662,15 @@@
  	    sections[t+1].rva = (((support[t*2]|(support[t*2+1]<<8))-2)<<12)-EC32(optional_hdr32.ImageBase);
  	}
  
- 	free(support);
- 
- 	if((src = (char *) cli_malloc(ssize)) == NULL) {
- 	    free(exe_sections);
- 	    free(sections);
- 	    return CL_EMEM;
- 	}
- 
- 	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
+ 	if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
  	    cli_dbgmsg("FSG: Can't read raw data of section %d\n", i);
  	    free(exe_sections);
  	    free(sections);
- 	    free(src);
  	    return CL_EREAD;
  	}
  
  	if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
  	    free(exe_sections);
- 	    free(src);
  	    free(sections);
  	    return CL_EMEM;
  	}
@@@ -1787,8 -1684,8 +1679,8 @@@
  	oldep = vep + gp + 6 + cli_readint32(src+gp+2+oldep);
  	cli_dbgmsg("FSG: found old EP @%x\n", oldep);
  
- 	CLI_UNPTEMP("FSG",(src,dest,sections,exe_sections,0));
- 	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(src,dest,sections,0));
+ 	CLI_UNPTEMP("FSG",(dest,sections,exe_sections,0));
+ 	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(dest,sections,0));
  	break; /* were done with 1.31 */
      }
  
@@@ -1809,25 -1706,17 +1701,17 @@@
  	    return CL_CLEAN;
  	}
  
- 	if((src = (char *) cli_malloc(ssize)) == NULL) {
+ 	if(!exe_sections[i + 1].raw || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
+ 	    cli_dbgmsg("UPX: Can't read raw data of section %d\n", i+1);
  	    free(exe_sections);
- 	    return CL_EMEM;
+ 	    return CL_EREAD;
  	}
  
  	if((dest = (char *) cli_calloc(dsize + 8192, sizeof(char))) == NULL) {
  	    free(exe_sections);
  	    return CL_EMEM;
  	}
  
- 	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
- 	    cli_dbgmsg("UPX: Can't read raw data of section %d\n", i+1);
- 	    free(exe_sections);
- 	    free(src);
- 	    free(dest);
- 	    return CL_EREAD;
- 	}
- 
  	/* try to detect UPX code */
  	if(cli_memstr(UPX_NRV2B, 24, epbuff + 0x69, 13) || cli_memstr(UPX_NRV2B, 24, epbuff + 0x69 + 8, 13)) {
  	    cli_dbgmsg("UPX: Looks like a NRV2B decompression routine\n");
@@@ -1901,13 -1790,11 +1785,11 @@@
  
  	if(!upx_success) {
  	    cli_dbgmsg("UPX: All decompressors failed\n");
- 	    free(src);
  	    free(dest);
  	}
      }
  
      if(upx_success) {
- 	free(src);
  	free(exe_sections);
  
  	CLI_UNPTEMP("UPX/FSG",(dest,0));
@@@ -1975,7 -1862,7 +1857,7 @@@
  
  	    for(i = 0 ; i < nsections; i++) {
  		if(exe_sections[i].raw) {
- 		    if(!cli_seeksect(desc, &exe_sections[i]) || (unsigned int) cli_readn(desc, dest + exe_sections[i].rva - min, exe_sections[i].ursz) != exe_sections[i].ursz) {
+ 		    if(!exe_sections[i].rsz || fmap_readn(map, dest + exe_sections[i].rva - min, exe_sections[i].raw, exe_sections[i].ursz) != exe_sections[i].ursz) {
  			free(exe_sections);
  			free(dest);
  			return CL_CLEAN;
@@@ -2004,8 -1891,7 +1886,7 @@@
  	    return CL_EMEM;
  	}
  
- 	lseek(desc, 0, SEEK_SET);
- 	if((size_t) cli_readn(desc, spinned, fsize) != fsize) {
+ 	if((size_t) fmap_readn(map, spinned, 0, fsize) != fsize) {
  	    cli_dbgmsg("PESpin: Can't read %lu bytes\n", (unsigned long)fsize);
  	    free(spinned);
  	    free(exe_sections);
@@@ -2069,8 -1955,7 +1950,7 @@@
  	    return CL_EMEM;
  	}
  
- 	lseek(desc, 0, SEEK_SET);
- 	if((size_t) cli_readn(desc, spinned, fsize) != fsize) {
+ 	if((size_t) fmap_readn(map, spinned, 0, fsize) != fsize) {
  	    cli_dbgmsg("yC: Can't read %lu bytes\n", (unsigned long)fsize);
  	    free(spinned);
  	    free(exe_sections);
@@@ -2107,8 -1992,7 +1987,7 @@@
  	    free(exe_sections);
  	    return CL_EMEM;
  	}
- 	lseek(desc, 0, SEEK_SET);
- 	if((size_t) cli_readn(desc, src, head) != head) {
+ 	if((size_t) fmap_readn(map, src, 0, head) != head) {
  	    cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", head);
  	    free(src);
  	    free(exe_sections);
@@@ -2116,9 -2000,8 +1995,8 @@@
  	}
          for(i = 0 ; i < (unsigned int)nsections-1; i++) {
  	    if(!exe_sections[i].rsz) continue;
- 	    if(!cli_seeksect(desc, &exe_sections[i])) break;
              if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break;
-             if(cli_readn(desc, src+exe_sections[i].rva, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
+             if(fmap_readn(map, src+exe_sections[i].rva, exe_sections[i].raw, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
          }
          if(i+1!=nsections) {
              cli_dbgmsg("WWpack: Probably hacked/damaged file.\n");
@@@ -2130,7 -2013,7 +2008,7 @@@
  	    free(exe_sections);
  	    return CL_EMEM;
  	}
- 	if(!cli_seeksect(desc, &exe_sections[nsections - 1]) || (size_t) cli_readn(desc, packer, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) {
+ 	if(!exe_sections[nsections - 1].rsz || (size_t) fmap_readn(map, packer, exe_sections[nsections - 1].raw, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) {
  	    cli_dbgmsg("WWPack: Can't read %d bytes from wwpack sect\n", exe_sections[nsections - 1].rsz);
  	    free(src);
  	    free(packer);
@@@ -2162,9 -2045,8 +2040,8 @@@
  	}
          for(i = 0 ; i < (unsigned int)nsections; i++) {
  	    if(!exe_sections[i].rsz) continue;
- 	    if(!cli_seeksect(desc, &exe_sections[i])) break;
              if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break;
-             if(cli_readn(desc, src+exe_sections[i].rva, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
+             if(fmap_readn(map, src+exe_sections[i].rva, exe_sections[i].raw, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
          }
          if(i!=nsections) {
              cli_dbgmsg("Aspack: Probably hacked/damaged Aspack file.\n");
@@@ -2183,14 -2065,13 +2060,13 @@@
  	uint32_t eprva = vep;
  	uint32_t start_of_stuff, ssize, dsize, rep = ep;
  	unsigned int nowinldr;
- 	char nbuff[24];
+ 	char *nbuff;
  	char *src=epbuff, *dest;
  
  	if (*epbuff=='\xe9') { /* bitched headers */
  	    eprva = cli_readint32(epbuff+1)+vep+5;
  	    if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) break;
- 	    if (lseek(desc, rep, SEEK_SET)==-1) break;
- 	    if (cli_readn(desc, nbuff, 24)!=24) break;
+ 	    if (!(nbuff = fmap_need_off_once(map, rep, 24))) break;
  	    src = nbuff;
  	}
  
@@@ -2199,11 -2080,9 +2075,9 @@@
  	nowinldr = 0x54-cli_readint32(src+17);
  	cli_dbgmsg("NsPack: Found *start_of_stuff @delta-%x\n", nowinldr);
  
- 	if (lseek(desc, rep-nowinldr, SEEK_SET)==-1) break;
- 	if (cli_readn(desc, nbuff, 4)!=4) break;
+ 	if(!(nbuff = fmap_need_off_once(map, rep-nowinldr, 4))) break;
  	start_of_stuff=rep+cli_readint32(nbuff);
- 	if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break;
- 	if (cli_readn(desc, nbuff, 20)!=20) break;
+ 	if(!(nbuff = fmap_need_off_once(map, start_of_stuff, 20))) break;
  	src = nbuff;
  	if (!cli_readint32(nbuff)) {
  	    start_of_stuff+=4; /* FIXME: more to do */
@@@ -2215,39 -2094,31 +2089,31 @@@
  
  	CLI_UNPSIZELIMITS("NsPack", MAX(ssize,dsize));
  
- 	if ( !ssize || !dsize || dsize != exe_sections[0].vsz) break;
- 	if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break;
+ 	if (!ssize || !dsize || dsize != exe_sections[0].vsz) break;
  	if (!(dest=cli_malloc(dsize))) break;
  	/* memset(dest, 0xfc, dsize); */
  
- 	if (!(src=cli_malloc(ssize))) {
+ 	if(!(src = fmap_need_off(map, start_of_stuff, ssize))) {
  	    free(dest);
  	    break;
  	}
  	/* memset(src, 0x00, ssize); */
- 	cli_readn(desc, src, ssize);
  
  	eprva+=0x27a;
  	if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) {
  	  free(dest);
- 	  free(src);
  	  break;
  	}
- 	if (lseek(desc, rep, SEEK_SET)==-1) {
+ 	if(!(nbuff = fmap_need_off_once(map, rep, 5))) {
  	  free(dest);
- 	  free(src);
- 	  break;
- 	}
- 	if (cli_readn(desc, nbuff, 5)!=5) {
- 	  free(dest);
- 	  free(src);
  	  break;
  	}
+ 	fmap_unneed_off(map, start_of_stuff, ssize);
  	eprva=eprva+5+cli_readint32(nbuff+1);
  	cli_dbgmsg("NsPack: OEP = %08x\n", eprva);
  
- 	CLI_UNPTEMP("NsPack",(src,dest,exe_sections,0));
- 	CLI_UNPRESULTS("NsPack",(unspack(src, dest, ctx, exe_sections[0].rva, EC32(optional_hdr32.ImageBase), eprva, ndesc)),0,(src,dest,0));
+ 	CLI_UNPTEMP("NsPack",(dest,exe_sections,0));
+ 	CLI_UNPRESULTS("NsPack",(unspack(src, dest, ctx, exe_sections[0].rva, EC32(optional_hdr32.ImageBase), eprva, ndesc)),0,(dest,0));
  	break;
      }
  
@@@ -2257,7 -2128,7 +2123,7 @@@
      return CL_CLEAN;
  }
  
- int cli_peheader(int desc, struct cli_exe_info *peinfo)
+ int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo)
  {
  	uint16_t e_magic; /* DOS signature ("MZ") */
  	uint32_t e_lfanew; /* address of new exe header */
@@@ -2270,24 -2141,18 +2136,18 @@@
  	    struct pe_image_optional_hdr32 opt32;
  	} pe_opt;
  	struct pe_image_section_hdr *section_hdr;
- 	struct stat sb;
  	int i;
  	unsigned int err, pe_plus = 0;
  	uint32_t valign, falign, hdr_size;
  	size_t fsize;
+ 	ssize_t at;
  
      cli_dbgmsg("in cli_peheader\n");
  
-     if(fstat(desc, &sb) == -1) {
- 	cli_dbgmsg("fstat failed\n");
- 	return -1;
-     }
- 
-     fsize = sb.st_size - peinfo->offset;
- 
-     if(cli_readn(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
+     fsize = map->len - peinfo->offset;
+     if(fmap_readn(map, &e_magic, peinfo->offset, sizeof(e_magic)) != sizeof(e_magic)) {
  	cli_dbgmsg("Can't read DOS signature\n");
- 	return -1;
+ 	return CL_CLEAN;
      }
  
      if(EC16(e_magic) != IMAGE_DOS_SIGNATURE && EC16(e_magic) != IMAGE_DOS_SIGNATURE_OLD) {
@@@ -2295,10 -2160,7 +2155,7 @@@
  	return -1;
      }
  
-     lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
- 
-     if(cli_readn(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
- 	cli_dbgmsg("Can't read new header address\n");
+     if(fmap_readn(map, &e_lfanew, peinfo->offset + 58 + sizeof(e_magic), sizeof(e_lfanew)) != sizeof(e_lfanew)) {
  	/* truncated header? */
  	return -1;
      }
@@@ -2309,13 -2171,7 +2166,7 @@@
  	return -1;
      }
  
-     if(lseek(desc, peinfo->offset + e_lfanew, SEEK_SET) < 0) {
- 	/* probably not a PE file */
- 	cli_dbgmsg("Can't lseek to e_lfanew\n");
- 	return -1;
-     }
- 
-     if(cli_readn(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
+     if(fmap_readn(map, &file_hdr, peinfo->offset + e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
  	/* bad information in e_lfanew - probably not a PE file */
  	cli_dbgmsg("Can't read file header\n");
  	return -1;
@@@ -2333,26 -2189,29 +2184,29 @@@
  	return -1;
      }
  
-     if(cli_readn(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
+     at = peinfo->offset + e_lfanew + sizeof(struct pe_image_file_hdr);
+     if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
          cli_dbgmsg("Can't read optional file header\n");
  	return -1;
      }
+     at += sizeof(struct pe_image_optional_hdr32);
  
      if(EC16(optional_hdr64.Magic)==PE32P_SIGNATURE) { /* PE+ */
          if(EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr64)) {
  	    cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n");
  	    return -1;
  	}
-         if(cli_readn(desc, &optional_hdr32 + 1, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
+ 	if(fmap_readn(map, &optional_hdr32 + 1, at, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
  	    cli_dbgmsg("Can't read optional file header\n");
  	    return -1;
  	}
+ 	at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
  	hdr_size = EC32(optional_hdr64.SizeOfHeaders);
  	pe_plus=1;
      } else { /* PE */
  	if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) {
  	    /* Seek to the end of the long header */
- 	    lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR);
+ 	    at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32);
  	}
  	hdr_size = EC32(optional_hdr32.SizeOfHeaders);
      }
@@@ -2378,7 -2237,7 +2232,7 @@@
  	return -1;
      }
  
-     if(cli_readn(desc, section_hdr, peinfo->nsections * sizeof(struct pe_image_section_hdr)) != peinfo->nsections * sizeof(struct pe_image_section_hdr)) {
+     if(fmap_readn(map, section_hdr, at, peinfo->nsections * sizeof(struct pe_image_section_hdr)) != peinfo->nsections * sizeof(struct pe_image_section_hdr)) {
          cli_dbgmsg("Can't read section header\n");
  	cli_dbgmsg("Possibly broken PE file\n");
  	free(section_hdr);
@@@ -2386,6 -2245,7 +2240,7 @@@
  	peinfo->section = NULL;
  	return -1;
      }
+     at += sizeof(struct pe_image_section_hdr)*peinfo->nsections;
  
      for(i = 0; falign!=0x200 && i<peinfo->nsections; i++) {
  	/* file alignment fallback mode - blah */
diff --combined libclamav/phishcheck.c
index 0b5bc80,5bb0ddb..74bda9d
--- a/libclamav/phishcheck.c
+++ b/libclamav/phishcheck.c
@@@ -322,6 -322,9 +322,6 @@@ static int build_regex(regex_t* preg,co
  	rc = cli_regcomp(preg,regex,REG_EXTENDED|REG_ICASE|(nosub ? REG_NOSUB :0));
  	if(rc) {
  
 -#ifdef	C_WINDOWS
 -		cli_errmsg("Phishcheck: Error in compiling regex, disabling phishing checks\n");
 -#else
  		size_t buflen =	cli_regerror(rc,preg,NULL,0);
  		char *errbuf = cli_malloc(buflen);
  
@@@ -331,6 -334,7 +331,6 @@@
  			free(errbuf);
  		} else
  			cli_errmsg("Phishcheck: Error in compiling regex, disabling phishing checks. Additionally an Out-of-memory error was encountered while generating a detailed error message\n");
 -#endif
  		return 1;
  	}
  	return CL_SUCCESS;
@@@ -1194,13 -1198,13 +1194,13 @@@ static int hash_match(const struct rege
  	    h[64]='\0';
  	    cli_dbgmsg("Looking up hash %s for %s(%u)%s(%u)\n", h, host, (unsigned)hlen, path, (unsigned)plen);
  	    if (prefix_matched) {
- 		if (cli_bm_scanbuff(sha256_dig, 4, &virname, NULL, &rlist->hostkey_prefix,0,-1,NULL) == CL_VIRUS) {
 -		if (cli_bm_scanbuff(sha256_dig, 4, &virname, &rlist->hostkey_prefix,0,NULL,NULL) == CL_VIRUS) {
++		if (cli_bm_scanbuff(sha256_dig, 4, &virname, NULL, &rlist->hostkey_prefix,0,NULL,NULL) == CL_VIRUS) {
  		    cli_dbgmsg("prefix matched\n");
  		    *prefix_matched = 1;
  		} else
  		    return CL_SUCCESS;
  	    }
- 	    if (cli_bm_scanbuff(sha256_dig, 32, &virname, NULL, &rlist->sha256_hashes,0,-1,NULL) == CL_VIRUS) {
 -	    if (cli_bm_scanbuff(sha256_dig, 32, &virname, &rlist->sha256_hashes,0,NULL,NULL) == CL_VIRUS) {
++	    if (cli_bm_scanbuff(sha256_dig, 32, &virname, NULL, &rlist->sha256_hashes,0,NULL,NULL) == CL_VIRUS) {
  		cli_dbgmsg("This hash matched: %s\n", h);
  		switch(*virname) {
  		    case 'W':
diff --combined libclamav/regex_list.c
index a90cc89,df19a53..6771ece
--- a/libclamav/regex_list.c
+++ b/libclamav/regex_list.c
@@@ -455,7 -455,7 +455,7 @@@ static int add_hash(struct regex_matche
  
  	if (fl != 'W' && pat->length == 32 &&
  	    cli_hashset_contains(&matcher->sha256_pfx_set, cli_readint32(pat->pattern)) &&
- 	    cli_bm_scanbuff(pat->pattern, 32, &vname, NULL, &matcher->sha256_hashes,0,-1,NULL) == CL_VIRUS) {
 -	    cli_bm_scanbuff(pat->pattern, 32, &vname, &matcher->sha256_hashes,0,NULL,NULL) == CL_VIRUS) {
++	    cli_bm_scanbuff(pat->pattern, 32, &vname, NULL, &matcher->sha256_hashes,0,NULL,NULL) == CL_VIRUS) {
  	    if (*vname == 'W') {
  		/* hash is whitelisted in local.gdb */
  		cli_dbgmsg("Skipping hash %s\n", pattern);
diff --combined libclamav/scanners.c
index 50ba696,e2b44dd..e8d890b
--- a/libclamav/scanners.c
+++ b/libclamav/scanners.c
@@@ -22,6 -22,7 +22,7 @@@
  #include "clamav-config.h"
  #endif
  
+ #include <sys/time.h>
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
@@@ -35,7 -36,14 +36,7 @@@
  #include <sys/param.h>
  #endif
  #include <fcntl.h>
 -#ifndef	C_WINDOWS
  #include <dirent.h>
 -#include <netinet/in.h>
 -#endif
 -
 -#ifndef	O_BINARY
 -#define	O_BINARY	0
 -#endif
  
  #define DCONF_ARCH  ctx->dconf->archive
  #define DCONF_DOC   ctx->dconf->doc
@@@ -81,6 -89,7 +82,7 @@@
  #include "macho.h"
  #include "ishield.h"
  #include "7z.h"
+ #include "fmap.h"
  
  #ifdef HAVE_BZLIB_H
  #include <bzlib.h>
@@@ -115,7 -124,9 +117,7 @@@ static int cli_scandir(const char *dirn
  #else
  	while((dent = readdir(dd))) {
  #endif
 -#if	(!defined(C_INTERIX)) && (!defined(C_WINDOWS))
  	    if(dent->d_ino)
 -#endif
  	    {
  		if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
  		    /* build the full name */
@@@ -125,7 -136,7 +127,7 @@@
  			return CL_EMEM;
  		    }
  
 -		    sprintf(fname, "%s/%s", dirname, dent->d_name);
 +		    sprintf(fname, "%s"PATHSEP"%s", dirname, dent->d_name);
  
  		    /* stat the file */
  		    if(lstat(fname, &statbuf) != -1) {
@@@ -209,7 -220,7 +211,7 @@@ static int cli_unrar_scanmetadata(int d
  
      if(mdata) {
  	*ctx->virname = mdata->virname;
 -	return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	return CL_VIRUS;
      }
  
      if(DETECT_ENCRYPTED && metadata->encrypted) {
@@@ -421,77 -432,72 +423,72 @@@ static int cli_scanarj(int desc, cli_ct
      return ret;
  }
  
- static int cli_scangzip(int desc, cli_ctx *ctx)
+ static int cli_scangzip(cli_ctx *ctx)
  {
- 	int fd, bytes, ret = CL_CLEAN;
- 	unsigned long int size = 0;
- 	char *buff;
+ 	int fd, ret = CL_CLEAN;
+ 	unsigned char buff[FILEBUFF];
  	char *tmpname;
- 	gzFile gd;
- 
- 
+ 	z_stream z;
+ 	size_t at = 0;
+ 	fmap_t *map = *ctx->fmap;
+  	
      cli_dbgmsg("in cli_scangzip()\n");
  
-     if((gd = gzdopen(dup(desc), "rb")) == NULL) {
- 	cli_dbgmsg("GZip: Can't open descriptor %d\n", desc);
- 	return CL_EOPEN;
+     memset(&z, 0, sizeof(z));
+     if(inflateInit2(&z, MAX_WBITS + 16) != Z_OK) {
+ 	cli_dbgmsg("GZip: InflateInit failed\n");
+ 	return CL_CLEAN;
      }
  
-     if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd))) {
+     if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
  	cli_dbgmsg("GZip: Can't generate temporary file.\n");
- 	gzclose(gd);
+ 	inflateEnd(&z);
  	return ret;
      }
  
-     if(!(buff = (char *) cli_malloc(FILEBUFF))) {
- 	cli_dbgmsg("GZip: Unable to malloc %u bytes.\n", FILEBUFF);
- 	gzclose(gd);
- 	close(fd);
- 	if(!ctx->engine->keeptmp) {
- 	    if(cli_unlink(tmpname)) {
- 	    	free(tmpname);
+     while (at < map->len) {
+ 	unsigned int bytes = MIN(map->len - at, map->pgsz);
+ 	if(!(z.next_in = fmap_need_off_once(map, at, bytes))) {
+ 	    cli_dbgmsg("GZip: Can't read %u bytes @ %lu.\n", bytes, (long unsigned)at);
+ 	    inflateEnd(&z);
+ 	    close(fd);
+ 	    if (cli_unlink(tmpname)) {
+ 		free(tmpname);
  		return CL_EUNLINK;
  	    }
+ 	    free(tmpname);
+ 	    return CL_EREAD;
  	}
- 	return CL_EMEM;
-     }
- 
-     while((bytes = gzread(gd, buff, FILEBUFF)) > 0) {
- 	size += bytes;
- 
- 	if(cli_checklimits("GZip", ctx, size + FILEBUFF, 0, 0)!=CL_CLEAN)
- 	    break;
- 
- 	if(cli_writen(fd, buff, bytes) != bytes) {
- 	    cli_dbgmsg("GZip: Can't write to file.\n");
- 	    close(fd);
- 	    if(!ctx->engine->keeptmp) {
- 	    	if (cli_unlink(tmpname)) {
+ 	at += bytes;
+ 	z.avail_in = bytes;
+ 	do {
+ 	    int inf;
+ 	    z.avail_out = sizeof(buff);
+             z.next_out = buff;
+ 	    inf = inflate(&z, Z_NO_FLUSH);
+ 	    if(inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
+ 		cli_dbgmsg("GZip: Bad stream.\n");
+ 		at = map->len;
+ 		break;
+ 	    }
+ 	    if(cli_writen(fd, buff, sizeof(buff) - z.avail_out) < 0) {
+ 		inflateEnd(&z);	    
+ 		close(fd);
+ 		if (cli_unlink(tmpname)) {
  		    free(tmpname);
  		    return CL_EUNLINK;
  		}
  	    }
- 	    free(tmpname);	
- 	    gzclose(gd);
- 	    free(buff);
- 	    return CL_EWRITE;
- 	}
+ 	    if(inf == Z_STREAM_END) {
+ 		at -= z.avail_in;
+ 		inflateReset(&z);
+ 		break;
+ 	    }
+ 	} while (z.avail_out == 0);
      }
  
-     free(buff);
-     gzclose(gd);
+     inflateEnd(&z);	    
  
-     if(ret == CL_VIRUS) {
- 	close(fd);
- 	if(!ctx->engine->keeptmp)
- 	    if (cli_unlink(tmpname)) ret = CL_EUNLINK;
- 	free(tmpname);	
- 	return ret;
-     }
- 
-     lseek(fd, 0, SEEK_SET);
      if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) {
  	cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname);
  	close(fd);
@@@ -501,14 -507,13 +498,13 @@@
  		return CL_EUNLINK;
  	    }
  	}
- 	free(tmpname);	
+ 	free(tmpname);
  	return CL_VIRUS;
      }
      close(fd);
      if(!ctx->engine->keeptmp)
  	if (cli_unlink(tmpname)) ret = CL_EUNLINK;
-     free(tmpname);	
- 
+     free(tmpname);
      return ret;
  }
  
@@@ -741,7 -746,7 +737,7 @@@ static int cli_vba_scandir(const char *
  
  	for(i = 0; i < vba_project->count; i++) {
  	    for(j = 0; (unsigned int)j < vba_project->colls[i]; j++) {
 -		snprintf(vbaname, 1024, "%s/%s_%u", vba_project->dir, vba_project->name[i], j);
 +		snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", vba_project->dir, vba_project->name[i], j);
  		vbaname[sizeof(vbaname)-1] = '\0';
  		fd = open(vbaname, O_RDONLY|O_BINARY);
  		if(fd == -1) continue;
@@@ -775,7 -780,7 +771,7 @@@
  
      if(ret == CL_CLEAN && (hashcnt = uniq_get(U, "powerpoint document", 19, &hash))) {
  	while(hashcnt--) {
 -	    snprintf(vbaname, 1024, "%s/%s_%u", dirname, hash, hashcnt);
 +	    snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
  	    vbaname[sizeof(vbaname)-1] = '\0';
  	    fd = open(vbaname, O_RDONLY|O_BINARY);
  	    if (fd == -1) continue;
@@@ -793,7 -798,7 +789,7 @@@
  
      if (ret == CL_CLEAN && (hashcnt = uniq_get(U, "worddocument", 12, &hash))) {
  	while(hashcnt--) {
 -	    snprintf(vbaname, sizeof(vbaname), "%s/%s_%u", dirname, hash, hashcnt);
 +	    snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
  	    vbaname[sizeof(vbaname)-1] = '\0';
  	    fd = open(vbaname, O_RDONLY|O_BINARY);
  	    if (fd == -1) continue;
@@@ -840,7 -845,7 +836,7 @@@
      /* Check directory for embedded OLE objects */
      hashcnt = uniq_get(U, "_1_ole10native", 14, &hash);
      while(hashcnt--) {
 -	snprintf(vbaname, sizeof(vbaname), "%s/%s_%u", dirname, hash, hashcnt);
 +	snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
  	vbaname[sizeof(vbaname)-1] = '\0';
  
  	fd = open(vbaname, O_RDONLY|O_BINARY);
@@@ -865,7 -870,9 +861,7 @@@
  #else
  	while((dent = readdir(dd))) {
  #endif
 -#if	(!defined(C_INTERIX)) && (!defined(C_WINDOWS))
  	    if(dent->d_ino)
 -#endif
  	    {
  		if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
  		    /* build the full name */
@@@ -874,7 -881,7 +870,7 @@@
  			ret = CL_EMEM;
  			break;
  		    }
 -		    sprintf(fullname, "%s/%s", dirname, dent->d_name);
 +		    sprintf(fullname, "%s"PATHSEP"%s", dirname, dent->d_name);
  
  		    /* stat the file */
  		    if(lstat(fullname, &statbuf) != -1) {
@@@ -898,24 -905,19 +894,19 @@@
      return ret;
  }
  
- static int cli_scanhtml(int desc, cli_ctx *ctx)
+ static int cli_scanhtml(cli_ctx *ctx)
  {
  	char *tempname, fullname[1024];
  	int ret=CL_CLEAN, fd;
- 	struct stat sb;
+ 	fmap_t *map = *ctx->fmap;
  
      cli_dbgmsg("in cli_scanhtml()\n");
  
-     if(fstat(desc, &sb) == -1) {
-         cli_errmsg("cli_scanhtml: fstat() failed for descriptor %d\n", desc);
- 	return CL_ESTAT;
-     }
- 
      /* Because HTML detection is FP-prone and html_normalise_fd() needs to
       * mmap the file don't normalise files larger than 10 MB.
       */
  
-     if(sb.st_size > 10485760) {
+     if(map->len > 10485760) {
  	cli_dbgmsg("cli_scanhtml: exiting (file larger than 10 MB)\n");
  	return CL_CLEAN;
      }
@@@ -931,18 -933,18 +922,18 @@@
  
      cli_dbgmsg("cli_scanhtml: using tempdir %s\n", tempname);
  
-     html_normalise_fd(desc, tempname, NULL, ctx->dconf);
+     html_normalise_map(map, tempname, NULL, ctx->dconf);
 -    snprintf(fullname, 1024, "%s/nocomment.html", tempname);
 +    snprintf(fullname, 1024, "%s"PATHSEP"nocomment.html", tempname);
      fd = open(fullname, O_RDONLY|O_BINARY);
      if (fd >= 0) {
  	    ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
  	    close(fd);
      }
  
-     if(ret == CL_CLEAN && sb.st_size < 2097152) {
+     if(ret == CL_CLEAN && map->len < 2097152) {
  	    /* limit to 2 MB, we're not interesting in scanning large files in notags form */
  	    /* TODO: don't even create notags if file is over 2 MB */
 -	    snprintf(fullname, 1024, "%s/notags.html", tempname);
 +	    snprintf(fullname, 1024, "%s"PATHSEP"notags.html", tempname);
  	    fd = open(fullname, O_RDONLY|O_BINARY);
  	    if(fd >= 0) {
  		    ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
@@@ -951,7 -953,7 +942,7 @@@
      }
  
      if(ret == CL_CLEAN) {
 -	    snprintf(fullname, 1024, "%s/javascript", tempname);
 +	    snprintf(fullname, 1024, "%s"PATHSEP"javascript", tempname);
  	    fd = open(fullname, O_RDONLY|O_BINARY);
  	    if(fd >= 0) {
  		    ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
@@@ -964,7 -966,7 +955,7 @@@
      }
  
      if (ret == CL_CLEAN) {
 -	snprintf(fullname, 1024, "%s/rfc2397", tempname);
 +	snprintf(fullname, 1024, "%s"PATHSEP"rfc2397", tempname);
  	ret = cli_scandir(fullname, ctx);
      }
  
@@@ -975,30 -977,25 +966,25 @@@
      return ret;
  }
  
- static int cli_scanscript(int desc, cli_ctx *ctx)
+ static int cli_scanscript(cli_ctx *ctx)
  {
- 	unsigned char buff[FILEBUFF];
+ 	unsigned char *buff;
  	unsigned char* normalized;
  	struct text_norm_state state;
  	struct stat sb;
  	char *tmpname = NULL;
  	int ofd = -1, ret;
- 	ssize_t nread;
  	const struct cli_matcher *troot = ctx->engine->root[7];
  	uint32_t maxpatlen = troot ? troot->maxpatlen : 0, offset = 0;
  	struct cli_matcher *groot = ctx->engine->root[0];
  	struct cli_ac_data gmdata, tmdata;
  	struct cli_ac_data *mdata[2];
+ 	fmap_t *map = *ctx->fmap;
+ 	size_t at = 0;
  
  	cli_dbgmsg("in cli_scanscript()\n");
  
- 	if(fstat(desc, &sb) == -1) {
- 		cli_errmsg("cli_scanscript: fstat() failed for descriptor %d\n", desc);
- 		return CL_ESTAT;
- 	}
- 
- 	/* don't normalize files that are too large */
- 	if(sb.st_size > 5242880) {
+ 	if(map->len > 5242880) {
  		cli_dbgmsg("cli_scanscript: exiting (file larger than 5 MB)\n");
  		return CL_CLEAN;
  	}
@@@ -1030,39 -1027,37 +1016,37 @@@
  	mdata[0] = &tmdata;
  	mdata[1] = &gmdata;
  
- 	do {
- 		nread = cli_readn(desc, buff, sizeof(buff));
- 		if(nread <= 0 || state.out_pos + nread > state.out_len) {
- 			/* flush if error/EOF, or too little buffer space left */
- 			if((ofd != -1) && (write(ofd, state.out, state.out_pos) == -1)) {
- 				cli_errmsg("cli_scanscript: can't write to file %s\n",tmpname);
- 				close(ofd);
- 				ofd = -1;
- 				/* we can continue to scan in memory */
- 			}
- 			/* when we flush the buffer also scan */
- 			if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
- 				ret = CL_VIRUS;
- 				if(ofd != -1)
- 				    ret = cli_checkfp(ofd, ctx) ? CL_CLEAN : CL_VIRUS;
- 				break;
- 			}
- 			if(ctx->scanned)
- 			    *ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
- 			offset += state.out_pos;
- 			/* carry over maxpatlen from previous buffer */
- 			if (state.out_pos > maxpatlen)
- 				memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen); 
- 			text_normalize_reset(&state);
- 			state.out_pos = maxpatlen;
+ 	while(1) {
+ 	    size_t len = MIN(map->pgsz, map->len - at);
+ 	    buff = fmap_need_off_once(map, at, len);
+ 	    at += len;
+ 	    if(!buff || !len || state.out_pos + len > state.out_len) {
+ 		/* flush if error/EOF, or too little buffer space left */
+ 		if((ofd != -1) && (write(ofd, state.out, state.out_pos) == -1)) {
+ 		    cli_errmsg("cli_scanscript: can't write to file %s\n",tmpname);
+ 		    close(ofd);
+ 		    ofd = -1;
+ 		    /* we can continue to scan in memory */
  		}
- 		if(nread > 0 && (text_normalize_buffer(&state, buff, nread) != nread)) {
- 			cli_dbgmsg("cli_scanscript: short read during normalizing\n");
+ 		/* when we flush the buffer also scan */
+ 		if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
+ 		    ret = CL_VIRUS;
+ 		    break;
  		}
- 		/* used a do {}while() here, since we need to flush our buffers at the end,
- 		 * and using while(){} loop would mean code duplication */
- 	} while (nread > 0);
- 
+ 		if(ctx->scanned)
+ 		    *ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
+ 		offset += state.out_pos;
+ 		/* carry over maxpatlen from previous buffer */
+ 		if (state.out_pos > maxpatlen)
+ 		    memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen); 
+ 		text_normalize_reset(&state);
+ 		state.out_pos = maxpatlen;
+ 	    }
+ 	    if(!len) break;
+ 	    if(text_normalize_buffer(&state, buff, len) != len) {
+ 		cli_dbgmsg("cli_scanscript: short read during normalizing\n");
+ 	    }
+ 	}
  	cli_ac_freedata(&tmdata);
  	cli_ac_freedata(&gmdata);
  	if(ctx->engine->keeptmp) {
@@@ -1074,11 -1069,12 +1058,12 @@@
  	return ret;
  }
  
- static int cli_scanhtml_utf16(int desc, cli_ctx *ctx)
+ static int cli_scanhtml_utf16(cli_ctx *ctx)
  {
- 	char *tempname, buff[512], *decoded;
+ 	char *tempname, *decoded, *buff;
  	int ret = CL_CLEAN, fd, bytes;
- 
+ 	size_t at = 0;
+ 	fmap_t *map = *ctx->fmap;
  
      cli_dbgmsg("in cli_scanhtml_utf16()\n");
  
@@@ -1093,7 -1089,15 +1078,15 @@@
  
      cli_dbgmsg("cli_scanhtml_utf16: using tempfile %s\n", tempname);
  
-     while((bytes = read(desc, buff, sizeof(buff))) > 0) {
+     while(at < map->len) {
+ 	bytes = MIN(map->len - at, map->pgsz * 16);
+ 	if(!(buff = fmap_need_off_once(map, at, bytes))) {
+ 	    close(fd);
+ 	    cli_unlink(tempname);
+ 	    free(tempname);
+ 	    return CL_EREAD;
+ 	}
+ 	at += bytes;
  	decoded = cli_utf16toascii(buff, bytes);
  	if(decoded) {
  	    if(write(fd, decoded, strlen(decoded)) == -1) {
@@@ -1108,8 -1112,14 +1101,14 @@@
  	}
      }
  
-     lseek(fd, 0, SEEK_SET);
-     ret = cli_scanhtml(fd, ctx);
+     *ctx->fmap = fmap(fd, 0, 0);
+     if(*ctx->fmap) {
+ 	ret = cli_scanhtml(ctx);
+ 	funmap(*ctx->fmap);
+     } else
+ 	cli_errmsg("cli_scanhtml_utf16: fmap of %s failed\n", tempname);
+ 
+     *ctx->fmap = map;
      close(fd);
  
      if(!ctx->engine->keeptmp) {
@@@ -1121,7 -1131,7 +1120,7 @@@
      return ret;
  }
  
- static int cli_scanole2(int desc, cli_ctx *ctx)
+ static int cli_scanole2(cli_ctx *ctx)
  {
  	char *dir;
  	int ret = CL_CLEAN;
@@@ -1142,7 -1152,7 +1141,7 @@@
  	return CL_ETMPDIR;
      }
  
-     ret = cli_ole2_extract(desc, dir, ctx, &vba);
+     ret = cli_ole2_extract(dir, ctx, &vba);
      if(ret!=CL_CLEAN && ret!=CL_VIRUS) {
  	cli_dbgmsg("OLE2: %s\n", cl_strerror(ret));
  	if(!ctx->engine->keeptmp)
@@@ -1195,7 -1205,7 +1194,7 @@@ static int cli_scantar(int desc, cli_ct
      return ret;
  }
  
- static int cli_scanbinhex(int desc, cli_ctx *ctx)
+ static int cli_scanbinhex(cli_ctx *ctx)
  {
  	char *dir;
  	int ret = CL_CLEAN;
@@@ -1213,7 -1223,7 +1212,7 @@@
  	return CL_ETMPDIR;
      }
  
-     if((ret = cli_binhex(dir, desc)))
+     if((ret = cli_binhex(dir, *ctx->fmap)))
  	cli_dbgmsg("Binhex: %s\n", cl_strerror(ret));
      else
  	ret = cli_scandir(dir, ctx);
@@@ -1253,11 -1263,11 +1252,11 @@@ static int cli_scanmschm(int desc, cli_
      }
  
     do {
- 	ret = cli_chm_prepare_file(desc, dir, &metadata);
+ 	ret = cli_chm_prepare_file(&metadata);
  	if (ret != CL_SUCCESS) {
  	   break;
  	}
- 	ret = cli_chm_extract_file(desc, dir, &metadata, ctx);
+ 	ret = cli_chm_extract_file(dir, &metadata, ctx);
  	if (ret == CL_SUCCESS) {
  	    lseek(metadata.ofd, 0, SEEK_SET);
  	    rc = cli_magic_scandesc(metadata.ofd, ctx);
@@@ -1316,8 -1326,10 +1315,8 @@@ static int cli_scanriff(int desc, cli_c
  	int ret = CL_CLEAN;
  
      if(cli_check_riff_exploit(desc) == 2) {
 -	if(!cli_checkfp(desc, ctx)) {
 -	    ret = CL_VIRUS;
 -	    *ctx->virname = "Exploit.W32.MS05-002";
 -	}
 +	ret = CL_VIRUS;
 +	*ctx->virname = "Exploit.W32.MS05-002";
      }
  
      return ret;
@@@ -1328,8 -1340,10 +1327,8 @@@ static int cli_scanjpeg(int desc, cli_c
  	int ret = CL_CLEAN;
  
      if(cli_check_jpeg_exploit(desc, ctx) == 1) {
 -	if(!cli_checkfp(desc, ctx)) {
 -	    ret = CL_VIRUS;
 -	    *ctx->virname = "Exploit.W32.MS04-028";
 -	}
 +	ret = CL_VIRUS;
 +	*ctx->virname = "Exploit.W32.MS04-028";
      }
  
      return ret;
@@@ -1420,7 -1434,7 +1419,7 @@@ static int cli_scancryptff(int desc, cl
      return ret;
  }
  
- static int cli_scanpdf(int desc, cli_ctx *ctx, off_t offset)
+ static int cli_scanpdf(cli_ctx *ctx, off_t offset)
  {
  	int ret;
  	char *dir = cli_gentemp(ctx->engine->tmpdir);
@@@ -1434,7 -1448,7 +1433,7 @@@
  	return CL_ETMPDIR;
      }
  
-     ret = cli_pdf(dir, desc, ctx, offset);
+     ret = cli_pdf(dir, ctx, offset);
  
      if(!ctx->engine->keeptmp)
  	cli_rmdirs(dir);
@@@ -1469,7 -1483,7 +1468,7 @@@ static int cli_scantnef(int desc, cli_c
      return ret;
  }
  
- static int cli_scanuuencoded(int desc, cli_ctx *ctx)
+ static int cli_scanuuencoded(cli_ctx *ctx)
  {
  	int ret;
  	char *dir = cli_gentemp(ctx->engine->tmpdir);
@@@ -1483,7 -1497,7 +1482,7 @@@
  	return CL_ETMPDIR;
      }
  
-     ret = cli_uuencode(dir, desc);
+     ret = cli_uuencode(dir, *ctx->fmap);
  
      if(ret == CL_CLEAN)
  	ret = cli_scandir(dir, ctx);
@@@ -1591,13 -1605,13 +1590,13 @@@ static int cli_scan_structured(int desc
      if(cc_count != 0 && cc_count >= ctx->engine->min_cc_count) {
  	cli_dbgmsg("cli_scan_structured: %u credit card numbers detected\n", cc_count);
  	*ctx->virname = "Structured.CreditCardNumber";
 -	return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	return CL_VIRUS;
      }
  
      if(ssn_count != 0 && ssn_count >= ctx->engine->min_ssn_count) {
  	cli_dbgmsg("cli_scan_structured: %u social security numbers detected\n", ssn_count);
  	*ctx->virname = "Structured.SSN";
 -	return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	return CL_VIRUS;
      }
  
      return CL_CLEAN;
@@@ -1669,14 -1683,14 +1668,14 @@@ static int cli_scanembpe(int desc, cli_
      return CL_CLEAN;
  }
  
- static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_t *dettype)
+ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_t *dettype)
  {
  	int ret = CL_CLEAN, nret = CL_CLEAN;
  	struct cli_matched_type *ftoffset = NULL, *fpt;
  	uint32_t lastzip, lastrar;
  	struct cli_exe_info peinfo;
  	unsigned int acmode = AC_SCAN_VIR, break_loop = 0;
- 	struct stat sb;
+ 	fmap_t *map = *ctx->fmap;
  
  
      if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
@@@ -1685,12 -1699,7 +1684,7 @@@
      if(typercg)
  	acmode |= AC_SCAN_FT;
  
-     if(lseek(desc, 0, SEEK_SET) < 0) {
- 	cli_errmsg("cli_scanraw: lseek() failed\n");
- 	return CL_ESEEK;
-     }
- 
-     ret = cli_scandesc(desc, ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode);
+     ret = cli_fmap_scandesc(ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode);
  
      if(ret >= CL_TYPENO) {
  	ctx->recursion++;
@@@ -1714,73 -1723,72 +1708,72 @@@
  			    cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
  			if(type != CL_TYPE_RAR && have_rar && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_RAR)) {
  			    cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
- 			    nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar);
+ 			    nret = cli_scanrar(map->fd, ctx, fpt->offset, &lastrar);
  			}
  			break;
  
  		    case CL_TYPE_ZIPSFX:
  			if(type != CL_TYPE_ZIP && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_ZIP)) {
  			    cli_dbgmsg("ZIP/ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset);
- 			    nret = cli_unzip_single(desc, ctx, fpt->offset);
+ 			    nret = cli_unzip_single(ctx, fpt->offset);
  			}
  			break;
  
  		    case CL_TYPE_CABSFX:
  			if(type != CL_TYPE_MSCAB && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_CAB)) {
  			    cli_dbgmsg("CAB/CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
- 			    nret = cli_scanmscab(desc, ctx, fpt->offset);
+ 			    nret = cli_scanmscab(map->fd, ctx, fpt->offset);
  			}
  			break;
  		    case CL_TYPE_ARJSFX:
  			if(type != CL_TYPE_ARJ && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_ARJ)) {
  			    cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset);
- 			    nret = cli_scanarj(desc, ctx, fpt->offset, &lastrar);
+ 			    nret = cli_scanarj(map->fd, ctx, fpt->offset, &lastrar);
  			}
  			break;
  
  		    case CL_TYPE_NULSFT:
  		        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_NSIS) && fpt->offset > 4) {
  			    cli_dbgmsg("NSIS signature found at %u\n", (unsigned int) fpt->offset-4);
- 			    nret = cli_scannulsft(desc, ctx, fpt->offset - 4);
+ 			    nret = cli_scannulsft(map->fd, ctx, fpt->offset - 4);
  			}
  			break;
  
  		    case CL_TYPE_AUTOIT:
  		        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_AUTOIT)) {
  			    cli_dbgmsg("AUTOIT signature found at %u\n", (unsigned int) fpt->offset);
- 			    nret = cli_scanautoit(desc, ctx, fpt->offset + 23);
+ 			    nret = cli_scanautoit(map->fd, ctx, fpt->offset + 23);
  			}
  			break;
  
  		    case CL_TYPE_ISHIELD_MSI:
  		        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ISHIELD)) {
  			    cli_dbgmsg("ISHIELD-MSI signature found at %u\n", (unsigned int) fpt->offset);
- 			    nret = cli_scanishield_msi(desc, ctx, fpt->offset + 14);
+ 			    nret = cli_scanishield_msi(ctx, fpt->offset + 14);
  			}
  			break;
  
  		    case CL_TYPE_PDF:
  			if(type != CL_TYPE_PDF && SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
  			    cli_dbgmsg("PDF signature found at %u\n", (unsigned int) fpt->offset);
- 			    nret = cli_scanpdf(desc, ctx, fpt->offset);
+ 			    nret = cli_scanpdf(ctx, fpt->offset);
  			}
  			break;
  
  		    case CL_TYPE_MSEXE:
   			if(SCAN_PE && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP || type == CL_TYPE_MSOLE2) && ctx->dconf->pe) {
- 			    fstat(desc, &sb);
- 			    if(sb.st_size > 10485760)
+ 			    if(map->len > 10485760)
  				break;
  			    memset(&peinfo, 0, sizeof(struct cli_exe_info));
  			    peinfo.offset = fpt->offset;
- 			    lseek(desc, fpt->offset, SEEK_SET);
- 			    if(cli_peheader(desc, &peinfo) == 0) {
+ 			    lseek(map->fd, fpt->offset, SEEK_SET);
+ 			    if(cli_peheader(map, &peinfo) == 0) {
  				cli_dbgmsg("*** Detected embedded PE file at %u ***\n", (unsigned int) fpt->offset);
  				if(peinfo.section)
  				    free(peinfo.section);
  
- 				lseek(desc, fpt->offset, SEEK_SET);
- 				nret = cli_scanembpe(desc, ctx);
+ 				lseek(map->fd, fpt->offset, SEEK_SET);
+ 				nret = cli_scanembpe(map->fd, ctx);
  				break_loop = 1; /* we can stop here and other
  						 * embedded executables will
  						 * be found recursively
@@@ -1805,13 -1813,13 +1798,13 @@@
  	    case CL_TYPE_HTML:
  		if(SCAN_HTML && type == CL_TYPE_TEXT_ASCII && (DCONF_DOC & DOC_CONF_HTML)) {
  		    *dettype = CL_TYPE_HTML;
- 		    nret = cli_scanhtml(desc, ctx);
+ 		    nret = cli_scanhtml(ctx);
  		}
  		break;
  
  	    case CL_TYPE_MAIL:
  		if(SCAN_MAIL && type == CL_TYPE_TEXT_ASCII && (DCONF_MAIL & MAIL_CONF_MBOX))
- 		    nret = cli_scanmail(desc, ctx);
+ 		    nret = cli_scanmail(map->fd, ctx);
  		break;
  
  	    default:
@@@ -1828,7 -1836,7 +1821,7 @@@
      }
  
      if(ret == CL_VIRUS)
- 	cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
+ 	cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, map->fd);
  
      return ret;
  }
@@@ -1869,30 -1877,40 +1862,41 @@@ int cli_magic_scandesc(int desc, cli_ct
      if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN)
          return CL_CLEAN;
  
+     ctx->fmap++;
+     if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
+ 	cli_errmsg("CRITICAL: fmap() failed\n");
+ 	return CL_EMEM;
+     }
+ 
      if(!ctx->options || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */
  	if(ctx->recursion == ctx->engine->maxreclevel)
  	    cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n");
  	else
  	    cli_dbgmsg("Raw mode: No support for special files\n");
- 	if((ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS) {
+ 	if((ret = cli_fmap_scandesc(ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS)
  	    cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
- 	    return CL_VIRUS;
- 	}
+ 	funmap(*ctx->fmap);
+ 	ctx->fmap--; 
  	return ret;
      }
  
-     lseek(desc, 0, SEEK_SET);
-     type = cli_filetype2(desc, ctx->engine);
+     type = cli_filetype2(*ctx->fmap, ctx->engine); /* FIXMEFMAP: port to fmap */
      if(type == CL_TYPE_ERROR) {
  	cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
+ 	funmap(*ctx->fmap);
+ 	ctx->fmap--; 
  	return CL_EREAD;
      }
-     lseek(desc, 0, SEEK_SET);
+     lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
  
      if(type != CL_TYPE_IGNORED && ctx->engine->sdb) {
- 	if((ret = cli_scanraw(desc, ctx, type, 0, &dettype)) == CL_VIRUS)
- 	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
- 	lseek(desc, 0, SEEK_SET);
+ 	if((ret = cli_scanraw(ctx, type, 0, &dettype)) == CL_VIRUS) {
++	    ret = cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ 	    funmap(*ctx->fmap);
+ 	    ctx->fmap--; 
 -	    return CL_VIRUS;
++	    return ret;
+ 	}
+ 	lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
      }
  
      ctx->container_type = 0;
@@@ -1908,12 -1926,12 +1912,12 @@@
  
  	case CL_TYPE_ZIP:
  	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP))
- 		ret = cli_unzip(desc, ctx);
+ 		ret = cli_unzip(ctx);
  	    break;
  
  	case CL_TYPE_GZ:
  	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_GZ))
- 		ret = cli_scangzip(desc, ctx);
+ 		ret = cli_scangzip(ctx);
  	    break;
  
  	case CL_TYPE_BZ:
@@@ -1947,17 -1965,17 +1951,17 @@@
  
  	case CL_TYPE_HTML:
  	    if(SCAN_HTML && (DCONF_DOC & DOC_CONF_HTML))
- 		ret = cli_scanhtml(desc, ctx);
+ 		ret = cli_scanhtml(ctx);
  	    break;
  
  	case CL_TYPE_HTML_UTF16:
  	    if(SCAN_HTML && (DCONF_DOC & DOC_CONF_HTML))
- 		ret = cli_scanhtml_utf16(desc, ctx);
+ 		ret = cli_scanhtml_utf16(ctx);
  	    break;
  
  	case CL_TYPE_SCRIPT:
  	    if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
- 	        ret = cli_scanscript(desc, ctx);
+ 	        ret = cli_scanscript(ctx);
  	    break;
  
  	case CL_TYPE_RTF:
@@@ -1977,7 -1995,7 +1981,7 @@@
  
  	case CL_TYPE_UUENCODED:
  	    if(DCONF_OTHER & OTHER_CONF_UUENC)
- 		ret = cli_scanuuencoded(desc, ctx);
+ 		ret = cli_scanuuencoded(ctx);
  	    break;
  
  	case CL_TYPE_MSCHM:
@@@ -1987,7 -2005,7 +1991,7 @@@
  
  	case CL_TYPE_MSOLE2:
  	    if(SCAN_OLE2 && (DCONF_ARCH & ARCH_CONF_OLE2))
- 		ret = cli_scanole2(desc, ctx);
+ 		ret = cli_scanole2(ctx);
  	    break;
  
  	case CL_TYPE_7Z:
@@@ -2027,7 -2045,7 +2031,7 @@@
  
  	case CL_TYPE_BINHEX:
  	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BINHEX))
- 		ret = cli_scanbinhex(desc, ctx);
+ 		ret = cli_scanbinhex(ctx);
  	    break;
  
  	case CL_TYPE_SCRENC:
@@@ -2047,7 -2065,7 +2051,7 @@@
  
          case CL_TYPE_PDF: /* FIXMELIMITS: pdf should be an archive! */
  	    if(SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF))
- 		ret = cli_scanpdf(desc, ctx, 0);
+ 		ret = cli_scanpdf(ctx, 0);
  	    break;
  
  	case CL_TYPE_CRYPTFF:
@@@ -2057,17 -2075,17 +2061,17 @@@
  
  	case CL_TYPE_ELF:
  	    if(SCAN_ELF && ctx->dconf->elf)
- 		ret = cli_scanelf(desc, ctx);
+ 		ret = cli_scanelf(ctx);
  	    break;
  
  	case CL_TYPE_MACHO:
  	    if(ctx->dconf->macho)
- 		ret = cli_scanmacho(desc, ctx, NULL);
+ 		ret = cli_scanmacho(ctx, NULL);
  	    break;
  
  	case CL_TYPE_MACHO_UNIBIN:
  	    if(ctx->dconf->macho)
- 		ret = cli_scanmacho_unibin(desc, ctx);
+ 		ret = cli_scanmacho_unibin(ctx);
  	    break;
  
  	case CL_TYPE_SIS:
@@@ -2094,8 -2112,11 +2098,12 @@@
      ctx->recursion--;
      ctx->container_type = current_container;
  
-     if(ret == CL_VIRUS)
- 	return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+     if(ret == CL_VIRUS) {
++	ret = cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ 	funmap(*ctx->fmap);
+ 	ctx->fmap--; 
 -	return CL_VIRUS;
++	return ret;
+     }
  
      if(type == CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
  	if(sb.st_size > 1048576) {
@@@ -2106,8 -2127,11 +2114,12 @@@
  
      /* CL_TYPE_HTML: raw HTML files are not scanned, unless safety measure activated via DCONF */
      if(type != CL_TYPE_IGNORED && (type != CL_TYPE_HTML || !(DCONF_DOC & DOC_CONF_HTML_SKIPRAW)) && !ctx->engine->sdb) {
- 	if(cli_scanraw(desc, ctx, type, typercg, &dettype) == CL_VIRUS)
- 	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ 	if(cli_scanraw(ctx, type, typercg, &dettype) == CL_VIRUS) {
++	    ret =  cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ 	    funmap(*ctx->fmap);
+ 	    ctx->fmap--; 
 -	    return CL_VIRUS;
++	    return ret;
+ 	}
      }
  
      ctx->recursion++;
@@@ -2118,7 -2142,7 +2130,7 @@@
  	case CL_TYPE_TEXT_UTF16LE:
  	case CL_TYPE_TEXT_UTF8:
  	    if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
- 	        ret = cli_scanscript(desc, ctx);
+ 	        ret = cli_scanscript(ctx);
  	    if(ret != CL_VIRUS && ctx->container_type == CL_TYPE_MAIL) {
  		lseek(desc, 0, SEEK_SET);
  		ret = cli_scandesc(desc, ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR);
@@@ -2129,17 -2153,16 +2141,19 @@@
  	 */
  	case CL_TYPE_MSEXE:
  	    if(SCAN_PE && ctx->dconf->pe)
- 		ret = cli_scanpe(desc, ctx);
+ 		ret = cli_scanpe(ctx);
  	    break;
  
  	default:
  	    break;
      }
      ctx->recursion--;
+     funmap(*ctx->fmap);
+     ctx->fmap--;
  
 +    if(ret == CL_VIRUS)
 +	return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +
      switch(ret) {
  	case CL_EFORMAT:
  	case CL_EMAXREC:
@@@ -2165,8 -2188,15 +2179,15 @@@ int cl_scandesc(int desc, const char **
      ctx.found_possibly_unwanted = 0;
      ctx.container_type = 0;
      ctx.dconf = (struct cli_dconf *) engine->dconf;
+     ctx.fmap = cli_calloc(sizeof(fmap_t *), ctx.engine->maxreclevel + 1);
+     if(!ctx.fmap)
+ 	return CL_EMEM;
+     ctx.fmap--;
  
      rc = cli_magic_scandesc(desc, &ctx);
+ 
+     ctx.fmap++;
+     free(ctx.fmap);
      if(rc == CL_CLEAN && ctx.found_possibly_unwanted)
      	rc = CL_VIRUS;
      return rc;
@@@ -2211,7 -2241,6 +2232,6 @@@ int cl_scanfile(const char *filename, c
  {
  	int fd, ret;
  
- 
      if((fd = open(filename, O_RDONLY|O_BINARY)) == -1)
  	return CL_EOPEN;
  
diff --combined libclamav/unzip.c
index 47c8cf7,1376996..bcc8e32
--- a/libclamav/unzip.c
+++ b/libclamav/unzip.c
@@@ -34,10 -34,8 +34,7 @@@
  #include <string.h>
  #endif
  #include <stdlib.h>
 -
  #include <stdio.h>
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
  
  #include <zlib.h>
  #include "inflate64.h"
@@@ -50,23 -48,20 +47,15 @@@
  #include "clamav.h"
  #include "scanners.h"
  #include "matcher.h"
+ #include "fmap.h"
  
  #define UNZIP_PRIVATE
  #include "unzip.h"
  
 -#ifndef O_BINARY
 -#define O_BINARY 0
 -#endif
 -
 -
  static int wrap_inflateinit2(void *a, int b) {
    return inflateInit2(a, b);
  }
  
- static inline void destroy_map(void *map, size_t fsize) {
- #if HAVE_MMAP
-   munmap(map, fsize);
- #else
-   free(map);
- #endif
- }
- 
- 
  static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, uint16_t flags, unsigned int *fu, cli_ctx *ctx, char *tmpd) {
    char name[1024], obuf[BUFSIZ];
    char *tempfile = name;
@@@ -74,7 -69,7 +63,7 @@@
    unsigned int res=1, written=0;
  
    if(tmpd) {
 -    snprintf(name, sizeof(name), "%s/zip.%03u", tmpd, *fu);
 +    snprintf(name, sizeof(name), "%s"PATHSEP"zip.%03u", tmpd, *fu);
      name[sizeof(name)-1]='\0';
    } else {
      if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM;
@@@ -308,33 -303,39 +297,39 @@@
    return ret;
  }
  
- static unsigned int lhdr(uint8_t *zip, uint32_t zsize, unsigned int *fu, unsigned int fc, uint8_t *ch, int *ret, cli_ctx *ctx, char *tmpd, int fd) {
-   uint8_t *lh = zip;
+ static unsigned int lhdr(fmap_t *map, uint32_t loff,uint32_t zsize, unsigned int *fu, unsigned int fc, uint8_t *ch, int *ret, cli_ctx *ctx, char *tmpd) {
+   uint8_t *lh, *zip;
    char name[256];
    uint32_t csize, usize;
    struct cli_meta_node *meta = ctx->engine->zip_mlist;
  
-   if(zsize<=SIZEOF_LH) {
-     cli_dbgmsg("cli_unzip: lh - out of file\n");
-     return 0;
+   if(!(lh = fmap_need_off(map, loff, SIZEOF_LH))) {
+       cli_dbgmsg("cli_unzip: lh - out of file\n");
+       return 0;
    }
    if(LH_magic != 0x04034b50) {
      if (!ch) cli_dbgmsg("cli_unzip: lh - wrkcomplete\n");
      else cli_dbgmsg("cli_unzip: lh - bad magic\n");
+     fmap_unneed_off(map, loff, SIZEOF_LH);
      return 0;
    }
  
-   zip+=SIZEOF_LH;
+   zip = lh + SIZEOF_LH;
    zsize-=SIZEOF_LH;
  
    if(zsize<=LH_flen) {
      cli_dbgmsg("cli_unzip: lh - fname out of file\n");
+     fmap_unneed_off(map, loff, SIZEOF_LH);
      return 0;
    }
    if(meta || cli_debug_flag) {
-     uint32_t nsize = (LH_flen>=sizeof(name))?sizeof(name)-1:LH_flen;
-     memcpy(name, zip, nsize);
-     name[nsize]='\0';
+       uint32_t nsize = (LH_flen>=sizeof(name))?sizeof(name)-1:LH_flen;
+       char *src;
+       if(nsize && (src = fmap_need_ptr_once(map, zip, nsize))) {
+ 	  memcpy(name, zip, nsize);
+ 	  name[nsize]='\0';
+       } else
+ 	  name[0] = '\0';
    }
    zip+=LH_flen;
    zsize-=LH_flen;
@@@ -355,14 -356,20 +350,15 @@@
  	 )
  	) meta = meta->next;
    if(meta) {
 -    if(!cli_checkfp(map->fd, ctx)) {
 -      *ctx->virname = meta->virname;
 -      *ret = CL_VIRUS;
 -    } else
 -      *ret = CL_CLEAN;
 -
 -    fmap_unneed_off(map, loff, SIZEOF_LH);
 +    *ctx->virname = meta->virname;
 +    *ret = CL_VIRUS;
      return 0;
    }
  
    if(LH_flags & F_MSKED) {
      cli_dbgmsg("cli_unzip: lh - header has got unusable masked data\n");
      /* FIXME: need to find/craft a sample */
+     fmap_unneed_off(map, loff, SIZEOF_LH);
      return 0;
    }
  
@@@ -370,63 -377,76 +366,76 @@@
      cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n");
      *ctx->virname = "Encrypted.Zip";
      *ret = CL_VIRUS;
+     fmap_unneed_off(map, loff, SIZEOF_LH);
      return 0;
    }
   
    if(LH_flags & F_USEDD) {
      cli_dbgmsg("cli_unzip: lh - has data desc\n");
-     if(!ch) return 0;
+     if(!ch) {
+ 	fmap_unneed_off(map, loff, SIZEOF_LH);
+ 	return 0;
+     }
      else { usize = CH_usize; csize = CH_csize; }
    } else { usize = LH_usize; csize = LH_csize; }
  
    if(zsize<=LH_elen) {
      cli_dbgmsg("cli_unzip: lh - extra out of file\n");
+     fmap_unneed_off(map, loff, SIZEOF_LH);
      return 0;
    }
    zip+=LH_elen;
    zsize-=LH_elen;
  
    if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */
-     cli_dbgmsg("cli_unzip: lh - skipping empty file\n");
+       cli_dbgmsg("cli_unzip: lh - skipping empty file\n");
    } else {
-     if(zsize<csize) {
-       cli_dbgmsg("cli_unzip: lh - stream out of file\n");
-       return 0;
-     } 
-     if(LH_flags & F_ENCR) {
-       cli_dbgmsg("cli_unzip: lh - skipping encrypted file\n");
-     } else *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd);
-     zip+=csize;
-     zsize-=csize;
+       if(zsize<csize) {
+ 	  cli_dbgmsg("cli_unzip: lh - stream out of file\n");
+ 	  fmap_unneed_off(map, loff, SIZEOF_LH);
+ 	  return 0;
+       }
+       if(LH_flags & F_ENCR) {
+ 	  cli_dbgmsg("cli_unzip: lh - skipping encrypted file\n");
+       } else {
+ 	  if(fmap_need_ptr_once(map, zip, csize))
+ 	      *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd);
+       }
+       zip+=csize;
+       zsize-=csize;
    }
  
+   fmap_unneed_off(map, loff, SIZEOF_LH); /* unneed now. block is guaranteed to exists till the next need */
    if(LH_flags & F_USEDD) {
-     if(zsize<12) {
-       cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
-       return 0;
-     }
-     zsize-=12;
-     if(cli_readint32(zip)==0x08074b50) {
-       if(zsize<4) {
- 	cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
- 	return 0;
+       if(zsize<12) {
+ 	  cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
+ 	  return 0;
        }
-       zip+=4;
-     }
-     zip+=12;
+       zsize-=12;
+       if(fmap_need_ptr_once(map, zip, 4)) {
+ 	  if(cli_readint32(zip)==0x08074b50) {
+ 	      if(zsize<4) {
+ 		  cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
+ 		  return 0;
+ 	      }
+ 	      zip+=4;
+ 	  }
+       }
+       zip+=12;
    }
    return zip-lh;
  }
  
  
- static unsigned int chdr(uint8_t *zip, uint32_t coff, uint32_t zsize, unsigned int *fu, unsigned int fc, int *ret, cli_ctx *ctx, char *tmpd, int fd) {
-   uint8_t *ch = &zip[coff];
+ static unsigned int chdr(fmap_t *map, uint32_t coff, uint32_t zsize, unsigned int *fu, unsigned int fc, int *ret, cli_ctx *ctx, char *tmpd) {
    char name[256];
    int last = 0;
+   int8_t *ch;
  
-   if(zsize-coff<=SIZEOF_CH || CH_magic != 0x02014b50) {
-     cli_dbgmsg("cli_unzip: ch - wrkcomplete\n");
-     return 0;
+   if(!(ch = fmap_need_off(map, coff, SIZEOF_CH)) || CH_magic != 0x02014b50) {
+       if(ch) fmap_unneed_ptr(map, ch, SIZEOF_CH);
+       cli_dbgmsg("cli_unzip: ch - wrkcomplete\n");
+       return 0;
    }
    coff+=SIZEOF_CH;
  
@@@ -437,10 -457,13 +446,13 @@@
      last=1;
    }
    if(cli_debug_flag && !last) {
-     unsigned int size = (CH_flen>=sizeof(name))?sizeof(name)-1:CH_flen;
-     memcpy(name, &zip[coff], size);
-     name[size]='\0';
-     cli_dbgmsg("cli_unzip: ch - fname: %s\n", name);
+       unsigned int size = (CH_flen>=sizeof(name))?sizeof(name)-1:CH_flen;
+       char *src = fmap_need_off_once(map, coff, size);
+       if(src) {
+ 	  memcpy(name, src, size);
+ 	  name[size]='\0';
+ 	  cli_dbgmsg("cli_unzip: ch - fname: %s\n", name);
+       }
    }
    coff+=CH_flen;
  
@@@ -457,27 -480,23 +469,23 @@@
    coff+=CH_clen;
  
    if(CH_off<zsize-SIZEOF_LH) {
-     lhdr(&zip[CH_off], zsize-CH_off, fu, fc, ch, ret, ctx, tmpd, fd);
+       lhdr(map, CH_off, zsize-CH_off, fu, fc, ch, ret, ctx, tmpd);
    } else cli_dbgmsg("cli_unzip: ch - local hdr out of file\n");
+   fmap_unneed_ptr(map, ch, SIZEOF_CH);
    return last?0:coff;
  }
  
  
- int cli_unzip(int f, cli_ctx *ctx) {
+ int cli_unzip(cli_ctx *ctx) {
    unsigned int fc=0, fu=0;
    int ret=CL_CLEAN;
    uint32_t fsize, lhoff = 0, coff = 0;
-   struct stat st;
-   uint8_t *map;
-   char *tmpd;
+   fmap_t *map = *ctx->fmap;
+   char *tmpd, *ptr;
  
    cli_dbgmsg("in cli_unzip\n");
-   if (fstat(f, &st)==-1) {
-     cli_warnmsg("cli_unzip: fstat() failed\n");
-     return CL_ESTAT;
-   }
-   fsize = (uint32_t)st.st_size;
-   if(sizeof(off_t)!=sizeof(uint32_t) && (off_t)fsize!=st.st_size) {
+   fsize = (uint32_t)map->len;
+   if(sizeof(off_t)!=sizeof(uint32_t) && (off_t)fsize!=map->len) {
      cli_dbgmsg("cli_unzip: file too big\n");
      return CL_CLEAN;
    }
@@@ -485,59 -504,39 +493,39 @@@
      cli_dbgmsg("cli_unzip: file too short\n");
      return CL_CLEAN;
    }
- 
- #if HAVE_MMAP
-   if ((map = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, f, 0))==MAP_FAILED) {
-     cli_dbgmsg("cli_unzip: mmap failed\n");
-     return CL_EMAP;
-   }
- #else
-   if(fsize > CLI_MAX_ALLOCATION) {
-     cli_warnmsg("cli_unzip: mmap not available and file is too big\n");
-     return CL_CLEAN;
-   }
-   lseek(f, 0, SEEK_SET);
-   if(!(map = cli_malloc(fsize)))
-     return CL_EMEM;
-   if(cli_readn(f, map, fsize)!=fsize) {
-     free(map);
-     return CL_EREAD;
-   }
- #endif
- 
    if (!(tmpd = cli_gentemp(ctx->engine->tmpdir))) {
-     destroy_map(map, fsize);
      return CL_ETMPDIR;
    }
    if (mkdir(tmpd, 0700)) {
      cli_dbgmsg("cli_unzip: Can't create temporary directory %s\n", tmpd);
-     destroy_map(map, fsize);
      free(tmpd);
      return CL_ETMPDIR;
    }
  
    for(coff=fsize-22 ; coff>0 ; coff--) { /* sizeof(EOC)==22 */
-     if(cli_readint32(&map[coff])==0x06054b50) {
-       uint32_t chptr = cli_readint32(&map[coff+16]);
-       if(!CLI_ISCONTAINED(map, fsize, map+chptr, SIZEOF_CH)) continue;
-       coff=chptr;
-       break;
-     }
+       if(!(ptr = fmap_need_off_once(map, coff, 20)))
+ 	  continue;
+       if(cli_readint32(ptr)==0x06054b50) {
+ 	  uint32_t chptr = cli_readint32(&ptr[16]);
+ 	  if(!CLI_ISCONTAINED(0, fsize, chptr, SIZEOF_CH)) continue;
+ 	  coff=chptr;
+ 	  break;
+       }
    }
  
    if(coff) {
-     cli_dbgmsg("cli_unzip: central @%x\n", coff);
-     while(ret==CL_CLEAN && (coff=chdr(map, coff, fsize, &fu, fc+1, &ret, ctx, tmpd, f))) {
-       fc++;
-       if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
- 	cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
- 	ret=CL_EMAXFILES;
+       cli_dbgmsg("cli_unzip: central @%x\n", coff);
+       while(ret==CL_CLEAN && (coff=chdr(map, coff, fsize, &fu, fc+1, &ret, ctx, tmpd))) {
+ 	  fc++;
+ 	  if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
+ 	      cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
+ 	      ret=CL_EMAXFILES;
+ 	  }
        }
    } else cli_dbgmsg("cli_unzip: central not found, using localhdrs\n");
    if(fu<=(fc/4)) { /* FIXME: make up a sane ratio or remove the whole logic */
      fc = 0;
-     while (ret==CL_CLEAN && lhoff<fsize && (coff=lhdr(&map[lhoff], fsize-lhoff, &fu, fc+1, NULL, &ret, ctx, tmpd, f))) {
+     while (ret==CL_CLEAN && lhoff<fsize && (coff=lhdr(map, lhoff, fsize-lhoff, &fu, fc+1, NULL, &ret, ctx, tmpd))) {
        fc++;
        lhoff+=coff;
        if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
@@@ -547,27 -546,21 +535,21 @@@
      }
    }
  
-   destroy_map(map, fsize);
    if (!ctx->engine->keeptmp) cli_rmdirs(tmpd);
    free(tmpd);
  
    return ret;
  }
  
- int cli_unzip_single(int f, cli_ctx *ctx, off_t lhoffl) {
+ int cli_unzip_single(cli_ctx *ctx, off_t lhoffl) {
    int ret=CL_CLEAN;
    unsigned int fu=0;
-   struct stat st;
    uint32_t fsize;
-   uint8_t *map;
+   fmap_t *map = *ctx->fmap;
  
    cli_dbgmsg("in cli_unzip_single\n");
-   if (fstat(f, &st)==-1) {
-     cli_warnmsg("cli_unzip: fstat() failed\n");
-     return CL_ESTAT;
-   }
-   fsize = (uint32_t)(st.st_size - lhoffl);
-   if (lhoffl<0 || lhoffl>st.st_size || (sizeof(off_t)!=sizeof(uint32_t) && (off_t)fsize!=st.st_size - lhoffl)) {
+   fsize = (uint32_t)(map->len - lhoffl);
+   if (lhoffl<0 || lhoffl>map->len || (sizeof(off_t)!=sizeof(uint32_t) && (off_t)fsize!=map->len - lhoffl)) {
      cli_dbgmsg("cli_unzip: bad offset\n");
      return CL_CLEAN;
    }
@@@ -576,26 -569,7 +558,7 @@@
      return CL_CLEAN;
    }
  
- #if HAVE_MMAP
-   if ((map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, f, 0))==MAP_FAILED) {
-     cli_dbgmsg("cli_unzip: mmap() failed\n");
-     return CL_EMAP;
-   }
- #else
-   if(st.st_size > CLI_MAX_ALLOCATION) {
-     cli_warnmsg("cli_unzip: mmap not available and file is too big\n");
-     return CL_CLEAN;
-   }
-   lseek(f, 0, SEEK_SET);
-   if(!(map = cli_malloc(st.st_size)))
-     return CL_EMEM;
-   if(cli_readn(f, map, st.st_size)!=st.st_size) {
-     free(map);
-     return CL_EREAD;
-   }
- #endif
-   lhdr(&map[lhoffl], fsize, &fu, 0, NULL, &ret, ctx, NULL, f);
+   lhdr(map, lhoffl, fsize, &fu, 0, NULL, &ret, ctx, NULL);
  
-   destroy_map(map, st.st_size);
    return ret;
  }
diff --combined libclamav/uuencode.c
index 71fa0ba,6619c94..517f48d
--- a/libclamav/uuencode.c
+++ b/libclamav/uuencode.c
@@@ -39,6 -39,10 +39,6 @@@ static	char	const	rcsid[] = "$Id: uuenc
  #include "others.h"
  #include "str.h"
  
 -#ifdef	C_WINDOWS
 -#include <io.h>
 -#endif
 -
  #include "mbox.h"
  #include "uuencode.h"
  
@@@ -46,48 -50,35 +46,35 @@@
  #define	RFC2821LENGTH	1000
  
  int
- cli_uuencode(const char *dir, int desc)
+ cli_uuencode(const char *dir, fmap_t *map)
  {
- 	FILE *fin;
- 	int i;
  	message *m;
  	char buffer[RFC2821LENGTH + 1];
+ 	size_t at = 0;
  
- 	i = dup(desc);
- 	if((fin = fdopen(i, "rb")) == NULL) {
- 		cli_errmsg("Can't open descriptor %d\n", desc);
- 		close(i);
- 		return CL_EOPEN;
- 	}
- 	if(fgets(buffer, sizeof(buffer) - 1, fin) == NULL) {
+ 	if(!fmap_gets(map, buffer, &at, sizeof(buffer) - 1)) {
  		/* empty message */
  		return CL_CLEAN;
  	}
  	if(!isuuencodebegin(buffer)) {
- 		fclose(fin);
  		cli_dbgmsg("Message is not in uuencoded format\n");
  		return CL_EFORMAT;
  	}
  
  	m = messageCreate();
  	if(m == NULL) {
- 		fclose(fin);
  		return CL_EMEM;
  	}
  
  	cli_dbgmsg("found uuencode file\n");
  
- 	if(uudecodeFile(m, buffer, dir, fin) < 0) {
+ 	if(uudecodeFile(m, buffer, dir, map, &at) < 0) {
  		messageDestroy(m);
- 		fclose(fin);
  		cli_dbgmsg("Message is not in uuencoded format\n");
  		return CL_EFORMAT;
  	}
  	messageDestroy(m);
  
- 	fclose(fin);
- 
  	return CL_CLEAN;	/* a lie - but it gets things going */
  }
  
@@@ -97,7 -88,7 +84,7 @@@
   * Return < 0 for failure
   */
  int
- uudecodeFile(message *m, const char *firstline, const char *dir, FILE *fin)
+ uudecodeFile(message *m, const char *firstline, const char *dir, fmap_t *map, size_t *at)
  {
  	fileblob *fb;
  	char buffer[RFC2821LENGTH + 1];
@@@ -116,7 -107,7 +103,7 @@@
  	cli_dbgmsg("uudecode %s\n", filename);
  	free(filename);
  
- 	while(fgets(buffer, sizeof(buffer) - 1, fin) != NULL) {
+ 	while(fmap_gets(map, buffer, at, sizeof(buffer) - 1)) {
  		unsigned char data[1024];
  		const unsigned char *uptr;
  		size_t len;
diff --combined sigtool/sigtool.c
index 66b4d3b,e3e5ce5..be290a2
--- a/sigtool/sigtool.c
+++ b/sigtool/sigtool.c
@@@ -34,13 -34,11 +34,13 @@@
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
 +#ifndef _WIN32
  #include <sys/socket.h>
  #include <sys/un.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <sys/wait.h>
 +#endif
  #include <dirent.h>
  
  #ifdef HAVE_TERMIOS_H
@@@ -63,6 -61,7 +63,7 @@@
  #include "libclamav/ole2_extract.h"
  #include "libclamav/htmlnorm.h"
  #include "libclamav/default.h"
+ #include "libclamav/fmap.h"
  
  #define MAX_DEL_LOOKAHEAD   200
  
@@@ -184,14 -183,19 +185,19 @@@ static int md5sig(const struct optstruc
  static int htmlnorm(const struct optstruct *opts)
  {
  	int fd;
- 
+ 	fmap_t *map;
  
      if((fd = open(optget(opts, "html-normalise")->strarg, O_RDONLY)) == -1) {
  	mprintf("!htmlnorm: Can't open file %s\n", optget(opts, "html-normalise")->strarg);
  	return -1;
      }
  
-     html_normalise_fd(fd, ".", NULL, NULL);
+     if((map = fmap(fd, 0, 0))) {
+ 	html_normalise_map(map, ".", NULL, NULL);
+ 	funmap(map);
+     } else
+ 	mprintf("!fmap failed\n");
+ 	
      close(fd);
  
      return 0;
@@@ -327,7 -331,7 +333,7 @@@ static char *getdsig(const char *host, 
      server.sin_port = htons(33101);
  
      if(connect(sockd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) < 0) {
 -        close(sockd);
 +        closesocket(sockd);
  	perror("connect()");
  	mprintf("!getdsig: Can't connect to ClamAV Signing Service at %s\n", host);
  	memset(pass, 0, sizeof(pass));
@@@ -345,9 -349,9 +351,9 @@@
      memcpy(pt, data, datalen);
      len += datalen;
  
 -    if(write(sockd, cmd, len) < 0) {
 +    if(send(sockd, cmd, len, 0) < 0) {
  	mprintf("!getdsig: Can't write to socket\n");
 -	close(sockd);
 +	closesocket(sockd);
  	memset(cmd, 0, sizeof(cmd));
  	memset(pass, 0, sizeof(pass));
  	return NULL;
@@@ -357,22 -361,22 +363,22 @@@
      memset(pass, 0, sizeof(pass));
      memset(buff, 0, sizeof(buff));
  
 -    if((bread = cli_readn(sockd, buff, sizeof(buff))) > 0) {
 +    if((bread = recv(sockd, buff, sizeof(buff), 0)) > 0) {
  	if(!strstr(buff, "Signature:")) {
  	    mprintf("!getdsig: Error generating digital signature\n");
  	    mprintf("!getdsig: Answer from remote server: %s\n", buff);
 -	    close(sockd);
 +	    closesocket(sockd);
  	    return NULL;
  	} else {
  	    mprintf("Signature received (length = %lu)\n", strlen(buff) - 10);
  	}
      } else {
  	mprintf("!getdsig: Communication error with remote server\n");
 -	close(sockd);
 +	closesocket(sockd);
  	return NULL;
      }
  
 -    close(sockd);
 +    closesocket(sockd);
  
      pt = buff;
      pt += 10;
@@@ -617,9 -621,9 +623,9 @@@ static int build(const struct optstruc
  
      } else {
  	pt = freshdbdir();
 -	snprintf(olddb, sizeof(olddb), "%s/%s.cvd", pt, dbname);
 +	snprintf(olddb, sizeof(olddb), "%s"PATHSEP"%s.cvd", pt, dbname);
  	if(access(olddb, R_OK))
 -	    snprintf(olddb, sizeof(olddb), "%s/%s.cld", pt, dbname);
 +	    snprintf(olddb, sizeof(olddb), "%s"PATHSEP"%s.cld", pt, dbname);
  	free(pt);
      }
  
@@@ -910,9 -914,9 +916,9 @@@ static int unpack(const struct optstruc
  
      if(optget(opts, "unpack-current")->enabled) {
  	dbdir = freshdbdir();
 -	snprintf(name, sizeof(name), "%s/%s.cvd", dbdir, optget(opts, "unpack-current")->strarg);
 +	snprintf(name, sizeof(name), "%s"PATHSEP"%s.cvd", dbdir, optget(opts, "unpack-current")->strarg);
  	if(access(name, R_OK)) {
 -	    snprintf(name, sizeof(name), "%s/%s.cld", dbdir, optget(opts, "unpack-current")->strarg);
 +	    snprintf(name, sizeof(name), "%s"PATHSEP"%s.cld", dbdir, optget(opts, "unpack-current")->strarg);
  	    if(access(name, R_OK)) {
  		mprintf("!unpack: Couldn't find %s CLD/CVD database\n", optget(opts, "unpack-current")->strarg);
  		free(dbdir);
@@@ -989,7 -993,9 +995,7 @@@ static int listdir(const char *dirname
      }
  
      while((dent = readdir(dd))) {
 -#ifndef C_INTERIX
  	if(dent->d_ino)
 -#endif
  	{
  	    if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") &&
  	    (cli_strbcasestr(dent->d_name, ".db")  ||
@@@ -1013,7 -1019,7 +1019,7 @@@
  		    closedir(dd);
  		    return -1;
  		}
 -		sprintf(dbfile, "%s/%s", dirname, dent->d_name);
 +		sprintf(dbfile, "%s"PATHSEP"%s", dirname, dent->d_name);
  
  		if(listdb(dbfile) == -1) {
  		    mprintf("!listdb: Error listing database %s\n", dbfile);
@@@ -1061,7 -1067,15 +1067,7 @@@ static int listdb(const char *filename
  	free(buffer);
  	fclose(fh);
  
 -	tmpdir = getenv("TMPDIR");
 -	if(tmpdir == NULL)
 -#ifdef P_tmpdir
 -	    tmpdir = P_tmpdir;
 -#else
 -	    tmpdir = "/tmp";
 -#endif
 -
 -	if(!(dir = cli_gentemp(tmpdir))) {
 +	if(!(dir = cli_gentemp(NULL))) {
  	    mprintf("!listdb: Can't generate temporary name\n");
  	    return -1;
  	}
@@@ -1201,6 -1215,7 +1207,7 @@@ static int vbadump(const struct optstru
  	char *dir;
  	const char *pt;
  	struct uniq *vba = NULL;
+ 	cli_ctx ctx;
  
  
      if(optget(opts, "vba-hex")->enabled) {
@@@ -1211,7 -1226,7 +1218,7 @@@
  	pt = optget(opts, "vba")->strarg;
      }
   
 -    if((fd = open(pt, O_RDONLY)) == -1) {
 +    if((fd = open(pt, O_RDONLY|O_BINARY)) == -1) {
  	mprintf("!vbadump: Can't open file %s\n", pt);
  	return -1;
      }
@@@ -1230,7 -1245,18 +1237,18 @@@
          return -1;
      }
  
-     if(cli_ole2_extract(fd, dir, NULL, &vba)) {
+     ctx.fmap = cli_malloc(sizeof(struct F_MAP *));
+     if(!ctx.fmap) {
+ 	printf("malloc failed\n");
+ 	return 1;
+     }
+     *ctx.fmap = fmap(fd, 0, 0);
+     if(*ctx.fmap) {
+ 	printf("fmap failed\n");
+ 	return 1;
+     }
+     
+     if(cli_ole2_extract(dir, NULL, &vba)) {
  	cli_rmdirs(dir);
          free(dir);
  	close(fd);
@@@ -1461,13 -1487,15 +1479,13 @@@ static int dircopy(const char *src, con
      }
  
      while((dent = readdir(dd))) {
 -#if (!defined(C_INTERIX)) && (!defined(C_WINDOWS))
  	if(dent->d_ino)
 -#endif
  	{
  	    if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
  		continue;
  
 -	    snprintf(spath, sizeof(spath), "%s/%s", src, dent->d_name);
 -	    snprintf(dpath, sizeof(dpath), "%s/%s", dest, dent->d_name);
 +	    snprintf(spath, sizeof(spath), "%s"PATHSEP"%s", src, dent->d_name);
 +	    snprintf(dpath, sizeof(dpath), "%s"PATHSEP"%s", dest, dent->d_name);
  
  	    if(filecopy(spath, dpath) == -1) {
  		/* mprintf("!dircopy: Can't copy %s to %s\n", spath, dpath); */
@@@ -1607,12 -1635,14 +1625,12 @@@ static int diffdirs(const char *old, co
      }
  
      while((dent = readdir(dd))) {
 -#ifndef C_INTERIX
  	if(dent->d_ino)
 -#endif
  	{
  	    if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
  		continue;
  
 -	    snprintf(path, sizeof(path), "%s/%s", old, dent->d_name);
 +	    snprintf(path, sizeof(path), "%s"PATHSEP"%s", old, dent->d_name);
  	    if(compare(path, dent->d_name, diff) == -1) {
  		if(chdir(cwd) == -1)
  		    mprintf("^diffdirs: Can't chdir to %s\n", cwd);
@@@ -1633,12 -1663,14 +1651,12 @@@
      }
  
      while((dent = readdir(dd))) {
 -#ifndef C_INTERIX
  	if(dent->d_ino)
 -#endif
  	{
  	    if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
  		continue;
  
 -	    snprintf(path, sizeof(path), "%s/%s", new, dent->d_name);
 +	    snprintf(path, sizeof(path), "%s"PATHSEP"%s", new, dent->d_name);
  	    if(access(path, R_OK))
  		fprintf(diff, "UNLINK %s\n", dent->d_name);
  	}
diff --combined sigtool/vba.c
index f0edeb2,1b6a5da..d3e6219
--- a/sigtool/vba.c
+++ b/sigtool/vba.c
@@@ -17,10 -17,6 +17,10 @@@
   *  MA 02110-1301, USA.
   */
  
 +#if HAVE_CONFIG_H
 +#include "clamav-config.h"
 +#endif
 +
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
@@@ -36,7 -32,10 +36,7 @@@
  #include "libclamav/others.h"
  #include "libclamav/cltypes.h"
  #include "libclamav/ole2_extract.h"
 -
 -#ifndef	O_BINARY
 -#define	O_BINARY	0
 -#endif
 +#include "shared/output.h"
  
  typedef struct mac_token_tag
  {
@@@ -967,6 -966,7 +967,7 @@@ static int sigtool_scandir (const char 
      const char *tmpdir;
      char *dir;
      int ret = CL_CLEAN, desc;
+     cli_ctx ctx;
  
  
      if ((dd = opendir (dirname)) != NULL) {
@@@ -975,7 -975,7 +976,7 @@@
  		if (strcmp (dent->d_name, ".") && strcmp (dent->d_name, "..")) {
  		    /* build the full name */
  		    fname = (char *) cli_calloc (strlen (dirname) + strlen (dent->d_name) + 2, sizeof (char));
 -		    sprintf (fname, "%s/%s", dirname, dent->d_name);
 +		    sprintf (fname, "%s"PATHSEP"%s", dirname, dent->d_name);
  
  		    /* stat the file */
  		    if (lstat (fname, &statbuf) != -1) {
@@@ -988,7 -988,14 +989,7 @@@
  			} else {
  			    if (S_ISREG (statbuf.st_mode)) {
  			        struct uniq *vba = NULL;
 -				tmpdir = getenv ("TMPDIR");
 -
 -				if (tmpdir == NULL)
 -#ifdef P_tmpdir
 -				    tmpdir = P_tmpdir;
 -#else
 -				    tmpdir = "/tmp";
 -#endif
 +				tmpdir = cli_gettmpdir();
  
  				/* generate the temporary directory */
  				dir = cli_gentemp (tmpdir);
@@@ -997,12 -1004,22 +998,22 @@@
  				    return CL_ETMPDIR;
  				}
  
 -				if ((desc = open (fname, O_RDONLY)) == -1) {
 +				if ((desc = open (fname, O_RDONLY|O_BINARY)) == -1) {
  				    printf ("Can't open file %s\n", fname);
  				    return 1;
  				}
  
- 				if ((ret = cli_ole2_extract (desc, dir, NULL, &vba))) {
+ 				ctx.fmap = cli_malloc(sizeof(struct F_MAP *));
+ 				if(!ctx.fmap) {
+ 				    printf("malloc failed\n");
+ 				    return 1;
+ 				}
+ 				*ctx.fmap = fmap(desc, 0, 0);
+ 				if(*ctx.fmap) {
+ 				    printf("fmap failed\n");
+ 				    return 1;
+ 				}
+ 				if ((ret = cli_ole2_extract (dir, &ctx, &vba))) {
  				    printf ("ERROR %s\n", cl_strerror (ret));
  				    cli_rmdirs (dir);
  				    free (dir);
@@@ -1011,9 -1028,11 +1022,11 @@@
  
  				if(vba)
  				    sigtool_vba_scandir (dir, hex_output, vba);
- 
  				cli_rmdirs (dir);
  				free (dir);
+ 				funmap(*ctx.fmap);
+ 				free(ctx.fmap);
+ 				close(desc);
  			    }
  			}
  
@@@ -1023,7 -1042,7 +1036,7 @@@
  	    }
  	}
      } else {
 -	cli_errmsg ("Can't open directory %s.\n", dirname);
 +	logg("!Can't open directory %s.\n", dirname);
  	return CL_EOPEN;
      }
  
@@@ -1048,7 -1067,7 +1061,7 @@@ int sigtool_vba_scandir (const char *di
  
  	for(i = 0; i < vba_project->count; i++) {
  	    for(j = 0; j < vba_project->colls[i]; j++) {
 -		snprintf(vbaname, 1024, "%s/%s_%u", vba_project->dir, vba_project->name[i], j);
 +		snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", vba_project->dir, vba_project->name[i], j);
  		vbaname[sizeof(vbaname)-1] = '\0';
  		fd = open(vbaname, O_RDONLY|O_BINARY);
  		if(fd == -1) continue;
@@@ -1074,7 -1093,7 +1087,7 @@@
  
      if((hashcnt = uniq_get(U, "powerpoint document", 19, &hash))) {
  	while(hashcnt--) {
 -	    snprintf(vbaname, 1024, "%s/%s_%u", dirname, hash, hashcnt);
 +	    snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
  	    vbaname[sizeof(vbaname)-1] = '\0';
  	    fd = open(vbaname, O_RDONLY|O_BINARY);
  	    if (fd == -1) continue;
@@@ -1090,7 -1109,7 +1103,7 @@@
  
      if ((hashcnt = uniq_get(U, "worddocument", 12, &hash))) {
  	while(hashcnt--) {
 -	    snprintf(vbaname, sizeof(vbaname), "%s/%s_%u", dirname, hash, hashcnt);
 +	    snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
  	    vbaname[sizeof(vbaname)-1] = '\0';
  	    fd = open(vbaname, O_RDONLY|O_BINARY);
  	    if (fd == -1) continue;
@@@ -1128,7 -1147,7 +1141,7 @@@
  		if (strcmp (dent->d_name, ".") && strcmp (dent->d_name, "..")) {
  		    /* build the full name */
  		    fullname = calloc (strlen (dirname) + strlen (dent->d_name) + 2, sizeof (char));
 -		    sprintf (fullname, "%s/%s", dirname, dent->d_name);
 +		    sprintf (fullname, "%s"PATHSEP"%s", dirname, dent->d_name);
  
  		    /* stat the file */
  		    if (lstat (fullname, &statbuf) != -1) {
@@@ -1140,7 -1159,7 +1153,7 @@@
  	    }
  	}
      } else {
 -	cli_errmsg ("ScanDir -> Can't open directory %s.\n", dirname);
 +	logg("!ScanDir -> Can't open directory %s.\n", dirname);
  	return CL_EOPEN;
      }
  

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list