#!/usr/bin/perl # # Perlskript um unter Linux ein nachtraeglich angeschlossenes # SCSI-Device im laufenden Betrieb verfuegbar zu machen. # Siehe jedoch Warnungen aus SCSI-Treiber-Sourcen weiter unten. # Version 1.0 # - pws Mon Feb 17 17:59:41 MET 1997 $usage = " Usage: $0 [--debug] [attach|detach|list] --debug listet alle angeschlossenen SCSI-Devices vor und nach der Aenderung --host Fuehrt attach/detach fuer Host aus. default: 0 --channel Fuehrt attach/detach fuer Channel aus. default: 0 ist die Nummer des SCSI-Adapters im Rechner. --id Fuehrt attach/detach fuer SCSI-ID aus. default: 5 ist die am Geraet eingestellte ID. --lun Fuehrt attach/detach fuer logical unit number aus. default:0 --help Gibt diesen Hilfetext aus attach Versucht das mit hosts/channel/id/lun spezifizierte Device im Kernel verfuegbar zu machen. detach Versucht das mit hosts/channel/id/lun spezifizierte Device aus dem Kernel auszutragen. attach ist default wenn weder attach noch detach angegeben wird "; # Siehe auch /usr/src/linux-2.0.25/drivers/scsi/scsi.c: # /* # * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi # * with "0 1 2 3" replaced by your "Host Channel Id Lun". # * Consider this feature BETA. # * CAUTION: This is not for hotplugging your peripherals. As # * SCSI was not designed for this you could damage your # * hardware ! # * However perhaps it is legal to switch on an # * already connected device. It is perhaps not # * guaranteed this device doesn't corrupt an ongoing data transfer. # */ # [...] # /* # * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi # * with "0 1 2 3" replaced by your "Host Channel Id Lun". # * # * Consider this feature pre-BETA. # * # * CAUTION: This is not for hotplugging your peripherals. As # * SCSI was not designed for this you could damage your # * hardware and thoroughly confuse the SCSI subsystem. # * # */ # Siehe auch man proc(5) (search for 'listing of all SCSI devices known') # wobei diese Angaben wahrscheinlich veraltet sind. # um uns das parsing der Kommandozeile zu vereinfachen use Getopt::Long; $result = &GetOptions('debug',\$debug,"host=i",\$host, "channel=i",\$channel,"id=i",\$id,"lun=i",\$lun,'help',\$help); #printf STDERR "Values: %1.1s %1.1s %1.1s %1.1s\n",$host,$channel,$id,$lun; # defaults setzen $host = 0 unless defined $host; $channel = 0 unless defined $channel; $id = 5 unless defined $id; $lun = 0 unless defined $lun; #printf STDERR "Values: %1.1s %1.1s %1.1s %1.1s\n",$host,$channel,$id,$lun; print STDERR " *** Debug-Mode enabled.\n" if $debug; # print STDERR " *** *** ARGC= $#ARGV ARGV[0]='$ARGV[0]'\n"; # Attach oder detach oder Hilfestellung gewuenscht ??? if ( ($#ARGV < 0) # keine Angabe, also default nehmen || ($ARGV[0] eq "attach") ) { $cmd="add-single-device"; } elsif ($ARGV[0] eq "detach") { $cmd="remove-single-device"; } elsif ($ARGV[0] eq "list") { $debug=1; &get_SCSI_status(); exit(0); } else { printf STDERR $usage; exit(1); } if ($help) { printf STDERR $usage; exit(1); } # Angeschlossene SCSI-Devices vor Aenderung print STDERR "\n *** Angeschlossene SCSI-Devices vor Aenderung:\n" if $debug; %vorher = &get_SCSI_status(); # Eigentliche Veraenderungen machen &change(); # Angeschlossene SCSI-Devices nach Aenderung print STDERR "\n *** Angeschlossene SCSI-Devices nach Aenderung:\n" if $debug; %nachher = &get_SCSI_status(); # Ausgeben was sich veraendert hat. &list_difference(); exit(0); # aus dem /proc-Filesystem-Interface in den Kernel die momentan # angeschlossenen SCSI-Geraete auslesen sub get_SCSI_status { my %list; print STDERR " *** reading /proc/scsi/scsi\n" if $debug; open (SCSI,"/proc/scsi/scsi"); $device="header"; while () { $device = $_ if ( /^Host:/ ); $list{$device} .= $_; print STDERR $_ if $debug; } close (SCSI); print STDERR"\n" if $debug; # den Eintrag brauchen wir nicht delete $list{"header"}; return %list; } # Eigentliches Ein/Austragen unter Verwendung des /proc-Filesystems sub change { if ($> != 0) { print STDERR "\nERROR: You're not root, won't change anything\n\n"; } else { print STDERR " *** writing 'scsi $cmd $host $channel $id $lun' ", "into /proc/scsi/scsi\n" if $debug; open (SCSI,">/proc/scsi/scsi"); print SCSI "scsi $cmd $host $channel $id $lun"; close (SCSI); } } sub list_difference { # Und was ist der Unterschied ??? foreach $device (keys %vorher) { if ($vorher{$device} eq $nachher{$device}) { # Normalfall fuer nicht betroffene Geraete print STDERR "\nVorher und Nachher gleich:\n $vorher{$device}" if $debug; print STDERR "\n" if $debug; delete $vorher{$device}; delete $nachher{$device}; } else { # Argl, da stimmt was nicht, da hat sich ein Eintrag # Inhaltlich veraendert, wurde also nicht geloescht oder # hinzugefuegt, sondern real veraendert. Sollte nicht passieren if (exists $nachher{$device}) { print STDERR "\nERROR: Veraenderter Eintrag\n"; print STDERR "ERROR: vorher:\n $vorher{$device}"; print STDERR "ERROR: nachher:\n $nachher{$device}\n"; delete $vorher{$device}; delete $nachher{$device}; } else { # Fuer detach der Normalfall print "\nRemoved:\n $vorher{$device}\n"; $changed=1; } } } foreach $device (keys %nachher) { # Oben wurde schon alles rausgefiltert was gleich war und was # sich fehlerhafterweise geaendert hat, also bleibt nur noch: # Fuer attach der Normalfall print "\nAdded:\n $nachher{$device}\n"; $changed=1; } if (!$changed) { print STDERR "\nWARNING WARNING WARNING WARNING WARNING "; print STDERR "WARNING WARNING WARNING WARNING WARNING\n"; print STDERR "\nno devices added or removed; possible reasons:\n"; print STDERR " - you're not root\n"; print STDERR " - device was already attached\n"; print STDERR " - device was already detached\n"; print STDERR " - no device was found\n"; print STDERR " - device is in use (mounted)\n"; print STDERR "\nWARNING WARNING WARNING WARNING WARNING "; print STDERR "WARNING WARNING WARNING WARNING WARNING\n\n"; } }