base/dracut-lib.sh: s/RDDEBUG/RD_DEBUG/g
[dracut.git] / dracut-update-initramfs
blob259c7744aed75df7a950caeb14c436771fb2d4e3
1 #!/bin/bash
2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
5 STATEDIR=/var/lib/dracut
6 BOOTDIR=/boot
7 CONF=/etc/dracut.conf
8 KPKGCONF=/etc/kernel-img.conf
9 USETRIGGERS=true
10 mode=""
11 version=""
13 set -e
15 if $USETRIGGERS \
16 && [ x"$DPKG_MAINTSCRIPT_PACKAGE" != x ] \
17 && [ $# = 1 ] \
18 && [ x"$1" = x-u ] \
19 && dpkg-trigger --check-supported 2>/dev/null
20 then
21 if dpkg-trigger --no-await update-initramfs; then
22 echo "dracut-update-initramfs: deferring update (trigger activated)"
23 exit 0
27 usage()
29 if [ -n "${1}" ]; then
30 printf "${@}\n\n" >&2
32 cat >&2 << EOF
33 Usage: ${0} [OPTION]...
35 Options:
36 -k [version] Specify kernel version or 'all'
37 -c Create a new initramfs
38 -u Update an existing initramfs
39 -d Remove an existing initramfs
40 -t Take over a custom initramfs with this one
41 -b Set alternate boot directory
42 -v Be verbose
43 -h This message
45 EOF
46 exit 1
49 # chroot check
50 chrooted()
52 # borrowed from udev's postinst
53 if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then
54 # the devicenumber/inode pair of / is the same as that of
55 # /sbin/init's root, so we're *not* in a chroot and hence
56 # return false.
57 return 1
59 return 0
62 mild_panic()
64 if [ -n "${1}" ]; then
65 printf "${@}\n" >&2
67 exit 0
70 panic()
72 if [ -n "${1}" ]; then
73 printf "${@}\n" >&2
75 exit 1
78 verbose()
80 if [ "${verbose}" = 1 ]; then
81 printf "${@}\n"
85 version_exists()
87 [ -e "${STATEDIR}/${1}" ] && [ -e "${initramfs}" ]
88 return $?
91 set_initramfs()
93 initramfs="${BOOTDIR}/dracut.img-${version}"
97 # backup initramfs while running
98 backup_initramfs()
100 [ ! -r "${initramfs}" ] && return 0
101 initramfs_bak="${initramfs}.dpkg-bak"
102 [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"
103 ln -f "${initramfs}" "${initramfs_bak}" \
104 || cp -a "${initramfs}" "${initramfs_bak}"
105 verbose "Keeping ${initramfs_bak}"
108 # keep booted initramfs
109 backup_booted_initramfs()
111 initramfs_bak="${initramfs}.dpkg-bak"
113 # first time run thus no backup
114 [ ! -r "${initramfs_bak}" ] && return 0
116 # chroot with no /proc
117 [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0
119 # no kept backup wanted
120 [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0
122 # no backup yet
123 if [ ! -r "${initramfs}.bak" ]; then
124 mv -f ${initramfs_bak} "${initramfs}.bak"
125 verbose "Backup ${initramfs}.bak"
126 return 0
129 # keep booted initramfs
130 uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)
131 if [ -n "$uptime_days" ]; then
132 boot_initramfs=$(find "${initramfs}.bak" -mtime +${uptime_days})
134 if [ -n "${boot_initramfs}" ]; then
135 mv -f "${initramfs_bak}" "${initramfs}.bak"
136 verbose "Backup ${initramfs}.bak"
137 return 0
139 verbose "Removing current backup ${initramfs_bak}"
140 rm -f ${initramfs_bak}
143 # nuke generated copy
144 remove_initramfs()
146 [ -z "${initramfs_bak}" ] && return 0
147 rm -f "${initramfs_bak}"
148 verbose "Removing ${initramfs_bak}"
152 generate_initramfs()
154 echo "dracut-update-initramfs: Generating ${initramfs}"
155 OPTS=""
156 if [ "${verbose}" = 1 ]; then
157 OPTS="-v ${OPTS}"
159 ##WORK HERE!
160 if dracut ${OPTS} "${initramfs}.new" "${version}"; then
161 mv -f "${initramfs}.new" "${initramfs}"
162 set_sha1
163 else
164 mkinitramfs_return="$?"
165 remove_initramfs
166 rm -f "${initramfs}.new"
167 if [ "$mkinitramfs_return" = "2" ]; then
168 # minversion wasn't met, exit 0
169 exit 0
171 echo "update-initramfs: failed for ${initramfs}"
172 exit $mkinitramfs_return
176 # lilo call
177 run_lilo()
179 # show lilo errors on failure
180 if ! lilo -t > /dev/null 2>&1 ; then
181 echo "ERROR lilo fails for new ${initramfs}:"
182 echo
183 lilo -t
185 lilo
188 # check if lilo is on mbr
189 mbr_check()
191 # try to discover grub|grub2 and be happy
192 [ -r /boot/grub/grub.cfg ] \
193 && groot=$(awk '/^set root=/{print substr($2, 7, 3); exit}' \
194 /boot/grub/grub.cfg)
195 [ -r /boot/grub/menu.lst ] \
196 && groot=$(awk '/^root/{print substr($2, 2, 3); exit}' \
197 /boot/grub/menu.lst)
198 [ -e /boot/grub/device.map ] && [ -n "${groot}" ] \
199 && dev=$(awk "/${groot}/{ print \$NF}" /boot/grub/device.map)
200 [ -n "${dev}" ] && [ -r ${dev} ] \
201 && dd if="${dev}" bs=512 skip=0 count=1 2> /dev/null \
202 | grep -q GRUB && return 0
204 # check out lilo.conf for validity
205 boot=$(awk -F = '/^boot=/{ print $2}' /etc/lilo.conf)
206 [ -z "${boot}" ] && return 0
207 case ${boot} in
208 /dev/md/*)
209 if [ -r /proc/mdstat ]; then
210 MD=${boot#/dev/md/}
211 boot="/dev/$(awk "/^md${MD}/{print substr(\$5, 1, 3)}" \
212 /proc/mdstat)"
215 /dev/md*)
216 if [ -r /proc/mdstat ]; then
217 MD=${boot#/dev/}
218 boot="/dev/$(awk "/^${MD}/{print substr(\$5, 1, 3)}" \
219 /proc/mdstat)"
222 esac
223 [ ! -r "${boot}" ] && return 0
224 dd if="${boot}" bs=512 skip=0 count=1 2> /dev/null | grep -q LILO \
225 && run_lilo && return 0
227 # no idea which bootloader is used
228 echo
229 echo "WARNING: grub and lilo installed."
230 echo "If you use grub as bootloader everything is fine."
231 echo "If you use lilo as bootloader you must run lilo!"
232 echo
235 # Invoke bootloader
236 run_bootloader()
238 # if both lilo and grub around, figure out if lilo needs to be run
239 if ( command -v update-grub >/dev/null 2>&1 \
240 || [ -e /boot/grub/menu.lst ] || [ -e /boot/grub/grub.cfg ] ) \
241 && ( [ -e /etc/lilo.conf ] && command -v lilo >/dev/null 2>&1 ); then
242 [ -r "${KPKGCONF}" ] && \
243 do_b=$(awk '/^do_bootloader/{print $3}' "${KPKGCONF}")
244 if [ "${do_b}" = "yes" ] || [ "${do_b}" = "Yes" ] \
245 || [ "${do_b}" = "YES" ]; then
246 run_lilo
247 return 0
248 elif [ "${do_b}" = "no" ] || [ "${do_b}" = "No" ] \
249 || [ "${do_b}" = "NO" ]; then
250 return 0
253 # do_bootloader unconfigured
254 mbr_check
255 return 0
257 if [ -r /etc/lilo.conf ] && command -v lilo >/dev/null 2>&1; then
258 run_lilo
259 return 0
261 if command -v elilo >/dev/null 2>&1; then
262 elilo
263 return 0
265 if [ -r /etc/zipl.conf ]; then
266 zipl
268 if flash-kernel --supported >/dev/null 2>&1; then
269 flash-kernel ${version}
273 compare_sha1()
275 sha1sum "${initramfs}" | diff "${STATEDIR}/${version}" - >/dev/null 2>&1
276 return $?
279 # Note that this must overwrite so that updates work.
280 set_sha1()
282 sha1sum "${initramfs}" > "${STATEDIR}/${version}"
285 delete_sha1()
287 rm -f "${STATEDIR}/${version}"
290 # ro /boot is not modified
291 ro_boot_check()
293 # check irrelevant inside of a chroot
294 if [ ! -r /proc/mounts ] || chrooted; then
295 return 0
298 boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \
299 && $2 == "/boot") print "ro"}' /proc/mounts)
300 if [ -n "${boot_opts}" ]; then
301 echo "WARNING: /boot is ro mounted."
302 echo "update-initramfs: Not updating ${initramfs}"
303 exit 0
307 get_sorted_versions()
309 version_list=""
311 for gsv_x in "${STATEDIR}"/*; do
312 gsv_x="$(basename "${gsv_x}")"
313 if [ "${gsv_x}" = '*' ]; then
314 return 0
316 worklist=""
317 for gsv_i in $version_list; do
318 if dpkg --compare-versions "${gsv_x}" '>' "${gsv_i}"; then
319 worklist="${worklist} ${gsv_x} ${gsv_i}"
320 gsv_x=""
321 else
322 worklist="${worklist} ${gsv_i}"
324 done
325 if [ "${gsv_x}" != "" ]; then
326 worklist="${worklist} ${gsv_x}"
328 version_list="${worklist}"
329 done
331 verbose "Available versions: ${version_list}"
334 set_current_version()
336 if [ -f /boot/dracut.img-`uname -r` ]; then
337 version=`uname -r`
341 set_linked_version()
343 if [ -e /initrd.img ] && [ -L /initrd.img ]; then
344 linktarget="$(basename "$(readlink /initrd.img)")"
347 if [ -e /boot/initrd.img ] && [ -L /boot/initrd.img ]; then
348 linktarget="$(basename "$(readlink /boot/initrd.img)")"
351 if [ -z "${linktarget}" ]; then
352 return
355 version="${linktarget##*img-}"
358 set_highest_version()
360 get_sorted_versions
361 set -- ${version_list}
362 version=${1}
365 create()
367 if [ -z "${version}" ]; then
368 usage "Create mode requires a version argument"
371 set_initramfs
373 if [ "${takeover}" = 0 ]; then
374 if version_exists "${version}"; then
375 panic "Cannot create version ${version}: already exists"
378 if [ -e "${initramfs}" ]; then
379 panic "${initramfs} already exists, cannot create."
383 generate_initramfs
386 update()
388 if [ "${update_initramfs}" = "no" ]; then
389 echo "update-initramfs: Not updating initramfs."
390 exit 0
393 if [ -z "${version}" ]; then
394 set_highest_version
397 if [ -z "${version}" ]; then
398 set_linked_version
401 if [ -z "${version}" ]; then
402 set_current_version
405 if [ -z "${version}" ]; then
406 verbose "Nothing to do, exiting."
407 exit 0
410 set_initramfs
412 ro_boot_check
414 altered_check
416 backup_initramfs
418 generate_initramfs
420 run_bootloader
422 backup_booted_initramfs
425 delete()
427 if [ -z "${version}" ]; then
428 usage "Delete mode requires a version argument"
431 set_initramfs
433 if [ ! -e "${initramfs}" ]; then
434 panic "Cannot delete ${initramfs}, doesn't exist."
437 if ! version_exists "${version}"; then
438 panic "Cannot delete version ${version}: Not created by this utility."
441 altered_check
443 echo "update-initramfs: Deleting ${initramfs}"
445 delete_sha1
447 rm -f "${initramfs}"
450 # Check for update mode on existing and modified initramfs
451 altered_check()
453 # No check on takeover
454 [ "${takeover}" = 1 ] && return 0
455 if [ ! -e "${initramfs}" ]; then
456 mild_panic "${initramfs} does not exist. Cannot update."
458 if ! compare_sha1; then
459 echo "update-initramfs: ${initramfs} has been altered." >&2
460 mild_panic "update-initramfs: Cannot update. Override with -t option."
464 # Defaults
465 verbose=0
466 yes=0
467 # We default to takeover=1 in Ubuntu, but not Debian
468 takeover=0
472 while getopts "k:cudyvtb:h?" flag; do
473 case "${flag}" in
475 version="${OPTARG}"
478 mode="c"
481 mode="d"
484 mode="u"
487 verbose="1"
490 yes="1"
493 takeover="1"
496 BOOTDIR="${OPTARG}"
497 if [ ! -d "${BOOTDIR}" ]; then
498 echo "Error: ${BOOTDIR} is not a directory."
499 exit 1
502 h|?)
503 usage
505 esac
506 done
508 shift $((${OPTIND} - 1))
510 if [ $# -ne 0 ]; then
511 echo "Invalid argument for option -k."
512 usage
515 # Validate arguments
516 if [ -z "${mode}" ]; then
517 usage "You must specify at least one of -c, -u, or -d."
520 if [ "${version}" = "all" ] \
521 || ( [ "${update_initramfs}" = "all" ] && [ -z "${version}" ] ); then
522 : FIXME check for --yes, and if not ask are you sure
523 get_sorted_versions
524 if [ -z "${version_list}" ]; then
525 verbose "Nothing to do, exiting."
526 exit 0
529 OPTS="-b ${BOOTDIR}"
530 if [ "${verbose}" = "1" ]; then
531 OPTS="${OPTS} -v"
533 if [ "${takeover}" = "1" ]; then
534 OPTS="${OPTS} -t"
536 if [ "${yes}" = "1" ]; then
537 OPTS="${OPTS} -y"
539 for u_version in ${version_list}; do
540 # Don't stop if one version doesn't work.
541 set +e
542 verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
543 "${0}" -${mode} -k "${u_version}" ${OPTS}
544 set -e
545 done
546 exit 0
550 case "${mode}" in
552 create
555 delete
558 update
560 esac