summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bash-completion24
-rwxr-xr-xmkinitcpio19
2 files changed, 33 insertions, 10 deletions
diff --git a/bash-completion b/bash-completion
index aa6efbb..597eab2 100644
--- a/bash-completion
+++ b/bash-completion
@@ -1,6 +1,14 @@
#!/bin/bash
# mkinitcpio bash completion by Seblu <seblu@seblu.net>
+detect_kver() {
+ local kver_validator='^[[:digit:]]+(\.[[:digit:]]+)+'
+ offset=$(hexdump -s 526 -n 2 -e '"%0d"' "$1" 2>/dev/null) || return 1
+ read kver _ < \
+ <(dd if="$1" bs=1 count=127 skip=$(( offset + 0x200 )) 2>/dev/null)
+ [[ $kver =~ $kver_validator ]] && printf "$kver"
+}
+
_lsinitcpio() {
local cur opts
opts=(-a --analyze -c --config -h --help -l --list
@@ -18,14 +26,14 @@ _lsinitcpio() {
_find_kernel_versions() {
local -a matches
- local dir regex
-
- # add completions from kernels in /boot
- regex="Linux kernel.*version"
- while IFS=':' read -r file metadata; do
- [[ $metadata =~ $regex ]] || continue
- matches+=("$file")
- done < <(file -e ascii /boot/*)
+ local dir f
+
+ for f in /boot/*; do
+ # only match regular files which pass validation
+ if [[ ! -L $f && -f $f ]] && kver=$(detect_kver "$f"); then
+ matches+=("$f")
+ fi
+ done
# add completions based on kernel versions in /lib/modules
for dir in /lib/modules/*/kernel; do
diff --git a/mkinitcpio b/mkinitcpio
index 013bc46..752107b 100755
--- a/mkinitcpio
+++ b/mkinitcpio
@@ -82,7 +82,13 @@ cleanup() {
}
resolve_kernver() {
- local kernel=$1
+ local kernel=$1 offset kver
+
+ # this is intentionally very loose. only ensure that we're
+ # dealing with some sort of string that starts with something
+ # resembling dotted decimal notation. remember that there's no
+ # requirement for CONFIG_LOCALVERSION to be set.
+ local kver_validator='^[[:digit:]]+(\.[[:digit:]]+)+'
if [[ -z $kernel ]]; then
uname -r
@@ -99,7 +105,16 @@ resolve_kernver() {
return 1
fi
- if file -Lb "$kernel" | grep -oP '(?<=version )[^ ]+'; then
+ # scrape the version out of the kernel image. locate the offset
+ # to the version string by reading 2 bytes out of image at at
+ # address 0x20E. this leads us to a string of, at most, 128 bytes.
+ # read the first word from this string as the kernel version.
+ offset=$(hexdump -s 526 -n 2 -e '"%0d"' "$kernel")
+ read kver _ < \
+ <(dd if="$kernel" bs=1 count=127 skip=$(( offset + 0x200 )) 2>/dev/null)
+
+ if [[ $kver =~ $kver_validator ]]; then
+ printf '%s' "$kver"
return 0
fi