/*==============================================================================

FICHIER     : [systools.c]

DATE        : 2005/12/0005 21:58:43

CREATEUR    : [Linux!jef]

COMMENTAIRE :
		Released under GPL license, see gnu.org
================================================================================

==============================================================================*/
#define __USE_LARGEFILE64
#define _LARGEFILE64_SOURCE
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#if defined(__sun)
#	include <sys/statvfs.h>
#	include <sys/ioctl.h>
#elif defined(__APPLE__)
#   include <sys/mount.h>
#else
#	include <sys/statfs.h>
#	include <sys/ioctl.h>
#endif
#include <fcntl.h>
#include <unistd.h>
#if defined(__sun)
#	include <stropts.h>
#endif
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#if defined(__sun)
#	include <sys/cdio.h>
#	define NON_BLOCKING
#elif defined(__APPLE__)
// TODO: DVD tests not properly implemented yet for Mac OS X
#else
#	include <sys/sysinfo.h>
#	include <linux/cdrom.h>
#	include <linux/loop.h>
#endif
#include <ctype.h>

#include "support.h"
#include "systools.h"

#define CTEST(x)		/* Traces futiles */

char ** environ;
#define	SH_PATH	"/bin/sh"
#define	SH_NAME	"sh"

/* Structure describing a popen child.  */
struct child
{
	int fd;
	int pid;
} Child;

#define PATHCHR		':'
#define SEPCHAR		'/'

/*@$#[systools.c] static proto. AutoProtoSigV1.1. date: 2009/02/04 23:22:17 */
#include "proto.h"
#ifdef __cplusplus
extern "C" {
#endif
/* systools.c */
static GSList *testAndAppend PROTO((GSList *list, char *devName));
#ifdef __cplusplus
}
#endif
/*@$% end of AutoProtoSigV1.1 (Dont remove this line) [-I ../include]*/

/*------------------------------------------------------------------------------
	MKFIFO-
Linux!jef 2005/12/05 21:59:11
------------------------------------------------------------------------------*/

int MkFifo( fifoName )
char * fifoName;
{
	return( mknod( fifoName, S_IFIFO | 0666, 0 ) ? -1 : 0 );
}
/*------------------------------------------------------------------------------
	DELFIFO-
Linux!jef 2005/12/05 22:00:27
------------------------------------------------------------------------------*/

int DelFifo( fifoName )
char * fifoName;
{
	unlink( fifoName );
	return( 0 );
}

/*------------------------------------------------------------------------------
	FILESTAT64-
Linux!jef 2005/12/16 21:19:35
------------------------------------------------------------------------------*/

long long FileSize64( char * fileName )
{
	struct stat64 bstat;
	int res;

	res = stat64( fileName, &bstat );
	if( res < 0 )	return( 0LL );
// fprintf(stderr,"sizeof(bstat.st_size)=%d := %lld\n", sizeof(bstat.st_size), bstat.st_size );
	return( (long long)bstat.st_size );
}

/*------------------------------------------------------------------------------
	LLSIZE2GIGA-
Linux!jef 2005/12/16 22:22:31
------------------------------------------------------------------------------*/

char * LLSize2Giga( long long size )
{
	static char string[200];
	double g;

// fprintf(stderr,"Size: %lld\n", size );

	g = (double)size / ( 1024.0 * 1024.0 * 1024.0 );
	if( g >= 1.0 ) {
		sprintf( string,_("%.2f gigas"), g );
	}
	else {
		g = (double)size / ( 1024.0 * 1024.0 );
		if( g >= 1.0 ) {
			sprintf( string,_("%.2f megas"), g );
		}
		else {
			g = (double)size / ( 1024.0 );
			sprintf( string,_("%.2f kilos"), g );
		}
	}
	return( string );
}

