#!/usr/bin/perl -w use strict; use warnings; use Digest::MD5 "md5_base64"; use POSIX; open (my $drand, "<", "/dev/urandom"); my $clobber; read($drand, $clobber, 10240000); close($drand); my $clobsum = md5_base64($clobber); my %color = ( "red" => "\e[0;31m", "green" => "\e[0;32m", "reset" => "\e[0m" ); my @failed = (); my $term = POSIX::Termios->new; 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 } sub warning { print shift; return 0; } sub getdisks { my $devices = `find /dev/sd*`; my %listhash = (); foreach(split("\n",$devices)) { my $devicepath = $_; my $serial = `udevadm info --query=all --name=$_ | grep SERIAL_SHORT | sed -e 's/^.*=//'`; chomp( $serial ); if ( $serial ) { print $devicepath."\t".$serial."\n"; $listhash{$_}{"path"} = $devicepath; $listhash{$_}{"serial"} = $serial; } else { next; } } return %listhash; } sub wipethemdrives { my $diskid = shift; my $disks = shift; 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"}); # open(my $diskw, ">", "./test") or warning("could not open "."./test"); print $diskw $clobber; close($diskw); system("sync"); print "Wipe attempt complete, checking...\n"; open(my $diskr, "<", $disks{$diskid}{"path"}) or return warning("could not open ".$disks{$diskid}{"path"}); # open(my $diskr, "<", "./test") or warning("could not open "."./test"); my $diskdata; read($diskr, $diskdata, 10240000); my $disksum = md5_base64($diskdata); close($diskr); print "Disk Checksum: ".$disksum."\n"; if ($disksum eq $clobsum) { print "Checksum ".$color{"green"}."PASSED!!!".$color{"reset"}."\n"; print $disks->{$diskid}{"path"}." is clean.\n"; return 1; } else { print "Wipe Checksum: ".$clobsum."\n"; print "Checksum ".$color{"red"}."FAILED!!!".$color{"reset"}."\n"; print $disks->{$diskid}{"path"}." did not take, it could be bad.\n"; return 0; } } 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); 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]; } close( $smartcommand ); for my $smartentry (keys %{$disks->{$diskid}{"smart"}}) { if ($disks->{$diskid}{"smart"}{$smartentry}{"id"} =~ /0x05|0x07|0xc4|0xc5|0xc6|0xc7/) { print $disks->{$diskid}{"smart"}{$smartentry}{"id"}." ".$disks->{$diskid}{"smart"}{$smartentry}{"name"}."\t".$disks->{$diskid}{"smart"}{$smartentry}{"raw_value"}."\t"; 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} } } return 1; } while () { my %disks = getdisks(); my $batchcount = keys %disks; print "About to wipe ".$batchcount." drives with the following serial numbers:\n"; foreach my $diskid (keys %disks) { print $disks{$diskid}{"serial"}."\n"; } anykey("Hit any key to continue...\n"); foreach my $diskid (keys %disks) { print "\e[J"; 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"; } else { push(@failed, $disks{$diskid}{"serial"}); } } else { push(@failed, $disks{$diskid}{"serial"}); } print "="x80; print "\n"x5; } print "The folowing drives did not wipe successfully,\nThey may need another attempt or they may be bad.\n"; print join("\n",@failed); @failed = (); print "\nWipe complete, insert more drives.\n"; anykey("Hit any key when ready to continue...\n"); }