Files
x3-backup/src/main.cpp
T
x3 4bff4f3db2 refactor: run as root via pkexec, remove sudo handling
- Add privilege escalation at startup (pkexec if not root)
- Remove all sudo password handling (echo password | sudo -S)
- Remove show_sudo_dialog and current_sudo_password_
- Remove --sudo-password CLI option
- All rsync/restore operations run directly as root
- format_size: use GB as default unit for large files
- Remove [cmd] log leaking sudo password
- Simplify snapshot_manager: no sudo_password parameter
- Simplify rsync_manager: no sudo_password parameter
2026-09-08 09:16:31 +00:00

170 lines
4.4 KiB
C++

#include <gtk/gtk.h>
#include <glib.h>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <fstream>
#include <string>
#include <unistd.h>
#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 bool is_root() {
return getuid() == 0;
}
static void escalate_privileges(int argc, char* argv[]) {
if (is_root()) return;
g_print("x3-backup requires root privileges. Re-launching with pkexec...\n");
std::string cmd = "pkexec";
for (int i = 0; i < argc; i++) {
std::string arg = argv[i];
if (arg.find(' ') != std::string::npos)
cmd += " \"" + arg + "\"";
else
cmd += " " + arg;
}
int ret = system(cmd.c_str());
exit(ret);
}
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 (uid=%d) ===", getuid());
g_message("Log file: %s", path.c_str());
}
int main(int argc, char* 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;
}
}
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("Note: x3-backup requires root privileges and will prompt\n");
g_print(" for authentication via pkexec on startup.\n\n");
g_print("Log file: ~/.config/x3-backup/x3-backup.log\n");
return 0;
}
escalate_privileges(argc, argv);
gtk_init(&argc, &argv);
setup_logging(cli_mode);
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;
}