home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / lib / udev / path_id < prev    next >
Encoding:
Text File  |  2006-08-23  |  11.0 KB  |  546 lines

  1. #!/bin/sh
  2.  
  3. # provide the shortest possible unique hardware path to a device
  4. # for the Linux Persistent Device Naming scheme
  5. #
  6. # Copyright (C) 2005-2006 SUSE Linux Products GmbH
  7. # Author:
  8. #    Hannes Reinecke <hare@suse.de>
  9. #
  10. #    This program is free software; you can redistribute it and/or modify it
  11. #    under the terms of the GNU General Public License as published by the
  12. #    Free Software Foundation version 2 of the License.
  13. #
  14. # to be called from a udev rule to return the name for a symlink
  15. #    DEVPATH=<devpath>; path_id
  16. #    path_id <devpath>
  17.  
  18. # examples for all block devices on a system:
  19. #    for i in `find /sys/class/block`; do DEVPATH="`echo $i | sed -e 's@^/sys\|/dev@@g'`"; path_id; done
  20.  
  21. SYSFS=/sys
  22. RESULT=1
  23. TYPE=
  24. OPWD="`pwd`"
  25. full_sysfs_path=
  26. full_sysfs_device_path=
  27.  
  28. if [ -z "$DEVPATH" -a -z "$1" ] ; then
  29.     exit 1
  30. fi
  31.  
  32. if [ -z "$DEVPATH" ] ; then
  33.     case "$1" in
  34.         $SYSFS/*)
  35.             DEVPATH="${1#$SYSFS}"
  36.             ;;
  37.         *)
  38.             DEVPATH=$1
  39.             ;;
  40.     esac
  41. fi
  42.  
  43. if [ ! -e $SYSFS$DEVPATH/dev ] ; then
  44.     exit 1
  45. fi
  46.  
  47. case "$DEVPATH" in
  48.     /devices/*)
  49.         cd "$SYSFS$DEVPATH/subsystem";
  50.         TYPE="`pwd -P`"
  51.         cd "$OPWD"
  52.         TYPE="${TYPE##*/}"
  53.         ;;
  54.     /class/*)
  55.         TYPE="${DEVPATH#/class/}"
  56.         TYPE="${TYPE%%/*}"
  57.         ;;
  58.     /block/*)
  59.         TYPE=block
  60.         ;;
  61.     *)
  62.         exit 1
  63.         ;;
  64. esac
  65.  
  66. get_port_offset () {
  67.     local type offset port
  68.     type=$1
  69.     offset=$2
  70.     for i in $type[0-9]* ; do
  71.         : i $i
  72.         port="${i#$type}"
  73.         if [ "$port" -lt "$offset" ] ; then offset=$port ; fi
  74.     done
  75.     echo $offset
  76. }
  77.  
  78. handle_pci () {
  79.     local DEV=$1
  80.     cd -P $1
  81.     DEV=${PWD}
  82.     pci_id=${DEV##*/}
  83.     host_dev_path=$DEV
  84.     while [ ! -z "$host_dev_path" ] ; do
  85.         case "$host_dev_path" in
  86.             */pci[0-9]*)
  87.                 host_dev_path=${host_dev_path%/*}
  88.                 ;;
  89.             *)
  90.                 break
  91.                 ;;
  92.         esac
  93.     done
  94.     d="pci-$pci_id-$d"
  95.     D="$host_dev_path"
  96.     RESULT=0
  97. }
  98.  
  99. handle_platform () {
  100.     local DEV=$1
  101.     cd -P $1
  102.     DEV=${PWD}
  103.     platform_id=${DEV##*/}
  104.     host_dev_path=$DEV
  105.     while [ ! -z "$host_dev_path" ] ; do
  106.         case "$host_dev_path" in
  107.             */platform*)
  108.                 host_dev_path=${host_dev_path%/*}
  109.                 ;;
  110.             *)
  111.                 break
  112.                 ;;
  113.         esac
  114.     done
  115.     if [ "$d" ]; then
  116.         d="platform-$platform_id-$d"
  117.     else
  118.         d="platform-$platform_id"
  119.     fi
  120.     D="$host_dev_path"
  121.     RESULT=0
  122. }
  123.  
  124. handle_serio () {
  125.     local DEV=$1
  126.     cd -P $1
  127.     DEV=${PWD}
  128.     serio_id=${DEV##*/serio}
  129.     host_dev_path=$DEV
  130.     while [ ! -z "$host_dev_path" ] ; do
  131.         case "$host_dev_path" in
  132.             */serio*)
  133.                 host_dev_path=${host_dev_path%/*}
  134.                 ;;
  135.             *)
  136.                 break
  137.                 ;;
  138.         esac
  139.     done
  140.     if [ "$d" ]; then
  141.         d="serio-$serio_id-$d"
  142.     else
  143.         d="serio-$serio_id"
  144.     fi
  145.     D="$host_dev_path"
  146.     RESULT=0
  147. }
  148.  
  149. handle_ide () {
  150.     : handle_ide $*
  151.     local DEV=$1
  152.     local port idedev idecontroller
  153.     # IDE
  154.     : DEV $DEV
  155.     port=${DEV##*/}
  156.     idedev=${DEV%/*}
  157.     idecontroller=${idedev%/*}
  158.     # port info if the controller has more than one interface
  159.     port="${port#ide}"
  160.     : port $port d $d
  161.     : idedev $idedev kernel_port $port
  162.     case "${port#*.}" in
  163.         0)
  164.             channel=0
  165.             ;;
  166.         1)
  167.             channel=1
  168.             ;;
  169.         *)
  170.             echo "Error: $idedev is neither master or slave" >&2
  171.             ;;
  172.     esac
  173.     cd $idecontroller
  174.     offset="`get_port_offset ide ${port%.*}`"
  175.     cd "$OPWD"
  176.     :  port offset $offset
  177.     port=$((${port%.*} - $offset))
  178.     if [ "$d" ] ; then
  179.         d="ide-${port}:$channel-$d"
  180.     else
  181.         d="ide-${port}:$channel"
  182.     fi
  183.     D=$idecontroller
  184.     RESULT=0
  185. }
  186.  
  187. handle_scsi () {
  188.     : handle_scsi $*
  189.     local DEV=$1
  190.     local cil controller_port controller_dev
  191.     # SCSI device
  192.     cil="${DEV##*/}"
  193.     cil="${cil#*:}"
  194.     target_dev=${DEV%/*}
  195.     target_id=${target_dev##*/target}
  196.     cd "$target_dev"
  197.     target_num=0
  198.     for tid in ${target_id}* ; do
  199.         target_num=$(( $target_num + 1 ))
  200.     done
  201.     controller_port=${target_dev%/*}
  202.     controller_dev="${controller_port%/*}"
  203.     : controller_dev $controller_dev
  204.     : controller_port $controller_port
  205.     # a host controller may have more than one interface/port
  206.     controller_port="${controller_port##*/host}"
  207.     #
  208.     cd "$controller_dev"
  209.     controller_offset=$(get_port_offset host $controller_port)
  210.     cd "$OPWD"
  211.     controller_port=$(( $controller_port - $controller_offset))
  212.     scsi_id="scsi-${controller_port}:${cil}"
  213.     if [ "$d" ] ; then
  214.         d="${scsi_id}-$d"
  215.     else
  216.         d="$scsi_id"
  217.     fi
  218.     D="$controller_dev"
  219.     RESULT=0
  220. }
  221.  
  222. handle_firewire () {
  223.     :handle_firewire $*
  224.     local DEV=$1
  225.     if [ -f "$D/ieee1394_id" ] ; then
  226.         read ieee1394_id < $D/ieee1394_id
  227.     fi
  228.     if [ -z "$ieee1394_id" ] ; then
  229.         : no IEEE1394 ID
  230.         RESULT=1
  231.         return
  232.     fi
  233.     fw_host_dev=${DEV%/fw-host*}
  234.     # IEEE1394 devices are always endpoints
  235.     d="ieee1394-0x$ieee1394_id"
  236.     D="$fw_host_dev"
  237.     RESULT=0
  238. }
  239.  
  240. handle_fc () {
  241.     : handle_fc $*
  242.     local DEV=$1
  243.     local cil controller_port controller_dev
  244.     # SCSI-FC device
  245.     fc_tgt_hcil="${DEV##*/}"
  246.     fc_tgt_lun="${fc_tgt_hcil##*:}"
  247.     fc_tgt_path="${DEV%/*}"
  248.     fc_tgt_num="${fc_tgt_path##*/}"
  249.     fc_tgt_dev="${fc_tgt_path}/fc_transport:${fc_tgt_num}"
  250.     if [ -e "$fc_tgt_dev/port_name" ]; then
  251.         read wwpn < $fc_tgt_dev/port_name
  252.     fi
  253.     if [ -z "$wwpn" ] ; then
  254.         : no WWPN
  255.         D=
  256.         RESULT=1
  257.         return
  258.     fi
  259.     # Linux currently knows about 32bit luns
  260.     tmp_lun3=$(printf "%04x" $(($fc_tgt_lun & 0xFFFF)))
  261.     tmp_lun2=$(printf "%04x" $(( ($fc_tgt_lun >> 16) & 0xFFFF)))
  262.     tmp_lun1="0000"
  263.     tmp_lun0="0000"
  264.     if (($fc_tgt_lun == 0)) ; then
  265.         lun="0x0000000000000000"
  266.     else
  267.         lun="0x${tmp_lun3}${tmp_lun2}${tmp_lun1}${tmp_lun0}"
  268.     fi
  269.     controller_dev="${fc_tgt_path%/host[0-9]*}"
  270.     # FC devices are always endpoints
  271.     d="fc-${wwpn}:${lun}"
  272.     D="$controller_dev"
  273.     RESULT=0
  274. }
  275.  
  276. handle_sas () {
  277.     : handle_sas $*
  278.     local DEV=$1
  279.     local cil adapter controller_dev
  280.     # SAS device
  281.     sas_host_path="${DEV%%/phy*}"
  282.     sas_phy_path="${DEV#*/host*/}"
  283.     sas_phy_path="${sas_phy_path%%/target*}"
  284.     sas_phy_id="${sas_phy_path%%/*}"
  285.     sas_rphy_id="${sas_phy_path##*/}"
  286.     sas_phy_dev="/sys/class/sas_phy/${sas_phy_id}"
  287.     if [ -e "$sas_phy_dev/sas_address" ]; then
  288.         read phy_address < $sas_phy_dev/sas_address
  289.         read phy_port < $sas_phy_dev/port_identifier
  290.         read phy_id < $sas_phy_dev/phy_identifier
  291.     fi
  292.     if [ -z "$phy_address" ] ; then
  293.         : no initiator address
  294.         D=
  295.         RESULT=1
  296.         return
  297.     fi
  298.     sas_phy_address="$phy_address:$phy_port:$phy_id"
  299.     sas_rphy_dev="/sys/class/sas_device/${sas_rphy_id}"
  300.     if [ -e "$sas_rphy_dev/sas_address" ]; then
  301.         read rphy_address < $sas_rphy_dev/sas_address
  302.         read rphy_id < $sas_rphy_dev/phy_identifier
  303.     fi
  304.     if [ -z "$rphy_address" ] ; then
  305.         : no initiator address
  306.         D=
  307.         RESULT=1
  308.         return
  309.     fi
  310.     sas_rphy_address="$rphy_address:$rphy_id"
  311.     controller_dev="${sas_host_path%/host[0-9]*}"
  312.     # SAS devices are always endpoints
  313.     d="sas-${sas_phy_address}-${sas_rphy_address}"
  314.     D="$controller_dev"
  315.     RESULT=0
  316. }
  317.  
  318. handle_iscsi() {
  319.     local DEV=$1
  320.     local iscsi_session_dir
  321.     local iscsi_session iscsi_session_path
  322.     local iscsi_connection iscsi_connection_path
  323.     # iSCSI device
  324.     iscsi_session_dir="${DEV%%/target*}"
  325.     iscsi_session="${iscsi_session_dir##*/}"
  326.     iscsi_session_path=/sys/class/iscsi_session/${iscsi_session}
  327.     if [ ! -d "$iscsi_session_path" ] ; then
  328.         : no iSCSI session path
  329.         RESULT=1
  330.         return
  331.     fi
  332.     # Currently we're not doing MC/S
  333.     for conn in ${iscsi_session_dir}/connection* ; do
  334.         iscsi_conn_num=${conn##*:}
  335.         if [ "$iscsi_conn_num" = '0' ] ; then
  336.         iscsi_connection=$(basename $conn)
  337.         fi
  338.     done
  339.     if [ -z "$iscsi_connection" ] ; then
  340.         : no iSCSI connection found
  341.         RESULT=1
  342.         return
  343.     fi
  344.     iscsi_connection_path=/sys/class/iscsi_connection/${iscsi_connection}
  345.     if [ ! -d "$iscsi_connection_path" ] ; then
  346.         : no iSCSI connection path
  347.         RESULT=1
  348.         return
  349.     fi
  350.     if [ -e "${iscsi_session_path}/targetname" ]; then
  351.         read iscsi_tgtname < ${iscsi_session_path}/targetname
  352.     fi
  353.     if [ -z "$iscsi_tgtname" ] ; then
  354.         : No iSCSI Targetname
  355.         RESULT=1
  356.         return
  357.     fi
  358.     if [ -e "${iscsi_connection_path}/persistent_address" ] ; then
  359.         read iscsi_address < ${iscsi_connection_path}/persistent_address
  360.     fi
  361.     if [ -z "$iscsi_address" ] ; then
  362.         : No iSCSI Target address
  363.         RESULT=1
  364.         return
  365.     fi
  366.     if [ -e "${iscsi_connection_path}/persistent_port" ] ; then
  367.         read iscsi_port < ${iscsi_connection_path}/persistent_port
  368.     fi
  369.     d="ip-${iscsi_address}:${iscsi_port}-iscsi-${iscsi_tgtname}"
  370.     RESULT=0
  371. }
  372.  
  373. handle_usb () {
  374. : handle_usb $*
  375.     local DEV=$1
  376.     cd -P $1
  377.     DEV=${PWD}
  378.     port_id=${DEV##*/}
  379.     port_num=${port_id#*-}
  380.     host_dev_path=$DEV
  381.     while [ ! -z "$host_dev_path" ] ; do
  382.         case "$host_dev_path" in
  383.             */usb*)
  384.                 usb_host_path=$host_dev_path
  385.                 host_dev_path="${host_dev_path%/*}"
  386.                 ;;
  387.             *)
  388.                 break
  389.                 ;;
  390.         esac
  391.     done
  392.     : host_dev_path $host_dev_path
  393.     usb_host_num=${usb_host_path##*/usb}
  394.  
  395.     cd "$host_dev_path"
  396.     usb_host_offset=$(get_port_offset usb $usb_host_num)
  397.     usb_host_port=$(($usb_host_num - $usb_host_offset))
  398.     cd "$OPWD"
  399.     if [ "$d" ] ; then
  400.         d="usb-$usb_host_port:$port_num-${d}"
  401.     else
  402.         d="usb-$usb_host_port:$port_num"
  403.     fi
  404.     D="$host_dev_path"
  405.     RESULT=0
  406. }
  407.  
  408. handle_device () {
  409.     full_sysfs_path="$SYSFS$DEVPATH"
  410.     if [ -L $full_sysfs_path/subsystem ]; then
  411.         # new sysfs block layout
  412.         full_sysfs_path="${full_sysfs_path%/*}"
  413.         cd "$full_sysfs_path/subsystem";
  414.         subsys="`pwd -P`"
  415.         cd "$OPWD"
  416.         subsys="${subsys##*/}"
  417.         if [ "$subsys" = "block" ]; then
  418.             # parent is "block", it's a partition, move one up
  419.             full_sysfs_path="${full_sysfs_path%/*}"
  420.         fi
  421.         cd $full_sysfs_path
  422.     else
  423.         # old sysfs block layout
  424.         if [ ! -L $full_sysfs_path/device ] ; then
  425.             if [ -f $full_sysfs_path/range ] ; then return ; fi
  426.             full_sysfs_path="${full_sysfs_path%/*}"
  427.             : full_sysfs_path "$full_sysfs_path"
  428.             if [ ! -L $full_sysfs_path/device -o ! -f $full_sysfs_path/dev ] ; then
  429.                 return
  430.             fi
  431.         fi
  432.         cd $full_sysfs_path/device
  433.     fi
  434.     full_sysfs_device_path="`pwd -P`"
  435.     cd "$OPWD"
  436.     D=$full_sysfs_device_path
  437.     while [ ! -z "$D" ] ; do
  438.         case "$D" in
  439.             */ide[0-9]/[0-9].[0-9]*|*/ide[0-9][0-9]/[0-9][0-9].[0-9]*)
  440.                 handle_ide "$D"
  441.                 ;;
  442.             */css0/*)
  443.                 if [ -r $full_sysfs_device_path/wwpn ]; then
  444.                     read wwpn < $full_sysfs_device_path/wwpn
  445.                 fi
  446.                 if [ -r $full_sysfs_device_path/fcp_lun ]; then
  447.                     read lun < $full_sysfs_device_path/fcp_lun
  448.                 fi
  449.                 if [ -r $full_sysfs_device_path/hba_id ]; then
  450.                     read bus_id < $full_sysfs_device_path/hba_id
  451.                 fi
  452.                 if [ "$bus_id" -a "$wwpn" -a "$lun" ]; then
  453.                     # S/390 zfcp adapter
  454.                     d="ccw-$bus_id-zfcp-$wwpn:$lun"
  455.                     RESULT=0
  456.                 else
  457.                     # DASD devices
  458.                     bus="ccw"
  459.                     adapter=${D##*/}
  460.                     d="$bus-$adapter"
  461.                     RESULT=0
  462.                 fi
  463.                 D=
  464.                 ;;
  465.             */rport-[0-9]*:[0-9]*-[0-9]*/*)
  466.                 handle_fc "$D"
  467.                 ;;
  468.             */phy-[0-9]*:[0-9]*/*)
  469.                 handle_sas "$D"
  470.                 ;;
  471.             */fw-host[0-9]*/*)
  472.                 handle_firewire "$D"
  473.                 ;;
  474.             */session[0-9]*/*)
  475.                 handle_iscsi "$D"
  476.                 D=
  477.                 ;;
  478.             */host[0-9]*/[0-9]*:[0-9]*:[0-9]*:[0-9]*)
  479.                 handle_scsi "$D"
  480.                 ;;
  481.             */usb[0-9]*/[0-9]*/*)
  482.                 handle_usb "$D"
  483.                 ;;
  484.             */pci[0-9]*:[0-9]*)
  485.                 handle_pci "$D"
  486.                 ;;
  487.             */serio[0-9]*)
  488.                 handle_serio "$D"
  489.                 ;;
  490.             */platform/*)
  491.                 handle_platform "$D"
  492.                 ;;
  493.             */devices)
  494.                 D=
  495.                 ;;
  496.             *)
  497.                 : not handled
  498.                 RESULT=1
  499.                 return
  500.                 ;;
  501.         esac
  502.     done
  503.     if [ "$TYPE" = "scsi_tape" ] ; then
  504.         devname=${full_sysfs_path##*/}
  505.         rewind="${devname%%st*}"
  506.         mode="${devname##*st}"
  507.         case "$mode" in
  508.             *l)
  509.                 mode="l"
  510.                 ;;
  511.             *m)
  512.                 mode="m"
  513.                 ;;
  514.             *a)
  515.                 mode="a"
  516.                 ;;
  517.             *)
  518.                 mode=""
  519.                ;;
  520.         esac
  521.         if [ "$d" ]; then
  522.             d="$d-${rewind}st${mode}"
  523.         fi
  524.     fi
  525. }
  526.  
  527. case "$TYPE" in
  528.     block)
  529.         handle_device
  530.         echo "ID_PATH=$d"
  531.         ;;
  532.     scsi_tape)
  533.         handle_device
  534.         echo "ID_PATH=$d"
  535.         ;;
  536.     input)
  537.         handle_device
  538.         echo "ID_PATH=$d"
  539.         ;;
  540.     *)
  541.         RESULT=1
  542.         ;;
  543. esac
  544.  
  545. exit $RESULT
  546.