diff --git a/wipe.pl b/wipe.pl index 6d7f607..7e1d5f5 100755 --- a/wipe.pl +++ b/wipe.pl @@ -5,7 +5,7 @@ use Digest::MD5 "md5_base64"; use POSIX; use v5.10; -$| = 1; #turn off IO buffering +$| = 1; #turn off IO buffering for STDOUT # 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. @@ -39,10 +39,10 @@ my %color = ( "reset" => `tput sgr0` ); -my $notreally = grep /--notreally/, @ARGV; +my $pretend = grep /--dryrun/, @ARGV; my $longrun = grep /--long/, @ARGV; -if (!$notreally && CONFIRMATION_PHRASE) { +if (!$pretend && 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 = ); @@ -106,13 +106,13 @@ sub wipethemdrives { my $disksum2; my $spacer = 29; # Write - if ($notreally) { + if ($pretend) { $spacer = 18; print "Pretend wipe complete, pretending to check..."; $disksum = $clobsum; $disksum2 = $clobsum; } else { - system("hdparm -W 0 ".$disks->{$diskid}{path}) and do { + system("hdparm -W 0 ".$disks->{$diskid}{path}." 1>/dev/null 2>/dev/null") and do { print "Cannot turn off drive write caching: $!\n"; print "Disk considered $color{red}FAILED$color{reset}\n"; $disks->{$diskid}{failure} = "Cannot turn off write caching"; @@ -125,6 +125,12 @@ sub wipethemdrives { close($diskw); print "Wipe attempt complete, checking..."; # Read + system("hdparm -F ".$disks->{$diskid}{path}." 1> /dev/null 2>/dev/null") and do { + print "Cannot flush drive buffer: $!\n"; + print "Disk considered $color{red}FAILED$color{reset}\n"; + $disks->{$diskid}{failure} = "Cannot flush drive buffer"; + return 0; + }; open(my $diskr, "<", $disks->{$diskid}{path}) or return warning("could not open $disks->{$diskid}{path}"); my $diskdata; read($diskr, $diskdata, 10240000); @@ -150,19 +156,32 @@ sub wipethemdrives { return 0; } # If long flag than zero whole disk and give a progress bar - if ($longrun && !$notreally) { - say "Zeroing $disks->{$diskid}{path}..."; + if ($longrun && !$pretend) { open(my $longdiskw, ">:raw", $disks->{$diskid}{path}) or return warning("could not open $disks->{$diskid}{path}"); + binmode($longdiskw); + my $old_file_handle = select($longdiskw); #Disable I/O buffering on $longdiskw + $| = 1; + select($old_file_handle); seek($longdiskw,0,2); my $totalBytes = tell($longdiskw); seek($longdiskw,0,0); -#################################################### Need to double check this math, its not calculating % right - for (0..($totalBytes/4096)) { + for (0..($totalBytes/4096 - 1)) { print $longdiskw "\0"x4096; - if ( !(tell($longdiskw) % (16*4096)) ) { - printf(" %5.5s%%\r", sprintf("%.2f", (tell($longdiskw)/$totalBytes)) ); + if ( !($_ % 4) ) { + system("hdparm -F ".$disks->{$diskid}{path}." 1>/dev/null 2>/dev/null"); + } + if ( !($_ % 16) ) { + printf("\r%31.31s%-".($spacer+11).".".($spacer+11)."s%6.2f%% ", + "Zeroing ".$disks->{$diskid}{path}, + "."x(tell($longdiskw)/$totalBytes*($spacer+11)), + (tell($longdiskw)/$totalBytes)*100 ); } } + my $leftover = $totalBytes - tell($longdiskw); + print $longdiskw "\0"x$leftover; + system("hdparm -F ".$disks->{$diskid}{path}." 1>/dev/null 2>/dev/null"); + close($longdiskw); + printf("\r%31.31s...".("."x($spacer-1))."Zeroing Complete\n", "Zeroing".$disks->{$diskid}{path}); } return 1; } @@ -173,7 +192,7 @@ sub smartcheck { my $diskid = shift; my $disks = shift; print "Checking overall-health self-assessment test result: ".(" "x19); - (my $smartassess = `smartctl $disks->{$diskid}{path} -H | grep overall`) or (say "\n$!\ncould not check smart data, skipping" and return 1); + (my $smartassess = `smartctl $disks->{$diskid}{path} -H 2>/dev/null | grep overall`) or (($disks->{$diskid}{failure} = "No Smart Data") and say +"N/A\n$!" and return 1); $disks->{$diskid}{selftest} = (split(": ", $smartassess))[1]; if ( "FAILED" eq $disks->{$diskid}{selftest} ) { say "$color{red}Failed$color{reset}"; @@ -182,7 +201,7 @@ sub smartcheck { } else { say "$color{green}Passed$color{reset}"; } 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); + (my $smartcommand = `smartctl $disks->{$diskid}{path} -A -f hex,id 2>/dev/null | grep "^0x"`) or (($disks->{$diskid}{failure} = "No Smart Data") and say +"N/A\n$!" and return 1); for (split("\n",$smartcommand)) { my @smartdata = split(/\s+/,$_); $disks->{$diskid}{smart}{$smartdata[0]}{id} = $smartdata[0];