/* * urlinstall.c - code to set up url (ftp/http) 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 "../pyanaconda/isys/iface.h" #include "../pyanaconda/isys/imount.h" #include "../pyanaconda/isys/log.h" #include "copy.h" #include "kickstart.h" #include "loader.h" #include "loadermisc.h" #include "lang.h" #include "method.h" #include "net.h" #include "method.h" #include "urlinstall.h" #include "cdinstall.h" #include "urls.h" #include "windows.h" #include "unpack.h" /* boot flags */ extern uint64_t flags; char **extraHeaders = NULL; static char **headers() { int len = 2; /* The list of HTTP headers is unlikely to change, unless a new ethernet * device suddenly shows up since last time we downloaded a file. So, * cache the result here to save some time. */ if (extraHeaders != NULL) return extraHeaders; if ((extraHeaders = realloc(extraHeaders, 2*sizeof(char *))) == NULL) { logMessage(CRITICAL, "%s: %d: %m", __func__, __LINE__); abort(); } checked_asprintf(&extraHeaders[0], "X-Anaconda-Architecture: %s", getProductArch()); checked_asprintf(&extraHeaders[1], "X-Anaconda-System-Release: %s", getProductName()); if (FL_KICKSTART_SEND_MAC(flags)) { /* find all ethernet devices and make a header entry for each one */ int i; char *dev, *mac; struct device **devices; devices = getDevices(DEVICE_NETWORK); for (i = 0; devices && devices[i]; i++) { dev = devices[i]->device; mac = iface_mac2str(dev); if (mac) { extraHeaders = realloc(extraHeaders, (len+1)*sizeof(char *)); checked_asprintf(&extraHeaders[len], "X-RHN-Provisioning-MAC-%d: %s %s", i, dev, mac); len++; free(mac); } } } if (FL_KICKSTART_SEND_SERIAL(flags) && !access("/usr/sbin/dmidecode", X_OK)) { FILE *f; char sn[1024]; size_t sn_len; if ((f = popen("/usr/sbin/dmidecode -s system-serial-number", "r")) == NULL) { logMessage(CRITICAL, "%s: %d: %m", __func__, __LINE__); abort(); } sn_len = fread(sn, sizeof(char), 1023, f); if (ferror(f)) { logMessage(CRITICAL, "%s: %d: %m", __func__, __LINE__); abort(); } sn[sn_len] = '\0'; pclose(f); extraHeaders = realloc(extraHeaders, (len+1)*sizeof(char *)); checked_asprintf(&extraHeaders[len], "X-System-Serial-Number: %s", sn); len++; } extraHeaders = realloc(extraHeaders, (len+1)*sizeof(char *)); extraHeaders[len] = NULL; return extraHeaders; } static int loadSingleUrlImage(struct loaderData_s *loaderData, const char *src, char *dest, char *mntpoint, int silentErrors) { char **ehdrs = NULL; int status; if (!strncmp(src, "http", 4)) ehdrs = headers(); status = urlinstTransfer(loaderData, src, ehdrs, dest); if (status) { if (!silentErrors) { newtWinMessage(_("Error"), _("OK"), _("Unable to retrieve %s."), src); } return 2; } if (dest != NULL) { if (doPwMount(dest, mntpoint, "auto", "ro", NULL)) { logMessage(ERROR, "Error mounting %s: %m", dest); return 1; } } return 0; } static void copyWarnFn (char *msg) { logMessage(WARNING, msg); } static void copyErrorFn (char *msg) { newtWinMessage(_("Error"), _("OK"), _(msg)); } int loadUrlImages(struct loaderData_s *loaderData) { char *url; logMessage(DEBUGLVL, "looking for extras for HTTP/FTP install"); if (!loaderData->instRepo) return 0; checked_asprintf(&url, "%s/images/%s", loaderData->instRepo, "updates.img"); if (!loadSingleUrlImage(loaderData, url, "/tmp/updates-disk.img", "/tmp/update-disk", 1)) { copyDirectory("/tmp/update-disk", "/tmp/updates", copyWarnFn, copyErrorFn); umount("/tmp/update-disk"); unlink("/tmp/updates-disk.img"); unlink("/tmp/update-disk"); } else if (!access("/tmp/updates-disk.img", R_OK)) { unpack_archive_file("/tmp/updates-disk.img", "/tmp/updates"); unlink("/tmp/updates-disk.img"); } free(url); checked_asprintf(&url, "%s/images/%s", loaderData->instRepo, "product.img"); if (!loadSingleUrlImage(loaderData, url, "/tmp/product-disk.img", "/tmp/product-disk", 1)) { copyDirectory("/tmp/product-disk", "/tmp/product", copyWarnFn, copyErrorFn); umount("/tmp/product-disk"); unlink("/tmp/product-disk.img"); unlink("/tmp/product-disk"); } free(url); return 0; } int promptForUrl(struct loaderData_s *loaderData) { char *url; do { if (urlMainSetupPanel(loaderData) == LOADER_BACK) { loaderData->instRepo = NULL; return LOADER_BACK; } checked_asprintf(&url, "%s/.treeinfo", loaderData->instRepo); if (getFileFromUrl(url, "/tmp/.treeinfo", loaderData)) { newtWinMessage(_("Error"), _("OK"), _("The URL provided does not contain installation media.")); free(url); continue; } free(url); break; } while (1); return LOADER_OK; } int getFileFromUrl(char * url, char * dest, struct loaderData_s * loaderData) { char **ehdrs = NULL; int rc; iface_t iface; iface_init_iface_t(&iface); if (kickstartNetworkUp(loaderData, &iface)) { logMessage(ERROR, "unable to bring up network"); return 1; } logMessage(INFO, "file location: %s", url); if (!strncmp(url, "http", 4)) { ehdrs = headers(); } rc = urlinstTransfer(loaderData, url, ehdrs, dest); if (rc) { logMessage(ERROR, "failed to retrieve %s", url); return 1; } return 0; } /* pull kickstart configuration file via http */ int kickstartFromUrl(char * url, struct loaderData_s * loaderData) { return getFileFromUrl(url, "/tmp/ks.cfg", loaderData); } /* vim:set shiftwidth=4 softtabstop=4: */