summaryrefslogtreecommitdiff
blob: 72b2be226a5fc7b863b05ac4557c5ca986ce0f69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#!/sbin/runscript
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

command_args="--daemon ${udev_opts}"
description="udev manages device permissions and symbolic links in /dev"
extra_started_commands="reload"
description_reload="Reload the udev rules and databases"

udev_monitor="${udev_monitor:-no}"
udevmonitor_log=/run/udevmonitor.log
udevmonitor_pid=/run/udevmonitor.pid

depend()
{
	provide dev
	need sysfs dev-mount
	before checkfs fsck

	# udev does not work inside vservers
	keyword -vserver -lxc
}

start_pre()
{
	# make sure devtmpfs is in the kernel
	if ! grep -qs devtmpfs /proc/filesystems; then
		eerror "CONFIG_DEVTMPFS=y is required in your kernel configuration"
		eerror "for this version of udev to run successfully."
		eerror "This requires immediate attention."
		if ! mountinfo -q /dev; then
			mount -n -t tmpfs dev /dev
			busybox mdev -s
			mkdir /dev/pts
		fi
		return 1
	fi

	# make sure /dev is a mounted devtmpfs
	if ! mountinfo -q -f devtmpfs /dev; then
		eerror "Udev requires /dev to be a mounted devtmpfs."
		eerror "Please reconfigure your system."
		return 1
	fi

	# load unix domain sockets if built as module, Bug #221253
	# and not yet loaded, Bug #363549
	if [ ! -e /proc/net/unix ]; then
		if ! modprobe unix; then
			eerror "Cannot load the unix domain socket module"
			return 1
		fi
	fi

	bins="/sbin/udevd /lib/systemd/systemd-udevd /usr/lib/systemd/systemd-udevd"
	for f in ${bins}; do
		if [ -x "$f" -a ! -L "$f" ]; then
			command="$f"
		fi
	done
	if [ -z "$command" ]; then
		eerror "Unable to find udev executable."
		return 1
	fi

	if [ -e /proc/sys/kernel/hotplug ]; then
		echo "" >/proc/sys/kernel/hotplug
	fi

	if yesno "${udev_debug:-NO}"; then
		command_args="${command_args} --debug 2> /run/udevdebug.log"
	fi

	return 0
}

start_udevmonitor()
{
	yesno "${udev_monitor}" || return 0

	einfo "udev: Running udevadm monitor ${udev_monitor_opts} to log all events"
	start-stop-daemon --start --stdout "${udevmonitor_log}" \
		--make-pidfile --pidfile "${udevmonitor_pid}" \
		--background --exec /bin/udevadm -- monitor ${udev_monitor_opts}
}

# This is here because some software expects /dev/root to exist.
# For more information, see this bug:
# https://bugs.gentoo.org/show_bug.cgi?id=438380
dev_root_link()
{
	local RULESDIR=/run/udev/rules.d
	[ -d $RULESDIR ] || mkdir -p $RULESDIR
	eval $(udevadm info --export --export-prefix=ROOT_ --device-id-of-file=/ ||
		true)
	[ "$ROOT_MAJOR" -a "$ROOT_MINOR" ] || return 0

	# btrfs filesystems have bogus major/minor numbers
	[ "$ROOT_MAJOR" != 0 ] || return 0

	echo 'ACTION=="add|change", SUBSYSTEM=="block", ENV{MAJOR}=="'$ROOT_MAJOR'", ENV{MINOR}=="'$ROOT_MINOR'", SYMLINK+="root"' > $RULESDIR/61-dev-root-link.rules
}

populate_dev()
{
	if yesno ${rc_dev_root_symlink:-yes}; then
		ebegin "Generating a rule to create a /dev/root symlink"
		dev_root_link
		eend $?
	fi

	get_bootparam "nocoldplug" && rc_coldplug="no"
	if ! yesno ${rc_coldplug:-${RC_COLDPLUG:-yes}}; then
		einfo "Setting /dev permissions and symbolic links"
		udevadm trigger --attr-match=dev --action=add
		udevadm trigger --subsystem-match=net --action=add
		ewarn "Skipping udev coldplug sequence"
		return 0
	fi

	ebegin "Populating /dev with existing devices through uevents"
	udevadm trigger --type=subsystems --action=add
	udevadm trigger --type=devices --action=add
	eend $?

	ebegin "Waiting for uevents to be processed"
	udevadm settle --timeout=${udev_settle_timeout:-60}
	eend $?
	return 0
}

stop_udevmonitor()
{
	yesno "${udev_monitor}" || return 0

	if yesno "${udev_monitor_keep_running:-no}"; then
		ewarn "udev: udevmonitor is still running and writing into ${udevmonitor_log}"
	else
		einfo "udev: Stopping udevmonitor: Log is in ${udevmonitor_log}"
		start-stop-daemon --stop --pidfile "${udevmonitor_pid}" --exec /bin/udevadm
	fi
}

display_hotplugged_services()
{
	local svcfile= svc= services=
	for svcfile in "${RC_SVCDIR}"/hotplugged/*; do
		svc="${svcfile##*/}"
		[ -x "${svcfile}" ] || continue

		services="${services} ${svc}"
	done
	[ -n "${services}" ] && einfo "Device initiated services:${HILITE}${services}${NORMAL}"
}

start_post()
{
	start_udevmonitor
	populate_dev
	stop_udevmonitor
	display_hotplugged_services
	return 0
}

stop()
{
	local rc=0
	ebegin "Stopping ${name:-$RC_SVCNAME}"
	udevadm control --exit
	rc=$?
	if [ $rc -ne 0 ]; then
		eend $rc "Failed to stop $RC_SVCNAME using udevadm"
		ebegin "Trying with start-stop-daemon"
		start-stop-daemon --stop --exec /sbin/udevd
		rc=$?
	fi
	eend $rc "Failed to stop $RC_SVCNAME"
}

reload()
{
	ebegin "reloading udev rules and databases"
	udevadm control --reload
	eend $?
}