#!/bin/bash # # script: rc.udev # # This is a script to initialize udev, which populates the /dev # directory with device nodes, scans for devices, loads the # appropriate kernel modules, and configures the devices. # # LimeTech - modified for Unraid OS # Bergware - modified for Unraid OS, October 2023 # Set the path. PATH=/sbin:/bin # run & log functions . /etc/rc.d/rc.runlog check_mounted(){ grep -Eq "^[^[:space:]]+ $1 $2" /proc/mounts } mount_devpts(){ if ! check_mounted /dev/pts devpts; then mkdir /dev/pts 2>/dev/null mount -n -o mode=0620,gid=5 -t devpts devpts /dev/pts fi } mount_devshm(){ if ! check_mounted /dev/shm tmpfs; then mkdir /dev/shm 2>/dev/null mount /dev/shm fi } case "$1" in 'start') # Sanity check #1, udev requires that the kernel support tmpfs: if ! grep -wq tmpfs /proc/filesystems; then log "Sorry, but you need tmpfs support in the kernel to use udev." log "FATAL: Refusing to run /etc/rc.d/rc.udev." exit 1 fi # Sanity check #2, make sure that a 2.6.x kernel is new enough: if [[ $(uname -r | cut -f 1,2 -d .) == 2.6 ]]; then if [[ $(uname -r | cut -f 3 -d . | sed 's/[^[:digit:]].*//') -lt 32 ]]; then log "Sorry, but you need a 2.6.32+ kernel to use this udev." log "Your kernel version is only $(uname -r)." log "FATAL: Refusing to run /etc/rc.d/rc.udev." exit 1 fi fi # Sanity check #3, make sure the udev package was not removed. If udevd # is not there, this will also shut off this script to prevent further # problems: if [[ ! -x /sbin/udevd ]]; then chmod 0644 /etc/rc.d/rc.udev log "No udevd daemon found." log "Turning off udev: chmod 644 /etc/rc.d/rc.udev" log "FATAL: Refusing to run /etc/rc.d/rc.udev." exit 1 fi # Disable hotplug helper since udevd listens to netlink: if [[ -e /proc/sys/kernel/hotplug ]]; then echo >/proc/sys/kernel/hotplug fi if grep -qw devtmpfs /proc/filesystems; then if ! check_mounted /dev devtmpfs; then # umount shm if needed check_mounted /dev/shm tmpfs && umount -l /dev/shm # Umount pts if needed, we will remount it later: check_mounted /dev/pts devpts && umount -l /dev/pts # Mount tmpfs on /dev: mount -n -t devtmpfs -o size=8M devtmpfs /dev fi else # Mount tmpfs on /dev: if ! check_mounted /dev tmpfs; then # umount shm if needed check_mounted /dev/shm tmpfs && umount -l /dev/shm # Umount pts if needed, we will remount it later: check_mounted /dev/pts devpts && umount -l /dev/pts # Mount tmpfs on /dev: # the -n is because we don't want /dev umounted when # someone (rc.[06]) calls umount -a mount -n -o mode=0755 -t tmpfs -o size=8M tmpfs /dev fi fi # Mount devpts mount_devpts mount_devshm if ! pidof udevd &>/dev/null; then # start udevd log "Creating static nodes in /dev." run kmod static-nodes -f tmpfiles --output /run/static-nodes grep "^d " /run/static-nodes | while read line; do mkdir -p -m $(echo $line | cut -f 3 -d ' ') $(echo $line | cut -f 2 -d ' ') done grep -v "^d " /run/static-nodes | while read line; do mknod -m $(echo $line | cut -f 3 -d ' ') \ $(echo $line | cut -f 2 -d ' ') \ $(echo $line | cut -b1 ) \ $(echo $line | cut -f 7 -d ' ' | cut -f 1 -d :) \ $(echo $line | cut -f 7 -d ' ' | cut -f 2 -d :) 2>/dev/null done rm -f /run/static-nodes # Add any system defined additional device nodes: cp --preserve=all --recursive --update /lib/udev/devices/* /dev 2>/dev/null # Add any locally defined additional device nodes: cp --preserve=all --recursive --update /etc/udev/devices/* /dev 2>/dev/null log "Starting udevd..." run udevd --daemon # Since udev is just now being started we want to use add events: log "Triggering udev events..." # Call udevtrigger and udevsettle to do the device configuration: run udevadm trigger --type=subsystems --action=add run udevadm trigger --type=devices --action=add else # trigger changes for already running udevd # Bergware - set file references RAM=/etc/udev/rules.d/70-persistent-net.rules ROM=/boot/config/network-rules.cfg MAC='ATTR{address}=="\K..:..:..:..:..:..' # If the persistent network rules file does not exist, trigger an add event: if [[ ! -r $RAM ]]; then # Test that we can actually write to the directory first: if touch /etc/udev/rules.d/testfile 2>/dev/null; then rm -f /etc/udev/rules.d/testfile # This should add persistent net rules: log "Triggering udev to write persistent rules to /etc/udev/rules.d/" run udevadm trigger --type=devices --action=add sleep 3 # Create the files if they don't exist at this point. # If a machine does not have a network device or an optical # device, we don't want to waste time trying to generate # rules at every boot. # To force another attempt, delete the file(s). touch $RAM fi fi # Bergware - start of code if [[ -f $ROM ]]; then NEW=$(grep -Po $MAC $RAM | sort) # Bergware - set persistent rules of existing interfaces grep -B2 "$NEW" $ROM | /usr/bin/fromdos >$RAM run udevadm control --reload # Bergware - find the unique drivers currently in use by the interface(s) DRIVERS= for PORT in $(ls --indicator-style=none /sys/class/net | grep -P '^eth\d+$'); do DRIVER=$(/usr/sbin/ethtool -i $PORT | grep -Po '^driver: \K\S+') [[ $DRIVERS != *$DRIVER* ]] && DRIVERS="$DRIVERS $DRIVER" done # Bergware - delete existing interfaces and recreate them using the updated udev rules modprobe -r $DRIVERS modprobe -a $DRIVERS # Bergware - check for changes and save them if [[ $NEW != $(grep -Po $MAC $ROM | sort) ]]; then # Bergware - copy to flash only when more than one interface is present [[ $(echo "$NEW" | wc -l) -gt 1 ]] && /usr/bin/todos <$RAM >$ROM || rm -f $ROM fi else # Bergware - remove leading remarks in file sed -i '/^# This/,/^$/d' $RAM # Bergware - copy to flash only when more than one interface is present [[ $(grep -Pc 'NAME="eth\d+"' $RAM) -gt 1 ]] && /usr/bin/todos <$RAM >$ROM || rm -f $ROM fi # Bergware - end of code # Update the hardware database index (/etc/udev/hwdb.bin), if possible: if touch /etc/udev/testfile 2>/dev/null; then rm -f /etc/udev/testfile log "Updating hardware database index..." run udevadm hwdb --update fi # Since udevd is running, most of the time we only need change events: log "Triggering udev events..." run udevadm trigger --type=subsystems --action=change run udevadm trigger --type=devices --action=change fi run udevadm settle --timeout=120 ;; 'stop') log "Stopping udevd is STRONGLY discouraged and not supported." log "If you are sure you want to do this, use 'force-stop' instead." ;; 'restart') log "Restarting udevd is STRONGLY discouraged and not supported." log "If you are sure you want to do this, use 'force-restart' instead." ;; 'reload') log "Reloading udev rules" udevadm control --reload ;; 'force-stop') log "Stopping udevd" udevadm control --exit killall udevd 2>/dev/null ;; 'force-restart') log "Restarting udevd" udevadm control --exit sleep 3 udevd --daemon ;; 'force-reload') log "Updating all available device nodes in /dev" udevadm control --reload rm -rf /dev/.udev /dev/disk cp --preserve=all --recursive --update /lib/udev/devices/* /dev 2>/dev/null ;; *) echo "Usage: $BASENAME start|stop|restart|reload|force-stop|force-restart|force-reload" exit 1 esac exit 0