/*------------------------------------------------------------------------------
	FLOOK-
JEF!jef 95/02/02 15:17:26
------------------------------------------------------------------------------*/
int flook( fname )
char *fname;
{
	char *path;	/* environmental PATH variable */
	char *sp;	/* pointer into path spec */
	char fspec[512];	/* full path spec to search */


	if( *fname == '/' ) {
		if( access( fname, 1 ) == 0 )	return( 1 );
// fprintf(stderr,"%s: is regular file !\n", fname );
		return( 0 );
	}
	/* get the PATH variable */
	path = getenv("PATH");
	if( path ) {
		while (*path) {

			/* build next possible file spec */
			sp = fspec;
			while (*path && (*path != PATHCHR))
				*sp++ = *path++;

			/* add a terminating dir separator if we need it */
			if (sp[-1] != SEPCHAR)
				*sp++ = SEPCHAR;

			*sp = 0;
			strcat(fspec, fname);
// fprintf(stderr,"Trying: (%s)\n",fspec);
			/* and try it out */
			if( access( fspec, 1 ) == 0 )
				return(1);
			if (*path == PATHCHR)
				++path;
		}
	}
	return(0);	/* no such luck */
}
/*------------------------------------------------------------------------------
	FSFREE-
Linux!jef 2005/12/19 20:57:02
------------------------------------------------------------------------------*/

long long FsFree( char * fsName )
{
#if defined(__sun)
        struct statvfs b;
	int res;
	long long freeSize;

        res = statvfs( fsName, &b);
	if( res < 0 )	return( 0LL );
	freeSize = ((long long)b.f_bavail * (long long)b.f_bsize);

	return( freeSize );
#else
	struct statfs b;
	int res;
	long long freeSize;

	res = statfs( fsName, &b );
	if( res < 0 )	return( 0LL );
	freeSize = ((long long)b.f_bavail * (long long)b.f_bsize);
// fprintf(stderr,"avail: %ld bsize: %ld = %lld\n", b.f_bavail,  b.f_bsize, freeSize );
	return( freeSize );
#endif
}
/*------------------------------------------------------------------------------
	DIREXIST-
Linux!jef 2006/01/31 20:46:19
------------------------------------------------------------------------------*/

int DirExist( char * dirName )
{
	struct stat bStat;
	int res;

	res = stat( dirName, &bStat );
// fprintf(stderr,"%s: res=%d\n", dirName, res );
	if( res )	return( 0 );
	if( S_ISDIR( bStat.st_mode ) )	return( 1 );
	return( -1 );
}

/***************************************************************************//**
 *	DIRCANWRITE-
 * @date	2009/07/07 22:22:21
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/
int DirCanWrite( char * dirname )
{
	if( access( dirname, W_OK ) )	return( -1 );
	return( 0 );
}

/*------------------------------------------------------------------------------
	FILEEXIST-
Linux!jef 2006/01/31 21:02:35
------------------------------------------------------------------------------*/

int FileExist( char * fileName )
{
	struct stat64 bStat;
	int res;

	res = stat64( fileName, &bStat );
// fprintf(stderr,"%s(%s) = %d errno: %d\n", __FUNCTION__,fileName, res, errno );
	if( res )	return( 0 );
	if( S_ISREG( bStat.st_mode ) )	return( 1 );
	if( S_ISBLK( bStat.st_mode ) )	return( 2 );
	return( -1 );
}

/*------------------------------------------------------------------------------
	IsDvdDevice-
------------------------------------------------------------------------------*/

int IsDvdDevice( char * fileName )
{
	struct stat64 bStat;
	int res;

	res = stat64( fileName, &bStat );
// fprintf(stderr,"%s(%s) = %d errno: %d\n", __FUNCTION__,fileName, res, errno );
	if( res )	return( 0 );
	if( S_ISREG( bStat.st_mode ) )	return( 1 );
	if( S_ISBLK( bStat.st_mode ) )	return( 2 );
#ifdef __APPLE__
	if ( strncmp("/dev/", fileName, 5) == 0) return 2;
	return 2;
#endif

	return( -1 );
}

