Pulled in Pegasus's Changes

This commit is contained in:
bluesaxman 2019-10-07 10:35:55 -06:00
commit cdff163010
2 changed files with 121 additions and 84 deletions

View File

@ -1,5 +1,6 @@
# Warning this will not ask before destorying information
# WARNING: This program will not ask before destroying literally all of your data
Squeegy is designed to perform quick file table wipes and smart disk checks on many drives at once.
It is designed to be quick and to accuratly and clearly provide feedback to the user in order to separate out bad and good drives,
and to determin if a drive has actually been properly wiped.
Squeegy is designed to perform quick file table wipes and smart disk checks on
many drives at once. It is designed to be quick and to accurately and clearly
provide feedback to the user in order to separate out good and bad drives, and
to determine if a drive has actually been properly wiped.

196
wipe.pl
View File

@ -3,35 +3,62 @@ use strict;
use warnings;
use Digest::MD5 "md5_base64";
use POSIX;
use v5.10;
# create our random data and store it in ram so we can keep reusing it
open (my $drand, "<", "/dev/urandom");
# set CONFIRMATION_PHRASE to anything falsy (like zero) if you are a fast and
# loose badass and you don't need no stinkin' safety net.
use constant CONFIRMATION_PHRASE => "I am a pretty pink pineapple!";
my $termios = POSIX::Termios->new;
$termios->getattr(fileno(STDIN));
# fetch this value once and cache it
my $startup_lflag = $termios->getlflag();
# set termios lflag to not echo keystrokes, and take us out of line mode
$termios->setlflag($startup_lflag & ~(ECHO | ECHOK | ICANON));
$termios->setattr(fileno(STDIN), TCSANOW);
END { # reset termios lflag on exit
$termios->setlflag($startup_lflag);
$termios->setattr(fileno(STDIN), TCSANOW);
}
if ($>) {
say "This program requires root, sorry.";
exit;
}
# define some colors for convenience
my %color = (
# use tput to support anything with a terminfo entry
"brightred" => `tput setaf 9`,
"red" => `tput setaf 1`,
"green" => `tput setaf 2`,
"reset" => `tput sgr0`
);
my $notreally = grep /--notreally/, @ARGV;
if (!$notreally && CONFIRMATION_PHRASE) {
say "$color{brightred}WARNING$color{reset}: This program will $color{brightred}COMPLETELY DESTROY ALL DATA ON ALL SYSTEM DRIVES$color{reset}";
print 'Please type "'.CONFIRMATION_PHRASE.qq(" if you are $color{brightred}CERTAIN$color{reset} you want to continue: );
chomp(my $confirm = <STDIN>);
do { say; exit } unless CONFIRMATION_PHRASE eq $confirm;
}
# create our random data and store it in RAM so we can keep reusing it
open(my $drand, "<", "/dev/urandom");
my $clobber;
read($drand, $clobber, 10240000);
close($drand);
my $clobsum = md5_base64($clobber);
# define some colors for conviniance
my %color = (
"red" => "\e[0;31m",
"green" => "\e[0;32m",
"reset" => "\e[0m"
);
my @failed = ();
my @good = ();
my $term = POSIX::Termios->new;
# for providing a waiting prompt
sub anykey {
print shift;
my $key;
my $oldflag = $term->getlflag;
$term->setlflag(ICANON);
system "stty", '-icanon', 'eol', "\001"; #ISNT POSIX compliant
$key = getc(STDIN);
$term->setlflag($oldflag);
system "stty", 'icanon', 'eol', "^@";
return $key
return getc(STDIN);
}
# to handle errors without using die
@ -43,7 +70,7 @@ sub warning {
# home made uniq function
sub uniq {
my %seen;
return grep { !$seen{$_}++} @_;
return grep { !$seen{$_}++ } @_;
}
# To get the list of devices we will be cleaning
@ -57,10 +84,10 @@ sub getdisks {
chomp( $serial );
chomp( $model );
if ( $serial && $model ) {
print $devicepath."\t".$serial."\n";
$listhash{$_}{"path"} = $devicepath;
$listhash{$_}{"serial"} = $serial;
$listhash{$_}{"model"} = $model;
say "$devicepath\t$serial";
$listhash{$_}{path} = $devicepath;
$listhash{$_}{serial} = $serial;
$listhash{$_}{model} = $model;
} else { next; }
}
return %listhash;
@ -71,27 +98,36 @@ sub wipethemdrives {
my $diskid = shift;
my $disks = shift;
# Write
print $disks->{$diskid}{"path"}." - Serial:".$disks->{$diskid}{"serial"}." is being wiped...\n";
open(my $diskw, ">", $disks->{$diskid}{"path"}) or return warning("could not open ".$disks->{$diskid}{"path"});
print $diskw $clobber;
close($diskw);
system("sync");
print "Wipe attempt complete, checking...";
# Read
open(my $diskr, "<", $disks->{$diskid}{"path"}) or return warning("could not open ".$disks->{$diskid}{"path"});
my $diskdata;
read($diskr, $diskdata, 10240000);
my $disksum = md5_base64($diskdata);
close($diskr);
# print "Disk Checksum: ".$disksum."\n";
say "$disks->{$diskid}{path} - Serial:$disks->{$diskid}{serial} is being wiped...";
my $disksum;
if ($notreally) {
print "Pretend wipe complete, pretending to check...";
$disksum = $clobsum;
} else {
open(my $diskw, ">", $disks->{$diskid}{path}) or return warning("could not open $disks->{$diskid}{path}");
print $diskw $clobber;
close($diskw);
system("sync");
print "Wipe attempt complete, checking...";
# Read
open(my $diskr, "<", $disks->{$diskid}{path}) or return warning("could not open $disks->{$diskid}{path}");
my $diskdata;
read($diskr, $diskdata, 10240000);
$disksum = md5_base64($diskdata);
close($diskr);
}
# say "Disk Checksum: $disksum";
if ($disksum eq $clobsum) {
printf("%-37.37s %9.9s", "Checksum ",$color{"green"}."PASSED!!!".$color{"reset"});
# print $disks->{$diskid}{"path"}." is clean.\n";
say +("."x28)."Checksum $color{green}PASSED!!!$color{reset}";
# say "$disks->{$diskid}{path} is clean.";
return 1;
} else {
# print "Wipe Checksum: ".$clobsum."\n";
printf("%-37.37s %9.9s", "Checksum ",$color{"red"}."FAILED!!!".$color{"reset"});
# print $disks->{$diskid}{"path"}." did not take, it could be bad.\n";
# say "Wipe Checksum: $clobsum";
say +("."x28)."Checksum $color{red}FAILED!!!$color{reset}";
# this code will not work on the majority of terminals,
# now that we support anything with a terminfo entry.
# printf("%-37.37s %9.9s\n", "Checksum ","$color{red}FAILED!!!$color{reset}");
# say "$disks->{$diskid}{path} did not take, it could be bad.";
return 0;
}
}
@ -101,29 +137,30 @@ sub smartcheck {
# Do our smart disk thing...
my $diskid = shift;
my $disks = shift;
print "Checking S.M.A.R.T. variables...\n";
# print 'smartctl '.$disks->{$diskid}{"path"}.' -A -f hex,id | grep "^0x"'."\n";
(my $smartcommand = `smartctl $disks->{$diskid}{"path"} -A -f hex,id | grep "^0x"`) or (print $!."\ncould not check smart data, skipping\n" and return 1);
say"Checking S.M.A.R.T. variables...";
# say qq(smartctl $disks->{$diskid}{path} -A -f hex,id | grep "^0x");
(my $smartcommand = `smartctl $disks->{$diskid}{path} -A -f hex,id | grep "^0x"`) or (say "$!\ncould not check smart data, skipping" and return 1);
for (split("\n",$smartcommand)) {
my @smartdata = split(/\s+/,$_);
$disks->{$diskid}{"smart"}{$smartdata[0]}{"id"} = $smartdata[0];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"name"} = $smartdata[1];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"flag"} = $smartdata[2];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"value"} = $smartdata[3];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"worst"} = $smartdata[4];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"thresh"} = $smartdata[5];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"type"} = $smartdata[6];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"updated"} = $smartdata[7];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"when_failed"} = $smartdata[8];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"raw_value"} = $smartdata[9];
$disks->{$diskid}{smart}{$smartdata[0]}{id} = $smartdata[0];
$disks->{$diskid}{smart}{$smartdata[0]}{name} = $smartdata[1];
$disks->{$diskid}{smart}{$smartdata[0]}{flag} = $smartdata[2];
$disks->{$diskid}{smart}{$smartdata[0]}{value} = $smartdata[3];
$disks->{$diskid}{smart}{$smartdata[0]}{worst} = $smartdata[4];
$disks->{$diskid}{smart}{$smartdata[0]}{thresh} = $smartdata[5];
$disks->{$diskid}{smart}{$smartdata[0]}{type} = $smartdata[6];
$disks->{$diskid}{smart}{$smartdata[0]}{updated} = $smartdata[7];
$disks->{$diskid}{smart}{$smartdata[0]}{when_failed} = $smartdata[8];
$disks->{$diskid}{smart}{$smartdata[0]}{raw_value} = $smartdata[9];
}
close( $smartcommand );
for my $smartentry (sort {$a cmp $b} keys %{$disks->{$diskid}{"smart"}}) {
if ($disks->{$diskid}{"smart"}{$smartentry}{"id"} =~ /0x05|0x07|0xc4|0xc5|0xc6|0xc7/) {
printf("%-6.6s %-26.26s\t%-26.26s\t", $disks->{$diskid}{"smart"}{$smartentry}{"id"}, $disks->{$diskid}{"smart"}{$smartentry}{"name"}, $disks->{$diskid}{"smart"}{$smartentry}{"raw_value"});
if ($disks->{$diskid}{"smart"}{$smartentry}{"raw_value"} =~ /0|0\/0/) {
print $color{"green"}."Passed".$color{"reset"}."\n";
} else { print $color{"red"}."Failed".$color{"reset"}."\n"; return 0}
# these are incredibly strict requirements, you probably should be looking at the when_failed field instead...
for my $smartentry (sort {$a cmp $b} keys %{$disks->{$diskid}{smart}}) {
if ($disks->{$diskid}{smart}{$smartentry}{id} =~ /0x05|0x07|0xc4|0xc5|0xc6|0xc7/) {
printf("%-6.6s %-26.26s\t%-26.26s\t", $disks->{$diskid}{smart}{$smartentry}{id}, $disks->{$diskid}{smart}{$smartentry}{name}, $disks->{$diskid}{smart}{$smartentry}{raw_value});
if ($disks->{$diskid}{smart}{$smartentry}{raw_value} =~ /0|0\/0/) {
say "$color{green}Passed$color{reset}";
} else { say "$color{red}Failed$color{reset}"; return 0}
}
}
@ -134,37 +171,36 @@ sub smartcheck {
while () {
my %disks = getdisks();
my $batchcount = keys %disks;
print "About to wipe ".$batchcount." drives with the following serial numbers:\n";
foreach my $diskid (sort {$disks{$a}{"serial"} cmp $disks{$b}{"serial"}} keys %disks) {
print $disks{$diskid}{"serial"}."\n";
say "$color{red}WARNING:$color{reset} This program will completely destroy all data on $batchcount drives with the following serial numbers:";
foreach my $diskid (sort {$disks{$a}{serial} cmp $disks{$b}{serial}} keys %disks) {
say $disks{$diskid}{serial};
}
anykey("Hit any key to continue...\n");
exit unless "\n" eq anykey("Last chance to save your data, hit ENTER to DESTROY ALL DATA, or any other key to abort!\n");
foreach my $diskid (sort {$a cmp $b}keys %disks) {
# Disabling this because it just dosen't look good.
# print "\e[0;0H\e[2J"; # move cursor to 0,0 and then clear all text below.
print "="x33;
printf '[ %-10s ]', $diskid;
print "="x33;
print "\n";
$disks{$diskid}{"wipe"} = wipethemdrives($diskid,\%disks);
if ($disks{$diskid}{"wipe"} == 1) {
$disks{$diskid}{"smartpass"} = smartcheck($diskid,\%disks);
if ($disks{$diskid}{"smartpass"} == 1) {
# print "Smart looks good.\n";
push(@good, sprintf("%-26.26s\t%46.46s",$disks{$diskid}{"serial"},$disks{$diskid}{"model"}));
} else { push(@failed, $disks{$diskid}{"serial"}); }
} else { push(@failed, $disks{$diskid}{"serial"}); }
say "="x33;
$disks{$diskid}{wipe} = wipethemdrives($diskid,\%disks);
if ($disks{$diskid}{wipe} == 1) {
$disks{$diskid}{smartpass} = smartcheck($diskid,\%disks);
if ($disks{$diskid}{smartpass} == 1) {
# say "Smart looks good.";
push(@good, sprintf("%-26.26s\t%46.46s",$disks{$diskid}{serial},$disks{$diskid}{model}));
} else { push(@failed, $disks{$diskid}{serial}); }
} else { push(@failed, $disks{$diskid}{serial}); }
print "="x80;
print "\n"x5;
}
print "These drives were successfully wiped and passed SMART, they may be put back into\nproduction:\n";
print $color{"green"}.join("\n",sort {$a cmp $b} uniq(@good)).$color{"reset"};
anykey("\nHit any key to see the list of failed drives. Please also note any drives that\ndo not appear on ether list. Those should be tried again (if they do not show\nup after three times assume falure).");
print "The folowing drives are bad, RMA or shred:\n";
print join("\n",sort {$a cmp $b} uniq(@failed));
say "These drives were successfully wiped and passed SMART, they may be put back into\nproduction:";
print $color{green}.join("\n",sort {$a cmp $b} uniq(@good)).$color{reset};
anykey("\nHit any key to see the list of failed drives. Please also note any drives that\ndo not appear on either list. Those should be tried again (if they do not show\nup after three times assume failure).\n");
say "$color{red}The following drives are bad, RMA or shred:";
say join("\n",sort {$a cmp $b} uniq(@failed));
print "$color{green}";
@failed = ();
@good = ();
print "\n";
print $color{"green"}.("-"x34).$color{"red"}."\nWipe complete, insert more drives.\n".$color{"green"}.("-"x34).$color{"reset"}."\n";
say $color{green}.("-"x34).$color{red}."\nWipe complete, insert more drives.\n".$color{green}.("-"x34).$color{reset};
anykey("Hit any key when ready to continue...\n");
}