File live-fat-stick of Package live-fat-stick
#!/bin/bash
# live-fat-stick
#
# Copyright (c) 2012 CyberOrg Info
# Copyright (c) 2014 Mindaugas Baranauskas
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# Original authors: Jigish Gohil <cyberorg@opensuse.org>
# Contributors: Mindaugas Baranauskas <opensuse.lietuviu.kalba@gmail.com>
#
# This script creates bootable openSUSE, Fedora or Ubuntu(or clones)
# live usb stick on fat partition
#
# To get POT file for localization, execute:
# bash --dump-po-strings live-fat-stick > live-fat-stick.pot
PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin
ionice -c3 -p$$
umount_everything () {
sync
if [[ $distroname != isohybrid ]]; then
umount $isomount &>/dev/null
umount $stickdevpart &>/dev/null
rmdir $isomount &>/dev/null || echo "unable to remove $isomount, please remove manually"
umount $stickmount &>/dev/null
while $(mount | grep $stickmount &>/dev/null); do
umount $stickdevpart &>/dev/null
sleep 2
done
rmdir $stickmount &>/dev/null || echo "unable to remove $stickmount, please remove manually"
if [[ -f $liveusbgui ]]; then
rm $liveusbgui &>/dev/null
fi
if [[ -h $iso_symlink ]]; then
rm "$iso_symlink" &>/dev/null
fi
fi
}
clean_up () {
if [[ $1 == user_killed ]] ; then
echo "aborting and cleaning up"
umount_everything
exit 1
else
echo "cleaning up"
umount_everything
echo "Your bootable usb stick is now ready"
echo "have a lot of fun..."
fi
}
trap "clean_up user_killed" SIGINT SIGTERM
need_help() {
cat <<EOF
Create multi boot USB stick/hard disk with whole iso/s on vfat/fat32 partition
keeping existing data untouched.
Note: File size greater than 4G is not usable on vfat/fat32 partition so the
live CD/DVD iso file should not exceed this limit. Use live-grub-stick on
grub supported non-vfat partition for image size greater than 4G such as
openSUSE installation DVD.
Note2: Install 32bit/x86 iso on the stick first if creating multiboot with both
x86 and x86_64 arch images.
Note3: Requires: syslinux, fuseiso and dd_rescue/ddrescue installed on the system running this.
Run this command as root (su -, not sudo)
live-fat-stick isopath stickpartition
e.g.:
live-fat-stick /home/geeko/openSUSE-Edu-li-f-e-12.2-1-i686.iso /dev/sdXY
To add various distribution iso to the stick, run the following:
For openSUSE : live-fat-stick --suse /path/to/openSUSE-filename.iso /dev/sdXY
For openSUSE with persistence : live-fat-stick --suse-persistent /path/to/openSUSE-filename.iso /dev/sdXY
For Ubuntu clones : live-fat-stick --ubuntu /path/to/ubuntu-filename.iso /dev/sdXY
For Ubuntu clones with persistence : live-fat-stick --ubuntu-persistent /path/to/ubuntu-filename.iso /dev/sdXY
For Mint : live-fat-stick --mint /path/to/mint-filename.iso /dev/sdXY
For Fedora : live-fat-stick --fedora /path/to/fedora-filename.iso /dev/sdXY
For iPXE : live-fat-stick --ipxe /path/to/ipxe.iso /dev/sdXY
For isohybrid : live-fat-stick --isohybrid /path/to/isohybridimage.iso /dev/sdX
isopath should be full absolute path of iso image and the device should be
actual partition on the stick like /dev/sdb1, /dev/sdc1,/dev/sdc2...
The stick partition has to be vfat/fat32 format if the image is not isohybrid.
Persistent option requires minimum 500M free space on the USB device apart from the spare needed by iso image.
To allocate more space for cow file use cowfile variable like this example: "export cowfile=1000M" before running the script
Please note that using isohybrid option will remove all existing data on the USB device
and create new partitions.
Run live-fat-stick -l(or --list) to list the possible usb storage devices available.
openSUSE users can install it via 1-click from here:
http://software.opensuse.org/package/live-fat-stick
EOF
}
if [[ $(id -u) != 0 ]]; then
echo "run this command as root"
need_help
exit 1
fi
while [ $# -gt 2 ]; do
case $1 in
--fedora)
distroname=fedora
;;
--suse|--opensuse)
distroname=suse
;;
--ubuntu|--mint)
distroname=ubuntu
;;
--suse-persistent|--opensuse-persistent)
distroname=suse
PERSISTENT_IMAGE=true
;;
--ubuntu-persistent|--mint-persistent)
distroname=ubuntu
PERSISTENT_IMAGE=true
;;
--isohybrid)
distroname=isohybrid
;;
--ipxe)
distroname=ipxe
;;
*)
echo "invalid arg -- $1, check spelling or if the distribution is supported"
need_help
exit 1
;;
esac
shift
done
if [ "$1" == "-h" -o "$1" == "--help" ]; then
need_help
exit
fi
if [ "$1" == "-l" -o "$1" == "--list" ]; then
echo "Here is the list of possible usb storage devices on your computer,"
echo "use the correct one, usually the one with a number at the end:"
echo "$(for i in $(find /dev/disk/by-path/ |grep usb); do readlink -f $i;done)"
exit
fi
if [[ x"$1" == x ]]; then
echo "Requires first argument as iso image path"
need_help
exit 1
fi
if [[ x"$2" == x ]]; then
echo "Requires second arguement as device partition path, /dev/sdb1 for example"
need_help
echo "Here is the list of possible usb storage devices on your computer, "
echo "use the correct one, usually the one with a number at the end: "
echo "$(for i in $(find /dev/disk/by-path/ |grep usb); do readlink -f $i;done)"
exit 1
fi
if [[ ! -e /usr/bin/syslinux ]]; then
echo "syslinux not found, please install syslinux package"
exit 1
fi
if [[ ! -e /usr/bin/fuseiso ]]; then
echo "fuseiso not found, please install fuseiso package"
exit 1
fi
if [[ ! -e $(which qemu-img) ]]; then
echo "qemu-img not found, please install qemu-tools package"
exit 1
fi
if [[ ! -e $1 ]]; then
echo "File $1 does not exist"
exit 1
fi
if [[ ! -e $2 ]]; then
echo "Device $2 does not exist"
exit 1
fi
#variables
distroname=${distroname:-suse}
isomount=$(mktemp -d)
isopath=$(readlink -f "$1")
isosize=$(stat -c%s "$isopath")
iso_symlink=$(mktemp) ; rm $iso_symlink ; ln -s "$isopath" $iso_symlink
stickmount=$(mktemp -d)
stickdevice=$(echo $2 | sed 's/[0-9]*//g')
stickbase=$(basename $2)
isoname=$(basename "$1")
isonametr=$(echo $isoname | tr " " _)
isonameshort=$(echo $isoname | cut -d "-" -f 1,2,3 | tr " " _)
#stickuuid=$(ls -l /dev/disk/by-uuid/ |grep $stickbase | cut -d " " -f 9)
stickuuid=$(blkid -s UUID -o value $2)
stickpart=$(basename $2 | sed 's/[a-z]*//g')
syslinuxpath=$stickmount/boot/syslinux
stickdevpart=$2
liveusbgui=/tmp/liveusbgui
benice="nice ionice -c3"
cowsize=${cowsize:-500M}
if [[ $distroname != isohybrid ]]; then
if [[ $isosize -gt 4187593113 ]]; then
echo "ISO size is larger than that allowed on vfat partition"
echo "Use live-grub-stick script on grub supported partition format"
exit 1
fi
fi
if [[ $isoname != $isonametr ]]; then
echo "removing space/s from iso name copied to the destination disk"
export isoname=$isonametr
fi
if [[ ! -h /dev/disk/by-uuid/$stickuuid ]]; then
echo "wrong uuid detected, please file bug with output of: blkid $2"
fi
if echo $isoname | grep -qi "Li-f-e" | grep -qi "suse"; then
isonameshort=openSUSE-Li-f-e
fi
are_you_sure () {
echo -n "$1 [$2/$3]? "
while true; do
read answer
case $answer in
y | Y | yes | YES ) answer="y"; break;;
n | N | no | NO ) exit;;
*) echo "Please answer (y)es or (n)o.";;
esac
done
}
try_cp_with_progress () {
sync
if [ -x /usr/bin/dd_rescue ]; then
$benice dd_rescue -A -b 4M -y 4M "$iso_symlink" "$2"
elif [ -x /usr/bin/ddrescue ]; then
$benice ddrescue --force -b 4M "$iso_symlink" "$2"
else
echo "dd_rescue or ddrescue not found, please install one of them, using dd for now"
$benice dd if="$iso_symlink" of="$2" bs=4M
fi
}
copy_kernel_initrd () {
fuseiso $isopath $isomount &>/dev/null
echo "copying kernel and initrd from iso image to $stickdevpart"
if [[ $distroname == suse ]]; then
if [[ $PERSISTENT_IMAGE == true ]]; then
echo "Creating image file for persistent data"
if ! qemu-img create $stickmount/boot/$isonameshort-cowfile $cowsize &>/dev/null;then
echo "Can't create cow file"
else
persistopts="kiwi_cowdevice=/dev/disk/by-uuid/$stickuuid kiwi_cowsystem=/boot/$isonameshort-cowfile"
fi
fi
rm $stickmount/syslinux.cfg &>/dev/null
if [[ ! -f $stickmount/fatstick ]]; then
cp -r $isomount/boot $stickmount/
mv $stickmount/boot/*/loader $syslinuxpath
mv $syslinuxpath/linux $syslinuxpath/linux-$isonameshort
mv $syslinuxpath/initrd $syslinuxpath/initrd-$isonameshort
fi
cp $isomount/boot/*/loader/linux $syslinuxpath/linux-$isonameshort
cp $isomount/boot/*/loader/initrd $syslinuxpath/initrd-$isonameshort
appendsection="append initrd=initrd-$isonameshort isofrom=/dev/disk/by-uuid/$stickuuid:/$isoname isofrom_device=/dev/disk/by-uuid/$stickuuid isofrom_system=/$isoname loader=syslinux splash=silent $persistopts quiet showopts"
isolinux_msg="display isolinux.msg"
ui="ui gfxboot bootlogo isolinux.msg"
fi
if [[ $distroname == ubuntu ]]; then
if [[ $PERSISTENT_IMAGE == true ]]; then
mkdir -p $stickmount/$isonameshort
echo "Creating image file for persistent data"
if ! qemu-img create $stickmount/$isonameshort/casper-rw $cowsize &>/dev/null;then
echo "Can't create cow file"
else
echo "Creating filesystem for persistent data"
mkfs.ext4 -F -O^has_journal -L casper-rw $stickmount/$isonameshort/casper-rw
persistopts="persistent persistent-path=/$isonameshort/"
fi
fi
mkdir -p $syslinuxpath
if [[ -e $isomount/casper/vmlinuz ]]; then
cp $isomount/casper/vmlinuz $syslinuxpath/linux-$isonameshort
else
cp $isomount/casper/vmlinuz.efi $syslinuxpath/linux-$isonameshort
fi
cp $isomount/casper/initrd.lz $syslinuxpath/initrd-$isonameshort
appendsection="append initrd=initrd-$isonameshort boot=casper iso-scan/filename=/$isoname $persistopts quiet splash"
fi
if [[ $distroname == fedora ]]; then
mkdir -p "$syslinuxpath"
mkdir -p "$stickmount/$isonameshort"
echo "copying the content of iso image, this may take a while"
$benice cp -r "$isomount"/* "/$stickmount/$isonameshort/"
mv "$stickmount/$isonameshort"/isolinux/initrd0.img $syslinuxpath/initrd-$isonameshort
mv "$stickmount/$isonameshort"/isolinux/vmlinuz0 $syslinuxpath/linux-$isonameshort
appendsection="append initrd=initrd-$isonameshort root=UUID=$stickuuid rootfstype=vfat rd.live.dir=/$isonameshort/LiveOS/ ro rd.live.image rd.luks=0 rd.md=0 rd.dm=0 quiet rhgb"
fi
if [[ $distroname == ipxe ]]; then
mkdir -p $syslinuxpath
cp $isomount/ipxe.krn $syslinuxpath/linux-$isonameshort
fi
umount $isomount &>/dev/null
}
syslinux_stuff () {
echo "installing syslinux on $stickdevpart"
syslinux -i $stickdevpart
echo "replacing mbr of $stickdevice with syslinux mbr.bin"
if [[ -e /usr/share/syslinux/mbr.bin ]]; then
dd if=/usr/share/syslinux/mbr.bin of=$stickdevice &>/dev/null
elif [[ -e /usr/lib/syslinux/mbr/mbr.bin ]]; then
dd if=/usr/lib/syslinux/mbr/mbr.bin of=$stickdevice &>/dev/null
else
dd if=/usr/lib/syslinux/mbr.bin of=$stickdevice &>/dev/null
fi
echo "setting $stickdevice partition $stickpart active"
parted $stickdevice set $stickpart boot on &>/dev/null
copy_kernel_initrd
}
add_harddisk_section () {
if ! grep -q localboot $syslinuxpath/syslinux.cfg; then
cat <<EOF >>$syslinuxpath/syslinux.cfg
label harddisk
localboot 0x80
EOF
fi
}
add_menu_section_suse () {
if echo $isoname | grep -qi "Li-f-e"; then
cat <<EOF >>$syslinuxpath/syslinux.cfg
label install
kernel linux-$isonameshort
$appendsection liveinstall
label Gnome
kernel linux-$isonameshort
$appendsection gnome
label memtest
kernel memtest
EOF
fi
add_harddisk_section
}
create_syslinux_cfg() {
if [[ $distroname == suse ]]; then
cat <<EOF >$syslinuxpath/syslinux.cfg
implicit 1
prompt 1
timeout 100
$isolinux_msg
$ui
default $isonameshort
EOF
else
if [[ -e /usr/share/syslinux/vesamenu.c32 ]]; then
cp /usr/share/syslinux/vesamenu.c32 $syslinuxpath/ || echo "vesamenu.c32 cannot be copied"
elif [[ -e /usr/lib/syslinux/modules/bios/vesamenu.c32 ]]; then
cp /usr/lib/syslinux/modules/bios/* $syslinuxpath/ || echo "vesamenu.c32 cannot be copied"
else
cp -r /usr/lib/syslinux/* $syslinuxpath/ || echo "vesamenu.c32 is missing or cannot be copied"
fi
cat <<EOF >$syslinuxpath/syslinux.cfg
default vesamenu.c32
ONTIMEOUT $isonameshort
ALLOWOPTIONS 0
PROMPT 0
IMPLICIT 1
OPTIONS 1
TIMEOUT 100
EOF
fi
}
add_menu_section () {
cat <<EOF >>$syslinuxpath/syslinux.cfg
LABEL $isonameshort
kernel linux-$isonameshort
$appendsection
EOF
if [[ $distroname == suse ]]; then
add_menu_section_suse
fi
}
echo "Please make sure the following information is correct:"
echo "iso name: $isoname distro: $distroname stick device: $stickdevice"
echo "stick uuid: /dev/disk/by-uuid/$stickuuid stick partition: $stickpart"
if [[ ! -f $liveusbgui ]]; then
are_you_sure "continue ?" "y" "n"
fi
if [[ $distroname == isohybrid ]];then
try_cp_with_progress "$1" "$2"
else
mkdir $isomount $stickmount &>/dev/null
if mount | grep $stickdevpart &>/dev/null; then
if ! umount $stickdevpart &>/dev/null; then
echo "$stickdevpart in use, please umount it before continuing"
exit 1
fi
fi
if ! mount $2 $stickmount &>/dev/null; then
echo "unable to mount the usb stick partition"
exit 1
fi
if [[ -e $stickmount/$isoname ]];then
isopath=$stickmount/$isoname
echo "using existing $isoname on the stick"
else
isopath=$iso_symlink
if [[ $distroname != fedora ]]; then
echo "copying $isoname to usb stick"
try_cp_with_progress "$1" "$stickmount/$isoname"
if [[ $isosize != $(stat -c%s "$stickmount/$isoname") ]]; then
echo "Source and destination image does not match"
exit 1
fi
fi
fi
if [[ -f $stickmount/fatstick ]]; then
echo "the stick is already bootable stick"
if ! grep -q $isonameshort $syslinuxpath/syslinux.cfg; then
copy_kernel_initrd
echo "adding new image to boot menu"
add_menu_section
fi
else
syslinux_stuff
echo "creating menu entries"
create_syslinux_cfg
add_menu_section
fi
touch $stickmount/fatstick
thisscript=$(readlink -f $0)
cp $thisscript $stickmount/ &>/dev/null || true
fi
clean_up