Пример #1
0
bool CGFile::CopyFileTo( LPCTSTR pszDstFileName )
{
	if ( ! IsFileOpen())
	{
		if ( ! Open())
			return( false );
	}
	else
	{
		SeekToBegin();
	}

	CGFile sDst;
	if ( ! sDst.Open( pszDstFileName, OF_WRITE|OF_CREATE|OF_BINARY ))
	{
		return( false );
	}

	BYTE * pData = new BYTE [ 32 * 1024 ];	// temporary buffer.
	ASSERT(pData);
	bool fSuccess = true;

	while ( true )
	{
		size_t iSize = Read( pData, 32 * 1024 );
		if ( iSize < 0 )
		{
			fSuccess = false;
			break;
		}
		if ( iSize == 0 )
			break;
		sDst.Write( pData, iSize );
		if ( iSize < 32 * 1024 )
			break;
	}

	delete [] pData;
	return( fSuccess );
}
Пример #2
0
void defragSphere(char *path)
{
	ASSERT(path != NULL);

	CFileText inf;
	CGFile ouf;
	char z[256], z1[256], buf[1024];
	size_t i;
	DWORD uid = UID_CLEAR;
	char *p = NULL, *p1 = NULL;
	DWORD dBytesRead;
	DWORD dTotalMb;
	DWORD mb10 = 10 * 1024 * 1024;
	DWORD mb5 = 5 * 1024 * 1024;
	bool bSpecial;
	DWORD dTotalUIDs;

	char	c,c1,c2;
	DWORD	d;

	// NOTE: Sure I could use CVarDefArray, but it is extremely slow with memory allocation, takes hours
	// to read and save the data. Moreover, it takes less memory in this case and does less convertations.

	g_Log.Event(LOGM_INIT, "Defragmentation (UID alteration) of " SPHERE_TITLE " saves.\n"
		"Use it at your own risk and if you know what you are doing, since it can possibly harm your server.\n"
		"The process can take up to several hours depending on the CPU you have.\n"
		"After finished, you will have your '" SPHERE_FILE "*.scp' save files converted to '" SPHERE_FILE "*.scp.new'.\n");

	DWORD *uids = static_cast<DWORD *>(calloc((SIZE_MAX / 2) / sizeof(DWORD), sizeof(DWORD)));
	for ( i = 0; i < 3; i++ )
	{
		strncpy(z, path, sizeof(z) - 1);
		if ( i == 0 )
			strcat(z, SPHERE_FILE "statics" SPHERE_SCRIPT);
		else if ( i == 1 )
			strcat(z, SPHERE_FILE "world" SPHERE_SCRIPT);
		else
			strcat(z, SPHERE_FILE "chars" SPHERE_SCRIPT);

		g_Log.Event(LOGM_INIT, "Reading %s\n", z);
		if ( !inf.Open(z, OF_READ|OF_TEXT|OF_DEFAULTMODE) )
		{
			g_Log.Event(LOGM_INIT, "Can't open file '%s' for reading. Skipped!\n", z);
			continue;
		}
		dBytesRead = dTotalMb = 0;
		while ( !feof(inf.m_pStream) )
		{
			fgets(buf, sizeof(buf), inf.m_pStream);
			dBytesRead += strlen(buf);
			if ( dBytesRead > mb10 )
			{
				dBytesRead -= mb10;
				dTotalMb += 10;
				g_Log.Event(LOGM_INIT, "Total read %lu Mb\n", dTotalMb);
			}
			if (( buf[0] == 'S' ) && ( strstr(buf, "SERIAL=") == buf ))
			{
				p = buf + 7;
				p1 = p;
				while ( *p1 && ( *p1 != '\r' ) && ( *p1 != '\n' ))
					p1++;
				*p1 = 0;

				//	prepare new uid
				*(p-1) = '0';
				*p = 'x';
				p--;
				uids[uid++] = strtoul(p, &p1, 16);
			}
		}
		inf.Close();
	}

	dTotalUIDs = uid;
	if ( dTotalUIDs <= 0 )
	{
		g_Log.Event(LOGM_INIT, "Save files are empty, defragmentation is not needed\n");
		return;
	}

	g_Log.Event(LOGM_INIT, "Found %lu UIDs (latest: 0%lx)\n", uid, uids[dTotalUIDs - 1]);
	g_Log.Event(LOGM_INIT, "Quick-sorting UIDs array...\n");
	dword_q_sort(uids, 0, dTotalUIDs - 1);

	for ( i = 0; i < 5; i++ )
	{
		strncpy(z, path, sizeof(z) - 1);
		if ( i == 0 )
			strcat(z, SPHERE_FILE "accu.scp");
		else if ( i == 1 )
			strcat(z, SPHERE_FILE "chars" SPHERE_SCRIPT);
		else if ( i == 2 )
			strcat(z, SPHERE_FILE "data" SPHERE_SCRIPT);
		else if ( i == 3 )
			strcat(z, SPHERE_FILE "world" SPHERE_SCRIPT);
		else if ( i == 4 )
			strcat(z, SPHERE_FILE "statics" SPHERE_SCRIPT);

		g_Log.Event(LOGM_INIT, "Updating UIDs in '%s' to '%s.new'\n", z, z);
		if ( !inf.Open(z, OF_READ|OF_TEXT|OF_DEFAULTMODE) )
		{
			g_Log.Event(LOGM_INIT, "Can't open file '%s' for reading. Skipped!\n", z);
			continue;
		}
		strcat(z, ".new");
		if ( !ouf.Open(z, OF_WRITE|OF_CREATE|OF_DEFAULTMODE) )
		{
			g_Log.Event(LOGM_INIT, "Can't open file '%s' for writing. Skipped!\n", z);
			continue;
		}
		dBytesRead = dTotalMb = 0;
		while ( inf.ReadString(buf, sizeof(buf)) )
		{
			uid = strlen(buf);
			if (uid > (COUNTOF(buf) - 3))
				uid = COUNTOF(buf) - 3;

			buf[uid] = buf[uid+1] = buf[uid+2] = 0;	// just to be sure to be in line always
							// NOTE: it is much faster than to use memcpy to clear before reading
			bSpecial = false;
			dBytesRead += uid;
			if ( dBytesRead > mb5 )
			{
				dBytesRead -= mb5;
				dTotalMb += 5;
				g_Log.Event(LOGM_INIT, "Total processed %lu Mb\n", dTotalMb);
			}
			p = buf;

			//	Note 28-Jun-2004
			//	mounts seems having ACTARG1 > 0x30000000. The actual UID is ACTARG1-0x30000000. The
			//	new also should be new+0x30000000. need investigation if this can help making mounts
			//	not to disappear after the defrag
			if (( buf[0] == 'A' ) && ( strstr(buf, "ACTARG1=0") == buf ))		// ACTARG1=
				p += 8;
			else if (( buf[0] == 'C' ) && ( strstr(buf, "CONT=0") == buf ))			// CONT=
				p += 5;
			else if (( buf[0] == 'C' ) && ( strstr(buf, "CHARUID=0") == buf ))		// CHARUID=
				p += 8;
			else if (( buf[0] == 'L' ) && ( strstr(buf, "LASTCHARUID=0") == buf ))	// LASTCHARUID=
				p += 12;
			else if (( buf[0] == 'L' ) && ( strstr(buf, "LINK=0") == buf ))			// LINK=
				p += 5;
			else if (( buf[0] == 'M' ) && ( strstr(buf, "MEMBER=0") == buf ))		// MEMBER=
			{
				p += 7;
				bSpecial = true;
			}
			else if (( buf[0] == 'M' ) && ( strstr(buf, "MORE1=0") == buf ))		// MORE1=
				p += 6;
			else if (( buf[0] == 'M' ) && ( strstr(buf, "MORE2=0") == buf ))		// MORE2=
				p += 6;
			else if (( buf[0] == 'S' ) && ( strstr(buf, "SERIAL=0") == buf ))		// SERIAL=
				p += 7;
			else if ((( buf[0] == 'T' ) && ( strstr(buf, "TAG.") == buf )) ||		// TAG.=
					 (( buf[0] == 'R' ) && ( strstr(buf, "REGION.TAG") == buf )))
			{
				while ( *p && ( *p != '=' )) p++;
				p++;
			}
			else if (( i == 2 ) && strchr(buf, '='))	// spheredata.scp - plain VARs
			{
				while ( *p && ( *p != '=' )) p++;
				p++;
			}
			else p = NULL;

			//	UIDs are always hex, so prefixed by 0
			if ( p && ( *p != '0' )) p = NULL;

			//	here we got potentialy UID-contained variable
			//	check if it really is only UID-like var containing
			if ( p )
			{
				p1 = p;
				while ( *p1 &&
					((( *p1 >= '0' ) && ( *p1 <= '9' )) ||
					 (( *p1 >= 'a' ) && ( *p1 <= 'f' )))) p1++;
				if ( !bSpecial )
				{
					if ( *p1 && ( *p1 != '\r' ) && ( *p1 != '\n' )) // some more text in line
						p = NULL;
				}
			}

			//	here we definitely know that this is very uid-like
			if ( p )
			{
				c = *p1;

				*p1 = 0;
				//	here in p we have the current value of the line.
				//	check if it is a valid UID

				//	prepare converting 0.. to 0x..
				c1 = *(p-1);
				c2 = *p;
				*(p-1) = '0';
				*p = 'x';
				p--;
				uid = strtoul(p, &p1, 16);
				p++;
				*(p-1) = c1;
				*p = c2;
				//	Note 28-Jun-2004
				//	The search algourytm is very simple and fast. But maybe integrate some other, at least /2 algorythm
				//	since has amount/2 tryes at worst chance to get the item and never scans the whole array
				//	It should improve speed since defragmenting 150Mb saves takes ~2:30 on 2.0Mhz CPU
				{
					DWORD	dStep = dTotalUIDs/2;
					d = dStep;
					for (;;)
					{
						dStep /= 2;

						if ( uids[d] == uid )
						{
							uid = d | (uids[d]&0xF0000000);	// do not forget attach item and special flags like 04..
							break;
						}
						else if ( uids[d] < uid ) d += dStep;
						else d -= dStep;

						if ( dStep == 1 )
						{
							uid = ULONG_MAX;
							break; // did not find the UID
						}
					}
				}

				//	Search for this uid in the table
/*				for ( d = 0; d < dTotalUIDs; d++ )
				{
					if ( !uids[d] )	// end of array
					{
						uid = ULONG_MAX;
						break;
					}
					else if ( uids[d] == uid )
					{
						uid = d | (uids[d]&0xF0000000);	// do not forget attach item and special flags like 04..
						break;
					}
				}*/

				//	replace UID by the new one since it has been found
				*p1 = c;
				if ( uid != ULONG_MAX )
				{
					*p = 0;
					strncpy(z, p1, sizeof(z) - 1);
					sprintf(z1, "0%lx", uid);
					strcat(buf, z1);
					strcat(buf, z);
				}
			}
			//	output the resulting line
			ouf.Write(buf, strlen(buf));
		}
		inf.Close();
		ouf.Close();
	}
	free(uids);
	g_Log.Event(LOGM_INIT,	"Defragmentation complete.\n");
}