#! /usr/bin/perl -T
#
# Attempt to do ReadSunDisklabel in perl
# 
# Author: Frank Crawford (frank@kent.ansto.gov.au)
# Submitted to syssumm: January 2000
# 
# This perl script needs to be installed as setgid sys.
# 
# Synopsis:
# 
#	ReadSunDisklabel.pl [ -d ] [ -h ] <device> | -p <pattern>
# 
# where you specify either the device or the command line option
# -p with a pattern to search over all devices matching the pattern.
# 
# Usage:
# 
#	-h	print help message
#	-d	print debug messages
#	-p	take the device as the stem of the device name
#		loop over all reasonable devices to find the
#		primary partition
# 
# Note, if you specify a full device for <pattern> it will
# try that device first (and possibly also later).
#
# $Header: /export/home/mohlerb/syssumm/remote/RCS/ReadSunDisklabel.pl,v 1.2 2000/04/05 14:29:40 mohlerb Exp mohlerb $
# 
# $Revision: 1.2 $
#
# $Log: ReadSunDisklabel.pl,v $
# Revision 1.2  2000/04/05 14:29:40  mohlerb
# changes from Frank Crawford including:
# clarified comment about this script needing to be run
# setgid sys
#
# Revision 1.1  2000/02/07 02:26:24  mohlerb
# Initial revision
#

use Config;
use Getopt::Std;

(!getopts('dhp') || $opt_h || @ARGV != 1)
    and die "Usage: $0 [-d] [-h] <device> | [-p] <pattern>\n";

print STDERR "Arch = $Config{'archname'}\n" if $opt_d;

# The following values were found by studying /usr/include/sys/dklabel.h
$BLOCKSIZE = 512;
$DISKMAGIC = 0xdabe;	# Magic number in label
# The structure is padded out to a single 512 block.
$LABELSIZE = $BLOCKSIZE;

$DiskDir = '/dev/rdsk/';

if ($Config{'archname'} =~ /sun4/) {
    $LabelOffset = 0;
    $PackFormat = 'A128 x380 S x2';
    $DiskPattern = '%.16ss%1d';
    @DiskList = ('2', '0', '1', '3' .. '7');
} else {
    $LabelOffset = 1 * $BLOCKSIZE;
    $PackFormat = 'x268 A128 x112 S x2';
    $DiskPattern = '%.16sp%1d';	# This could be 14 or 16 chars
    @DiskList = ('0');
}

$device = shift(@ARGV);

if ($device =~ tr:/:/:) {
    die "$0: $device: not in $DiskDir\n" unless $device =~ /^$DiskDir/;
} else {
    $device = $DiskDir . $device;
}

if ($opt_p) {
    unshift(@DiskList, substr($device, -1, 1)) if (length($device) > 16);
    print STDERR "Trying ...\n" if $opt_d;
    foreach $part (@DiskList) {
	my $diskdev = sprintf($DiskPattern, $device, $part);

	print STDERR "\t$diskdev\n" if $opt_d;
	next unless -c $diskdev;
	last if $DiskType = ReadLabel($diskdev);
    }
} else {
    die "$0: $device: not raw device\n" unless -c $device;

    $DiskType = ReadLabel($device);
}

exit(2) unless $DiskType;

print "$DiskType\n";

exit(0);

sub ReadLabel {
    my $device = shift(@_);

    return "" unless -c $device;

    my $Label = "\0" x $LABELSIZE;
    sysopen(DISK, $device, 0) or die "$0: sysopen($device, 0): $!\n";
    sysseek(DISK, $LabelOffset, 0)
	or die "$0: sysseek($device, $LabelOffset, 0): $!\n";
    sysread(DISK, $Label, $LABELSIZE)
	or die "$0: sysread($device, \$Label, $LABELSIZE): $!\n";
    close(DISK);

    my ($DiskType, $DiskMagic) = unpack($PackFormat, $Label);

    printf STDERR ("Label = <%.128s> DiskType = <%.128s> Magic = %#x\n", $Label, $DiskType, $DiskMagic) if $opt_d;
    return ($DISKMAGIC == $DiskMagic) ? "<$DiskType>" : "";
}

