add persistent rules generator for net devices and optical drives
This commit is contained in:
committed by
Kay Sievers
parent
d60fd52af8
commit
fbcbf70bb2
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user