home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / sbin / update-initramfs < prev    next >
Encoding:
Text File  |  2012-09-21  |  8.7 KB  |  489 lines

  1. #!/bin/sh
  2.  
  3. STATEDIR=/var/lib/initramfs-tools
  4. BOOTDIR=/boot
  5. CONF=/etc/initramfs-tools/update-initramfs.conf
  6. USETRIGGERS=true
  7. mode=""
  8. version=""
  9. update_initramfs=yes
  10. backup_initramfs=no
  11.  
  12. set -e
  13.  
  14. [ -r ${CONF} ] && . ${CONF}
  15.  
  16. case "$DPKG_MAINTSCRIPT_PACKAGE" in
  17. linux-image-*)
  18.     if [ -z "$INITRAMFS_TOOLS_KERNEL_HOOK" ]; then
  19.         # kernel maintainer script called us directly; ignore
  20.         # it and let the hook script handle it instead
  21.         echo "update-initramfs: deferring update (hook will be called later)"
  22.         exit 0
  23.     fi
  24.     ;;
  25. ?*)
  26.     if       $USETRIGGERS                        \
  27.         && [ $# = 1 ]                        \
  28.         && [ x"$1" = x-u ]                    \
  29.         && dpkg-trigger --check-supported 2>/dev/null
  30.     then
  31.         if dpkg-trigger --no-await update-initramfs; then
  32.             echo "update-initramfs: deferring update (trigger activated)"
  33.             exit 0
  34.         fi
  35.     fi
  36.     ;;
  37. esac
  38.  
  39. usage()
  40. {
  41.     if [ -n "${1:-}" ]; then
  42.         printf "${*}\n\n" >&2
  43.     fi
  44.     cat >&2 << EOF
  45. Usage: ${0} [OPTION]...
  46.  
  47. Options:
  48.  -k [version]    Specify kernel version or 'all'
  49.  -c        Create a new initramfs
  50.  -u        Update an existing initramfs
  51.  -d        Remove an existing initramfs
  52.  -t        Take over a custom initramfs with this one
  53.  -b        Set alternate boot directory
  54.  -v        Be verbose
  55.  -h        This message
  56.  
  57. EOF
  58.     exit 1
  59. }
  60.  
  61. # chroot check
  62. chrooted()
  63. {
  64.     # borrowed from udev's postinst
  65.     if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then
  66.         # the devicenumber/inode pair of / is the same as that of
  67.         # /sbin/init's root, so we're *not* in a chroot and hence
  68.         # return false.
  69.         return 1
  70.     fi
  71. return 0
  72. }
  73.  
  74. mild_panic()
  75. {
  76.     if [ -n "${1:-}" ]; then
  77.         printf "${*}\n" >&2
  78.     fi
  79.     exit 0
  80. }
  81.  
  82. panic()
  83. {
  84.     if [ -n "${1:-}" ]; then
  85.         printf "${*}\n" >&2
  86.     fi
  87.     exit 1
  88. }
  89.  
  90. verbose()
  91. {
  92.     if [ "${verbose}" = 1 ]; then
  93.         printf "${*}\n"
  94.     fi
  95. }
  96.  
  97. version_exists()
  98. {
  99.     [ -e "${STATEDIR}/${1}" ] && [ -e "${initramfs}" ]
  100.     return $?
  101. }
  102.  
  103. set_initramfs()
  104. {
  105.     initramfs="${BOOTDIR}/initrd.img-${version}"
  106. }
  107.  
  108.  
  109. # backup initramfs while running
  110. backup_initramfs()
  111. {
  112.     [ ! -r "${initramfs}" ] && return 0
  113.     initramfs_bak="${initramfs}.dpkg-bak"
  114.     [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"
  115.     ln -f "${initramfs}" "${initramfs_bak}" \
  116.         || cp -a "${initramfs}" "${initramfs_bak}"
  117.     verbose "Keeping ${initramfs_bak}"
  118. }
  119.  
  120. # keep booted initramfs
  121. backup_booted_initramfs()
  122. {
  123.     initramfs_bak="${initramfs}.dpkg-bak"
  124.  
  125.     # first time run thus no backup
  126.     [ ! -r "${initramfs_bak}" ] && return 0
  127.  
  128.     # chroot with no /proc
  129.     [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0
  130.  
  131.     # no kept backup wanted
  132.     [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0
  133.  
  134.     # no backup yet
  135.     if [ ! -r "${initramfs}.bak" ]; then
  136.         mv -f ${initramfs_bak} "${initramfs}.bak"
  137.         verbose "Backup ${initramfs}.bak"
  138.         return 0
  139.     fi
  140.  
  141.     # keep booted initramfs
  142.     boot_initramfs=
  143.     uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)
  144.     if [ -n "$uptime_days" ]; then
  145.         boot_initramfs=$(find "${initramfs}.bak" -mtime +${uptime_days})
  146.     fi
  147.     if [ -n "${boot_initramfs}" ]; then
  148.         mv -f "${initramfs_bak}" "${initramfs}.bak"
  149.         verbose "Backup ${initramfs}.bak"
  150.         return 0
  151.     fi
  152.     verbose "Removing current backup ${initramfs_bak}"
  153.     rm -f ${initramfs_bak}
  154. }
  155.  
  156. # nuke generated copy
  157. remove_initramfs_bak()
  158. {
  159.     [ -z "${initramfs_bak:-}" ] && return 0
  160.     rm -f "${initramfs_bak}"
  161.     verbose "Removing ${initramfs_bak}"
  162. }
  163.  
  164.  
  165. generate_initramfs()
  166. {
  167.     echo "update-initramfs: Generating ${initramfs}"
  168.     OPTS="-o"
  169.     if [ "${verbose}" = 1 ]; then
  170.         OPTS="-v ${OPTS}"
  171.     fi
  172.     if mkinitramfs ${OPTS} "${initramfs}.new" "${version}"; then
  173.         mv -f "${initramfs}.new" "${initramfs}"
  174.         set_sha1
  175.     else
  176.         mkinitramfs_return="$?"
  177.         remove_initramfs_bak
  178.         rm -f "${initramfs}.new"
  179.         echo "update-initramfs: failed for ${initramfs} with $mkinitramfs_return." >&2
  180.         exit $mkinitramfs_return
  181.     fi
  182. }
  183.  
  184. # Invoke bootloader
  185. run_bootloader()
  186. {
  187.     # invoke policy conformant bootloader hooks
  188.     if [ -d /etc/initramfs/post-update.d/ ]; then
  189.         run-parts --arg=${version} --arg=${initramfs} \
  190.             /etc/initramfs/post-update.d/
  191.         return 0
  192.     fi
  193. }
  194.  
  195. compare_sha1()
  196. {
  197.     sha1sum "${initramfs}" | diff "${STATEDIR}/${version}" - >/dev/null 2>&1
  198.     return $?
  199. }
  200.  
  201. # Note that this must overwrite so that updates work.
  202. set_sha1()
  203. {
  204.     sha1sum "${initramfs}" > "${STATEDIR}/${version}"
  205. }
  206.  
  207. delete_sha1()
  208. {
  209.     rm -f "${STATEDIR}/${version}"
  210. }
  211.  
  212. # ro /boot is not modified
  213. ro_boot_check()
  214. {
  215.     # check irrelevant inside of a chroot
  216.     if [ ! -r /proc/mounts ] || chrooted; then
  217.         return 0
  218.     fi
  219.  
  220.     boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \
  221.         && $2 == "/boot") print "ro"}' /proc/mounts)
  222.     if [ -n "${boot_opts}" ]; then
  223.         echo "WARNING: /boot is ro mounted."
  224.         echo "update-initramfs: Not updating ${initramfs}"
  225.         exit 0
  226.     fi
  227. }
  228.  
  229. get_sorted_versions()
  230. {
  231.     version_list=""
  232.  
  233.     for gsv_x in "${STATEDIR}"/*; do
  234.         gsv_x="$(basename "${gsv_x}")"
  235.         if [ "${gsv_x}" = '*' ]; then
  236.             return 0
  237.         fi
  238.         worklist=""
  239.         for gsv_i in $version_list; do
  240.             if dpkg --compare-versions "${gsv_x}" '>' "${gsv_i}" 2>/dev/null; then
  241.                 worklist="${worklist} ${gsv_x} ${gsv_i}"
  242.                 gsv_x=""
  243.             else
  244.                 worklist="${worklist} ${gsv_i}"
  245.             fi
  246.         done
  247.         if [ "${gsv_x}" != "" ]; then
  248.             worklist="${worklist} ${gsv_x}"
  249.         fi
  250.         version_list="${worklist}"
  251.     done
  252.  
  253.     verbose "Available versions: ${version_list}"
  254. }
  255.  
  256. set_current_version()
  257. {
  258.     if [ -f /boot/initrd.img-`uname -r` ]; then
  259.         version=`uname -r`
  260.     fi
  261. }
  262.  
  263. set_linked_version()
  264. {
  265.     linktarget=
  266.     if [ -e /initrd.img ] && [ -L /initrd.img ]; then
  267.         linktarget="$(basename "$(readlink /initrd.img)")"
  268.     fi
  269.  
  270.     if [ -e /boot/initrd.img ] && [ -L /boot/initrd.img ]; then
  271.         linktarget="$(basename "$(readlink /boot/initrd.img)")"
  272.     fi
  273.  
  274.     if [ -z "${linktarget}" ]; then
  275.         return
  276.     fi
  277.  
  278.     version="${linktarget##initrd.img-}"
  279. }
  280.  
  281. set_highest_version()
  282. {
  283.     get_sorted_versions
  284.     if [ -z "${version_list}" ]; then
  285.         version=
  286.         return
  287.     fi
  288.     set -- ${version_list}
  289.     version=${1}
  290. }
  291.  
  292. create()
  293. {
  294.     if [ -z "${version}" ]; then
  295.         usage "Create mode requires a version argument"
  296.     fi
  297.  
  298.     set_initramfs
  299.  
  300.     if [ "${takeover}" = 0 ]; then
  301.         if version_exists "${version}"; then
  302.             panic "Cannot create version ${version}: already exists"
  303.         fi
  304.  
  305.         if [ -e "${initramfs}" ]; then
  306.             panic "${initramfs} already exists, cannot create."
  307.         fi
  308.     fi
  309.  
  310.     generate_initramfs
  311.  
  312.     run_bootloader
  313. }
  314.  
  315. update()
  316. {
  317.     if [ "${update_initramfs}" = "no" ]; then
  318.         echo "update-initramfs: Not updating initramfs."
  319.         exit 0
  320.     fi
  321.  
  322.     if [ -z "${version}" ]; then
  323.         set_highest_version
  324.     fi
  325.  
  326.     if [ -z "${version}" ]; then
  327.         set_linked_version
  328.     fi
  329.  
  330.     if [ -z "${version}" ]; then
  331.         set_current_version
  332.     fi
  333.  
  334.     if [ -z "${version}" ]; then
  335.         verbose "Nothing to do, exiting."
  336.         exit 0
  337.     fi
  338.  
  339.     set_initramfs
  340.  
  341.     ro_boot_check
  342.  
  343.     altered_check
  344.  
  345.     backup_initramfs
  346.  
  347.     generate_initramfs
  348.  
  349.     run_bootloader
  350.  
  351.     backup_booted_initramfs
  352. }
  353.  
  354. delete()
  355. {
  356.     if [ -z "${version}" ]; then
  357.         usage "Delete mode requires a version argument"
  358.     fi
  359.  
  360.     set_initramfs
  361.  
  362.     if [ "${takeover}" = 0 ]; then
  363.         if [ ! -e "${initramfs}" ]; then
  364.             panic "Cannot delete ${initramfs}, doesn't exist."
  365.         fi
  366.  
  367.         if ! version_exists "${version}"; then
  368.             panic "Cannot delete version ${version}: Not created by this utility."
  369.         fi
  370.     fi
  371.  
  372.     altered_check
  373.  
  374.     echo "update-initramfs: Deleting ${initramfs}"
  375.  
  376.     delete_sha1
  377.  
  378.     rm -f "${initramfs}" "${initramfs}.bak"
  379. }
  380.  
  381. # Check for update mode on existing and modified initramfs
  382. altered_check()
  383. {
  384.     # No check on takeover
  385.     [ "${takeover}" = 1 ] && return 0
  386.     if [ ! -e "${initramfs}" ]; then
  387.         mild_panic "${initramfs} does not exist. Cannot update."
  388.     fi
  389.     if ! compare_sha1; then
  390.         echo "update-initramfs: ${initramfs} has been altered." >&2
  391.         mild_panic "update-initramfs: Cannot update. Override with -t option."
  392.     fi
  393. }
  394.  
  395. # Defaults
  396. verbose=0
  397. yes=0
  398. # We default to takeover=1 in Ubuntu, but not Debian
  399. takeover=0
  400.  
  401. ##
  402.  
  403. while getopts "k:cudyvtb:h?" flag; do
  404.     case "${flag}" in
  405.     k)
  406.         version="${OPTARG}"
  407.         ;;
  408.     c)
  409.         mode="c"
  410.         ;;
  411.     d)
  412.         mode="d"
  413.         ;;
  414.     u)
  415.         mode="u"
  416.         ;;
  417.     v)
  418.         verbose="1"
  419.         ;;
  420.     y)
  421.         yes="1"
  422.         ;;
  423.     t)
  424.         takeover="1"
  425.         ;;
  426.     b)
  427.         BOOTDIR="${OPTARG}"
  428.         if [ ! -d "${BOOTDIR}" ]; then
  429.             echo "Error: ${BOOTDIR} is not a directory." >&2
  430.             exit 1
  431.         fi
  432.         ;;
  433.     h|?)
  434.         usage
  435.         ;;
  436.     esac
  437. done
  438.  
  439. shift $((${OPTIND} - 1))
  440.  
  441. if [ $# -ne 0 ]; then
  442.     echo "Invalid argument for option -k." >&2
  443.     usage
  444. fi
  445.  
  446. # Validate arguments
  447. if [ -z "${mode}" ]; then
  448.     usage "You must specify at least one of -c, -u, or -d."
  449. fi
  450.  
  451. if [ "${version}" = "all" ] \
  452.     || ( [ "${update_initramfs}" = "all" ] && [ -z "${version}" ] ); then
  453.     : FIXME check for --yes, and if not ask are you sure
  454.     get_sorted_versions
  455.     if [ -z "${version_list}" ]; then
  456.         verbose "Nothing to do, exiting."
  457.         exit 0
  458.     fi
  459.  
  460.     OPTS="-b ${BOOTDIR}"
  461.     if [ "${verbose}" = "1" ]; then
  462.         OPTS="${OPTS} -v"
  463.     fi
  464.     if [ "${takeover}" = "1" ]; then
  465.         OPTS="${OPTS} -t"
  466.     fi
  467.     if [ "${yes}" = "1" ]; then
  468.         OPTS="${OPTS} -y"
  469.     fi
  470.     for u_version in ${version_list}; do
  471.         verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
  472.         "${0}" -${mode} -k "${u_version}" ${OPTS}
  473.     done
  474.     exit 0
  475. fi
  476.  
  477.  
  478. case "${mode}" in
  479.     c)
  480.         create
  481.         ;;
  482.     d)
  483.         delete
  484.         ;;
  485.     u)
  486.         update
  487.         ;;
  488. esac
  489.