Restore

O Operator
Restore

Restore file to captured state

Every captured change carries its SHA-256-addressed content in BLOB_STORE. Restoring writes that content back to the original path — current file gets backed up to <path>.drift_restore_backup_<epoch> before overwrite.

What will change
Preview -- nothing has been written yet.
Target file/var/www/vhosts/3dshawn.com/site1/file_monitors.cgi
SiteDriftSense self-monitor on local
Kindlocal
Captured at2026-07-10 18:57:29
Captured SHAf0a44a1113a6c6e97a9dbc36220a70852c3cdb19166afd64447abd1cbc9234ce
Current state on disk
Live check just now. If SHAs match, the restore is a no-op.
File presentyes
Size2883 bytes
Current SHA6db9f3b7ebe4
Same as captured?no -- restore will change it
What restore will change — live diff
Left column shows current on-disk content; right shows what restore will write. +3 additions, -20 deletions, 37 unchanged context lines.
11#!/usr/bin/perl
22use strict; use warnings; use CGI ();
33use MODS::Config; use MODS::DBConnect; use MODS::Template; use MODS::PageWrapper;
44my $cgi = CGI->new; my $db = MODS::DBConnect->new; my $tpl = MODS::Template->new;
55$|=1;
66my $dbh = $db->db_connect or die "DB connect failed\n";
77
88if (($ENV{REQUEST_METHOD} || '') eq 'POST' && $cgi->param('save')) {
99 my $q_name = $dbh->quote($cgi->param('scan_name') || '');
1010 my $q_path = $dbh->quote($cgi->param('scan_path') || '');
1111 my $q_ig = $dbh->quote($cgi->param('ignore_list') || '.git/,node_modules/,*.log,*.tmp,.DS_Store');
1212 my $q_ft = $dbh->quote($cgi->param('file_type_filter') || '');
1313 my $status = $cgi->param('status') ? 1 : 0;
14 my $ret = int($cgi->param('retention_days') || 0);
15 my $ret_expr = $ret > 0 ? $ret : 'NULL';
1614 $db->db_readwrite($dbh, qq~
1715 INSERT INTO FILE_MONITOR_SETTINGS
18 (scan_name, scan_path, ignore_list, file_type_filter, status, server_id, retention_days)
19 VALUES ($q_name, $q_path, $q_ig, $q_ft, $status, 1, $ret_expr)
16 (scan_name, scan_path, ignore_list, file_type_filter, status, server_id)
17 VALUES ($q_name, $q_path, $q_ig, $q_ft, $status, 1)
2018 ~, __FILE__, __LINE__);
2119 print "Status: 302 Found\nLocation: /file_monitors.cgi?saved=1\n\n"; exit;
22}
23
24# POST-update: change per-monitor retention_days
25if (($ENV{REQUEST_METHOD} || '') eq 'POST' && $cgi->param('update_retention')) {
26 my $mid = int($cgi->param('mid') || 0);
27 my $ret = int($cgi->param('retention_days') || 0);
28 my $ret_expr = $ret > 0 ? $ret : 'NULL';
29 $db->db_readwrite($dbh,
30 "UPDATE FILE_MONITOR_SETTINGS SET retention_days = $ret_expr WHERE file_monitor_list_id = $mid",
31 __FILE__, __LINE__);
32 print "Status: 302 Found\nLocation: /file_monitors.cgi?updated=1\n\n"; exit;
3320}
3421
3522print "Content-Type: text/html; charset=utf-8\nCache-Control: no-cache\n\n";
3623my @rows = $db->db_readwrite_multiple($dbh, q~
3724 SELECT file_monitor_list_id AS id, scan_name, scan_path, ignore_list, file_type_filter,
38 status, retention_days,
39 DATE_FORMAT(last_scanned, '%b %d %H:%i') AS last_h
25 status, DATE_FORMAT(last_scanned, '%b %d %H:%i') AS last_h
4026 FROM FILE_MONITOR_SETTINGS ORDER BY file_monitor_list_id ASC
4127~, __FILE__, __LINE__);
4228foreach my $r (@rows) {
4329 $r->{status_pill} = $r->{status} ? 'pill-ok' : 'pill-mute';
4430 $r->{status_lbl} = $r->{status} ? 'ACTIVE' : 'DISABLED';
4531 $r->{ignore_preview} = $r->{ignore_list} ? substr($r->{ignore_list}, 0, 50) . (length($r->{ignore_list}) > 50 ? '...' : '') : '';
46 $r->{retention_h} = defined($r->{retention_days}) && $r->{retention_days} > 0
47 ? "$r->{retention_days} d" : '(global)';
48 $r->{retention_days} //= 0;
4932}
5033$db->db_disconnect($dbh);
5134
5235my @body = $tpl->template('file_monitors.html',
5336 { rows => \@rows, has_rows => scalar(@rows) ? 1 : 0, total => scalar @rows });
5437MODS::PageWrapper->new->wrapper(
5538 page_title => 'File monitors', page_key => 'file_monitors',
5639 body_html => join('', @body), userinfo => { display_name => 'Operator' },
5740);
Confirm restore
Backs current content to <target>.drift_restore_backup_<epoch>, writes the captured content, verifies SHA post-write.
Cancel Logged to RESTORE_LOG regardless of outcome.