#!/usr/bin/perl -w # # findbill - Search a drive for UFS backup superblocks. Prints potential # backups for use with "fsck -o b=...". Perl, Solaris. # # This works by looking for the UFS magic number at specific locations, and # does have a small potential for false positives. The magic number is # 0x011954, which I've heard is either Bill Joy's or Marshall Kirk McKusick's # birthday (hence the name). # # This now also searches for MTB_UFS magic numbers (0xdecade). # # 23-Jan-2006, ver 1.55 # # USAGE: findbill raw-special-device # eg, # findbill /dev/rdsk/c0t0d0s0 # # Note: realistically you wouldn't want to try anything past your third # backup super block - by that point it's time to restore from tape. # # COPYRIGHT: Copyright (c) 2006 Brendan Gregg. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # (http://www.gnu.org/copyleft/gpl.html) # # 21-Mar-2004 Brendan Gregg Created this. # 17-Jan-2005 " " Added MTB_UFS. # 10-Jan-2006 " " Added last write time and mountpoint fields. # 23-Jan-2006 " " Tweaked style. use strict; ### Check Argument my $pathname = defined $ARGV[0] ? $ARGV[0] : ""; die "USAGE: findbill raw-special-device\n" if $pathname =~ /^(-h|--help|)$/; unless (-c "$pathname" || -b "$pathname") { print STDERR "WARNING: $pathname isn't a raw-special-device.\n\n"; # this is probably a typo, but it may be ok - eg, when running # findbill on a dd image of UFS. } ### Variables my $MAGIC1 = 0x011954; my $MAGIC2 = 0xdecade; my $block = 0; my $offset = 0; my ($time, $name, $int, $junk); ### Search for magic number open RAW, "$pathname" or die "ERROR1: Can't open $pathname: $!\n"; print "Searching $pathname,\n\n"; printf "%-8s %-8s %-25s %s\n", "Type", "Block", "Time last written", "Mountpoint"; while ( read(RAW, my $buffer, 512) > 0) { if ($block == 0) { ($junk, $time, $junk, $name) = unpack('a32La176Z302', $buffer); } elsif ($block == 2) { ($junk, $int) = unpack('a348L', $buffer); if ($int == $MAGIC1) { printf("%-8s %-8d %-25s %s\n", "UFS", $offset/512 - 2, scalar localtime($time), $name); } elsif ($int == $MAGIC2) { printf("%-8s %-8d %-25s %s\n", "MTB_UFS", $offset/512 - 2, scalar localtime($time), $name); } } $block = 0 if ++$block > 15; $offset += 512; $buffer = ""; } close RAW;