From: Michael Tremer Date: Sat, 25 Oct 2014 12:56:23 +0000 (+0200) Subject: installer: Rework downloading ISO and allow using a custom URL X-Git-Tag: v2.17-core87~103^2~47 X-Git-Url: http://git.ipfire.org/?p=ipfire-2.x.git;a=commitdiff_plain;h=c0511f3ab35cc059e0777b7481eaee105c738f5e installer: Rework downloading ISO and allow using a custom URL --- diff --git a/lfs/installer b/lfs/installer index 7f73222c1b..3364a4d7fd 100644 --- a/lfs/installer +++ b/lfs/installer @@ -31,6 +31,7 @@ DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) SLOGAN = An Open Source Firewall Solution +DOWNLOAD_URL = http://downloads.ipfire.org/releases/ipfire-2.x/$(VERSION)-core$(CORE)/$(SNAME)-$(VERSION).$(MACHINE)-full-core$(CORE).iso ############################################################################### # Top-level Rules @@ -58,12 +59,11 @@ $(TARGET) : --with-distro-name="$(NAME)" \ --with-distro-sname="$(SNAME)" \ --with-distro-slogan="$(SLOGAN)" \ - --with-config-root="$(CONFIG_ROOT)" + --with-config-root="$(CONFIG_ROOT)" \ + --with-download-url="$(DOWNLOAD_URL)" + cd $(DIR_APP) && make $(MAKETUNING) cd $(DIR_APP) && make install - #Patch ISO Name for download ... - #sed -i -e "s|ipfire.iso|download.ipfire.org/releases/ipfire-2.x/$(VERSION)-core$(CORE)/$(SNAME)-$(VERSION).$(MACHINE)-full-core$(CORE).iso|g" \ - # /usr/bin/downloadsource.sh @rm -rf $(DIR_APP) @$(POSTBUILD) diff --git a/src/installer/configure.ac b/src/installer/configure.ac index da968f637f..e93e0afe41 100644 --- a/src/installer/configure.ac +++ b/src/installer/configure.ac @@ -84,6 +84,11 @@ AC_ARG_WITH([config-root], AC_DEFINE_UNQUOTED([CONFIG_ROOT], "$withval", [The config-root]), AC_MSG_ERROR([*** you need to set CONFIG_ROOT with --with-config-root=])) +AC_ARG_WITH([download-url], + AS_HELP_STRING([--with-download-url] [The default download URL]), + AC_DEFINE_UNQUOTED([DOWNLOAD_URL], "$withval", [The default download URL]), + AC_MSG_ERROR([*** you need to set DOWNLOAD_URL with --with-download-url=])) + AC_CONFIG_FILES([ Makefile po/Makefile.in diff --git a/src/installer/downloadsource.sh b/src/installer/downloadsource.sh index 7504c198fd..4a48686ea9 100644 --- a/src/installer/downloadsource.sh +++ b/src/installer/downloadsource.sh @@ -19,29 +19,39 @@ # # ############################################################################### -#lfs change the url while build! -IPFireISO=ipfire.iso -# - -#Get user defined download from boot cmdline -grep "netinstall=" /proc/cmdline > /dev/null && CMDLINE=1 -if ( [ "$CMDLINE" == "1" ]); then - read CMDLINE < /proc/cmdline - POS=${CMDLINE%%netinstall*} - POS=${#POS} - IPFireISO=`echo ${CMDLINE:POS} | cut -d"=" -f2 | cut -d" " -f1` +function download() { + wget -U "IPFire-NetInstall/2.x" "$@" +} + +if [ $# -lt 2 ]; then + echo "$0: Insufficient number of arguments" >&2 + exit 2 +fi + +OUTPUT="${1}" +URL="${2}" + +echo "Downloading ${URL}..." +if ! download -O "${OUTPUT}" "${URL}"; then + echo "Download failed" >&2 + + rm -f "${OUTPUT}" + exit 1 fi -echo "Download with wget..." -wget $IPFireISO -O /tmp/download.iso -t3 -U IPFire_NetInstall/2.x -wget $IPFireISO.md5 -O /tmp/download.iso.md5 -t3 -U IPFire_NetInstall/2.x -echo -echo "Checking download..." -md5_file=`md5sum /tmp/download.iso | cut -d" " -f1` -md5_down=`cat /tmp/download.iso.md5 | cut -d" " -f1` -if [ "$md5_file" == "$md5_down" ]; then - echo -n "/tmp/download.iso" > /tmp/source_device - exit 0 +# Download went well. Checking for MD5 sum +if download -O "${OUTPUT}.md5" "${URL}.md5" &>/dev/null; then + # Read downloaded checksum + read -r md5sum rest < "${OUTPUT}.md5" + rm -f "${OUTPUT}.md5" + + # Compute checkum of downloaded image file + read -r md5sum_image rest <<< "$(md5sum "${OUTPUT}")" + + if [ "${md5sum}" != "${md5sum_image}" ]; then + echo "MD5 sum mismatch: ${md5sum} != ${md5sum_image}" >&2 + exit 2 + fi fi -echo "Error - SKIP" -exit 10 + +exit 0 diff --git a/src/installer/dracut-module/70-dhcpcd.exe b/src/installer/dracut-module/70-dhcpcd.exe index 4100fc9570..660f269410 100755 --- a/src/installer/dracut-module/70-dhcpcd.exe +++ b/src/installer/dracut-module/70-dhcpcd.exe @@ -12,21 +12,45 @@ # ######################################################################## -dhcpcd_up() -{ - set | grep "^new_" | sed "s|^new_||g" | \ - sed "s|'||g" | \ - sort > /var/ipfire/dhcpc/dhcpcd-$interface.info +LEASE_FILE="/var/ipfire/dhcpc/dhcpcd-${interface}.info" - DNS=`grep "domain_name_servers" /var/ipfire/dhcpc/dhcpcd-$interface.info | cut -d"=" -f2` - DNS1=`echo $DNS | cut -d" " -f1` - DNS2=`echo $DNS | cut -d" " -f2` +export_lease() { + set | grep "^new_" | sed "s|^new_||g" | \ + sed "s|'||g" | sort > ${LEASE_FILE} +} - echo "nameserver $DNS1" > /etc/resolv.conf - echo "nameserver $DNS2" >> /etc/resolv.conf +make_resolvconf() { + local DNS="$(grep 'domain_name_servers' ${LEASE_FILE} | cut -d'=' -f2)" + local DNS1="$(echo ${DNS} | cut -d' ' -f1)" + local DNS2="$(echo ${DNS} | cut -d' ' -f2)" + ( + echo "nameserver ${DNS1}" + echo "nameserver ${DNS2}" + ) > /etc/resolv.conf } -case "$reason" in -BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) dhcpcd_up;; +case "${reason}" in + PREINIT) + # Configure MTU + if [ -n "${new_interface_mtu}" ] && [ ${new_interface_mtu} -gt 576 ]; then + echo "Setting MTU to ${new_interface_mtu}" + ip link set "${interface}" mtu "${new_interface_mtu}" + fi + ;; + + BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) + # Export all information about the newly received lease + # to file + export_lease + + # Create system configuration files + make_resolvconf + ;; + + EXPIRE|FAIL|IPV4LL|NAK|NOCARRIER|RELEASE|STOP) + rm -f "${LEASE_FILE}" + ;; esac + +exit 0 diff --git a/src/installer/dracut-module/module-setup.sh b/src/installer/dracut-module/module-setup.sh index 31caa5489d..992fcecb79 100755 --- a/src/installer/dracut-module/module-setup.sh +++ b/src/installer/dracut-module/module-setup.sh @@ -35,17 +35,18 @@ install() { inst_multiple tar gzip lzma xz # Networking - inst_multiple dhcpcd ethtool hostname ip ping wget + inst_multiple dhcpcd ethtool hostname ip ping sort wget inst /usr/bin/start-networking.sh - inst /var/ipfire/dhcpc/dhcpcd-run-hooks inst /var/ipfire/dhcpc/dhcpcd.conf - for file in /var/ipfire/dhcpc/dhcpcd-hooks/*; do - inst "${file}" - done + inst /var/ipfire/dhcpc/dhcpcd-run-hooks inst "$moddir/70-dhcpcd.exe" "/var/ipfire/dhcpc/dhcpcd-hooks/70-dhcpcd.exe" + inst /etc/host.conf /etc/hosts /etc/protocols + inst /etc/nsswitch.conf /etc/resolv.conf + inst_libdir_file "libnss_dns.so.*" + # Misc. tools - inst_multiple cut grep eject killall md5sum touch + inst_multiple cut grep eject id killall md5sum touch inst_multiple -o fdisk cfdisk df ps top # Hardware IDs diff --git a/src/installer/hw.c b/src/installer/hw.c index 9b9a2d0029..651ffdf27c 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -26,12 +26,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -82,11 +84,56 @@ static int strstartswith(const char* a, const char* b) { return (strncmp(a, b, strlen(b)) == 0); } +static char loop_device[STRING_SIZE]; + +static int setup_loop_device(const char* source, const char* device) { + int file_fd = open(source, O_RDWR); + if (file_fd < 0) + goto ERROR; + + int device_fd = -1; + if ((device_fd = open(device, O_RDWR)) < 0) + goto ERROR; + + if (ioctl(device_fd, LOOP_SET_FD, file_fd) < 0) + goto ERROR; + + close(file_fd); + close(device_fd); + + return 0; + +ERROR: + if (file_fd >= 0) + close(file_fd); + + if (device_fd >= 0) { + ioctl(device_fd, LOOP_CLR_FD, 0); + close(device_fd); + } + + return -1; +} + int hw_mount(const char* source, const char* target, const char* fs, int flags) { + const char* loop_device = "/dev/loop0"; + // Create target if it does not exist if (access(target, X_OK) != 0) mkdir(target, S_IRWXU|S_IRWXG|S_IRWXO); + struct stat st; + stat(source, &st); + + if (S_ISREG(st.st_mode)) { + int r = setup_loop_device(source, loop_device); + if (r == 0) { + source = loop_device; + } else { + return -1; + } + } + return mount(source, target, fs, flags, NULL); } diff --git a/src/installer/main.c b/src/installer/main.c index c1a61b3457..5a2e0c4067 100644 --- a/src/installer/main.c +++ b/src/installer/main.c @@ -229,13 +229,18 @@ static struct config { int unattended; int serial_console; int require_networking; + int perform_download; + char download_url[STRING_SIZE]; } config = { .unattended = 0, .serial_console = 0, .require_networking = 0, + .perform_download = 0, + .download_url = DOWNLOAD_URL, }; static void parse_command_line(struct config* c) { + char buffer[STRING_SIZE]; char cmdline[STRING_SIZE]; FILE* f = fopen("/proc/cmdline", "r"); @@ -244,9 +249,13 @@ static void parse_command_line(struct config* c) { int r = fread(&cmdline, 1, sizeof(cmdline) - 1, f); if (r > 0) { - char* token = strtok(&cmdline, " "); + char* token = strtok(cmdline, " "); while (token) { + strncpy(buffer, token, sizeof(buffer)); + char* val = &buffer; + char* key = strsep(&val, "="); + // serial console if (strcmp(token, "console=ttyS0") == 0) c->serial_console = 1; @@ -259,6 +268,15 @@ static void parse_command_line(struct config* c) { else if (strcmp(token, "installer.unattended") == 0) c->unattended = 1; + // download url + else if (strcmp(key, "installer.download-url") == 0) { + strncpy(&c->download_url, val, sizeof(c->download_url)); + c->perform_download = 1; + + // Require networking for the download + c->require_networking = 1; + } + token = strtok(NULL, " "); } } @@ -364,16 +382,21 @@ int main(int argc, char *argv[]) { /* Search for a source drive that holds the right * version of the image we are going to install. */ - sourcedrive = hw_find_source_medium(hw); - fprintf(flog, "Source drive: %s\n", sourcedrive); + if (!config.perform_download) { + sourcedrive = hw_find_source_medium(hw); + fprintf(flog, "Source drive: %s\n", sourcedrive); + } /* If we could not find a source drive, we will try * downloading the install image */ - if (!sourcedrive) { + if (!sourcedrive) + config.perform_download = 1; + + if (config.perform_download) { if (!config.unattended) { // Show the right message to the user char reason[STRING_SIZE]; - if (config.require_networking) { + if (config.perform_download) { snprintf(reason, sizeof(reason), _("The installer will now try downloading the installation image.")); } else { @@ -392,6 +415,7 @@ int main(int argc, char *argv[]) { goto EXIT; } + // Make sure that we enable networking before download config.require_networking = 1; } @@ -420,20 +444,31 @@ int main(int argc, char *argv[]) { } // Download the image if required - while (!sourcedrive) { - snprintf(commandstring, sizeof(commandstring), "/usr/bin/downloadsource.sh %s", SOURCE_TEMPFILE); - runcommandwithstatus(commandstring, title, _("Downloading installation image..."), logfile); - - FILE* f = fopen(SOURCE_TEMPFILE, "r"); - if (f) { - sourcedrive = SOURCE_TEMPFILE; - fclose(f); - } else { - rc = newtWinOkCancel(title, _("The installation image could not be downloaded."), - 60, 8, _("Retry"), _("Cancel")); + if (config.perform_download) { + fprintf(flog, "Download URL: %s\n", config.download_url); + snprintf(commandstring, sizeof(commandstring), "/usr/bin/downloadsource.sh %s %s", + SOURCE_TEMPFILE, config.download_url); + + while (!sourcedrive) { + rc = runcommandwithstatus(commandstring, title, _("Downloading installation image..."), logfile); + + FILE* f = fopen(SOURCE_TEMPFILE, "r"); + if (f) { + sourcedrive = SOURCE_TEMPFILE; + fclose(f); + } else { + char reason[STRING_SIZE] = "-"; + if (rc == 2) + snprintf(reason, sizeof(STRING_SIZE), _("MD5 checksum mismatch")); - if (rc) - goto EXIT; + snprintf(message, sizeof(message), + _("The installation image could not be downloaded.\n Reason: %s\n\n%s"), + reason, config.download_url); + + rc = newtWinOkCancel(title, message, 75, 12, _("Retry"), _("Cancel")); + if (rc) + goto EXIT; + } } } } @@ -442,9 +477,10 @@ int main(int argc, char *argv[]) { int r = hw_mount(sourcedrive, SOURCE_MOUNT_PATH, "iso9660", MS_RDONLY); if (r) { - fprintf(flog, "Could not mount %s to %s\n", sourcedrive, SOURCE_MOUNT_PATH); - fprintf(flog, strerror(errno)); - exit(1); + snprintf(message, sizeof(message), _("Could not mount %s to %s:\n %s\n"), + sourcedrive, SOURCE_MOUNT_PATH, strerror(errno)); + errorbox(message); + goto EXIT; } if (!config.unattended) { diff --git a/src/installer/start-networking.sh b/src/installer/start-networking.sh index faeeb17237..3cb7a2172e 100644 --- a/src/installer/start-networking.sh +++ b/src/installer/start-networking.sh @@ -56,6 +56,10 @@ function main() { fi echo "Successfully started on ${interface}" + + # Wait until everything is settled + sleep 15 + return 0 done