add persistent rules generator for net devices and optical drives

This commit is contained in:
Marco d'Itri
2006-09-05 15:20:28 +02:00
committed by Kay Sievers
parent d60fd52af8
commit fbcbf70bb2
7 changed files with 397 additions and 1 deletions
@@ -0,0 +1,3 @@
# these rules generate rules for the /dev/{cdrom,dvd,...} symlinks
ACTION=="add", SUBSYSTEM=="block", ENV{ID_CDROM}=="?*", ENV{GENERATED}!="?*", PROGRAM="write_cd_rules", SYMLINK+="%c"
@@ -0,0 +1,17 @@
# these rules generate rules for persistent network device naming
ACTION=="add", SUBSYSTEM=="net", NAME!="?*", DRIVERS=="?*", GOTO="persistent_net_generator_do"
GOTO="persistent_net_generator_end"
LABEL="persistent_net_generator_do"
# export device description to comment the generated rule
SUBSYSTEMS=="pci", ENV{COMMENT}="PCI Device: $attr{vendor}:$attr{device} ($attr{driver})"
SUBSYSTEMS=="usb", ENV{COMMENT}="USB Device: 0x$attr{idVendor}:0x$attr{idProduct} ($attr{driver})"
SUBSYSTEMS=="ieee1394", ENV{COMMENT}="Firewire Device: $attr{host_id} ($attr{driver})"
SUBSYSTEMS=="xen", ENV{COMMENT}="Xen virtual device"
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"
+68
View File
@@ -0,0 +1,68 @@
# Makefile for udev extra invoked from the udev main Makefile
#
# Copyright (C) 2004-2006 Kay Sievers <kay.sievers@vrfy.org>
#
# Released under the GNU General Public License, version 2.
#
PROG =
MAN_PAGES =
prefix =
etcdir = ${prefix}/etc
sbindir = ${prefix}/sbin
usrbindir = ${prefix}/usr/bin
usrsbindir = ${prefix}/usr/sbin
libudevdir = ${prefix}/lib/udev
mandir = ${prefix}/usr/share/man
configdir = ${etcdir}/udev
INSTALL = /usr/bin/install -c
INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644
INSTALL_SCRIPT = ${INSTALL_PROGRAM}
all: $(PROG) $(MAN_PAGES)
.PHONY: all
.DEFAULT: all
# man pages
%.8: %.xml
$(E) " XMLTO " $@
$(Q) xmlto man $?
.PRECIOUS: %.8
clean:
$(E) " CLEAN "
.PHONY: clean
install-bin: all
$(INSTALL_PROGRAM) -D rule_generator.functions $(DESTDIR)$(libudevdir)/rule_generator.functions
$(INSTALL_PROGRAM) -D write_cd_rules $(DESTDIR)$(libudevdir)/write_cd_rules
$(INSTALL_PROGRAM) -D write_net_rules $(DESTDIR)$(libudevdir)/write_net_rules
$(INSTALL_DATA) -D 75-cd-aliases-generator.rules \
$(DESTDIR)$(configdir)/rules.d/75-cd-aliases-generator.rules
$(INSTALL_DATA) -D 75-persistent-net-generator.rules \
$(DESTDIR)$(configdir)/rules.d/75-persistent-net-generator.rules
.PHONY: install-bin
uninstall-bin:
- rm $(DESTDIR)$(libudevdir)/rule_generator.functions
- rm $(DESTDIR)$(libudevdir)/write_cd_rules
- rm $(DESTDIR)$(libudevdir)/write_net_rules
- rm $(DESTDIR)$(configdir)/rules.d/75-cd-aliases-generator.rules
- rm $(DESTDIR)$(configdir)/rules.d/75-persistent-net-generator.rules
.PHONY: uninstall-bin
install-man:
@echo "Please create a man page for this tool."
.PHONY: install-man
uninstall-man:
@echo "Please create a man page for this tool."
.PHONY: uninstall-man
install-config:
@echo "no config file to install"
.PHONY: install-config
@@ -0,0 +1,98 @@
# functions used by the udev rule generator
#
# 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 version 2 of the License.
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
}
# 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)
}
+78
View File
@@ -0,0 +1,78 @@
#!/bin/sh -e
# This script is run if an optical drive lacks a rule for persistent naming.
#
# It adds symlinks for optical drives based on the device class determined
# by cdrom_id and used ID_PATH to identify the device.
#
# (C) 2006 Marco d'Itri <md@Linux.IT>
#
# 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 version 2 of the License.
RULES_FILE="/etc/udev/rules.d/70-persistent-cd.rules"
. /lib/udev/rule_generator.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
# 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
+130
View File
@@ -0,0 +1,130 @@
#!/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.
#
# (C) 2006 Marco d'Itri <md@Linux.IT>
#
# 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 version 2 of the License.
RULES_FILE='/etc/udev/rules.d/70-persistent-net.rules'
. /lib/udev/rule_generator.functions
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
}
# used only if $RULES_FILE is empty, like on installation
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
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
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
# 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
# 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
+3 -1
View File
@@ -11,7 +11,9 @@ EXTRAS="\
extras/edd_id \
extras/floppy \
extras/run_directory \
extras/firmware"
extras/firmware \
extras/path_id \
extras/rule_generator"
# with debug
make clean EXTRAS="$EXTRAS" >/dev/null