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 *sFile = get_amxstring(amx, params[1], 0, iLen); | ||||||
| 	char *file = build_pathname("%s", sFile); | 	char *file = build_pathname("%s", sFile); | ||||||
|  |  | ||||||
| #if defined WIN32 || defined _WIN32 | 	return DirExists(file) ? 1 : 0; | ||||||
| 	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 |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static cell AMX_NATIVE_CALL file_size(AMX *amx, cell *params) /* 1 param */ | static cell AMX_NATIVE_CALL file_size(AMX *amx, cell *params) /* 1 param */ | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ | |||||||
| #include "fakemeta.h" | #include "fakemeta.h" | ||||||
| #include "newmenus.h" | #include "newmenus.h" | ||||||
| #include "natives.h" | #include "natives.h" | ||||||
|  | #include "binlog.h" | ||||||
|  |  | ||||||
| plugin_info_t Plugin_info =  | plugin_info_t Plugin_info =  | ||||||
| { | { | ||||||
| @@ -298,6 +299,13 @@ int	C_Spawn(edict_t *pent) | |||||||
| 	// Set server flags | 	// Set server flags | ||||||
| 	memset(g_players[0].flags, -1, sizeof(g_players[0].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 | 	// ###### Load AMX scripts | ||||||
| 	g_plugins.loadPluginsFromFile(get_localinfo("amxx_plugins", "addons/amxmodx/configs/plugins.ini")); | 	g_plugins.loadPluginsFromFile(get_localinfo("amxx_plugins", "addons/amxmodx/configs/plugins.ini")); | ||||||
| 	g_plugins.Finalize(); | 	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_ClientAuthorized = registerForward("client_authorized", ET_IGNORE, FP_CELL, FP_DONE); | ||||||
| 	FF_ChangeLevel = registerForward("server_changelevel", ET_STOP, FP_STRING, FP_DONE); | 	FF_ChangeLevel = registerForward("server_changelevel", ET_STOP, FP_STRING, FP_DONE); | ||||||
|  |  | ||||||
|  | #if defined BINLOG_ENABLED | ||||||
|  | 	g_BinLog.CacheAllPlugins(); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	modules_callPluginsLoaded(); | 	modules_callPluginsLoaded(); | ||||||
|  |  | ||||||
| 	// ###### Call precache forward function | 	// ###### Call precache forward function | ||||||
|   | |||||||
| @@ -57,6 +57,30 @@ ModuleCallReason g_ModuleCallReason; | |||||||
|  |  | ||||||
| extern const char* no_function;				// stupid work around | 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, ...) | void report_error(int code, char* fmt, ...) | ||||||
| { | { | ||||||
| 	va_list argptr; | 	va_list argptr; | ||||||
|   | |||||||
| @@ -78,6 +78,8 @@ class Debugger; | |||||||
| Debugger *DisableDebugHandler(AMX *amx); | Debugger *DisableDebugHandler(AMX *amx); | ||||||
| void EnableDebugHandler(AMX *amx, Debugger *pd); | void EnableDebugHandler(AMX *amx, Debugger *pd); | ||||||
|  |  | ||||||
|  | bool DirExists(const char *dir); | ||||||
|  |  | ||||||
| const char* GetFileName(AMX *amx); | const char* GetFileName(AMX *amx); | ||||||
|  |  | ||||||
| #endif // __MODULES_H__ | #endif // __MODULES_H__ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user