blob: e181886468163fad5a7aa017e2deacff6167aa46 (
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
186
187
188
189
190
191
192
193
194
195
196
|
# -*-eselect-*- vim: ft=eselect
# Copyright 2005-2023 Gentoo Authors
# Distributed under the terms of the GNU GPL version 2 or later
DESCRIPTION="Manage the /usr/src/linux symlink"
MAINTAINER="eselect@gentoo.org"
# sort function for kernel versions, to be used in a pipe
sort_kernel_versions() {
local vsort="sort --version-sort"
# Test if our sort supports the --version-sort option
# (should be GNU sort, since the kernel module is GNU/Linux specific)
${vsort} </dev/null &>/dev/null || vsort=sort
# We sort kernel versions as follows:
# 1. Run sed to prepend the version string by the numeric version
# and an additional rank indicator that is 0 for release candidates
# or 1 otherwise. After this step we have, for example:
# 2.6.29 1 linux-2.6.29
# 2.6.29 0 linux-2.6.29-rc8
# 2. sort --version-sort
# 3. Run sed again to remove the prepended keys from step 1.
sed -e 's/^\(linux-\)\?\([[:digit:].]\+\)[-_]rc/\2 0 &/' \
-e 't;s/^\(linux-\)\?\([[:digit:].]\+\)/\2 1 &/' \
| LC_ALL=C ${vsort} | sed 's/.* //'
}
# find a list of kernel symlink targets
find_targets() {
local f
for f in "${EROOT}"/usr/src/linux-*; do
[[ -f ${f}/Makefile && -f ${f}/Kconfig ]] && basename "${f}"
done | sort_kernel_versions
}
# remove the kernel symlink
remove_symlink() {
rm -f "${EROOT}/usr/src/linux"
}
# set the kernel symlink
set_symlink() {
local target=$1
if is_number "${target}"; then
local targets=( $(find_targets) )
[[ ${target} -ge 1 && ${target} -le ${#targets[@]} ]] \
|| die -q "Number out of range: $1"
target=${targets[target-1]}
fi
if [[ -n ${target} ]]; then
if [[ -f ${EROOT}/usr/src/${target}/Makefile ]]; then
:
elif [[ -f ${EROOT}/usr/src/linux-${target}/Makefile ]]; then
target=linux-${target}
else # target not valid
target=
fi
fi
[[ -n ${target} ]] || die -q "Target \"$1\" doesn't appear to be valid!"
remove_symlink || die -q "Couldn't remove existing symlink"
ln -s "${target}" "${EROOT}/usr/src/linux"
}
### show action ###
describe_show() {
echo "Show the current kernel symlink"
}
do_show() {
write_list_start "Current kernel symlink:"
if [[ -L ${EROOT}/usr/src/linux ]]; then
local kernel=$(canonicalise "${EROOT}/usr/src/linux")
write_kv_list_entry "${kernel%/}" ""
[[ -f ${kernel}/Makefile ]] \
|| write_warning_msg "Symlink target doesn't appear to be valid!"
else
write_kv_list_entry "(unset)" ""
fi
}
### list action ###
describe_list() {
echo "List available kernel symlink targets"
}
do_list() {
local i targets=( $(find_targets) )
write_list_start "Available kernel symlink targets:"
for (( i = 0; i < ${#targets[@]}; i++ )); do
[[ ${targets[i]} = \
$(basename "$(canonicalise "${EROOT}/usr/src/linux")") ]] \
&& targets[i]=$(highlight_marker "${targets[i]}")
done
write_numbered_list -m "(none found)" "${targets[@]}"
}
### set action ###
describe_set() {
echo "Set a new kernel symlink target"
}
describe_set_parameters() {
echo "<target>"
}
describe_set_options() {
echo "target : Target name or number (from 'list' action)"
}
do_set() {
[[ -z $1 ]] && die -q "You didn't tell me what to set the symlink to"
[[ $# -gt 1 ]] && die -q "Too many parameters"
if [[ -e ${EROOT}/usr/src/linux && ! -L ${EROOT}/usr/src/linux ]]; then
# we have something strange
die -q "${EROOT}/usr/src/linux exists but is not a symlink"
fi
set_symlink "$1" || die -q "Couldn't set a new symlink"
}
### update action ###
describe_update() {
echo "Update the kernel symlink to running kernel"
}
describe_update_options() {
echo "ifunset: Do not override currently set version"
}
do_update() {
[[ -z $1 || $1 == ifunset ]] || die -q "Usage error"
[[ $# -gt 1 ]] && die -q "Too many parameters"
test_for_root
if [[ -e ${EROOT}/usr/src/linux ]]; then
if [[ ! -L ${EROOT}/usr/src/linux ]]; then
# we have something strange
die -q "${EROOT}/usr/src/linux exists but is not a symlink"
fi
if [[ $1 == ifunset ]]; then
# The /usr/src/linux symlink exists, points to a path that
# exists, and 'ifunset' is provided. Nothing to do.
return
fi
fi
local targets=( $(find_targets) )
[[ ${#targets[@]} -gt 0 ]] || die -q "No target kernel-source trees found"
local running_kernel_release
running_kernel_release=$(uname -r) || die -q "uname failed with $?"
local running_kernel_symlink_target="linux-${running_kernel_release}"
if [[ -e ${EROOT}/usr/src/linux ]]; then
local current_target
current_target=$(basename "$(canonicalise "${EROOT}/usr/src/linux")")
if [[ ${current_target} == "${running_kernel_symlink_target}" ]]; then
# The /usr/src/linux symlink already points to the running
# kernel's sources. Nothing to do.
return
fi
fi
local target
for target in "${targets[@]}"; do
if [[ ${target} == "${running_kernel_symlink_target}" ]]; then
set_symlink "${target}"
return
fi
done
write_error_msg \
"No sources for running kernel ${running_kernel_release} found."
if ! is_output_mode brief; then
do_list >&2
fi
die -q "Could not update the kernel symlink"
}
### helper functions ###
test_for_root() {
if [[ ! -w ${EROOT}/usr/src ]]; then
die -q "${EROOT}/usr/src not writeable by current user. Are you root?"
fi
}
|