linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: md@Linux.IT (Marco d'Itri)
To: linux-hotplug@vger.kernel.org
Subject: scripts for persistent names support
Date: Sat, 02 Sep 2006 09:06:53 +0000	[thread overview]
Message-ID: <20060902090653.GA4424@wonderland.linux.it> (raw)

[-- Attachment #1: Type: text/plain, Size: 272 bytes --]

I implemented both the "try again later" and "use a temporary file now"
methods to work around the read-only root problem.
Removing the part of the code you do not need is trivial, and I expect
that everybody will only use the scripts as examples anyway.

-- 
ciao,
Marco

[-- Attachment #2: write_cd_rules --]
[-- Type: text/plain, Size: 1793 bytes --]

#!/bin/sh -e

RULES_FILE="/etc/udev/rules.d/z25_persistent-cd.rules"

. /lib/udev/hotplug.functions

##############################################################################
find_next_available() {
  raw_find_next_available "$(find_all_rules 'SYMLINK+=' $1)"
}

write_rule() {
  local match="$1"
  local link="$2"
  local comment="$3"

  {
  if [ "$PRINT_HEADER" ]; then
    PRINT_HEADER=
    echo "# This file was automatically generated by the $0"
    echo "# program, probably run by the cd-aliases-generator.rules rules file."
    echo "#"
    echo "# You can modify it, as long as you keep each rule on a single line"
    echo "# and set the \$GENERATED variable."
    echo ""
  fi

  [ "$comment" ] && echo "# $comment"
  echo "$match, SYMLINK+=\"$link\", ENV{GENERATED}=\"1\""
  } >> $RULES_FILE
  SYMLINKS="$SYMLINKS $link"
}

##############################################################################
if [ -z "$DEVPATH" ]; then
  echo "Missing \$DEVPATH." >&2
  exit 1
fi
if [ -z "$ID_CDROM" ]; then
  echo "$DEVPATH is not a CD reader." >&2
  exit 1
fi

# Exit if the rules file should not be written yet.
abort_if_run_early

# Prevent concurrent processes from modifying the file at the same time.
lock_rules_file

# Check if the rules file is writeable.
choose_rules_file

link_num=$(find_next_available 'cdrom[0-9]*')

match="ENV{ID_CDROM}==\"?*\", ENV{ID_PATH}==\"$ID_PATH\""

comment="$ID_MODEL ($ID_PATH)"

    write_rule "$match" "cdrom$link_num" "$comment"
[ "$ID_CDROM_CD_R" -o "$ID_CDROM_CD_RW" ] && \
    write_rule "$match" "cdrw$link_num"
[ "$ID_CDROM_DVD" ] && \
    write_rule "$match" "dvd$link_num"
[ "$ID_CDROM_DVD_R" -o "$ID_CDROM_DVD_RW" -o "$ID_CDROM_DVD_RAM" ] && \
    write_rule "$match" "dvdrw$link_num"

unlock_rules_file

echo $SYMLINKS

exit 0


[-- Attachment #3: write_net_rules --]
[-- Type: text/plain, Size: 4544 bytes --]

#!/bin/sh -e
#
# This script is run if the interface (recognized by its MAC address) lacks
# a rule for persistent naming.
#
# If there is already a persistent rule with that interface name then the
# current interface needs to be renamed.
# If the interface needs to be renamed, a NAME=value pair will be printed
# on stdout to allow udev to IMPORT it 
#
# Then a rule for the MAC address and interface name is written.

RULES_FILE='/etc/udev/rules.d/z25_persistent-net.rules'

. /lib/udev/hotplug.functions

##############################################################################
device_description() {
  local bus=$(sysreadlink device/bus)
  bus=${bus##*/}

  if   [ "$bus" = pci ]; then
    local vendor_id=$(sysread device/vendor)
    local device_id=$(sysread device/device)
    echo -n "PCI device ${vendor_id#0x}:${device_id#0x}"
  elif [ "$bus" = usb ]; then
    local device=$(sysreadlink device)
    if [ "$device" -a -e $device/../idVendor ]; then
      local idVendor idProduct
      read idVendor  < $device/../idVendor  || true
      read idProduct < $device/../idProduct || true
      printf 'USB device %x/%x' 0x$idVendor 0x$idProduct
    else
      echo -n "UNKNOWN USB device ($DEVPATH)"
    fi
  elif [ "$bus" = ieee1394 ]; then
    local hostid=$(sysreadlink device/host_id)
    if [ "$hostid" ]; then
      hostid=${hostid##*/}
      echo -n "FireWire host adapter $hostid ($DEVPATH)"
    else
      echo -n "UNKNOWN FireWire device ($DEVPATH)"
    fi
  elif [ "$bus" = xen ]; then
    echo -n "Xen virtual interface"
  elif [ "$bus" ]; then
    echo -n "UNKNOWN $bus device ($DEVPATH)"
  else
    echo -n "UNKNOWN device ($DEVPATH)"
  fi

  local driver=$(sysreadlink device/driver)
  if [ "$driver" ]; then echo -n " (${driver##*/})"; fi
}

##############################################################################
interface_name_taken() {
  local value="$(find_all_rules 'NAME=' $INTERFACE)"
  if [ "$value" ]; then
    return 0
  else
    return 1
  fi
}

find_next_available() {
  raw_find_next_available "$(find_all_rules 'NAME=' "$1")"
}

write_rule() {
  local match="$1"
  local name="$2"
  local comment="$3"

  {
  if [ "$PRINT_HEADER" ]; then
    PRINT_HEADER=
    echo "# This file was automatically generated by the $0"
    echo "# program, probably run by the persistent-net-generator.rules rules file."
    echo "#"
    echo "# You can modify it, as long as you keep each rule on a single line."
  fi

  echo ""
  [ "$comment" ] && echo "# $comment"
  echo "SUBSYSTEM==\"net\", $match, NAME=\"$name\""
  } >> $RULES_FILE
}

write_all_rules() {
  cd /sys/class/net/ || return 0

  for INTERFACE in *; do
    case $INTERFACE in
    eth*|ath*|wlan*|ra*|sta*) ;;
    *) continue ;;
    esac

    INTERFACE="$INTERFACE" DEVPATH="/class/net/$INTERFACE" \
      /lib/udev/write_net_rules || true
  done
}

##############################################################################
# can be used only if $RULES_FILE is empty
if [ "$1" = "all_interfaces" ]; then
  if [ -e $RULES_FILE ]; then
    printf "$RULES_FILE exists, persistent interface names\nnot saved.\n" >&2
    exit 0
  fi

  if [ ! -e /sys/class/net/ ]; then
    echo "/sys/class/net/ is not available, persistent interface names not saved." >&2
    exit 0
  fi

  write_all_rules
  exit 0
fi

if [ -z "$INTERFACE" ]; then
  echo "Missing \$INTERFACE." >&2
  exit 1
fi

if [ "$1" ]; then
  MAC_ADDR="$1"
else
  MAC_ADDR=$(sysread address)
fi

if [ -z "$MAC_ADDR" ]; then
  echo "No MAC address for $INTERFACE." >&2
  exit 1
fi
if [ "$MAC_ADDR" = "00:00:00:00:00:00" ]; then
  echo "NULL MAC address for $INTERFACE." >&2
  exit 1
fi

# Exit if the rules file should not be written yet.
abort_if_run_early

# Prevent concurrent processes from modifying the file at the same time.
lock_rules_file

# Check if the rules file is writeable.
choose_rules_file

# If a rule using the current name already exists then find a new name and
# report it to udev which will rename the interface.
basename=${INTERFACE%%[0-9]*}
if interface_name_taken; then
  INTERFACE="$basename$(find_next_available "$basename[0-9]*")"
  if [ ! -t 1 ]; then
    echo "INTERFACE_NEW=$INTERFACE"
  fi
fi

comment=$(device_description)

# the DRIVERS key is needed to not match bridges and VLAN sub-interfaces
match="DRIVERS==\"?*\", ATTRS{address}==\"$MAC_ADDR\""
if [ $basename = "ath" -o $basename = "wlan" ]; then
  match="$match, ATTRS{type}==\"1\"" # do not match the wifi* interfaces
fi

write_rule "$match" "$INTERFACE" "$comment"

unlock_rules_file

exit 0


[-- Attachment #4: hotplug.functions --]
[-- Type: text/plain, Size: 2561 bytes --]

# vim: syntax=sh

PATH='/sbin:/bin'


# Read a single line from file $1 in the $DEVPATH directory.
# The function must not return an error even if the file does not exist.
sysread() {
  local file="$1"
  [ -e "/sys$DEVPATH/$file" ] || return 0
  local value
  read value < "/sys$DEVPATH/$file" || return 0
  echo "$value"
}

sysreadlink() {
  local file="$1"
  [ -e "/sys$DEVPATH/$file" ] || return 0
  readlink -f /sys$DEVPATH/$file 2> /dev/null || true
}

##############################################################################
# Return true if a directory is writeable.
writeable() {
  if ln -s test-link $1/.is-writeable 2> /dev/null; then
    rm -f $1/.is-writeable
    return 0
  else
    return 1
  fi
}

##############################################################################
# Create a lock file for the current rules file.
lock_rules_file() {
  [ -e /dev/.udev/ ] || return 0

  RULES_LOCK="/dev/.udev/.lock-${RULES_FILE##*/}"

  retry=30
  while ! mkdir $RULES_LOCK 2> /dev/null; do
    if [ $retry -eq 0 ]; then
       echo "Cannot lock $RULES_FILE!" >&2
       exit 2
    fi
    sleep 1
    retry=$(($retry - 1))
  done
}

unlock_rules_file() {
  [ "$RULES_LOCK" ] || return 0
  rmdir $RULES_LOCK || true
}

# Choose the real rules file if it is writeable or a temporary file if not.
# Both files should be checked later when looking for existing rules.
choose_rules_file() {
  local tmp_rules_file="/dev/.udev/tmp-rules--${RULES_FILE##*/}"
  [ -e "$RULES_FILE" -o -e "$tmp_rules_file" ] || PRINT_HEADER=1

  if writeable ${RULES_FILE%/*}; then
    RO_RULES_FILE='/dev/null'
  else
    RO_RULES_FILE=$RULES_FILE
    RULES_FILE=$tmp_rules_file
  fi
}

abort_if_run_early() {
  return # DISABLED

  if ! writeable ${RULES_FILE%/*}; then
    exit 0
  fi
}

##############################################################################
# Return the name of the first free device.
raw_find_next_available() {
  local links="$1"

  local basename=${links%%[ 0-9]*}
  local max=-1
  for name in $links; do
    local num=${name#$basename}
    [ "$num" ] || num=0
    [ $num -gt $max ] && max=$num
  done

  local max=$(($max + 1))
  # "name0" actually is just "name"
  [ $max -eq 0 ] && return
  echo "$max"
}

# Find all rules matching a key (with action) and a pattern.
find_all_rules() {
  local key="$1"
  local linkre="$2"
  local match="$3"

  [ -e $RULES_FILE ] || return

  local search='.*[[:space:],]'"$key"'"\('"$linkre"'\)"[[:space:]]*\(,.*\|\\\|\)$'

  echo $(sed -n -e "${match}s/${search}/\1/p" $RO_RULES_FILE $RULES_FILE)
}


[-- Attachment #5: udev.udev-mtab.init --]
[-- Type: text/plain, Size: 422 bytes --]

#!/bin/sh -e
### BEGIN INIT INFO
# Provides:          udev-mtab
# Required-Start:    udev checkroot
# Required-Stop:     
# Default-Start:     S
# Default-Stop:
### END INIT INFO

PATH="/sbin:/bin"

# copy the rules generated before / was mounted read-write
for file in /dev/.udev/tmp-rules--*; do
  dest=${file##*tmp-rules--}
  [ "$dest" = '*' ] && break
  cat $file >> /etc/udev/rules.d/$dest
  rm -f $file
done

exit 0

[-- Attachment #6: cd-aliases-generator.rules --]
[-- Type: text/plain, Size: 558 bytes --]

# These rules generate rules for the /dev/{cdrom,dvd,...} symlinks and
# write them in /etc/udev/rules.d/z20_persistent-cd.rules.
#
# If you want to configure them manually then just delete the symlink
# pointing to this file.
#
# The default symlink for this file is z75_cd-aliases-generator.rules.

ACTION!="add",				GOTO="cd_aliases_generator_end"
SUBSYSTEM!="block",			GOTO="cd_aliases_generator_end"
ENV{GENERATED}=="?*",			GOTO="cd_aliases_generator_end"

ENV{ID_CDROM}=="?*", PROGRAM="write_cd_rules", SYMLINK+="%c"

LABEL="cd_aliases_generator_end"


[-- Attachment #7: persistent-net-generator.rules --]
[-- Type: text/plain, Size: 497 bytes --]

ACTION!="add",				GOTO="persistent_net_generator_end"
SUBSYSTEM!="net",			GOTO="persistent_net_generator_end"

# ignore the interface if a name has already been set
NAME=="?*",				GOTO="persistent_net_generator_end"
# ignore interfaces without a driver link
ENV{DRIVER}!="?*",			GOTO="persistent_net_generator_end"

KERNEL=="eth*|ath*|wlan*|ra*|sta*", \
	IMPORT{program}="write_net_rules $attr{address}"

ENV{INTERFACE_NEW}=="?*", NAME="$env{INTERFACE_NEW}"

LABEL="persistent_net_generator_end"


[-- Attachment #8: Type: text/plain, Size: 373 bytes --]

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

[-- Attachment #9: Type: text/plain, Size: 226 bytes --]

_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

             reply	other threads:[~2006-09-02  9:06 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-09-02  9:06 Marco d'Itri [this message]
2006-09-03  3:16 ` scripts for persistent names support Kay Sievers
2006-09-03 10:10 ` Marco d'Itri
2006-09-03 12:48 ` Kay Sievers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060902090653.GA4424@wonderland.linux.it \
    --to=md@linux.it \
    --cc=linux-hotplug@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).