NEWS: update
[dracut.git] / dracut-update-initramfs
blob36a98a23f4f627839213d29d28e2eaef0213defb
1 #!/bin/sh
3 STATEDIR=/var/lib/dracut
4 BOOTDIR=/boot
5 CONF=/etc/dracut.conf
6 KPKGCONF=/etc/kernel-img.conf
7 USETRIGGERS=true
8 mode=""
9 version=""
11 set -e
13 if $USETRIGGERS \
14 && [ x"$DPKG_MAINTSCRIPT_PACKAGE" != x ] \
15 && [ $# = 1 ] \
16 && [ x"$1" = x-u ] \
17 && dpkg-trigger --check-supported 2>/dev/null
18 then
19 if dpkg-trigger --no-await update-initramfs; then
20 echo "dracut-update-initramfs: deferring update (trigger activated)"
21 exit 0
25 usage()
27 if [ -n "${1}" ]; then
28 printf "${@}\n\n" >&2
30 cat >&2 << EOF
31 Usage: ${0} [OPTION]...
33 Options:
34 -k [version] Specify kernel version or 'all'
35 -c Create a new initramfs
36 -u Update an existing initramfs
37 -d Remove an existing initramfs
38 -t Take over a custom initramfs with this one
39 -b Set alternate boot directory
40 -v Be verbose
41 -h This message
43 EOF
44 exit 1
47 # chroot check
48 chrooted()
50 # borrowed from udev's postinst
51 if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then
52 # the devicenumber/inode pair of / is the same as that of
53 # /sbin/init's root, so we're *not* in a chroot and hence
54 # return false.
55 return 1
57 return 0
60 mild_panic()
62 if [ -n "${1}" ]; then
63 printf "${@}\n" >&2
65 exit 0
68 panic()
70 if [ -n "${1}" ]; then
71 printf "${@}\n" >&2
73 exit 1
76 verbose()
78 if [ "${verbose}" = 1 ]; then
79 printf "${@}\n"
83 version_exists()
85 [ -e "${STATEDIR}/${1}" ] && [ -e "${initramfs}" ]
86 return $?
89 set_initramfs()
91 initramfs="${BOOTDIR}/dracut.img-${version}"
95 # backup initramfs while running
96 backup_initramfs()
98 [ ! -r "${initramfs}" ] && return 0
99 initramfs_bak="${initramfs}.dpkg-bak"
100 [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"
101 ln -f "${initramfs}" "${initramfs_bak}" \
102 || cp -a "${initramfs}" "${initramfs_bak}"
103 verbose "Keeping ${initramfs_bak}"
106 # keep booted initramfs
107 backup_booted_initramfs()
109 initramfs_bak="${initramfs}.dpkg-bak"
111 # first time run thus no backup
112 [ ! -r "${initramfs_bak}" ] && return 0
114 # chroot with no /proc
115 [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0
117 # no kept backup wanted
118 [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0
120 # no backup yet
121 if [ ! -r "${initramfs}.bak" ]; then
122 mv -f ${initramfs_bak} "${initramfs}.bak"
123 verbose "Backup ${initramfs}.bak"
124 return 0
127 # keep booted initramfs
128 uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)
129 if [ -n "$uptime_days" ]; then
130 boot_initramfs=$(find "${initramfs}.bak" -mtime +${uptime_days})
132 if [ -n "${boot_initramfs}" ]; then
133 mv -f "${initramfs_bak}" "${initramfs}.bak"
134 verbose "Backup ${initramfs}.bak"
135 return 0
137 verbose "Removing current backup ${initramfs_bak}"
138 rm -f ${initramfs_bak}
141 # nuke generated copy
142 remove_initramfs()
144 [ -z "${initramfs_bak}" ] && return 0
145 rm -f "${initramfs_bak}"
146 verbose "Removing ${initramfs_bak}"
150 generate_initramfs()
152 echo "dracut-update-initramfs: Generating ${initramfs}"
153 OPTS=""
154 if [ "${verbose}" = 1 ]; then
155 OPTS="-v ${OPTS}"
157 ##WORK HERE!
158 if dracut ${OPTS} "${initramfs}.new" "${version}"; then
159 mv -f "${initramfs}.new" "${initramfs}"
160 set_sha1
161 else
162 mkinitramfs_return="$?"
163 remove_initramfs
164 rm -f "${initramfs}.new"
165 if [ "$mkinitramfs_return" = "2" ]; then
166 # minversion wasn't met, exit 0
167 exit 0
169 echo "update-initramfs: failed for ${initramfs}"
170 exit $mkinitramfs_return
174 # lilo call
175 run_lilo()
177 # show lilo errors on failure
178 if ! lilo -t > /dev/null 2>&1 ; then
179 echo "ERROR lilo fails for new ${initramfs}:"
180 echo
181 lilo -t
183 lilo
186 # check if lilo is on mbr
187 mbr_check()
189 # try to discover grub|grub2 and be happy
190 [ -r /boot/grub/grub.cfg ] \
191 && groot=$(awk '/^set root=/{print substr($2, 7, 3); exit}' \
192 /boot/grub/grub.cfg)
193 [ -r /boot/grub/menu.lst ] \
194 && groot=$(awk '/^root/{print substr($2, 2, 3); exit}' \
195 /boot/grub/menu.lst)
196 [ -e /boot/grub/device.map ] && [ -n "${groot}" ] \
197 && dev=$(awk "/${groot}/{ print \$NF}" /boot/grub/device.map)
198 [ -n "${dev}" ] && [ -r ${dev} ] \
199 && dd if="${dev}" bs=512 skip=0 count=1 2> /dev/null \
200 | grep -q GRUB && return 0
202 # check out lilo.conf for validity
203 boot=$(awk -F = '/^boot=/{ print $2}' /etc/lilo.conf)
204 [ -z "${boot}" ] && return 0
205 case ${boot} in
206 /dev/md/*)
207 if [ -r /proc/mdstat ]; then
208 MD=${boot#/dev/md/}
209 boot="/dev/$(awk "/^md${MD}/{print substr(\$5, 1, 3)}" \
210 /proc/mdstat)"
213 /dev/md*)
214 if [ -r /proc/mdstat ]; then
215 MD=${boot#/dev/}
216 boot="/dev/$(awk "/^${MD}/{print substr(\$5, 1, 3)}" \
217 /proc/mdstat)"
220 esac
221 [ ! -r "${boot}" ] && return 0
222 dd if="${boot}" bs=512 skip=0 count=1 2> /dev/null | grep -q LILO \
223 && run_lilo && return 0
225 # no idea which bootloader is used
226 echo
227 echo "WARNING: grub and lilo installed."
228 echo "If you use grub as bootloader everything is fine."
229 echo "If you use lilo as bootloader you must run lilo!"
230 echo
233 # Invoke bootloader
234 run_bootloader()
236 # if both lilo and grub around, figure out if lilo needs to be run
237 if ( command -v update-grub >/dev/null 2>&1 \
238 || [ -e /boot/grub/menu.lst ] || [ -e /boot/grub/grub.cfg ] ) \
239 && ( [ -e /etc/lilo.conf ] && command -v lilo >/dev/null 2>&1 ); then
240 [ -r "${KPKGCONF}" ] && \
241 do_b=$(awk '/^do_bootloader/{print $3}' "${KPKGCONF}")
242 if [ "${do_b}" = "yes" ] || [ "${do_b}" = "Yes" ] \
243 || [ "${do_b}" = "YES" ]; then
244 run_lilo
245 return 0
246 elif [ "${do_b}" = "no" ] || [ "${do_b}" = "No" ] \
247 || [ "${do_b}" = "NO" ]; then
248 return 0
251 # do_bootloader unconfigured
252 mbr_check
253 return 0
255 if [ -r /etc/lilo.conf ] && command -v lilo >/dev/null 2>&1; then
256 run_lilo
257 return 0
259 if command -v elilo >/dev/null 2>&1; then
260 elilo
261 return 0
263 if [ -r /etc/zipl.conf ]; then
264 zipl
266 if flash-kernel --supported >/dev/null 2>&1; then
267 flash-kernel ${version}
271 compare_sha1()
273 sha1sum "${initramfs}" | diff "${STATEDIR}/${version}" - >/dev/null 2>&1
274 return $?
277 # Note that this must overwrite so that updates work.
278 set_sha1()
280 sha1sum "${initramfs}" > "${STATEDIR}/${version}"
283 delete_sha1()
285 rm -f "${STATEDIR}/${version}"
288 # ro /boot is not modified
289 ro_boot_check()
291 # check irrelevant inside of a chroot
292 if [ ! -r /proc/mounts ] || chrooted; then
293 return 0
296 boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \
297 && $2 == "/boot") print "ro"}' /proc/mounts)
298 if [ -n "${boot_opts}" ]; then
299 echo "WARNING: /boot is ro mounted."
300 echo "update-initramfs: Not updating ${initramfs}"
301 exit 0
305 get_sorted_versions()
307 version_list=""
309 for gsv_x in "${STATEDIR}"/*; do
310 gsv_x="$(basename "${gsv_x}")"
311 if [ "${gsv_x}" = '*' ]; then
312 return 0
314 worklist=""
315 for gsv_i in $version_list; do
316 if dpkg --compare-versions "${gsv_x}" '>' "${gsv_i}"; then
317 worklist="${worklist} ${gsv_x} ${gsv_i}"
318 gsv_x=""
319 else
320 worklist="${worklist} ${gsv_i}"
322 done
323 if [ "${gsv_x}" != "" ]; then
324 worklist="${worklist} ${gsv_x}"
326 version_list="${worklist}"
327 done
329 verbose "Available versions: ${version_list}"
332 set_current_version()
334 if [ -f /boot/dracut.img-`uname -r` ]; then
335 version=`uname -r`
339 set_linked_version()
341 if [ -e /initrd.img ] && [ -L /initrd.img ]; then
342 linktarget="$(basename "$(readlink /initrd.img)")"
345 if [ -e /boot/initrd.img ] && [ -L /boot/initrd.img ]; then
346 linktarget="$(basename "$(readlink /boot/initrd.img)")"
349 if [ -z "${linktarget}" ]; then
350 return
353 version="${linktarget##*img-}"
356 set_highest_version()
358 get_sorted_versions
359 set -- ${version_list}
360 version=${1}
363 create()
365 if [ -z "${version}" ]; then
366 usage "Create mode requires a version argument"
369 set_initramfs
371 if [ "${takeover}" = 0 ]; then
372 if version_exists "${version}"; then
373 panic "Cannot create version ${version}: already exists"
376 if [ -e "${initramfs}" ]; then
377 panic "${initramfs} already exists, cannot create."
381 generate_initramfs
384 update()
386 if [ "${update_initramfs}" = "no" ]; then
387 echo "update-initramfs: Not updating initramfs."
388 exit 0
391 if [ -z "${version}" ]; then
392 set_highest_version
395 if [ -z "${version}" ]; then
396 set_linked_version
399 if [ -z "${version}" ]; then
400 set_current_version
403 if [ -z "${version}" ]; then
404 verbose "Nothing to do, exiting."
405 exit 0
408 set_initramfs
410 ro_boot_check
412 altered_check
414 backup_initramfs
416 generate_initramfs
418 run_bootloader
420 backup_booted_initramfs
423 delete()
425 if [ -z "${version}" ]; then
426 usage "Delete mode requires a version argument"
429 set_initramfs
431 if [ ! -e "${initramfs}" ]; then
432 panic "Cannot delete ${initramfs}, doesn't exist."
435 if ! version_exists "${version}"; then
436 panic "Cannot delete version ${version}: Not created by this utility."
439 altered_check
441 echo "update-initramfs: Deleting ${initramfs}"
443 delete_sha1
445 rm -f "${initramfs}"
448 # Check for update mode on existing and modified initramfs
449 altered_check()
451 # No check on takeover
452 [ "${takeover}" = 1 ] && return 0
453 if [ ! -e "${initramfs}" ]; then
454 mild_panic "${initramfs} does not exist. Cannot update."
456 if ! compare_sha1; then
457 echo "update-initramfs: ${initramfs} has been altered." >&2
458 mild_panic "update-initramfs: Cannot update. Override with -t option."
462 # Defaults
463 verbose=0
464 yes=0
465 # We default to takeover=1 in Ubuntu, but not Debian
466 takeover=0
470 while getopts "k:cudyvtb:h?" flag; do
471 case "${flag}" in
473 version="${OPTARG}"
476 mode="c"
479 mode="d"
482 mode="u"
485 verbose="1"
488 yes="1"
491 takeover="1"
494 BOOTDIR="${OPTARG}"
495 if [ ! -d "${BOOTDIR}" ]; then
496 echo "Error: ${BOOTDIR} is not a directory."
497 exit 1
500 h|?)
501 usage
503 esac
504 done
506 shift $((${OPTIND} - 1))
508 if [ $# -ne 0 ]; then
509 echo "Invalid argument for option -k."
510 usage
513 # Validate arguments
514 if [ -z "${mode}" ]; then
515 usage "You must specify at least one of -c, -u, or -d."
518 if [ "${version}" = "all" ] \
519 || ( [ "${update_initramfs}" = "all" ] && [ -z "${version}" ] ); then
520 : FIXME check for --yes, and if not ask are you sure
521 get_sorted_versions
522 if [ -z "${version_list}" ]; then
523 verbose "Nothing to do, exiting."
524 exit 0
527 OPTS="-b ${BOOTDIR}"
528 if [ "${verbose}" = "1" ]; then
529 OPTS="${OPTS} -v"
531 if [ "${takeover}" = "1" ]; then
532 OPTS="${OPTS} -t"
534 if [ "${yes}" = "1" ]; then
535 OPTS="${OPTS} -y"
537 for u_version in ${version_list}; do
538 # Don't stop if one version doesn't work.
539 set +e
540 verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
541 "${0}" -${mode} -k "${u_version}" ${OPTS}
542 set -e
543 done
544 exit 0
548 case "${mode}" in
550 create
553 delete
556 update
558 esac