libdevuansdk/zlibs/imaging

382 lines
8.8 KiB
Plaintext
Raw Permalink Normal View History

2016-09-29 20:36:12 +00:00
#!/usr/bin/env zsh
# shellcheck shell=bash
2020-12-23 08:10:47 +00:00
# Copyright (c) 2016-2021 Ivan J. <parazyd@dyne.org>
2016-09-29 20:36:12 +00:00
# This file is part of libdevuansdk
#
# This source code 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 3 of the License, or
# (at your option) any later version.
#
# This software 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 source code. If not, see <http://www.gnu.org/licenses/>.
vars+=(bootpart rootpart loopdevice)
2016-09-29 20:36:12 +00:00
strapdir_to_image()
{
fn strapdir_to_image
req=(workdir strapdir)
ckreq || return 1
notice "Copying strapdir to image ..."
if [[ ! -d "$workdir/mnt" ]]; then
die "$workdir/mnt doesn't exist. Did you run image_mount?"
zerr; return 1
fi
2016-09-29 20:36:12 +00:00
pushd "$strapdir"
sudo find . \
-not -path "./dev/*" \
-a -not -path "./proc/*" \
-a -not -path "./sys/*" \
| sudo cpio --quiet -adm -p "$workdir/mnt" || { zerr; return 1; }
popd
}
image_prepare_raw()
{
2016-09-29 20:36:12 +00:00
fn image_prepare_raw
req=(workdir size image_name)
ckreq || return 1
notice "Creating raw image of $size MB"
touch "$workdir/${image_name}.img"
chattr -f +C "$workdir/${image_name}.img"
dd if=/dev/zero of="$workdir/${image_name}.img" bs=1M count="$size" || { zerr; return 1; }
}
2016-09-29 20:36:12 +00:00
image_prepare_qcow2()
{
fn image_prepare_qcow2
req=(workdir size image_name)
ckreq || return 1
notice "Creating qcow2 image of $size MB"
touch "$workdir/${image_name}.qcow2"
chattr -f +C "$workdir/${image_name}.qcow2"
qemu-img create -f qcow2 "${workdir}/${image_name}.qcow2" "${size}M" || { zerr; return 1; }
2016-09-29 20:36:12 +00:00
}
image_format_partitions()
{
fn image_format_partitions
req=(bootfs bootpart rootpart)
ckreq || return 1
notice "Formatting image partitions"
case "$bootfs" in
none)
act "Skipping boot partition"
;;
vfat|fat|dos)
act "Formatting boot as VFAT"
sudo mkfs.vfat ${=bootopts} "${bootpart}" >>/dev/null || { zerr; return 1; }
;;
ext?)
act "Formatting boot as $bootfs"
sudo mkfs.${bootfs} ${=bootopts} "${bootpart}" || { zerr; return 1; }
;;
btrfs)
act "Formatting boot as btrfs"
sudo mkfs.btrfs ${=bootopts} "${bootpart}" || { zerr; return 1; }
;;
f2fs)
act "Formatting boot as f2fs"
sudo mkfs.f2fs ${=bootopts} "${bootpart}" || { zerr; return 1; }
;;
"")
die "No bootfs filesystem set!"
zerr; return 1
;;
*)
die "Unimplemented filesystem: $bootfs"
die "Please report it for inclusion."
zerr; return 1
;;
esac
case "$rootfs" in
none)
act "Skipping root partition"
;;
vfat|fat|dos)
act "Formatting root as VFAT"
sudo mkfs.vfat ${=rootopts} "${rootpart}" >>/dev/null || { zerr; return 1; }
;;
ext?)
act "Formatting root as $rootfs"
sudo mkfs.${rootfs} ${=rootopts} "${rootpart}" || { zerr; return 1; }
;;
btrfs)
act "Formatting root as btrfs"
sudo mkfs.btrfs ${=rootopts} "${rootpart}" || { zerr; return 1; }
;;
f2fs)
act "Formatting root as f2fs"
sudo mkfs.f2fs ${=rootopts} "${rootpart}" || { zerr; return 1; }
;;
"")
die "No rootfs filesystem set!"
zerr; return 1
;;
*)
die "Unimplemented filesystem: $rootfs"
die "Please report it for inclusion."
zerr; return 1
;;
esac
}
image_connect_raw()
{
fn image_connect_raw
2016-09-29 20:36:12 +00:00
notice "Connecting raw image to loop device"
2016-09-29 20:36:12 +00:00
loopdevice="$(findloopdev)"
if [[ -z "$loopdevice" ]]; then
die "Didn't find a free loop device"
zerr; return 1
fi
2016-09-29 20:36:12 +00:00
bootpart="${loopdevice}p1"
rootpart="${loopdevice}p2"
2016-09-29 20:36:12 +00:00
}
image_connect_qcow2()
{
fn image_connect_qcow2
req=(workdir image_name)
2016-09-29 20:36:12 +00:00
ckreq || return 1
notice "Connecting qcow2 image to nbd device"
2016-09-29 20:36:12 +00:00
sudo modprobe nbd max_part=8 || { zerr; return 1; }
loopdevice="$(findnbddev)"
if [[ -z "$loopdevice" ]]; then
die "Didn't find a free nbd device"
zerr; return 1
fi
2016-10-12 11:58:06 +00:00
sudo qemu-nbd --connect="${loopdevice}" "$workdir/${image_name}.qcow2" || { zerr; return 1; }
}
2016-10-12 11:58:06 +00:00
image_partition_dos()
{
fn image_partition_dos
req=(loopdevice dos_boot dos_root)
ckreq || return 1
2016-09-29 20:36:12 +00:00
notice "Partitioning dos image"
2016-09-29 20:36:12 +00:00
sudo parted "$loopdevice" --script -- mklabel msdos || { zerr; return 1; }
sudo parted "$loopdevice" --script -- mkpart primary "$dos_boot" || { zerr; return 1; }
sudo parted "$loopdevice" --script -- mkpart primary "$dos_root" || { zerr; return 1; }
if [[ -n "$bootable_part" ]]; then
sudo parted "$loopdevice" --script -- set "$bootable_part" boot on
fi
2016-09-29 20:36:12 +00:00
sudo partprobe "$loopdevice" || { zerr; return 1; }
2016-09-29 20:36:12 +00:00
}
2021-03-25 19:43:01 +00:00
image_partition_gpt()
{
fn image_partition_gpt
req=(loopdevice bootpart rootpart gpt_boot gpt_root)
ckreq || return 1
notice "Partitioning gpt image"
sudo parted "$loopdevice" --script -- mklabel gpt || { zerr; return 1; }
sudo cgpt create -z "$loopdevice" || { zerr; return 1; }
sudo cgpt create "$loopdevice" || { zerr; return 1; }
sudo cgpt add -i 1 -t kernel -b ${gpt_boot[1]} -s ${gpt_boot[2]} \
-l kernel -S 1 -T 5 -P 10 "$loopdevice" || { zerr; return 1; }
2021-03-25 20:27:40 +00:00
sudo cgpt add -i 2 -t data -b ${gpt_root[1]} -s \
$(expr $(sudo cgpt show "$loopdevice" \
2021-03-25 19:43:01 +00:00
| awk '/Sec GPT table/ {print $1}') - ${gpt_root[1]}) \
-l Root "$loopdevice" || { zerr; return 1; }
sudo partprobe "$loopdevice" || { zerr; return 1; }
}
image_mount()
{
fn image_mount
req=(workdir bootpart rootpart bootfs)
2016-09-29 21:19:15 +00:00
ckreq || return 1
notice "Mounting image to $workdir/mnt"
2016-09-29 21:19:15 +00:00
mkdir -p "$workdir/mnt"
sudo mount "$rootpart" "$workdir/mnt" || { zerr; return 1; }
act "Mounted root partition"
2016-09-29 21:19:15 +00:00
if [[ "$bootfs" = none ]]; then
return
fi
sudo mkdir -p "$workdir/mnt/boot"
sudo mount "$bootpart" "$workdir/mnt/boot" || { zerr; return 1; }
act "Mounted boot partition"
}
2016-09-29 21:19:15 +00:00
image_umount()
{
fn image_umount
req=(workdir loopdevice)
ckreq || return 1
notice "Umounting image from $workdir/mnt"
sudo umount -R "$workdir/mnt" || { zerr; return 1; }
act "Umounted"
2019-02-26 00:04:49 +00:00
act "Flushing bytes and buffers"
sudo blockdev --flushbufs "$loopdevice" || { zerr; return 1; }
sudo python -c 'import os; os.fsync(open("'$loopdevice'", "r+b"))' || { zerr; return 1; }
}
2019-02-26 00:04:49 +00:00
image_disconnect_raw()
{
fn image_disconnect_raw
req=(loopdevice bootfs rootfs bootpart rootpart)
ckreq || return 1
2016-09-29 21:19:15 +00:00
notice "Disconnecting image from $loopdevice"
2017-10-27 18:33:14 +00:00
act "Rechecking filesystems"
case "$bootfs" in
ext?)
sudo e2fsck -fy "$bootpart"
sudo resize2fs "$bootpart"
;;
esac
2016-09-29 21:19:15 +00:00
case "$rootfs" in
ext?)
sudo e2fsck -fy "$rootpart"
sudo resize2fs "$rootpart"
;;
esac
2016-09-29 21:19:15 +00:00
act "Disconnecting"
sudo partx -dv "$loopdevice" >>/dev/null || {
die "partx failed to remove $loopdevice"
zerr; return 1
}
2016-09-29 21:19:15 +00:00
sudo losetup -d "$loopdevice" || {
die "losetup failed to remove $loopdevice"
zerr; return 1
}
2016-09-29 21:19:15 +00:00
}
image_disconnect_qcow2()
{
fn image_disconnect_qcow2
req=(loopdevice bootfs rootfs bootpart rootpart)
2016-09-29 20:36:12 +00:00
ckreq || return 1
notice "Disconnecting image from $loopdevice"
2017-03-18 20:30:58 +00:00
act "Rechecking filesystems"
case "$bootfs" in
ext?)
sudo e2fsck -fy "$bootpart"
sudo resize2fs "$bootpart"
;;
esac
2016-09-29 21:19:15 +00:00
case "$rootfs" in
ext?)
sudo e2fsck -fy "$rootpart"
sudo resize2fs "$rootpart"
;;
esac
2016-09-29 21:19:15 +00:00
act "Disconnecting"
sudo qemu-nbd --disconnect "$loopdevice" || { zerr; return 1; }
2016-09-29 21:19:15 +00:00
}
2017-02-14 16:23:23 +00:00
image_raw_to_qcow2()
{
fn image_raw_to_qcow2
req=(image_name workdir)
2017-02-14 16:23:23 +00:00
ckreq || return 1
notice "Converting raw image to qcow2"
pushd "$workdir" || { zerr; return 1; }
touch "${image_name}.qcow2"
chattr -f +C "${image_name}.qcow2"
qemu-img convert -f raw -O qcow2 "${image_name}.img" "${image_name}.qcow2" || { zerr; return 1; }
2017-02-14 16:23:23 +00:00
popd
}
2017-02-15 13:49:02 +00:00
image_raw_to_vdi()
{
fn image_raw_to_vdi
req=(image_name workdir)
2017-02-15 13:49:02 +00:00
ckreq || return 1
notice "Converting raw image to vdi"
pushd "$workdir" || { zerr; return 1; }
touch "${image_name}.vdi"
chattr -f +C "${image_name}.vdi"
qemu-img convert -f raw -O vdi "${image_name}.img" "${image_name}.vdi" || { zerr; return 1; }
#VBoxManage modifyhd "${image_name}.vdi" --type immutable --compact || { zerr; return 1; }
2017-02-15 13:49:02 +00:00
popd
}
image_pack_dist()
{
fn image_pack_dist
req=(R image_name workdir)
ckreq || return 1
notice "Packing up built images"
local _xzcomp=""
local _rsuffix="img"
if [[ -n "$COMPRESS_IMAGE" ]]; then
if command -v pixz >/dev/null; then
_xzcomp="$(command -v pixz)"
else
_xzcomp="$(command -v xz)"
fi
_rsuffix="img.xz"
fi
pushd "$workdir" || { zerr; return 1; }
if [[ -n "$COMPRESS_IMAGE" ]]; then
act "Compressing images with $_xzcomp"
silly
$_xzcomp "${image_name}.img" || { zerr; return 1; }
# TODO: cpio image?
fi
act "Calculating sha256 checksums"
silly
sha256sum "${image_name}.${_rsuffix}" > "${image_name}.${_rsuffix}.sha256"
# TODO: cpio image?
mkdir -p "$R/dist"
mv -v "${image_name}".* "$R/dist" || { zerr; return 1; }
notice "Done! Thanks for being patient!"
popd
}