95 string conf_path =
"";
101 log_debug(
"BastionGuard BackupImport: nessuna config trovata");
106 result.config_path = conf_path;
107 log_msg(
"BastionGuard BackupImport: config trovata in %s".printf(conf_path));
115 if (result.backup_device.length == 0) {
116 log_error(
"BastionGuard BackupImport: device con UUID %s non trovato".printf(result.backup_uuid));
119 log_msg(
"BastionGuard BackupImport: device backup = %s".printf(result.backup_device));
127 result.snapshots_path = result.mount_path +
"/bastionguard-backup-btrfs/snapshots";
129 result.snapshots_path = result.mount_path +
"/bastionguard-backup/snapshots";
132 if (FileUtils.test(result.snapshots_path, FileTest.IS_DIR))
135 log_msg(
"BastionGuard BackupImport: dir snapshot non trovata in %s".printf(result.snapshots_path));
137 log_msg(
"BastionGuard BackupImport: trovati %d snapshot".printf(result.snapshots.size));
148 bool remove_timeshift_config =
false,
149 Gtk.Window? parent_window =
null) {
152 log_error(
"BastionGuard BackupImport: nulla da migrare");
156 log_msg(
"==> BastionGuard BackupImport: avvio migrazione...");
159 string out_str, err_str;
162 try { GLib.Process.spawn_command_line_sync(
163 "mount -o remount,rw %s %s".printf(
165 out out_str, out err_str, out status);
166 }
catch (GLib.SpawnError e) {
log_error(e.message); }
167 }
catch (GLib.SpawnError e) {
log_error(
"mount remount: " + e.message);
return false; }
169 log_error(
"BastionGuard BackupImport: impossibile rimontare in rw: " + err_str);
176 string old_base, new_base;
178 old_base = detected.mount_path +
"/bastionguard-backup-btrfs";
179 new_base = detected.mount_path +
"/bastionguard-backup-btrfs";
181 old_base = detected.mount_path +
"/bastionguard-backup";
182 new_base = detected.mount_path +
"/bastionguard-backup";
185 if (FileUtils.test(old_base, FileTest.IS_DIR)) {
186 if (FileUtils.rename(old_base, new_base) != 0) {
187 log_error(
"BastionGuard BackupImport: impossibile rinominare %s → %s".printf(
188 old_base, new_base));
191 log_msg(
"BastionGuard BackupImport: rinominato %s → %s".printf(old_base, new_base));
194 detected.snapshots_path = new_base +
"/snapshots";
196 detected.snapshots_path = new_base +
"/snapshots";
201 foreach (var snap
in detected.snapshots) {
203 snap.path = snap.path.replace(old_base, new_base);
204 string info_path = snap.path +
"/info.json";
206 if (!FileUtils.test(info_path, FileTest.EXISTS))
continue;
210 FileUtils.get_contents(info_path, out raw);
211 }
catch {
continue; }
214 var parser =
new Json.Parser();
215 parser.load_from_data(raw);
216 var config = parser.get_root().get_object();
219 config.set_string_member(
"app-version",
220 "bastionguard-backup-%s".printf(Constants.VERSION));
222 config.set_string_member(
"imported-from",
"bastionguard-backup");
225 var gen =
new Json.Generator();
226 gen.set_root(
new Json.Node.alloc().init_object(config));
227 gen.set_pretty(
true);
228 string new_json = gen.to_data(
null);
229 FileUtils.set_contents(info_path, new_json);
232 log_error(
"BastionGuard BackupImport: errore aggiornamento %s: %s".printf(
233 info_path, e.message));
241 if (remove_timeshift_config) {
247 log_msg(
"BastionGuard BackupImport: config BastionGuard Backup rimossa");
249 log_error(
"BastionGuard BackupImport: impossibile rimuovere config: " + e.message);
256 log_msg(
"==> BastionGuard BackupImport: migrazione completata. " +
257 "%d snapshot importati.".printf(detected.snapshots.size));
293 if (uuid.length == 0)
return "";
294 string path =
"/dev/disk/by-uuid/" + uuid;
295 if (FileUtils.test(path, FileTest.EXISTS)) {
297 string out_str, err_str;
300 GLib.Process.spawn_command_line_sync(
301 "readlink -f " + path,
302 out out_str, out err_str, out status);
303 }
catch (GLib.SpawnError e) {
log_error(e.message); }
305 return out_str.strip();
308 string out_str, err_str;
311 GLib.Process.spawn_command_line_sync(
313 out out_str, out err_str, out status);
314 }
catch (GLib.SpawnError e) {
log_error(e.message); }
315 if (status == 0 && out_str.strip().length > 0)
316 return out_str.strip();
358 while ((name = dir.read_name()) !=
null) {
359 string snap_path = result.snapshots_path +
"/" + name;
360 if (!FileUtils.test(snap_path, FileTest.IS_DIR))
continue;
368 return (
int)(b.date_unix - a.date_unix);
371 log_error(
"BastionGuard BackupImport: errore scansione snapshot: " + e.message);
379 snap.is_btrfs = is_btrfs;
381 string info_path = path +
"/info.json";
382 if (!FileUtils.test(info_path, FileTest.EXISTS)) {
383 log_debug(
"BastionGuard BackupImport: info.json non trovato in " + path);
389 FileUtils.get_contents(info_path, out raw);
390 }
catch {
return snap; }
393 var parser =
new Json.Parser();
394 parser.load_from_data(raw);
395 var config = parser.get_root().get_object();
403 snap.date_unix = int64.parse(created_str);
404 var dt =
new DateTime.from_unix_utc(snap.date_unix).to_local();
405 snap.date = dt.format(
"%Y-%m-%d %H:%M:%S");
409 log_error(
"BastionGuard BackupImport: errore parsing info.json in %s: %s".printf(
420 var config =
new Json.Object();
425 var parser =
new Json.Parser();
426 parser.load_from_data(raw);
427 config = parser.get_root().get_object();
432 config.set_string_member(
"backup_device_uuid", detected.
backup_uuid);
433 config.set_string_member(
"btrfs_mode", detected.
is_btrfs.to_string());
434 config.set_string_member(
"imported_from_timeshift",
"true");
438 var gen =
new Json.Generator();
439 gen.set_root(
new Json.Node.alloc().init_object(config));
440 gen.set_pretty(
true);
441 string json_str = gen.to_data(
null);
445 log_error(
"BastionGuard BackupImport: impossibile scrivere config: " + e.message);