/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

***************************************************************************/


#include <ddiommap.h>


/**
	Default constructor.
*/

ddiommap::ddiommap()
:	ddiobuffer()
{

}


/**
	Copy construtor
*/

ddiommap::ddiommap( const ddiommap& src)
: ddiobuffer()
{
	*this = src;
}


/**
	Standard constructor. Create a mmap object from file "filename"
	with following defaultprotocol: PROT_READ
	@param filename
	@param prot
	@see man mmap for more information about prot.
*/

ddiommap::ddiommap( const ddstring& filename, int prot )
:	ddiobuffer()
{
	mmap( filename, prot );
}


/**
	Assignment operator. Dummy implementation. Does nothing yet.
*/

ddiommap& ddiommap::operator=( const ddiommap& src )
{
	if( this == &src )
		return *this;
	log_fatal( "ddiommap::operator=" );
	return *this;
}


/**
	Destructor. Unmaps this mmap.
*/


ddiommap::~ddiommap()
{
	unmap();
}


/**
	Map the file "filename" into memory using flags "prot".
	If a file has been mapped before, its unmapped first.
	@param filename
	@param prot	default:PROT_READ
	@return the size of the mapped memblock.
*/

int ddiommap::mmap( const ddstring& filename, int prot )
{
   if( _data != 0 )
		unmap();

	int fd = ::open( filename.c_str(), O_RDONLY );
	if( fd<0 )
	{
		log_error( "ddiommap: can't open: " + filename );
		return -1;
	}

	struct stat file;
	if( ::fstat( fd, &file ) < 0 )
	{
		log_error( "ddiommap: can't stat: " + filename );
		::close( fd );
		return -1;
	}

  if( S_ISDIR( file.st_mode ) )
	{
		log_error( "ddiommap: can't mmap dirs: " + filename );
		::close( fd );
		return 0;
	}

	_size = file.st_size;
	// leere files sind kein Fehler!
	if( !_size )
	{
		//log_error( "ddiommap: file empty: " + filename );
		::close( fd );
		return 0;
	}
	_data = (char*) ::mmap( 0, _size, prot, MAP_PRIVATE, fd, 0 );
	if( MAP_FAILED == _data )
	{
		log_error( "ddiommap: can't mmap: " + filename );
		::close( fd );
		_data = 0;
		return -1;
	}

	::close(fd);
	
	// set read buf to "full", so that max_output() == size()
	_input_offset = _size;
	return _size;
}


/**
	Unmaps the memblock by calling ::munmap.
	@return -1 on error, 0 on success
*/

void ddiommap::unmap()
{
	if( !_data )
		return;
	if( ::munmap( _data, _size ) < 0 )
		log_error( "ddiommap: can't munmap" );
	_data = 0;
}




/**
	Dumps the contents of the data buffer for debugging.	
*/

void ddiommap::dump() const
{
	if( _size )
		::write( 1, _data, _size );
	else
		cout <<  "ddiommap.dump(): not valid!" << endl;

}

