/* * hdinstall.c - code to set up hard drive installs * * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. * All rights reserved. * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 program. If not, see . * * Author(s): Erik Troan * Matt Wilson * Michael Fulbright * Jeremy Katz */ #include #include #include #include #include #include #include #include #include #include #include "dirbrowser.h" #include "driverdisk.h" #include "hdinstall.h" #include "getparts.h" #include "kickstart.h" #include "loader.h" #include "loadermisc.h" #include "lang.h" #include "modules.h" #include "method.h" #include "mediacheck.h" #include "cdinstall.h" #include "windows.h" #include "../pyanaconda/isys/imount.h" #include "../pyanaconda/isys/isys.h" #include "../pyanaconda/isys/eddsupport.h" #include "../pyanaconda/isys/log.h" /* boot flags */ extern uint64_t flags; /* format is hd:device:/path */ static void parseDeviceAndDir(char *url, char **device, char **dir) { char *token, *src = NULL; if (!url) return; /* Skip over the leading hd: if present. */ if (!strncmp(url, "hd:", 3)) url += 3; logMessage(DEBUGLVL, "parseDeviceAndDir url: |%s|", url); src = strdup(url); token = strtok(src, ":"); if (!token) return; *device = strdup(token); token = strtok(NULL, ":"); if (!token) *dir = strdup("/"); else *dir = strdup(token); logMessage(DEBUGLVL, "parseDeviceAndDir device: |%s|", *device); logMessage(DEBUGLVL, "parseDeviceAndDir dir: |%s|", *dir); } static int ends_with_iso(char *dirname, struct dirent *ent) { char *suffix; if (ent->d_type != DT_REG) return 0; suffix = rindex(ent->d_name, '.'); return (!strcmp(suffix, "iso")); } int loadHdImages(struct loaderData_s *loaderData) { char *device = NULL, *dir = NULL, *path; logMessage(DEBUGLVL, "looking for extras for HD install"); if (!loaderData->instRepo) return 0; parseDeviceAndDir(loaderData->instRepo, &device, &dir); if (doPwMount(device, "/mnt/isodir", "auto", "ro", NULL)) return 0; if (dir[0] == '/') { checked_asprintf(&path, "/mnt/isodir%s/updates.img", dir); } else { checked_asprintf(&path, "/mnt/isodir/%s/updates.img", dir); } logMessage(INFO, "Looking for updates for HD in %s", path); copyUpdatesImg(path); free(path); if (dir[0] == '/') { checked_asprintf(&path, "/mnt/isodir%s/product.img", dir); } else { checked_asprintf(&path, "/mnt/isodir/%s/product.img", dir); } logMessage(INFO, "Looking for product for HD in %s", path); copyProductImg(path); free(device); free(dir); free(path); umount("/mnt/isodir"); return 1; } int promptForHardDrive(struct loaderData_s *loaderData) { int rc; int i; newtComponent listbox, label, dirEntry, form, okay, back, text; struct newtExitStruct es; newtGrid entryGrid, grid, buttons; char * dir = g_strdup(""); char * tmpDir; char * buf; int numPartitions; char **files; char **partition_list; char *selpart; char *kspartition = NULL, *ksdirectory = NULL; partition_list = NULL; while (1) { /* if we're doing another pass free this up first */ if (partition_list) g_strfreev(partition_list); partition_list = getPartitionsList(NULL); numPartitions = g_strv_length(partition_list); /* no partitions found, try to load a device driver disk for storage */ if (!numPartitions) { rc = newtWinChoice(_("Hard Drives"), _("Yes"), _("Back"), _("You don't seem to have any hard drives on " "your system! Would you like to configure " "additional devices?")); if (rc == 2) { loaderData->instRepo = NULL; return LOADER_BACK; } rc = loadDriverFromMedia(DEVICE_DISK, loaderData, 0, 0, NULL); continue; } /* now find out which partition has the stage2 image */ checked_asprintf(&buf, _("What partition and directory on that " "partition holds the installation image " "for %s? If you don't see the disk drive " "you're using listed here, press F2 to " "configure additional devices."), getProductName()); text = newtTextboxReflowed(-1, -1, buf, 62, 5, 5, 0); free(buf); listbox = newtListbox(-1, -1, numPartitions > 5 ? 5 : numPartitions, NEWT_FLAG_RETURNEXIT | (numPartitions > 5 ? NEWT_FLAG_SCROLL : 0)); for (i = 0; i < numPartitions; i++) newtListboxAppendEntry(listbox,partition_list[i],partition_list[i]); /* if we had ks data around use it to prime entry, then get rid of it*/ if (kspartition) { newtListboxSetCurrentByKey(listbox, kspartition); g_free(kspartition); kspartition = NULL; } label = newtLabel(-1, -1, _("Directory holding image:")); dirEntry = newtEntry(28, 11, dir, 28, (const char **) &tmpDir, NEWT_ENTRY_SCROLL); /* if we had ks data around use it to prime entry, then get rid of it*/ if (ksdirectory) { newtEntrySet(dirEntry, ksdirectory, 1); g_free(ksdirectory); ksdirectory = NULL; } entryGrid = newtGridHStacked(NEWT_GRID_COMPONENT, label, NEWT_GRID_COMPONENT, dirEntry, NEWT_GRID_EMPTY); buttons = newtButtonBar(_("OK"), &okay, _("Back"), &back, NULL); grid = newtCreateGrid(1, 4); newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text, 0, 0, 0, 1, 0, 0); newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, listbox, 0, 0, 0, 1, 0, 0); newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, entryGrid, 0, 0, 0, 1, 0, 0); newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons, 0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX); newtGridWrappedWindow(grid, _("Select Partition")); form = newtForm(NULL, NULL, 0); newtFormAddHotKey(form, NEWT_KEY_F2); newtFormAddHotKey(form, NEWT_KEY_F12); newtGridAddComponentsToForm(grid, form, 1); newtGridFree(grid, 1); newtFormRun(form, &es); selpart = newtListboxGetCurrent(listbox); g_free(dir); if (tmpDir && *tmpDir) { /* Protect from form free. */ dir = g_strdup(tmpDir); } else { dir = g_strdup(""); } newtFormDestroy(form); newtPopWindow(); if (es.reason == NEWT_EXIT_COMPONENT && es.u.co == back) { loaderData->instRepo = NULL; return LOADER_BACK; } else if (es.reason == NEWT_EXIT_HOTKEY && es.u.key == NEWT_KEY_F2) { rc = loadDriverFromMedia(DEVICE_DISK, loaderData, 0, 0, NULL); continue; } logMessage(INFO, "partition %s selected", selpart); /* Now verify the ISO images pointed to contain an installation source. */ if (doPwMount(selpart, "/mnt/isodir", "auto", "ro", NULL)) { logMessage(ERROR, "couldn't mount %s to verify images", selpart); continue; } if (dir[0] == '/') { checked_asprintf(&buf, "/mnt/isodir%s", dir); } else { checked_asprintf(&buf, "/mnt/isodir/%s", dir); } files = get_file_list(buf, ends_with_iso); if (!files) { newtWinMessage(_("Error"), _("OK"), _("That directory does not contain installation media.")); umount("/mnt/isodir"); free(buf); continue; } free(buf); /* mount the first image and check for a .treeinfo file */ if (dir[0] == '/') { checked_asprintf(&buf, "/mnt/isodir%s/%s", dir, files[0]); } else { checked_asprintf(&buf, "/mnt/isodir/%s/%s", dir, files[0]); } if (doPwMount(buf, "/tmp/testmnt", "auto", "ro", NULL)) { free(buf); newtWinMessage(_("Error"), _("OK"), _("That directory does not contain installation media.")); umount("/mnt/isodir"); continue; } free(buf); if (access("/tmp/testmnt/.treeinfo", R_OK)) { newtWinMessage(_("Error"), _("OK"), _("That directory does not contain installation media.")); umount("/tmp/testmnt"); umount("/mnt/isodir"); continue; } umount("/tmp/testmnt"); umount("/mnt/isodir"); break; } checked_asprintf(&loaderData->instRepo, "hd:%s:/%s", selpart, dir); g_free(dir); loaderData->method = METHOD_HD; return LOADER_OK; } int kickstartFromHD(char *kssrc) { int rc; char *ksdev, *kspath; logMessage(INFO, "getting kickstart file from harddrive"); parseDeviceAndDir(kssrc, &ksdev, &kspath); if (!ksdev || !kspath) { logMessage(WARNING, "Format of command line is ks=hd:[device]:/path/to/ks.cfg"); return 1; } logMessage(INFO, "Loading ks from device %s on path %s", ksdev, kspath); if ((rc=getKickstartFromBlockDevice(ksdev, kspath))) { if (rc == 3) { startNewt(); newtWinMessage(_("Error"), _("OK"), _("Cannot find kickstart file on hard drive.")); } free(ksdev); free(kspath); return 1; } free(ksdev); free(kspath); return 0; } int kickstartFromBD(char *kssrc) { int rc; char *r = NULL, *ksdev, *kspath, *biosksdev; logMessage(INFO, "getting kickstart file from biosdrive"); parseDeviceAndDir(kssrc, &ksdev, &kspath); if (!ksdev || !kspath) { logMessage(WARNING, "Format of command line is ks=bd:device:/path/to/ks.cfg"); return 1; } r = strchr(ksdev, 'p'); if (!r) { logMessage(INFO, "Format of biosdisk is 80p1"); free(ksdev); free(kspath); return 1; } *r = '\0'; biosksdev = getBiosDisk(ksdev); if(!biosksdev){ startNewt(); newtWinMessage(_("Error"), _("OK"), _("Cannot find hard drive for BIOS disk %s"), ksdev); free(ksdev); free(kspath); return 1; } ksdev = malloc(strlen(biosksdev) + 3); sprintf(ksdev, "%s%s", biosksdev, r + 1); logMessage(INFO, "Loading ks from device %s on path %s", ksdev, kspath); if ((rc=getKickstartFromBlockDevice(ksdev, kspath))) { if (rc == 3) { startNewt(); newtWinMessage(_("Error"), _("OK"), _("Cannot find kickstart file on hard drive.")); } return 1; } return 0; } /* vim:set shiftwidth=4 softtabstop=4: */