#if defined BINLOG_ENABLED #include #include "amxmodx.h" #include "binlog.h" BinLog g_BinLog; int g_binlog_level = 0; int g_binlog_maxsize = 0; 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); /** * it's now safe to create the binary log */ FILE *fp = fopen(m_logfile.c_str(), "wb"); if (!fp) return false; int magic = BINLOG_MAGIC; short vers = BINLOG_VERSION; char c = sizeof(time_t); fwrite(&magic, sizeof(int), 1, fp); fwrite(&vers, sizeof(short), 1, fp); fwrite(&c, sizeof(char), 1, fp); WritePluginDB(fp); fclose(fp); m_state = true; WriteOp(BinLog_Start, -1); return true; } void BinLog::Close() { WriteOp(BinLog_End, -1); m_state = false; } void BinLog::WriteOp(BinLogOp op, int plug, ...) { if (!m_state) return; FILE *fp = fopen(m_logfile.c_str(), "ab"); if (!fp) return; if (g_binlog_maxsize && op != BinLog_End) { fseek(fp, 0, SEEK_END); if (ftell(fp) > (g_binlog_maxsize * (1024 * 1024))) { fclose(fp); Close(); Open(); fp = fopen(m_logfile.c_str(), "ab"); if (!fp) return; } } unsigned char c = static_cast(op); time_t t = time(NULL); float gt = gpGlobals->time; fwrite(&c, sizeof(char), 1, fp); fwrite(&t, sizeof(time_t), 1, fp); fwrite(>, sizeof(float), 1, fp); fwrite(&plug, sizeof(int), 1, fp); va_list ap; va_start(ap, plug); switch (c) { case BinLog_Registered: { const char *title = va_arg(ap, const char *); const char *vers = va_arg(ap, const char *); c = (char)strlen(title); fwrite(&c, sizeof(char), 1, fp); fwrite(title, sizeof(char), c+1, fp); c = (char)strlen(vers); fwrite(&c, sizeof(char), 1 ,fp); fwrite(vers, sizeof(char), c+1, fp); break; } case BinLog_NativeCall: { int native = va_arg(ap, int); int params = va_arg(ap, int); fwrite(&native, sizeof(int), 1, fp); fwrite(¶ms, sizeof(int), 1, fp); break; } case BinLog_NativeRet: { cell retval = va_arg(ap, cell); fwrite(&retval, sizeof(cell), 1, fp); break; } case BinLog_NativeError: { int err = va_arg(ap, int); const char *msg = va_arg(ap, const char *); short len = (short)strlen(msg); fwrite(&err, sizeof(int), 1, fp); fwrite(&len, sizeof(short), 1, fp); fwrite(msg, sizeof(char), len+1, fp); break; } case BinLog_CallPubFunc: { int num = va_arg(ap, int); fwrite(&num, sizeof(int), 1, fp); break; } case BinLog_SetLine: { int line = va_arg(ap, int); fwrite(&line, sizeof(int), 1, fp); break; } case BinLog_FormatString: { int param = va_arg(ap, int); int maxlen = va_arg(ap, int); const char *str = va_arg(ap, const char *); short len = (short)strlen(str); fwrite(¶m, sizeof(int), 1, fp); fwrite(&maxlen, sizeof(int), 1, fp); fwrite(&len, sizeof(short), 1, fp); fwrite(str, sizeof(char), len+1, fp); break; } case BinLog_NativeParams: { cell *params = va_arg(ap, cell *); cell num = params[0] / sizeof(cell); fwrite(&num, sizeof(cell), 1, fp); for (cell i=1; i<=num; i++) fwrite(&(params[i]), sizeof(cell), 1, fp); break; } case BinLog_GetString: { cell addr = va_arg(ap, cell); const char *str = va_arg(ap, const char *); short len = (short)strlen(str); fwrite(&addr, sizeof(cell), 1, fp); fwrite(&len, sizeof(short), 1, fp); fwrite(str, sizeof(char), len+1, fp); break; } case BinLog_SetString: { cell addr = va_arg(ap, cell); int maxlen = va_arg(ap, int); const char *str = va_arg(ap, const char *); short len = (short)strlen(str); fwrite(&addr, sizeof(cell), 1, fp); fwrite(&maxlen, sizeof(int), 1, fp); fwrite(&len, sizeof(short), 1, fp); fwrite(str, sizeof(char), len+1, fp); break; } }; va_end(ap); fclose(fp); } void BinLog::WritePluginDB(FILE *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; if (c && pl->isDebug()) c = 2; 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 natives, publics; AMX *amx = pl->getAMX(); amx_NumNatives(amx, &natives); amx_NumPublics(amx, &publics); fwrite(&natives, sizeof(int), 1, fp); fwrite(&publics, sizeof(int), 1, fp); char name[34]; for (int i=0; i