summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am5
-rw-r--r--configure.ac10
-rw-r--r--rule_generator/75-cd-aliases-generator.rules9
-rw-r--r--rule_generator/75-persistent-net-generator.rules (renamed from rules/75-persistent-net-generator.rules)0
-rw-r--r--rule_generator/Makefile.am15
-rw-r--r--rule_generator/rule_generator.functions116
-rw-r--r--rule_generator/write_cd_rules127
-rw-r--r--rule_generator/write_net_rules141
8 files changed, 423 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 60e3ce90f1..4b07a365d5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,3 +18,8 @@ if ENABLE_MANPAGES
SUBDIRS += \
man
endif
+
+if ENABLE_RULE_GENERATOR
+SUBDIRS += \
+ rule_generator
+endif
diff --git a/configure.ac b/configure.ac
index 045445214b..c6aaa6a9ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -296,6 +296,15 @@ AC_ARG_WITH([modprobe],
AC_SUBST([MODPROBE], ["${with_modprobe}"])
# ------------------------------------------------------------------------------
+# rule_generator - persistent network and optical device rule generator
+# ------------------------------------------------------------------------------
+AC_ARG_ENABLE([rule_generator],
+ AS_HELP_STRING([--enable-rule_generator], [enable persistent network, cdrom support]),
+ [], [enable_rule_generator=no])
+
+AM_CONDITIONAL([ENABLE_RULE_GENERATOR], [test "x$enable_rule_generator" = xyes])
+
+# ------------------------------------------------------------------------------
AC_CONFIG_FILES([Makefile
docs/Makefile
@@ -308,6 +317,7 @@ AC_CONFIG_FILES([Makefile
keymaps/Makefile
man/Makefile
rules/Makefile
+ rule_generator/Makefile
src/Makefile
src/accelerometer/Makefile
src/ata_id/Makefile
diff --git a/rule_generator/75-cd-aliases-generator.rules b/rule_generator/75-cd-aliases-generator.rules
new file mode 100644
index 0000000000..e6da0101d6
--- /dev/null
+++ b/rule_generator/75-cd-aliases-generator.rules
@@ -0,0 +1,9 @@
+# these rules generate rules for the /dev/{cdrom,dvd,...} symlinks
+
+# the "path" of usb/ieee1394 devices changes frequently, use "id"
+ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb|ieee1394", ENV{ID_CDROM}=="?*", ENV{GENERATED}!="?*", \
+ PROGRAM="write_cd_rules by-id", SYMLINK+="%c", GOTO="persistent_cd_end"
+
+ACTION=="add", SUBSYSTEM=="block", ENV{ID_CDROM}=="?*", ENV{GENERATED}!="?*", PROGRAM="write_cd_rules", SYMLINK+="%c"
+
+LABEL="persistent_cd_end"
diff --git a/rules/75-persistent-net-generator.rules b/rule_generator/75-persistent-net-generator.rules
index 539807c861..539807c861 100644
--- a/rules/75-persistent-net-generator.rules
+++ b/rule_generator/75-persistent-net-generator.rules
diff --git a/rule_generator/Makefile.am b/rule_generator/Makefile.am
new file mode 100644
index 0000000000..2754c9db67
--- /dev/null
+++ b/rule_generator/Makefile.am
@@ -0,0 +1,15 @@
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+# ------------------------------------------------------------------------------
+# rule_generator - persistent network and optical device rule generator
+# ------------------------------------------------------------------------------
+dist_udevlibexec_SCRIPTS = \
+ write_cd_rules \
+ write_net_rules
+
+udevhomedir = $(udevlibexecdir)
+dist_udevhome_DATA = rule_generator.functions
+
+dist_udevrules_DATA = \
+ 75-cd-aliases-generator.rules \
+ 75-persistent-net-generator.rules
diff --git a/rule_generator/rule_generator.functions b/rule_generator/rule_generator.functions
new file mode 100644
index 0000000000..4bec27a1b7
--- /dev/null
+++ b/rule_generator/rule_generator.functions
@@ -0,0 +1,116 @@
+# functions used by the udev rule generator
+
+# Copyright (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, either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+PATH='/sbin:/bin'
+#
+
+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() {
+ RUNDIR=$(udevadm info --run)
+ [ -e "$RUNDIR" ] || return 0
+
+ RULES_LOCK="$RUNDIR/.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() {
+ RUNDIR=$(udevadm info --run)
+ local tmp_rules_file="$RUNDIR/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"
+
+ local search='.*[[:space:],]'"$key"'"('"$linkre"')".*'
+ echo $(sed -n -r -e 's/^#.*//' -e "${match}s/${search}/\1/p" \
+ $RO_RULES_FILE \
+ $([ -e $RULES_FILE ] && echo $RULES_FILE) \
+ 2>/dev/null)
+}
diff --git a/rule_generator/write_cd_rules b/rule_generator/write_cd_rules
new file mode 100644
index 0000000000..00382ada2f
--- /dev/null
+++ b/rule_generator/write_cd_rules
@@ -0,0 +1,127 @@
+#!/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, either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# debug, if UDEV_LOG=<debug>
+if [ -n "$UDEV_LOG" ]; then
+ if [ "$UDEV_LOG" -ge 7 ]; then
+ set -x
+ fi
+fi
+
+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, 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"
+ echo "# line, 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
+
+if [ "$1" ]; then
+ METHOD="$1"
+else
+ METHOD='by-path'
+fi
+
+case "$METHOD" in
+ by-path)
+ if [ -z "$ID_PATH" ]; then
+ echo "$DEVPATH not supported by path_id. by-id may work." >&2
+ exit 1
+ fi
+ RULE="ENV{ID_PATH}==\"$ID_PATH\""
+ ;;
+
+ by-id)
+ if [ "$ID_SERIAL" ]; then
+ RULE="ENV{ID_SERIAL}==\"$ID_SERIAL\""
+ elif [ "$ID_MODEL" -a "$ID_REVISION" ]; then
+ RULE="ENV{ID_MODEL}==\"$ID_MODEL\", ENV{ID_REVISION}==\"$ID_REVISION\""
+ else
+ echo "$DEVPATH not supported by ata_id. by-path may work." >&2
+ exit 1
+ fi
+ ;;
+
+ *)
+ echo "Invalid argument (must be either by-path or by-id)." >&2
+ exit 1
+ ;;
+esac
+
+# 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="SUBSYSTEM==\"block\", ENV{ID_CDROM}==\"?*\", $RULE"
+
+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"
+echo >> $RULES_FILE
+
+unlock_rules_file
+
+echo $SYMLINKS
+
+exit 0
+
diff --git a/rule_generator/write_net_rules b/rule_generator/write_net_rules
new file mode 100644
index 0000000000..437979241f
--- /dev/null
+++ b/rule_generator/write_net_rules
@@ -0,0 +1,141 @@
+#!/bin/sh -e
+
+# This script is run to create persistent network device naming rules
+# based on properties of the device.
+# If the interface needs to be renamed, INTERFACE_NEW=<name> will be printed
+# on stdout to allow udev to IMPORT it.
+
+# variables used to communicate:
+# MATCHADDR MAC address used for the match
+# MATCHID bus_id used for the match
+# MATCHDEVID dev_id used for the match
+# MATCHDRV driver name used for the match
+# MATCHIFTYPE interface type match
+# COMMENT comment to add to the generated rule
+# INTERFACE_NAME requested name supplied by external tool
+# INTERFACE_NEW new interface name returned by rule writer
+
+# Copyright (C) 2006 Marco d'Itri <md@Linux.IT>
+# Copyright (C) 2007 Kay Sievers <kay.sievers@vrfy.org>
+#
+# 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, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# debug, if UDEV_LOG=<debug>
+if [ -n "$UDEV_LOG" ]; then
+ if [ "$UDEV_LOG" -ge 7 ]; then
+ set -x
+ fi
+fi
+
+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, 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"
+ echo "# line, and change only the value of the NAME= key."
+ fi
+
+ echo ""
+ [ "$comment" ] && echo "# $comment"
+ echo "SUBSYSTEM==\"net\", ACTION==\"add\"$match, NAME=\"$name\""
+ } >> $RULES_FILE
+}
+
+if [ -z "$INTERFACE" ]; then
+ echo "missing \$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
+
+# the DRIVERS key is needed to not match bridges and VLAN sub-interfaces
+if [ "$MATCHADDR" ]; then
+ match="$match, DRIVERS==\"?*\", ATTR{address}==\"$MATCHADDR\""
+fi
+
+if [ "$MATCHDRV" ]; then
+ match="$match, DRIVERS==\"$MATCHDRV\""
+fi
+
+if [ "$MATCHDEVID" ]; then
+ match="$match, ATTR{dev_id}==\"$MATCHDEVID\""
+fi
+
+if [ "$MATCHID" ]; then
+ match="$match, KERNELS==\"$MATCHID\""
+fi
+
+if [ "$MATCHIFTYPE" ]; then
+ match="$match, ATTR{type}==\"$MATCHIFTYPE\""
+fi
+
+if [ -z "$match" ]; then
+ echo "missing valid match" >&2
+ unlock_rules_file
+ exit 1
+fi
+
+basename=${INTERFACE%%[0-9]*}
+match="$match, KERNEL==\"$basename*\""
+
+if [ "$INTERFACE_NAME" ]; then
+ # external tools may request a custom name
+ COMMENT="$COMMENT (custom name provided by external tool)"
+ if [ "$INTERFACE_NAME" != "$INTERFACE" ]; then
+ INTERFACE=$INTERFACE_NAME;
+ echo "INTERFACE_NEW=$INTERFACE"
+ fi
+else
+ # if a rule using the current name already exists, find a new name
+ if interface_name_taken; then
+ INTERFACE="$basename$(find_next_available "$basename[0-9]*")"
+ # prevent INTERFACE from being "eth" instead of "eth0"
+ [ "$INTERFACE" = "${INTERFACE%%[ \[\]0-9]*}" ] && INTERFACE=${INTERFACE}0
+ echo "INTERFACE_NEW=$INTERFACE"
+ fi
+fi
+
+write_rule "$match" "$INTERFACE" "$COMMENT"
+
+unlock_rules_file
+
+exit 0