#!/usr/bin/env bash export LC_ALL=C # Here the quick 'n dirty guide to adding a new OS to quickget # # 1. Update os_support() - add new OS, all lowercase # 2. Update pretty_name() - add a pretty name for new OS *only if the catch all is not suitable* # 3. Create a releases_newos() generator (required) outputs the current supported release versions # 4. Create a editions_newos() generator (optional) outputs the editions if new OS has multiple flavours/editions # 5. Update make_vm_config() - add any *required* new OS tweaks # 6. Create a get_newos() function - that does something like this: # function get_newos() { # local EDITION="${1:-}" # local HASH="" # local ISO="newos-${RELEASE}-${EDITION}-amd64.iso" # local URL="https://www.newos.org/download/${RELEASE}/${EDITION}" # # HASH=$(wget -q -O- "${URL}/SHA512SUMS" | grep "${ISO}" | cut -d' ' -f1) # echo "${URL}/${ISO} ${HASH}" # } function cleanup() { if [ -n "$(jobs -p)" ]; then kill "$(jobs -p)" fi } function pretty_name() { local SIMPLE_NAME="" local PRETTY_NAME="" SIMPLE_NAME="${1}" case ${SIMPLE_NAME} in alma) PRETTY_NAME="Alma Linux";; alpine) PRETTY_NAME="Alpine Linux";; android) PRETTY_NAME="Android x86";; archlinux) PRETTY_NAME="Arch Linux";; arcolinux) PRETTY_NAME="Arco Linux";; cachyos) PRETTY_NAME="CachyOS";; centos-stream) PRETTY_NAME="CentOS Stream";; dragonflybsd) PRETTY_NAME="DragonFlyBSD";; elementary) PRETTY_NAME="elementary OS";; endeavouros) PRETTY_NAME="EndeavourOS";; freebsd) PRETTY_NAME="FreeBSD";; freedos) PRETTY_NAME="FreeDOS";; garuda) PRETTY_NAME="Garuda Linux";; ghostbsd) PRETTY_NAME="GhostBSD";; kdeneon) PRETTY_NAME="KDE Neon";; kolibrios) PRETTY_NAME="KolibriOS";; linuxmint) PRETTY_NAME="Linux Mint";; lmde) PRETTY_NAME="Linux Mint Debian Edition";; mxlinux) PRETTY_NAME="MX Linux";; netboot) PRETTY_NAME="netboot.xyz";; netbsd) PRETTY_NAME="NetBSD";; nixos) PRETTY_NAME="NixOS";; macos) PRETTY_NAME="macOS";; openbsd) PRETTY_NAME="OpenBSD";; opensuse) PRETTY_NAME="openSUSE";; oraclelinux) PRETTY_NAME="Oracle Linux";; popos) PRETTY_NAME="Pop!_OS";; reactos) PRETTY_NAME="ReactOS";; regolith) PRETTY_NAME="Regolith Linux";; rockylinux) PRETTY_NAME="Rocky Linux";; ubuntu-budgie) PRETTY_NAME="Ubuntu Budgie";; ubuntukylin) PRETTY_NAME="Ubuntu Kylin";; ubuntu-mate) PRETTY_NAME="Ubuntu MATE";; ubuntustudio) PRETTY_NAME="Ubuntu Studio";; void) PRETTY_NAME="Void Linux";; zorin) PRETTY_NAME="Zorin OS";; *) PRETTY_NAME="${SIMPLE_NAME^}";; esac echo "${PRETTY_NAME}" } function validate_release() { local DISPLAY_NAME="" local RELEASE_GENERATOR="" local RELEASES="" DISPLAY_NAME="$(pretty_name "${OS}")" case ${OS} in *ubuntu*) RELEASE_GENERATOR="releases_ubuntu";; *) RELEASE_GENERATOR="${1}";; esac RELEASES=$(${RELEASE_GENERATOR}) if [[ "${RELEASES}" != *"${RELEASE}"* ]]; then echo -e "ERROR! ${DISPLAY_NAME} ${RELEASE} is not a supported release.\n" echo -n "${RELEASES}" exit 1 fi } function list_json() { # Reference: https://stackoverflow.com/a/67359273 list_csv | jq -R 'split(",") as $h|reduce inputs as $in ([]; . += [$in|split(",")|. as $a|reduce range(0,length) as $i ({};.[$h[$i]]=$a[$i])])' exit 0 } function list_csv() { local DISPLAY_NAME local DL="" local DOWNLOADER local FUNC local OPTION local OS local PNG local RELEASE local SVG local HAS_ZSYNC=0 # Check if zsync is available if command -v zsync &>/dev/null; then HAS_ZSYNC=1 fi if command -v aria2c &>/dev/null; then DL="aria2c" elif command -v wget &>/dev/null; then DL="wget" fi echo "Display Name,OS,Release,Option,Downloader,PNG,SVG" for OS in $(os_support); do DISPLAY_NAME="$(pretty_name "${OS}")" if [[ "${OS}" == *"ubuntu"* ]]; then FUNC="ubuntu" else FUNC="${OS}" fi PNG="https://quickemu-project.github.io/quickemu-icons/png/${FUNC}/${FUNC}-quickemu-white-pinkbg.png" SVG="https://quickemu-project.github.io/quickemu-icons/svg/${FUNC}/${FUNC}-quickemu-white-pinkbg.svg" for RELEASE in $("releases_${FUNC}"); do if [ "${OS}" == "macos" ]; then DOWNLOADER="macrecovery" elif [ "${OS}" == "ubuntu" ] && [ "${RELEASE}" == "canary" ] && [ ${HAS_ZSYNC} -eq 1 ]; then DOWNLOADER="zsync" elif [[ "${OS}" == *"ubuntu"* ]] && [ "${RELEASE}" == "devel" ] && [ ${HAS_ZSYNC} -eq 1 ]; then DOWNLOADER="zsync" else DOWNLOADER="${DL}" fi # If the OS has an editions_() function, use it. if [[ $(type -t "editions_${OS}") == function ]]; then for OPTION in $(editions_"${OS}"); do echo "${DISPLAY_NAME},${OS},${RELEASE},${OPTION},${DOWNLOADER},${PNG},${SVG}" done elif [ "${OS}" == "windows" ]; then for OPTION in "${LANGS[@]}"; do echo "${DISPLAY_NAME},${OS},${RELEASE},${OPTION},${DOWNLOADER},${PNG},${SVG}" done else echo "${DISPLAY_NAME},${OS},${RELEASE},,${DOWNLOADER},${PNG},${SVG}" fi done done exit 0 } function os_support() { echo alma \ alpine \ android \ archlinux \ arcolinux \ batocera \ cachyos \ centos-stream \ debian \ deepin \ devuan \ dragonflybsd \ elementary \ endeavouros \ fedora \ freebsd \ freedos \ garuda \ gentoo \ ghostbsd \ haiku \ kali \ kdeneon \ kolibrios \ kubuntu \ linuxmint \ lmde \ manjaro \ mxlinux \ netboot \ netbsd \ nixos \ lubuntu \ macos \ openbsd \ opensuse \ oraclelinux \ popos \ reactos \ regolith \ rockylinux \ slackware \ solus \ tails \ ubuntu \ ubuntu-budgie \ ubuntukylin \ ubuntu-mate \ ubuntustudio \ void \ windows \ xubuntu \ zorin } function releases_alma() { echo 8.6 9.0 } function editions_alma() { echo minimal dvd } function releases_alpine() { echo 3.12 3.13 3.14 3.15 latest } function releases_android() { echo 7.1 8.1 9.0 } function editions_android() { echo x86 x86_64 } function releases_archlinux() { echo latest } function releases_arcolinux() { echo v21.09.11 v21.11.05 v22.01.10 } function editions_arcolinux() { echo large small } function releases_cachyos() { echo 220731 } function editions_cachyos() { echo kde gnome xfce } function releases_centos-stream() { echo 8 9 } function editions_centos-stream() { echo dvd1 boot } function releases_debian() { echo 10.11.0 10.12.0 10.13.0 11.2.0 11.3.0 11.4.0 11.5.0 } function editions_debian() { echo standard cinnamon gnome kde lxde lxqt mate xfce netinst } function releases_deepin() { echo 20 20.1 20.2 20.2.1 20.2.2 20.2.3 20.2.4 20.3 20.4 20.5 20.6 20.7 } function releases_devuan() { echo beowulf chimaera } function releases_dragonflybsd() { echo 6.2.1 } function releases_elementary() { echo 6.1 } function releases_endeavouros() { echo apollo_22_1 \ atlantis-21_4 \ atlantis_neo-21_5 } function releases_fedora() { echo 33 34 35 36 } function releases_batocera() { echo 32 33 34 } function editions_fedora() { echo Workstation \ Cinnamon \ i3 \ KDE \ LXDE \ LXQt \ Mate \ Xfce \ Silverblue \ Server } function releases_freebsd(){ echo 12.3 13.0 } function editions_freebsd(){ echo disc1 dvd1 } function releases_freedos() { echo 1.2 1.3 } function releases_garuda() { echo latest } function editions_garuda() { URL="https://mirrors.fossho.st/garuda/iso/latest/garuda/" echo $(wget -q -O - ${URL} | grep '^/dev/null; then echo "ERROR! Unable to create directory ${DIR}" exit 1 fi if command -v aria2c &>/dev/null; then if ! aria2c --stderr -x16 --continue=true --summary-interval=0 --download-result=hide --console-log-level=error "${URL}" -o "${DIR}/${FILE}"; then echo #Necessary as aria2c in suppressed mode does not have new lines echo "ERROR! Failed to download ${URL} with aria2c. Try running 'quickget' again." exit 1 fi echo #Necessary as aria2c in suppressed mode does not have new lines else if ! wget --quiet --continue --show-progress --progress=bar:force:noscroll "${URL}" -O "${DIR}/${FILE}"; then echo "ERROR! Failed to download ${URL} with wget. Try running 'quickget' again." exit 1 fi fi } function zsync_get() { local DIR="${2}" local FILE="${1##*/}" local OUT="" local URL="${1}" if command -v zsync &>/dev/null; then if [ -n "${3}" ]; then OUT="${3}" else OUT="${FILE}" fi if ! mkdir -p "${DIR}" 2>/dev/null; then echo "ERROR! Unable to create directory ${DIR}" exit 1 fi # Only force http for zsync - not earlier because we might fall through here if ! zsync "${URL/https/http}.zsync" -i "${DIR}/${OUT}" -o "${DIR}/${OUT}" 2>/dev/null; then echo "ERROR! Failed to download ${URL/https/http}.zsync" exit 1 fi if [ -e "${DIR}/${OUT}.zs-old" ]; then rm "${DIR}/${OUT}.zs-old" fi else echo "INFO: zsync not found, falling back to wget/aria2c" if [ -n "${3}" ]; then web_get "${1}" "${2}" "${3}" else web_get "${1}" "${2}" fi fi } function make_vm_config() { local CONF_FILE="" local IMAGE_FILE="" local ISO_FILE="" local IMAGE_TYPE="" local GUEST="" local SEC_BOOT="" IMAGE_FILE="${1}" ISO_FILE="${2}" case "${OS}" in batocera) GUEST="batocera" IMAGE_TYPE="img";; dragonflybsd) GUEST="dragonflybsd" IMAGE_TYPE="iso";; freebsd|ghostbsd) GUEST="freebsd" IMAGE_TYPE="iso";; haiku) GUEST="haiku" IMAGE_TYPE="iso";; freedos) GUEST="freedos" IMAGE_TYPE="iso";; kolibrios) GUEST="kolibrios" IMAGE_TYPE="iso";; macos) GUEST="macos" IMAGE_TYPE="img";; netbsd) GUEST="netbsd" IMAGE_TYPE="iso";; openbsd) GUEST="openbsd" IMAGE_TYPE="iso";; reactos) GUEST="reactos" IMAGE_TYPE="iso";; windows) GUEST="windows" IMAGE_TYPE="iso";; *) GUEST="linux" IMAGE_TYPE="iso";; esac if [ -n "${EDITION}" ]; then CONF_FILE="${OS}-${RELEASE}-${EDITION}.conf" else CONF_FILE="${OS}-${RELEASE}.conf" fi if [ ! -e "${CONF_FILE}" ]; then echo "Making ${CONF_FILE}" cat << EOF > "${CONF_FILE}" #!$(which quickemu) --vm guest_os="${GUEST}" disk_img="${VM_PATH}/disk.qcow2" ${IMAGE_TYPE}="${VM_PATH}/${IMAGE_FILE}" EOF echo "Giving user execute permissions on ${CONF_FILE}," chmod u+x "${CONF_FILE}" if [ -n "${ISO_FILE}" ]; then echo "fixed_iso=\"${VM_PATH}/${ISO_FILE}\"" >> "${CONF_FILE}" fi # OS specific tweaks case ${OS} in alma|centos-stream|oraclelinux|rockylinux) echo "disk_size=\"32G\"" >> "${CONF_FILE}";; batocera) echo "disk_size=\"8G\"" >> "${CONF_FILE}";; dragonflybsd|haiku|openbsd|netbsd|slackware|tails) echo "boot=\"legacy\"" >> "${CONF_FILE}";; deepin) echo "disk_size=\"64G\"" >> "${CONF_FILE}" echo "ram=\"4G\"" >> "${CONF_FILE}" ;; freedos) echo "boot=\"legacy\"" >> "${CONF_FILE}" echo "disk_size=\"4G\"" >> "${CONF_FILE}" echo "ram=\"256M\"" >> "${CONF_FILE}" ;; kolibrios) echo "boot=\"legacy\"" >> "${CONF_FILE}" echo "disk_size=\"2G\"" >> "${CONF_FILE}" echo "ram=\"128M\"" >> "${CONF_FILE}" ;; zorin) case ${EDITION} in education64|edulite64) echo "disk_size=\"32G\"" >> "${CONF_FILE}";; esac ;; reactos) echo "boot=\"legacy\"" >> "${CONF_FILE}" echo "disk_size=\"12G\"" >> "${CONF_FILE}" echo "ram=\"2048M\"" >> "${CONF_FILE}" ;; macos) echo "macos_release=\"${RELEASE}\"" >> "${CONF_FILE}" # https://github.com/quickemu-project/quickemu/issues/438 if [ "${RELEASE}" == "monterey" ]; then echo "cpu_cores=2" >> "${CONF_FILE}" fi ;; esac # Enable TPM for Windows 11 if [ "${OS}" == "windows" ] && [ "${RELEASE}" -ge 11 ]; then echo "tpm=\"on\"" >> "${CONF_FILE}" # Only force SecureBoot on for non-Debian/Ubuntu distros. if [ -e "/usr/share/OVMF/OVMF_CODE_4M.fd" ] && [ -e "/usr/share/OVMF/OVMF_VARS_4M.fd" ]; then SEC_BOOT="off" else SEC_BOOT="on" fi echo "secureboot=\"${SEC_BOOT}\"" >> "${CONF_FILE}" fi fi echo echo "To start your $(pretty_name "${OS}") virtual machine run:" echo " quickemu --vm ${CONF_FILE}" echo exit 0 } function get_alma() { local EDITION="${1:-}" local HASH="" local ISO="AlmaLinux-${RELEASE}-x86_64-${EDITION}.iso" local URL="http://lon.mirror.rackspace.com/almalinux/${RELEASE/beta-1/beta}/isos/x86_64/" HASH="$(wget -q -O- "${URL}/CHECKSUM" | grep "(${ISO}" | cut -d' ' -f4)" echo "${URL}/${ISO} ${HASH}" } function get_alpine() { local HASH="" local ISO="" local URL="" local VERSION="" case ${RELEASE} in latest) URL="https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64";; *) URL="https://dl-cdn.alpinelinux.org/alpine/v${RELEASE}/releases/x86_64";; esac VERSION=$(wget -qO- "${URL}/latest-releases.yaml" | awk '/"Xen"/{found=0} {if(found) print} /"Virtual"/{found=1}' | grep 'version:' | awk '{print $2}') ISO="alpine-virt-${VERSION}-x86_64.iso" HASH=$(wget -qO- "${URL}/latest-releases.yaml" | awk '/"Xen"/{found=0} {if(found) print} /"Virtual"/{found=1}' | grep 'sha256:' | awk '{print $2}') echo "${URL}/${ISO} ${HASH}" } function get_android() { local EDITION="${1:-}" local HASH="" local ISO="" local JSON_ALL="" local JSON_REL="" local URL="https://mirrors.gigenet.com/OSDN/android-x86" JSON_ALL=$(wget -q -O- "https://www.fosshub.com/Android-x86-old.html" | grep "var settings =" | cut -d'=' -f2-) JSON_REL=$(echo "${JSON_ALL}" | jq --arg ver "${OS}-${EDITION}-${RELEASE}" 'first(.pool.f[] | select((.n | startswith($ver)) and (.n | endswith(".iso"))))') ISO=$(echo "${JSON_REL}" | jq -r .n) HASH=$(echo "${JSON_REL}" | jq -r .hash.sha256) # Traverse the directories to find the .iso location for DIR in $(wget -4 -q -O- "${URL}" | grep -o -E '[0-9]{5}' | sort -ur); do if wget -4 -q -O- "${URL}/${DIR}" | grep "${ISO}" &>/dev/null; then URL="${URL}/${DIR}" break fi done echo "${URL}/${ISO} ${HASH}" } function get_archlinux() { local HASH="" local ISO="" local URL="https://mirror.rackspace.com/archlinux" ISO=$(wget -q -O- "https://archlinux.org/releng/releases/json/" | jq -r '.releases[0].iso_url') HASH=$(wget -q -O- "https://archlinux.org/releng/releases/json/" | jq -r '.releases[0].sha1_sum') echo "${URL}/${ISO} ${HASH}" } function get_arcolinux() { local EDITION="${1:-}" local HASH="" local ISO="arcolinux${EDITION:0:1}-${RELEASE}-x86_64.iso" local URL="https://ant.seedhost.eu/arcolinux/iso/${RELEASE}" HASH=$(wget -q -O- "${URL}/${ISO}.sha1" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_batocera() { local HASH="" local URL="https://mirrors.o2switch.fr/batocera/x86_64/stable/last" local ISO="$(curl -sl ${URL}/ | grep -e 'batocera.*img.gz'|cut -d\" -f2)" local CURRENT_RELEASE=$(echo "${ISO}"| cut -d\- -f3) case ${RELEASE} in ${CURRENT_RELEASE}) #Current release URL+="" ;; *) URL+="/archives/${RELEASE}" ISO="$(curl -sl ${URL}/ | grep -e 'batocera.*img.gz'|cut -d\" -f2)" ;; # non-current are here esac echo "${URL}/${ISO} ${HASH}" } function get_cachyos() { local HASH="" local ISO="cachyos-${EDITION}-linux-${RELEASE}.iso" local URL="https://mirror.cachyos.org/ISO/${EDITION}/${RELEASE}" HASH=$(wget -q -O- "${URL}/${ISO}.sha256" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_centos-stream() { local HASH="" local ISO="" case ${RELEASE} in 8) ISO="CentOS-Stream-${RELEASE}-x86_64-latest-${EDITION}.iso" URL="https://mirrors.ocf.berkeley.edu/centos/8-stream/isos/x86_64" HASH=$(wget -q -O- ${URL}/CHECKSUM | grep "SHA256 (${ISO}" | cut -d' ' -f4) ;; 9) ISO="CentOS-Stream-${RELEASE}-latest-x86_64-${EDITION}.iso" URL="https://mirrors.ocf.berkeley.edu/centos-stream/9-stream/BaseOS/x86_64/iso" HASH=$(wget -q -O- ${URL}/${ISO}.SHA256SUM | grep "SHA256 (${ISO}" | cut -d' ' -f4) ;; esac echo "${URL}/${ISO} ${HASH}" } function get_debian() { local EDITION="${1:-}" local HASH="" local ISO="debian-live-${RELEASE}-amd64-${EDITION}.iso" local URL="" case ${RELEASE} in 11.5.0) URL="https://cdimage.debian.org/debian-cd/${RELEASE}-live/amd64/iso-hybrid";; *) URL="https://cdimage.debian.org/cdimage/archive/${RELEASE}-live/amd64/iso-hybrid/";; esac if [ "${EDITION}" == "netinst" ]; then URL="${URL/-live/}" URL="${URL/hybrid/cd}" ISO="${ISO/-live/}" fi HASH=$(wget -q -O- "${URL}/SHA512SUMS" | grep "${ISO}" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_deepin() { local HASH="" local EDITION="" local ISO="deepin-desktop-community-${RELEASE}-amd64.iso" # deepin-desktop-community-20.3-amd64.iso local URL="https://cdimage.deepin.com/releases/"${RELEASE} # fix iso name if [[ "${RELEASE}" == *"20" ]] ; then EDITION="1003" ISO="deepin-desktop-community-${EDITION}-amd64.iso" elif [[ "${RELEASE}" == *"20.1" ]]; then EDITION="1010" ISO="deepin-desktop-community-${EDITION}-amd64.iso" fi HASH=$(wget -q -O- "${URL}/SHA256SUMS" | grep "${ISO}" | cut -d' ' -f1) #echo "${URL}/${ISO} ${HASH}" web_get "${URL}/${ISO}" "${VM_PATH}" check_hash "${ISO}" "${HASH}" make_vm_config "${ISO}" } function get_devuan() { local HASH="" local ISO="" local URL="https://files.devuan.org/devuan_${RELEASE}/desktop-live" case ${RELEASE} in beowulf) ISO="devuan_${RELEASE}_3.1.1_amd64_desktop-live.iso";; chimaera) ISO="devuan_${RELEASE}_4.0.2_amd64_desktop-live.iso";; esac HASH=$(wget -q -O- "${URL}/SHASUMS.txt" | grep "${ISO}" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_dragonflybsd() { local HASH="" local ISO="dfly-x86_64-${RELEASE}_REL.iso" local URL="http://mirror-master.dragonflybsd.org/iso-images" HASH=$(wget -q -O- "${URL}/md5.txt" | grep "(${ISO})" | cut -d' ' -f4) echo "${URL}/${ISO} ${HASH}" } function get_elementary() { local HASH="" local ISO="elementaryos-${RELEASE}-stable.20211218-rc.iso" local URL="https://ams3.dl.elementary.io/download" echo "${URL}/$(date +%s | base64)/${ISO} ${HASH}" } function get_endeavouros() { local HASH="" # Endeavour release names are Capitalized and our $RELEASE is forced to lowercase so we have to revert it local ISO="EndeavourOS_${RELEASE@u}.iso" local URL="https://github.com/endeavouros-team/ISO/releases/download/1-EndeavourOS-ISO-releases-archive" HASH=$(wget -q -O- "${URL}/${ISO}.sha512sum" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_fedora() { local EDITION="${1:-}" local HASH="" local ISO="" local JSON="" local URL="" local VARIANT="" case ${EDITION} in Server|Silverblue|Workstation) VARIANT="${EDITION}";; *) VARIANT="Spins";; esac JSON=$(wget -q -O- "https://getfedora.org/releases.json" | jq '.[] | select(.variant=="'${VARIANT}'" and .subvariant=="'"${EDITION}"'" and .arch=="x86_64" and .version=="'"${RELEASE}"'")') URL=$(echo "${JSON}" | jq -r '.link' | head -n1) HASH=$(echo "${JSON}" | jq -r '.sha256' | head -n1) echo "${URL} ${HASH}" } function get_freebsd() { local EDITION="${1}" local HASH="" local ISO="FreeBSD-${RELEASE}-RELEASE-amd64-${EDITION}.iso" local URL="https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/${RELEASE}" HASH=$(wget -q -O- "${URL}/CHECKSUM.SHA256-FreeBSD-${RELEASE}-RELEASE-amd64" | grep "${ISO}" | grep -v ".xz" | cut -d' ' -f4) echo "${URL}/${ISO} ${HASH}" } function get_freedos() { local HASH="" local ISO="" local URL="http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/distributions/${RELEASE}/official" case ${RELEASE} in 1.2) ISO="FD12CD.iso" HASH=$(wget -q -O- "${URL}/FD12.sha" | grep "${ISO}" | cut -d' ' -f1) ;; 1.3) ISO="FD13-LiveCD.zip" HASH=$(wget -q -O- "${URL}/verify.txt" | grep -A 8 "sha256sum" | grep "${ISO}" | cut -d' ' -f1) ;; esac echo "${URL}/${ISO} ${HASH}" } function get_garuda() { local EDITION="${1:-}" local HASH="" local ISO="" local URL="https://mirrors.fossho.st/garuda/iso/latest/garuda/" ISO=${EDITION}/latest.iso HASH="$(wget -q -O- "${URL}/${ISO}.sha256" | cut -d' ' -f1)" echo "${URL}/${ISO} ${HASH}" } function get_gentoo() { local HASH="" local ISO="" local URL="https://mirror.bytemark.co.uk/gentoo/releases/amd64/autobuilds/" ISO=$(wget -q -O- "${URL}/${RELEASE}-iso.txt" | grep install | cut -d' ' -f1) HASH=$( wget -q -O- "${URL}/${ISO}.DIGESTS" | grep iso | grep -v CONTENTS | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_ghostbsd() { local EDITION="${1:-}" local ISO="" local URL="https://download.ghostbsd.org/releases/amd64/${RELEASE}" local HASH="" case ${EDITION} in mate) ISO="GhostBSD-${RELEASE}.iso";; xfce) ISO="GhostBSD-${RELEASE}-XFCE.iso";; esac HASH=$(wget -q -O- "${URL}/${ISO}.sha256" | grep "${ISO}" | cut -d' ' -f4) echo "${URL}/${ISO} ${HASH}" } function get_haiku() { local EDITION="${1:-}" local ISO="haiku-${RELEASE}-${EDITION}-anyboot.iso" # local URL="https://cdn.haiku-os.org/haiku-release/${RELEASE}" # domain gone local URL="http://mirror.rit.edu/haiku/${RELEASE}" # NY, USA # local URL="https://mirrors.tnonline.net/haiku/haiku-release/${RELEASE}" # Sweden # local URL="https://mirror.aarnet.edu.au/pub/haiku/${RELEASE}" # Aus HASH=$(wget -q -O- "${URL}/${ISO}.sha256" | grep "${ISO}" | cut -d' ' -f4) echo "${URL}/${ISO} ${HASH}" } function get_kali() { local HASH="" local ISO="" local URL="https://cdimage.kali.org/${RELEASE}" ISO=$(wget -q -O- "${URL}/?C=M;O=D" | grep -o ">kali-linux-.*-installer-amd64.iso" | head -n 1 | cut -c 2-) HASH=$(wget -q -O- "${URL}/SHA256SUMS" | grep -v torrent | grep "${ISO}" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_kdeneon() { local HASH="" local ISO="" local URL="https://files.kde.org/neon/images/${RELEASE}/current" ISO=$(wget -q -O- "${URL}/neon-${RELEASE}-current.sha256sum" | cut -d' ' -f3-) HASH=$(wget -q -O- "${URL}/neon-${RELEASE}-current.sha256sum" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_kolibrios() { local HASH="" local ISO="kolibri.iso" local URL="https://builds.kolibrios.org/eng" echo "${URL}/${ISO} ${HASH}" } function get_linuxmint() { local EDITION="${1:-}" local HASH="" local ISO="linuxmint-${RELEASE}-${EDITION}-64bit.iso" local URL="https://mirror.bytemark.co.uk/linuxmint/stable/${RELEASE}" HASH=$(wget -q -O- "${URL}/sha256sum.txt" | grep "${ISO}" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_lmde() { local EDITION="${1:-}" local HASH="" local ISO="lmde-${RELEASE}-${EDITION}-64bit.iso" local URL="https://mirror.bytemark.co.uk/linuxmint/debian" HASH=$(wget -q -O- "${URL}/sha256sum.txt" | grep "${ISO}" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_macos() { local BOARD_ID="" local CWD="" local MACRECOVERY="" local MLB="00000000000000000" local OS_TYPE="default" case ${RELEASE} in high-sierra) BOARD_ID="Mac-7BA5B2D9E42DDD94" MLB="00000000000J80300";; mojave) BOARD_ID="Mac-7BA5B2DFE22DDD8C" MLB="00000000000KXPG00";; catalina) BOARD_ID="Mac-C3EC7CD22292981F" MLB="00000000000PHCD00";; big-sur) BOARD_ID="Mac-3CBD00234E554E41";; monterey) BOARD_ID="Mac-06F11F11946D27C5" MLB="00000000000000000";; *) echo "ERROR! Unknown release: ${RELEASE}" releases_macos exit 1;; esac # Use a bundled macrecovery if possible CWD="$(dirname "${0}")" if [ -x "${CWD}/macrecovery" ]; then MACRECOVERY="${CWD}/macrecovery" elif [ -x /usr/bin/macrecovery ]; then MACRECOVERY="/usr/bin/macrecovery" else web_get "https://raw.githubusercontent.com/wimpysworld/quickemu/master/macrecovery" "${HOME}/.quickemu" MACRECOVERY="python3 ${HOME}/.quickemu/macrecovery" fi if [ -z "${MACRECOVERY}" ]; then echo "ERROR! Can not find a usable macrecovery." exit 1 fi # Get firmware web_get "https://github.com/kholia/OSX-KVM/raw/master/OpenCore/OpenCore.qcow2" "${VM_PATH}" web_get "https://github.com/kholia/OSX-KVM/raw/master/OVMF_CODE.fd" "${VM_PATH}" if [ ! -e "${VM_PATH}/OVMF_VARS-1024x768.fd" ]; then web_get "https://github.com/kholia/OSX-KVM/raw/master/OVMF_VARS-1024x768.fd" "${VM_PATH}" fi if [ ! -e "${VM_PATH}/RecoveryImage.chunklist" ]; then echo "Downloading ${RELEASE}..." ${MACRECOVERY} \ --board-id "${BOARD_ID}" \ --mlb "${MLB}" \ --os-type "${OS_TYPE}" \ --basename RecoveryImage \ --outdir "${VM_PATH}" \ download fi if [ -e "${VM_PATH}/RecoveryImage.dmg" ] && [ ! -e "${VM_PATH}/RecoveryImage.img" ]; then echo "Converting RecoveryImage..." qemu-img convert "${VM_PATH}/RecoveryImage.dmg" -O raw "${VM_PATH}/RecoveryImage.img" fi make_vm_config RecoveryImage.img } function get_manjaro() { local HASH="" local ISO="" local MANIFESTURL="" local URL="" case ${RELEASE} in gnome|kde|xfce) MANIFESTURL="https://gitlab.manjaro.org/webpage/manjaro-homepage/-/raw/master/site/content/downloads/official/${RELEASE}.md";; budgie|cinnamon|deepin|i3|mate) MANIFESTURL="https://gitlab.manjaro.org/webpage/manjaro-homepage/-/raw/master/site/content/downloads/community/${RELEASE}.md";; esac URL="$(wget -qO- "${MANIFESTURL}" | grep "Download_x64 =" | cut -d'"' -f2)" HASH=$(wget -qO- "${MANIFESTURL}" | grep "Download_x64_Checksum =" | cut -d'"' -f2) echo "${URL} ${HASH}" } function get_mxlinux() { local EDITION="${1:-}" local HASH="" local ISO="" local URL="https://sourceforge.net/projects/mx-linux/files/Final/${EDITION}" case ${EDITION} in Xfce) ISO="MX-${RELEASE}_x64.iso";; KDE) ISO="MX-${RELEASE}_KDE_x64.iso";; Fluxbox) ISO="MX-${RELEASE}_fluxbox_x64.iso";; esac HASH=$(wget -q -O- "${URL}/${ISO}.sha256" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_netboot() { local ISO="netboot.xyz.iso" local HASH="" local URL="https://boot.netboot.xyz/ipxe" HASH=$(wget -q -O- "${URL}/netboot.xyz-sha256-checksums.txt" | grep "${ISO}" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_netbsd() { local HASH="" local ISO="NetBSD-${RELEASE}-amd64.iso" local URL="https://cdn.netbsd.org/pub/NetBSD/NetBSD-${RELEASE}/images/" HASH=$(wget -q -O- "${URL}/MD5" | grep "${ISO}" | cut -d' ' -f4) echo "${URL}/${ISO} ${HASH}" } function get_nixos() { local EDITION="${1:-}" local HASH="" local ISO="latest-nixos-${EDITION}-x86_64-linux.iso" local URL="https://channels.nixos.org/nixos-${RELEASE}" HASH=$(wget -q -O- "${URL}/${ISO}.sha256" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_openbsd() { local HASH="" local ISO="install${RELEASE//\./}.iso" local URL="https://cdn.openbsd.org/pub/OpenBSD/${RELEASE}/amd64" HASH=$(wget -q -O- "${URL}/SHA256" | grep "${ISO}" | cut -d' ' -f4) echo "${URL}/${ISO} ${HASH}" } function get_opensuse() { local HASH="" local ISO="" local URL="" if [ "${RELEASE}" == "tumbleweed" ]; then ISO="openSUSE-Tumbleweed-DVD-x86_64-Current.iso" URL="https://download.opensuse.org/tumbleweed/iso" elif [ "${RELEASE}" == "microos" ]; then ISO="openSUSE-MicroOS-DVD-x86_64-Current.iso" URL="https://download.opensuse.org/tumbleweed/iso" elif [ "$RELEASE" == 15.0 ] || [ "$RELEASE" == 15.1 ]; then ISO="openSUSE-Leap-${RELEASE}-DVD-x86_64.iso" URL="https://download.opensuse.org/distribution/leap/${RELEASE}/iso" else ISO="openSUSE-Leap-${RELEASE}-DVD-x86_64-Current.iso" URL="https://download.opensuse.org/distribution/leap/${RELEASE}/iso" fi HASH=$(wget -q -O- "${URL}/${ISO}.sha256" |awk '{if(NR==4) print $0}'|cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_oraclelinux() { local HASH="" local ISO="" local VER_MAJ=${RELEASE::1} local VER_MIN=${RELEASE:2:1} local URL="https://yum.oracle.com/ISOS/OracleLinux/OL${VER_MAJ}/u${VER_MIN}/x86_64/" case ${VER_MAJ} in 7) ISO="OracleLinux-R${VER_MAJ}-U${VER_MIN}-Server-x86_64-dvd.iso";; *) ISO="OracleLinux-R${VER_MAJ}-U${VER_MIN}-x86_64-dvd.iso";; esac HASH=$(wget -q -O- "https://linux.oracle.com/security/gpg/checksum/OracleLinux-R${VER_MAJ}-U${VER_MIN}-Server-x86_64.checksum" | grep "${ISO}" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_popos() { local EDITION="${1:-}" local HASH="" local ISO="" local URL="" URL=$(wget -q -O- "https://api.pop-os.org/builds/${RELEASE}/${EDITION}" | jq -r .url) HASH=$(wget -q -O- "https://api.pop-os.org/builds/${RELEASE}/${EDITION}" | jq -r .sha_sum) echo "${URL} ${HASH}" } function get_reactos() { local HASH="" local URL="" local TMPURL="" TMPURL=$(wget -q -S -O- --max-redirect=0 "https://sourceforge.net/projects/reactos/files/latest/download" 2>&1 | grep Location | cut -d' ' -f4) URL=${TMPURL%\?*} echo "${URL} ${HASH}" } function get_regolith() { local EDITION="${1:-}" local HASH="" local ISO="Regolith_${EDITION}_${RELEASE}.iso" local URL="" case ${EDITION} in 1.6.0) URL="https://github.com/regolith-linux/regolith-ubuntu-iso-builder/releases/download/release-release-${RELEASE}-${RELEASE}_standard-${EDITION}";; 2.0.0) URL="https://github.com/regolith-linux/regolith-ubuntu-iso-builder/releases/download/regolith-linux-2.0-${RELEASE}-latest";; esac HASH=$(wget -q -O- "${URL}/SHA256SUMS" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_rockylinux() { local EDITION="${1:-}" local HASH="" local ISO="Rocky-${RELEASE}-x86_64-${EDITION}.iso" local URL="" case ${RELEASE} in 9.0) URL="https://download.rockylinux.org/pub/rocky/${RELEASE}/isos/x86_64";; *) URL="http://dl.rockylinux.org/vault/rocky/${RELEASE}/isos/x86_64/";; esac HASH=$(wget -q -O- "${URL}/CHECKSUM" | grep "SHA256" | grep "${ISO})" | cut -d' ' -f4) echo "${URL}/${ISO} ${HASH}" } function get_slackware() { local HASH="" local ISO="slackware64-${RELEASE}-install-dvd.iso" local URL="https://slackware.nl/slackware/slackware-iso/slackware64-${RELEASE}-iso" HASH=$(wget -q -O- "${URL}/${ISO}.md5" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_solus() { local EDITION="${1:-}" local HASH="" local ISO="Solus-${RELEASE}-${EDITION}.iso" local URL="https://mirrors.rit.edu/solus/images/${RELEASE}" HASH=$(wget -q -O- "${URL}/${ISO}.sha256sum" | cut -d' ' -f1) echo "${URL}/${ISO} ${HASH}" } function get_tails() { local ISO="" local JSON="" local HASH="" local URL="" JSON="$(wget -q -O- "https://tails.boum.org/install/v2/Tails/amd64/${RELEASE}/latest.json")" URL=$(echo "${JSON}" | jq -r '.installations[0]."installation-paths"[]|select(.type=="iso")|."target-files"[0].url') HASH=$(echo "${JSON}" | jq -r '.installations[0]."installation-paths"[]|select(.type=="iso")|."target-files"[0].sha256') echo "${URL} ${HASH}" } function get_ubuntu() { local ISO="" local HASH="" local URL="" if [[ "${RELEASE}" == *"daily"* ]] && [ "${OS}" == "ubuntustudio" ]; then # Ubuntu Studio daily-live images are in the dvd directory RELEASE="dvd" elif [ "${RELEASE}" == "daily-canary" ] && [ "${OS}" != "ubuntu" ]; then # daily-canary is only available for Ubuntu, switch flavours to daily-live RELEASE="daily-live" fi if [[ "${RELEASE}" == "eol-"* ]]; then URL="https://old-releases.ubuntu.com/releases/${RELEASE/eol-/}" elif [[ "${RELEASE}" == "jammy-daily" ]]; then URL="https://cdimage.ubuntu.com/${OS}/jammy/daily-live/current" VM_PATH="${OS}-jammy-live" elif [[ "${RELEASE}" == *"daily"* ]] || [ "${RELEASE}" == "dvd" ]; then URL="https://cdimage.ubuntu.com/${OS}/${RELEASE}/current" VM_PATH="${OS}-daily-live" elif [ "${OS}" == "ubuntu" ]; then URL="https://releases.ubuntu.com/${RELEASE}" else URL="https://cdimage.ubuntu.com/${OS}/releases/${RELEASE}/release" fi if wget -q --spider "${URL}/SHA256SUMS"; then ISO=$(wget -q -O- "${URL}/SHA256SUMS" | grep 'desktop\|dvd\|install' | grep amd64 | grep iso | cut -d'*' -f2) HASH=$(wget -q -O- "${URL}/SHA256SUMS" | grep 'desktop\|dvd\|install' | grep amd64 | grep iso |cut -d' ' -f1) else ISO=$(wget -q -O- "${URL}/MD5SUMS" | grep 'desktop\|dvd\|install' | grep amd64 | grep iso | cut -d' ' -f3) HASH=$(wget -q -O- "${URL}/MD5SUMS" | grep 'desktop\|dvd\|install' | grep amd64 | grep iso | cut -d' ' -f1) fi #echo "${URL}/${ISO} ${HASH}" if [[ "${RELEASE}" == *"daily"* ]] || [ "${RELEASE}" == "dvd" ]; then zsync_get "${URL}/${ISO}" "${VM_PATH}" "${OS}-devel.iso" make_vm_config "${OS}-devel.iso" else web_get "${URL}/${ISO}" "${VM_PATH}" check_hash "${ISO}" "${HASH}" make_vm_config "${ISO}" fi } function get_void() { local DATE="" local EDITION="${1:-}" local HASH="" local ISO="" local URL="https://alpha.de.repo.voidlinux.org/live/current" DATE=$(wget -q -O- "${URL}/sha256sum.txt" | head -n1 | cut -d'.' -f1 | cut -d'-' -f4) case ${EDITION} in glibc) ISO="void-live-x86_64-${DATE}.iso";; musl) ISO="void-live-x86_64-musl-${DATE}.iso";; xfce-glibc) ISO="void-live-x86_64-${DATE}-xfce.iso";; xfce-musl) ISO="void-live-x86_64-musl-${DATE}-xfce.iso";; esac HASH="$(wget -q -O- "${URL}/sha256sum.txt" | grep "${ISO}" | cut -d' ' -f4)" echo "${URL}/${ISO} ${HASH}" } function get_zorin() { local EDITION="${1:-}" local HASH="" local ISO="" local URL="" # Parse out the iso URL from the redirector URL=$(wget -q -S -O- --max-redirect=0 "https://zrn.co/${RELEASE}${EDITION}" 2>&1 | grep Location | cut -d' ' -f4) echo "${URL} ${HASH}" } function unattended_windows() { cat << 'EOF' > "${1}" false * true 1 true * Quickemu Project Quickemu 24/7 Quickemu Project https://github.com/quickemu-project/quickemu/issues Quickemu Project W269N-WFGWX-YVC9B-4J6C9-T83GX 0 false 0 true 1 Primary 256 2 EFI 128 3 MSR 128 4 Primary true 1 1 NTFS DE94BBA4-06D1-4D40-A16A-BFD50179D6AC 2 2 FAT32 3 3 4 4 C NTFS true Never 0 4 false 1 reg add HKLM\System\Setup\LabConfig /v BypassCPUCheck /t REG_DWORD /d 0x00000001 /f 2 reg add HKLM\System\Setup\LabConfig /v BypassRAMCheck /t REG_DWORD /d 0x00000001 /f 3 reg add HKLM\System\Setup\LabConfig /v BypassSecureBootCheck /t REG_DWORD /d 0x00000001 /f 4 reg add HKLM\System\Setup\LabConfig /v BypassTPMCheck /t REG_DWORD /d 0x00000001 /f false Never true Quickemu Quickemu Project W269N-WFGWX-YVC9B-4J6C9-T83GX Never E:\qemufwcfg\w10\amd64 E:\vioinput\w10\amd64 E:\vioscsi\w10\amd64 E:\viostor\w10\amd64 E:\vioserial\w10\amd64 E:\qxldod\w10\amd64 E:\amd64\w10 E:\viogpudo\w10\amd64 E:\viorng\w10\amd64 E:\NetKVM\w10\amd64 E:\viofs\w10\amd64 E:\Balloon\w10\amd64 quickemu true</PlainText> </Password> <Enabled>true</Enabled> <Username>Quickemu</Username> </AutoLogon> <DisableAutoDaylightTimeSet>false</DisableAutoDaylightTimeSet> <OOBE> <HideEULAPage>true</HideEULAPage> <HideLocalAccountScreen>true</HideLocalAccountScreen> <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> <HideOnlineAccountScreens>true</HideOnlineAccountScreens> <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> <NetworkLocation>Home</NetworkLocation> <ProtectYourPC>3</ProtectYourPC> <SkipUserOOBE>true</SkipUserOOBE> <SkipMachineOOBE>true</SkipMachineOOBE> <VMModeOptimizations> <SkipWinREInitialization>true</SkipWinREInitialization> </VMModeOptimizations> </OOBE> <UserAccounts> <LocalAccounts> <LocalAccount wcm:action="add"> <Password> <Value>quickemu</Value> <PlainText>true</PlainText> </Password> <Description>Quickemu</Description> <DisplayName>Quickemu</DisplayName> <Group>Administrators</Group> <Name>Quickemu</Name> </LocalAccount> </LocalAccounts> </UserAccounts> <RegisteredOrganization>Quickemu Project</RegisteredOrganization> <RegisteredOwner>Quickemu</RegisteredOwner> <FirstLogonCommands> <SynchronousCommand wcm:action="add"> <CommandLine>msiexec /i E:\guest-agent\qemu-ga-x86_64.msi /quiet /passive /qn</CommandLine> <Description>Install Virtio Guest Agent</Description> <Order>1</Order> </SynchronousCommand> <SynchronousCommand wcm:action="add"> <CommandLine>msiexec /i F:\spice-webdavd-x64-latest.msi /quiet /passive /qn</CommandLine> <Description>Install spice-webdavd file sharing agent</Description> <Order>2</Order> </SynchronousCommand> <SynchronousCommand wcm:action="add"> <CommandLine>msiexec /i F:\UsbDk_1.0.22_x64.msi /quiet /passive /qn</CommandLine> <Description>Install usbdk USB sharing agent</Description> <Order>3</Order> </SynchronousCommand> <SynchronousCommand wcm:action="add"> <CommandLine>msiexec /i F:\spice-vdagent-x64-0.10.0.msi /quiet /passive /qn</CommandLine> <Description>Install spice-vdagent SPICE agent</Description> <Order>4</Order> </SynchronousCommand> <SynchronousCommand wcm:action="add"> <CommandLine>Cmd /c POWERCFG -H OFF</CommandLine> <Description>Disable Hibernation</Description> <Order>5</Order> </SynchronousCommand> </FirstLogonCommands> </component> </settings> </unattend> EOF } function dbg_windows() { local DEBUG=0 if [ ${DEBUG} -eq 1 ]; then echo "${1}" fi } # Adapted from https://gist.github.com/hongkongkiwi/15a5bf16437315df256c118c163607cb function get_windows() { local ARCH="x64" local INDEX=0 local LANG_CODE="en" local LANG_EDITION="${1}" local LATEST_WINDOWS_VERSION="" local WINDOWS_NAME="" local VERSION_ID="" local EDITION_ID="" local LANGUAGE_ID="" local FILE_NAME="" local ARCH_ID="" local DOWNLOAD_INFO="" local DOWNLOAD_ID="" local DOWNLOAD_URL="" # Ignore the most recent Windows 10 release for now. case ${RELEASE} in 10) INDEX=0;; 11) INDEX=0;; esac echo "Getting Windows ${RELEASE} URL..." WINDOWS_VERSIONS=$(wget -4 -q -O- "https://tb.rg-adguard.net/php/get_version.php?type_id=1" | jq '.versions | sort_by(-(.version_id | tonumber))') dbg_windows "${WINDOWS_VERSIONS}" LATEST_WINDOWS_VERSION=$(echo "${WINDOWS_VERSIONS}" | jq -c 'map(select(.name | contains("Windows '"${RELEASE}"'")))['${INDEX}']') dbg_windows "${LATEST_WINDOWS_VERSION}" WINDOWS_NAME=$(echo "${LATEST_WINDOWS_VERSION}" | jq -r .name) dbg_windows "${WINDOWS_NAME}" VERSION_ID=$(echo "${LATEST_WINDOWS_VERSION}" | jq -r .version_id) dbg_windows "${VERSION_ID}" case ${RELEASE} in 8) EDITION_ID=$(wget -4 -q -O- "https://tb.rg-adguard.net/php/get_edition.php?version_id=${VERSION_ID}&lang=name_${LANG_CODE}" | jq -r '.editions[] | select(.name_'${LANG_CODE}'=="Windows 8.1 Pro + Core").edition_id');; 10|11) EDITION_ID=$(wget -4 -q -O- "https://tb.rg-adguard.net/php/get_edition.php?version_id=${VERSION_ID}&lang=name_${LANG_CODE}" | jq -r '.editions[] | select(.name_'${LANG_CODE}'=="Windows '"${RELEASE}"'").edition_id');; esac dbg_windows "${EDITION_ID}" LANGUAGE_ID=$(wget -4 -q -O- "https://tb.rg-adguard.net/php/get_language.php?edition_id=${EDITION_ID}&lang=name_${LANG_CODE}" | jq -r '.languages[] | select(.name_'${LANG_CODE}'=="'"${LANG_EDITION}"'").language_id') dbg_windows "${LANGUAGE_ID}" ARCH_INFO=$(wget -4 -q -O- "https://tb.rg-adguard.net/php/get_arch.php?language_id=${LANGUAGE_ID}") dbg_windows "${ARCH_INFO}" FILE_NAME=$(echo "${ARCH_INFO}" | jq -r '.archs[] | select(.name | contains("'${ARCH}'")).name') dbg_windows "${FILE_NAME}" ARCH_ID=$(echo "${ARCH_INFO}" | jq -r '.archs[] | select(.name | contains("'${ARCH}'")).arch_id') dbg_windows "${ARCH_ID}" DOWNLOAD_INFO=$(wget -4 -q -O- "https://tb.rg-adguard.net/dl.php?fileName=${ARCH_ID}&lang=en") dbg_windows "${DOWNLOAD_INFO}" DOWNLOAD_SHA1=$(echo "${DOWNLOAD_INFO}" | sed -e 's/<[^>]*>//g' | grep -o -P '(?<=SHA1: ).*(?= expire)' | sed 's/Link//') dbg_windows "${DOWNLOAD_SHA1}" DOWNLOAD_ID=$(echo "${DOWNLOAD_INFO}" | grep -oP '(?<=https:\/\/tb\.rg-adguard\.net/dl\.php\?go=)[0-9a-z]+') dbg_windows "${DOWNLOAD_ID}" REDIRECT_URL="https://tb.rg-adguard.net/dl.php?go=${DOWNLOAD_ID}" dbg_windows "${REDIRECT_URL}" DOWNLOAD_URL=$(curl --head --silent --write-out "%{redirect_url}\n" --output /dev/null "${REDIRECT_URL}") dbg_windows "${DOWNLOAD_URL}" MS_BASE_URL="https://software.download.prss.microsoft.com/" if [[ ! ${DOWNLOAD_URL} =~ ^${MS_BASE_URL} ]]; then echo "Download URL not leading to Microsoft CDN" exit 1 fi echo "Downloading ${WINDOWS_NAME}..." web_get "${DOWNLOAD_URL}" "${VM_PATH}" "${FILE_NAME}" # Windows 10 doesn't include a SHA1, so only check the integrity if the SHA1 is available. if [ -n "${DOWNLOAD_SHA1}" ]; then check_hash "${FILE_NAME}" "${DOWNLOAD_SHA1}" fi web_get "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso" "${VM_PATH}" rm -f "${VM_PATH}/unattended.iso" case ${RELEASE} in 10|11) echo "Making unattended.iso" mkdir -p "${VM_PATH}/unattended" 2>/dev/null web_get https://www.spice-space.org/download/windows/spice-webdavd/spice-webdavd-x64-latest.msi "${VM_PATH}/unattended" web_get https://www.spice-space.org/download/windows/vdagent/vdagent-win-0.10.0/spice-vdagent-x64-0.10.0.msi "${VM_PATH}/unattended" web_get https://www.spice-space.org/download/windows/usbdk/UsbDk_1.0.22_x64.msi "${VM_PATH}/unattended" unattended_windows "${VM_PATH}/unattended/autounattend.xml" mkisofs -quiet -l -o "${VM_PATH}/unattended.iso" "${VM_PATH}/unattended/" ;; esac make_vm_config "${FILE_NAME}" "virtio-win.iso" } create_vm() { # shellcheck disable=SC2206 local URL_HASH=(${1// / }) local URL="${URL_HASH[0]}" local HASH="${URL_HASH[1]}" local ISO="${URL##*/}" #echo "${URL}" #echo "${ISO}" #echo "${HASH}" web_get "${URL}" "${VM_PATH}" if [ -n "${HASH}" ]; then check_hash "${ISO}" "${HASH}" fi if [ ${OS} == "freedos" ] && [[ $ISO =~ ".zip" ]]; then unzip ${VM_PATH}/${ISO} -d ${VM_PATH} ISO=$(ls ${VM_PATH} | grep -i '.iso') fi if [[ ${OS} == "batocera" ]] && [[ ${ISO} =~ ".gz" ]]; then gzip -d "${VM_PATH}/${ISO}" ISO="${ISO/.gz/}" fi if [ ${OS} == "reactos" ] && [[ $ISO =~ ".zip" ]]; then unzip ${VM_PATH}/${ISO} -d ${VM_PATH} ISO=$(ls ${VM_PATH} | grep -i '.iso' | grep -v '.zip') fi make_vm_config "${ISO}" } trap cleanup EXIT if ((BASH_VERSINFO[0] < 4)); then echo "Sorry, you need bash 4.0 or newer to run this script." exit 1 fi LANGS=() languages_windows if [ -n "${1}" ]; then OS="${1,,}" if [ "${OS}" == "list" ] || [ "${OS}" == "list_csv" ]; then list_csv elif [ "${OS}" == "list_json" ]; then list_json elif [ "${OS}" == "--version" ] || [ "${OS}" == "-version" ] || [ "${OS}" == "version" ]; then WHERE=$(dirname "${BASH_SOURCE[0]}") "${WHERE}/quickemu" --version exit 0 fi else echo "ERROR! You must specify an operating system." echo -n " - Operating Systems: " os_support exit 1 fi if [[ ! $(os_support) =~ ${OS} ]]; then echo -e "ERROR! ${OS} is not a supported OS.\n" os_support exit 1 fi if [ -n "${2}" ]; then RELEASE="${2,,}" VM_PATH="${OS}-${RELEASE}" # If the OS has an editions_() function, use it. if [[ $(type -t "editions_${OS}") == function ]]; then EDITIONS=($(editions_${OS})) EDITION=${EDITIONS[0]} if [ -n "${3}" ]; then EDITION="${3}" if [[ ! ${EDITIONS[*]} =~ ${EDITION} ]]; then echo -e "ERROR! ${EDITION} is not a supported $(pretty_name "${OS}") edition:\n" for EDITION in "${EDITIONS[@]}"; do echo -n "${EDITION} " done exit 1 fi fi # Workaround for Regolith if [ "${OS}" == "regolith" ]; then if [ "${RELEASE}" == "focal" ] && [ "${EDITION}" == "2.0.0" ]; then echo "WARNING! $(pretty_name "${OS}") ${EDITION} is not available for ${RELEASE}" EDITION="1.6.0" echo " - Setting edition to: ${EDITION}" elif [ "${RELEASE}" == "impish" ] && [ "${EDITION}" == "1.6.0" ]; then echo "WARNING! $(pretty_name "${OS}") ${EDITION} is not available for ${RELEASE}" EDITION="2.0.0" echo " - Setting edition to: ${EDITION}" fi fi # Handle odd missing fedora cominations if [[ $OS == fedora ]] ; then if [[ ${RELEASE} = "33" && ${EDITION} = "i3" ]] || [[ ${RELEASE} = "34" && ${EDITION} = "Cinnamon" ]] ; then echo "ERROR! Unsupported combination" echo " Fedora 33 i3 and Fedora 34 Cinnamon are not available, please choose another Release or Edition" exit 1; fi fi VM_PATH="${OS}-${RELEASE}-${EDITION}" validate_release "releases_${OS}" create_vm "$("get_${OS}" "${EDITION}")" elif [ "${OS}" == "macos" ]; then # macOS doesn't use create_vm() validate_release releases_macos get_macos elif [[ "${OS}" == *"ubuntu"* ]]; then # Ubuntu doesn't use create_vm() validate_release releases_ubuntu get_ubuntu elif [[ "${OS}" == *"deepin"* ]]; then # deepin doesn't use create_vm() validate_release releases_deepin get_deepin elif [ "${OS}" == "windows" ]; then LANG="English International" if [ -n "${3}" ]; then LANG="${3}" if [[ ! ${LANGS[*]} =~ "${LANG}" ]]; then echo -e "ERROR! ${LANG} is not a supported Windows language:\n" for LANG in "${LANGS[@]}"; do echo -n "${LANG} " done exit 1 fi fi # Windows doesn't use create_vm() validate_release releases_windows get_windows "${LANG}" else validate_release "releases_${OS}" create_vm "$("get_${OS}")" fi else echo "ERROR! You must specify a release." case ${OS} in *ubuntu*) echo -n " - Releases: " releases_ubuntu | sed -Ee 's/eol-\S+//g' # hide eol releases ;; *) echo -n " - Releases: " releases_"${OS}" if [[ $(type -t "editions_${OS}") == function ]]; then echo -n " - Editions: " editions_"${OS}" fi ;; esac exit 1 fi # vim:tabstop=4:shiftwidth=4:expandtab