/*------------------------------------------------------------------------------
	MY_POPEN-
JEF!jef 95/09/26 14:29:09
	Open a new stream that is a one-way pipe to a
	child process running the given shell command.
------------------------------------------------------------------------------*/
FILE * my_popen( command, mode)
char * command;
char * mode;
{
	int pid;
	int pipedes[2];
	FILE * stream;

	if (command == NULL || mode == NULL || (*mode != 'r' && *mode != 'w'))
	{
		errno = EINVAL;
		return NULL;
	}

  /* Create the pipe.  */
	if( pipe(pipedes) < 0)
		return NULL;

  /* Fork off the child.  */
	pid = fork();
	if( pid == -1)
	{
/* The fork failed.  */
		close(pipedes[0]);
		close(pipedes[1]);
		return( NULL );
	}
	else {
		if( !pid )
		{
			char *new_argv[4];
			int res;

			signal( SIGHUP, SIG_DFL );
			signal( SIGTERM, SIG_DFL );
			signal( SIGINT, SIG_DFL );
			signal( SIGQUIT, SIG_DFL );
			if( *mode == 'w' ) {
				res = dup2( pipedes[0] , 0 );
			}
			else {
				res = dup2( pipedes[1] , 1 );
/* Ajout Stderr */
				res |= dup2( pipedes[1] , 2 );
			}
			if( res < 0 )	_exit( 127 );

      /* Close the pipe descriptors.  */
			close(pipedes[0]);
			close(pipedes[1]);

      /* Exec the shell.  */
			new_argv[0] = SH_NAME;
			new_argv[1] = "-c";
			new_argv[2] = command;
			new_argv[3] = NULL;
			(void) execve(	SH_PATH,
					(const char **) new_argv,
					(const char **)environ);
			/* Die if it failed.  */
			_exit(127);
		}
	}
  /* We are the parent side.  */

  /* Close the irrelevant side of the pipe and open the relevant side as a
     new stream.  Mark our side of the pipe to close on exec, so new children
     won't see it.  */
	if( *mode == 'r')
	{
		close(pipedes[1]);
		fcntl( pipedes[0], F_SETFD, FD_CLOEXEC);
		stream = fdopen(pipedes[0], mode);
	}
	else {
		close(pipedes[0]);
		fcntl( pipedes[1], F_SETFD, FD_CLOEXEC);
		stream = fdopen(1, mode);
	}

	if( !stream )
		goto error;

	memset( &Child , 0 , sizeof( Child ));
	Child.fd = fileno(stream);
	Child.pid = pid;
	setvbuf( stream , NULL,_IOFBF,0 );
	return( stream );

error:;
	{
		int save = errno;

		kill(pid, SIGKILL);
		if( !stream )
			close(pipedes[*mode == 'r' ? 1 : 0]);
		else
			fclose(stream);
		{
			int dead;
			do
				dead = wait ((int *) NULL);
			while (dead > 0 && dead != pid);
		}
		errno = save;
		return NULL;
	}
}

/* Close a stream opened by popen and return its status.
   Returns -1 if the stream was not opened by popen.  */
int my_pclose( stream )
FILE *stream;
{
	int pid, dead;
	int status;
	pid = Child.pid;

// fprintf(stderr,"killing: %d\n", pid );

	status = kill( pid, SIGHUP );
	if( fclose(stream) )
		return( -1 );
	do
		dead = wait (&status);
	while (dead > 0 && dead != pid);
	if (dead != pid)
		status = -1;
	return( status );
}
/*------------------------------------------------------------------------------
	DUREE2STRING-
Linux!jef 2006/11/06 22:32:50
------------------------------------------------------------------------------*/

char * Duree2String( int duree )
{
	static char result[100];
	int h,m,s;

	h = duree / 3600;
	duree -= h * 3600;
	m = duree / 60;
	duree -= m * 60;
	s = duree;

	sprintf( result, "%02dh%02dm%02ds", h, m, s );
	return( result );
}
/*------------------------------------------------------------------------------
	ADDSTRING2LIST-
Linux!jef 2007/01/19 22:06:45
------------------------------------------------------------------------------*/

