/* * method.c - generic install method setup functions * * Copyright (C) 2002 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 #include #include #include #include #include "copy.h" #include "loader.h" #include "loadermisc.h" #include "lang.h" #include "mediacheck.h" #include "method.h" #include "unpack.h" #include "../pyanaconda/isys/imount.h" #include "../pyanaconda/isys/isys.h" #include "../pyanaconda/isys/log.h" #include "nfsinstall.h" #include "hdinstall.h" #include "urlinstall.h" /* boot flags */ extern uint64_t flags; /* returns the *absolute* path (malloced) to the #1 iso image */ /* get timestamp and description of ISO image from stamp file */ /* returns 0 on success, -1 otherwise */ int readStampFileFromIso(char *file, char **timestamp, char **releasedescr) { DIR * dir; FILE *f; struct dirent * ent; struct stat sb; char *stampfile; char *descr, *tstamp; char tmpstr[1024]; int rc; lstat(file, &sb); if (S_ISBLK(sb.st_mode)) { if (doPwMount(file, "/mnt/install/testmnt", "iso9660", "ro", NULL)) { logMessage(ERROR, "Failed to mount device %s to get description", file); return -1; } } else if (S_ISREG(sb.st_mode)) { if (doPwMount(file, "/mnt/install/testmnt", "auto", "ro", NULL)) { logMessage(ERROR, "Failed to mount iso %s to get description", file); return -1; } } else { logMessage(ERROR, "Unknown type of file %s to get description", file); return -1; } if (!(dir = opendir("/mnt/install/testmnt"))) { umount("/mnt/install/testmnt"); return -1; } errno = 0; stampfile = NULL; while ((ent = readdir(dir))) { if (!strncmp(ent->d_name, ".discinfo", 9)) { stampfile = strdup(".discinfo"); break; } } closedir(dir); descr = NULL; tstamp = NULL; if (stampfile) { snprintf(tmpstr, sizeof(tmpstr), "/mnt/install/testmnt/%s", stampfile); f = fopen(tmpstr, "r"); if (f) { char *tmpptr; /* readtime stamp line */ tmpptr = fgets(tmpstr, sizeof(tmpstr), f); if (tmpptr) tstamp = strdup(tmpstr); /* now read OS description line */ if (tmpptr) tmpptr = fgets(tmpstr, sizeof(tmpstr), f); if (tmpptr) descr = strdup(tmpstr); fclose(f); } } free(stampfile); umount("/mnt/install/testmnt"); if (descr != NULL && tstamp != NULL) { descr[strlen(descr)-1] = '\0'; *releasedescr = descr; tstamp[strlen(tstamp)-1] = '\0'; *timestamp = tstamp; rc = 0; } else { rc = 1; } return rc; } /* XXX this ignores "location", which should be fixed * * Given a starting isoFile, will offer choice to mediacheck it and * all other ISO images in the same directory with the same stamp */ void queryIsoMediaCheck(char *isoFile) { DIR * dir; struct dirent * ent; char *isoDir; char isoImage[1024]; char tmpmessage[1024]; char *master_timestamp; char *tmpstr; int rc, first; /* dont bother to test in automated installs */ if (FL_KICKSTART(flags) && !FL_MEDIACHECK(flags)) return; /* if they did not specify to mediacheck explicitely then return */ if (!FL_MEDIACHECK(flags)) return; /* check that file is actually an iso */ if (!fileIsIso(isoFile)) return; /* get stamp of isoFile, free descr since we dont care */ readStampFileFromIso(isoFile, &master_timestamp, &tmpstr); free(tmpstr); /* get base path from isoFile */ tmpstr = strdup(isoFile); isoDir = strdup(dirname(tmpstr)); free(tmpstr); logMessage(DEBUGLVL, "isoFile = %s", isoFile); logMessage(DEBUGLVL, "isoDir = %s", isoDir); logMessage(DEBUGLVL, "Master Timestemp = %s", master_timestamp); if (!(dir = opendir(isoDir))) { newtWinMessage(_("Error"), _("OK"), _("Failed to read directory %s: %m"), isoDir); free(isoDir); free(master_timestamp); return; } /* Walk through the directories looking for a CD images. */ errno = 0; first = 0; while (1) { char *nextname; char *tdescr, *tstamp; if (first) { first = 1; nextname = isoFile; } else { ent = readdir(dir); if (!ent) break; nextname = ent->d_name; } /* synthesize name of iso from isoDir and file entry */ snprintf(isoImage, sizeof(isoImage), "%s/%s", isoDir, nextname); /* see if this is an iso image */ if (!fileIsIso(isoImage)) { errno = 0; continue; } /* see if its part of the current CD set */ readStampFileFromIso(isoImage, &tstamp, &tdescr); if (strcmp(tstamp, master_timestamp)) { errno = 0; continue; } /* found a valid candidate, proceed */ snprintf(tmpmessage, sizeof(tmpmessage), _("Would you like to perform a checksum " "test of the ISO image:\n\n %s?"), isoImage); rc = newtWinChoice(_("Checksum Test"), _("Test"), _("Skip"), tmpmessage); if (rc == 2) { logMessage(INFO, "mediacheck: skipped checking of %s", isoImage); if (tdescr) free(tdescr); continue; } else { doMediaCheck(isoImage, tdescr); if (tdescr) free(tdescr); continue; } } free(isoDir); free(master_timestamp); closedir(dir); } static void copyWarnFn (char *msg) { logMessage(WARNING, msg); } static void copyErrorFn (char *msg) { newtWinMessage(_("Error"), _("OK"), _(msg)); } void copyUpdatesImg(char * path) { if (!access(path, R_OK)) { if (!doPwMount(path, "/mnt/install/update-disk", "auto", "ro", NULL)) { copyDirectory("/mnt/install/update-disk", "/tmp/updates", copyWarnFn, copyErrorFn); umount("/mnt/install/update-disk"); unlink("/mnt/install/update-disk"); } else { unpack_archive_file(path, "/tmp/updates"); } } } void copyProductImg(char * path) { if (!access(path, R_OK)) { if (!doPwMount(path, "/mnt/install/product-disk", "auto", "ro", NULL)) { copyDirectory("/mnt/install/product-disk", "/tmp/product", copyWarnFn, copyErrorFn); umount("/mnt/install/product-disk"); unlink("/mnt/install/product-disk"); } } } /* given a device name (w/o '/dev' on it), try to get a file */ /* Error codes: 1 - could not create device node 2 - could not mount device as ext2, vfat, or iso9660 3 - file named path not there */ int getFileFromBlockDevice(char *device, char *path, char * dest) { int rc, i; char file[4096]; logMessage(INFO, "getFileFromBlockDevice(%s, %s)", device, path); /* some USB thumb drives and hard drives are slow to initialize */ /* retry up to 5 times or 31 seconds */ rc = doPwMount(device, "/mnt/install/testmnt", "auto", "ro", NULL); for (i = 0; mountMightSucceedLater(rc) && i < 5; ++i) { logMessage(INFO, "sleeping to wait for USB storage devices"); sleep(1 << i); rc = doPwMount(device, "/mnt/install/testmnt", "auto", "ro", NULL); logMessage(ERROR, "error code: %d", rc); } if (rc) { logMessage(ERROR, "failed to mount /dev/%s: %m", device); return 2; } snprintf(file, sizeof(file), "/mnt/install/testmnt/%s", path); logMessage(INFO, "Searching for file on path %s", file); if (access(file, R_OK)) { rc = 3; } else { copyFile(file, dest); rc = 0; logMessage(INFO, "file copied to %s", dest); } umount("/mnt/install/testmnt"); unlink("/mnt/install/testmnt"); return rc; }