X-Git-Url: http://git.ipfire.org/?p=ipfire-2.x.git;a=blobdiff_plain;f=src%2Finstaller%2Fmain.c;h=d02db2834afeccb60c891d88964640c6edf44000;hp=77c1d67d73021c493863796b23951a4e376fc65c;hb=ade96ba8a590df6411f7effec637609494072034;hpb=eb3ff46eaa94c123f7874e2b9e97f5796db9f904 diff --git a/src/installer/main.c b/src/installer/main.c index 77c1d67d73..d02db2834a 100644 --- a/src/installer/main.c +++ b/src/installer/main.c @@ -7,27 +7,25 @@ * Contains main entry point, and misc functions.6 * */ +#define _GNU_SOURCE #include #include +#include #include #include #include #include #include "hw.h" -#include "install.h" // Translation #include #define _(x) dgettext("installer", x) #define INST_FILECOUNT 21000 -#define UNATTENDED_CONF "/cdrom/boot/unattended.conf" #define LICENSE_FILE "/cdrom/COPYING" - -FILE *flog = NULL; -char *mylog; +#define SOURCE_TEMPFILE "/tmp/downloads/image.iso" extern char url[STRING_SIZE]; @@ -106,6 +104,37 @@ static int newtWinOkCancel(const char* title, const char* message, int width, in const char* btn_txt_ok, const char* btn_txt_cancel) { int ret = 1; + unsigned int btn_width_ok = strlen(btn_txt_ok); + unsigned int btn_width_cancel = strlen(btn_txt_cancel); + + // Maybe make the box wider to fix both buttons inside + unsigned int min_width = btn_width_ok + btn_width_cancel + 5; + if (width < min_width) + width = min_width; + + unsigned int btn_pos_ok = (width / 3) - (btn_width_ok / 2) - 1; + unsigned int btn_pos_cancel = (width * 2 / 3) - (btn_width_cancel / 2) - 1; + + // Move buttons a bit if they overlap + while ((btn_pos_ok + btn_width_ok + 5) > btn_pos_cancel) { + // Move the cancel button to the right if there is enough space left + if ((btn_pos_cancel + btn_width_cancel + 2) < width) { + ++btn_pos_cancel; + continue; + } + + // Move the OK button to the left if possible + if (btn_pos_ok > 1) { + --btn_pos_ok; + continue; + } + + // If they still overlap, we cannot fix the situtation + // and break. Should actually never get here, because we + // adjust the width of the window earlier. + break; + } + newtCenteredWindow(width, height, title); newtComponent form = newtForm(NULL, NULL, 0); @@ -114,9 +143,8 @@ static int newtWinOkCancel(const char* title, const char* message, int width, in newtTextboxSetText(textbox, message); newtFormAddComponent(form, textbox); - newtComponent btn_ok = newtButton((width - 16) / 3, height - 4, btn_txt_ok); - newtComponent btn_cancel = newtButton((width - 16) / 3 * 2 + 9, height - 4, - btn_txt_cancel); + newtComponent btn_ok = newtButton(btn_pos_ok, height - 4, btn_txt_ok); + newtComponent btn_cancel = newtButton(btn_pos_cancel, height - 4, btn_txt_cancel); newtFormAddComponents(form, btn_ok, btn_cancel, NULL); @@ -162,7 +190,7 @@ static int newtLicenseBox(const char* title, const char* text, int width, int he return ret; } -int write_lang_configs(const char *lang) { +int write_lang_configs(char* lang) { struct keyvalue *kv = initkeyvalues(); /* default stuff for main/settings. */ @@ -206,25 +234,102 @@ static char* center_string(const char* str, int width) { } #define DEFAULT_LANG "English" -#define NUM_LANGS 8 +#define NUM_LANGS 10 static struct lang { const char* code; char* name; } languages[NUM_LANGS + 1] = { - { "nl", "Dutch (Nederlands)" }, - { "en", "English" }, - { "fr", "French (Français)" }, - { "de", "German (Deutsch)" }, - { "pl", "Polish (Polski)" }, - { "ru", "Russian (Русский)" }, - { "es", "Spanish (Español)" }, - { "tr", "Turkish (Türkçe)" }, + { "da.utf8", "Danish (Dansk)" }, + { "nl_NL.utf8", "Dutch (Nederlands)" }, + { "en_US.utf8", "English" }, + { "fr_FR.utf8", "French (Français)" }, + { "de_DE.utf8", "German (Deutsch)" }, + { "pl_PL.utf8", "Polish (Polski)" }, + { "pt_BR.utf8", "Portuguese (Brasil)" }, + { "ru_RU.utf8", "Russian (Русский)" }, + { "es_ES.utf8", "Spanish (Español)" }, + { "tr_TR.utf8", "Turkish (Türkçe)" }, { NULL, NULL }, }; +static struct config { + int unattended; + int serial_console; + int require_networking; + int perform_download; + int disable_swap; + char download_url[STRING_SIZE]; + char postinstall[STRING_SIZE]; +} config = { + .unattended = 0, + .serial_console = 0, + .require_networking = 0, + .perform_download = 0, + .disable_swap = 0, + .download_url = DOWNLOAD_URL, + .postinstall = "\0", +}; + +static void parse_command_line(struct config* c) { + char buffer[STRING_SIZE]; + char cmdline[STRING_SIZE]; + + FILE* f = fopen("/proc/cmdline", "r"); + if (!f) + return; + + int r = fread(&cmdline, 1, sizeof(cmdline) - 1, f); + if (r > 0) { + char* token = strtok(cmdline, " "); + + while (token) { + strncpy(buffer, token, sizeof(buffer)); + char* val = buffer; + char* key = strsep(&val, "="); + + // serial console + if ((strcmp(key, "console") == 0) && (strncmp(val, "ttyS", 4) == 0)) + c->serial_console = 1; + + // enable networking? + else if (strcmp(token, "installer.net") == 0) + c->require_networking = 1; + + // unattended mode + else if (strcmp(token, "installer.unattended") == 0) + c->unattended = 1; + + // disable swap + else if (strcmp(token, "installer.disable-swap") == 0) + c->disable_swap = 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; + + // postinstall script + } else if (strcmp(key, "installer.postinstall") == 0) { + strncpy(c->postinstall, val, sizeof(c->postinstall)); + + // Require networking for the download + c->require_networking = 1; + } + + token = strtok(NULL, " "); + } + } + + fclose(f); +} + int main(int argc, char *argv[]) { struct hw* hw = hw_init(); + const char* logfile = NULL; // Read /etc/system-release char* system_release = get_system_release(); @@ -235,32 +340,26 @@ int main(int argc, char *argv[]) { int rc = 0; char commandstring[STRING_SIZE]; int choice; - char shortlangname[10]; + char language[STRING_SIZE]; char message[STRING_SIZE]; char title[STRING_SIZE]; int allok = 0; - FILE *handle, *cmdfile, *copying; - char line[STRING_SIZE]; - - int unattended = 0; - int serialconsole = 0; - struct keyvalue *unattendedkv = initkeyvalues(); - char restore_file[STRING_SIZE] = ""; + FILE *copying; - setlocale (LC_ALL, ""); - sethostname( SNAME , 10); + setlocale(LC_ALL, ""); + sethostname(SNAME, 10); /* Log file/terminal stuff. */ - if (argc >= 2) - { - if (!(flog = fopen(argv[1], "w+"))) + FILE* flog = NULL; + if (argc >= 2) { + logfile = argv[1]; + + if (!(flog = fopen(logfile, "w+"))) return 0; - } - else + } else { return 0; - - mylog = argv[1]; - + } + fprintf(flog, "Install program started.\n"); newtInit(); @@ -276,30 +375,20 @@ int main(int argc, char *argv[]) { char* roottext = center_string(system_release, screen_cols); newtDrawRootText(0, 0, roottext); - sprintf (title, "%s %s - %s", NAME, VERSION, SLOGAN); + snprintf(title, sizeof(title), "%s - %s", NAME, SLOGAN); - if (! (cmdfile = fopen("/proc/cmdline", "r"))) - { - fprintf(flog, "Couldn't open commandline: /proc/cmdline\n"); - } else { - fgets(line, STRING_SIZE, cmdfile); - - // check if we have to make an unattended install - if (strstr (line, "unattended") != NULL) { - unattended = 1; - runcommandwithstatus("/bin/sleep 10", title, "WARNING: Unattended installation will start in 10 seconds..."); - } - // check if we have to patch for serial console - if (strstr (line, "console=ttyS0") != NULL) { - serialconsole = 1; - } + // Parse parameters from the kernel command line + parse_command_line(&config); + + if (config.unattended) { + splashWindow(title, _("Warning: Unattended installation will start in 10 seconds..."), 10); } // Load common modules - mysystem("/sbin/modprobe vfat"); // USB key - hw_stop_all_raid_arrays(); + mysystem(logfile, "/sbin/modprobe vfat"); // USB key + hw_stop_all_raid_arrays(logfile); - if (!unattended) { + if (!config.unattended) { // Language selection char* langnames[NUM_LANGS + 1]; @@ -311,69 +400,147 @@ int main(int argc, char *argv[]) { } langnames[NUM_LANGS] = NULL; - rc = newtWinMenu(_("Language selection"), _("Select the language you wish to use for the installation."), + rc = newtWinMenu(_("Language selection"), _("Select the language you wish to use for the installation."), 50, 5, 5, 8, langnames, &choice, _("OK"), NULL); assert(choice <= NUM_LANGS); fprintf(flog, "Selected language: %s (%s)\n", languages[choice].name, languages[choice].code); - setlocale(LC_ALL, languages[choice].code); + snprintf(language, sizeof(language), "%s", languages[choice].code); + + setenv("LANGUAGE", language, 1); + setlocale(LC_ALL, language); } - char* helpline = center_string(_("/ between elements | selects | next screen"), screen_cols); + // Set helpline + char* helpline = NULL; + if (config.unattended) + helpline = center_string(_("Unattended mode"), screen_cols); + else + helpline = center_string(_("/ between elements | selects | next screen"), screen_cols); + newtPushHelpLine(helpline); - if (!unattended) { + if (!config.unattended) { snprintf(message, sizeof(message), - _("Welcome to the %s installation program. " + _("Welcome to the %s installation program.\n\n" "Selecting Cancel on any of the following screens will reboot the computer."), NAME); newtWinMessage(title, _("Start installation"), message); } /* 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 (!sourcedrive) { - newtWinMessage(title, _("OK"), _("No local source media found. Starting download.")); - runcommandwithstatus("/bin/downloadsource.sh", title, _("Downloading installation image ...")); - if ((handle = fopen("/tmp/source_device", "r")) == NULL) { - errorbox(_("Download error")); - goto EXIT; + 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) + config.perform_download = 1; + + if (config.perform_download) { + if (!config.unattended) { + // Show the right message to the user + char reason[STRING_SIZE]; + if (config.perform_download) { + snprintf(reason, sizeof(reason), + _("The installer will now try downloading the installation image.")); + } else { + snprintf(reason, sizeof(reason), + _("No source drive could be found.\n\n" + "You can try downloading the required installation image.")); + } + snprintf(message, sizeof(message), "%s %s", reason, + _("Please make sure to connect your machine to a network and " + "the installer will try connect to acquire an IP address.")); + + rc = newtWinOkCancel(title, message, 55, 12, + _("Download installation image"), _("Cancel")); + + if (rc != 0) + goto EXIT; } - fgets(sourcedrive, 5, handle); - fclose(handle); + // Make sure that we enable networking before download + config.require_networking = 1; } - assert(sourcedrive); + // Try starting the networking if we require it + if (config.require_networking) { + while (1) { + statuswindow(60, 4, title, _("Trying to start networking (DHCP)...")); - 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); + rc = hw_start_networking(logfile); + newtPopWindow(); + + // Networking was successfully started + if (rc == 0) { + break; + + // An error happened, ask the user what to do + } else { + rc = newtWinOkCancel(title, _("Networking could not be started " + "but is required to go on with the installation.\n\n" + "Please connect your machine to a network with a " + "DHCP server and retry."), 50, 10, _("Retry"), _("Cancel")); + + if (rc) + goto EXIT; + } + } + + // Download the image if required + 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 = strdup(SOURCE_TEMPFILE); + fclose(f); + } else { + char reason[STRING_SIZE] = "-"; + if (rc == 2) + snprintf(reason, sizeof(STRING_SIZE), _("MD5 checksum mismatch")); + + 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; + } + } + } } - /* load unattended configuration */ - if (unattended) { - fprintf(flog, "unattended: Reading unattended.conf\n"); + assert(sourcedrive); - (void) readkeyvalues(unattendedkv, UNATTENDED_CONF); - findkey(unattendedkv, "RESTORE_FILE", restore_file); + int r = hw_mount(sourcedrive, SOURCE_MOUNT_PATH, "iso9660", MS_RDONLY); + if (r) { + snprintf(message, sizeof(message), _("Could not mount %s to %s:\n %s\n"), + sourcedrive, SOURCE_MOUNT_PATH, strerror(errno)); + errorbox(message); + goto EXIT; } - if (!unattended) { + if (!config.unattended) { // Read the license file. if (!(copying = fopen(LICENSE_FILE, "r"))) { sprintf(discl_msg, "Could not open license file: %s\n", LICENSE_FILE); - fprintf(flog, discl_msg); + fprintf(flog, "%s", discl_msg); } else { fread(discl_msg, 1, 40000, copying); fclose(copying); - if (newtLicenseBox(title, discl_msg, 75, 20)) { + if (newtLicenseBox(_("License Agreement"), discl_msg, 75, 20)) { errorbox(_("License not accepted!")); goto EXIT; @@ -384,14 +551,14 @@ int main(int argc, char *argv[]) { int part_type = HW_PART_TYPE_NORMAL; // Scan for disks to install on. - struct hw_disk** disks = hw_find_disks(hw); + struct hw_disk** disks = hw_find_disks(hw, sourcedrive); struct hw_disk** selected_disks = NULL; unsigned int num_selected_disks = 0; // Check how many disks have been found and what // we can do with them. - unsigned int num_disks = hw_count_disks(disks); + unsigned int num_disks = hw_count_disks((const struct hw_disk**)disks); while (1) { // no harddisks found @@ -400,8 +567,10 @@ int main(int argc, char *argv[]) { goto EXIT; // exactly one disk has been found - } else if (num_disks == 1) { - selected_disks = hw_select_disks(disks, NULL); + // or if we are running in unattended mode, we will select + // the first disk and go with that one + } else if ((num_disks == 1) || (config.unattended && num_disks >= 1)) { + selected_disks = hw_select_first_disk((const struct hw_disk**)disks); // more than one usable disk has been found and // the user needs to choose what to do with them @@ -410,7 +579,7 @@ int main(int argc, char *argv[]) { int disk_selection[num_disks]; for (unsigned int i = 0; i < num_disks; i++) { - disk_names[i] = &disks[i]->description; + disk_names[i] = disks[i]->description; disk_selection[i] = 0; } @@ -436,7 +605,12 @@ int main(int argc, char *argv[]) { } } - num_selected_disks = hw_count_disks(selected_disks); + // Don't print the auto-selected harddisk setup in + // unattended mode. + if (config.unattended) + break; + + num_selected_disks = hw_count_disks((const struct hw_disk**)selected_disks); if (num_selected_disks == 1) { snprintf(message, sizeof(message), @@ -451,7 +625,7 @@ int main(int argc, char *argv[]) { } else if (num_selected_disks == 2) { snprintf(message, sizeof(message), _("The installation program will now set up a RAID configuration on the selected harddisks:\n\n %s\n %s\n\n" - "Do you agree to continue?"), (*selected_disks)->description, (*selected_disks + 1)->description); + "Do you agree to continue?"), selected_disks[0]->description, selected_disks[1]->description); rc = newtWinOkCancel(_("RAID Setup"), message, 50, 14, _("Delete all data"), _("Cancel")); @@ -463,7 +637,8 @@ int main(int argc, char *argv[]) { // Currently not supported } else { - errorbox(_("You disk configuration is currently not supported.")); + errorbox(_("Your disk configuration is currently not supported.")); + fprintf(flog, "Num disks selected: %d\n", num_selected_disks); } if (selected_disks) { @@ -474,7 +649,7 @@ int main(int argc, char *argv[]) { hw_free_disks(disks); - struct hw_destination* destination = hw_make_destination(part_type, selected_disks); + struct hw_destination* destination = hw_make_destination(part_type, selected_disks, config.disable_swap); if (!destination) { errorbox(_("Your harddisk is too small.")); @@ -487,21 +662,24 @@ int main(int argc, char *argv[]) { fprintf(flog, " swap : %s (%lluMB)\n", destination->part_swap, BYTES2MB(destination->size_swap)); fprintf(flog, " root : %s (%lluMB)\n", destination->part_root, BYTES2MB(destination->size_root)); fprintf(flog, " data : %s (%lluMB)\n", destination->part_data, BYTES2MB(destination->size_data)); + fprintf(flog, "Memory : %lluMB\n", BYTES2MB(hw_memory())); // Warn the user if there is not enough space to create a swap partition - if (!unattended && !*destination->part_swap) { - rc = newtWinChoice(title, _("OK"), _("Cancel"), - _("Your harddisk is very small, but you can continue with an very small swap. (Use with caution).")); + if (!config.unattended) { + if (!config.disable_swap && !*destination->part_swap) { + rc = newtWinChoice(title, _("OK"), _("Cancel"), + _("Your harddisk is very small, but you can continue without a swap partition.")); - if (rc != 1) - goto EXIT; + if (rc != 1) + goto EXIT; + } } // Filesystem selection - if (!unattended) { + if (!config.unattended) { struct filesystems { int fstype; - const char* description; + char* description; } filesystems[] = { { HW_FS_EXT4, _("ext4 Filesystem") }, { HW_FS_EXT4_WO_JOURNAL, _("ext4 Filesystem without journal") }, @@ -533,19 +711,23 @@ int main(int argc, char *argv[]) { if (destination->is_raid) { statuswindow(60, 4, title, _("Building RAID...")); - rc = hw_setup_raid(destination); + rc = hw_setup_raid(destination, logfile); if (rc) { errorbox(_("Unable to build the RAID.")); goto EXIT; } newtPopWindow(); + } else { + // We will have to destroy all RAID setups that may have + // been on the devices that we want to use now. + hw_destroy_raid_superblocks(destination, logfile); } // Execute the partitioning... statuswindow(60, 4, title, _("Partitioning disk...")); - rc = hw_create_partitions(destination); + rc = hw_create_partitions(destination, logfile); if (rc) { errorbox(_("Unable to partition the disk.")); goto EXIT; @@ -556,7 +738,7 @@ int main(int argc, char *argv[]) { // Execute the formatting... statuswindow(60, 4, title, _("Creating filesystems...")); - rc = hw_create_filesystems(destination); + rc = hw_create_filesystems(destination, logfile); if (rc) { errorbox(_("Unable to create filesystems.")); goto EXIT; @@ -575,7 +757,7 @@ int main(int argc, char *argv[]) { "/bin/tar -C /harddisk -xvf /cdrom/distro.img --lzma 2>/dev/null"); if (runcommandwithprogress(60, 4, title, commandstring, INST_FILECOUNT, - _("Installing the system..."))) { + _("Installing the system..."), logfile)) { errorbox(_("Unable to install the system.")); goto EXIT; } @@ -588,11 +770,11 @@ int main(int argc, char *argv[]) { } /* Save language und local settings */ - write_lang_configs(shortlangname); + write_lang_configs(language); /* Build cache lang file */ snprintf(commandstring, STRING_SIZE, "/usr/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT "/lang.pl'; &Lang::BuildCacheLang\""); - if (runcommandwithstatus(commandstring, title, _("Installing the language cache..."))) { + if (runcommandwithstatus(commandstring, title, _("Installing the language cache..."), logfile)) { errorbox(_("Unable to install the language cache.")); goto EXIT; } @@ -600,23 +782,22 @@ int main(int argc, char *argv[]) { // Installing bootloader... statuswindow(60, 4, title, _("Installing the bootloader...")); - rc = hw_install_bootloader(destination); - if (rc) { - errorbox(_("Unable to install the bootloader.")); - goto EXIT; - } - - newtPopWindow(); - /* Serial console ? */ - if (serialconsole) { + if (config.serial_console) { /* grub */ - replace("/harddisk/boot/grub/grub.conf", "splashimage", "#splashimage"); - replace("/harddisk/boot/grub/grub.conf", "#serial", "serial"); - replace("/harddisk/boot/grub/grub.conf", "#terminal", "terminal"); - replace("/harddisk/boot/grub/grub.conf", " panic=10 ", " console=ttyS0,115200n8 panic=10 "); + FILE* f = fopen(DESTINATION_MOUNT_PATH "/etc/default/grub", "a"); + if (!f) { + errorbox(_("Unable to open /etc/default/grub for writing.")); + goto EXIT; + } - /*inittab*/ + fprintf(f, "GRUB_TERMINAL=\"serial\"\n"); + fprintf(f, "GRUB_SERIAL_COMMAND=\"serial --unit=0 --speed=%d\"\n", SERIAL_BAUDRATE); + fclose(f); + + replace(DESTINATION_MOUNT_PATH "/etc/default/grub", "panic=10", "panic=10 console=ttyS0,115200n8"); + + /* inittab */ replace("/harddisk/etc/inittab", "1:2345:respawn:", "#1:2345:respawn:"); replace("/harddisk/etc/inittab", "2:2345:respawn:", "#2:2345:respawn:"); replace("/harddisk/etc/inittab", "3:2345:respawn:", "#3:2345:respawn:"); @@ -626,68 +807,131 @@ int main(int argc, char *argv[]) { replace("/harddisk/etc/inittab", "#7:2345:respawn:", "7:2345:respawn:"); } + rc = hw_install_bootloader(destination, logfile); + if (rc) { + errorbox(_("Unable to install the bootloader.")); + goto EXIT; + } + + newtPopWindow(); + /* Set marker that the user has already accepted the gpl */ - mysystem("/usr/bin/touch /harddisk/var/ipfire/main/gpl_accepted"); + mysystem(logfile, "/usr/bin/touch /harddisk/var/ipfire/main/gpl_accepted"); /* Copy restore file from cdrom */ - if (unattended && (strlen(restore_file) > 0)) { - fprintf(flog, "unattended: Copy restore file\n"); - snprintf(commandstring, STRING_SIZE, - "cp /cdrom/%s /harddisk/var/ipfire/backup", restore_file); - mysystem(commandstring); + char* backup_file = hw_find_backup_file(logfile, SOURCE_MOUNT_PATH); + if (backup_file) { + rc = 0; + if (!config.unattended) { + rc = newtWinOkCancel(title, _("A backup file has been found on the installation image.\n\n" + "Do you want to restore the backup?"), 50, 10, _("Yes"), _("No")); + } + + if (rc == 0) { + rc = hw_restore_backup(logfile, backup_file, DESTINATION_MOUNT_PATH); + + if (rc) { + errorbox(_("An error occured when the backup file was restored.")); + goto EXIT; + } + } + + free(backup_file); + } + + // Download and execute the postinstall script + if (*config.postinstall) { + snprintf(commandstring, sizeof(commandstring), + "/usr/bin/execute-postinstall.sh %s %s", DESTINATION_MOUNT_PATH, config.postinstall); + + if (runcommandwithstatus(commandstring, title, _("Running post-install script..."), logfile)) { + errorbox(_("Post-install script failed.")); + goto EXIT; + } + } + + // Umount the destination drive + statuswindow(60, 4, title, _("Umounting filesystems...")); + + rc = hw_umount_filesystems(destination, DESTINATION_MOUNT_PATH); + if (rc) { + // Show an error message if filesystems could not be umounted properly + snprintf(message, sizeof(message), + _("Could not umount all filesystems successfully:\n\n %s"), strerror(errno)); + errorbox(message); + goto EXIT; } // Umount source drive and eject hw_umount(SOURCE_MOUNT_PATH); - snprintf(commandstring, STRING_SIZE, "/usr/bin/eject %s", sourcedrive); - mysystem(commandstring); + // Free downloaded ISO image + if (strcmp(sourcedrive, SOURCE_TEMPFILE) == 0) { + rc = unlink(sourcedrive); + if (rc) + fprintf(flog, "Could not free downloaded ISO image: %s\n", sourcedrive); + + // or eject real images + } else { + snprintf(commandstring, STRING_SIZE, "/usr/bin/eject %s", sourcedrive); + mysystem(logfile, commandstring); + } + newtPopWindow(); - if (!unattended) { - snprintf(message, sizeof(message), _("%s was successfully installed. " - "Please remove any installation mediums from this system. " - "Setup will now run where you may configure networking and the system passwords. " - "After Setup has been completed, you should point your web browser at https://%s:444 " - "(or whatever you name your %s), and configure dialup networking (if required) and " - "remote access."), NAME, SNAME, NAME); + // Stop the RAID array if we are using RAID + if (destination->is_raid) + hw_stop_all_raid_arrays(logfile); + + // Show a short message that the installation went well and + // wait a moment so that all disk caches get flushed. + if (config.unattended) { + splashWindow(title, _("Unattended installation has finished. The system will be shutting down in a moment..."), 5); + + } else { + snprintf(message, sizeof(message), _( + "%s was successfully installed!\n\n" + "Please remove any installation mediums from this system and hit the reboot button. " + "Once the system has restarted you will be asked to setup networking and system passwords. " + "After that, you should point your web browser at https://%s:444 (or what ever you name " + "your %s) for the web configuration console."), NAME, SNAME, NAME); newtWinMessage(_("Congratulations!"), _("Reboot"), message); } allok = 1; EXIT: - fprintf(flog, "Install program ended.\n"); + fprintf(flog, "Install program ended.\n"); + fflush(flog); + fclose(flog); - if (!(allok)) - newtWinMessage(title, _("OK"), _("Press Ok to reboot.")); - - if (allok) { - fflush(flog); - fclose(flog); - } + if (!allok) + newtWinMessage(title, _("OK"), _("Setup has failed. Press Ok to reboot.")); newtFinished(); // Free resources - free(system_release); - free(roottext); - free(helpline); + if (system_release) + free(system_release); + + if (roottext) + free(roottext); - free(sourcedrive); + if (helpline) + free(helpline); - if (destination) { - hw_sync(); + if (sourcedrive) + free(sourcedrive); - hw_umount_filesystems(destination, DESTINATION_MOUNT_PATH); + if (destination) free(destination); - } - hw_stop_all_raid_arrays(); + hw_stop_all_raid_arrays(logfile); if (selected_disks) hw_free_disks(selected_disks); - hw_free(hw); + if (hw) + hw_free(hw); fcloseall();