char * AddString2List( char * list, char * string )
{
	char * newList;

	if( strstr( list, string ) ) {
		return( strdup( list ));
	}
	newList = alloca( strlen( list ) + strlen( string ) + 1 + 1 );
	strcpy( newList, list );
	if( *newList ) {
		strcat( newList, "," );
	}
	strcat( newList, string );
	return( strdup( newList ) );
}
/*------------------------------------------------------------------------------
	REMOVESTRINGFROMLIST-
Linux!jef 2007/01/19 22:08:50
------------------------------------------------------------------------------*/

char * RemoveStringFromList( char * list, char * string )
{
	char * newList;
	char * temp;
	char * tok;

	if( !strstr( list, string ) ) {
		return( strdup( list ));
	}
	newList = alloca( strlen( list ) + 1 );
	*newList = 0;
	temp = alloca( strlen( list ) + 1 );
	strcpy( temp, list );
	tok = strtok( temp, "," );
	while( tok ) {
		if( strcmp( tok, string ) ) {
			if( *newList )	strcat( newList, "," );
			strcat( newList, tok );
		}
		tok = strtok( NULL, "," );
	}
	return( strdup( newList ) );
}
/*------------------------------------------------------------------------------
	MAKEDIRIFNEEDED-
Linux!jef 2007/01/23 23:05:51
------------------------------------------------------------------------------*/

int MakeDirIfNeeded( char * path )
{
	struct stat64 bStat;
	int res;

	res = stat64( path, &bStat );
// fprintf(stderr,"%s(%s) = %d errno: %d\n", __FUNCTION__,fileName, res, errno );
	if( !res && S_ISDIR( bStat.st_mode ) )	return( 0 );
	return( mkdir( path, 0777 ) );
}


/*------------------------------------------------------------------------------
	ISDVDLOADED-
Linux!jef 2007/01/09 22:13:37
------------------------------------------------------------------------------*/

int IsDvdLoaded( char * device )
{
	int fd;
	int ret;
	struct stat64 b;
#if !defined(__sun) && !defined(__APPLE__)
	struct loop_info lInfo;
#endif
// fprintf(stderr,"%s(%s)\n", __FUNCTION__, device );
	if( stat64( device, &b) ) {
// perror( device );
		return( -1 );
	}
/* If this is a VIDEO STRUCTURE go-on */
	if( S_ISDIR( b.st_mode ) )	return( 1 );

	if( S_ISREG( b.st_mode ) )	return( 1 );
	fd = open( device, O_RDONLY | O_NONBLOCK);
	if( fd < 0 ) {
// perror( "open" );
		return( -1 );
	}
#if defined (__sun)
	struct cdrom_tochdr cdth;
	ret = ioctl( fd, CDROMREADTOCHDR, &cdth);
	if( cdth.cdth_trk1 > 0 ) {
		close( fd );
		return( 1 );
	}
#elif defined (__APPLE__)
	close( fd );
	return( 1 );
#else
	ret = ioctl( fd,  CDROM_DRIVE_STATUS, CDSL_CURRENT);
	if( ret == CDS_DISC_OK ) {
		close( fd );
		return( 1 );
	}
	/* Try to know if it is a loop device */
	ret = ioctl( fd, LOOP_GET_STATUS, &lInfo );
	close( fd );
	if( !ret )	return( 1 );
	close( fd );
#endif
	return( 0 );
}
/*------------------------------------------------------------------------------
	STRINGDUREE2SEC-
Linux!jef 2007/01/30 22:07:02
------------------------------------------------------------------------------*/

