545 lines
16 KiB
C++
545 lines
16 KiB
C++
|
|
#include "stdafx.h"
|
|
#include "file.h"
|
|
#include "globaldata.h"
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
|
|
tdeStatus fn_eCreateDirectory( const char *_szDirectory )
|
|
{
|
|
if ( (!CreateDirectory( _szDirectory, NULL )) && (GetLastError() != ERROR_ALREADY_EXISTS) )
|
|
{
|
|
char *p_szCur;
|
|
|
|
p_szCur = strchr( _szDirectory, '\\');
|
|
while (p_szCur != NULL)
|
|
{
|
|
*p_szCur = 0;
|
|
if ((!CreateDirectory (_szDirectory, NULL)) && (GetLastError() != ERROR_ALREADY_EXISTS) )
|
|
{
|
|
char szMessage[ 512 ];
|
|
sprintf( szMessage, "Can't create local path '%s'", _szDirectory );
|
|
AfxMessageBox( szMessage, MB_OK | MB_ICONSTOP );
|
|
return STATUS_C_Error;
|
|
}
|
|
*p_szCur++ = '\\';
|
|
p_szCur = strchr( p_szCur, '\\');
|
|
};
|
|
|
|
if ((!CreateDirectory (_szDirectory, NULL)) && (GetLastError() != ERROR_ALREADY_EXISTS) )
|
|
{
|
|
char szMessage[ 512 ];
|
|
sprintf( szMessage, "Can't create local path '%s'", _szDirectory );
|
|
AfxMessageBox( szMessage, MB_OK | MB_ICONSTOP );
|
|
return STATUS_C_Error;
|
|
}
|
|
}
|
|
return STATUS_C_OK;
|
|
}
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Copy a file or a directory (no '\' at end of directory name !)
|
|
// Source may contain wilcards. Dest must be a path to a directory !
|
|
// If source is a directory, the copy is recursive
|
|
tdeStatus fn_eCopyFileOrDirectory( const char *_szSource, const char *_szDest )
|
|
{
|
|
HANDLE hCopyhandle;
|
|
WIN32_FIND_DATA stFindData;
|
|
int iNbCharactersForSourcePath;
|
|
char szSource[512];
|
|
char szDest[512];
|
|
tdeStatus eStatus;
|
|
|
|
if( (eStatus = fn_eCreateDirectory( _szDest )) != STATUS_C_OK )
|
|
return eStatus;
|
|
|
|
// No file to copy, nothing to do...
|
|
if( (hCopyhandle = FindFirstFile( _szSource, &stFindData )) == INVALID_HANDLE_VALUE )
|
|
return STATUS_C_OK;
|
|
|
|
iNbCharactersForSourcePath = (strrchr( _szSource, '\\' ) - _szSource);
|
|
do
|
|
{
|
|
// Skip . and ..
|
|
if( (stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
&& ( (strcmp( stFindData.cFileName, ".") == 0)
|
|
|| strcmp( stFindData.cFileName, "..") == 0) )
|
|
continue;
|
|
|
|
strncpy( szSource, _szSource, iNbCharactersForSourcePath+1 );
|
|
szSource[iNbCharactersForSourcePath+1] = 0;
|
|
strcat( szSource, stFindData.cFileName );
|
|
sprintf( szDest, "%s\\%s", _szDest, stFindData.cFileName );
|
|
|
|
// If file is a directory
|
|
if( (stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
|
{
|
|
strcat( szSource, "\\*.*" );
|
|
if( (eStatus = fn_eCopyFileOrDirectory( szSource, szDest )) != STATUS_C_OK )
|
|
return eStatus;
|
|
}
|
|
else
|
|
{
|
|
if( ! CopyFile( szSource, szDest, FALSE ) )
|
|
{
|
|
char szMessage[1024];
|
|
sprintf( szMessage, "Copy failed: '%s' to '%s", szSource, szDest );
|
|
AfxMessageBox( szMessage, MB_OK | MB_ICONSTOP );
|
|
return STATUS_C_Error;
|
|
}
|
|
}
|
|
|
|
// Test for end of work.
|
|
if( g_stTheGlobalData.bStopWork )
|
|
return STATUS_C_UserBreak;
|
|
|
|
} while( FindNextFile( hCopyhandle, &stFindData ) );
|
|
|
|
FindClose( hCopyhandle );
|
|
|
|
return STATUS_C_OK;
|
|
}
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Copy some files to a directory. Function will also seach for files in sub-dirs of source.
|
|
// Source may contain wilcards. Dest must be a path to a directory !
|
|
tdeStatus fn_eRecursiveFileCopy( const char *_szSource, const char *_szDest )
|
|
{
|
|
HANDLE hDirectoryHandle;
|
|
WIN32_FIND_DATA stFindData;
|
|
int iNbCharactersForSourcePath;
|
|
char szSource[512];
|
|
char szDest[512];
|
|
tdeStatus eStatus;
|
|
|
|
// Copy this level of directory
|
|
if( (eStatus = fn_eCopyFileOrDirectory( _szSource, _szDest )) != STATUS_C_OK )
|
|
return eStatus;
|
|
|
|
// Now we are going to check for subdirs.
|
|
iNbCharactersForSourcePath = (strrchr( _szSource, '\\' ) - _szSource);
|
|
strncpy( szSource, _szSource, iNbCharactersForSourcePath+1 );
|
|
szSource[iNbCharactersForSourcePath+1] = 0;
|
|
strcat( szSource, "*.*" );
|
|
|
|
// No files in directory, nothing to do...
|
|
if( (hDirectoryHandle = FindFirstFile( szSource, &stFindData )) == INVALID_HANDLE_VALUE )
|
|
return STATUS_C_OK;
|
|
|
|
do
|
|
{
|
|
// Skip . and ..
|
|
if( (stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
&& ( (strcmp( stFindData.cFileName, ".") == 0)
|
|
|| strcmp( stFindData.cFileName, "..") == 0) )
|
|
continue;
|
|
|
|
// We treat only directories
|
|
if( (stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
|
{
|
|
strncpy( szSource, _szSource, iNbCharactersForSourcePath+1 );
|
|
szSource[iNbCharactersForSourcePath+1] = 0;
|
|
strcat( szSource, stFindData.cFileName );
|
|
strcat( szSource, _szSource+iNbCharactersForSourcePath );
|
|
|
|
sprintf( szDest, "%s\\%s", _szDest, stFindData.cFileName );
|
|
|
|
if( (eStatus = fn_eRecursiveFileCopy( szSource, szDest )) != STATUS_C_OK )
|
|
return eStatus;
|
|
}
|
|
|
|
// Test for end of work.
|
|
if( g_stTheGlobalData.bStopWork )
|
|
return STATUS_C_UserBreak;
|
|
|
|
} while( FindNextFile( hDirectoryHandle, &stFindData ) );
|
|
|
|
FindClose( hDirectoryHandle );
|
|
|
|
return STATUS_C_OK;
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Moves file(s) or a directory (no '\' at end of directory name !)
|
|
// Source may contain wilcards. Dest must be a path to a directory !
|
|
tdeStatus fn_eMoveFileOrDirectory( const char *_szSource, const char *_szDest )
|
|
{
|
|
HANDLE hCopyhandle;
|
|
WIN32_FIND_DATA stFindData;
|
|
int iNbCharactersForSourcePath;
|
|
char szSource[512], szDest[512];
|
|
tdeStatus eStatus;
|
|
|
|
if( (eStatus = fn_eCreateDirectory( _szDest )) != STATUS_C_OK )
|
|
return eStatus;
|
|
|
|
// No file to copy, nothing to do...
|
|
if( (hCopyhandle = FindFirstFile( _szSource, &stFindData )) == INVALID_HANDLE_VALUE )
|
|
return STATUS_C_OK;
|
|
|
|
iNbCharactersForSourcePath = (strrchr( _szSource, '\\' ) - _szSource);
|
|
do
|
|
{
|
|
// Skip . and ..
|
|
if( (stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
&& ( (strcmp( stFindData.cFileName, ".") == 0)
|
|
|| strcmp( stFindData.cFileName, "..") == 0) )
|
|
continue;
|
|
|
|
strncpy( szSource, _szSource, iNbCharactersForSourcePath+1 );
|
|
szSource[iNbCharactersForSourcePath+1] = 0;
|
|
strcat( szSource, stFindData.cFileName );
|
|
sprintf( szDest, "%s\\%s", _szDest, stFindData.cFileName );
|
|
|
|
if( ! MoveFile( szSource, szDest ) )
|
|
{
|
|
char szMessage[1024];
|
|
sprintf( szMessage, "Move failed: '%s' to '%s", szSource, szDest );
|
|
AfxMessageBox( szMessage, MB_OK | MB_ICONSTOP );
|
|
return STATUS_C_Error;
|
|
}
|
|
|
|
// Test for end of work.
|
|
if( g_stTheGlobalData.bStopWork )
|
|
return STATUS_C_UserBreak;
|
|
|
|
} while( FindNextFile( hCopyhandle, &stFindData ) );
|
|
|
|
FindClose( hCopyhandle );
|
|
|
|
return STATUS_C_OK;
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Deletes file(s) or directory (no '\' at end of directory name !)
|
|
// Source may contain wilcards.
|
|
// If source is a directory, the delete is recursive.
|
|
tdeStatus fn_eDeleteFileOrDirectory( const char *_szSource )
|
|
{
|
|
HANDLE hDeletehandle;
|
|
WIN32_FIND_DATA stFindData;
|
|
int iNbCharactersForSourcePath;
|
|
char szSource[512];
|
|
tdeStatus eStatus;
|
|
|
|
// No file to delete, nothing to do...
|
|
if( (hDeletehandle = FindFirstFile( _szSource, &stFindData )) == INVALID_HANDLE_VALUE )
|
|
return STATUS_C_OK;
|
|
|
|
iNbCharactersForSourcePath = (strrchr( _szSource, '\\' ) - _szSource);
|
|
do
|
|
{
|
|
// Skip . and ..
|
|
if( (stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
&& ( (strcmp( stFindData.cFileName, ".") == 0)
|
|
|| strcmp( stFindData.cFileName, "..") == 0) )
|
|
continue;
|
|
|
|
strncpy( szSource, _szSource, iNbCharactersForSourcePath+1 );
|
|
szSource[iNbCharactersForSourcePath+1] = 0;
|
|
strcat( szSource, stFindData.cFileName );
|
|
|
|
// If file is a directory
|
|
if( (stFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
|
{
|
|
strcat( szSource, "\\*.*" );
|
|
if( (eStatus = fn_eDeleteFileOrDirectory( szSource )) != STATUS_C_OK )
|
|
return eStatus;
|
|
*strrchr( szSource, '\\' ) = 0;
|
|
if( ! RemoveDirectory( szSource ) )
|
|
{
|
|
char szMessage[1024];
|
|
sprintf( szMessage, "Delete failed on '%s'", szSource );
|
|
AfxMessageBox( szMessage, MB_OK | MB_ICONSTOP );
|
|
return STATUS_C_Error;
|
|
}
|
|
}
|
|
else if( ! DeleteFile( szSource ) )
|
|
{
|
|
char szMessage[1024];
|
|
sprintf( szMessage, "Delete failed on '%s'", szSource );
|
|
AfxMessageBox( szMessage, MB_OK | MB_ICONSTOP );
|
|
return STATUS_C_Error;
|
|
}
|
|
|
|
// Test for end of work.
|
|
if( g_stTheGlobalData.bStopWork )
|
|
return STATUS_C_UserBreak;
|
|
|
|
} while( FindNextFile( hDeletehandle, &stFindData ) );
|
|
|
|
FindClose( hDeletehandle );
|
|
|
|
return STATUS_C_OK;
|
|
}
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// This part deals with batch copy/move of files :
|
|
|
|
// Common files for all binarised maps (no files generated by binarisation nor sound or textures)
|
|
// files relative to main directory
|
|
char *g_a_szCommonFiles[] =
|
|
{
|
|
"Copy", "Gamedata\\Options\\current.cfg", "%bin%\\Options",
|
|
"End"
|
|
};
|
|
|
|
char *g_a_szFilesBeforeBinarize[] =
|
|
{
|
|
// Make sure main directory is clean
|
|
"Delete", "fix*.sna",
|
|
"Delete", "fix*.snd",
|
|
"Delete", "fix*.ptx",
|
|
"Delete", "fix*.gpt",
|
|
"Delete", "fix.rt?",
|
|
|
|
"Delete", "%level%*.sna",
|
|
"Delete", "%level%*.snd",
|
|
"Delete", "%level%*.ptx",
|
|
"Delete", "%level%*.gpt",
|
|
"Delete", "%level%.rt?",
|
|
|
|
"End"
|
|
};
|
|
|
|
char *g_a_szFilesAfterFirstPass[] =
|
|
{
|
|
// Get fix files from gamedata\world\levels
|
|
"Move", "Gamedata\\World\\Levels\\fix*", "",
|
|
"Rename", "Fix.sna", "Fix0.sna",
|
|
"Rename", "Fix.snd", "Fix0.snd",
|
|
"Rename", "Fix.ptx", "Fix0.ptx",
|
|
"Rename", "Fix.gpt", "Fix0.gpt",
|
|
|
|
// Get level files from gamedata\world\levels\<LevelName>
|
|
"Rename", "Gamedata\\World\\Levels\\%level%\\%level%.sna", "%level%0.sna",
|
|
"Rename", "Gamedata\\World\\Levels\\%level%\\%level%.snd", "%level%0.snd",
|
|
"Rename", "Gamedata\\World\\Levels\\%level%\\%level%.ptx", "%level%0.ptx",
|
|
"Rename", "Gamedata\\World\\Levels\\%level%\\%level%.gpt", "%level%0.gpt",
|
|
|
|
"End"
|
|
};
|
|
|
|
char *g_a_szFilesAfterSecondPass[] =
|
|
{
|
|
// Get fix files from gamedata\world\levels
|
|
"Move", "Gamedata\\World\\Levels\\fix*", "",
|
|
"Rename", "Fix.sna", "Fix1.sna",
|
|
"Rename", "Fix.snd", "Fix1.snd",
|
|
"Rename", "Fix.ptx", "Fix1.ptx",
|
|
"Rename", "Fix.gpt", "Fix1.gpt",
|
|
|
|
// Get level files from gamedata\world\levels\<LevelName>
|
|
"Rename", "Gamedata\\World\\Levels\\%level%\\%level%.sna", "%level%1.sna",
|
|
"Rename", "Gamedata\\World\\Levels\\%level%\\%level%.snd", "%level%1.snd",
|
|
"Rename", "Gamedata\\World\\Levels\\%level%\\%level%.ptx", "%level%1.ptx",
|
|
"Rename", "Gamedata\\World\\Levels\\%level%\\%level%.gpt", "%level%1.gpt",
|
|
"End"
|
|
};
|
|
|
|
|
|
char *g_a_szFixFilesAfterCRB[] =
|
|
{
|
|
// Delete previous fix files
|
|
"Delete", "%bin%\\World\\Levels\\fix*",
|
|
"Delete", "%bin%\\Game.dsb",
|
|
|
|
// Delete files from second pass
|
|
"Delete", "Fix1.*",
|
|
|
|
// We will use files from first pass.
|
|
"Rename", "Fix0.sna", "Fix.sna",
|
|
"Rename", "Fix0.snd", "Fix.snd",
|
|
"Rename", "Fix0.ptx", "Fix.ptx",
|
|
"Rename", "Fix0.gpt", "Fix.gpt",
|
|
"Move", "Fix.*", "%bin%\\World\\Levels",
|
|
// "Move", "Fix.rt?", "%bin%\\World\\Levels",
|
|
"Move", "Gamedata\\Game.dsb", "%bin%",
|
|
"End"
|
|
};
|
|
|
|
char *g_a_szDeleteFixFilesAfterCRB[] =
|
|
{
|
|
// Delete fix files
|
|
"Delete", "fix*.sna",
|
|
"Delete", "fix*.snd",
|
|
"Delete", "fix*.ptx",
|
|
"Delete", "fix*.gpt",
|
|
"Delete", "fix.rt?",
|
|
"End"
|
|
};
|
|
|
|
char *g_a_szLevelFilesAfterCRB[] =
|
|
{
|
|
// Delete files from second pass
|
|
"Delete", "%level%1.*",
|
|
|
|
// We will use files from first pass.
|
|
"Rename", "%level%0.sna", "%level%.sna",
|
|
"Rename", "%level%0.snd", "%level%.snd",
|
|
"Rename", "%level%0.ptx", "%level%.ptx",
|
|
"Rename", "%level%0.gpt", "%level%.gpt",
|
|
|
|
// Delete bin level directory
|
|
"Delete", "%bin%\\World\\Levels\\%level%\\*.*",
|
|
|
|
// Move all files to destination directory
|
|
"Move", "%level%*", "%bin%\\World\\Levels\\%level%",
|
|
"Move", "Gamedata\\World\\Levels\\%level%\\%level%.dsb", "%bin%\\World\\Levels\\%level%",
|
|
"End"
|
|
};
|
|
|
|
char *g_a_szDeleteFilesAfterBinarize[] =
|
|
{
|
|
// Delete all remaining files in main directory
|
|
"Delete", "fix*.sna",
|
|
"Delete", "fix*.snd",
|
|
"Delete", "fix*.ptx",
|
|
"Delete", "fix*.gpt",
|
|
"Delete", "fix.rt?",
|
|
|
|
"Delete", "%level%*.sna",
|
|
"Delete", "%level%*.snd",
|
|
"Delete", "%level%*.ptx",
|
|
"Delete", "%level%*.gpt",
|
|
"Delete", "%level%.rt?",
|
|
|
|
// Also delete files in level
|
|
"Delete", "Gamedata\\Game.dsb",
|
|
"Delete", "Gamedata\\World\\Levels\\%level%\\%level%.dsb",
|
|
"End"
|
|
};
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
// Analyse keyword
|
|
// Used by fn_eTreatArrayOfFiles
|
|
int fn_iGetKeyword( char *_szKeyword )
|
|
{
|
|
if( stricmp( _szKeyword, "Copy" )==0 )
|
|
return 0;
|
|
else if( stricmp( _szKeyword, "Move" )==0 )
|
|
return 1;
|
|
else if( stricmp( _szKeyword, "Rename" )==0 )
|
|
return 2;
|
|
else if( stricmp( _szKeyword, "Delete" )==0 )
|
|
return 3;
|
|
else if( stricmp( _szKeyword, "End" )==0 )
|
|
return 4;
|
|
|
|
return -1;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
// Analyse parameter
|
|
// Used by fn_eTreatArrayOfFiles
|
|
void fn_vGetParameter( char *_szResult, char *_szParam, tdstCopyFileContext *_p_stContext )
|
|
{
|
|
char *p_cSource = _szParam, *p_cDest = _szResult;
|
|
|
|
// hack: if no %bin%, assume path is main directory
|
|
if( strnicmp( p_cSource, "%bin%", 5 ) == 0 )
|
|
{
|
|
strcpy( p_cDest, _p_stContext->csBinDirectory );
|
|
p_cDest += strlen( p_cDest );
|
|
p_cSource += 5;
|
|
}
|
|
else
|
|
{
|
|
strcpy( p_cDest, _p_stContext->csMainDirectory );
|
|
p_cDest += strlen( p_cDest );
|
|
if( *p_cSource ) *p_cDest++ = '\\';
|
|
}
|
|
|
|
while( *p_cSource )
|
|
{
|
|
if( strnicmp( p_cSource, "%level%", 7 ) == 0 )
|
|
{
|
|
strcpy( p_cDest, _p_stContext->csLevelName );
|
|
p_cDest += strlen( p_cDest );
|
|
p_cSource += 7;
|
|
}
|
|
else
|
|
{
|
|
*p_cDest++ = *p_cSource++;
|
|
}
|
|
}
|
|
|
|
*p_cDest = 0;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
// Execute copy/move/deletes/rename commands in given array
|
|
// See above for exemples.
|
|
// stContext contains strings used when replacing %bin%, %level%....
|
|
tdeStatus fn_eTreatArrayOfFiles( char *_a_szFileCommands[], tdstCopyFileContext *_p_stContext )
|
|
{
|
|
char szSource[512], szDest[512];
|
|
int iKeyWord;
|
|
tdeStatus eCommandOK;
|
|
char **p_szCommand = _a_szFileCommands;
|
|
|
|
do
|
|
{
|
|
switch( fn_iGetKeyword( *p_szCommand++ ) )
|
|
{
|
|
case 0: // Copy
|
|
fn_vGetParameter( szSource, *p_szCommand++, _p_stContext );
|
|
fn_vGetParameter( szDest, *p_szCommand++, _p_stContext );
|
|
eCommandOK = fn_eCopyFileOrDirectory( szSource, szDest );
|
|
break;
|
|
|
|
case 1: // Move
|
|
fn_vGetParameter( szSource, *p_szCommand++, _p_stContext );
|
|
fn_vGetParameter( szDest, *p_szCommand++, _p_stContext );
|
|
eCommandOK = fn_eMoveFileOrDirectory( szSource, szDest );
|
|
break;
|
|
|
|
case 2: // Rename
|
|
fn_vGetParameter( szSource, *p_szCommand++, _p_stContext );
|
|
fn_vGetParameter( szDest, *p_szCommand++, _p_stContext );
|
|
eCommandOK = STATUS_C_OK;
|
|
if( ! MoveFile( szSource, szDest ) )
|
|
{
|
|
char szMessage[1024];
|
|
sprintf( szMessage, "Move failed: '%s' to '%s", szSource, szDest );
|
|
AfxMessageBox( szMessage, MB_OK | MB_ICONSTOP );
|
|
eCommandOK = STATUS_C_Error;
|
|
}
|
|
break;
|
|
|
|
case 3: // Delete
|
|
fn_vGetParameter( szSource, *p_szCommand++, _p_stContext );
|
|
eCommandOK = fn_eDeleteFileOrDirectory( szSource );
|
|
break;
|
|
|
|
case 4: // End
|
|
return STATUS_C_OK;
|
|
break;
|
|
|
|
default: // Error in array !
|
|
ASSERT(0);
|
|
iKeyWord = -1;
|
|
eCommandOK = STATUS_C_Error;
|
|
break;
|
|
}
|
|
|
|
} while( eCommandOK == STATUS_C_OK );
|
|
|
|
return eCommandOK;
|
|
}
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|