/g' | grep "$LANG 64-bit" | grep -o -P '(?<= | ).*(?= |
)')
# Limit untrusted size for input validation
iso_download_link_html="$(echo "$iso_download_link_html" | head -c 4096)"
if ! [ "$iso_download_link_html" ]; then
# This should only happen if there's been some change to how this API works
echo " - Microsoft servers gave us an empty response to our request for an automated download."
failed=1
fi
if echo "$iso_download_link_html" | grep -q "We are unable to complete your request at this time."; then
if [ "${show_iso_url}" == 'on' ] || [ "${test_iso_url}" == 'on' ]; then
echo " - Failed to get URL: Microsoft blocked the automated download request based on your IP address."
exit 1
fi
echo " - Microsoft blocked the automated download request based on your IP address."
failed=1
fi
if [ ${failed} -eq 1 ]; then
echo " - Manually download the Windows ${windows_version} ISO using a web browser from: ${url}"
echo " - Save the downloaded ISO to: $(realpath "${VM_PATH}")"
echo " - Update the config file to reference the downloaded ISO: ./${VM_PATH}.conf"
echo " - Continuing with the VM creation process..."
return 1
fi
# Filter for 64-bit ISO download URL
# sed: HTML decode "&" character
# tr: Filter for only alphanumerics or punctuation
local iso_download_link="$(echo "$iso_download_link_html" | grep -o "https://software.download.prss.microsoft.com.*IsoX64" | cut -d '"' -f 1 | sed 's/&/\&/g' | tr -cd '[:alnum:][:punct:]' | head -c 512)"
if ! [ "$iso_download_link" ]; then
# This should only happen if there's been some change to the download endpoint web address
echo " - Microsoft servers gave us no download link to our request for an automated download. Please manually download this ISO in a web browser: $url"
return 1
fi
if [ "${show_iso_url}" == 'on' ]; then
echo -e " Windows ${RELEASE} Download (valid for 24 hours):\n${iso_download_link}"
exit 0
elif [ "${test_iso_url}" == 'on' ]; then
wget --spider "${iso_download_link}"
exit 0
fi
if [ "${LANG}" != "English International" ]; then
echo Downloading Windows ${RELEASE} in "${LANG}" from "$iso_download_link"
else
echo Downloading Windows ${RELEASE} from "$iso_download_link"
fi
# Download ISO
FILE_NAME="$(echo "$iso_download_link" | cut -d'?' -f1 | cut -d'/' -f5)"
web_get "$iso_download_link" "${VM_PATH}" "${FILE_NAME}"
# Only Windows 11 hashes can be found directly from Microsoft's page.
if [ "${windows_version}" == 11 ]; then
check_hash "${FILE_NAME}" "${HASH}"
fi
}
function get_windows() {
if [ "${RELEASE}" == "10-ltsc" ]; then
download_windows-server windows-10-enterprise ltsc
elif [ "${OS}" == "windows-server" ]; then
download_windows-server windows-server-${RELEASE}
else
download_windows "${RELEASE}"
fi
if [ "${download_iso}" == 'on' ]; then
exit 0
fi
echo "Downloading VirtIO drivers..."
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
if [ -n "${FILE_NAME}" ]; then
make_vm_config "${FILE_NAME}" "virtio-win.iso"
else
make_vm_config "windows-${RELEASE}.iso" "virtio-win.iso"
fi
}
open_url() {
local URL="$1";
xdg-open $URL || sensible-browser $URL || x-www-browser $URL || gnome-open $URL;
}
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} == "guix" ] && [[ $ISO =~ ".qcow2" ]]; then
#cp ${VM_PATH}/${ISO} ${VM_PATH}/disc.qcow2
#fi
if [[ ${OS} == "batocera" ]] && [[ ${ISO} =~ ".gz" ]]; then
gzip -d "${VM_PATH}/${ISO}"
ISO="${ISO/.gz/}"
fi
# Could be other OS iso files compressed with bzip2 or gzip
# but for now we'll keep this to know cases
if [[ ${OS} == "dragonflybsd" ]] && [[ ${ISO} =~ ".bz2" ]]; then
bzip2 -d "${VM_PATH}/${ISO}"
ISO="${ISO/.bz2/}"
fi
if [[ ${OS} == "easyos" ]] && [[ ${ISO} =~ ".img" ]]; then
qemu-img convert -f raw -O qcow2 "${VM_PATH}/${ISO}" "${VM_PATH}/disk.qcow2"
ISO="${ISO/.img/}"
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=()
os_supported_edition() {
if [[ ! " ${EDITIONS[*]} " =~ " ${EDITION} " ]]; then
echo -e "ERROR! ${EDITION} is not a supported $(pretty_name "${OS}") edition\n"
echo -n ' - Editions: '
for EDITION in "${EDITIONS[@]}"; do
echo -n "${EDITION} "
done
echo ""
exit 1
fi
}
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
echo "
You can also use these arguments:
Only show ISO download URL
--show-iso-url / -s {distro} {release} [edition]
Test if ISO is available
--test-iso-url / -t {distro} {release} [edition]
Open distro homepage
--open-distro-homepage / -o {distro}
Only download ISO
--download-iso / -d {distro} {release} [edition]"
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
validate_release "releases_${OS}"
EDITIONS=($(editions_${OS}))
EDITION=${EDITIONS[0]}
if [ -n "${3}" ]; then
EDITION="${3}"
os_supported_edition
else
echo -en "ERROR! You must specify an edition.\n - Editions: "
editions_"${OS}"
exit 1
fi
# Handle odd missing fedora cominations
if [[ $OS == fedora ]] ; then
if [[ ${RELEASE} = "33" && ${EDITION} = "i3" ]] || [[ ${RELEASE} = "34" && ${EDITION} = "Cinnamon" ]] || [[ "${RELEASE}" < "39" && ${EDITION} = "Onyx" ]]; then
echo "ERROR! Unsupported combination"
echo " Fedora ${RELEASE} ${EDITION} is not available, please choose another Release or Edition"
exit 1;
fi
fi
# Handle missing Mangaro Sway minimal
if [[ $OS == manjaro ]] ; then
if [[ ${RELEASE} == "sway" && ${EDITION} == "minimal" ]] ; then
echo "ERROR! Unsupported combination"
echo " Manjaro Sway does not have a minimal edition"
exit 1;
fi
fi
VM_PATH="${OS}-${RELEASE}-${EDITION}"
create_vm "$("get_${OS}" "${EDITION}")"
elif [ "${OS}" == "macos" ]; then
# macOS doesn't use create_vm()
validate_release releases_macos
get_macos
elif [[ "${OS}" == *"ubuntu-server"* ]]; then
# (Comes before regular Ubuntu, or the code tries to download the desktop) #
# Ubuntu doesn't use create_vm()
validate_release releases_ubuntu-server
get_ubuntu-server
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"
"languages_${OS}"
if [ -n "${3}" ]; then
LANG="${3}"
if [[ ! ${LANGS[*]} =~ "${LANG}" ]]; then
echo -e "ERROR! ${LANG} is not a supported Windows ${RELEASE} language:\n"
for LANG in "${LANGS[@]}"; do
echo -n "${LANG} "
done
exit 1
fi
VM_PATH="$(echo "${OS}-${RELEASE}-${LANG// /-}" | tr -d '()')"
fi
validate_release "releases_${OS}"
get_windows
else
validate_release "releases_${OS}"
create_vm "$("get_${OS}")"
fi
elif [ "${open_distro_homepage}" == 'on' ]; then
HOMEPAGE=$(os_homepages ${OS})
open_url "${HOMEPAGE}" && exit 0
else
echo "ERROR! You must specify a release."
case ${OS} in
*ubuntu-server*)
echo -n " - Releases: "
releases_ubuntu-server | sed -Ee 's/eol-\S+//g' # hide eol releases
;;
*ubuntu*)
echo -n " - Releases: "
releases_ubuntu | sed -Ee 's/eol-\S+//g' # hide eol releases
;;
*windows*)
echo -n " - Releases: "
"releases_${OS}"
echo -n " - Languages: "
"languages_${OS}" && echo "${LANGS[@]}"
;;
*)
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