int StringDuree2Sec( char * string )
{
	int sec = 0;
	int acc = 0;

	while( *string ) {
		if( isdigit( *string ) ) {
			acc *= 10;
			acc += *string - '0';
		}
		else {
			if( tolower( *string ) == 'h' ) { sec += acc * 3600; acc = 0; }
			if( tolower( *string ) == 'm' ) { sec += acc * 60; acc = 0; }
			if( tolower( *string ) == 's' ) { sec += acc     ; acc = 0; }
		}
		string++;
	}
	return( sec );
}
/*------------------------------------------------------------------------------
	ISLOOPDEVICEREADY-
Linux!jef 2007/02/12 20:55:27
------------------------------------------------------------------------------*/

int IsLoopDeviceReady( char * loopDevice )
{
#if !defined(__sun) && !defined(__APPLE__)
	struct loop_info lInfo;
	int fd;
	int ret;

	fd = open( loopDevice, O_RDONLY | O_NONBLOCK);
	if( fd < 0 )	return( 0 );
	ret = ioctl( fd, LOOP_GET_STATUS, &lInfo );
// fprintf(stderr,"(%s)=%d lInfo.lo_name(%s)\n", loopDevice, ret,lInfo.lo_name );
	close( fd );
	if( !ret )	return( 1 );
#endif
	return( 0 );
}

/*------------------------------------------------------------------------------
+	GETDEVICES-
+    get list of available DVD devices as glib single linked list
+------------------------------------------------------------------------------*/
static GSList * testAndAppend( GSList *list, char *devName )
{
	if( FileExist( devName ) == 2 ){
		char *nameCopy = malloc (strlen(devName)+1);
		if (nameCopy){
			strcpy(nameCopy, devName);
			list = g_slist_append( list, nameCopy);
			CTEST(fprintf(stderr,"Found device %s\n", nameCopy););
		}
	}
	return( list );
}
/***************************************************************************//**
 *	FREEDEVICES-
 * @date	2008/07/16 22:41:59
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/

void freeDevices( GSList * list )
{
	GSList * head = list;

	while( list ) {
		GSList * next = list->next;
		if( list->data ) free( list->data );
		list = next;
	}
	g_slist_free( head );
}
/***************************************************************************//**
 *	GETDEVICES-
 * @date	2008/07/16 22:41:29
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/

#ifndef __APPLE__
GSList *getDevices( void )
{
	int i;
	char devName[100];
	GSList *list = NULL;

	list = testAndAppend( list, "/dev/dvd" );

/* Ide cdrom/dvdrom devices */
	for( i = 0; i < 26; i++ ) {
		sprintf( devName, "/dev/hd%c", 'a'+i );
		list = testAndAppend( list, devName );
	}
/* Scsi cdrom/dvdrom devices */
	for( i = 0; i < 10; i++ ) {
		sprintf( devName, "/dev/sr%d", i );
		list = testAndAppend( list, devName );
	}
	for( i = 0; i < 10; i++ ) {
		sprintf( devName, "/dev/scd%d", i );
		list = testAndAppend( list, devName );
	}
/* Loop devices */
	for( i = 0; i < 10; i++ ) {
		sprintf( devName, "/dev/loop%d", i );
		if( FileExist( devName ) == 2 && IsLoopDeviceReady( devName ) ) {
			list = testAndAppend( list, devName );
		}
	}
	return( list );
}
#else /* __APPLE__ */
#include <stdio.h>
#include <string.h>

#include <paths.h>
#include <sys/param.h>

#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>

char deviceFilePath[MAXPATHLEN]; //MAXPATHLEN is defined in sys/param.h

