#include "logging.h" #include #include #include #include #include #include #include #include #define LOG_MAX_SIZE (10 * 1024 * 1024) #define LOG_MAX_ROTATIONS 5 static int g_debug_mode = 0; static FILE *g_log_file = NULL; static char g_log_path[512] = ""; static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; void logging_set_debug(int enabled) { g_debug_mode = enabled; } int logging_get_debug(void) { return g_debug_mode; } static void rotate_log_file(void) { if (g_log_path[0] == '\0') return; if (g_log_file && g_log_file != stdout && g_log_file != stderr) { fclose(g_log_file); g_log_file = NULL; } char old_path[520], new_path[520]; snprintf(old_path, sizeof(old_path), "%s.%d", g_log_path, LOG_MAX_ROTATIONS); unlink(old_path); for (int i = LOG_MAX_ROTATIONS - 1; i >= 1; i--) { snprintf(old_path, sizeof(old_path), "%s.%d", g_log_path, i); snprintf(new_path, sizeof(new_path), "%s.%d", g_log_path, i + 1); rename(old_path, new_path); } snprintf(new_path, sizeof(new_path), "%s.1", g_log_path); rename(g_log_path, new_path); g_log_file = fopen(g_log_path, "a"); if (!g_log_file) { g_log_file = stdout; } } static void check_rotation(void) { if (!g_log_file || g_log_file == stdout || g_log_file == stderr) return; if (g_log_path[0] == '\0') return; struct stat st; if (fstat(fileno(g_log_file), &st) == 0) { if (st.st_size >= LOG_MAX_SIZE) { rotate_log_file(); } } } int logging_set_file(const char *path) { pthread_mutex_lock(&log_mutex); if (g_log_file && g_log_file != stdout && g_log_file != stderr) { fclose(g_log_file); } g_log_path[0] = '\0'; if (path) { strncpy(g_log_path, path, sizeof(g_log_path) - 1); g_log_path[sizeof(g_log_path) - 1] = '\0'; g_log_file = fopen(path, "a"); if (!g_log_file) { g_log_file = stdout; g_log_path[0] = '\0'; pthread_mutex_unlock(&log_mutex); return -1; } } else { g_log_file = stdout; } pthread_mutex_unlock(&log_mutex); return 0; } void logging_cleanup(void) { pthread_mutex_lock(&log_mutex); if (g_log_file && g_log_file != stdout && g_log_file != stderr) { fclose(g_log_file); } g_log_file = NULL; g_log_path[0] = '\0'; pthread_mutex_unlock(&log_mutex); } static void log_message(const char *level, const char *format, va_list args) { pthread_mutex_lock(&log_mutex); check_rotation(); FILE *out = g_log_file ? g_log_file : stdout; time_t now; time(&now); struct tm *local = localtime(&now); char buf[32]; strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", local); fprintf(out, "%s - %-5s - ", buf, level); vfprintf(out, format, args); fprintf(out, "\n"); fflush(out); pthread_mutex_unlock(&log_mutex); } void log_error(const char *format, ...) { va_list args; va_start(args, format); int saved_errno = errno; char msg[1024]; vsnprintf(msg, sizeof(msg), format, args); va_end(args); pthread_mutex_lock(&log_mutex); check_rotation(); FILE *out = g_log_file ? g_log_file : stderr; time_t now; time(&now); struct tm *local = localtime(&now); char buf[32]; strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", local); if (saved_errno != 0) { fprintf(out, "%s - ERROR - %s: %s\n", buf, msg, strerror(saved_errno)); } else { fprintf(out, "%s - ERROR - %s\n", buf, msg); } fflush(out); pthread_mutex_unlock(&log_mutex); } void log_info(const char *format, ...) { va_list args; va_start(args, format); log_message("INFO", format, args); va_end(args); } void log_debug(const char *format, ...) { if (!g_debug_mode) return; va_list args; va_start(args, format); log_message("DEBUG", format, args); va_end(args); }