Guest User

Untitled

a guest
May 22nd, 2018
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 41.40 KB | None | 0 0
  1. #!/bin/bash
  2. # Moves an Ubuntu install (normal or a loopinstallation e.g. Wubi)
  3. # to a dedicated partition install.
  4. # Migration from a Wubi root.disk is supported as well.
  5. #
  6. # If you have grub legacy installed, it will remove it on the
  7. # target (only) and replace it with grub2.
  8. #
  9. # While every effort has been made to ensure the script works as
  10. # intended and is bug free, please note you use it AT YOUR OWN RISK.
  11. # Please BACKUP any important data prior to running.
  12. #
  13. # Credits:
  14. # Much of the script's fundamentals are based on the work of
  15. # other people e.g. the original wubi migration script and lupin:
  16. #    Copyright (C) 2007 Agostino Russo <agostino.russo@gmail.com>
  17. #
  18. # This program is free software; you can redistribute it and/or modify
  19. # it under the terms of the GNU General Public License as published by
  20. # the Free Software Foundation; either version 2, or (at your option) any
  21. # later version.
  22. #
  23. # This program is distributed in the hope that it will be useful,
  24. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26. # GNU General Public License for more details.
  27. #
  28. # You should have received a copy of the GNU General Public License
  29. # along with this program; if not, write to the Free Software
  30. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  31. #
  32. ### Variable declaration ###
  33. #
  34. # Options
  35. no_bootloader=false         # Bypass Grub2 bootloader install
  36. no_mkswap=false             # Skip mkswap on swap partition
  37. assume_yes=false            # Assume "Y" to all prompts
  38. root_disk=                  # path and name of root.disk file
  39. debug=false                 # Output debug information
  40. dev=                        # target device for migration
  41. swapdev=                    # swap device for migration
  42. rootdiskpath=               # path to root.disk file
  43.  
  44. # Literals
  45. version=2.1.1               # Script version
  46. target=/tmp/wubitarget      # target device mountpoint
  47. root_mount=/tmp/rootdisk    # root.disk mountpoint
  48.  
  49. # Bools
  50. formatted_dev=false         # Has the target been formatted?
  51. grub_legacy=false           # Is grub legacy installed?
  52. install_grub=false          # Must the grub2 bootloader be installed?
  53. wubi_install=true           # Is this a Wubi install migration?
  54. internet_connection=false   # Is there an internet connection present?
  55. suppress_chroot_output=true # Default - suppress output of chroot commands
  56. grub_common_exists=true     # Check for grub-common (not on 8.04)
  57. mint=false                  # mint4win
  58.  
  59. # Working variables
  60. fs=ext4                     # Default file system - else ext3 if detected on install being migrated
  61. rc=                         # Preserve return code
  62. root="/"                    # Default root of the install being migrated
  63. host_mountpoint=            # Host mountpoint for Wubi install
  64. root_device=                # Device that root (/) is mounted on
  65. loop_file=                  # Root.disk for running Wubi install
  66. loop_device=                # Loop device for mounted root.disk
  67. mtpt=                       # Mount point determination working variable
  68. awkscript=                  # Contains AWK script
  69. target_size=                # size of target partition
  70. install_size=               # size of current install
  71.  
  72. usage ()
  73. {
  74.     cat <<EOF
  75. Usage: sudo bash $0 [OPTION] target_partition [swap_partition]
  76.        e.g. sudo bash $0 /dev/sda5 /dev/sda6
  77.  
  78. Migrate an ubuntu install (wubi or normal) to partition
  79.   -h, --help              print this message and exit
  80.   -v, --version           print the version information and exit
  81.   --notes                 print the Assumptions and Notes, and exit
  82.   --no-bootloader         do not install the grub2 bootloader
  83.   --shared-swap           share swap partition with an existing install
  84.   -y, --assume-yes        assume yes to all prompts
  85.   --root-disk=<root.disk> Specify a root.disk file to migrate
  86. EOF
  87. }
  88. assumptions_notes ()
  89. {
  90.     cat <<EOF
  91. Assumptions:
  92.   1. The script will detect automatically whether the current install
  93.      to be migrated is a Wubi or normal install.
  94.   2. If you are running the script from a live CD/USB then the
  95.      --root-disk= option is required. The grub2 bootloader must be
  96.      installed when using this option.
  97.   3. The grub2 bootloader will be installed to /dev/sdX where /dev/sdXY
  98.      is the target partition, unless --no-bootloader is specified.
  99.      You will still be prompted whether to install the grub bootloader
  100.      unless option -y or --assume-yes is supplied.
  101.   4. If the install being migrated contains grub-legacy it will be
  102.      replaced with Grub2 (only on the migrated install). You are not
  103.      required to install the Grub2 bootloader, however, if you choose
  104.      not to then you will have to manually modify the menu.lst to boot
  105.      the migrated install.
  106.      NOTE: the grub2 installation takes control and requires user input
  107.      on releases 9.10 and greater. It will also prompt for the bootloader
  108.      install drive/partition.
  109.   5. The target partition file system will be formatted as ext4 (default)
  110.      or ext3 if detected on the install being migrated.
  111.   6. An install with separate /home, /boot, or /usr partitions or virtual
  112.      disks will be merged when it is migrated onto the single target
  113.      partition and fstab modified accordingly.
  114.  
  115. Notes:
  116.   If you install the grub bootloader, then the grub menu from your migrated
  117.   install will be presented at boot - not the windows menu (for Wubi installs.)
  118.   If you do not install the bootloader, then you will still be able to
  119.   boot the migrated install from the current install's Grub menu, unless your
  120.   current install uses grub legacy.
  121.   For Wubi users, make sure you install bootloader before uninstalling Wubi.
  122.  
  123.   To install the bootloader manually, boot your new installation and run:
  124.        sudo grub-install /dev/sdX
  125.   (where X is the drive you boot from e.g. /dev/sda)
  126.  
  127. Recommended:
  128.   Run "sudo update-grub" on the migrated install after booting the first time
  129. EOF
  130. }
  131.  
  132. ### Check the options and parameters
  133. for option in "$@"; do
  134.     case "$option" in
  135.     -h | --help)
  136.     usage
  137.     exit 0 ;;
  138.     -v | --version)
  139.     echo "$0: Version $version"
  140.     exit 0 ;;
  141.     --notes)
  142.     assumptions_notes
  143.     exit 0 ;;
  144.     --no-bootloader)
  145.     no_bootloader=true
  146.     ;;
  147.     --shared-swap)
  148.     no_mkswap=true
  149.     ;;
  150.     -y | --assume-yes)
  151.     assume_yes=true
  152.     ;;
  153.     --root-disk=*)
  154.     root_disk=`echo "$option" | sed 's/--root-disk=//'` ;;
  155. ### undocumented debug option
  156.     -d | --debug)
  157.     set -x
  158.     debug=true
  159.     ;;
  160.     -*)
  161.     echo "$0: Unrecognized option '$option'" 1>&2
  162.     usage
  163.     exit 1
  164.     ;;
  165.     *)
  166. ### Positional parameters - Order is important
  167. ### Identify the target partition to install to
  168. ### and the swap partition (if supplied)
  169. ### Any additional parameters are errors
  170.     if test "x$dev" != x; then
  171.       if  test "x$swapdev" != x; then
  172.           echo "$0: Too many parameters" 1>&2
  173.           usage
  174.           exit 1
  175.       else
  176.         swapdev="${option}"
  177.       fi
  178.     else
  179.       dev="${option}"
  180.     fi
  181.     ;;
  182.     esac
  183. done
  184.  
  185. ### Present Y/N questions and check response
  186. ### (a valid response is required)
  187. ### Parameter: the question requiring an answer
  188. ### Returns: 0 = Yes, 1 = No
  189. test_YN ()
  190. {
  191.     while true; do
  192.       echo "$0: $@"
  193.       read input
  194.       case "$input" in
  195.         "y" | "Y" )
  196.           return 0 ;;
  197.         "n" | "N" )
  198.           return 1 ;;
  199.         * )
  200.           echo "$0: Invalid response ('$input')"
  201.       esac
  202.     done
  203. }
  204.  
  205. ### Exit script - cleanup on way out
  206. ### Parameter 1:
  207. ###    0 = successful execution
  208. ###    1 = exception
  209. exit_script ()
  210. {
  211. # all mount checks with grep add a space to differentiate e.g. /dev/sda1 from /dev/sda11
  212. # Not really necessary for these custom mountpoints but do it anyway.
  213. # Depending on when the exception is encountered there may be nothing to cleanup
  214.  
  215. # If the migration is from a named root.disk, unmount if required,
  216. # and then delete mountpoint. Also check home.disk and usr.disk
  217.     if [ ! -z "$root_disk" ]; then
  218.       if [ $(mount | grep "$root_mount"/home'\ ' | wc -l) -ne 0 ]; then
  219.         umount "$root_mount"/home > /dev/null 2>&1
  220.         sleep 3
  221.         [ -d "$root_mount"/home ] && rmdir "$root_mount"/home > /dev/null 2>&1
  222.       fi
  223.       if [ $(mount | grep "$root_mount"/usr'\ ' | wc -l) -ne 0 ]; then
  224.         umount "$root_mount"/usr > /dev/null 2>&1
  225.         sleep 3
  226.         [ -d "$root_mount"/usr ] && rmdir "$root_mount"/usr > /dev/null 2>&1
  227.       fi
  228.       if [ $(mount | grep "$root_mount"'\ ' | wc -l) -ne 0 ]; then
  229.         umount "$root_mount" > /dev/null 2>&1
  230.         sleep 3
  231.       fi
  232.       [ -d "$root_mount" ] && rmdir "$root_mount" > /dev/null 2>&1
  233.     fi
  234.  
  235. # If a wubi install is being migrated, remove the fake /host
  236. # created to bypass grub errors. Do this before unmounting
  237.     if [ "$wubi_install" = "true" ] && [ -d "$target"/host ]; then
  238.       rmdir "$target"/host > /dev/null 2>&1
  239.     fi
  240.  
  241. # Now unmount migrated install if required, and delete the mountpoint
  242.     if [ $(mount | grep "$target"'\ ' | wc -l) -ne 0 ]; then
  243.       umount $target > /dev/null 2>&1
  244.       sleep 1
  245.     fi
  246.     if [ -d "$target" ]; then
  247.       rmdir "$target" > /dev/null 2>&1
  248.     fi
  249.  
  250. # Output success message if normal termination
  251.     if [ $1 -eq 0 ]; then
  252.       echo ""
  253.       echo "$0: Operation completed successfully."
  254.     fi
  255.     exit $1
  256. }
  257.  
  258. # Check that a virtual disk is not mounted
  259. check_disk_mount ()
  260. {
  261. # this code goes through each line in /proc/mounts
  262. # and compares the first column ($DEV) to "/dev/loop*"
  263. # If it finds an existing loop mount it retrieves the
  264. # associated filename and compares it to the root.disk
  265.     while read DEV MTPT FSTYPE OPTS REST; do
  266.         case "$DEV" in
  267.           /dev/loop/*|/dev/loop[0-9])
  268.             loop_file=`losetup "$DEV" | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
  269.             if  [ "$loop_file" = "$1" ]; then
  270.                 echo "$0: "$1" is mounted - please unmount and try again"
  271.                 exit_script 1
  272.             fi
  273.           ;;
  274.         esac
  275.     done < /proc/mounts
  276. }
  277.  
  278. # mount a virtual disk - exit if it fails
  279. mount_virtual_disk()
  280. {
  281.     if mount -o loop "$1" "$2" 2> /tmp/wubi-move-error; then
  282.         true #nothing yet
  283.     else
  284.         echo "$0: "$1" could not be mounted"
  285. # Check for 'file system ext4 unknown' message e.g. if you boot an
  286. # 8.04 disk and try to migrate a current ext4 root.disk
  287.         if [ $(cat /tmp/wubi-move-error | grep "unknown filesystem type 'ext4'" | wc -l) -eq 1 ]; then
  288.             echo "$0: The live environment you are using doesn't support"
  289.             echo "$0: the virtual disks ext4 file system. Try using an"
  290.             echo "$0: Ubuntu CD containing release 9.10 or later."
  291.         else
  292.             # some other issue - output message
  293.             echo "$0: Error is: $(cat /tmp/wubi-move-error)"        
  294.             echo "$0: Check that the path/name is correct and"
  295.             echo "$0: contains a working Wubi install."
  296.         fi
  297.         exit_script 1
  298.     fi
  299. }
  300.  
  301. check_fstab ()
  302. {
  303. # this code goes through each line in /etc/fstab
  304. # and makes sure the virtual disks are not mounted
  305. # and mountable. It assumes that /host/ubuntu/disks/xxx.disk
  306. # means that xxx.disk is in the same location as the current
  307. # root.disk that whose /etc/fstab contains xxx.disk
  308.     while read fDEV fMTPT fTYPE fOPTS fDMP fPASS; do
  309.         case "$fMTPT" in
  310.           /home|/usr)
  311.             disks_path=`echo $fDEV | sed -e "s/\(^\/host\/ubuntu\/disks\/\)\(.*\)/\1/"`
  312.             if [ "$disks_path" = "/host/ubuntu/disks/" ]; then          
  313.                 virtual_disk=`echo $fDEV | sed -e "s/\(^\/host\/ubuntu\/disks\/\)\(.*\)/\2/"`
  314.                 if [ ! -f "$rootdiskpath"$virtual_disk ]; then
  315.                    echo "$0: Root disk contains a reference to: "$virtual_disk""
  316.                    echo "$0: This cannot be found in: "$rootdiskpath""
  317.                    echo "$0: Please fix and retry"
  318.                    exit_script 1
  319.                 fi
  320.                 check_disk_mount "$rootdiskpath"$virtual_disk"\ "
  321.                 mkdir "$root_mount"$fMTPT
  322.                 mount_virtual_disk "$rootdiskpath"$virtual_disk "$root_mount"$fMTPT
  323.             fi    
  324.           ;;
  325.         esac
  326.     done < "$root_mount"/etc/fstab
  327. }
  328.  
  329.  
  330.  
  331. # Attempt to migrate from a root.disk. The root.disk must be a fully
  332. # contained Ubuntu install with /, /boot, /home, /usr (note this excludes
  333. # grub-legacy Ubuntu since /boot is on the windows partition).
  334. # The checks performed here are pretty basic.
  335. # The onus is on the user to have a working Wubi root.disk
  336. root_disk_migration ()
  337. {
  338.     if [ ! -f "$root_disk" ]; then
  339.         echo "$0: root disk not found: "$root_disk""
  340.         exit_script 1
  341.     fi
  342. # Since the migration can be from a live CD
  343.     if [ "$no_bootloader" = "true" ]; then
  344.         echo "$0: You cannot use --no-bootloader with --root-disk"
  345.         exit_script 1
  346.     fi
  347.     install_grub=true
  348.  
  349.  
  350. # mount the root.disk and check it is a fully contained install
  351. # or else the /etc/fstab links to additional virtual disks and
  352. # these can be validated.
  353. # /usr, /home, and /boot are present. If this is a grub legacy
  354. # migration /boot is always separate so it's not possible to migrate
  355.     mkdir -p $root_mount
  356.  
  357. # make sure the root.disk is not already mounted
  358.     check_disk_mount "$root_disk""\ "
  359.  
  360. # mount it - fail if the mount fails
  361.     mount_virtual_disk "$root_disk" "$root_mount"
  362.  
  363. # override root for the copy command.
  364.     root="$root_mount"/
  365.  
  366. # read the /etc/fstab and check for other virtual disks, make sure they are there, and unmounted.
  367. # Create mountpoints for /usr and /home if they exist and mount them
  368.     rootdiskpath=${root_disk%/*}/
  369.     check_fstab    
  370.    
  371. # determine size of install
  372.     awkscript="\$6==\""$root_mount"\" || \$6==\""$root_mount"/usr\" || \$6==\""$root_mount"/home\" {sum += \$3} END {print sum}"
  373.     install_size=$(df | awk "$awkscript")
  374.  
  375. # check we have all the required files - grub legacy won't work as
  376. # we never mount /boot separately
  377.     if [ $(ls -1 "$root_mount"/usr | wc -l) -eq 0 ] || \
  378.        [ $(ls -1 "$root_mount"/home | wc -l) -eq 0 ] || \
  379.        [ $(ls -1 "$root_mount"/boot | wc -l) -eq 0 ]; then
  380.         echo "$0: Root disk ("$root_disk") missing required directories."
  381.         echo "$0: If the original release was prior to 9.10 then it can"
  382.         echo "$0: not be migrated from the root.disk."
  383.         exit_script 1
  384.     fi
  385.  
  386. # make sure the architecture matches
  387.     if [ $(file /bin/bash | grep '32-bit' | wc -l) -eq 1 ]; then
  388.       if [ $(file "$root_mount"/bin/bash | grep '64-bit' | wc -l) -eq 1 ]; then
  389.         echo "$0: Current Ubuntu architecture is 32-bit but root.disk contains a 64-bit install."
  390.         echo "$0: You need to migrate from a 64-bit environment"
  391.         exit_script 1
  392.       fi
  393.     elif [ $(file "$root_mount"/bin/bash | grep '32-bit' | wc -l) -eq 1 ]; then
  394.       echo "$0: Current Ubuntu architecture is 64-bit but root.disk contains a 32-bit install."
  395.       echo "$0: You need to migrate from a 32-bit environment"
  396.       exit_script 1
  397.     fi
  398. }
  399.  
  400. ### Determine whether this is a wubi install or not
  401. ### Returns 0: Wubi, 1: Not wubi
  402. check_wubi ()
  403. {
  404. # first check for a root_disk - always wubi
  405.     if [ ! -z "$root_disk" ]; then
  406.         root_disk_migration
  407.         return 0 # wubi
  408.     fi
  409.  
  410. # Identify root device - looking for /dev/loop , and then identify the loop file (root.disk)
  411. # Note for Grub legacy, the /boot device is the windows host.
  412. # For releases without grub-probe the mount output directly refers to root.disk on Wubi
  413.     if ! type grub-probe > /dev/null 2>&1 ; then
  414.       if [ $(mount | grep ' / ' | grep '/host/ubuntu/disks/root.disk' | wc -l) -eq 1 ]; then
  415.         return 0 # e.g. wubi in release 8.04
  416.       elif [ $(mount | grep ' / ' | wc -l) -eq 1 ]; then
  417.         fs=ext3
  418.         return 1
  419.       else
  420.         echo "$0: Cannot migrate from a Live CD/USB"
  421.         echo "$0: unless you use option: --root-disk= "
  422.         exit_script 1
  423.       fi
  424.     fi
  425.  
  426. # Check what device root (/) is mounted on
  427.     root_device="`grub-probe --target=device / 2> /dev/null`"
  428.     if [ -z "$root_device" ]; then
  429.         echo "$0: Cannot migrate from a Live CD/USB"
  430.         echo "$0: unless you use option: --root-disk= "
  431.         exit_script 1
  432.     fi
  433.  
  434. # identify root.disk if a Wubi install
  435.     case ${root_device} in
  436.       /dev/loop/*|/dev/loop[0-9])
  437.         loop_file=`losetup ${root_device} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
  438.       ;;
  439.     esac
  440.  
  441.     # Check whether booted from loop device
  442.     # Check whether ext3 - stick with that (not supporting ext2)
  443.     if [ "x${loop_file}" = x ] || [ ! -f "${loop_file}" ]; then
  444.         # not wubi - but before leaving, check whether the file system is ext3
  445.         if [ "$(blkid -c /dev/null -o value -s TYPE "$root_device")" = "ext3" ]; then
  446.             fs=ext3
  447.         fi
  448.         return 1 # not wubi
  449.     fi
  450.  
  451.     # Irregular root.disk - don't allow (at this time) since it's possible
  452.     # to migrate using the --root-disk= option anyway.
  453.     if [ "$loop_file" != "/host/ubuntu/disks/root.disk" ]; then
  454.         return 2 # migrate not permitted
  455.     fi
  456.  
  457.     # find the mountpoint for the root.disk - basically strip
  458.     # /host/ubuntu/disks/root.disk down from the right to the left
  459.     # until it is a mountpoint (/host/ubuntu/disks, /host/ubuntu, /host)
  460.     # We're expecting /host
  461.     mtpt="${loop_file%/*}"
  462.     while [ -n "$mtpt" ]; do
  463.         while read DEV MTPT FSTYPE OPTS REST; do
  464.             if [ "$MTPT" = "$mtpt" ]; then
  465.                 loop_file=${loop_file#$MTPT}
  466.                 host_mountpoint=$MTPT
  467.                 break
  468.             fi
  469.         done < /proc/mounts
  470.         mtpt="${mtpt%/*}"
  471.         [ -z "$host_mountpoint" ] || break
  472.     done
  473.  
  474.     #keep it to the known scenarios
  475.     if [ "$host_mountpoint" != "/host" ]; then
  476.         return 2 # irregular - avoid
  477.     fi
  478. }
  479.  
  480. ### Early checks - must be admin, check target and swap device(s)
  481. ### Determine migration type - can be a normal Ubuntu install
  482. ### or a Wubi install (running or from a root.disk)
  483. pre_checks ()
  484. {
  485.     if [ "$(whoami)" != root ]; then
  486.       echo "$0: Admin rights are required to run this program."
  487.       exit 1  # exit immediately no cleanup required
  488.     fi
  489.  
  490. # target device must be a non-empty string and a block device
  491. # make sure the device is not mounted already
  492.     if [ -z "$dev" ] || [ ! -b "$dev" ]; then
  493.         echo "$0: target_partition ("$dev") must be a valid partition."
  494.         exit_script 1
  495.     fi
  496.  
  497. # determine drive of target partition - make sure the user hasn't
  498. # specified the drive instead of the partition
  499.     disk=${dev%%[0-9]*}
  500.     if [ "$disk" = "$dev" ]; then
  501.         echo "$0: target_partition "$dev" is a drive, not a partition."
  502.         exit_script 1
  503.     fi
  504.     if [ $(fdisk -l | grep "$dev[ \t]" | grep "[ \t]5[ \t]" | grep -i "Extended" | wc -l) -eq 1 ]; then
  505.         echo "$0: target_partition "$dev" is an Extended partition."
  506.         exit_script 1
  507.     fi
  508.     if [ $(fdisk -l | grep "$dev[ \t]" | grep "[ \t]f[ \t]" | grep -i "W95 Ext'd (LBA)" | wc -l) -eq 1 ]; then
  509.         echo "$0: target_partition "$dev" is an Extended partition."
  510.         exit_script 1
  511.     fi
  512.     if [ $(fdisk -l | grep "$dev[ \t]" | grep "[ \t]85[ \t]" | grep -i "Linux extended" | wc -l) -eq 1 ]; then
  513.         echo "$0: target_partition "$dev" is an Extended partition."
  514.         exit_script 1
  515.     fi
  516. # hard check - partition type must be "83 - Linux"
  517. # previous version of script will happily use e.g. an ntfs partition in which case you end up
  518. # with a partition type ntfs and a file system ext3/4. For future sanity and to avoid confusion
  519. # the partition should be prepared correctly beforehand. My own attempts to modify it to 83 in the
  520. # scripts with sfdisk have proven to be dangerous.
  521.     if [ $(fdisk -l | grep "$dev[ \t]" | grep "[ \t]83[ \t]" | grep -i "Linux" | wc -l) -eq 0 ]; then
  522.         echo "$0: target_partition "$dev" must be type 83 - Linux."
  523.         exit_script 1
  524.    fi
  525.  
  526.     if [ $(mount | grep "$dev"'\ ' | wc -l) -ne 0 ]; then
  527.         echo "$0: "$dev" is mounted - please unmount and try again"
  528.         exit_script 1
  529.     fi
  530.  
  531. # swap device must be the correct type
  532.     if [ -n "$swapdev" ] && [ ! -b "$swapdev" ]; then
  533.         echo "$0: swapdevice ("$swapdev") is not a block device."            
  534.         exit_script 1
  535.     fi
  536. # swap partition type is '82 - Linux swap / Solaris'
  537. # Blkid will report type "swap" or "swsuspend", the latter if
  538. # the swap partition contains a hibernated image.
  539.     if [ -b "$swapdev" ]; then
  540.         if [ $(fdisk -l | grep "$swapdev[ \t]" | grep "[ \t]82[ \t]" | grep -i "Linux swap" | wc -l) -eq 0 ]; then
  541.             echo "$0: "$swapdev" is not a swap partition"
  542.             exit_script 1
  543.         fi
  544.         if [ "$(blkid -c /dev/null -o value -s TYPE "$swapdev")" = "swsuspend" ]; then
  545.             echo "$0: "$swapdev" contains a hibernated image"
  546.             exit_script 1
  547.         fi
  548.     fi
  549. # Option --shared-swap is when you want to share the swap partition that is
  550. # already in use by another install. So you want to avoid running mkswap as
  551. # this will change the UUID (and you have to update the other install)
  552. # So make sure a) a swap partition has been supplied, and b) that is is valid
  553.     if [ -z "$swapdev" ] && [ "$no_mkswap" = "true" ]; then
  554.         echo "$0: Option --shared-swap only valid with a swap partition"
  555.         exit_script 1
  556.     fi
  557.     if [ "$no_mkswap" = "true" ]; then
  558.       if [ $(swapon -s | grep "$swapdev"'\ ' | wc -l) -eq 0 ]; then
  559.         swapon $swapdev > /dev/null 2>&1
  560.         if [ $? -ne 0 ]; then
  561.             echo "$0: "$swapdev" is not an existing swap partition"
  562.             echo "$0: Option --shared-swap cannot be used"
  563.             exit_script 1
  564.         else
  565.           swapoff $swapdev > /dev/null 2>&1
  566.         fi
  567.       fi
  568.     fi
  569.  
  570. # check for partitions mounted on 'unexpected' mountpoints. These aren't
  571. # included in the space check and can cause the migration to run out of space
  572. # during the rsync copy. Mountpoints under /mnt or /media and of course
  573. # /boot, /usr, /home, /root, /tmp and /host are not a problem.
  574. # This check doesn't apply to a root.disk migration
  575.     mtpt=
  576.     if [ -z "$root_disk" ]; then
  577.       while read DEV MTPT FSTYPE OPTS REST; do
  578.         case "$DEV" in
  579.           /dev/sd[a-z][0-9])
  580.             mtpt=$MTPT
  581.             work=$MTPT
  582.             while true; do
  583.                 work=${mtpt%/*}
  584.                 if [ "$work" == "" ]; then
  585.                     break
  586.                 fi
  587.                 mtpt=$work
  588.             done
  589.             case $mtpt in
  590.             /mnt|/media|/host|/home|/usr|/boot|/tmp|/root)
  591.                 true #ok
  592.                 ;;
  593.             *)
  594.                 echo "$0: "$DEV" is mounted on "$MTPT""
  595.                 echo "$0: The migration script does not automatically"
  596.                 echo "$0: exclude this mountpoint."
  597.                 echo "$0: Please unmount "$MTPT" and try again."
  598.                 exit_script 1
  599.                 ;;
  600.             esac
  601.           ;;
  602.         esac
  603.       done < /proc/mounts
  604.     fi
  605.  
  606. # Ubuntu releases prior to 9.10 don't support ext4 (default)
  607.     if ! type mkfs.ext4 > /dev/null 2>&1 ; then
  608.         fs=ext3
  609.     fi
  610.  
  611. # Check whether we're migrating a Wubi install or normal install.
  612. # The Wubi install can either be running or a root.disk file
  613.     check_wubi
  614.     rc="$?"
  615.     if [ "$rc" -ne "0" ]; then
  616.       wubi_install=false
  617.     fi
  618.     if [ "$rc" -eq "2" ]; then
  619.       echo "$0: Unsupported Wubi install (irregular root.disk or mountpoint)"
  620.       exit_script 1
  621.     fi
  622.  
  623. # create a temp directory to mount the target partition
  624.     mkdir -p $target
  625.  
  626. # make sure the mountpoint is not in use
  627.     umount $target 2> /dev/null
  628.  
  629. # check whether connected to internet - required when converting
  630. # a grub-legacy install to grub2.
  631.     ping -c 1 google.com > /dev/null 2>&1
  632.     if [ "$?" -eq 0 ]; then        
  633.         internet_connection=true
  634.     fi
  635.  
  636. # If this isn't a root.disk install, check
  637. # which version of grub is installed.
  638. # Have to use grub-install.real on Wubi or else you
  639. # can get grub-probe and/or permission errors
  640.     if [ -z "$root_disk" ]; then
  641.       if [ -f "/usr/sbin/grub-install.real" ]; then
  642.         if [ $(grub-install.real --version | grep "0.97" | wc -l) -ne 0 ]; then
  643.             grub_legacy=true
  644.         fi
  645.       elif [ $(grub-install --version | grep "0.97" | wc -l) -ne 0 ]; then
  646.           grub_legacy=true
  647.       fi        
  648.       if [ "$grub_legacy" = "true" ]; then
  649.         if [ "$internet_connection" = "false" ]; then
  650.           echo "$0: You need an active internet connection to replace"
  651.           echo "$0: Grub legacy with Grub2 on the migrated install"
  652.           exit_script 1
  653.         fi
  654.         echo "$0: Grub (legacy) is installed - this will be replaced"
  655.         echo "$0: with Grub2 (only on the migrated install)."
  656.         if [ "$no_bootloader" = "true" ]; then
  657.           echo "$0: You have selected --no-bootloader with grub-legacy"
  658.           echo "$0: You will have to manually modify your current grub"
  659.           echo "$0: menu.lst to boot the migrated install."
  660.         else
  661.           echo "$0: The Grub2 bootloader will be installed on "$disk""
  662.           install_grub=true
  663.         fi
  664.         # grub legacy wubi is always ext3
  665.         if [ "$wubi_install" = "true" ]; then
  666.           fs=ext3
  667.         fi
  668.         if [ "$assume_yes" = "false" ] ; then
  669.           test_YN "Continue and replace Grub legacy? (Y/N)"
  670.           # User pressed N
  671.           if [ "$?" -eq "1" ]; then
  672.             echo "$0: Migration request canceled by user"
  673.             exit_script 1
  674.           fi
  675.         fi
  676.         # for old installs (8.04, 8.10?) there is no grub-common package
  677.         if dpkg -s grub-common > /dev/null 2>&1; then
  678.           grub_common_exists=true
  679.         else
  680.           grub_common_exists=false
  681.         fi
  682.       fi
  683.     fi
  684. }
  685.  
  686. ### Validate target device and swap device
  687. ### Check size is sufficient
  688. ### Check options against type of install
  689. sanity_checks ()
  690. {
  691.  
  692. # try and mount target partition, and ensure that it is empty
  693. # (note freshly formatted ext2/3/4 contain a single 'lost and found'
  694. # and freshly formatted ntfs contains a "System Volume Information")
  695. # Checks are performed prior to formatting if possible, however,
  696. # if the mount fails, it could be unformatted in which case we
  697. # have to format first
  698.     echo ""
  699.     if mount -t auto "$dev" $target 2> /dev/null; then
  700.         if [ $(ls -1 $target | wc -l) -ne 0 ] ; then
  701.           if [ $(ls -1 $target | wc -l) -gt 1 ] || \
  702.              [ "$(ls $target)" != "lost+found" ]; then
  703.             echo "$0: Partition $dev is not empty. Cancelling"
  704.             if [ "$debug" = "true" ]; then
  705.                 test_YN "DEBUG mode: do you want to continue anyway?"
  706.                 if [ $? -ne 0 ]; then
  707.                     exit_script 1
  708.                 fi
  709.             else
  710.                exit_script 1
  711.             fi
  712.           fi
  713.         fi
  714.     else
  715.         echo "$0: Partition $dev could not be mounted for validation."
  716.         echo "$0: This is normal if the partition is unformatted or the file"
  717.         echo "$0: system is corrupted. It could also mean you have entered"
  718.         echo "$0: the wrong partition. The partition will have to be formatted"
  719.         echo "$0: in order to complete validation."
  720.         echo "$0: PLEASE MAKE SURE YOU HAVE SELECTED THE CORRECT PARTITION."
  721.         # have to interrupt if the user has select --assume-yes, otherwise the
  722.         # format_partition function will ask to continue.
  723.         if [ "$assume_yes" = "true" ]; then
  724.           test_YN "Continue? (Y/N)"
  725.           # User pressed N
  726.           if [ "$?" -eq "1" ]; then
  727.             echo "$0: Migration request canceled by user"
  728.             exit_script 1
  729.           fi
  730.         fi
  731.         format_partition
  732.         mount $dev $target
  733.     fi
  734.  
  735. # Determine the install size to be migrated and the total size of the target
  736. # Install size sums the 3rd column (Used space) on the /, /home and /usr partitions
  737. # Total size takes the 2nd column on the target partition.
  738. # For root.disk migrations we already know the size and the release is 9.10 or greater
  739. # so just get the target size and don't bother checking for zero based index in awk
  740.     target_size=$(df $target|tail -n 1|awk '{print $2}')
  741.     if [ -z "$root_disk" ]; then
  742.         install_size=$(df | awk '$6=="/" || $6=="/home" || $6=="/usr"|| $6=="/boot" {sum += $3} END {print sum}')
  743.         if [ "$install_size" = "" ]; then # 8.04 - awk used zero based column index
  744.           install_size=$(df | awk '$5=="/" || $5=="/home" || $5=="/usr" || $6=="/boot" {sum += $2} END {print sum}')
  745.           target_size=$(df $target|tail -n 1|awk '{print $1}')
  746.         fi
  747.     fi
  748.  
  749. # just in case of an error, the size might be zero
  750.     if [ $install_size = "" ] || [ $install_size -eq 0 ]; then
  751.         echo "$0: Error determining size of install. Cancelling"
  752.         exit_script 1
  753.     fi
  754.  
  755. # Ensure the target partition is large enough
  756. # Technically you can have an install less that 5GB but this seems
  757. # too small to be worth allowing
  758.     if [ $target_size -lt $install_size ] || [ $target_size -lt 5120000 ]; then
  759.         echo "$0: Target partition ($dev) is not big enough"
  760.         echo "$0: Current install is $install_size K"
  761.         echo "$0: Total space on target is $target_size K, (min reqd 5 GB)"
  762.         echo "$0: Cancelling"
  763.         exit_script 1
  764.     fi
  765.     umount $target
  766. }
  767.  
  768. ### get all user interaction out of the way so that the
  769. ### migration can proceed unattended
  770. final_questions ()
  771. {
  772.     # Already notified grub-legacy users about grub2 upgrade
  773.     if [ "$grub_legacy" = "true" ] ; then
  774.        return 0
  775.     fi
  776.     # No opt out for --root-disk= option, but user can cancel migration
  777.     if [ ! -z "$root_disk" ] ; then
  778.       echo "$0: The Grub2 bootloader will be installed to "$disk"."
  779.       echo "$0: This is required when a migration is performed"
  780.       echo "$0: from a named root.disk file."
  781.       test_YN "Continue and install Grub2 to "$disk?" (Y/N)"
  782.       # User pressed N
  783.       if [ "$?" -eq "1" ]; then
  784.         echo "$0: User canceled migration."
  785.         exit_script 1
  786.       fi
  787.       return 0
  788.     fi
  789.     if [ "$no_bootloader" = "true" ] ; then
  790.        return 0
  791.     fi
  792.     if [ "$assume_yes" = "true" ] ; then
  793.        install_grub=true
  794.        return 0
  795.     fi
  796.  
  797.     echo ""        
  798.     echo "$0: Would you like the grub2 bootloader to be installed"
  799.     echo "$0: to drive "$disk"? If you choose not to, you will"
  800.     echo "$0: still be able to boot your migrated install from"
  801.     echo "$0: your current install."
  802.     test_YN "Install grub bootloader to "$disk?" (Y/N)"
  803.     # User pressed Y
  804.     if [ "$?" -eq "0" ]; then
  805.       install_grub=true
  806.     fi
  807. }
  808.  
  809. # Format the target partition file system
  810. # Message to close open programs to prevent partial updates
  811. # being copied as is.
  812. format_partition ()
  813. {
  814.     if [ "$formatted_dev" != true ] ; then
  815.       formatted_dev="true"
  816.       if [ "$assume_yes" != true ] ; then
  817.         echo "$0: Please close all open files before continuing."
  818.         echo "$0: About to format the target partition ($dev)."
  819.         test_YN "Proceed with format (Y/N)"
  820.         # User pressed N
  821.         if [ "$?" -eq "1" ]; then
  822.           echo "$0: Migration request canceled by user"
  823.           exit_script 1
  824.         fi
  825.       fi    
  826.       echo "$0: Formatting $dev with "$fs" file system"
  827.       mkfs."$fs" $dev > /dev/null 2>&1
  828.       if [ "$?" != 0 ]; then
  829.         echo "$0: Formatting "$dev" failed or was canceled"
  830.         echo "$0: Migration request canceled"
  831.         exit_script 1
  832.       fi
  833.     fi
  834. }
  835.  
  836. # Copy entire install to target partition
  837. # Monitor return code from rsync in case user hits CTRL-C.
  838. # Make fake /host directory to allow override of /host mount
  839. # and prevent update-grub errors in chroot
  840. # Disable 10_lupin script
  841. migrate_files ()
  842. {
  843.     mount $dev $target # should't fail ever - freshly formatted
  844.     if [ "$?" != 0 ]; then
  845.         echo "$0: "$dev" failed to mount"
  846.         echo "$0: Migration request canceled"
  847.         exit_script 1
  848.     fi
  849.     echo ""
  850.     echo "$0: Copying files - please be patient - this takes some time"
  851.     rsync -a --exclude="$root"host --exclude="$root"mnt/* --exclude="$root"home/*/.gvfs --exclude="$root"var/lib/lightdm/.gvfs --exclude="$root"media/*/* --exclude="$root"tmp/* --exclude="$root"proc/* --exclude="$root"sys/* $root $target # let errors show
  852.     if [ "$?" -ne 0 ]; then
  853.         echo ""
  854.         echo "$0: Copying files failed - user canceled?"
  855.         echo "$0: Unmounting target..."
  856.         sleep 3
  857.         umount $dev
  858.         echo "$0: Migration request canceled"
  859.         exit_script 1
  860.     fi
  861.  
  862.     if [ "$wubi_install" = "true" ]; then
  863.       mkdir $target/host
  864.       chmod -x $target/etc/grub.d/10_lupin > /dev/null 2>&1
  865.     fi    
  866. }
  867.  
  868. ### Run mkswap on swap partition and enable hibernation
  869. ### Note: swap must be at least as big as RAM for hibernation
  870. ### It's possible to bypass mkswap if you would like to share
  871. ### an existing swap partition from another install
  872. create_swap ()
  873. {
  874.     if [ -b "$swapdev" ]; then
  875.         if [ "$no_mkswap" = "false" ]; then
  876.           echo "$0: Creating swap..."
  877.           mkswap $swapdev > /dev/null
  878.           if [ "$?" != 0 ]; then
  879.             echo "$0: Command mkswap on "$swapdev" failed"
  880.             echo "$0: Migration will continue without swap"
  881.             swapdev=
  882.           fi
  883.         fi
  884.     fi
  885.     if [ -b "$swapdev" ]; then
  886.         echo "RESUME=UUID=$(blkid -c /dev/null -o value -s UUID $swapdev)" > $target/etc/initramfs-tools/conf.d/resume
  887.     fi
  888. }
  889.  
  890.  
  891. edit_fstab ()
  892. {
  893. # sed s:regexp:replacement:
  894. # Replace characters matched between 1st ':' and 2nd ':' with
  895. # whatever is between the 2nd  ':' and 3rd ':' (in this case, we're
  896. #  replacing with nothing - blanking out)
  897. # .* means match any characters up until the next match
  898. # [\.]disk means match a period followed by disk: '.disk'
  899. # -i replaces file (breaking symbolic links).
  900.  
  901. # blank any line starting with '/' and containing '.disk'
  902.     sed -i 's:/.*[\.]disk .*::' $target/etc/fstab
  903. # blank out line starting with '/' and containing '/disks.boot'
  904.     sed -i 's:/.*/disks/boot .*::' $target/etc/fstab
  905. # blank out line starting with ' /host ' mounted (some wubi users do this)
  906.     sed -i 's:.*[ \t]/host[ \t].*::' $target/etc/fstab
  907.  
  908. # for non-wubi blank out line mounting root or swap (and comments "root was..." / "swap was")
  909.     if [ "$wubi_install" = "false" ]; then
  910.       sed -i 's:.*[ \t]/[ \t].*::' $target/etc/fstab
  911.       sed -i 's:#.*[ \t]root[ \t].*::' $target/etc/fstab
  912.       sed -i 's:.*[ \t]swap[ \t].*::' $target/etc/fstab
  913.     fi
  914.  
  915. # the migration will 'merge' installs with separated /home, /boot, /usr
  916. # (not if the migration is from a root.disk file)
  917.     if [ "$wubi_install" = "true" ]; then
  918.       sed -i 's:/.*home[\.]disk .*::' $target/etc/fstab
  919.       sed -i 's:/.*usr[\.]disk .*::' $target/etc/fstab
  920.       sed -i 's:/.*boot[\.]disk .*::' $target/etc/fstab
  921.     else
  922.       sed -i 's:.*[ \t]/home[ \t].*::' $target/etc/fstab
  923.       sed -i 's:.*[ \t]/usr[ \t].*::' $target/etc/fstab
  924.       sed -i 's:.*[ \t]/boot[ \t].*::' $target/etc/fstab
  925.     fi
  926.  
  927. # add line to mount $dev as new root (based on UUID)
  928.     echo "# root was on "$dev" when migrated" >> $target/etc/fstab    
  929.     echo "UUID=$(blkid -c /dev/null -o value -s UUID "$dev")    /    "$fs"    errors=remount-ro    0    1" >> $target/etc/fstab
  930. # add line to mount swapdev based on uuid if passed
  931.     if [ -b "$swapdev" ]; then
  932.         echo "# swap was on "$swapdev" when migrated" >> $target/etc/fstab
  933.         echo "UUID=$(blkid -c /dev/null -o value -s UUID $swapdev)    none    swap    sw    0    0" >> $target/etc/fstab
  934.     fi
  935. }
  936.  
  937. # Start chroot to target install
  938. # (mount empty /host to prevent update-grub errors for Wubi)
  939. start_chroot ()
  940. {
  941.     echo ""
  942.     echo "$0: Starting chroot to the target install."
  943. # Note: for internet connection on chroot, the /etc/resolv.conf
  944. # is already copied - unless migrating from
  945. # root.disk - but this only supports grub2 right now so
  946. # not required to connect to net
  947. #    cp /etc/resolv.conf $target/etc/resolv.conf
  948.     for i in dev proc sys dev/pts; do
  949.         mount --bind /$i $target/$i;
  950.     done
  951.     if [ "$wubi_install" = "true" ] && [ -z "$root_disk" ]; then
  952.       mount --bind /host $target/host
  953.     fi
  954. }
  955.  
  956. # Exit chroot from target install
  957. end_chroot ()
  958. {
  959.     echo "$0: Exiting from chroot on target install..."
  960.     if [ "$wubi_install" = "true" ] && [ -z "$root_disk" ]; then
  961.         umount $target/host
  962.     fi
  963.     for i in dev/pts dev proc sys; do
  964.         umount $target/$i;
  965.     done
  966. }
  967.  
  968. # Run command in chroot on target install - suppress output
  969. # Check return code - if an error is encountered try to
  970. # exit the chroot in an orderly fashion before terminating.
  971. # Allow command suppression unless in debug mode, or if
  972. # requested - e.g. to allow user interaction in chroot
  973. target_cmd ()
  974. {
  975.     if  [ "$debug" = "true" ] || [ "$suppress_chroot_output" = "false" ]; then
  976.         chroot $target $*
  977.     else
  978.         chroot $target $* > /dev/null 2> /tmp/wubi-move-error
  979.     fi
  980.     if [ $? -ne 0 ]; then
  981.         echo "$0: An error occurred within chroot"
  982.         echo "$0: Error is: $(cat /tmp/wubi-move-error)"        
  983.         echo "$0: Attempting to exit chroot normally..."
  984.         end_chroot
  985.         echo "$0: Cancelling migration... "
  986.         exit_script 1
  987.     fi
  988. }
  989.  
  990. # Prevent upstart jobs running in the chroot
  991. bypass_upstart()
  992. {
  993.     target_cmd dpkg-divert --local --rename --add /sbin/initctl
  994.     target_cmd ln -s /bin/true /sbin/initctl
  995. }
  996.  
  997. # remove Upstart bypass
  998. remove_upstart_bypass()
  999. {
  1000.     target_cmd rm /sbin/initctl
  1001.     target_cmd dpkg-divert --local --rename --remove /sbin/initctl
  1002. }
  1003.  
  1004. ### remove lupin support and update the target install grub menu
  1005. ### if no lupin, then rebuild initrd image to permit hibernation
  1006. ### (done automatically when lupin removed)
  1007. chroot_cmds ()
  1008. {
  1009.     if [ "$wubi_install" = "true" ]; then
  1010.       echo "$0: Removing lupin-support on target..."
  1011.       target_cmd apt-get -y remove lupin-support
  1012.     else
  1013.       target_cmd update-initramfs -u
  1014.     fi
  1015. }
  1016.  
  1017. ### replace grub legacy with grub2
  1018. ### if version 10.04 or greater, grub-pc should prompt
  1019. ### where to install and run update-grub
  1020. grub_legacy()
  1021. {
  1022.     echo "$0: Removing Grub Legacy on target..."
  1023.     if [ "$grub_common_exists" = "true" ]; then
  1024.       target_cmd apt-get -y purge grub grub-common
  1025.     else
  1026.       target_cmd apt-get -y purge grub
  1027.     fi
  1028.     target_cmd mv /boot/grub /boot/grubold
  1029.     echo "$0: Installing Grub2 on target..."
  1030.     echo "$0: Transferring control to grub2 install process:"
  1031.     sleep 5
  1032. # installing grub-pc in release 9.10 and greater requires user interaction
  1033. # so don't suppress chroot output
  1034.     suppress_chroot_output=false
  1035.     if [ "$grub_common_exists" = "true" ]; then
  1036.       target_cmd apt-get -y install grub-pc grub-common
  1037.     else
  1038.       target_cmd apt-get -y install grub-pc
  1039.     fi
  1040.     suppress_chroot_output=true
  1041. # For 9.10 and later, installing grub-pc will already have prompted
  1042. # the user where to install the grub2 bootloader, and run update-grub.
  1043. # But as a safeguard - do it anyway (if requested)
  1044.     echo ""
  1045.     echo ""
  1046.     sleep 2
  1047.     if [ "$install_grub" = "true" ]; then
  1048.         target_cmd grub-install $disk
  1049.         echo "$0: Grub bootloader installed to $disk"
  1050.     fi
  1051.     echo "$0: Updating the target grub menu"
  1052.     target_cmd update-grub
  1053.  
  1054. }
  1055.  
  1056. # Check whether there is a need to install the grub2 bootloader on the
  1057. # target drive MBR. Divert to separate grub legacy code as appropriate.
  1058. # Reasons for not installing are e.g.
  1059. # you are installing to /dev/sdbY, but you boot from # /dev/sda. In this
  1060. # case you should manually replace the bootloader after booting it.
  1061. # You will also be able to boot it from the menu of your current install
  1062. # This code sets or resets the grub install device on the target so that
  1063. # grub knows where to update itself later (or not to). These commands are
  1064. # run direct to the chroot to avoid error handling logic (grub2 changes a lot
  1065. # and these aren't relevant on earlier installs, 1.96 for instance).
  1066. grub_bootloader ()
  1067. {
  1068.     if  [ "$grub_legacy" = "true" ]; then
  1069.       grub_legacy
  1070.     else
  1071.       if [ "$install_grub" = "true" ]; then
  1072.         target_cmd grub-install $disk
  1073.         echo "$0: Grub bootloader installed to $disk"
  1074.         echo SET grub-pc/install_devices $disk | chroot $target debconf-communicate > /dev/null 2>&1
  1075.       else
  1076.         echo RESET grub-pc/install_devices | chroot $target debconf-communicate > /dev/null 2>&1
  1077.       fi
  1078.       echo "$0: Updating the target grub menu..."
  1079.       target_cmd update-grub
  1080.     fi
  1081. }
  1082.  
  1083. # Update the local install grub menu to add the new install
  1084. # (If you haven't installed the grub2 bootloader then this is
  1085. # the only way to boot the migrated install. For Wubi this
  1086. # leaves the windows bootloader in control)
  1087. # Migrating from a root.disk will bypass this step
  1088. # From a grub legacy install this is left to the user to do manually
  1089. update_grub ()
  1090. {
  1091.     if [ -z "$root_disk" ] && [ "$grub_legacy" = "false" ]; then
  1092.         echo ""
  1093.         echo "$0: Updating current grub menu to add new install..."
  1094.         sleep 1
  1095.         update-grub
  1096.     fi
  1097. }
  1098.  
  1099. #######################
  1100. ### Main processing ###
  1101. #######################
  1102. pre_checks
  1103. sanity_checks
  1104. final_questions
  1105. format_partition
  1106. migrate_files
  1107. create_swap
  1108. edit_fstab
  1109. start_chroot
  1110. bypass_upstart
  1111. chroot_cmds
  1112. grub_bootloader
  1113. remove_upstart_bypass
  1114. end_chroot
  1115. update_grub
  1116. exit_script 0
Add Comment
Please, Sign In to add comment