int getBSDnameForDVDService( io_object_t device, char *path)
{
	CFTypeRef deviceNameAsCFString = NULL;
	Boolean gotString = false;
	size_t devPathLength;

	/* the DVD drive is the child of the IODVDBlockStorageDriver child */
	io_iterator_t children;
	kern_return_t krc = IORegistryEntryGetChildIterator(device, kIOServicePlane, &children);
	if (krc == KERN_SUCCESS) {
		io_service_t child;
		while ((child = IOIteratorNext(children)))
		{
			io_string_t type;

			IOObjectGetClass(child, type);
			if (strcmp( type, "IODVDBlockStorageDriver") == 0){
				io_service_t drive;
				IORegistryEntryGetChildEntry(child, kIOServicePlane, &drive);
				if (child){
					deviceNameAsCFString = IORegistryEntryCreateCFProperty( drive, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, kNilOptions);
				}
			}
			IOObjectRelease(child);
		}
		IOObjectRelease(children);
	}
	if (deviceNameAsCFString) {
		path[0] = '\0';
		devPathLength = strlen(_PATH_DEV); //_PATH_DEV is defined in paths.h
		strcpy(path, _PATH_DEV);
		strcat(path,"r"); // dvds have to be opened in "r"aw mode
		gotString = CFStringGetCString( deviceNameAsCFString, path + strlen(path), MAXPATHLEN - strlen(deviceFilePath), kCFStringEncodingASCII);
	}
	if (gotString) {
		// printf("Device file path: %s\n", path);
		//deviceFilePath will look something like /dev/rdisk1
		return 0;
	}
	return -1;
}

/*
* Find all DVD drives
*/

