#!/usr/bin/perl

##############################################################################
# sysfs.pl - print out information about scsi devices in /sys filesystem
# Useful for determining vendor, disk size, LUN, etc.
#
# Copyright (c) 2006 Steve Suehring
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
# USA. 
##############################################################################
#
#
#	Version 0.2 7/18/2006
#		The program prints out info about things named "sd" (like scsi disks).
#		LUNs are printed in hex, size in 512 byte blocks, so divide by 2.
#	To do:
#		Clean up this code.
#		Add command-line arguments for version, usage, and others?
#		Clean up the size calculations to better calculate MB.
#		Clean up hex printing, there's an extra : there.
#		Get PCI numbers or info in here to tie an sd to a pci interface.
#
##############################################################################

use Getopt::Long;
Getopt::Long::Configure ("bundling");
my $dir = "/sys/block";
my $debug = 0;
my $hex = '';
my $rawsize = '';
my @devices;
GetOptions ( 
	"debug|d" => \$debug, 
	"hex|x" => \$hex, 
	"rawsize|r" => \$rawsize 
);

opendir(SYSDIR, $dir) or die "Cannot open $dir: $!";

my @files = grep { /sd/ } readdir(SYSDIR);

while (<@files>) {
	my $device = $_;
	print "grepped device: $device\n" if $debug;
	print "full path: $dir/$device\n" if $debug;
	push @devices,$device;
}

for $d (@devices) {
	print "device: \"$d\" in $dir\n";
	@udev = `udevinfo -a -p $dir/$d`;
	@sysfslines = grep { /SYSFS|ID|SUBSYSTEM|BUS|DRIVER/ } @udev;

	print "@udev" if $debug;

	while (<@sysfslines>) {
		$_ =~ s/SYSFS//;
		#fragile
		($key,$value) = split(/=/,$_);
		#certainly seems like there must be a better way for this.
		if (($key eq "ID") && ($hex)) {
			$value = "0:0:0:32" if $debug;
			@ids = split (/:/, $value);
			while (<@ids>) {
				$result = sprintf ("%02x", "$_");
				push @results,$result;
			}
			$value = "";
			while (<@results>) {
    			$value .= $_ . ":";
			}
		}	

		#This is set by the raw or r option to give size in MB
    	if (($key eq "size") && ($rawsize)) {
        	$result = (($value/2) / 1024) . "\t(MB)";
        	$value = $result;
    	} elsif ($key eq "size") { 
			$value = $values . "\t(512 byte blocks)"; 
		}

		$list{$d}{$key} = $value;
	} #end while for parsing @sysfslines from the udevinfo output

} # end 'for' loop for iterating through devices

foreach $devname ( keys %list ) {
	print "Device: $devname\n";
	for $item ( keys %{ $list{$devname} } ) {
		print "$item=$list{$devname}{$item}\n";
	}
}
