#include #include #include #include #include #include #include #include #include "config.h" #include "rsync_manager.h" #include "snapshot_manager.h" #include "main_window.h" static FILE* log_file = nullptr; static bool log_to_stdout = false; static std::string get_log_path() { const char* home = getenv("HOME"); if (!home) home = "."; std::string dir = std::string(home) + "/.config/x3-backup"; std::string cmd = "mkdir -p \"" + dir + "\""; (void)system(cmd.c_str()); return dir + "/x3-backup.log"; } static void log_handler(const gchar* domain, GLogLevelFlags level, const gchar* message, gpointer) { const char* level_str = "INFO"; if (level & G_LOG_LEVEL_WARNING) level_str = "WARN"; if (level & G_LOG_LEVEL_CRITICAL) level_str = "CRIT"; if (level & G_LOG_LEVEL_ERROR) level_str = "ERROR"; time_t now = time(nullptr); struct tm* t = localtime(&now); char timebuf[32]; strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", t); char line[2048]; snprintf(line, sizeof(line), "[%s] [%s] %s: %s\n", timebuf, level_str, domain ? domain : "app", message); if (log_to_stdout) { fputs(line, stdout); fflush(stdout); } if (log_file) { fputs(line, log_file); fflush(log_file); } } static void setup_logging(bool cli_mode) { const char* env_log = g_getenv("X3_BACKUP_LOG"); if (env_log && strcmp(env_log, "1") == 0) { log_to_stdout = true; } if (cli_mode) { log_to_stdout = true; } std::string path = get_log_path(); log_file = fopen(path.c_str(), "a"); if (!log_file) { g_warning("Cannot open log file: %s", path.c_str()); } g_log_set_handler("x3-backup", (GLogLevelFlags)(G_LOG_LEVEL_MASK), log_handler, nullptr); g_log_set_handler(nullptr, (GLogLevelFlags)(G_LOG_LEVEL_MASK), log_handler, nullptr); g_message("=== x3-backup started ==="); g_message("Log file: %s", path.c_str()); } int main(int argc, char* argv[]) { gtk_init(&argc, &argv); bool system_mode = false; bool backup_now = false; bool show_help = false; bool cli_mode = false; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--system-backup") == 0) { system_mode = true; backup_now = true; cli_mode = true; } else if (strcmp(argv[i], "--backup") == 0) { backup_now = true; cli_mode = true; } else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { show_help = true; } else if (strcmp(argv[i], "--log") == 0) { log_to_stdout = true; } } setup_logging(cli_mode); if (show_help) { g_print("x3-Backup - GTK3 Backup/Snapshot Tool\n\n"); g_print("Usage: x3-backup [OPTIONS]\n\n"); g_print("Options:\n"); g_print(" --backup Create a backup immediately and exit\n"); g_print(" --system-backup Create a full system backup and exit\n"); g_print(" --log Print log to stdout\n"); g_print(" --help, -h Show this help\n\n"); g_print("Without options, x3-backup starts in GUI mode with system tray.\n\n"); g_print("Log file: ~/.config/x3-backup/x3-backup.log\n"); return 0; } Config config; config.load(); if (backup_now) { if (system_mode) { config.set_system_backup_mode(true); config.settings().source_path = "/"; g_message("System backup mode: backing up entire system"); } RsyncManager rsync(config); SnapshotManager snapshots(config, rsync); g_message("Starting backup..."); snapshots.cleanup_old_snapshots(); std::string ts = snapshots.create_snapshot(system_mode ? "System backup" : "Manual backup"); if (!ts.empty()) { g_message("Backup completed: %s", ts.c_str()); } else { g_warning("Backup failed!"); return 1; } return 0; } MainWindow window(config); window.run(); g_message("=== x3-backup exiting ==="); if (log_file) fclose(log_file); return 0; }