Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
241 lines
5.7 KiB
C++
241 lines
5.7 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/utime.h>
|
|
#include <sys/stat.h>
|
|
#include <direct.h>
|
|
#include <io.h>
|
|
#include <windows.h>
|
|
|
|
void
|
|
Recursive_Copy(
|
|
const char* source_path,
|
|
const char* dest_path,
|
|
int mask_count,
|
|
const char* masks[],
|
|
bool delete_ok
|
|
)
|
|
{
|
|
//
|
|
//------------------------------------------------
|
|
// Get the mask to search in the current directory
|
|
//------------------------------------------------
|
|
//
|
|
char local_mask[200];
|
|
printf("Copying %s\n", source_path);
|
|
strcpy(local_mask, source_path);
|
|
strcat(local_mask, "\\*.*");
|
|
bool dest_exists = !_access(dest_path, 0);
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// Spin through and find all non directory objects
|
|
//------------------------------------------------
|
|
//
|
|
WIN32_FIND_DATA data;
|
|
HANDLE handle = FindFirstFile(local_mask, &data);
|
|
if (handle != INVALID_HANDLE_VALUE)
|
|
{
|
|
do
|
|
{
|
|
if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
|
|
//
|
|
//-------------------------------------------
|
|
// Create the official from and to file names
|
|
//-------------------------------------------
|
|
//
|
|
char source[200];
|
|
strcpy(source, source_path);
|
|
strcat(source, "\\");
|
|
strcat(source, data.cFileName);
|
|
char dest[200];
|
|
strcpy(dest, dest_path);
|
|
strcat(dest, "\\");
|
|
strcat(dest, data.cFileName);
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// See if we can get a handle to the destination file. If so, lets
|
|
// check its data before doing the copy
|
|
//-----------------------------------------------------------------
|
|
//
|
|
bool copy = true;
|
|
struct _stat dest_info;
|
|
if (!_stat(dest, &dest_info))
|
|
{
|
|
struct _stat src_info;
|
|
_stat(source, &src_info);
|
|
copy = (src_info.st_mtime > dest_info.st_mtime);
|
|
if (copy && !(dest_info.st_mode&_S_IWRITE))
|
|
_chmod(dest, _S_IWRITE|_S_IREAD);
|
|
}
|
|
|
|
//
|
|
//---------------------------
|
|
// Copy the file if indicated
|
|
//---------------------------
|
|
//
|
|
if (copy)
|
|
{
|
|
if (!dest_exists)
|
|
{
|
|
_mkdir(dest_path);
|
|
dest_exists = true;
|
|
}
|
|
CopyFile(source, dest, FALSE);
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// Otherwise, update the read/write flag of the destination if it
|
|
// is different from the source
|
|
//---------------------------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
int dest_mode = dest_info.st_mode&(_S_IWRITE|_S_IREAD);
|
|
int src_mode =
|
|
(data.dwFileAttributes&FILE_ATTRIBUTE_READONLY) ?
|
|
_S_IREAD : _S_IREAD|_S_IWRITE;
|
|
if (dest_mode != src_mode)
|
|
_chmod(dest, src_mode);
|
|
}
|
|
}
|
|
} while (FindNextFile(handle, &data));
|
|
}
|
|
FindClose(handle);
|
|
|
|
//
|
|
//---------------------
|
|
// Look for directories
|
|
//---------------------
|
|
//
|
|
handle = FindFirstFile(local_mask, &data);
|
|
if (handle != INVALID_HANDLE_VALUE)
|
|
{
|
|
do
|
|
{
|
|
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if (
|
|
!strcmp(data.cFileName, ".")
|
|
|| !strcmp(data.cFileName, "..")
|
|
)
|
|
continue;
|
|
int i;
|
|
for (i=0; i<mask_count; ++i)
|
|
{
|
|
if (!_stricmp(data.cFileName, masks[i]))
|
|
break;
|
|
}
|
|
if (i<mask_count)
|
|
continue;
|
|
char source[200];
|
|
strcpy(source, source_path);
|
|
strcat(source, "\\");
|
|
strcat(source, data.cFileName);
|
|
char dest[200];
|
|
strcpy(dest, dest_path);
|
|
strcat(dest, "\\");
|
|
strcat(dest, data.cFileName);
|
|
if (!dest_exists)
|
|
{
|
|
_mkdir(dest_path);
|
|
dest_exists = true;
|
|
}
|
|
Recursive_Copy(source, dest, mask_count, masks, delete_ok);
|
|
}
|
|
} while (FindNextFile(handle, &data));
|
|
}
|
|
FindClose(handle);
|
|
|
|
|
|
//
|
|
//--------------------------------------------
|
|
// Spin through and delete all obsolete things
|
|
//--------------------------------------------
|
|
//
|
|
if (delete_ok)
|
|
{
|
|
strcpy(local_mask, dest_path);
|
|
strcat(local_mask, "\\*.*");
|
|
handle = FindFirstFile(local_mask, &data);
|
|
if (handle != INVALID_HANDLE_VALUE)
|
|
{
|
|
do
|
|
{
|
|
if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
|
|
//
|
|
//------------------------------
|
|
// Create the official from name
|
|
//------------------------------
|
|
//
|
|
char source[200];
|
|
strcpy(source, source_path);
|
|
strcat(source, "\\");
|
|
strcat(source, data.cFileName);
|
|
char dest[200];
|
|
strcpy(dest, dest_path);
|
|
strcat(dest, "\\");
|
|
strcat(dest, data.cFileName);
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// See if we can get a handle to the destination file. If so, lets
|
|
// check its data before doing the copy
|
|
//-----------------------------------------------------------------
|
|
//
|
|
struct _stat src_info;
|
|
if (_stat(source, &src_info))
|
|
{
|
|
printf("Deleting %s\n", dest);
|
|
_chmod(dest, _S_IWRITE|_S_IREAD);
|
|
_unlink(dest);
|
|
}
|
|
}
|
|
} while (FindNextFile(handle, &data));
|
|
}
|
|
FindClose(handle);
|
|
}
|
|
}
|
|
|
|
int
|
|
main(
|
|
int argc,
|
|
const char* argv[]
|
|
)
|
|
{
|
|
if (argc < 3 || argc > 4)
|
|
{
|
|
printf("Usage: CopyProject [-nodelete] <srcpath> <destpath>\n");
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
//-------------------------------
|
|
// First deal with the code files
|
|
//-------------------------------
|
|
//
|
|
const char *masks[]={
|
|
"Debug",
|
|
"Armor",
|
|
"Profile",
|
|
"Release"
|
|
};
|
|
int source_base = 1;
|
|
if (argc == 4)
|
|
++source_base;
|
|
Recursive_Copy(
|
|
argv[source_base],
|
|
argv[source_base+1],
|
|
sizeof(masks)/sizeof(*masks),
|
|
masks,
|
|
argc == 3
|
|
);
|
|
return 0;
|
|
}
|