Il programma è supportato per Windows e per Linux (x11 o Wayland).
Per installare il programma, scaricare la cartella compressa con la build da ./Build/<OS>, spostarla nella posizione in cui si intende installare l'applicazione ed estrarne il contenuto (in Linux: tar -xvzf emergency-backup_Linux.tar.gz .). È anche possibile compilare il progetto dalla repository come specificato nella prossima sezione (consigliato per Linux per via delle dipendenze).
Successivamente:
- Windows: eseguire
main_emergency-backup.execome amministratore - Linux: eseguire
main_emergency-backupNON consudoin Linux (la password disudoper l'utente corrente verrà richiesta successivamente dall'installer).
Inoltre, il programma sarà impostato per essere eseguito ogni volta che il computer verrà acceso, la GUI verrà aggiunta alla lista delle applicazione per entrambi i sistemi operativi e:
- Windows: sarà anche accessibile attraverso un link sul desktop
- Linux: sarà accessibile da terminale con il comando
emergency-backup
A installazione completata, il programma starà girando in background, la GUI si aprirà e verranno creati i seguenti file:
settings.json: file di configurazione, che può essere modificato anche con l'ausilio della GUIcpu_log.csv: file di log dell'utilizzo della CPU (-1 segnala l'accensione del programma)
Per disabilitare l'esecuzione a startup, fermare l'applicazione in background, rimuovere settings.json e i link creati:
- Windows: eseguire
disable.batcome amministratore - Linux: eseguire il comando
main_emergency-backupda terminale con--uninstallcome argomento senzasudo(la password per sudo verrà richiesta dall'uninstaller)
La rimozione dei file è a discrezione dell'utente.
Il programma può essere compilato eseguendo windows_build.bat o linux_build.sh, avendo la repository del progetto e cargo (Rust) e npm (Node.js) installati.
Il progetto compilato avrà:
main_emergency-backup(.exe): eseguibile principaleemergency-backup(.exe): eseguibile della GUIcat_ext.json: file di configurazione che contiene l'associazione delle estensioni dei file alle categorieicons: cartella con l'icona dell'appvoice_audios: cartella con i file audio (due lingue supportate: EN/IT)
Solo su Windows:
disable.bat: script per disinstallare
Cambiando le impostazioni, utilizzando la GUI o modificando direttamente il file settings.json nella cartella di installazione, è possibile agire sui seguenti parametri:
- Lingua: selezionare la lingua degli audio e delle finestre (supportati: EN/IT)
- Sorgenti: selezionare i file e le cartelle da copiare durante il backup, specificando per ogni sorgente (come liste separate da virgola):
- quali categorie di estensioni includere
- quali estensioni includere e quali escludere (indipendentemente dalle categorie specificate)
- quali percorsi relativi escludere
- Destinazione (opzionale): selezionare il percorso di destinazione, che può essere un drive esterno oppure una cartella condivisa; se non specificato (consigliato), al momento del backup il drive esterno con maggiore spazio disponibile verrà scelto come destinazione; inoltre, se lo spazio di archiviazione del drive si riempirà, verrà richiesto l'inserimento di un altro drive
Per la GUI, fare riferimento alla guida presente nel punto di domanda in alto a sinistra, mentre per il file setting.json è possibile fare riferimento al sample presente in ./Sample e rispettare le regole di formattazione dei file JSON.
NB: è possibile aggiungere, rimuovere o spostare le estensioni dalle categorie modificando il file cat_ext.json.
NB: i file senza estensione sono identificati dalla stringa No_ext.
Infine, ci sono alcune impostazioni più avanzate che sono solo accessibili modificando il file settings.json:
- Minimal: se la flag è settata, il backup avrà un file di log minimale con solo le informazioni essenziali, avendo un tempo di CPU inferiore, e in alcuni casi, anche un tempo totale di backup minore
- Threadpool: se la flag è settata, il backup avverrà attraverso l'utilizzo di un threadpool
- Screen info: lo struct contiene le informazioni relative allo schermo (in pixel) rilevate in automatico, considerando l'angolo in alto a destra come origine
NB: l'utilizzo di una threadpool per effettuare un'operazione di copia può portare ad un miglioramento delle prestazioni, ma potrebbe anche essere deleterio. Per discriminare cosa sia meglio è consigliato testare entrambi le possibilità con il drive che si intende utilizzare al momento del backup (se si specifica una sola sorgente, il backup sarà sempre single thread). Nella maggior parte dei casi, è consigliabile un backup single thread.
Per attivare la procedura, muovere il mouse lungo il mouse lungo il bordo dello schermo in senso orario, iniziando dall'angolo in alto a sinistra, formando un rettangolo. Un audio segnalerà il rilevamento del pattern e si aprirà una finestra di conferma. Da questo momento, si avranno 20 secondi per confermare, facendo un altro rettangolo, ma in senso antiorario. Scaduto il tempo, la procedura verrà annullata.
È inoltre possibile confermare o annullare tramite i pulsanti della finestra di conferma.
Nel caso in cui:
- nessuna destinazione sia stata selezionata nelle impostazioni,
- al momento di avvio del backup, non venisse rilevata alcuna unità USB,
- oppure, la memoria della destinazione corrente diventasse piena
un audio lo segnalerà e il programma rimarrà in attesa di una nuova unità. Dopo l’inserimento, premere Ctrl per confermare e proseguire con il backup. Per annullare, premere Esc.
Durante il processo di backup, una finestra mostrerà il progresso e le informazioni su sorgenti e destinazione.
Il programma creerà nella destinazione una cartella _Emergency_Backup_, in cui verranno create tante cartelle Source_<n> quante le sorgenti specificate nelle impostazioni.
Al termine del backup un messaggio audio ne comunicherà l'esito.
Poi, in caso di backup minimal, verrà creato un log minimal_backup_log.txt con le informazioni essenziali. Altrimenti, verranno creati backup_log.txt, contenente informazioni dettagliate del backup, e un log _backup_paths_log.json per ciascuna sorgente con gli esiti di ciascun percorso processato.
Se la memoria del primo drive dovesse diventare piena, il nuovo drive conterrà anche i log del primo (verrà comunque tentata la scrittura dei log nel primo), oltre che, ovviamente, i file mancanti che non sono stati copiati in precedenza (con i relativi log).
In qualsiasi momento, se il programma dovesse chiudersi inaspettatamente, verrà aperta una finestra con dettagli sull'errore e verrà riprodotto un audio.
Se il rilevamento del pattern (rettangolo) per attivare la procedura di backup dovesse non funzionare su Linux con Wayland, è possibile premere Ctrl + CapsLock, mentre la modalità di conferma rimane invariata. Questa soluzione è stata necessaria in quanto non c'è un metodo consolidato per il rilevamento della posizione globale del mouse in Wayland, a causa della sicurezza imposta dal protocollo.
Questa funzione è utilizzabile eseguendo la build del progetto indicando la feature “wayland” (il Linux builder chiederà questa impostazione).
BackupGuiRust: contiene il progetto tauri dell'interfaccia per la modifica delle impostazioniMain: contiene il progetto rust dell'applicazione che gestisce il backup di emergenza
audio_playerstates_audio.rs: player audio per le voci guida
auto_launchstartup_launch.rs: abilita/disabilita l'esecuzione dell'app all'avvio del sistema operativo e crea/elimina i link (desktop/app)
backup_process: si occupa del backupbackup.rs: logica principale del backup e wrapper delle funzioni di copiacopy_thread.rs: funzioni di copia che iterano sulle cartelle e calcolano le statistichedestination.rs: richiesta e ricerca della destinazionelog.rs: funzioni di stampa dei logminimal.rs: funzioni di copia più veloce con meno statistichethreadpool.rs: threadpool per gestire copie concorrenti
cpu_logger: si occupa dei log sull'uso di cpucpu_log.rs: aggiorna il logcpu_time.rs: per ottenere il cpu time (usato anche dal backup)
pattern_detection: monitoraggio dei movimenti del mouse per attivazione/confermapatt_detect_state.rs: gestisce la logica di aggiornamento dello statopatt_detect.rs: gestisce gli interrupts del mouse
usb_driveusb.rs: legge i dirve USB connessi
window_spawnerwindow.rs: crea finestre per informare/avvisare l'utente
settings.rs: gestisce lettura/scrittura delle impostazionimain.rs: logica di esecuzione principale e argomenti di linea di comando
Il programma, tramite una macchina a stati finiti, attende l'esecuzione del pattern da parte dell'utente, poi gestisce la conferma e se richiesto esegue il processo di backup. Il rilevamento del pattern ed il log della cpu vengono eseguiti in thread separati, avviati all'inizio del programma. Siccome il rilevamento del pattern avviene tramite interrupt, lo stato viene salvato in una variabile globale protetta da mutex ed accoppiata ad una condition variable, in modo da rendere le fasi di attesa del main “non-busy”.
L'esecuzione all'avvio del sistema operativo viene abilitata la prima volta che si esegue l'app (se si provasse ad avviare l'app nuovamente, si otterrà una finestra d'errore):
- Windows: viene creato un task per eseguire il programma all'avvio con permessi di amministratore e vengono creati dei collegamenti sul desktop e nelle app del menu start
- Linux: vengono creati un file di autostart che esegue uno script bash, e dei link nel $PATH e nelle applicazioni (come entry desktop); inoltre, viene creata una regola sudo per permettere l'esecuzione del programma senza richiedere la password
Per disattivare il programma, viene lanciato l'eseguibile con un argomento di linea di comando.
Il backup viene gestito in un processo separato, creato come processo figlio del main, lanciando l'eseguibile con l'apposito argomento di linea di comando.
Il processo per prima cosa cerca la destinazione se non specificata nelle impostazioni. La ricerca viene effettuata nel bus USB, mentre le interazioni con la tastiera vengono catturate tramite gli interrupt e per gli stati viene usata una variabile globale thread-safe con condition variable (come per il rilevamento del pattern).
Successivamente, viene creato un vettore di struct di input con i dati di ciascuna sorgente, poi passato alla funzione di copia. La copia viene effettuata iterando su ciascuna cartella copiando file e sottocartelle e calcolando statistiche relative a numero e dimensione di file copiati. I filtri applicati (configurati nelle impostazioni) ed il calcolo delle statistiche dettagliate vengono gestiti tramite hash map o hash set. La copia ritorna una struct di output con i risultati. I vettori di struct sono utili per semplificare la gestione del backup nel caso multithread e la gestione dell'inserimento di un nuovo drive al riempimento del precedente.
Ci sono due versioni della funzione di copia: una minimal ed una completa. La differenza principale è l'assenza, nella versione minimal, dei log di ciascun path processato, siccome richiede un tempo di CPU maggiore dato che ha bisogno di salvare i dati in un vettore di dimensioni piuttosto elevate. Inoltre, la copia può essere eseguita multi-thread (tramite una threadpool) o single-thread, in base alle impostazioni specificate dall'utente e al numero di sorgenti selezionate.
Se la memoria dell'unità dovesse riempirsi, il programma chiederà e attenderà l'inserimento di una nuova unità USB, e riprenderà la copia da dove si era fermato, grazie alle modifiche fatte alle struct di input nel vettore. Alla fine del backup verranno stampati i log.
La gestione delle interazioni tra il programma principale e le finestre, di conferma e di progresso, avviene tramite l'utilizzo di canali.
Per quanto riguarda gli audio, la sequenzialità della loro riproduzione è garantita da degli sleep che forzano l'attesa del thread.
In caso di errore fatale, avviene una cattura del panic, in modo tale che sia possibile mostrare la stringa di errore in una apposita finestra ed attivare un audio di segnalazione.
La GUI è stata sviluppata utilizzando Tauri, che combina il backend in Rust con il frontend in React. L'applicazione consente agli utenti di configurare le impostazioni per il backup dei dati, specificando cartelle, file e opzioni personalizzate per il salvataggio su disco nel file settings.json.
Il progetto è organizzato in due principali directory:
src: contiene i componenti React che gestiscono l'interfaccia utentesrc-tauri: contiene il codice Rust che gestisce la logica di backend, inclusa la manipolazione del file delle impostazioni
Questa cartella contiene l'applicazione frontend sviluppata con React. La struttura delle sottocartelle è la seguente:
-
components: contiene i componenti React utilizzati per l'interfaccia utente, quelli principali sono:DarkModeTable.jsx: componente che permette di inserire i percorsi dei file e delle cartelle da salvareInfoModal.jsx: componente per visualizzare informazioni modaliLanguageComponent.jsx: componente per cambiare la lingua dell'applicazioneMyFormComponent.jsx: componente per gestire il form di selezione delle preferenze relative alle categorie di file che si desidera includere o escludere dal backup
-
pages: contiene le pagine principali dell'applicazione:Homepage.jsx: la homepage dell'applicazione
-
File principali:
App.jsx: gestisce la logica dell'applicazione React e le chiamate API verso il backend RUSTmain.jsx: punto di ingresso dell'applicazione ReactApp.css: stili CSS per l'applicazione
Questa cartella contiene la logica backend dell'applicazione scritta in Rust:
main.rs: contiene tutte le funzioni principali necessarie per gestire le impostazioni, il caricamento e il salvataggio del filesettings.json, e la gestione delle preferenze dell'utentefile_categories.rs: contiene la gestione del mapping tra estensioni e categorie, leggendocat_ext.json
pattern_detectionlibxtst-dev libudev-dev libinput-dev libxdo-dev libxkbcommon-dev xorg-dev
audio_playerlibs2dl-dev
settingslibxcb1 libxrandr2
GUIlibwebkit2gtk-4.0-dev build-essential curl wget file libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev