reman3/Rayman_X/cpa/Appli/VersMngr/SaveMngr.cpp

468 lines
14 KiB
C++

/*
=======================================================================================
Name :SaveMngr.cpp
Author :Vincent Lhullier Date :11/07/97
Description :manage save of data before modification
Create a copy of GameData tree with all file that would be modified. That will allow
someone to recuperate previous version if save generate some problem in data.
=======================================================================================
Modification -> Author : Date :
Description :
=======================================================================================
*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#include "stdafx.h"
#include <io.h>
#include <sys/stat.h>
#include "SaveMngr.h"
//#include "acp_base.h"
//#include "itf/CPAProj.hpp"
//#include "DPT.h"
//#include "SCR.h"
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*
=======================================================================================
GLOBALS
=======================================================================================
*/
static char SAVE_g_szDirName[ _MAX_PATH ];
static char SAVE_g_szTargetDirName[ _MAX_PATH ];
/*
=======================================================================================
=======================================================================================
FUNCTIONS
=======================================================================================
=======================================================================================
*/
char *fn_szGetGameDataPath( void )
{
return "GameData";
}
/*
=======================================================================================
Directory Functions
=======================================================================================
*/
/*
----------------------------------------------------------------------------------------
Don't call this function directly, it is used by SAVE_fn_bDeleteTree
Description : delete recursively a directory
Returns (BOOL ) true if success
----------------------------------------------------------------------------------------
*/
BOOL fn_bDeleteTree( void )
{
WIN32_FIND_DATA stFindData;
HANDLE hFind;
char *p_szEndDirName;
p_szEndDirName = SAVE_g_szDirName + strlen( SAVE_g_szDirName );
strcpy( p_szEndDirName, "\\*.*" );
if( (hFind = FindFirstFile(SAVE_g_szDirName, &stFindData )) == INVALID_HANDLE_VALUE)
return TRUE;
*p_szEndDirName = 0;
do
{
*p_szEndDirName = '\\';
strcpy( p_szEndDirName + 1, stFindData.cFileName );
if ( stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
if ( *stFindData.cFileName != '.')
{
if ( !fn_bDeleteTree() )
return FALSE;
}
}
else
{
if (_access( SAVE_g_szDirName, 2) == -1 )
_chmod( SAVE_g_szDirName, _S_IWRITE );
if ( !DeleteFile( SAVE_g_szDirName ) )
return FALSE;
}
*p_szEndDirName = 0;
} while(FindNextFile( hFind, &stFindData ));
FindClose( hFind );
return RemoveDirectory( SAVE_g_szDirName );
}
/*
----------------------------------------------------------------------------------------
Description : delete completely a directory
szDirName -> name of dir to delete
Returns (BOOL ) true if success
----------------------------------------------------------------------------------------
*/
BOOL SAVE_fn_bDeleteTree( char *szDirName )
{
strcpy( SAVE_g_szDirName, szDirName );
return fn_bDeleteTree();
}
/*
----------------------------------------------------------------------------------------
Description : create a directory
szDirName -> name of directory
Returns (BOOL ) true if sucess
----------------------------------------------------------------------------------------
*/
BOOL SAVE_fn_bCreateDirectory( char *szDirName )
{
if ( (!CreateDirectory( szDirName, NULL )) && (GetLastError() != ERROR_ALREADY_EXISTS) )
{
char *p_szCur;
p_szCur = strchr( szDirName, '\\');
while (p_szCur != NULL)
{
*p_szCur = 0;
if ((!CreateDirectory (szDirName, NULL)) && (GetLastError() != ERROR_ALREADY_EXISTS) )
{
char szMessage[ 512 ];
sprintf( szMessage, "Can't create local path %s", szDirName );
SAVE_fn_vErrorMessage( szMessage );
return FALSE;
}
*p_szCur++ = '\\';
p_szCur = strchr( p_szCur, '\\');
};
if ((!CreateDirectory (szDirName, NULL)) && (GetLastError() != ERROR_ALREADY_EXISTS) )
{
char szMessage[ 512 ];
sprintf( szMessage, "Can't create local path %s", szDirName );
SAVE_fn_vErrorMessage( szMessage );
return FALSE;
}
}
return TRUE;
}
/*
----------------------------------------------------------------------------------------
Description : move directory (source and target dir names are stored in global var
SAVE_g_szDirName and SAVE_g_szTargetDirName )
Returns (BOOL ) true if success
----------------------------------------------------------------------------------------
*/
BOOL fn_bMoveDirectory( void )
{
WIN32_FIND_DATA stFindData;
HANDLE hFind;
char *p_szEndSource;
char *p_szEndTarget;
if ( _access( SAVE_g_szTargetDirName, 0) != 0)
return MoveFile( SAVE_g_szDirName , SAVE_g_szTargetDirName );
p_szEndSource = SAVE_g_szDirName + strlen( SAVE_g_szDirName );
p_szEndTarget = SAVE_g_szTargetDirName + strlen( SAVE_g_szTargetDirName );
strcpy( p_szEndSource, "\\*.*" );
if( (hFind = FindFirstFile(SAVE_g_szDirName, &stFindData )) == INVALID_HANDLE_VALUE)
return TRUE;
*p_szEndSource = 0;
do
{
*p_szEndTarget = *p_szEndSource = '\\';
strcpy( p_szEndSource + 1, stFindData.cFileName );
strcpy( p_szEndTarget + 1, stFindData.cFileName );
if ( stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
if ( *stFindData.cFileName != '.')
{
if ( !fn_bMoveDirectory() )
return FALSE;
}
}
else
{
if (_access( SAVE_g_szTargetDirName, 0) == 0)
{
if (_access( SAVE_g_szTargetDirName, 2) == -1 )
_chmod( SAVE_g_szTargetDirName, _S_IWRITE );
if ( !DeleteFile( SAVE_g_szTargetDirName ) )
return FALSE;
}
if ( !MoveFile( SAVE_g_szDirName, SAVE_g_szTargetDirName ) )
return FALSE;
}
*p_szEndSource = *p_szEndTarget = 0;
} while(FindNextFile( hFind, &stFindData ));
FindClose( hFind );
return RemoveDirectory( SAVE_g_szDirName );
}
/*
----------------------------------------------------------------------------------------
Description : move a directory into another one
szSourceDir -> source directory
szTargetDir -> target directory
Returns (BOOL ) true if success
----------------------------------------------------------------------------------------
*/
BOOL SAVE_fn_bMoveDirectory( char *szSourceDir, char *szTargetDir )
{
strcpy( SAVE_g_szTargetDirName, szTargetDir );
strcpy( SAVE_g_szDirName, szSourceDir );
return fn_bMoveDirectory();
}
/*
=======================================================================================
Error functions
=======================================================================================
*/
/*
----------------------------------------------------------------------------------------
Description : display an error message
_szMessage -> message to display
----------------------------------------------------------------------------------------
*/
void SAVE_fn_vErrorMessage( char *_szMessage )
{
char szError[1024];
char *p_szError = szError;
p_szError += sprintf( p_szError, "Error saving current version before saving new data\n" );
p_szError += sprintf( p_szError, "You will not be able to get local previous version\n" );
p_szError += sprintf( p_szError, "---------------------------------------------------\n" );
p_szError += sprintf( p_szError, "%s\n\n", _szMessage );
p_szError += sprintf( p_szError, " Save anyway ?" );
//SAVE_g_bContinue = AfxMessageBox( szError, MB_ICONSTOP | MB_YESNO );
}
/*
=======================================================================================
Version functions
=======================================================================================
*/
/*
----------------------------------------------------------------------------------------
Description :
_szSavedDirectoryName -> name of directory from which function extract version number
Returns (long ) version number if it's a valid directory, -1 else
----------------------------------------------------------------------------------------
*/
long SAVE_fn_lGetVersionNumberFromDirExt( char *_szSavedDirectoryName )
{
char *p_szExt;
long lVersionNumber = -1;
p_szExt = strchr( _szSavedDirectoryName, '.' );
if (p_szExt != NULL)
{
if ( strlen( ++p_szExt ) == 3)
{
lVersionNumber = 0;
while (*p_szExt != 0)
{
if ( !isdigit (*p_szExt) )
return -1;
lVersionNumber = lVersionNumber * 10 + (*p_szExt++ - '0');
}
}
}
return lVersionNumber;
}
/*
----------------------------------------------------------------------------------------
Description : return name of directory used to store data for a given version
lVersion -> version number
szVersionDirName -> to put dir name (assumed to be long enough )
----------------------------------------------------------------------------------------
*/
void SAVE_fn_vGetVersionDirName( long _lVersion, char *_szVersionDirName )
{
sprintf( _szVersionDirName, "%s.%03d", fn_szGetGameDataPath(), _lVersion );
}
/*
----------------------------------------------------------------------------------------
Description : delete a version directory
_lVersion -> number of version
Returns (BOOL ) true if success
----------------------------------------------------------------------------------------
*/
BOOL SAVE_fn_bDeleteVersion( long _lVersion )
{
char szVersionName[ _MAX_PATH ];
SAVE_fn_vGetVersionDirName( _lVersion, szVersionName );
if (!SAVE_fn_bDeleteTree( szVersionName ))
{
char szMessage[100];
sprintf( szMessage, "Can't delete old %s version directory", szVersionName );
SAVE_fn_vErrorMessage( szMessage );
return FALSE;
}
return TRUE;
}
/*
----------------------------------------------------------------------------------------
Description : rename a version
_lOldVersion -> old version number
_lNewVersion -> new version number
Returns (BOOL )
----------------------------------------------------------------------------------------
*/
BOOL SAVE_fn_bRenameVersion( long _lOldVersion, long _lNewVersion )
{
char szOldVersion[ _MAX_PATH ];
char szNewVersion[ _MAX_PATH ];
SAVE_fn_vGetVersionDirName( _lOldVersion, szOldVersion );
SAVE_fn_vGetVersionDirName( _lNewVersion, szNewVersion );
if ( !MoveFile( szOldVersion, szNewVersion) )
{
char szMessage[100];
sprintf( szMessage, "Can't rename old %s version to new version %s ", szOldVersion, szNewVersion );
SAVE_fn_vErrorMessage( szMessage );
return FALSE;
}
return TRUE;
}
/*
----------------------------------------------------------------------------------------
Description : analyse the current version that are on disk
a_cVersion -> array of 1000 char that will be filled
each case is a flag that indicate if a version number is used or not
return (long) number of used version
----------------------------------------------------------------------------------------
*/
long SAVE_fn_lGetUsedVersion( char *a_cVersion, SYSTEMTIME *a_stTime )
{
WIN32_FIND_DATA stFindData;
HANDLE hFind;
char szFilter[ _MAX_PATH ];
long lNumberOfVersions = 0;
long lVersion;
FILETIME stLocalFileTime;
/*
* set all version as unused
*/
memset ( a_cVersion , 0, 1000 );
sprintf( szFilter, "%s.*", fn_szGetGameDataPath() );
if( (hFind = FindFirstFile(szFilter, &stFindData )) == INVALID_HANDLE_VALUE)
return 0;
do
{
if ( stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
lVersion = SAVE_fn_lGetVersionNumberFromDirExt( stFindData.cFileName );
if (lVersion != -1)
{
a_cVersion[ lVersion ] = 1;
if (a_stTime != NULL)
{
FileTimeToLocalFileTime( &stFindData.ftCreationTime, &stLocalFileTime );
FileTimeToSystemTime( &stLocalFileTime, &a_stTime[ lVersion ] );
}
lNumberOfVersions++ ;
}
}
} while(FindNextFile( hFind, &stFindData ));
FindClose( hFind );
return lNumberOfVersions;
}
/*
----------------------------------------------------------------------------------------
Description : analyse the current version that are on disk
----------------------------------------------------------------------------------------
*/
long SAVE_fn_lAnalyseCurrentUsedVersion( char *a_cVersion, SYSTEMTIME *a_stTime )
{
long lNumberOfVersions;
long lVersion;
long lVersionIndex;
long lLastUnusedVersion = -1;
/*
* get used versions
*/
lNumberOfVersions = SAVE_fn_lGetUsedVersion( a_cVersion, a_stTime );
if (lNumberOfVersions == 0)
return 0;
/*
* check for hole in version number
*/
lVersion = 0;
for (lVersionIndex = 0; lVersion < lNumberOfVersions; lVersionIndex ++)
{
if (a_cVersion[ lVersionIndex ])
lVersion ++;
else
lLastUnusedVersion = lVersionIndex;
}
if (lLastUnusedVersion == -1)
return lNumberOfVersions;
for (lVersionIndex = 0; lVersionIndex < lLastUnusedVersion; lVersionIndex++)
{
if (a_cVersion[ lVersionIndex ])
{
if (!SAVE_fn_bDeleteVersion( lVersionIndex ))
return 0;
}
}
lVersion = 0;
for (lVersionIndex = lLastUnusedVersion + 1; a_cVersion[ lVersionIndex ]; lVersionIndex ++)
{
if (!SAVE_fn_bRenameVersion( lVersionIndex, lVersion ))
return 0;
a_cVersion[lVersion] = 1;
if (a_stTime != NULL)
a_stTime[lVersion] = a_stTime[lVersionIndex];
lVersion ++;
}
return lVersion;
}