initial import of binary logger support code
This commit is contained in:
		
							
								
								
									
										125
									
								
								amxmodx/binlog.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								amxmodx/binlog.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| #include "amxmodx.h" | ||||
| #include "binlog.h" | ||||
|  | ||||
| #if defined BINLOG_ENABLED | ||||
|  | ||||
| BinLog g_BinLog; | ||||
|  | ||||
| bool BinLog::Open() | ||||
| { | ||||
| 	const char *data = get_localinfo("amxmodx_datadir", "addons/amxmodx/data"); | ||||
| 	char path[255]; | ||||
| 	build_pathname_r(path, sizeof(path)-1, "%s/binlogs", data); | ||||
| 	 | ||||
| 	if (!DirExists(path)) | ||||
| 	{ | ||||
| 		mkdir(path | ||||
| #if defined __linux__ | ||||
| 			, 0755 | ||||
| #endif | ||||
| 			); | ||||
| 		if (!DirExists(path)) | ||||
| 			return false; | ||||
| 	} | ||||
|  | ||||
| 	char file[255]; | ||||
| 	build_pathname_r(file, sizeof(file)-1, "%s/binlogs/lastlog", data); | ||||
|  | ||||
| 	unsigned int lastcntr = 0; | ||||
| 	FILE *lastlog = fopen(file, "rb"); | ||||
| 	if (lastlog) | ||||
| 	{ | ||||
| 		if (fread(&lastcntr, sizeof(int), 1, lastlog) != 1) | ||||
| 			lastcntr = 0; | ||||
| 		fclose(lastlog); | ||||
| 	} | ||||
| 	lastlog = fopen(file, "wb"); | ||||
| 	if (lastlog) | ||||
| 	{ | ||||
| 		lastcntr++; | ||||
| 		fwrite(&lastcntr, sizeof(int), 1, lastlog); | ||||
| 		fclose(lastlog); | ||||
| 	} | ||||
| 	build_pathname_r(file, sizeof(file)-1, "%s/binlogs/binlog%04d.blg", data, lastcntr); | ||||
| 	m_logfile.assign(file); | ||||
| 	build_pathname_r(file, sizeof(file)-1, "%s/binlogs/bindb%04d.bdb", data, lastcntr); | ||||
| 	m_dbfile.assign(file); | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void BinLog::Close() | ||||
| { | ||||
| 	//dummy function - logs are not kept open | ||||
| } | ||||
|  | ||||
| void BinLog::CacheAllPlugins() | ||||
| { | ||||
| 	FILE *fp = fopen(m_dbfile.c_str(), "wb"); | ||||
| 	if (!fp) | ||||
| 		return; | ||||
|  | ||||
| 	unsigned int magic = BINDB_MAGIC; | ||||
| 	unsigned short vers = BINDB_VERSION; | ||||
|  | ||||
| 	fwrite(&magic, sizeof(unsigned int), 1, fp); | ||||
| 	fwrite(&vers, sizeof(unsigned short), 1, fp); | ||||
|  | ||||
| 	int num = g_plugins.getPluginsNum(); | ||||
| 	fwrite(&num, sizeof(int), 1, fp); | ||||
|  | ||||
| 	CPluginMngr::CPlugin *pl; | ||||
| 	char c; | ||||
| 	unsigned char len; | ||||
| 	for (CPluginMngr::iterator iter = g_plugins.begin(); iter; ++iter) | ||||
| 	{ | ||||
| 		pl = &(*iter); | ||||
| 		if (pl->isValid()) | ||||
| 			c = 1; | ||||
| 		else | ||||
| 			c = 0; | ||||
| 		fwrite(&c, sizeof(char), 1, fp); | ||||
| 		len = (char)strlen(pl->getName()); | ||||
| 		fwrite(&len, sizeof(char), 1, fp); | ||||
| 		len++; | ||||
| 		fwrite(pl->getName(), sizeof(char), len, fp); | ||||
| 		int objcount; | ||||
| 		AMX *amx = pl->getAMX(); | ||||
| 		amx_NumNatives(amx, &objcount); | ||||
| 		char name[34]; | ||||
| 		for (int i=0; i<objcount; i++) | ||||
| 		{ | ||||
| 			amx_GetNative(amx, i, name); | ||||
| 			len = (char)strlen(name); | ||||
| 			fwrite(&len, sizeof(char), 1, fp); | ||||
| 			len++; | ||||
| 			fwrite(name, sizeof(char), len, fp); | ||||
| 		} | ||||
| 		amx_NumPublics(amx, &objcount); | ||||
| 		for (int i=0; i<objcount; i++) | ||||
| 		{ | ||||
| 			amx_GetPublic(amx, i, name); | ||||
| 			len = (char)strlen(name); | ||||
| 			fwrite(&len, sizeof(char), 1, fp); | ||||
| 			len++; | ||||
| 			fwrite(name, sizeof(char), len, fp); | ||||
| 		} | ||||
| 	} | ||||
| 	fclose(fp); | ||||
|  | ||||
| 	/** | ||||
| 	 * it's now safe to create the binary log | ||||
| 	 */ | ||||
| 	fp = fopen(m_logfile.c_str(), "wb"); | ||||
| 	if (!fp) | ||||
| 		return; | ||||
|  | ||||
| 	magic = BINLOG_MAGIC; | ||||
| 	vers = BINLOG_VERSION; | ||||
| 	c = sizeof(time_t); | ||||
| 	fwrite(&magic, sizeof(int), 1, fp); | ||||
| 	fwrite(&vers, sizeof(short), 1, fp); | ||||
| 	fwrite(&c, sizeof(char), 1, fp); | ||||
| } | ||||
|  | ||||
| #endif //BINLOG_ENABLED | ||||
							
								
								
									
										68
									
								
								amxmodx/binlog.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								amxmodx/binlog.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| #ifndef _INCLUDE_BINLOG_H | ||||
| #define _INCLUDE_BINLOG_H | ||||
|  | ||||
| #if defined BINLOG_ENABLED | ||||
|  | ||||
| #include "CString.h" | ||||
|  | ||||
| #define BINLOG_MAGIC	0x414D424C | ||||
| #define BINLOG_VERSION	0x0100 | ||||
| #define BINDB_MAGIC		0x414D4244 | ||||
| #define BINDB_VERSION	0x0100 | ||||
|  | ||||
| /** | ||||
|  * Format of binlog: | ||||
|  * int32_t		magic | ||||
|  * int16_t		version | ||||
|  * int8_t		sizeof(time_t) | ||||
|  * [ | ||||
|  *  time_t		realtime | ||||
|  *  float		gametime | ||||
|  *  int8_t		operation code | ||||
|  *  int16_t		plugin id | ||||
|  *  <extra info> | ||||
|  * ] | ||||
|  * Format of bindb: | ||||
|  * int32_t		magic | ||||
|  * int16_t		version | ||||
|  * int16_t		num plugins | ||||
|  * [ | ||||
|  *  str[int8_t]	filename | ||||
|  *  int8_t		valid/loaded? | ||||
|  *  int16_t		num natives | ||||
|  *  [ | ||||
|  *   str[int8_t] native name | ||||
|  *  ] | ||||
|  *  int16_t		num publics | ||||
|  *  [ | ||||
|  *   str[int8_t] public name | ||||
|  *  ] | ||||
|  */ | ||||
|  | ||||
| enum BinLogOp | ||||
| { | ||||
| 	BinLog_Start=0, | ||||
| 	BinLog_End, | ||||
| 	BinLog_NativeCall,	//<int16_t native id> | ||||
| 	BinLog_CallPubFunc,	//<int16_t public id> | ||||
| 	BinLog_SetLine,		//<int16_t line no#> | ||||
| 	BinLog_Registered,	//<string title> <string version> | ||||
| }; | ||||
|  | ||||
| class BinLog | ||||
| { | ||||
| public: | ||||
| 	bool Open(); | ||||
| 	void Close(); | ||||
| 	void CacheAllPlugins(); | ||||
| 	void WriteOp(BinLogOp op, ...); | ||||
| private: | ||||
| 	String m_dbfile; | ||||
| 	String m_logfile; | ||||
| }; | ||||
|  | ||||
| #endif //BINLOG_ENABLED | ||||
|  | ||||
| extern BinLog g_BinLog; | ||||
|  | ||||
| #endif //_INCLUDE_BINLOG_H | ||||
| @@ -307,27 +307,7 @@ static cell AMX_NATIVE_CALL dir_exists(AMX *amx, cell *params) /* 1 param */ | ||||
| 	char *sFile = get_amxstring(amx, params[1], 0, iLen); | ||||
| 	char *file = build_pathname("%s", sFile); | ||||
|  | ||||
| #if defined WIN32 || defined _WIN32 | ||||
| 	DWORD attr = GetFileAttributes(file); | ||||
| 	 | ||||
| 	if (attr == INVALID_FILE_ATTRIBUTES) | ||||
| 		return 0; | ||||
| 	 | ||||
| 	if (attr & FILE_ATTRIBUTE_DIRECTORY) | ||||
| 		return 1; | ||||
| 	 | ||||
| 	return 0; | ||||
| #else | ||||
| 	struct stat s; | ||||
| 	 | ||||
| 	if (stat(file, &s) != 0) | ||||
| 		return 0; | ||||
| 	 | ||||
| 	if (S_ISDIR(s.st_mode)) | ||||
| 		return 1; | ||||
| 	 | ||||
| 	return 0; | ||||
| #endif | ||||
| 	return DirExists(file) ? 1 : 0; | ||||
| } | ||||
|  | ||||
| static cell AMX_NATIVE_CALL file_size(AMX *amx, cell *params) /* 1 param */ | ||||
|   | ||||
| @@ -39,6 +39,7 @@ | ||||
| #include "fakemeta.h" | ||||
| #include "newmenus.h" | ||||
| #include "natives.h" | ||||
| #include "binlog.h" | ||||
|  | ||||
| plugin_info_t Plugin_info =  | ||||
| { | ||||
| @@ -298,6 +299,13 @@ int	C_Spawn(edict_t *pent) | ||||
| 	// Set server flags | ||||
| 	memset(g_players[0].flags, -1, sizeof(g_players[0].flags)); | ||||
|  | ||||
| #if defined BINLOG_ENABLED | ||||
| 	if (!g_BinLog.Open()) | ||||
| 	{ | ||||
| 		LOG_ERROR(PLID, "Binary log failed to open."); | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	// ###### Load AMX scripts | ||||
| 	g_plugins.loadPluginsFromFile(get_localinfo("amxx_plugins", "addons/amxmodx/configs/plugins.ini")); | ||||
| 	g_plugins.Finalize(); | ||||
| @@ -317,6 +325,10 @@ int	C_Spawn(edict_t *pent) | ||||
| 	FF_ClientAuthorized = registerForward("client_authorized", ET_IGNORE, FP_CELL, FP_DONE); | ||||
| 	FF_ChangeLevel = registerForward("server_changelevel", ET_STOP, FP_STRING, FP_DONE); | ||||
|  | ||||
| #if defined BINLOG_ENABLED | ||||
| 	g_BinLog.CacheAllPlugins(); | ||||
| #endif | ||||
|  | ||||
| 	modules_callPluginsLoaded(); | ||||
|  | ||||
| 	// ###### Call precache forward function | ||||
|   | ||||
| @@ -57,6 +57,30 @@ ModuleCallReason g_ModuleCallReason; | ||||
|  | ||||
| extern const char* no_function;				// stupid work around | ||||
|  | ||||
| bool DirExists(const char *dir) | ||||
| { | ||||
| #if defined WIN32 || defined _WIN32 | ||||
| 	DWORD attr = GetFileAttributes(dir); | ||||
| 	 | ||||
| 	if (attr == INVALID_FILE_ATTRIBUTES) | ||||
| 		return false; | ||||
| 	 | ||||
| 	if (attr & FILE_ATTRIBUTE_DIRECTORY) | ||||
| 		return true; | ||||
| 	 | ||||
| #else | ||||
| 	struct stat s; | ||||
| 	 | ||||
| 	if (stat(dir, &s) != 0) | ||||
| 		return false; | ||||
| 	 | ||||
| 	if (S_ISDIR(s.st_mode)) | ||||
| 		return true; | ||||
| #endif | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void report_error(int code, char* fmt, ...) | ||||
| { | ||||
| 	va_list argptr; | ||||
|   | ||||
| @@ -78,6 +78,8 @@ class Debugger; | ||||
| Debugger *DisableDebugHandler(AMX *amx); | ||||
| void EnableDebugHandler(AMX *amx, Debugger *pd); | ||||
|  | ||||
| bool DirExists(const char *dir); | ||||
|  | ||||
| const char* GetFileName(AMX *amx); | ||||
|  | ||||
| #endif // __MODULES_H__ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user