GSList *getDevices(void)
{
	GSList *list = NULL;

/*
* Create a matching dictionary to search for DVD services in the IOKit.
*/
	CFMutableDictionaryRef RefMatchingDict = IOServiceMatching("IODVDServices");
	if (RefMatchingDict == NULL){
		// no dvd drives found
		return list;
	}

/*
* Get a collection of DVD services.
*/
	io_iterator_t DVDServices = 0;
	IOReturn rc = IOServiceGetMatchingServices(kIOMasterPortDefault, RefMatchingDict, &DVDServices);

	io_object_t DVDService;
	while ((DVDService = IOIteratorNext(DVDServices)) != 0)
	{
		if (getBSDnameForDVDService( DVDService, deviceFilePath ) >= 0){
			char *nameCopy = malloc (strlen(deviceFilePath)+1);
			if (nameCopy){
				strcpy(nameCopy, deviceFilePath);
				list = g_slist_append( list, nameCopy);
				CTEST(fprintf(stderr,"Found device %s\n", nameCopy););
			}
		}
		IOObjectRelease(DVDService);
	}
	IOObjectRelease(DVDServices);

	return list;
}
#endif
/***************************************************************************//**
 *	GETNUMCPU-
 * @date	2009/01/15 23:40:20
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/

int GetNumCpu()
{
	int	numcpu = sysconf( _SC_NPROCESSORS_ONLN );

	if( numcpu < 1 )        numcpu = 1;
	return( numcpu );
}
/***************************************************************************//**
 *	CANCREATEFILE-
 * @date	2009/01/27 23:05:23
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/

int CanCreateFile( char * dirName )
{
	char * fName = alloca( strlen(dirName) + 1 + strlen( ".dvd95" ) + 1 );
	FILE * fp;

	sprintf( fName, "%s/.dvd95", dirName );
	fp = fopen( fName, "w" );
	if( !fp )	return( 0 );
	fclose( fp );
	unlink( fName );
	return( 1 );
}
/***************************************************************************//**
 *	GETMKISOTOOL-
 * @date	2009/01/29 21:28:00
 * @author	jef-Linux
 * @brief
 *	Return ISO builder tool name
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/

char * GetMkIsoTool()
{
	if( flook( "genisoimage" ) )	return( "genisoimage" );
	return( "mkisofs" );
}

/***************************************************************************//**
 *	GETENV-
 * @date	2009/07/07 21:52:07
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/
char * GetEnv( char * evKey, char * defValue )
{
	char * envValue = getenv( evKey );
	if( envValue )	return( envValue );
	return( defValue );
}

/***************************************************************************//**
 *	STARTTIMER-
 * @date	2010/02/02 22:07:35
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/
Timer_t * StartTimer()
{
	Timer_t * new =(Timer_t *)malloc( sizeof(*new ));
	gettimeofday( &new->StartTime, NULL );
	return( new );
}

/***************************************************************************//**
 *	STOPTIMER-
 * @date	2010/02/02 22:08:59
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/
void StopTimer( Timer_t * timer )
{
	if( timer )	gettimeofday( &timer->EndTime, NULL );
}

/***************************************************************************//**
 *	ELAPSEDTIMER-
 * @date	2010/02/02 22:10:11
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/
double ElapsedTimer( Timer_t * timer )
{
	double elapsedTime;

	if( !timer )	return( 0 );
	elapsedTime = timer->EndTime.tv_sec - timer->StartTime.tv_sec;
	elapsedTime += (double)(timer->EndTime.tv_usec - timer->StartTime.tv_usec) / 1000000.0;
	return( elapsedTime );
}
/***************************************************************************//**
 *	FREETIMER-
 * @date	2010/02/02 22:10:59
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/
void FreeTimer( Timer_t * timer )
{
	if( timer )	free( timer );
}
/***************************************************************************//**
 *	CPUPHYSMEMSIZE-
 * @date	2010/02/04 20:49:56
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/
long long CpuPhysMemSize()
{
	double pSize = 0;
#ifdef linux
	struct sysinfo info;

	if( sysinfo( &info ) >= 0 ) {
// Broken sur kernel >= 2.4.0	pSize = info.freeram + info.bufferram + info.sharedram;
#if	LINUX_VERSION_CODE >= 0x020400
		pSize = (double)info.totalram * (double)info.mem_unit;
#else
		pSize = (double)info.totalram;
#endif
	}
#else
#ifdef __FreeBSD__
#include <sys/types.h>
#include <sys/sysctl.h>
	{
		int mib[2];
		int msize;
		size_t len;

		mib[0] = CTL_HW;
		mib[1] = HW_USERMEM;
		len = sizeof(msize);
		sysctl(mib, 2, &msize, &len, NULL, 0);
		pSize = msize;
	}
#endif
#endif
	if( pSize <= 0 )	pSize = 512.0 * 1024.0 * 1024.0;
	return( (long long)pSize );
}
/***************************************************************************//**
 *	BURNTOOL-
 * @date	2010/05/28 22:13:28
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/
int BurnTool()
{
	if( flook( "k3b" ) )		return( BURNTOOL_K3B );
	if( flook( "brasero" ) ) 	return( BURNTOOL_BRASERO );
	return( BURNTOOL_NONE );
}
/***************************************************************************//**
 *	BURNISOFILE-
 * @date	2010/05/28 21:03:36
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/
int BurnIsoFile( int tool, char * device, char * isoFile )
{
	char sysCmd[1024];
	int res;

	sprintf( sysCmd, "eject %s", device );
	res = system( sysCmd );
	if( tool == BURNTOOL_K3B ) {
		sprintf( sysCmd,"k3b \"%s\" -cdimage", isoFile );/*FIXME: verify ! */
		res = system( sysCmd );
		return( res );
	}
	if( tool == BURNTOOL_BRASERO) {
		sprintf( sysCmd,"brasero -i \"%s\"", isoFile );
		res = system( sysCmd );
		return( res );
	}
	return( -1 );
}
/***************************************************************************//**
 *	BURNVIDEODIR-
 * @date	2010/05/28 21:03:36
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/
int BurnVideoDir( int tool, char * device, char * videoDir )
{
	char sysCmd[1024];
	int res;

	sprintf( sysCmd, "eject %s", device );
	res = system( sysCmd );
	if( tool == BURNTOOL_K3B ) {
		sprintf( sysCmd,"k3b \"%s/VIDEO_TS\" -videodvd", videoDir );
		res = system( sysCmd );
		return( res ? -1 : 0 );
	}
/*FIXME: howto in brasero !*/
	return( -1 );
}
