IT IS ACCOMPLISHED. --- loader/.gitignore | 10 - loader/Makefile.am | 97 -- loader/cdinstall.c | 421 --------- loader/cdinstall.h | 31 - loader/copy.c | 141 --- loader/copy.h | 26 - loader/dirbrowser.c | 208 ----- loader/dirbrowser.h | 32 - loader/driverdisk.c | 795 ---------------- loader/driverdisk.h | 50 - loader/driverselect.c | 243 ----- loader/fwloader.c | 673 -------------- loader/fwloader.h | 35 - loader/getparts.c | 131 --- loader/getparts.h | 27 - loader/hardware.c | 150 --- loader/hardware.h | 28 - loader/hdinstall.c | 407 -------- loader/hdinstall.h | 30 - loader/ibft.c | 105 --- loader/ibft.h | 45 - loader/kbd.c | 152 --- loader/kbd.h | 25 - loader/keymaps-i386 | Bin 12173 -> 0 bytes loader/keymaps-ppc | Bin 12871 -> 0 bytes loader/keymaps-x86_64 | Bin 12173 -> 0 bytes loader/kickstart.c | 1108 ---------------------- loader/kickstart.h | 29 - loader/lang.c | 479 ---------- loader/lang.h | 42 - loader/loader.c | 2441 ------------------------------------------------ loader/loader.h | 193 ---- loader/loadermisc.c | 168 ---- loader/loadermisc.h | 33 - loader/mediacheck.c | 115 --- loader/mediacheck.h | 25 - loader/method.c | 333 ------- loader/method.h | 51 - loader/moduleinfo.c | 274 ------ loader/moduleinfo.h | 78 -- loader/modules.c | 551 ----------- loader/modules.h | 50 - loader/net.c | 2466 ------------------------------------------------- loader/net.h | 109 --- loader/nfsinstall.c | 473 ---------- loader/nfsinstall.h | 31 - loader/readvars.c | 125 --- loader/readvars.h | 29 - loader/rpmextract.c | 260 ------ loader/rpmextract.h | 46 - loader/selinux.c | 56 -- loader/selinux.h | 27 - loader/serial.c | 222 ----- loader/serial.h | 9 - loader/simplemot | 81 -- loader/udelay.h | 199 ---- loader/unpack.c | 164 ---- loader/unpack.h | 34 - loader/urlinstall.c | 259 ------ loader/urlinstall.h | 32 - loader/urls.c | 381 -------- loader/urls.h | 31 - loader/windows.c | 116 --- loader/windows.h | 42 - 64 files changed, 0 insertions(+), 15024 deletions(-) delete mode 100644 loader/.gitignore delete mode 100644 loader/Makefile.am delete mode 100644 loader/cdinstall.c delete mode 100644 loader/cdinstall.h delete mode 100644 loader/copy.c delete mode 100644 loader/copy.h delete mode 100644 loader/dirbrowser.c delete mode 100644 loader/dirbrowser.h delete mode 100644 loader/driverdisk.c delete mode 100644 loader/driverdisk.h delete mode 100644 loader/driverselect.c delete mode 100644 loader/fwloader.c delete mode 100644 loader/fwloader.h delete mode 100644 loader/getparts.c delete mode 100644 loader/getparts.h delete mode 100644 loader/hardware.c delete mode 100644 loader/hardware.h delete mode 100644 loader/hdinstall.c delete mode 100644 loader/hdinstall.h delete mode 100644 loader/ibft.c delete mode 100644 loader/ibft.h delete mode 100644 loader/kbd.c delete mode 100644 loader/kbd.h delete mode 100644 loader/keymaps-i386 delete mode 100644 loader/keymaps-ppc delete mode 100644 loader/keymaps-x86_64 delete mode 100644 loader/kickstart.c delete mode 100644 loader/kickstart.h delete mode 100644 loader/lang.c delete mode 100644 loader/lang.h delete mode 100644 loader/loader.c delete mode 100644 loader/loader.h delete mode 100644 loader/loadermisc.c delete mode 100644 loader/loadermisc.h delete mode 100644 loader/mediacheck.c delete mode 100644 loader/mediacheck.h delete mode 100644 loader/method.c delete mode 100644 loader/method.h delete mode 100644 loader/moduleinfo.c delete mode 100644 loader/moduleinfo.h delete mode 100644 loader/modules.c delete mode 100644 loader/modules.h delete mode 100644 loader/net.c delete mode 100644 loader/net.h delete mode 100644 loader/nfsinstall.c delete mode 100644 loader/nfsinstall.h delete mode 100644 loader/readvars.c delete mode 100644 loader/readvars.h delete mode 100644 loader/rpmextract.c delete mode 100644 loader/rpmextract.h delete mode 100644 loader/selinux.c delete mode 100644 loader/selinux.h delete mode 100644 loader/serial.c delete mode 100644 loader/serial.h delete mode 100755 loader/simplemot delete mode 100644 loader/udelay.h delete mode 100644 loader/unpack.c delete mode 100644 loader/unpack.h delete mode 100644 loader/urlinstall.c delete mode 100644 loader/urlinstall.h delete mode 100644 loader/urls.c delete mode 100644 loader/urls.h delete mode 100644 loader/windows.c delete mode 100644 loader/windows.h diff --git a/loader/.gitignore b/loader/.gitignore deleted file mode 100644 index c894638..0000000 --- a/loader/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -loader -init -debug.log -loader.tr -.depend -font.bgf.gz -loader.po -shutdown -checkisomd5 -tr diff --git a/loader/Makefile.am b/loader/Makefile.am deleted file mode 100644 index 243817c..0000000 --- a/loader/Makefile.am +++ /dev/null @@ -1,97 +0,0 @@ -# loader/Makefile.am for anaconda -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Author: David Cantrell <dcantrell@xxxxxxxxxx> - -bootdir = $(libdir)/$(PACKAGE_NAME) -shareddir = $(datadir)/$(PACKAGE_NAME) - -boot_PROGRAMS = loader -shared_DATA = loader.tr -noinst_PROGRAMS = dirbrowser -noinst_HEADERS = *.h - -if IS_S390 -dist_shared_SCRIPTS = linuxrc.s390 -endif - -if IS_KEYMAPS_OVERRIDE_ARCH -keymapsdir = $(datadir)/$(PACKAGE_NAME) -keymaps_DATA = keymaps-override-$(ARCH) -endif - -COMMON_CFLAGS = -DUSE_LOGDEV -DVERSION='"$(PACKAGE_VERSION)"' - -loader_CFLAGS = $(COMMON_CFLAGS) $(GLIB_CFLAGS) $(LIBNM_GLIB_CFLAGS) \ - $(LIBCURL_CFLAGS) $(IPV6_CFLAGS) $(LIBARCHIVE_CFLAGS) \ - $(RPM_CFLAGS) $(PYTHON_INCLUDES) -DINCLUDE_LOCAL -DINCLUDE_NETWORK \ - -fno-strict-aliasing -loader_LDADD = $(NEWT_LIBS) $(GLIB_LIBS) $(LIBNL_LIBS) $(PYTHON_EMBED_LIBS) \ - $(LIBNM_GLIB_LIBS) $(CHECKISOMD5_LIBS) \ - $(LIBCURL_LIBS) $(LIBARCHIVE_LIBS) $(RPM_LIBS) \ - $(ISCSI_LIBS) $(top_srcdir)/pyanaconda/isys/libisys.la -lm -loader_SOURCES = loader.c copy.c moduleinfo.c loadermisc.c \ - modules.c windows.c lang.c kbd.c driverdisk.c \ - selinux.c mediacheck.c kickstart.c driverselect.c \ - getparts.c dirbrowser.c fwloader.c ibft.c hardware.c \ - method.c cdinstall.c hdinstall.c nfsinstall.c \ - urlinstall.c net.c urls.c rpmextract.c readvars.c \ - serial.c unpack.c - -dirbrowser_CFLAGS = $(COMMON_CFLAGS) -DSTANDALONE -dirbrowser_LDADD = $(NEWT_LIBS) -dirbrowser_SOURCES = dirbrowser.c - -EXTRA_DIST = simplemot keymaps-* - -CLEANFILES = keymaps-override-$(ARCH) tr/*.tr - -MAINTAINERCLEANFILES = Makefile.in - -sed_verbose = $(sed_verbose_$(V)) -sed_verbose_ = $(sed_verbose_$(AM_DEFAULT_VERBOSITY)) -sed_verbose_0 = @echo " SED "$@; - -cp_verbose = $(cp_verbose_$(V)) -cp_verbose_ = $(cp_verbose_$(AM_DEFAULT_VERBOSITY)) -cp_verbose_0 = @echo " CP "$@; - -msgmerge_verbose = $(msgmerge_verbose_$(V)) -msgmerge_verbose_ = $(msgmerge_verbose_$(AM_DEFAULT_VERBOSITY)) -msgmerge_verbose_0 = echo " MERGE "$${lang}.po; - -xgettext_verbose = $(xgettext_verbose_$(V)) -xgettext_verbose_ = $(xgettext_verbose_$(AM_DEFAULT_VERBOSITY)) -xgettext_verbose_0 = @echo " GETTXT "$@; - -keymaps-override-$(ARCH): keymaps-$(ARCH) - $(cp_verbose)cp -p $< $@ - -loader.tr: $(top_srcdir)/data/lang-table loader.po - @LANGS="`cut -f 2 $(top_srcdir)/data/lang-table | egrep -v '(^en$$)'`" ; \ - if [ ! -d tr ]; then \ - mkdir -p tr ; \ - fi ; \ - for lang in $$LANGS ; do \ - $(msgmerge_verbose)msgmerge -q $(top_srcdir)/po/$$lang.po loader.po | msgconv -t utf-8 | ./simplemot > tr/$$lang.tr ; \ - done ; \ - (cd tr ; ls -1 *.tr | cpio --quiet -Hcrc -o | gzip -9) > $@ - -loader.po: - $(xgettext_verbose)xgettext --default-domain=loader --add-comments \ - --keyword=_ --keyword=N_ *.c - $(sed_verbose)sed -i 's/charset=CHARSET/charset=UTF-8/' $@ diff --git a/loader/cdinstall.c b/loader/cdinstall.c deleted file mode 100644 index b0f8ffb..0000000 --- a/loader/cdinstall.c +++ /dev/null @@ -1,421 +0,0 @@ -/* - * cdinstall.c - code to set up cdrom 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <ctype.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <newt.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mount.h> -#include <sys/ioctl.h> -#include <unistd.h> -/* FIXME Remove hack when: https://bugzilla.redhat.com/show_bug.cgi?id=478663 - is resolved */ -/* Hack both __BIG_ENDIAN and __LITTLE_ENDIAN get defined by glibc, the - kernel headers we need do not like this! */ -#if __BYTE_ORDER == __LITTLE_ENDIAN -#undef __BIG_ENDIAN -#else -#undef __LITTLE_ENDIAN -#endif -#include <asm/types.h> -#include <limits.h> -#include <linux/cdrom.h> - -#include "kickstart.h" -#include "loader.h" -#include "loadermisc.h" -#include "lang.h" -#include "modules.h" -#include "method.h" -#include "cdinstall.h" -#include "mediacheck.h" -#include "windows.h" - -#include "../pyanaconda/isys/imount.h" -#include "../pyanaconda/isys/isys.h" -#include "../pyanaconda/isys/log.h" -#include "../pyanaconda/isys/mem.h" - -/* boot flags */ -extern uint64_t flags; - -/* ejects the CD device the device node points at */ -static void ejectCdrom(char *device) { - int ejectfd; - - if (!device) return; - - if (FL_NOEJECT(flags)) { - logMessage(INFO, "noeject in effect, not ejecting cdrom"); - return; - } - - logMessage(INFO, "ejecting %s...",device); - if ((ejectfd = open(device, O_RDONLY | O_NONBLOCK, 0)) >= 0) { - ioctl(ejectfd, CDROM_LOCKDOOR, 0); - if (ioctl(ejectfd, CDROMEJECT, 0)) - logMessage(ERROR, "eject failed on device %s: %m", device); - close(ejectfd); - } else { - logMessage(ERROR, "could not open device %s: %m", device); - } -} - -static char *cdrom_drive_status(int rc) { - struct { - int code; - char *str; - } status_codes[] = - { - { CDS_NO_INFO, "CDS_NO_INFO" }, - { CDS_NO_DISC, "CDS_NO_DISC" }, - { CDS_TRAY_OPEN, "CDS_TRAY_OPEN" }, - { CDS_DRIVE_NOT_READY, "CDS_DRIVE_NOT_READY" }, - { CDS_DISC_OK, "CDS_DISC_OK" }, - { CDS_AUDIO, "CDS_AUDIO" }, - { CDS_DATA_1, "CDS_DATA_1" }, - { CDS_DATA_2, "CDS_DATA_2" }, - { CDS_XA_2_1, "CDS_XA_2_1" }, - { CDS_XA_2_2, "CDS_XA_2_2" }, - { CDS_MIXED, "CDS_MIXED" }, - { INT_MAX, NULL }, - }; - int i; - - if (rc < 0) - return strerror(-rc); - - for (i = 0; status_codes[i].code != INT_MAX; i++) { - if (status_codes[i].code == rc) - return status_codes[i].str; - } - return NULL; -} - -static int waitForCdromTrayClose(int fd) { - int rc; - int prev = INT_MAX; - - do { - char *status = NULL; - rc = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); - if (rc < 0) - rc = -errno; - - /* only bother to print the status if it changes */ - if (prev == INT_MAX || prev != rc) { - status = cdrom_drive_status(rc); - if (status != NULL) { - logMessage(INFO, "drive status is %s", status); - } else { - logMessage(INFO, "drive status is unknown status code %d", rc); - } - } - prev = rc; - if (rc == CDS_DRIVE_NOT_READY) - usleep(100000); - } while (rc == CDS_DRIVE_NOT_READY); - return rc; -} - -static void closeCdromTray(char *device) { - int fd; - - if (!device || !*device) - return; - - logMessage(INFO, "closing CD tray on %s .", device); - if ((fd = open(device, O_RDONLY | O_NONBLOCK, 0)) >= 0) { - if (ioctl(fd, CDROMCLOSETRAY, 0)) { - logMessage(ERROR, "closetray failed on device %s: %m", device); - } else { - waitForCdromTrayClose(fd); - ioctl(fd, CDROM_LOCKDOOR, 1); - } - close(fd); - } else { - logMessage(ERROR, "could not open device %s: %m", device); - } -} - -/* Given cd device cddriver, this function will attempt to check its internal - * checksum. - */ -static void mediaCheckCdrom(char *cddriver) { - char *descr, *tstamp; - - closeCdromTray(cddriver); - readStampFileFromIso(cddriver, &tstamp, &descr); - doMediaCheck(cddriver, descr); - - if (descr) - free(descr); - - if (tstamp) - free(tstamp); -} - -/* output an error message when CD in drive is not the correct one */ -/* Used by mountCdromStage2() */ -static void wrongCDMessage(void) { - newtWinMessage(_("Error"), _("OK"), - _("The %s disc was not found " - "in any of your drives. Please insert " - "the %s disc and press %s to retry."), - getProductName(), getProductName(), _("OK")); -} - -/* ask about doing media check */ -void queryCDMediaCheck(char *instRepo) { - int rc; - char *tmp, *device; - - /* dont bother to test in automated installs */ - if (FL_KICKSTART(flags) && !FL_MEDIACHECK(flags)) - return; - - /* Skip over the leading "cdrom://". */ - tmp = instRepo+8; - checked_asprintf(&device, "%.*s", (int) (strchr(tmp, ':')-tmp), tmp); - - /* see if we should check image(s) */ - /* in rescue mode only test if they explicitly asked to */ - if (!FL_RESCUE(flags) || FL_MEDIACHECK(flags)) { - startNewt(); - rc = newtWinChoice(_("Disc Found"), _("OK"), _("Skip"), - _("To begin testing the media before installation press %s.\n\n" - "Choose %s to skip the media test and start the installation."), - _("OK"), _("Skip")); - - if (rc != 2) { - /* We already mounted the CD earlier to verify there's installation - * media. Now we need to unmount it to perform the check, then - * remount to pretend nothing ever happened. - */ - umount("/mnt/install/source"); - mediaCheckCdrom(device); - - do { - if (doPwMount(device, "/mnt/install/source", "iso9660", "ro", NULL)) { - ejectCdrom(device); - wrongCDMessage(); - continue; - } - - if (access("/mnt/install/source/.discinfo", R_OK)) { - umount("/mnt/install/source"); - ejectCdrom(device); - wrongCDMessage(); - continue; - } - - break; - } while (1); - } - } - - free(device); -} - -int findInstallCD(struct loaderData_s *loaderData) { - int i, rc; - struct device **devices; - - devices = getDevices(DEVICE_CDROM); - if (!devices) { - logMessage(ERROR, "got to findInstallCD without a CD device"); - return LOADER_ERROR; - } - - for (i = 0; devices[i]; i++) { - char *tmp = NULL; - int fd; - - if (!devices[i]->device) - continue; - - if (strncmp("/dev/", devices[i]->device, 5)) { - checked_asprintf(&tmp, "/dev/%s", devices[i]->device); - - free(devices[i]->device); - devices[i]->device = tmp; - } - - logMessage(INFO, "trying to mount CD device %s on /mnt/install/source", - devices[i]->device); - - if (!FL_CMDLINE(flags)) - winStatus(60, 3, _("Scanning"), _("Looking for installation media on CD device %s\n"), devices[i]->device); - else - printf(_("Looking for installation media on CD device %s"), devices[i]->device); - - fd = open(devices[i]->device, O_RDONLY | O_NONBLOCK); - if (fd < 0) { - logMessage(ERROR, "Couldn't open %s: %m", devices[i]->device); - if (!FL_CMDLINE(flags)) - newtPopWindow(); - continue; - } - - rc = waitForCdromTrayClose(fd); - close(fd); - switch (rc) { - case CDS_NO_INFO: - logMessage(ERROR, "Drive tray reports CDS_NO_INFO"); - break; - case CDS_NO_DISC: - if (!FL_CMDLINE(flags)) - newtPopWindow(); - continue; - case CDS_TRAY_OPEN: - logMessage(ERROR, "Drive tray reports open when it should be closed"); - break; - default: - break; - } - - if (!FL_CMDLINE(flags)) - newtPopWindow(); - - if ((rc = doPwMount(devices[i]->device, "/mnt/install/source", "iso9660", "ro", NULL)) == 0) { - if (!access("/mnt/install/source/.treeinfo", R_OK) && !access("/mnt/install/source/.discinfo", R_OK)) { - loaderData->method = METHOD_CDROM; - checked_asprintf(&loaderData->instRepo, "cdrom://%s:/mnt/install/source", devices[i]->device); - return LOADER_OK; - } else { - /* This wasn't the CD we were looking for. Clean up and - * try the next drive. - */ - umount("/mnt/install/source"); - } - } - } - - return LOADER_ERROR; -} - -int promptForCdrom(struct loaderData_s *loaderData) { - int rc; - - do { - rc = findInstallCD(loaderData); - - if (loaderData->instRepo && rc == LOADER_OK) { - queryCDMediaCheck(loaderData->instRepo); - return rc; - } else { - char * buf; - - checked_asprintf(&buf, _("The %s disc was not found in any of your " - "CDROM drives. Please insert the %s disc " - "and press %s to retry."), - getProductName(), getProductName(), _("OK")); - - rc = newtWinChoice(_("Disc Not Found"), - _("OK"), _("Back"), buf, _("OK")); - free(buf); - if (rc == 2) - return LOADER_BACK; - } - } while (!loaderData->instRepo); - - return LOADER_OK; -} - -int loadCdromImages(struct loaderData_s *loaderData) { - char *device = NULL; - char *tmp; - - logMessage(DEBUGLVL, "looking for extras for CD/DVD install"); - - if (!loaderData->instRepo) - return 0; - - /* Skip over the leading "cdrom://". */ - tmp = loaderData->instRepo+8; - checked_asprintf(&device, "%.*s", (int) (strchr(tmp, ':')-tmp), tmp); - - if (doPwMount(device, "/mnt/install/source", "auto", "ro", NULL)) - return 0; - - logMessage(INFO, "Looking for updates in /mnt/install/source/images/updates.img"); - copyUpdatesImg("/mnt/install/source/images/updates.img"); - - logMessage(INFO, "Looking for product in /mnt/install/source/images/product.img"); - copyProductImg("/mnt/install/source/images/product.img"); - - umount("/mnt/install/source"); - return 1; -} - -int kickstartFromCD(char *kssrc) { - int rc, i; - char *p, *kspath; - struct device ** devices; - - logMessage(INFO, "getting kickstart file from first CDROM"); - - devices = getDevices(DEVICE_CDROM); - /* usb can take some time to settle, even with the various hacks we - * have in place. some systems use portable USB CD-ROM drives, try to - * make sure there really isn't one before bailing */ - for (i = 0; !devices && i < 10; ++i) { - logMessage(INFO, "sleeping to wait for a USB CD-ROM"); - sleep(2); - devices = getDevices(DEVICE_CDROM); - } - if (!devices) { - logMessage(ERROR, "No CDROM devices found!"); - return 1; - } - - /* format is cdrom:[/path/to/ks.cfg] */ - kspath = ""; - p = strchr(kssrc, ':'); - if (p) - kspath = p + 1; - - if (!p || strlen(kspath) < 1) - kspath = "/ks.cfg"; - - for (i=0; devices[i]; i++) { - if (!devices[i]->device) - continue; - - rc = getKickstartFromBlockDevice(devices[i]->device, kspath); - if (rc == 0) - return 0; - } - - startNewt(); - newtWinMessage(_("Error"), _("OK"), - _("Cannot find kickstart file on CDROM.")); - return 1; -} - -/* vim:set shiftwidth=4 softtabstop=4 et */ diff --git a/loader/cdinstall.h b/loader/cdinstall.h deleted file mode 100644 index f883e7a..0000000 --- a/loader/cdinstall.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * cdinstall.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef H_CDINSTALL -#define H_CDINSTALL - -#include "method.h" - -int findInstallCD(struct loaderData_s *loaderData); -int promptForCdrom(struct loaderData_s *loaderData); -int loadCdromImages(struct loaderData_s *loaderData); -void queryCDMediaCheck(char *instRepo); - -int kickstartFromCD(char *kssrc); -#endif diff --git a/loader/copy.c b/loader/copy.c deleted file mode 100644 index 1c61233..0000000 --- a/loader/copy.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * copy.c - functions for copying files and directories - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "lang.h" - -/* Recursive */ -int copyDirectory(char * from, char * to, void (*warnFn)(char *), - void (*errorFn)(char *)) { - char *msg; - DIR * dir; - struct dirent * ent; - int fd, outfd; - char buf[4096]; - int i; - struct stat sb; - char filespec[256]; - char filespec2[256]; - char link[1024]; - - mkdir(to, 0755); - - if (!(dir = opendir(from))) { - if (errorFn) { - if (asprintf(&msg, N_("Failed to read directory %s: %m"), from) == -1) { - fprintf(stderr, "%s: %d: %m\n", __func__, __LINE__); - fflush(stderr); - abort(); - } - - errorFn(msg); - free(msg); - } - - return 1; - } - - errno = 0; - while ((ent = readdir(dir))) { - if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) - continue; - - sprintf(filespec, "%s/%s", from, ent->d_name); - sprintf(filespec2, "%s/%s", to, ent->d_name); - - lstat(filespec, &sb); - - if (S_ISDIR(sb.st_mode)) { - if (copyDirectory(filespec, filespec2, warnFn, errorFn)) { - closedir(dir); - return 1; - } - } else if (S_ISLNK(sb.st_mode)) { - i = readlink(filespec, link, sizeof(link) - 1); - link[i] = '\0'; - if (symlink(link, filespec2)) { - if (warnFn) { - if (asprintf(&msg, "Failed to symlink %s to %s: %m", - filespec2, link) == -1) { - fprintf(stderr, "%s: %d: %m\n", __func__, __LINE__); - fflush(stderr); - abort(); - } - - warnFn(msg); - free(msg); - } - } - } else { - fd = open(filespec, O_RDONLY); - if (fd == -1) { - if (errorFn) { - if (asprintf(&msg, "Failed to open %s: %m", filespec) == -1) { - fprintf(stderr, "%s: %d: %m\n", __func__, __LINE__); - fflush(stderr); - abort(); - } - - errorFn(msg); - free(msg); - } - - closedir(dir); - return 1; - } - outfd = open(filespec2, O_RDWR | O_TRUNC | O_CREAT, 0644); - if (outfd == -1) { - if (warnFn) { - if (asprintf(&msg, "Failed to create %s: %m", filespec2) == -1) { - fprintf(stderr, "%s: %d: %m\n", __func__, __LINE__); - fflush(stderr); - abort(); - } - - warnFn(msg); - free(msg); - } - } else { - fchmod(outfd, sb.st_mode & 07777); - - while ((i = read(fd, buf, sizeof(buf))) > 0) - i = write(outfd, buf, i); - close(outfd); - } - - close(fd); - } - - errno = 0; - } - - closedir(dir); - - return 0; -} diff --git a/loader/copy.h b/loader/copy.h deleted file mode 100644 index 1153bf8..0000000 --- a/loader/copy.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * copy.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef H_COPY -#define H_COPY - -int copyDirectory (char *from, char *to, void (*warnFn)(char *), - void (*errorFn)(char *)); - -#endif diff --git a/loader/dirbrowser.c b/loader/dirbrowser.c deleted file mode 100644 index e4bc9d4..0000000 --- a/loader/dirbrowser.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * dirbrowser.c - newt-based directory browser to get a file name - * - * Copyright (C) 2004 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <newt.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/types.h> -#include <dirent.h> -#include <errno.h> -#include <string.h> -#include <sys/stat.h> - -#include "dirbrowser.h" - -#ifndef STANDALONE -#include "../pyanaconda/isys/log.h" - -#include "loader.h" -#include "loadermisc.h" -#include "lang.h" -#endif - -#ifdef STANDALONE -#define _(x) x - -static int simpleStringCmp(const void * a, const void * b) { - const char * first = *((const char **) a); - const char * second = *((const char **) b); - - return strcmp(first, second); -} -#endif - -#define FSTEP 10 - -/* Return a NULL terminated list of the directory contents, non-recursively. - * Return a NULL if the directory cannot be opened. - * - * dirname -- The directory to list. - * filterfunc -- An optional function to use for filtering out the results. - * If this function returns 1, the directory is included. - * Otherwise, it is omitted. - */ -char ** get_file_list(char * dirname, filterfunc_t filterfunc) { - DIR * dir; - struct dirent *entry; - char ** files; - int numfiles = FSTEP, i = 0; - - dir = opendir(dirname); - if (dir == NULL) { - fprintf(stderr, "error opening %s: %m", dirname); - return NULL; - } - - files = malloc(numfiles * sizeof(char *)); - - while ((entry = readdir(dir))) { - if ((strlen(entry->d_name) == 1) && !strncmp(entry->d_name, ".", 1)) - continue; - if ((strlen(entry->d_name) == 2) && !strncmp(entry->d_name, "..", 2)) - continue; - if (filterfunc && !filterfunc(dirname, entry)) - continue; - - files[i] = strdup(entry->d_name); - if (i++ >= (numfiles - 1)) { - numfiles += FSTEP; - files = realloc(files, numfiles * sizeof(char *)); - } - } - files[i] = NULL; - closedir(dir); - - qsort(files, i, sizeof(*files), simpleStringCmp); - return files; -} - -/* Browse through a directory structure looking for a file. - * Returns the full path to the file. - * - * Parameters: - * title: Title for newt dialog window - * dirname: Directory to use for root of browsing. NOTE: you cannot go - * up above this root. - * filterfunc: An (optional) function to filter out files based on whatever - * criteria you want. Returns 1 if it passes, 0 if not. - * Function should take arguments of the directory name and - * the dirent for the file. - */ -char * newt_select_file(char * title, char * text, char * dirname, - filterfunc_t filterfunc) { - char ** files; - char * fn = NULL; - int i, done = 0; - char * topdir = dirname; - char * dir = malloc(PATH_MAX); - char * path = NULL; - newtGrid grid, buttons; - newtComponent f, tb, listbox, ok, cancel; - struct stat sb; - struct newtExitStruct es; - - dir = realpath(dirname, dir); - - do { - files = get_file_list(dir, filterfunc); - - f = newtForm(NULL, NULL, 0); - grid = newtCreateGrid(1, 4); - - tb = newtTextboxReflowed(-1, -1, text, 60, 0, 10, 0); - - listbox = newtListbox(12, 65, 10, - NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); - - newtListboxSetWidth(listbox, 55); - buttons = newtButtonBar(_("OK"), &ok, _("Cancel"), &cancel, NULL); - newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, tb, - 0, 0, 0, 1, 0, 0); - newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, listbox, - 0, 0, 0, 1, 0, 0); - newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons, - 0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX); - - /* if this isn't our topdir, we want to let them go up a dir */ - if (strcmp(topdir, dir)) - newtListboxAppendEntry(listbox, "../", ".."); - - for (i = 0; files && (files[i] != NULL); i++) { - if ((files[i] == NULL) || (strlen(files[i]) == 0)) continue; - path = malloc(strlen(files[i]) + strlen(dir) + 2); - sprintf(path, "%s/%s", dir, files[i]); - stat(path, &sb); - free(path); - if (S_ISDIR(sb.st_mode)) { - char *dir = malloc(strlen(files[i]) + 2); - sprintf(dir, "%s/", files[i]); - newtListboxAppendEntry(listbox, dir, files[i]); - } else { - newtListboxAppendEntry(listbox, files[i], files[i]); - } - } - - newtGridWrappedWindow(grid, title); - newtGridAddComponentsToForm(grid, f, 1); - newtFormRun(f, &es); - - if (es.reason == NEWT_EXIT_COMPONENT && es.u.co == cancel) { - fn = NULL; - done = -1; - } else { - fn = (char *) newtListboxGetCurrent(listbox); - path = malloc(strlen(fn) + strlen(dir) + 2); - sprintf(path, "%s/%s", dir, fn); - - stat(path, &sb); - if (!S_ISDIR(sb.st_mode)) { - fn = path; - done = 1; - } else { - dir = realpath(path, dir); - free(path); - } - } - - newtGridFree(grid, 1); - newtFormDestroy(f); - newtPopWindow(); - } while (done == 0); - - return fn; -} - -#ifdef STANDALONE -int main(int argc, char ** argv) { - char * foo; - - newtInit(); - newtCls(); - - foo = newt_select_file("Get File Name", "foo, blah blah blah", - "/etc", NULL); - newtFinished(); - printf("got %s\n", foo); - return 0; -} -#endif diff --git a/loader/dirbrowser.h b/loader/dirbrowser.h deleted file mode 100644 index 77f5681..0000000 --- a/loader/dirbrowser.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * dirbrowser.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef DIRBROWSER_H -#define DIRBROWSER_H - -#include <dirent.h> - -typedef int (*filterfunc_t)(char *, struct dirent *); - -char **get_file_list(char *dirname, filterfunc_t filterfunc); - -char * newt_select_file(char * title, char * text, char * dirname, - filterfunc_t filterfunc); - -#endif diff --git a/loader/driverdisk.c b/loader/driverdisk.c deleted file mode 100644 index f6af331..0000000 --- a/loader/driverdisk.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - * driverdisk.c - driver disk functionality - * - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <errno.h> -#include <fcntl.h> -#include <newt.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> -#include <glib.h> - -#include <blkid/blkid.h> - -#include <glob.h> -#include <rpm/rpmlib.h> -#include <sys/utsname.h> - -#include "copy.h" -#include "loader.h" -#include "loadermisc.h" -#include "lang.h" -#include "fwloader.h" -#include "method.h" -#include "modules.h" -#include "moduleinfo.h" -#include "windows.h" -#include "hardware.h" -#include "driverdisk.h" -#include "getparts.h" -#include "dirbrowser.h" - -#include "nfsinstall.h" -#include "urlinstall.h" - -#include "rpmextract.h" -#include "unpack.h" - -#include "../pyanaconda/isys/isys.h" -#include "../pyanaconda/isys/imount.h" -#include "../pyanaconda/isys/eddsupport.h" -#include "../pyanaconda/isys/log.h" - -/* boot flags */ -extern uint64_t flags; - -/* - * check if the RPM in question provides - * Provides: <dep> = <version> - * we use it to check if kernel-modules = <kernelversion> - */ -int dlabelProvides(const char* dep, const char* version, void *userptr) -{ - char *kernelver = (char*)userptr; - - logMessage(DEBUGLVL, "Provides: %s = %s", dep, version); - - if (version == NULL) - return -1; - - return strcmp(dep, "kernel-modules") || strcmp(version, kernelver); -} - -/* - * during cpio extraction, only extract files we need - * eg. module .ko files and firmware directory - */ -int dlabelFilter(const char* name, const struct stat *fstat, void *userptr) -{ - int l = strlen(name); - - logMessage(DEBUGLVL, "Unpacking %s", name); - - /* we want firmware files */ - if (strstr(name, "lib/firmware/") == NULL) - return 0; - - if (l<3) - return 1; - l-=3; - - /* and we want only .ko files */ - if (strcmp(".ko", name+l)) - return 1; - - /* TODO we are unpacking kernel module, read it's description */ - - return 0; -} - -char* moduleDescription(const char* modulePath) -{ - char *command = NULL; - FILE *f = NULL; - char *description = NULL; - int size; - - checked_asprintf(&command, "modinfo --description '%s'", modulePath); - f = popen(command, "r"); - free(command); - - if (f==NULL) - return NULL; - - description = malloc(sizeof(char)*256); - if (!description) - return NULL; - - size = fread(description, 1, 255, f); - if (size == 0) { - free(description); - return NULL; - } - - description[size-1]=0; /* strip the trailing newline */ - pclose(f); - - return description; -} - -int globErrFunc(const char *epath, int eerrno) -{ - /* TODO check fatal errors */ - - return 0; -} - -int dlabelUnpackRPMDir(char* rpmdir, char* destination, char *kernelver) -{ - char *globpattern; - int rc = 0; - - checked_asprintf(&globpattern, "%s/*.rpm", rpmdir); - glob_t globres; - char** globitem; - if (!glob(globpattern, GLOB_NOSORT|GLOB_NOESCAPE, globErrFunc, &globres)) { - /* iterate over all rpm files */ - globitem = globres.gl_pathv; - while (globres.gl_pathc>0 && globitem != NULL && *globitem != NULL) { - explodeRPM(*globitem, dlabelFilter, dlabelProvides, NULL, kernelver, destination); - globitem++; - } - globfree(&globres); - /* end of iteration */ - } - free(globpattern); - - return rc; -} - - -static char * driverDiskFiles[] = { "repodata", NULL }; - -static int verifyDriverDisk(char *mntpt) { - char ** fnPtr; - char file[200]; - struct stat sb; - - /* check for dd descriptor */ - sprintf(file, "%s/rhdd3", mntpt); - if (access(file, R_OK)) { - logMessage(ERROR, "can't find driver disk identifier, bad " - "driver disk"); - return LOADER_BACK; - } - - /* side effect: file is still mntpt/ddident */ - stat(file, &sb); - if (!sb.st_size) - return LOADER_BACK; - - for (fnPtr = driverDiskFiles; *fnPtr; fnPtr++) { - snprintf(file, 200, "%s/rpms/%s/%s", mntpt, getProductArch(), *fnPtr); - if (access(file, R_OK)) { - logMessage(ERROR, "cannot find %s, bad driver disk", file); - return LOADER_BACK; - } - } - - return LOADER_OK; -} - -static void copyWarnFn (char *msg) { - logMessage(WARNING, msg); -} - -static void copyErrorFn (char *msg) { - newtWinMessage(_("Error"), _("OK"), _(msg)); -} - -/* this copies the contents of the driver disk to a ramdisk and loads - * the moduleinfo, etc. assumes a "valid" driver disk mounted at mntpt */ -static int loadDriverDisk(struct loaderData_s *loaderData, char *mntpt) { - /* FIXME moduleInfoSet modInfo = loaderData->modInfo; */ - char file[200], dest[200], src[200]; - char *title; - char *fwdir = NULL; - struct moduleBallLocation * location; - struct stat sb; - static int disknum = 0; - int rc, fd; - char *kernelver; - struct utsname unamedata; - - /* check for new version */ - sprintf(file, "%s/rhdd3", mntpt); - if (access(file, R_OK)) { - /* this can't happen, we already verified it! */ - return LOADER_BACK; - } - stat(file, &sb); - title = malloc(sb.st_size + 1); - - fd = open(file, O_RDONLY); - read(fd, title, sb.st_size); - if (title[sb.st_size - 1] == '\n') - sb.st_size--; - title[sb.st_size] = '\0'; - close(fd); - - /* get running kernel version */ - rc = uname(&unamedata); - checked_asprintf(&kernelver, "%s", - rc ? "unknown" : unamedata.release); - logMessage(DEBUGLVL, "Kernel version: %s", kernelver); - - sprintf(file, DD_RPMDIR_TEMPLATE, disknum); - - if (unpack_mkpath(file) != ARCHIVE_OK || - unpack_mkpath(DD_MODULES) != ARCHIVE_OK || - unpack_mkpath(DD_FIRMWARE) != ARCHIVE_OK) - goto loadDriverDiscException; - - if (!FL_CMDLINE(flags)) { - startNewt(); - winStatus(40, 3, _("Loading"), _("Reading driver disk")); - } - - location = malloc(sizeof(struct moduleBallLocation)); - location->title = strdup(title); - checked_asprintf(&location->path, DD_MODULES); - - sprintf(dest, DD_RPMDIR_TEMPLATE, disknum); - sprintf(src, "%s/rpms/%s", mntpt, getProductArch()); - copyDirectory(src, dest, copyWarnFn, copyErrorFn); - - /* unpack packages from dest into location->path */ - if (dlabelUnpackRPMDir(dest, DD_EXTRACTED, kernelver)) { - /* fatal error, log this and jump to exception handler */ - logMessage(ERROR, "Error unpacking RPMs from driver disc no.%d", - disknum); - goto loadDriverDiscException; - } - - - /* ensure updates directory exists */ - sprintf(file, "/lib/modules/%s/updates", kernelver); - if (unpack_mkpath(file) != ARCHIVE_OK) - goto loadDriverDiscException; - - /* make sure driver update are referenced from system module dir - but from a different subdir, initrd overlays use the main - /lib/modules/<kernel>/updates - */ - sprintf(file, "/lib/modules/%s/updates/DD", kernelver); - rc = symlink(DD_MODULES, file); - - /* run depmod to refresh modules db */ - if (system("depmod -a")) { - /* this is not really fatal error, it might still work, log it */ - logMessage(ERROR, "Error running depmod -a for driverdisc no.%d", disknum); - } - - checked_asprintf(&fwdir, DD_FIRMWARE); - if (!access(fwdir, R_OK|X_OK)) { - add_fw_search_dir(loaderData, fwdir); - stop_fw_loader(loaderData); - start_fw_loader(loaderData); - } - free(fwdir); - - /* TODO generate and read module info - * - * sprintf(file, "%s/modinfo", mntpt); - * readModuleInfo(file, modInfo, location, 1); - */ - -loadDriverDiscException: - - /* cleanup */ - free(kernelver); - - if (!FL_CMDLINE(flags)) - newtPopWindow(); - - disknum++; - return 0; -} - -/* Get the list of removable devices (floppy/cdrom) available. Used to - * find suitable devices for update disk / driver disk source. - * Returns the number of devices. ***devNames will be a NULL-terminated list - * of device names - */ -int getRemovableDevices(char *** devNames) { - struct device **devs; - int numDevices = 0; - int i = 0; - - devs = getDevices(DEVICE_DISK | DEVICE_CDROM); - - if(devs) for (i = 0; devs[i] ; i++) { - logMessage(DEBUGLVL, "Considering device %s (isremovable: %d)", devs[i]->device, devs[i]->priv.removable); - - /* XXX Filter out memory devices from the list for now, we have to come - up with smarter way of filtering someday.. */ - if (strncmp(devs[i]->device, "ram", 3) && strncmp(devs[i]->device, "loop", 4)) { - *devNames = realloc(*devNames, (numDevices + 2) * sizeof(char *)); - (*devNames)[numDevices] = strdup(devs[i]->device); - (*devNames)[numDevices+1] = NULL; - numDevices ++; - } - } - if (!numDevices) { - logMessage(ERROR, "no devices found to load drivers from"); - } - return numDevices; -} - -/* Prompt for loading a driver from "media" - * - * class: type of driver to load. - * usecancel: if 1, use cancel instead of back - */ -int loadDriverFromMedia(int class, struct loaderData_s *loaderData, - int usecancel, int noprobe, GTree *moduleState) { - char * device = NULL, * part = NULL, * ddfile = NULL; - char ** devNames = NULL; - enum { DEV_DEVICE, DEV_PART, DEV_CHOOSEFILE, DEV_LOADFILE, - DEV_INSERT, DEV_LOAD, DEV_PROBE, - DEV_DONE } stage = DEV_DEVICE; - int rc, num = 0; - int dir = 1; - int found = 0, before = 0; - VersionState preDDstate, postDDstate; - - while (stage != DEV_DONE) { - switch(stage) { - case DEV_DEVICE: - rc = getRemovableDevices(&devNames); - if (rc == 0) - return LOADER_BACK; - - /* we don't need to ask which to use if they only have one */ - if (rc == 1) { - device = strdup(devNames[0]); - free(devNames); - if (dir == -1) - return LOADER_BACK; - - stage = DEV_PART; - break; - } - dir = 1; - - startNewt(); - rc = newtWinMenu(_("Driver Disk Source"), - _("You have multiple devices which could serve " - "as sources for a driver disk. Which would " - "you like to use?"), 40, 10, 10, - rc < 6 ? rc : 6, devNames, - &num, _("OK"), - (usecancel) ? _("Cancel") : _("Back"), NULL); - - if (rc == 2) { - free(devNames); - return LOADER_BACK; - } - device = strdup(devNames[num]); - free(devNames); - - stage = DEV_PART; - case DEV_PART: { - char ** part_list = getPartitionsList(device); - int nump = 0, num = 0; - - if (part != NULL) - free(part); - - if ((nump = g_strv_length(part_list)) == 0) { - if (dir == -1) - stage = DEV_DEVICE; - else - stage = DEV_INSERT; - break; - } - dir = 1; - - startNewt(); - rc = newtWinMenu(_("Driver Disk Source"), - _("There are multiple partitions on this device " - "which could contain the driver disk image. " - "Which would you like to use?"), 40, 10, 10, - nump < 6 ? nump : 6, part_list, &num, _("OK"), - _("Back"), NULL); - - if (rc == 2) { - g_strfreev(part_list); - stage = DEV_DEVICE; - dir = -1; - break; - } - - part = strdup(part_list[num]); - stage = DEV_CHOOSEFILE; - - } - - case DEV_CHOOSEFILE: { - if (part == NULL) { - logMessage(ERROR, "somehow got to choosing file with a NULL part, going back"); - stage = DEV_PART; - break; - } - /* make sure nothing is mounted when we get here */ - num = umount("/mnt/install/dpart"); - if (num == -1) { - logMessage(ERROR, "error unmounting: %m"); - if ((errno != EINVAL) && (errno != ENOENT)) - exit(1); - } - - logMessage(INFO, "trying to mount %s as partition", part); - if (doPwMount(part, "/mnt/install/dpart", "auto", "ro", NULL)) { - newtWinMessage(_("Error"), _("OK"), - _("Failed to mount partition.")); - stage = DEV_PART; - break; - } - - ddfile = newt_select_file(_("Select driver disk image"), - _("Select the file which is your driver " - "disk image."), - "/mnt/install/dpart", NULL); - if (ddfile == NULL) { - umount("/mnt/install/dpart"); - stage = DEV_PART; - dir = -1; - break; - } - dir = 1; - - stage = DEV_LOADFILE; - } - - case DEV_LOADFILE: { - if (ddfile == NULL) { - logMessage(DEBUGLVL, "trying to load dd from NULL"); - stage = DEV_CHOOSEFILE; - break; - } - if (dir == -1) { - umount("/mnt/install/drivers"); - unlink("/mnt/install/drivers"); - ddfile = NULL; - stage = DEV_CHOOSEFILE; - break; - } - if (doPwMount(ddfile, "/mnt/install/drivers", "auto", "ro", NULL)) { - newtWinMessage(_("Error"), _("OK"), - _("Failed to load driver disk from file.")); - stage = DEV_CHOOSEFILE; - break; - } - stage = DEV_LOAD; - break; - } - - case DEV_INSERT: { - char * buf; - - checked_asprintf(&buf, - _("Insert your driver disk into /dev/%s " - "and press \"OK\" to continue."), device); - - rc = newtWinChoice(_("Insert Driver Disk"), _("OK"), _("Back"), - buf); - free(buf); - if (rc == 2) { - stage = DEV_DEVICE; - dir = -1; - break; - } - dir = 1; - - logMessage(INFO, "trying to mount %s", device); - if (doPwMount(device, "/mnt/install/drivers", "auto", "ro", NULL)) { - newtWinMessage(_("Error"), _("OK"), - _("Failed to mount driver disk.")); - stage = DEV_INSERT; - break; - } - - rc = verifyDriverDisk("/mnt/install/drivers"); - if (rc == LOADER_BACK) { - newtWinMessage(_("Error"), _("OK"), - _("Driver disk is invalid for this " - "release of %s."), getProductName()); - umount("/mnt/install/drivers"); - stage = DEV_INSERT; - break; - } - - stage = DEV_LOAD; - break; - } - case DEV_LOAD: { - struct device ** devices; - - before = 0; - found = 0; - - devices = getDevices(class); - if (devices) - for(; devices[before]; before++); - - rc = loadDriverDisk(loaderData, "/mnt/install/drivers"); - umount("/mnt/install/drivers"); - if (rc == LOADER_BACK) { - dir = -1; - if (ddfile != NULL) - stage = DEV_CHOOSEFILE; - else - stage = DEV_INSERT; - break; - } - /* fall through to probing */ - stage = DEV_PROBE; - - if (ddfile != NULL) { - umount("/mnt/install/drivers"); - unlink("/mnt/install/drivers"); - umount("/mnt/install/dpart"); - } - } - - case DEV_PROBE: { - /* if they didn't specify that we should probe, then we should - * just fall out */ - if (noprobe) { - stage = DEV_DONE; - break; - } - - /* Get info about modules before the update */ - preDDstate = mlVersions(); - - /* Unload all devices and load them again to use the updated modules */ - logMessage(INFO, "Trying to refresh loaded drivers"); - mlRestoreModuleState(moduleState); - busProbe(0); - - /* Get info about modules after the update */ - postDDstate = mlVersions(); - found = mlDetectUpdate(preDDstate, postDDstate); - logMessage(DEBUGLVL, "mlDetectUpdate returned %d", found); - - mlFreeVersions(postDDstate); - mlFreeVersions(preDDstate); - - if (found) { - stage = DEV_DONE; - break; - } - - /* we don't have any more modules of the proper class. ask - * them to manually load */ - rc = newtWinTernary(_("Error"), _("Manually choose"), - _("Continue"), _("Load another disk"), - _("No devices of the appropriate type were " - "found on this driver disk. Would you " - "like to manually select the driver, " - "continue anyway, or load another " - "driver disk?")); - - if (rc == 2) { - /* if they choose to continue, just go ahead and continue */ - stage = DEV_DONE; - } else if (rc == 3) { - /* if they choose to load another disk, back to the - * beginning with them */ - stage = DEV_DEVICE; - } else { - rc = chooseManualDriver(class, loaderData); - /* if they go back from a manual driver, we'll ask again. - * if they load something, assume it's what we need */ - if (rc == LOADER_OK) { - stage = DEV_DONE; - } - } - - break; - } - - case DEV_DONE: - break; - } - } - - return LOADER_OK; -} - - -/* looping way to load driver disks */ -int loadDriverDisks(int class, struct loaderData_s *loaderData, GTree *moduleState) { - int rc; - - rc = newtWinChoice(_("Driver disk"), _("Yes"), _("No"), - _("Do you have a driver disk?")); - if (rc != 1) - return LOADER_OK; - - rc = loadDriverFromMedia(DEVICE_ANY, loaderData, 1, 0, moduleState); - if (rc == LOADER_BACK) - return LOADER_OK; - - do { - rc = newtWinChoice(_("More Driver Disks?"), _("Yes"), _("No"), - _("Do you wish to load any more driver disks?")); - if (rc != 1) - break; - loadDriverFromMedia(DEVICE_ANY, loaderData, 0, 0, moduleState); - } while (1); - - return LOADER_OK; -} - -static void loadFromLocation(struct loaderData_s * loaderData, char * dir, GTree *moduleState) { - if (verifyDriverDisk(dir) == LOADER_BACK) { - logMessage(ERROR, "not a valid driver disk"); - return; - } - - loadDriverDisk(loaderData, dir); - - /* Unload all devices and load them again to use the updated modules */ - logMessage(INFO, "Trying to refresh loaded drivers"); - mlRestoreModuleState(moduleState); - busProbe(0); -} - -void getDDFromSource(struct loaderData_s * loaderData, char * src, GTree *moduleState) { - char *path = "/tmp/dd.img"; - int unlinkf = 0; - - if (!strncmp(src, "nfs:", 4)) { - unlinkf = 1; - if (getFileFromNfs(src + 4, "/tmp/dd.img", loaderData)) { - logMessage(ERROR, "unable to retrieve driver disk: %s", src); - return; - } - } else if (!strncmp(src, "ftp://", 6) || !strncmp(src, "http", 4)) { - unlinkf = 1; - if (getFileFromUrl(src, "/tmp/dd.img", loaderData)) { - logMessage(ERROR, "unable to retrieve driver disk: %s", src); - return; - } - /* FIXME: this is a hack so that you can load a driver disk from, eg, - * scsi cdrom drives */ -#if !defined(__s390__) && !defined(__s390x__) - } else if (!strncmp(src, "cdrom", 5)) { - loadDriverDisks(DEVICE_ANY, loaderData, moduleState); - return; -#endif - } else if (!strncmp(src, "path:", 5)) { - path = src + 5; - } else { - newtWinMessage(_("Kickstart Error"), _("OK"), - _("Unknown driver disk kickstart source: %s"), src); - return; - } - - if (!doPwMount(path, "/mnt/install/drivers", "auto", "ro", NULL)) { - loadFromLocation(loaderData, "/mnt/install/drivers", moduleState); - umount("/mnt/install/drivers"); - unlink("/mnt/install/drivers"); - if (unlinkf) unlink(path); - } - -} - -void getDDFromDev(struct loaderData_s * loaderData, char * dev, GTree* moduleState) { - if (doPwMount(dev, "/mnt/install/drivers", "auto", "ro", NULL)) { - logMessage(ERROR, "unable to mount driver disk %s", dev); - return; - } - - loadFromLocation(loaderData, "/mnt/install/drivers", moduleState); - umount("/mnt/install/drivers"); - unlink("/mnt/install/drivers"); -} - - -/* - * Look for partition with specific label (part of #316481) - */ -GSList* findDriverDiskByLabel(void) -{ - char *ddLabel = "OEMDRV"; - GSList *ddDevice = NULL; - blkid_cache bCache; - - int res; - blkid_dev_iterate bIter; - blkid_dev bDev; - - if (blkid_get_cache(&bCache, NULL)<0) { - logMessage(ERROR, "Cannot initialize cache instance for blkid"); - return NULL; - } - if ((res = blkid_probe_all(bCache))<0) { - logMessage(ERROR, "Cannot probe devices in blkid: %d", res); - return NULL; - } - if ((res = blkid_probe_all_removable(bCache))<0) { - logMessage(ERROR, "Cannot probe removable devices in blkid: %d", res); - } - - bIter = blkid_dev_iterate_begin(bCache); - blkid_dev_set_search(bIter, "LABEL", ddLabel); - while ((res = blkid_dev_next(bIter, &bDev)) == 0) { - bDev = blkid_verify(bCache, bDev); - if (!bDev) - continue; - - char *devname = strdup(blkid_dev_devname(bDev)); - logMessage(DEBUGLVL, "Adding driver disc %s to the list " - "of available DDs.", devname); - ddDevice = g_slist_prepend(ddDevice, (gpointer)devname); - /* Freeing bDev is taken care of by the put cache call */ - } - blkid_dev_iterate_end(bIter); - - blkid_put_cache(bCache); - - return ddDevice; -} - -int loadDriverDiskFromPartition(struct loaderData_s *loaderData, char* device) -{ - int rc; - - logMessage(INFO, "trying to mount %s", device); - if (doPwMount(device, "/mnt/install/drivers", "auto", "ro", NULL)) { - logMessage(ERROR, "Failed to mount driver disk."); - return -1; - } - - rc = verifyDriverDisk("/mnt/install/drivers"); - if (rc == LOADER_BACK) { - logMessage(ERROR, "Driver disk is invalid for this " - "release of %s.", getProductName()); - umount("/tmp/drivers"); - return -2; - } - - rc = loadDriverDisk(loaderData, "/mnt/install/drivers"); - umount("/mnt/install/drivers"); - if (rc == LOADER_BACK) { - return -3; - } - - return 0; -} - diff --git a/loader/driverdisk.h b/loader/driverdisk.h deleted file mode 100644 index 302a8c4..0000000 --- a/loader/driverdisk.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * driverdisk.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef DRIVERDISK_H -#define DRIVERDISK_H - -#include "loader.h" -#include "modules.h" -#include "moduleinfo.h" - -#define DD_RPMDIR_TEMPLATE "/tmp/DD-%d" -#define DD_EXTRACTED "/tmp/DD" -#define DD_MODULES "/tmp/DD/lib/modules" -#define DD_FIRMWARE "/tmp/DD/lib/firmware" - -extern char *ddFsTypes[]; - -int loadDriverFromMedia(int class, struct loaderData_s *loaderData, - int usecancel, int noprobe, GTree *moduleState); - -int loadDriverDisks(int class, struct loaderData_s *loaderData, GTree *moduleState); - -int getRemovableDevices(char *** devNames); - -int chooseManualDriver(int class, struct loaderData_s *loaderData); - -void getDDFromSource(struct loaderData_s * loaderData, char * src, GTree *moduleState); -void getDDFromDev(struct loaderData_s * loaderData, char * dev, GTree *moduleState); - -int loadDriverDiskFromPartition(struct loaderData_s *loaderData, char* device); - -GSList* findDriverDiskByLabel(void); - -#endif diff --git a/loader/driverselect.c b/loader/driverselect.c deleted file mode 100644 index a563bad..0000000 --- a/loader/driverselect.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * driverselect.c - functionality for manually selecting drivers - * - * Copyright (C) 1997, 1998, 1999, 2000, 2001, 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <ctype.h> -#include <newt.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include "../pyanaconda/isys/log.h" - -#include "modules.h" -#include "moduleinfo.h" -#include "loader.h" -#include "loadermisc.h" -#include "lang.h" -#include "driverdisk.h" - -struct sortModuleList { - int index; - moduleInfoSet modInfo; -}; - -static int sortDrivers(const void * a, const void * b) { - const struct sortModuleList * one = a; - const struct sortModuleList * two = b; - - return strcmp(one->modInfo->moduleList[one->index].description, - one->modInfo->moduleList[two->index].description); -} - -static int getManualModuleArgs(struct moduleInfo * mod, gchar *** moduleArgs) { - newtGrid grid, buttons; - newtComponent text, f, ok, back, entry; - struct newtExitStruct es; - int done = 0, i; - char * buf; - char *argsEntry = ""; - - if (*moduleArgs) { - for (i = 0; (*moduleArgs)[i]; i++) - argsEntry = strcat(argsEntry, (*moduleArgs)[i]); - } - - f = newtForm(NULL, NULL, 0); - checked_asprintf(&buf, - _("Please enter any parameters which you wish to pass " - "to the %s module separated by spaces. If you don't " - "know what parameters to supply, skip this screen " - "by pressing the \"OK\" button."), mod->moduleName); - - text = newtTextboxReflowed(-1, -1, buf, 60, 0, 10, 0); - entry = newtEntry(-1, -1, argsEntry, 50, (const char **) &argsEntry, - NEWT_ENTRY_SCROLL); - - newtFormAddHotKey(f, NEWT_KEY_F12); - - buttons = newtButtonBar(_("OK"), &ok, _("Back"), &back, NULL); - - grid = newtCreateGrid(1, 3); - newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text, - 0, 0, 0, 1, 0, 0); - newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, entry, - 0, 0, 0, 1, 0, 0); - newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons, - 0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX); - - newtGridWrappedWindow(grid, _("Enter Module Parameters")); - newtGridAddComponentsToForm(grid, f, 1); - - do { - newtFormRun(f, &es); - - if (es.reason == NEWT_EXIT_COMPONENT && es.u.co == back) { - done = -1; - } else { - done = 1; - } - } while (done == 0); - - free(buf); - newtGridFree(grid, 1); - - if (done == -1) { - newtFormDestroy(f); - newtPopWindow(); - - return LOADER_BACK; - } - logMessage(INFO, "specified args of %s for %s", argsEntry, mod->moduleName); - - if (strlen(argsEntry) > 0) { - *moduleArgs = g_strsplit(argsEntry, " ", 0); - } - - newtFormDestroy(f); - newtPopWindow(); - - return LOADER_OK; -} - -int chooseManualDriver(int class, struct loaderData_s *loaderData) { - int i, numSorted, num = 0, done = 0; - struct sortModuleList * sortedOrder; - char giveArgs = ' '; - gchar **moduleArgs = NULL; - moduleInfoSet modInfo = loaderData->modInfo; - - newtComponent text, f, ok, back, argcheckbox, listbox; - newtGrid grid, buttons; - struct newtExitStruct es; - - do { - sortedOrder = malloc(sizeof(*sortedOrder) * modInfo->numModules); - numSorted = 0; - - for (i = 0; i < modInfo->numModules; i++) { - sortedOrder[numSorted].index = i; - sortedOrder[numSorted++].modInfo = modInfo; - } - - if (numSorted == 0) { - i = newtWinChoice(_("No drivers found"), _("Load driver disk"), - _("Back"), _("No drivers were found to manually " - "insert. Would you like to use " - "a driver disk?")); - if (i != 1) - return LOADER_BACK; - - loadDriverFromMedia(class, loaderData, 1, 1, NULL); - continue; - } else { - break; - } - } while (1); - - qsort(sortedOrder, numSorted, sizeof(*sortedOrder), sortDrivers); - - f = newtForm(NULL, NULL, 0); - - text = newtTextboxReflowed(-1, -1, - _("Please select the driver below which you " - "wish to load. If it does not appear and " - "you have a driver disk, press F2."), - 60, 0, 10, 0); - - listbox = newtListbox(-1, -1, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); - newtListboxSetWidth(listbox, 55); - - buttons = newtButtonBar(_("OK"), &ok, _("Back"), &back, NULL); - argcheckbox = newtCheckbox(-1, -1, _("Specify optional module arguments"), - giveArgs, NULL, &giveArgs); - - newtFormAddHotKey(f, NEWT_KEY_F2); - newtFormAddHotKey(f, NEWT_KEY_F12); - - for (i = 0; i < numSorted; i++) { - char *buf = NULL; - - checked_asprintf(&buf, "%s (%s)", - modInfo->moduleList[sortedOrder[i].index].description, - modInfo->moduleList[sortedOrder[i].index].moduleName); - - newtListboxAppendEntry(listbox, buf, - INT_TO_POINTER(sortedOrder[i].index)); - } - - 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_COMPONENT, argcheckbox, - 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 Device Driver to Load")); - - newtGridAddComponentsToForm(grid, f, 1); - - do { - newtFormRun(f, &es); - - num = POINTER_TO_INT(newtListboxGetCurrent(listbox)); - - if (es.reason == NEWT_EXIT_COMPONENT && es.u.co == back) { - done = -1; - } else if (es.reason == NEWT_EXIT_HOTKEY && es.u.key == NEWT_KEY_F2) { - done = -2; - } else { - if (giveArgs != ' ') { - i = getManualModuleArgs(&(modInfo->moduleList[num]), - &moduleArgs); - if (i == LOADER_BACK) - done = 0; - else - done = 1; - } else { - done = 1; - } - } - } while (done == 0); - - newtGridFree(grid, 1); - newtFormDestroy(f); - newtPopWindow(); - - if (done == -1) - return LOADER_BACK; - if (done == -2) { - loadDriverFromMedia(class, loaderData, 1, 1, NULL); - return chooseManualDriver(class, loaderData); - } - - mlLoadModule(modInfo->moduleList[num].moduleName, moduleArgs); - free(sortedOrder); - - if (moduleArgs) { - g_strfreev(moduleArgs); - } - - return LOADER_OK; -} diff --git a/loader/fwloader.c b/loader/fwloader.c deleted file mode 100644 index 77b4aa3..0000000 --- a/loader/fwloader.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - * fwloader.c -- a small firmware loader. - * - * Copyright (C) 2006, 2007 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Peter Jones (pjones@xxxxxxxxxx) - */ - -#define _GNU_SOURCE 1 - -#include <argz.h> -#include <envz.h> -#include <fcntl.h> -#include <poll.h> -#include <signal.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/mman.h> -#include <sys/poll.h> -#include <sys/prctl.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> - -#include <asm/types.h> -#include <linux/netlink.h> - -#include "../pyanaconda/isys/log.h" - -#include "loader.h" -#include "fwloader.h" -#include "udelay.h" - -#ifndef FWDEBUG -#define logMessage(x, ...) -#endif - -struct fw_loader { - int netlinkfd; - sigset_t sigmask; - char *fw_pathz; - size_t fw_pathz_len; - struct pollfd *fds; -}; - -int done = 0; - -static inline int set_fd_coe(int fd, int enable) -{ - int rc; - long flags = 0; - - rc = fcntl(fd, F_GETFD, &flags); - if (rc < 0) - return rc; - - if (enable) - flags |= FD_CLOEXEC; - else - flags &= ~FD_CLOEXEC; - - rc = fcntl(fd, F_SETFD, flags); - return rc; -} - -static int open_uevent_socket(struct fw_loader *fwl) -{ - int fd; - struct sockaddr_nl sa; - - fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); - if (fd < 0) - return -1; - set_fd_coe(fd, 1); - - memset(&sa, '\0', sizeof (sa)); - sa.nl_family = AF_NETLINK; - sa.nl_pid = getpid(); - sa.nl_groups = -1; - - if (bind(fd, (struct sockaddr *)&sa, sizeof (sa)) < 0) { - close(fd); - return -1; - } - - fwl->netlinkfd = fd; - - fd = open("/proc/sys/kernel/hotplug", O_RDWR); - if (fd >= 0) { - ftruncate(fd, 0); - write(fd, "\n", 1); - close(fd); - } - - fd = open("/sys/class/firmware/timeout", O_RDWR); - if (fd >= 0) { - write(fd, "10", 2); - close(fd); - } - - return 0; -} - -extern void loaderSegvHandler(int signum); - -static void kill_hotplug_signal(int signum) -{ - signal(signum, kill_hotplug_signal); - logMessage(DEBUGLVL, "fwloader: got exit signal, quitting"); - done = 1; -} - -static int daemonize(struct fw_loader *fwl) -{ - int fd; - - signal(SIGTERM, kill_hotplug_signal); - signal(SIGSEGV, loaderSegvHandler); - signal(SIGTTOU, SIG_IGN); - signal(SIGTTIN, SIG_IGN); - signal(SIGTSTP, SIG_IGN); - - sigfillset(&fwl->sigmask); - sigdelset(&fwl->sigmask, SIGTERM); - sigdelset(&fwl->sigmask, SIGSEGV); - sigemptyset(&fwl->sigmask); - - prctl(PR_SET_NAME, "hotplug", 0, 0, 0); - chdir("/"); - - fd = open("/proc/self/oom_adj", O_RDWR); - if (fd >= 0) { - write(fd, "-17", 3); - close(fd); - } - - for (fd = 0; fd < getdtablesize(); fd++) { - if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) - continue; - if (fd == tty_logfd || fd == file_logfd) - continue; - close(fd); - } - - setsid(); - fd = open("/dev/null", O_RDONLY); - close(STDIN_FILENO); - dup2(fd, STDIN_FILENO); - set_fd_coe(STDIN_FILENO, 1); - close(fd); - fd = open("/dev/null", O_WRONLY); - close(STDOUT_FILENO); - dup2(fd, STDOUT_FILENO); - set_fd_coe(STDOUT_FILENO, 1); - close(STDERR_FILENO); - dup2(fd, STDERR_FILENO); - set_fd_coe(STDERR_FILENO, 1); - close(fd); - - logMessage(DEBUGLVL, "fwloader: starting up (pid %d)", getpid()); - return 0; -} - -struct uevent { - char *msg; - char *path; - char *envz; - size_t envz_len; -}; - -static int get_netlink_msg(struct fw_loader *fwl, struct uevent *uevent) -{ - size_t len; - ssize_t size; - static char buffer[2560]; - char *pos; - char *msg = NULL, *path = NULL, *envz = NULL; - char *argv[] = { NULL }; - size_t envz_len; - error_t errnum; - - size = recv(fwl->netlinkfd, &buffer, sizeof (buffer), 0); - if (size < 0) - return -1; - - if ((size_t)size > sizeof (buffer) - 1) - size = sizeof (buffer) - 1; - buffer[size] = '\0'; - - len = strcspn(buffer, "@"); - if (!buffer[len]) - return -1; - - if ((errnum = argz_create(argv, &envz, &envz_len)) > 0) - goto err; - - pos = buffer; - msg = strndup(pos, len++); - pos += len; - path = strdup(pos); - - pos += strlen(pos) + 1; - if (len < size + 1) { - while (pos[0]) { - char *value = strchr(pos, '='); - if (value) - *(value++) = '\0'; - - if ((errnum = envz_add(&envz, &envz_len, pos, value)) > 0) - goto err; - pos += strlen(pos) + 1; - if (*pos) - pos += strlen(pos) + 1; - } - } - - uevent->msg = msg; - uevent->path = path; - uevent->envz = envz; - uevent->envz_len = envz_len; - return 0; -err: - if (msg) - free(msg); - if (path) - free(path); - while(envz) - argz_delete(&envz, &envz_len, envz); - errno = errnum; - return -1; -} - -/* Set the 'loading' attribute for a firmware device. - * 1 == currently loading - * 0 == done loading - * -1 == error - */ -static int -get_loading_fd(const char *device) -{ - int fd = -1; - char *loading_path = NULL; - - if (asprintf(&loading_path, "%s/loading", device) < 0) { - logMessage(ERROR, "fwloader: device %s: asprintf: %m", device); - return -1; - } - logMessage(DEBUGLVL, "fwloader: looking for loading file at %s", loading_path); - fd = open(loading_path, O_RDWR | O_SYNC ); - if (fd < 0) - logMessage(ERROR, "fwloader: open %s: %m", loading_path); - free(loading_path); - return fd; -} - -static int -set_loading(int fd, int value) -{ - int rc = 0; - - if (value == -1) - rc = write(fd, "-1", 3); - else if (value == 0) - rc = write(fd, "0", 2); - else if (value == 1) - rc = write(fd, "1", 2); - fsync(fd); - fdatasync(fd); - - return rc < 0 ? rc : 0; -} - -static int -fd_map(int fd, char **buf, size_t *bufsize) -{ - struct stat stats; - int en = 0; - - if (fstat(fd, &stats) < 0) { - en = errno; - close(fd); - errno = en; - return -1; - } - - *buf = mmap(NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (*buf == MAP_FAILED) { - *buf = NULL; - en = errno; - close(fd); - errno = en; - return -1; - } - *bufsize = stats.st_size; - return 0; -} - -static int -file_map(const char *filename, char **buf, size_t *bufsize, int flags) -{ - int fd, en, rc = 0; - - if ((fd = open(filename, flags ? flags : O_RDONLY)) < 0) - return -1; - - if (fd_map(fd, buf, bufsize) < 0) - rc = -1; - - en = errno; - close(fd); - errno = en; - - return rc; -} - -static void -file_unmap(void *buf, size_t bufsize) -{ - munmap(buf, bufsize); -} - -static int -fetcher(char *inpath, int outfd) -{ - char *inbuf = NULL; - size_t inlen; - int count; - int en = 0; - - errno = 0; - if (access(inpath, F_OK)) - goto out; - - if (file_map(inpath, &inbuf, &inlen, O_RDONLY) < 0) - goto out; - - lseek(outfd, 0, SEEK_SET); - ftruncate(outfd, 0); - ftruncate(outfd, inlen); - - count = 0; - while (count < inlen) { - ssize_t c; - c = write(outfd, inbuf + count, inlen - count); - if (c <= 0) - goto out; - count += c; - } - -out: - en = errno; - if (inbuf) - file_unmap(inbuf, inlen); - if (en) { - errno = en; - return -1; - } - return 0; -} - - -static int -_load_firmware(struct fw_loader *fwl, int fw_fd, char *sysdir, int timeout) -{ - int rc = 0; - char *fw_buf = NULL, *data = NULL; - size_t fw_len = 0; - int dfd = -1, lfd = -1; - int loading = -2; - size_t count; - - logMessage(DEBUGLVL, "fwloader: waiting for firmware dir at %s", sysdir); - timeout *= 1000000; - while (access(sysdir, F_OK) && timeout) { - udelay(100); - timeout -= 100; - } - if (!timeout) { - logMessage(ERROR, "fwloader: never found firmware dir at %s", sysdir); - return -ENOENT; - } - - if ((lfd = get_loading_fd(sysdir)) < 0) - return lfd; - - set_loading(lfd, 1); - loading = -1; - - if (fd_map(fw_fd, &fw_buf, &fw_len) < 0) { - rc = -errno; - goto out; - } - - if (asprintf(&data, "%s/data", sysdir) < 0) { - rc = -errno; - goto out; - } - if ((dfd = open(data, O_RDWR)) < 0) { - rc = -errno; - goto out; - } - count = 0; - while (count < fw_len) { - ssize_t c; - if ((c = write(dfd, fw_buf + count, fw_len - count)) <= 0) - goto out; - count += c; - } - loading = 0; - -out: - if (dfd >= 0) - close(dfd); - if (fw_buf) - file_unmap(fw_buf, fw_len); - if (loading != -2) - set_loading(lfd, loading); - if (lfd >= 0) - close(lfd); - if (data) - free(data); - - return rc; -} - -static void load_firmware(struct fw_loader *fwl, struct uevent *uevent) -{ - char *devpath = NULL, *firmware = NULL, *timeout; - char *fw_file = NULL, *sys_file = NULL; - char *entry; - int timeout_secs; - char *tempfile; - int fd = -1; - - tempfile = strdup("/tmp/fw-XXXXXX"); - fd = mkstemp(tempfile); - if (fd < 0) { - logMessage(ERROR, "fwloader: mkstemp(\"%s\") failed: %m", tempfile); - free(tempfile); - return; - } - unlink(tempfile); - free(tempfile); - - devpath = envz_get(uevent->envz, uevent->envz_len, "DEVPATH"); - firmware = envz_get(uevent->envz, uevent->envz_len, "FIRMWARE"); - timeout = envz_get(uevent->envz, uevent->envz_len, "TIMEOUT"); - - if (!devpath || !firmware) { - argz_stringify(uevent->envz, uevent->envz_len, ' '); - logMessage(ERROR, "fwloader: environment: %s", uevent->envz); - return; - } - - errno = 0; - timeout_secs = strtol(timeout, NULL, 10); - - if ((errno == ERANGE && (timeout_secs == LONG_MIN || - timeout_secs == LONG_MAX)) || - (errno != 0 && timeout_secs == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - /* find the file */ - for (entry = fwl->fw_pathz; entry; - entry = argz_next(fwl->fw_pathz, fwl->fw_pathz_len, entry)) { - if (asprintf(&fw_file, "%s/%s", entry, firmware) < 0) - return; - - logMessage(INFO, "fwloader: trying to find %s at %s", firmware, fw_file); - - if (fetcher(fw_file, fd) >= 0) - break; - - free(fw_file); - fw_file = NULL; - if (errno == ENOENT || errno == EPERM) - continue; - break; - } - if (!fw_file) - goto out; - - if (asprintf(&sys_file, "/sys%s/", devpath) < 0) - goto out; - - _load_firmware(fwl, fd, sys_file, timeout_secs); - -out: - if (fw_file) - free(fw_file); - if (sys_file) - free(sys_file); - if (fd != -1) - close(fd); -} - -static void handle_single_uevent(struct fw_loader *fwl, struct uevent *uevent) -{ - char *action = NULL; - char *subsystem = NULL; - - action = envz_get(uevent->envz, uevent->envz_len, "ACTION"); - subsystem = envz_get(uevent->envz, uevent->envz_len, "SUBSYSTEM"); - - logMessage(DEBUGLVL, "fwloader: subsystem %s got action %s", subsystem, action); - if (!strcmp(action, "add") && !strcmp(subsystem, "firmware")) - load_firmware(fwl, uevent); -} - -static void handle_events(struct fw_loader *fwl) -{ - int rc; - struct uevent uevent; - if (fwl->fds == NULL) - fwl->fds = calloc(1, sizeof (struct pollfd)); - - do { - do { - if (done) - exit(0); - fwl->fds[0].events = POLLIN | POLLPRI; - fwl->fds[0].revents = 0; - fwl->fds[0].fd = fwl->netlinkfd; - - //logMessage(DEBUGLVL, "fwloader: polling on netlink socket"); - errno = 0; - rc = poll(fwl->fds, 1, -1); - //logMessage(DEBUGLVL, "fwloader: poll returned %d", rc); - - if (done) - exit(0); - } while (rc < 1 || (rc < 0 && errno == EINTR)); - - memset(&uevent, '\0', sizeof (uevent)); - if (get_netlink_msg(fwl, &uevent) < 0) - continue; - - handle_single_uevent(fwl, &uevent); - } while (1); - - if (fwl->fds) { - free(fwl->fds); - fwl->fds = NULL; - } -} - -void set_fw_search_path(struct loaderData_s *loaderData, char *path) -{ - char *old = loaderData->fw_search_pathz, *new = NULL; - size_t old_len = loaderData->fw_search_pathz_len; - - loaderData->fw_search_pathz = NULL; - loaderData->fw_search_pathz_len = -1; - if (!path) { - if (old) - free(old); - return; - } - - if ((new = strdup(path)) == NULL) - goto out; - - loaderData->fw_search_pathz = NULL; - loaderData->fw_search_pathz_len = 0; - if (argz_create_sep(new, ':', &loaderData->fw_search_pathz, - &loaderData->fw_search_pathz_len) != 0) - goto out; - - if (old) - free(old); - - return; -out: - if (new) - free(new); - loaderData->fw_search_pathz = old; - loaderData->fw_search_pathz_len = old_len; - - return; -} - -void add_fw_search_dir(struct loaderData_s *loaderData, char *dir) -{ - argz_add(&loaderData->fw_search_pathz, &loaderData->fw_search_pathz_len, - dir); -} - -void do_fw_loader(struct loaderData_s *loaderData) -{ - struct fw_loader fwl; - int rc; - - memset(&fwl, '\0', sizeof (fwl)); - fwl.netlinkfd = -1; - - fwl.fw_pathz = loaderData->fw_search_pathz; - fwl.fw_pathz_len = loaderData->fw_search_pathz_len; - - logMessage(INFO, "fwloader: starting firmware loader"); - - rc = daemonize(&fwl); - if (rc < 0) { - logMessage(ERROR, "fwloader: daemonize() failed with %d: %m", rc); - exit(1); - } - - if (open_uevent_socket(&fwl) < 0) { - logMessage(ERROR, "fwloader: open_uevent_socket() failed: %m"); - exit(1); - } - - logMessage(DEBUGLVL, "fwloader: entering event loop"); - handle_events(&fwl); - - exit(1); -} - - -void start_fw_loader(struct loaderData_s *loaderData) { - pid_t loader; - - loader = fork(); - if (loader > 0) - loaderData->fw_loader_pid = loader; - if (loader != 0) - return; - - do_fw_loader(loaderData); -} - -void stop_fw_loader(struct loaderData_s *loaderData) { - int x = 0, rc; - siginfo_t siginfo; - if (loaderData->fw_loader_pid > 0) - kill(loaderData->fw_loader_pid, SIGTERM); - while (x <= 100) { - if (x > 90) - kill(loaderData->fw_loader_pid, SIGKILL); - memset(&siginfo, '\0', sizeof (siginfo)); - rc = waitid(P_PID, loaderData->fw_loader_pid, &siginfo, WNOHANG|WEXITED); - if (rc < 0 && errno == ECHILD) - return; - else if (rc == 0 && siginfo.si_pid != 0) - return; - else if (rc == 0) - x++; - usleep(10000); - } - return; -} - - -/* - * vim:ts=8:sw=4:sts=4:et - */ diff --git a/loader/fwloader.h b/loader/fwloader.h deleted file mode 100644 index e0b0fe8..0000000 --- a/loader/fwloader.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * fwloader.h -- a small firmware loader. - * - * Copyright (C) 2006, 2007 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Peter Jones <pjones@xxxxxxxxxx> - */ - -#ifndef FWLOADER_H -#define FWLOADER_H 1 - -#include "loader.h" - -extern void set_fw_search_path(struct loaderData_s *loaderData, char *path); -extern void add_fw_search_dir(struct loaderData_s *loaderData, char *dir); -extern void start_fw_loader(struct loaderData_s *loaderData); -extern void stop_fw_loader(struct loaderData_s *loaderData); - -#endif /* FWLOADER_H */ -/* - * vim:ts=8:sw=4:sts=4:et - */ diff --git a/loader/getparts.c b/loader/getparts.c deleted file mode 100644 index e08e2f8..0000000 --- a/loader/getparts.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * getparts.c - functions associated with getting partitions for a disk - * - * Copyright (C) 1997-2010 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - * David Cantrell <dcantrell@xxxxxxxxxx> - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <ctype.h> -#include <string.h> -#include <glib.h> - -#include "../pyanaconda/isys/log.h" - -/* see if this is a partition name or not */ -static int isPartitionName(char *pname) { - - /* if it doesnt start with a alpha its not one */ - if (!isalpha(*pname) || strstr(pname, "ram")) - return 0; - - /* if it has a '/' in it then treat it specially */ - if (strchr(pname, '/') && !strstr(pname, "iseries") && - !strstr(pname, "i2o")) { - /* assume its either a /dev/ida/ or /dev/cciss device */ - /* these have form of c?d?p? if its a partition */ - return strchr(pname, 'p') != NULL; - } else { - /* if it ends with a digit we're ok */ - return isdigit(pname[strlen(pname)-1]); - } -} - -/* Return array of the names of partitons in /proc/partitions */ -gchar **getPartitionsList(gchar *disk) { - guint i, j; - gchar *contents = NULL; - gchar *tokens[] = { NULL, NULL, NULL, NULL }; - gchar **lines, **iter, **rc; - gsize len; - GError *e = NULL; - GSList *parts = NULL, *list = NULL; - - /* read in /proc/partitions and split in to an array of lines */ - if (!g_file_get_contents("/proc/partitions", &contents, &len, &e)) { - return NULL; - } - - if (contents == NULL) { - return NULL; - } - - iter = lines = g_strsplit_set(contents, "\n", 0); - g_free(contents); - - /* extract partition names from /proc/partitions lines */ - while (*iter != NULL) { - /* split the line in to fields */ - gchar **fields = g_strsplit_set(*iter, " ", 0); - i = j = 0; - - if (g_strv_length(fields) > 0) { - /* if we're on a non-empty line, toss empty fields so we - * end up with the major, minor, #blocks, and name fields - * in positions 0, 1, 2, and 3 - */ - while ((j < g_strv_length(fields)) && (i < 4)) { - if (g_strcmp0(fields[j], "")) { - tokens[i++] = fields[j]; - } - - j++; - } - - /* skip lines where: - * - the 'major' column is a non-digit - * - the '#blocks' column is '1' (indicates extended partition) - * - the 'name' column is not a valid partition name - */ - if (isdigit(*tokens[0]) && g_strcmp0(tokens[2], "1") && - isPartitionName(tokens[3])) { - /* if disk is specified, only return a list of partitions - * for that device - */ - if (disk != NULL && !g_str_has_prefix(tokens[3], disk)) { - g_strfreev(fields); - iter++; - continue; - } - - parts = g_slist_prepend(parts, g_strdup(tokens[3])); - } - } - - g_strfreev(fields); - iter++; - } - - i = g_slist_length(parts); - rc = g_new(gchar *, i + 1); - rc[i] = NULL; - - for (list = parts; list != NULL; list = list->next) { - rc[--i] = list->data; - } - - g_strfreev(lines); - g_slist_free(parts); - return rc; -} diff --git a/loader/getparts.h b/loader/getparts.h deleted file mode 100644 index 52a978c..0000000 --- a/loader/getparts.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * getparts.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef GETPARTS_H -#define GETPARTS_H - -#include <glib.h> - -gchar **getPartitionsList(gchar * disk); - -#endif diff --git a/loader/hardware.c b/loader/hardware.c deleted file mode 100644 index 272846b..0000000 --- a/loader/hardware.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * hardware.c - various hardware probing functionality - * - * 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <strings.h> -#include <stdlib.h> -#include <unistd.h> -#include <ctype.h> -#include <sys/wait.h> -#include <glib.h> - -#include "loader.h" -#include "hardware.h" - -/* FIXME: for turning off dma */ -#include <sys/ioctl.h> -#include <linux/hdreg.h> -#include "../pyanaconda/isys/isys.h" -#include "../pyanaconda/isys/log.h" - -/* boot flags */ -extern uint64_t flags; - -static int detectHardware() { - int child, rc, status; - int timeout = 0; /* FIXME: commandline option for this */ - - fprintf(stderr, "detecting hardware...\n"); - logMessage(DEBUGLVL, "probing buses"); - - if (!(child = fork())) { - int fd = open("/dev/tty3", O_RDWR); - - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - close(fd); - - rc = execl("/sbin/udevadm", "udevadm", "trigger", NULL); - _exit(1); - } - - waitpid(child, &status, 0); - if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { - rc = 1; - } else { - rc = 0; - } - - fprintf(stderr, "waiting for hardware to initialize...\n"); - logMessage(DEBUGLVL, "waiting for hardware to initialize"); - - if (!(child = fork())) { - char *args[] = { "/sbin/udevadm", "settle", NULL, NULL }; - int fd = open("/dev/tty3", O_RDWR); - - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - close(fd); - - if (timeout) { - checked_asprintf(&args[2], "--timeout=%d", timeout); - } - - rc = execv("/sbin/udevadm", args); - _exit(1); - } - - waitpid(child, &status, 0); - if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { - rc = 1; - } else { - rc = 0; - } - if (rc) { - return LOADER_ERROR; - } - return LOADER_OK; -} - -/* this allows us to do an early load of modules specified on the - * command line to allow automating the load order of modules so that - * eg, certain scsi controllers are definitely first. - * FIXME: this syntax is likely to change in a future release - * but is done as a quick hack for the present. - */ -int earlyModuleLoad(int justProbe) { - int fd, len, i; - char buf[1024], *cmdLine; - gint argc = 0; - gchar **argv = NULL; - GError *optErr = NULL; - - /* FIXME: reparsing /proc/cmdline to avoid major loader changes. - * should probably be done in loader.c:parseCmdline() like everything - * else - */ - if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) return 1; - len = read(fd, buf, sizeof(buf) - 1); - close(fd); - if (len <= 0) return 1; - - buf[len] = '\0'; - cmdLine = buf; - - if (!g_shell_parse_argv(cmdLine, &argc, &argv, &optErr)) { - g_error_free(optErr); - return 1; - } - - for (i=0; i < argc; i++) { - if (!strncasecmp(argv[i], "driverload=", 11)) { - logMessage(INFO, "loading %s early", argv[i] + 11); - mlLoadModuleSet(argv[i] + 11); - } - } - return 0; -} - -int busProbe(int justProbe) { - /* autodetect whatever we can */ - if (justProbe) - return 0; - return detectHardware(); -} diff --git a/loader/hardware.h b/loader/hardware.h deleted file mode 100644 index 47c34d2..0000000 --- a/loader/hardware.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * hardware.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef LOADERHW_H -#define LOADERHW_H - -#include "modules.h" - -int earlyModuleLoad(int justProbe); -int busProbe(int justProbe); - -#endif diff --git a/loader/hdinstall.c b/loader/hdinstall.c deleted file mode 100644 index a284869..0000000 --- a/loader/hdinstall.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <ctype.h> -#include <errno.h> -#include <dirent.h> -#include <fcntl.h> -#include <newt.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mount.h> -#include <unistd.h> -#include <glib.h> - -#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 (suffix && !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/install/isodir", "auto", "ro", NULL)) - return 0; - - if (dir[0] == '/') { - checked_asprintf(&path, "/mnt/install/isodir%s/updates.img", dir); - } else { - checked_asprintf(&path, "/mnt/install/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/install/isodir%s/product.img", dir); - } else { - checked_asprintf(&path, "/mnt/install/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/install/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 an installation tree " - "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 tree:")); - - 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/install/isodir", "auto", "ro", NULL)) { - logMessage(ERROR, "couldn't mount %s to verify images", selpart); - continue; - } - - if (dir[0] == '/') { - checked_asprintf(&buf, "/mnt/install/isodir%s", dir); - } else { - checked_asprintf(&buf, "/mnt/install/isodir/%s", dir); - } - - files = get_file_list(buf, ends_with_iso); - if (!files || !files[0] || !strlen(files[0])) { - newtWinMessage(_("Error"), _("OK"), - _("That directory does not contain an installable tree.")); - umount("/mnt/install/isodir"); - free(buf); - continue; - } - - free(buf); - - /* mount the first image and check for a .treeinfo file */ - if (dir[0] == '/') { - checked_asprintf(&buf, "/mnt/install/isodir%s/%s", dir, files[0]); - } else { - checked_asprintf(&buf, "/mnt/install/isodir/%s/%s", dir, files[0]); - } - - if (doPwMount(buf, "/mnt/install/testmnt", "auto", "ro", NULL)) { - free(buf); - newtWinMessage(_("Error"), _("OK"), - _("That directory does not contain an installable tree.")); - umount("/mnt/install/isodir"); - continue; - } - - free(buf); - - if (access("/mnt/install/testmnt/.treeinfo", R_OK)) { - newtWinMessage(_("Error"), _("OK"), - _("That directory does not contain an installable tree.")); - umount("/mnt/install/testmnt"); - umount("/mnt/install/isodir"); - continue; - } - - umount("/mnt/install/testmnt"); - umount("/mnt/install/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: */ diff --git a/loader/hdinstall.h b/loader/hdinstall.h deleted file mode 100644 index 6654c45..0000000 --- a/loader/hdinstall.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * hdinstall.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef H_HDINSTALL -#define H_HDINSTALL - -#include "method.h" - -int promptForHardDrive(struct loaderData_s *loaderData); -int loadHdImages(struct loaderData_s *loaderData); -int kickstartFromHD(char *kssrc); -int kickstartFromBD(char *kssrc); - -#endif diff --git a/loader/ibft.c b/loader/ibft.c deleted file mode 100644 index b3a3827..0000000 --- a/loader/ibft.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - File name: ibft.c - Date: 2008/09/02 - Author: Martin Sivak <msivak@xxxxxxxxxx> - - Copyright (C) 2008 Red Hat - - 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 - in a file called COPYING along with this program; if not, write to - the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA - 02139, USA. -*/ - - -#include <stddef.h> -#include <stdio.h> -#include <string.h> - -#include <libiscsi.h> -#include "ibft.h" - -struct libiscsi_network_config ibft_context; -int ibft_ispresent = 0; -int ibft_initialized = 0; - -int ibft_init(void) -{ - int ret; - - memset(&ibft_context, 0, sizeof(ibft_context)); - - ret = libiscsi_get_firmware_network_config(&ibft_context); - - /* ret == 0 -> OK */ - ibft_ispresent = !ret; - ibft_initialized = 1; - - return ibft_initialized; -} - -/* Is iBFT available on this system */ -int ibft_present() -{ - if(!ibft_initialized) - ibft_init(); - - return ibft_ispresent; -} - -/* Is the iBFT network configured to use DHCP */ -int ibft_iface_dhcp() -{ - if(!ibft_initialized) - ibft_init(); - - if(!ibft_present()) - return -1; - - return ibft_context.dhcp; -} - -#define ibft_iface_charfunc(name, var) char* ibft_iface_##name()\ -{\ - if(!ibft_initialized)\ - ibft_init();\ -\ - if(!ibft_present())\ - return NULL;\ -\ - if(!strlen(ibft_context.var))\ - return NULL;\ -\ - return ibft_context.var;\ -} - - -/* Get the iBFT MAC address */ -ibft_iface_charfunc(mac, mac_address) - -/* Get the iBFT ip address */ -ibft_iface_charfunc(ip, ip_address) - -/* Get the iBFT subnet mask */ -ibft_iface_charfunc(mask, netmask) - -/* Get the iBFT gateway */ -ibft_iface_charfunc(gw, gateway) - -/* Get the iBFT iface name */ -ibft_iface_charfunc(iface, iface_name) - -/* Get the iBFT dns servers */ -ibft_iface_charfunc(dns1, primary_dns) -ibft_iface_charfunc(dns2, secondary_dns) - diff --git a/loader/ibft.h b/loader/ibft.h deleted file mode 100644 index a922c91..0000000 --- a/loader/ibft.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - File name: ibft.h - Date: 2008/09/02 - Author: Martin Sivak - - Copyright (C) 2008 Red Hat - - 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 - in a file called COPYING along with this program; if not, write to - the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA - 02139, USA. -*/ - - -#ifndef __IBFT_H__ -#define __IBFT_H__ - - -int ibft_init(); -int ibft_present(); - -int ibft_iface_dhcp(); - -char* ibft_iface_mac(); -char* ibft_iface_ip(); -char* ibft_iface_mask(); -char* ibft_iface_gw(); -char* ibft_iface_iface(); -char* ibft_iface_dns1(); -char* ibft_iface_dns2(); - - -#endif - -/* end of ibft.h */ diff --git a/loader/kbd.c b/loader/kbd.c deleted file mode 100644 index c484cbd..0000000 --- a/loader/kbd.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * kbd.c - keyboard handling - * - * Copyright (C) 1997, 1998, 1999, 2000, 2001, 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <alloca.h> -#include <errno.h> -#include <newt.h> -#include <stdlib.h> -#include <string.h> - -#include "loader.h" -#include "loadermisc.h" -#include "lang.h" -#include "windows.h" - -#include "../pyanaconda/isys/lang.h" -#include "../pyanaconda/isys/log.h" - -/* boot flags */ -extern uint64_t flags; - -int chooseKeyboard(struct loaderData_s * loaderData, char ** kbdtypep) { - int num = -1; - int rc; - gzFile f; - struct kmapHeader hdr; - struct kmapInfo * infoTable; - struct langInfo * languages; - int numLanguages; - char ** kbds; - char buf[16384]; /* I hope this is big enough */ - int i; - char * defkbd = loaderData->kbd ? loaderData->kbd : NULL; - char *lang; - -#if defined(__s390__) || defined(__s390x__) - return LOADER_NOOP; -#endif - - if (FL_SERIAL (flags) || FL_VIRTPCONSOLE(flags)) return LOADER_NOOP; - - numLanguages = getLangInfo(&languages); - - lang = getenv("LANG"); - if (!lang) - lang = loaderData->lang; - - if (!defkbd && lang) { - for (i = 0; i < numLanguages; i++) { - if (!strncmp(languages[i].lc_all, lang, 2)) { - defkbd = languages[i].keyboard; - break; - } - } - } - - if (!defkbd) - defkbd = "us"; - - f = gzopen("/etc/keymaps.gz", "r"); - if (!f) { - errorWindow("cannot open /etc/keymaps.gz: %s"); - return LOADER_ERROR; - } - - if (gzread(f, &hdr, sizeof(hdr)) != sizeof(hdr)) { - errorWindow("failed to read keymaps header: %s"); - gzclose(f); - return LOADER_ERROR; - } - - logMessage(INFO, "%d keymaps are available", hdr.numEntries); - - i = hdr.numEntries * sizeof(*infoTable); - infoTable = alloca(i); - if (gzread(f, infoTable, i) != i) { - errorWindow("failed to read keymap information: %s"); - gzclose(f); - return LOADER_ERROR; - } - - if (num == -1 ) { - kbds = alloca(sizeof(*kbds) * (hdr.numEntries + 1)); - for (i = 0; i < hdr.numEntries; i++) { - kbds[i] = infoTable[i].name; - } - - kbds[i] = NULL; - qsort(kbds, i, sizeof(*kbds), simpleStringCmp); - - for (i = 0; i < hdr.numEntries; i++) - if (!strcmp(kbds[i], defkbd)) - num = i; - - rc = newtWinMenu(_("Keyboard Type"), - _("What type of keyboard do you have?"), - 40, 5, 5, 8, kbds, &num, _("OK"), _("Back"), NULL); - if (rc == 2) return LOADER_BACK; - - /* num needs to index the right keyboard infoTable */ - for (i = 0; i < hdr.numEntries; i++) - if (!strcmp(kbds[num], infoTable[i].name)) break; - num = i; - } - - rc = 0; - - for (i = 0; i < num; i++) { - if (gzread(f, buf, infoTable[i].size) != infoTable[i].size) { - logMessage(ERROR, "error reading %d bytes from file: %m", - infoTable[i].size); - gzclose(f); - rc = LOADER_ERROR; - } - } - - if (!rc) rc = loadKeymap(f); - - /* normalize the error condition */ - /* MSWFIXME - do we want to warn the user that setting the - keyboard didn't work? - */ - if (rc != 0) - rc = LOADER_ERROR; - else - gzclose(f); - - loaderData->kbd = strdup(infoTable[num].name); - - return rc; -} diff --git a/loader/kbd.h b/loader/kbd.h deleted file mode 100644 index c19018f..0000000 --- a/loader/kbd.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * kbd.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef H_KBD -#define H_KBD - -int chooseKeyboard(struct loaderData_s * loaderData, char ** kbdtypep); - -#endif diff --git a/loader/keymaps-i386 b/loader/keymaps-i386 deleted file mode 100644 index 93f2e58d10c66c2586ad2f42deccdecaec16b177..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12173 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 V7~sRTFNEiTfZ~fQc(x<}`9D*L!)E{h diff --git a/loader/keymaps-ppc b/loader/keymaps-ppc deleted file mode 100644 index 914f4bfd6a36a0b42c8fb5f61284a4c15ee26b8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12871 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 diff --git a/loader/keymaps-x86_64 b/loader/keymaps-x86_64 deleted file mode 100644 index 93f2e58d10c66c2586ad2f42deccdecaec16b177..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12173 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 V7~sRTFNEiTfZ~fQc(x<}`9D*L!)E{h diff --git a/loader/kickstart.c b/loader/kickstart.c deleted file mode 100644 index 320dfb3..0000000 --- a/loader/kickstart.c +++ /dev/null @@ -1,1108 +0,0 @@ -/* - * kickstart.c - kickstart file handling - * - * Copyright (C) 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <Python.h> - -#include <alloca.h> -#include <arpa/inet.h> -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <newt.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> -#include <glib.h> - -#include "loader.h" -#include "loadermisc.h" -#include "lang.h" -#include "kickstart.h" -#include "modules.h" - -#include "kbd.h" -#include "driverdisk.h" -#include "net.h" -#include "method.h" -#include "ibft.h" - -#include "nfsinstall.h" -#include "urlinstall.h" -#include "cdinstall.h" -#include "hdinstall.h" - -#include "../pyanaconda/isys/eddsupport.h" -#include "../pyanaconda/isys/imount.h" -#include "../pyanaconda/isys/isys.h" -#include "../pyanaconda/isys/log.h" - -/* Too bad, but we need constants visible everywhere. */ -static PyObject *constantsMod; - -/* boot flags */ -extern uint64_t flags; - -static void setDisplayMode(struct loaderData_s * loaderData, PyObject *handler); -static void setSELinux(struct loaderData_s * loaderData, PyObject *handler); -static void setMediaCheck(struct loaderData_s * loaderData, PyObject *handler); -static void setUpdates(struct loaderData_s * loaderData, PyObject *handler); -static void setVnc(struct loaderData_s * loaderData, PyObject *handler); -static void useKickstartDD(struct loaderData_s * loaderData, PyObject *handler); -static void setKickstartKeyboard(struct loaderData_s * loaderData, PyObject *handler); -static void setKickstartLanguage(struct loaderData_s * loaderData, PyObject *handler); -static void setKickstartNetwork(struct loaderData_s * loaderData, PyObject *handler); -static void setKickstartCD(struct loaderData_s * loaderData, PyObject *handler); -static void setKickstartHD(struct loaderData_s * loaderData, PyObject *handler); -static void setKickstartNfs(struct loaderData_s * loaderData, PyObject *handler); -static void setKickstartUrl(struct loaderData_s * loaderData, PyObject *handler); -static void loadKickstartModule(struct loaderData_s * loaderData, PyObject *handler); - -typedef void (*commandFunc_t)(struct loaderData_s *loaderData, PyObject *handler); - -commandFunc_t ksTable[] = { - &loadKickstartModule, - &setDisplayMode, - &setKickstartCD, - &setKickstartHD, - &setKickstartKeyboard, - &setKickstartLanguage, - &setKickstartNfs, - &setKickstartUrl, - &setVnc, - &setKickstartNetwork, - &setMediaCheck, - &setSELinux, - &setUpdates, - &useKickstartDD, - NULL -}; - -/* INTERNAL PYTHON INTERFACE FUNCTIONS */ - -static PyObject *getObject(PyObject *module, const char *name, unsigned int isCallable) { - PyObject *obj = NULL; - - obj = PyObject_GetAttrString(module, name); - if (!obj) - return NULL; - - if (isCallable && !PyCallable_Check(obj)) { - Py_XDECREF(obj); - return NULL; - } - - return obj; -} - -static PyObject *import(const char *moduleName) { - PyObject *module = NULL; - - module = PyImport_ImportModule(moduleName); - return module; -} - -static PyObject *makeHandler(PyObject *module) { - PyObject *func, *handler; - - func = getObject(module, "makeVersion", 1); - if (!func) - return NULL; - - handler = PyObject_CallObject(func, NULL); - if (!handler) { - Py_DECREF(func); - return NULL; - } - - Py_DECREF(func); - return handler; -} - -static PyObject *makeParser(PyObject *parserClass, PyObject *handler) { - PyObject *parser = NULL, *args, *kwargs; - - args = PyTuple_New(1); - PyTuple_SetItem(args, 0, handler); - - kwargs = PyDict_New(); - Py_INCREF(Py_True); - PyDict_SetItemString(kwargs, "followIncludes", Py_True); - Py_INCREF(Py_True); - PyDict_SetItemString(kwargs, "errorsAreFatal", Py_True); - Py_INCREF(Py_False); - PyDict_SetItemString(kwargs, "missingIncludeIsFatal", Py_False); - - parser = PyObject_Call(parserClass, args, kwargs); - - Py_DECREF(kwargs); - Py_DECREF(args); - - return parser; -} - -static void handleException() { - PyObject *ptype, *pvalue, *ptraceback; - - if (!PyErr_Occurred()) - return; - - PyErr_Fetch(&ptype, &pvalue, &ptraceback); - - startNewt(); - newtWinMessage(_("Kickstart Error"), _("OK"), - PyString_AsString(PyObject_Str(pvalue))); - - Py_XDECREF(ptype); - Py_XDECREF(pvalue); - Py_XDECREF(ptraceback); -} - -/* Returns the handler.<command>.<attr> object if it exists, or NULL on error. */ -static PyObject *getattr(PyObject *handler, const char *command, const char *attr) { - PyObject *commandObj = NULL, *attrObj = NULL; - - commandObj = PyObject_GetAttrString(handler, command); - if (!commandObj) - goto cleanup; - - attrObj = PyObject_GetAttrString(commandObj, attr); - if (!attrObj) - goto cleanup; - -cleanup: - Py_XDECREF(commandObj); - return attrObj; -} - -static PyObject *getDataList(PyObject *handler, const char *command) { - PyObject *attrObj = getattr(handler, command, "dataList"); - PyObject *retval = NULL; - - if (!attrObj || !PyCallable_Check(attrObj)) - goto cleanup; - - retval = PyObject_CallObject(attrObj, NULL); - -cleanup: - Py_XDECREF(attrObj); - return retval; -} - -/* Perform the same tasks as pykickstart.parser.preprocessKickstart. Currently - * this is just fetching and expanding %ksappend lines. - */ -static PyObject *preprocessKickstart(PyObject *module, const char *inputFile) { - PyObject *output = NULL, *func; - - func = getObject(module, "preprocessKickstart", 1); - if (!func) - return NULL; - - output = PyObject_CallFunctionObjArgs(func, PyString_FromString(inputFile), NULL); - if (!output) { - handleException(); - return NULL; - } - - return output; -} - -/* Process a kickstart file given by the filename f, as a PyObject. This sets - * attributes on the parser object as a side effect, returning that object or - * NULL on exception. - */ -static PyObject *readKickstart(PyObject *parser, PyObject *f) { - PyObject *retval; - - retval = PyObject_CallMethodObjArgs(parser, PyString_FromString("readKickstart"), f, NULL); - if (!retval) { - handleException(); - return NULL; - } - - return retval; -} - -/* PYTHON HELPERS */ - -static unsigned int isNotEmpty(PyObject *obj) { - return obj && PyString_Check(obj) && strcmp("", PyString_AsString(obj)); -} - -static unsigned int objIsStr(PyObject *obj, const char *str) { - return obj && PyString_Check(obj) && !strcmp(str, PyString_AsString(obj)); -} - -static unsigned int isTrue(PyObject *obj) { - return obj && PyBool_Check(obj) && obj == Py_True; -} - -int kickstartFromRemovable(char *kssrc) { - struct device ** devices; - char *p, *kspath; - int i, rc; - - logMessage(INFO, "doing kickstart from removable media"); - devices = getDevices(DEVICE_DISK); - /* usb can take some time to settle, even with the various hacks we - * have in place. some systems use portable USB CD-ROM drives, try to - * make sure there really isn't one before bailing. */ - for (i = 0; !devices && i < 10; ++i) { - logMessage(INFO, "sleeping to wait for a USB disk"); - sleep(2); - devices = getDevices(DEVICE_DISK); - } - if (!devices) { - logMessage(ERROR, "no disks"); - return 1; - } - - for (i = 0; devices[i]; i++) { - if (devices[i]->priv.removable == 1) { - logMessage(INFO, "first removable media is %s", devices[i]->device); - break; - } - } - - if (!devices[i] || (devices[i]->priv.removable == 0)) { - logMessage(ERROR, "no removable devices"); - return 1; - } - - /* format is floppy:[/path/to/ks.cfg] */ - kspath = ""; - p = strchr(kssrc, ':'); - if (p) - kspath = p + 1; - - if (!p || strlen(kspath) < 1) - kspath = "/ks.cfg"; - - if ((rc=getKickstartFromBlockDevice(devices[i]->device, kspath))) { - if (rc == 3) { - startNewt(); - newtWinMessage(_("Error"), _("OK"), - _("Cannot find ks.cfg on removable media.")); - } - return 1; - } - - return 0; -} - - -/* given a device name (w/o '/dev' on it), try to get ks file */ -/* Error codes: - 1 - could not create device node - 2 - could not mount device as ext2, vfat, or iso9660 - 3 - kickstart file named path not there -*/ -int getKickstartFromBlockDevice(char *device, char *path) { - return getFileFromBlockDevice(device, path, "/tmp/ks.cfg"); -} - -void loadKickstartModule(struct loaderData_s * loaderData, PyObject *handler) { - Py_ssize_t i; - PyObject *list = getDataList(handler, "device"); - - if (!list) - return; - - for (i = 0; i < PyList_Size(list); i++) { - PyObject *ele = PyList_GetItem(list, i); - PyObject *moduleName, *moduleOpts; - - if (!ele) - continue; - - moduleName = getObject(ele, "moduleName", 0); - moduleOpts = getObject(ele, "moduleOpts", 0); - - if (isNotEmpty(moduleName)) { - if (isNotEmpty(moduleOpts)) { - gchar **args = g_strsplit(PyString_AsString(moduleOpts), " ", 0); - mlLoadModule(PyString_AsString(moduleName), args); - g_strfreev(args); - } else - mlLoadModule(PyString_AsString(moduleName), NULL); - } - - Py_XDECREF(moduleName); - Py_XDECREF(moduleOpts); - } - - Py_XDECREF(list); -} - -static char *newKickstartLocation(const char *origLocation) { - const char *location; - char *retval = NULL; - newtComponent f, okay, cancel, answer, locationEntry; - newtGrid grid, buttons; - - startNewt(); - - locationEntry = newtEntry(-1, -1, NULL, 60, &location, NEWT_FLAG_SCROLL); - newtEntrySet(locationEntry, origLocation, 1); - - /* button bar at the bottom of the window */ - buttons = newtButtonBar(_("OK"), &okay, _("Cancel"), &cancel, NULL); - - grid = newtCreateGrid(1, 3); - - newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, - newtTextboxReflowed(-1, -1, _("Unable to download the kickstart file. Please modify the kickstart parameter below or press Cancel to proceed as an interactive installation."), 60, 0, 0, 0), - 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, locationEntry, - 0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons, - 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX); - - f = newtForm(NULL, NULL, 0); - newtGridAddComponentsToForm(grid, f, 1); - newtGridWrappedWindow(grid, _("Error downloading kickstart file")); - newtGridFree(grid, 1); - - /* run the form */ - answer = newtRunForm(f); - - if (answer != cancel) - retval = strdup(location); - - newtFormDestroy(f); - newtPopWindow(); - - return retval; -} - -int isKickstartFileRemote(char *ksFile) { - char *location = NULL; - - if (ksFile == NULL) { - return 0; - } - - if (!strcmp(ksFile, "ks")) { - return 1; - } else if (!strncmp(ksFile, "ks=", 3)) { - location = ksFile + 3; - } - - return isURLRemote(location); -} - -void getKickstartFile(struct loaderData_s *loaderData) { - char *c; - int rc = 1; - - /* Chop off the parameter name, if given. */ - if (!strncmp(loaderData->ksFile, "ks=", 3)) - c = loaderData->ksFile+3; - else - c = loaderData->ksFile; - - while (rc != 0) { - if (!strncmp(c, "ks", 2)) { - rc = kickstartFromNfs(NULL, loaderData); - loaderData->ksFile = strdup("/tmp/ks.cfg"); - } else if (!strncmp(c, "http", 4) || !strncmp(c, "ftp://", 6)) { - rc = kickstartFromUrl(c, loaderData); - loaderData->ksFile = strdup("/tmp/ks.cfg"); - } else if (!strncmp(c, "nfs:", 4)) { - rc = kickstartFromNfs(c+4, loaderData); - loaderData->ksFile = strdup("/tmp/ks.cfg"); - } else if (!strncmp(c, "floppy", 6)) { - rc = kickstartFromRemovable(c); - loaderData->ksFile = strdup("/tmp/ks.cfg"); - } else if (!strncmp(c, "hd:", 3)) { - rc = kickstartFromHD(c); - loaderData->ksFile = strdup("/tmp/ks.cfg"); - } else if (!strncmp(c, "bd:", 3)) { - rc = kickstartFromBD(c); - loaderData->ksFile = strdup("/tmp/ks.cfg"); - } else if (!strncmp(c, "cdrom", 5)) { - rc = kickstartFromCD(c); - loaderData->ksFile = strdup("/tmp/ks.cfg"); - } else if (!strncmp(c, "file:", 5)) { - loaderData->ksFile = c+5; - break; - } - - if (rc != 0) { - char *newLocation; - - if (!strcmp(c, "ks")) - newLocation = newKickstartLocation(""); - else - newLocation = newKickstartLocation(c); - - if (loaderData->ksFile != NULL) - free(loaderData->ksFile); - - if (newLocation != NULL) { - loaderData->ksFile = strdup(newLocation); - free(newLocation); - return getKickstartFile(loaderData); - } - else - return; - } - } - - flags |= LOADER_FLAGS_KICKSTART; - return; -} - -static void setVnc(struct loaderData_s * loaderData, PyObject *handler) { - PyObject *vncEnabled = getattr(handler, "vnc", "enabled"); - - if (isTrue(vncEnabled)) { - logMessage(INFO, "kickstart forcing graphical mode over vnc"); - flags |= LOADER_FLAGS_GRAPHICAL | LOADER_FLAGS_EARLY_NETWORKING; - } - - Py_XDECREF(vncEnabled); -} - -static void setUpdates(struct loaderData_s * loaderData, PyObject *handler) { - PyObject *url = getattr(handler, "updates", "url"); - - if (isNotEmpty(url)) { - if (objIsStr(url, "floppy")) - flags |= LOADER_FLAGS_UPDATES; - else - loaderData->updatessrc = strdup(PyString_AsString(url)); - } - - Py_XDECREF(url); -} - -static void setDisplayMode(struct loaderData_s * loaderData, PyObject *handler) { - PyObject *textObj = getObject(constantsMod, "DISPLAY_MODE_TEXT", 0); - PyObject *cmdlineObj = getObject(constantsMod, "DISPLAY_MODE_CMDLINE", 0); - PyObject *settingObj = getattr(handler, "displaymode", "displayMode"); - - if (!settingObj) - goto cleanup; - - if (settingObj == textObj) { - logMessage(INFO, "kickstart forcing text mode"); - flags |= LOADER_FLAGS_TEXT; - } else if (settingObj == cmdlineObj) { - logMessage(INFO, "kickstart forcing cmdline mode"); - flags |= LOADER_FLAGS_CMDLINE; - } else { - logMessage(INFO, "kickstart forcing graphical mode"); - flags |= LOADER_FLAGS_GRAPHICAL; - } - -cleanup: - Py_XDECREF(textObj); - Py_XDECREF(cmdlineObj); - Py_XDECREF(settingObj); -} - -static void setSELinux(struct loaderData_s * loaderData, PyObject *handler) { - PyObject *disabledObj = getObject(constantsMod, "SELINUX_DISABLED", 0); - PyObject *settingObj = getattr(handler, "selinux", "selinux"); - - if (settingObj && settingObj != disabledObj) - flags |= LOADER_FLAGS_SELINUX; - - Py_XDECREF(disabledObj); - Py_XDECREF(settingObj); -} - -static void setMediaCheck(struct loaderData_s * loaderData, PyObject *handler) { - PyObject *mediaCheckEnabled = getattr(handler, "mediacheck", "mediacheck"); - - if (isTrue(mediaCheckEnabled)) - flags |= LOADER_FLAGS_MEDIACHECK; - - Py_XDECREF(mediaCheckEnabled); -} - -static void useKickstartDD(struct loaderData_s * loaderData, PyObject *handler) { - Py_ssize_t i; - PyObject *list = getDataList(handler, "driverdisk"); - - if (!list) - return; - - for (i = 0; i < PyList_Size(list); i++) { - PyObject *ele = PyList_GetItem(list, i); - PyObject *attr; - - if (!ele) - continue; - - attr = getObject(ele, "source", 0); - if (isNotEmpty(attr)) { - getDDFromSource(loaderData, PyString_AsString(attr), NULL); - goto cleanup; - } - - Py_XDECREF(attr); - attr = getObject(ele, "partition", 0); - - if (isNotEmpty(attr)) { - getDDFromDev(loaderData, PyString_AsString(attr), NULL); - goto cleanup; - } - - Py_XDECREF(attr); - attr = getObject(ele, "biospart", 0); - - if (isNotEmpty(attr)) { - char *dev = strdup(PyString_AsString(attr)); - char *biospart = NULL, *p = NULL; - - p = strchr(dev,'p'); - if (!p){ - logMessage(ERROR, "Bad argument for biospart"); - goto cleanup; - } - *p = '\0'; - - biospart = getBiosDisk(dev); - if (biospart == NULL) { - logMessage(ERROR, "Unable to locate BIOS dev %s",dev); - goto cleanup; - } - - free(dev); - dev = malloc(strlen(biospart) + strlen(p + 1) + 2); - sprintf(dev, "%s%s", biospart, p + 1); - getDDFromDev(loaderData, dev, NULL); - } - -cleanup: - Py_XDECREF(attr); - } - - Py_XDECREF(list); -} - -static void setKickstartKeyboard(struct loaderData_s * loaderData, PyObject *handler) { - PyObject *kbdObj = getattr(handler, "keyboard", "keyboard"); - - if (isNotEmpty(kbdObj)) { - loaderData->kbd = strdup(PyString_AsString(kbdObj)); - loaderData->kbd_set = 1; - } - - Py_XDECREF(kbdObj); -} - -static void setKickstartLanguage(struct loaderData_s * loaderData, PyObject *handler) { - PyObject *langObj = getattr(handler, "lang", "lang"); - - if (isNotEmpty(langObj)) { - loaderData->lang = strdup(PyString_AsString(langObj)); - loaderData->lang_set = 1; - } - - Py_XDECREF(langObj); -} - -static void _setNetworkString(PyObject *obj, const char *name, char **dest, int *sentinel) { - PyObject *attr = getObject(obj, name, 0); - - if (!isNotEmpty(attr)) - goto cleanup; - - if (*dest) - free(*dest); - *dest = strdup(PyString_AsString(attr)); - - Py_XDECREF(attr); - - if (sentinel) - *sentinel = 1; - -cleanup: - Py_XDECREF(attr); -} - -int process_kickstart_wifi (struct loaderData_s * loaderData) { - int rc = -1; - - if (loaderData->essid != NULL) { - checkIPsettings(&(loaderData->ipinfo_set), &(loaderData->ipv4), - &(loaderData->gateway), &(loaderData->netmask)); - if (loaderData->wepkey != NULL) { - rc = add_and_activate_wifi_connection(&(loaderData->netDev), loaderData->essid, - WIFI_PROTECTION_WEP, loaderData->wepkey, loaderData->ipinfo_set, loaderData->ipv4, - loaderData->gateway, loaderData->dns, loaderData->netmask); - } - else if (loaderData->wpakey != NULL) { - rc = add_and_activate_wifi_connection(&(loaderData->netDev), loaderData->essid, - WIFI_PROTECTION_WPA, loaderData->wpakey, loaderData->ipinfo_set, loaderData->ipv4, - loaderData->gateway, loaderData->dns, loaderData->netmask); - } - else { - rc = add_and_activate_wifi_connection(&(loaderData->netDev), loaderData->essid, - WIFI_PROTECTION_UNPROTECTED, NULL, loaderData->ipinfo_set, loaderData->ipv4, - loaderData->gateway, loaderData->dns, loaderData->netmask); - } - } - - if (rc == WIFI_ACTIVATION_OK) loaderData->netDev_set = 1; - else logMessage(ERROR, "wifi activation in kickstart failed"); - - return rc; -} - - -static void setKickstartNetwork(struct loaderData_s * loaderData, PyObject *handler) { - Py_ssize_t i; - PyObject *list = getDataList(handler, "network"); - iface_t iface; - char *cmdline_device = NULL; - - if (!list) - return; - - for (i = 0; i < PyList_Size(list); i++) { - PyObject *ele = PyList_GetItem(list, i); - PyObject *attr; - - if (!ele) - continue; - - iface_init_iface_t(&iface); - - /* initialize network configuration bits of loaderData struct */ - /* except for --device which we want to take over from cmdline */ - /* ksdevice for the first command */ - free(loaderData->ipv4); - loaderData->ipv4 = NULL; - loaderData->ipinfo_set = 0; - free(loaderData->dns); - loaderData->dns = NULL; - free(loaderData->netmask); - loaderData->netmask = NULL; - free(loaderData->hostname); - loaderData->hostname = NULL; - free(loaderData->gateway); - loaderData->gateway = NULL; - free(loaderData->netCls); - loaderData->netCls = NULL; - loaderData->netCls_set = 0; - free(loaderData->ethtool); - loaderData->ethtool = NULL; - loaderData->essid = NULL; - free(loaderData->wepkey); - loaderData->wepkey = NULL; - free(loaderData->wpakey); - loaderData->wpakey = NULL; - loaderData->mtu = 0; - -#ifdef ENABLE_IPV6 - free(loaderData->ipv6); - loaderData->ipv6 = NULL; - free(loaderData->ipv6prefix); - loaderData->ipv6prefix = NULL; - loaderData->ipv6info_set = 0; - free(loaderData->gateway6); - loaderData->gateway6 = NULL; -#endif - - /* if they've specified dhcp/bootp use dhcp for the interface */ - attr = getObject(ele, "bootProto", 0); - if (objIsStr(attr, "dhcp") || objIsStr(attr, "bootp")) { - loaderData->ipv4 = strdup("dhcp"); - loaderData->ipinfo_set = 1; - } else if (objIsStr(attr, "ibft")) { - loaderData->ipv4 = strdup("ibft"); - loaderData->ipinfo_set = 1; - } else if (objIsStr(attr, "static")) { - _setNetworkString(ele, "ip", &loaderData->ipv4, &loaderData->ipinfo_set); - } - - Py_XDECREF(attr); - -#ifdef ENABLE_IPV6 - _setNetworkString(ele, "ipv6", &loaderData->ipv6, &loaderData->ipv6info_set); - if (loaderData->ipv6) { - split_ipv6addr_prefix_length(loaderData->ipv6, - &(loaderData->ipv6), - &(loaderData->ipv6prefix)); - } -#endif - - _setNetworkString(ele, "nameserver", &loaderData->dns, NULL); - _setNetworkString(ele, "netmask", &loaderData->netmask, NULL); - _setNetworkString(ele, "hostname", &loaderData->hostname, NULL); - - /* --gateway is common for ipv4 and ipv6, same as in loader UI */ - attr = getObject(ele, "gateway", 0); - if (isNotEmpty(attr)) { - char *gateway = strdup(PyString_AsString(attr)); - if (isValidIPv4Address(gateway)) { - loaderData->gateway = gateway; -#ifdef ENABLE_IPV6 - } else if (isValidIPv6Address(gateway)) { - loaderData->gateway6 = gateway; -#endif - } else { - logMessage(WARNING, - "invalid address in kickstart --gateway"); - free(gateway); - } - } - - Py_XDECREF(attr); - - attr = getObject(ele, "device", 0); - if (isNotEmpty(attr)) { - char *device = PyString_AsString(attr); - - /* If --device=MAC was given, translate into a device name now. */ - if (index(device, ':') == NULL || - (loaderData->netDev = iface_mac2device(device)) == NULL) - loaderData->netDev = strdup(device); - - loaderData->netDev_set = 1; - logMessage(INFO, "kickstart network command - device %s", loaderData->netDev); - } else { - if (loaderData->netDev) { - /* save it so we can use it if wifi activation fails */ - cmdline_device = loaderData->netDev; - loaderData->netDev = NULL; - loaderData->netDev_set = 0; - } - logMessage(INFO, "kickstart network command - unspecified device"); - } - - Py_XDECREF(attr); - - _setNetworkString(ele, "dhcpclass", &loaderData->netCls, &loaderData->netCls_set); - _setNetworkString(ele, "ethtool", &loaderData->ethtool, NULL); - _setNetworkString(ele, "essid", &loaderData->essid, NULL); - _setNetworkString(ele, "wepkey", &loaderData->wepkey, NULL); - _setNetworkString(ele, "wpakey", &loaderData->wpakey, NULL); - - attr = getObject(ele, "noipv4", 0); - if (isTrue(attr)) - flags |= LOADER_FLAGS_NOIPV4; - - Py_XDECREF(attr); - - attr = getObject(ele, "mtu", 0); - if (isNotEmpty(attr)) { - /* Don't free this string! */ - char *mtu = PyString_AsString(attr); - - errno = 0; - loaderData->mtu = strtol(mtu, NULL, 10); - - if ((errno == ERANGE && (loaderData->mtu == LONG_MIN || - loaderData->mtu == LONG_MAX)) || - (errno != 0 && loaderData->mtu == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - } - - Py_XDECREF(attr); - -#ifdef ENABLE_IPV6 - attr = getObject(ele, "noipv6", 0); - if (isTrue(attr)) - flags |= LOADER_FLAGS_NOIPV6; - - Py_XDECREF(attr); -#endif - - attr = getObject(ele, "nodns", 0); - if (isTrue(attr)) - loaderData->noDns = 1; - - Py_XDECREF(attr); - - attr = getObject(ele, "nodefroute", 0); - if (isTrue(attr)) - iface.defroute = 0; - - Py_XDECREF(attr); - - /* Always activate first network command device for network - * installs(RHEL 5 behaviour) */ - if (!i && - (isURLRemote(loaderData->instRepo) || - FL_EARLY_NETWORKING(flags) || - ibft_present())) { - logMessage(INFO, "activating first device from kickstart because network is needed"); - if (process_kickstart_wifi(loaderData) != WIFI_ACTIVATION_OK) { - if (cmdline_device) { - loaderData->netDev = cmdline_device; - loaderData->netDev_set = 1; - cmdline_device = NULL; - } - activateDevice(loaderData, &iface); - } - continue; - } - - attr = getObject(ele, "activate", 0); - if (isTrue(attr)) { - logMessage(INFO, "activating because --activate flag is set"); - if (process_kickstart_wifi(loaderData) != WIFI_ACTIVATION_OK) { - if (cmdline_device) { - loaderData->netDev = cmdline_device; - loaderData->netDev_set = 1; - cmdline_device = NULL; - } - activateDevice(loaderData, &iface); - } - } else { - logMessage(INFO, "not activating becuase --activate flag is not set"); - } - - Py_XDECREF(attr); - } - - Py_XDECREF(list); -} - -static void setKickstartCD(struct loaderData_s * loaderData, PyObject *handler) { - PyObject *methodObj = getattr(handler, "method", "method"); - - if (objIsStr(methodObj, "cdrom")) { - logMessage(INFO, "kickstartFromCD"); - loaderData->method = METHOD_CDROM; - } - - Py_XDECREF(methodObj); -} - -static void setKickstartHD(struct loaderData_s * loaderData, PyObject *handler) { - PyObject *methodObj = getattr(handler, "method", "method"); - PyObject *biospartObj = NULL; - char *partition = NULL, *dir = NULL; - - if (!objIsStr(methodObj, "harddrive")) - goto cleanup; - - logMessage(INFO, "kickstartFromHD"); - - biospartObj = getattr(handler, "method", "biospart"); - if (isNotEmpty(biospartObj)) { - char *biospart = strdup(PyString_AsString(biospartObj)); - char *dev, *p; - - p = strchr(biospart,'p'); - if(!p) { - logMessage(ERROR, "Bad argument for --biospart"); - free(biospart); - goto cleanup; - } - - *p = '\0'; - dev = getBiosDisk(biospart); - if (dev == NULL) { - logMessage(ERROR, "Unable to location BIOS partition %s", biospart); - free(biospart); - goto cleanup; - } - - partition = malloc(strlen(dev) + strlen(p + 1) + 2); - sprintf(partition, "%s%s", dev, p + 1); - } - - loaderData->method = METHOD_HD; - - if (!partition) - partition = strdup(PyString_AsString(getattr(handler, "method", "partition"))); - - dir = strdup(PyString_AsString(getattr(handler, "method", "dir"))); - - checked_asprintf(&loaderData->instRepo, "hd:%s:%s", partition, dir); - logMessage(INFO, "results of hd ks, partition is %s, dir is %s", partition, - dir); - - free(partition); - free(dir); -cleanup: - Py_XDECREF(methodObj); - Py_XDECREF(biospartObj); -} - -static void setKickstartNfs(struct loaderData_s * loaderData, PyObject *handler) { - PyObject *methodObj = getattr(handler, "method", "method"); - PyObject *hostObj = NULL, *dirObj = NULL, *optsObj = NULL; - char *host, *dir; - - if (!objIsStr(methodObj, "nfs")) - goto cleanup; - - logMessage(INFO, "kickstartFromNfs"); - - hostObj = getattr(handler, "method", "server"); - dirObj = getattr(handler, "method", "dir"); - optsObj = getattr(handler, "method", "opts"); - - if (!isNotEmpty(hostObj) || !isNotEmpty(dirObj)) { - logMessage(ERROR, "host and directory for nfs kickstart not specified"); - goto cleanup; - } - - /* Don't free these strings! */ - host = PyString_AsString(hostObj); - dir = PyString_AsString(dirObj); - - loaderData->method = METHOD_NFS; - - if (isNotEmpty(optsObj)) { - logMessage(INFO, "results of nfs, host is %s, dir is %s, opts are '%s'", - host, dir, PyString_AsString(optsObj)); - checked_asprintf(&loaderData->instRepo, "nfs:%s:%s:%s", - PyString_AsString(optsObj), host, dir); - } else { - logMessage(INFO, "results of nfs, host is %s, dir is %s", host, dir); - checked_asprintf(&loaderData->instRepo, "nfs:%s:%s", host, dir); - } - -cleanup: - Py_XDECREF(methodObj); - Py_XDECREF(hostObj); - Py_XDECREF(dirObj); - Py_XDECREF(optsObj); -} - -static void setKickstartUrl(struct loaderData_s * loaderData, PyObject *handler) { - char *url = NULL; - PyObject *methodObj = getattr(handler, "method", "method"); - PyObject *urlObj = NULL; - PyObject *noverifysslObj = NULL, *proxyObj = NULL; - - if (!objIsStr(methodObj, "url")) - goto cleanup; - - urlObj = getattr(handler, "method", "url"); - - if (!isNotEmpty(urlObj)) - goto cleanup; - - /* Don't free this string! */ - url = PyString_AsString(urlObj); - logMessage(INFO, "kickstartFromUrl"); - - /* determine install type */ - if (strncmp(url, "http", 4) && strncmp(url, "ftp://", 6)) { - newtWinMessage(_("Kickstart Error"), _("OK"), - _("Unknown Url method %s"), url); - goto cleanup; - } - - noverifysslObj = getattr(handler, "method", "noverifyssl"); - proxyObj = getattr(handler, "method", "proxy"); - - loaderData->instRepo = strdup(url); - loaderData->method = METHOD_URL; - - if (isTrue(noverifysslObj)) - loaderData->instRepo_noverifyssl = 1; - else - loaderData->instRepo_noverifyssl = 0; - - if (isNotEmpty(proxyObj)) { - splitProxyParam(PyString_AsString(proxyObj), &loaderData->proxyUser, - &loaderData->proxyPassword, - &loaderData->proxy); - } - - logMessage(INFO, "results of url ks, url %s", url); - -cleanup: - Py_XDECREF(methodObj); - Py_XDECREF(urlObj); - Py_XDECREF(noverifysslObj); - Py_XDECREF(proxyObj); -} - -char *runKickstart(struct loaderData_s * loaderData, const char *file) { - PyObject *versionMod, *parserMod = NULL; - PyObject *handler, *parser; - PyObject *processedFile; - char *retval = NULL; - - PyObject *callable = NULL; - - logMessage(INFO, "setting up kickstart"); - - Py_Initialize(); - - if ((versionMod = import("pykickstart.version")) == NULL) - goto quit; - - if ((parserMod = import("pykickstart.parser")) == NULL) - goto quit; - - if ((constantsMod = import("pykickstart.constants")) == NULL) - goto quit; - - /* make the KickstartHandler object */ - if ((handler = makeHandler(versionMod)) == NULL) - goto quit; - - /* make the KickstartParser object */ - if ((callable = getObject(parserMod, "KickstartParser", 1)) == NULL) - goto quit; - else - parser = makeParser(callable, handler); - - /* call preprocessKickstart */ - processedFile = preprocessKickstart(parserMod, file); - - /* call readKickstart */ - if (processedFile) { - commandFunc_t *cmd; - - if (!readKickstart(parser, processedFile)) - goto quit; - - /* Now handler is set up with all the kickstart data. Run through - * every element of the ksTable and run its function. The functions - * themselves will decide if they should do anything or not. - */ - for (cmd = ksTable; *cmd != NULL; cmd++) - (*cmd)(loaderData, handler); - - retval = strdup(PyString_AsString(processedFile)); - } - -quit: - Py_XDECREF(constantsMod); - Py_XDECREF(versionMod); - Py_XDECREF(callable); - Py_XDECREF(parserMod); - Py_Finalize(); - return retval; -} - -/* vim:set sw=4 sts=4 et: */ diff --git a/loader/kickstart.h b/loader/kickstart.h deleted file mode 100644 index 8163cb7..0000000 --- a/loader/kickstart.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * kickstart.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef H_KICKSTART - -#include "loader.h" - -int isKickstartFileRemote(char *ksFile); -void getKickstartFile(struct loaderData_s * loaderData); -char *runKickstart(struct loaderData_s * loaderData, const char *file); -int getKickstartFromBlockDevice(char *device, char *path); - -#endif diff --git a/loader/lang.c b/loader/lang.c deleted file mode 100644 index 0b8a76f..0000000 --- a/loader/lang.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * lang.c - determines language, handles translations - * - * 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <alloca.h> -#include <errno.h> -#include <fcntl.h> -#include <netinet/in.h> -#include <newt.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <wchar.h> -#include <glib.h> - -#include "loader.h" -#include "lang.h" -#include "loadermisc.h" -#include "windows.h" -#include "unpack.h" - -#include "../pyanaconda/isys/lang.h" -#include "../pyanaconda/isys/isys.h" -#include "../pyanaconda/isys/log.h" - -const char *LANG_DEFAULT = "en_US.UTF-8"; - -/* boot flags */ -extern uint64_t flags; - -struct aString { - unsigned int hash; - short length; - char * str; -} ; - -struct aString * strings = NULL; -int numStrings = 0, allocedStrings = 0; - -static int english = 0; - -static char * topLineWelcome = N_("Welcome to %s for %s"); -static char * topLineWelcomeRescue = N_("Welcome to %s for %s - Rescue Mode"); -static char * bottomHelpLine = N_(" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen "); - -static int aStringCmp(const void * a, const void * b) { - const struct aString * first = a; - const struct aString * second = b; - - if (first->hash < second->hash) - return -1; - else if (first->hash == second->hash) - return 0; - - return 1; -} - -char * translateString(char * str) { - unsigned int sum = 0, xor = 0; - int len = 0; - char * chptr; - struct aString * match; - struct aString key; - - for (chptr = str; *chptr; chptr++) { - sum += *chptr; - xor ^= *chptr; - len++; - } - - key.hash = (sum << 16) | ((xor & 0xFF) << 8) | (len & 0xFF); - match = bsearch(&key, strings, numStrings, sizeof(*strings), aStringCmp); - if (!match) - return str; - - return match->str; -} - -static struct langInfo * languages = NULL; -static int numLanguages = 0; - -static int defaultLanguageIndex(void) { - int i; - for (i = 0; i < numLanguages; ++i) - if (!strcmp(languages[i].lc_all, LANG_DEFAULT)) - return i; - return -1; -} - -static void loadLanguageList(void) { - char * file = "/etc/lang-table"; - FILE * f; - char line[256]; - char name[256], key[256], text_supported[256], code[256], - keyboard[256], timezone[256]; - int lineNum = 0; - - wcwidth(0); - f = fopen(file, "r"); - if (!f) { - newtWinMessage(_("Error"), _("OK"), "cannot open %s: %m", file); - return; - } - - while (fgets(line, sizeof(line), f)) { - lineNum++; - languages = realloc(languages, sizeof(*languages) * (numLanguages + 1)); - if (sscanf(line, "%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\n", - name, key, text_supported, code, keyboard, timezone) != 6) { - printf("bad line %d in lang-table", lineNum); - logMessage(WARNING, "bad line %d in lang-table", lineNum); - } else { - languages[numLanguages].lang = strdup(name); - languages[numLanguages].key = strdup(key); - languages[numLanguages].text_supported = !strcmp(text_supported, "True"); - languages[numLanguages].lc_all = strdup(code); - languages[numLanguages++].keyboard = strdup(keyboard); - } - } - fclose(f); -} - -int getLangInfo(struct langInfo ** langs) { - if (!languages) - loadLanguageList(); - - *langs = languages; - return numLanguages; -} - -/** - * Normalize the value of lang= boot argument. - * - * Currently only replaces the trailing .utf8 with .UTF-8. - * - * Returns a heap-allocated string. - */ -gchar *normalizeLang(const gchar *s) -{ - if (g_str_has_suffix(s, ".utf8")) { - gchar *lang = g_strndup(s, strlen(s) - strlen(".utf8")); - gchar *result = g_strconcat(lang, ".UTF-8", NULL); - g_free(lang); - return result; - } - - return g_strdup(s); -} - -void loadLanguage(void) -{ - char *filename; - int fd, hash, rc; - char * key = getenv("LANGKEY"); - - if (strings) { - free(strings), strings = NULL; - numStrings = allocedStrings = 0; - } - - /* english requires no files */ - if (!strcmp(key, "en")) - return; - - checked_asprintf(&filename, "/tmp/translation/%s.tr", key); - - rc = unpack_archive_file("/etc/loader.tr", "/tmp/translation"); - if (rc != ARCHIVE_OK || access("/tmp/translation", R_OK) == -1) { - newtWinMessage("Error", "OK", "Cannot get translation file %s.\n", - filename); - return; - } - - fd = open(filename, O_RDONLY); - if (fd < 0) { - newtWinMessage("Error", "OK", "Failed to open /tmp/translation: %m\n"); - free(filename); - return; - } - - while (read(fd, &hash, 4) == 4) { - if (allocedStrings == numStrings) { - allocedStrings += 10; - strings = realloc(strings, sizeof(*strings) * allocedStrings); - } - - strings[numStrings].hash = ntohl(hash); - rc = read(fd, &strings[numStrings].length, 2); - strings[numStrings].length = ntohs(strings[numStrings].length); - strings[numStrings].str = malloc(strings[numStrings].length + 1); - rc = read(fd, strings[numStrings].str, strings[numStrings].length); - strings[numStrings].str[strings[numStrings].length] = '\0'; - numStrings++; - } - - close(fd); - free(filename); - int translation_dir_fd = open("/tmp/translation", O_RDONLY); - recursiveRemove(translation_dir_fd); - close(translation_dir_fd); - rmdir("/tmp/translation"); - - qsort(strings, numStrings, sizeof(*strings), aStringCmp); -} - - -/* give the index of the language to set to -- sets the appropriate - * lang variables if we have a font. - * - * ASSUMPTION: languages exists - */ -static void setLangEnv (int i) { - if (i > numLanguages) - return; - - if (!languages[i].text_supported) - return; - logMessage(INFO, "setting language to %s", languages[i].lc_all); - - setenv("LANG", languages[i].lc_all, 1); - setenv("LANGKEY", languages[i].key, 1); - setenv("LINGUAS", languages[i].lang, 1); - loadLanguage(); -} - -/* choice is the index of the chosen language in languages */ -static int setupLanguage(int choice, int forced) { - char * buf; - char *locale_def = NULL; /* locale lang name */ - char *locale_charset = NULL;/* locale charset */ - char *locale_mod = NULL; /* locale variant */ - char *locale_p = NULL; /* last known locale separator */ - char *locale_i = NULL; /* string iterator */ - int i; - pid_t localedef_pid; - - logMessage(DEBUGLVL, "going to set language to %s", languages[choice].lc_all); - - /* Parse locale parts out of locale name. - - Locale examples: - en - en_US - cz_CS.UTF-8 - cz_CS.UTF-8@latin - */ - - locale_p = locale_i = languages[choice].lc_all; - while (1) { - // we found new separator - if (*locale_i == '.' || *locale_i == '@' || *locale_i == '\0') { - // last separator was annotating charset - if (*locale_p == '.') locale_charset = strndup(locale_p + 1, locale_i - locale_p - 1); - // last separator was annotating modifier - else if (*locale_p == '@') locale_mod = strndup(locale_p + 1, locale_i - locale_p - 1); - // there was no known separator last time - else locale_def = strndup(locale_p, locale_i - locale_p); - - // save last known separator - locale_p = locale_i; - - if(*locale_i == '\0') break; // end of the string - } - - // test next character - locale_i++; - } - - logMessage(DEBUGLVL, "locale %s: base: %s, mod: %s, charset: %s", languages[choice].lc_all, locale_def, locale_mod, locale_charset); - - /* prepare locale name without charset */ - i = strlen(locale_def); - if (locale_mod) i+= strlen(locale_mod) + 1; /* +1 for the @ char */ - locale_p = (char*)calloc(i+1, sizeof(char)); - locale_p = strcpy(locale_p, locale_def); - if (locale_mod){ - locale_p[strlen(locale_p)] = '@'; - locale_p = strcat(locale_p, locale_mod); - } - - /* generate locale record */ - logMessage(INFO, "going to prepare locales for %s (locale: %s, charset: %s)", languages[choice].lc_all, locale_p, locale_charset); - if ((localedef_pid = fork()) == 0) { - execl("/usr/bin/localedef", "localedef", - "-i", locale_p, - "-f", (locale_charset) ? locale_charset : "UTF-8", - languages[choice].lc_all, NULL); - _exit(254); - } - - if (localedef_pid < 0) logMessage(ERROR, "failed forking localedef for %s", languages[choice].lc_all); - else{ - waitpid(localedef_pid, &i, 0); - if (WEXITSTATUS(i) != 0) logMessage(ERROR, "failed preparing locales %s [%d]", languages[choice].lc_all, WEXITSTATUS(i)); - } - - /* cleanup */ - if (locale_charset) free(locale_charset); - if (locale_def) free(locale_def); - if (locale_mod) free(locale_mod); - if (locale_p) free(locale_p); - - /* load the language only if it is displayable. if they're using - * a serial console or iSeries vioconsole, we hope it's smart enough */ - if (!languages[choice].text_supported && !FL_SERIAL(flags) && - !FL_VIRTPCONSOLE(flags) && !isVioConsole()) { - if (forced == 1) return 0; - - newtWinMessage("Language Unavailable", "OK", - "%s display is unavailable in text mode. The " - "installation will continue in English until the " - "display of %s is possible.", languages[choice].lang, - languages[choice].lang); - setLangEnv(english); - return 0; - } - - setLangEnv (choice); - - /* clear out top line */ - buf = alloca(81); /* reserve one byte for \0 */ - for (i=0; i < 80; i++) - buf[i] = ' '; - buf[80] = 0; /* and set the \0 */ - newtDrawRootText(0, 0, buf); - - char *fmt = FL_RESCUE(flags) ? _(topLineWelcomeRescue) : _(topLineWelcome); - checked_asprintf(&buf, fmt, getProductName(), getProductArch()); - - newtDrawRootText(0, 0, buf); - free(buf); - newtPopHelpLine(); - newtPushHelpLine(_(bottomHelpLine)); - - return 0; -} - -/* this is pretty simple. we want to break down the language specifier - * into its short form (eg, en_US) - */ -static char * getLangShortForm(char * oldLang) { - char * lang; - char * c; - - lang = strdup(oldLang); - - c = strchr(lang, '@'); - if (c) { - *c = '\0'; - } - - c = strchr(lang, '.'); - if (c) { - *c = '\0'; - } - - return lang; -} - -/* return the nick of a language -- eg en_US -> en */ -static char * getLangNick(char * oldLang) { - char * lang; - char * c; - - lang = strdup(oldLang); - - c = strchr(lang, '_'); - if (c) { - *c = '\0'; - } - - return lang; -} - -int setLanguage (const char * key, int forced) { - int i; - - if (!languages) loadLanguageList(); - - for (i = 0; i < numLanguages; i++) { - if (!strcmp(languages[i].lc_all, key)) { - return setupLanguage(i, forced | !FL_KICKSTART(flags)); - } - } - - /* we didn't specify anything that's exactly in the lang-table. check - * against short forms and nicks */ - for (i = 0; i < numLanguages; i++) { - if (!strcmp(getLangShortForm(languages[i].lc_all), key)) { - return setupLanguage(i, forced | !FL_KICKSTART(flags)); - } - } - - for (i = 0; i < numLanguages; i++) { - if (!strcmp(getLangNick(languages[i].lc_all), key)) { - return setupLanguage(i, forced | !FL_KICKSTART(flags)); - } - } - - logMessage(ERROR, "unable to set the requested language '%s', " - "setting the default '%s'", key, LANG_DEFAULT); - return setupLanguage(defaultLanguageIndex(), forced | !FL_KICKSTART(flags)); -} - -int chooseLanguage(char ** lang) { - int choice = 0; - char ** langs; - int i; - int current = -1; - char * currentLangName = getenv("LANG"); - int numLangs = 0; - char * langPicked; - - if (!languages) loadLanguageList(); - - langs = alloca(sizeof(*langs) * (numLanguages + 1)); - - for (i = 0; i < numLanguages; i++) { - if (!strncmp(languages[i].key, "en", 2)) - english = numLangs; - if (currentLangName && - !strcmp(languages[i].lang, currentLangName)) - current = numLangs; - - langs[numLangs++] = languages[i].lang; - } - - langs[numLangs] = NULL; - - if (current >= 0) - choice = current; - else - choice = english; - - if (!FL_CMDLINE(flags)) - newtWinMenu(_("Choose a Language"), - _("What language would you like to use during the " - "installation process?"), 40, 5, 5, 8, - langs, &choice, _("OK"), NULL); - - langPicked = langs[choice]; - for (i = 0; i < numLanguages; i++) { - if (!strcmp(langPicked, languages[i].lang)) { - *lang = languages[i].lc_all; - choice = i; - break; - } - } - - /* this can't happen */ - if (i == numLanguages) abort(); - - return setupLanguage(choice, 0); -} diff --git a/loader/lang.h b/loader/lang.h deleted file mode 100644 index 6531381..0000000 --- a/loader/lang.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * lang.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef _LANG_H_ -#define _LANG_H_ - -#include "loader.h" - -#define _(x) translateString (x) -#define N_(foo) (foo) - -struct langInfo { - char * lang, * key, * lc_all, * keyboard; - unsigned int text_supported; -} ; - - -int chooseLanguage(char ** lang); -char * translateString(char * str); -int setLanguage (const char * key, int forced); -int getLangInfo(struct langInfo **langs); -char * normalizeLang(const char *s); - -extern const char *LANG_DEFAULT; - -#endif /* _LANG_H_ */ diff --git a/loader/loader.c b/loader/loader.c deleted file mode 100644 index c60795f..0000000 --- a/loader/loader.c +++ /dev/null @@ -1,2441 +0,0 @@ -/* - * loader.c - * - * This is the installer loader. Its job is to somehow load the rest - * of the installer into memory and run it. This may require setting - * up some devices and networking, etc. The main point of this code is - * to stay SMALL! Remember that, live by that, and learn to like it. - * - * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006, 2007 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <ctype.h> -#include <errno.h> -#include <execinfo.h> -#include <fcntl.h> -#include <newt.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <unistd.h> -#include <stdint.h> -#include <dirent.h> -#include <arpa/inet.h> - -#include <sys/ioctl.h> -#include <sys/klog.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/utsname.h> - -#include <linux/fb.h> -#include <linux/serial.h> -#include <linux/vt.h> - -#include <glib.h> - -#ifdef USE_MTRACE -#include <mcheck.h> -#endif - -#include "serial.h" -#include "copy.h" -#include "getparts.h" -#include "loader.h" -#include "loadermisc.h" /* JKFIXME: functions here should be split out */ -#include "lang.h" -#include "fwloader.h" -#include "kbd.h" -#include "kickstart.h" -#include "windows.h" - -/* module stuff */ -#include "modules.h" -#include "moduleinfo.h" - -#include "driverdisk.h" - -/* hardware stuff */ -#include "hardware.h" - -/* install method stuff */ -#include "method.h" -#include "cdinstall.h" -#include "nfsinstall.h" -#include "hdinstall.h" -#include "urls.h" -#include "urlinstall.h" - -#include "ibft.h" -#include "net.h" -#include "readvars.h" -#include "unpack.h" -#ifdef USESELINUX -#include <selinux/selinux.h> -#endif -#include "selinux.h" - -#include "../pyanaconda/isys/imount.h" -#include "../pyanaconda/isys/isys.h" -#include "../pyanaconda/isys/lang.h" -#include "../pyanaconda/isys/eddsupport.h" -#include "../pyanaconda/isys/log.h" -#include "../pyanaconda/isys/mem.h" - -/* maximum number of extra arguments that can be passed to the second stage */ -#define MAX_EXTRA_ARGS 128 -static char * extraArgs[MAX_EXTRA_ARGS]; -static int hasGraphicalOverride(); - -static int newtRunning = 0; - -/* boot flags -- we need these in a lot of places */ -uint64_t flags = LOADER_FLAGS_SELINUX; - -#ifdef INCLUDE_LOCAL -#include "cdinstall.h" -#include "hdinstall.h" -#endif -#ifdef INCLUDE_NETWORK -#include "nfsinstall.h" -#include "urlinstall.h" -#endif - -int num_link_checks = 5; -int post_link_sleep = 0; - -static int init_sig = SIGUSR1; /* default to shutdown=halt */ - -static char *VIRTIO_PORT = "/dev/virtio-ports/org.fedoraproject.anaconda.log.0"; - -static struct installMethod installMethods[] = { - { N_("Local CD/DVD"), "METHOD_CDROM", 0, DEVICE_CDROM, promptForCdrom, loadCdromImages}, - { N_("Hard drive"), "METHOD_HD", 0, DEVICE_DISK, promptForHardDrive, loadHdImages }, - { N_("NFS directory"), "METHOD_NFS", 1, DEVICE_NETWORK, promptForNfs, loadNfsImages }, - { "URL", "METHOD_URL", 1, DEVICE_NETWORK, promptForUrl, loadUrlImages}, -}; -static int numMethods = sizeof(installMethods) / sizeof(struct installMethod); - -static int expected_exit = 0; - -static GHashTable *cmdline = NULL; - -void doExit(int result) -{ - expected_exit = 1; - exit(result); -} - -void doSuspend(void) { - newtFinished(); - doExit(1); -} - -void doShell(void) { - pid_t child; - int status; - - newtSuspend(); - child = fork(); - - if (child == 0) { - if (chdir("/root") == 0) { - if (execl("/bin/bash", "/bin/bash", "-i", NULL) == -1) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - _exit(1); - } - } else { - logMessage(ERROR, "missing /root, cannot run shell"); - } - } else if (child == -1) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - newtResume(); - } else { - if (waitpid(child, &status, 0) == -1) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - } - - newtResume(); - } -} - -void doGdbserver(struct loaderData_s *loaderData) { - int child, fd; - char *pid; - iface_t iface; - - /* If gdbserver is found, go ahead and run it on the loader process now - * before anything bad happens. - */ - if (loaderData->gdbServer && !access("/usr/bin/gdbserver", X_OK)) { - pid_t loaderPid = getpid(); - iface_init_iface_t(&iface); - - if (kickstartNetworkUp(loaderData, &iface)) { - logMessage(ERROR, "can't run gdbserver due to no network"); - return; - } - - checked_asprintf(&pid, "%d", loaderPid); - - if (!(child = fork())) { - logMessage(INFO, "starting gdbserver: %s %s %s %s", - "/usr/bin/gdbserver", "--attach", loaderData->gdbServer, - pid); - - fd = open("/dev/null", O_RDONLY); - close(STDIN_FILENO); - dup2(fd, STDIN_FILENO); - close(fd); - fd = open("/dev/null", O_WRONLY); - close(STDOUT_FILENO); - dup2(fd, STDOUT_FILENO); - close(STDERR_FILENO); - dup2(fd, STDERR_FILENO); - close(fd); - - if (execl("/usr/bin/gdbserver", "/usr/bin/gdbserver", "--attach", - loaderData->gdbServer, pid, NULL) == -1) - logMessage(ERROR, "error running gdbserver: %m"); - - _exit(1); - } - } -} - -void startNewt(void) { - if (!newtRunning) { - char *buf; - char *arch = getProductArch(); - checked_asprintf(&buf, _("Welcome to %s for %s"), getProductName(), arch); - - /* - * Because currently initrd.img only has got the default English locale - * support, pretend for newtInit() it is actually the used LANG so Newt - * knows how to compute character widths etc. - */ - char *lang = getenv("LANG"); - if (lang) { - lang = strdup(lang); - } - setenv("LANG", LANG_DEFAULT, 1); - newtInit(); - unsetenv("LANG"); - /* restore the original LANG value */ - if (lang) { - setenv("LANG", lang, 1); - free(lang); - } - - newtCls(); - newtDrawRootText(0, 0, buf); - free(buf); - - newtPushHelpLine(_(" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen ")); - - newtRunning = 1; - if (!access("/bin/sh", X_OK)) - newtSetSuspendCallback((void *) doShell, NULL); - } -} - -void stopNewt(void) { - if (newtRunning) newtFinished(); - newtRunning = 0; -} - -static gchar *productName = NULL; -static gchar *productArch = NULL; - -/* The product info comes from ./.buildstamp, which is an .ini-style file - * written out by scripts/mk-images and put into every initrd. It contains - * information about the product being booted, which is what differentiates it - * from .treeinfo. A valid file looks like this: - * - * [Main] - * BugURL=http://bugzilla.redhat.com - * IsFinal=true|false - * Product=<name of the product - Fedora, RHEL, etc.> - * UUID=<time and date stamp, then a dot, then the architecture> - * Version=<version of the product - 6.0, 14, etc.> - * - * Any other key/value pairs will be silently ignored. - */ -static void initProductInfo(void) { - GKeyFile *key_file = g_key_file_new(); - GError *loadErr = NULL; - - if (!g_key_file_load_from_file(key_file, "/.buildstamp", G_KEY_FILE_NONE, &loadErr)) { - logMessage(ERROR, "error reading .buildstamp: %s", loadErr->message); - g_error_free(loadErr); - productName = g_strdup("anaconda"); - productArch = g_strdup("unknown architecture"); - return; - } - - if (g_key_file_has_key(key_file, "Main", "Product", NULL)) - productName = g_key_file_get_string(key_file, "Main", "Product", NULL); - else - productName = g_strdup("anaconda"); - - if (g_key_file_has_key(key_file, "Main", "UUID", NULL)) { - gchar **parts = g_strsplit(g_key_file_get_string(key_file, "Main", "UUID", NULL), ".", 0); - - if (parts != NULL && g_strv_length(parts) == 2) - productArch = g_strdup(parts[1]); - else - productArch = g_strdup("unknown architecture"); - - g_strfreev(parts); - } else { - productArch = g_strdup("unknown architecture"); - } - - return; -} - -char * getProductName(void) { - if (!productName) { - initProductInfo(); - } - return productName; -} - -char * getProductArch(void) { - if (!productArch) { - initProductInfo(); - } - return productArch; -} - -void initializeConsole() { - /* enable UTF-8 console */ - setenv("LANG", LANG_DEFAULT, 1); - printf("\033%%G"); - fflush(stdout); - - isysSetUnicodeKeymap(); -} - -/* fbcon is buggy and resets our color palette if we allocate a terminal - * after initializing it, so we initialize 9 of them before we need them. - * If it doesn't work, the user gets to suffer through having an ugly palette, - * but things are still usable. */ -static void initializeTtys(void) { - int fd, n; - char dev[] = "/dev/ttyX"; - - for (n = 9; n > 0; n--) { - sprintf(dev, "/dev/tty%d", n); - mknod(dev, 0600 | S_IFCHR, makedev(4, n)); - fd = open(dev, O_RDWR|O_NOCTTY); - if (fd >= 0) { - ioctl(fd, VT_ACTIVATE, n); - if (n == 1) - ioctl(fd, VT_WAITACTIVE, n); - close(fd); - } else - logMessage(ERROR, "failed to initialize %s", dev); - } -} - -static void copyWarnFn (char *msg) { - logMessage(WARNING, msg); -} - -static void copyErrorFn (char *msg) { - newtWinMessage(_("Error"), _("OK"), _(msg)); -} - -void loadUpdates(struct loaderData_s *loaderData) { - char *device = NULL, *part = NULL, *buf; - char **devNames = NULL; - enum { UPD_DEVICE, UPD_PART, UPD_PROMPT, UPD_LOAD, UPD_DONE } stage = UPD_DEVICE; - int rc, num = 0; - int dir = 1; - - while (stage != UPD_DONE) { - switch (stage) { - case UPD_DEVICE: { - rc = getRemovableDevices(&devNames); - if (rc == 0) - return; - - /* we don't need to ask which to use if they only have one */ - if (rc == 1) { - device = strdup(devNames[0]); - free(devNames); - devNames = NULL; - if (dir == -1) - return; - - stage = UPD_PART; - break; - } - dir = 1; - - startNewt(); - rc = newtWinMenu(_("Update Disk Source"), - _("You have multiple devices which could serve " - "as sources for an update disk. Which would " - "you like to use?"), 40, 10, 10, - rc < 6 ? rc : 6, devNames, - &num, _("OK"), _("Cancel"), NULL); - - if (rc == 2) { - free(devNames); - devNames = NULL; - return; - } - - device = strdup(devNames[num]); - free(devNames); - devNames = NULL; - stage = UPD_PART; - } - - case UPD_PART: { - char ** part_list = getPartitionsList(device); - int nump = 0, num = 0; - - if (part != NULL) { - free(part); - part = NULL; - } - - if ((nump = g_strv_length(part_list)) == 0) { - if (dir == -1) { - stage = UPD_DEVICE; - } else { - checked_asprintf(&part, "/dev/%s", device); - stage = UPD_PROMPT; - } - - break; - } - dir = 1; - - startNewt(); - rc = newtWinMenu(_("Update Disk Source"), - _("There are multiple partitions on this device " - "which could contain the update disk image. " - "Which would you like to use?"), 40, 10, 10, - nump < 6 ? nump : 6, part_list, &num, _("OK"), - _("Back"), NULL); - - if (rc == 2) { - g_strfreev(part_list); - stage = UPD_DEVICE; - dir = -1; - break; - } - - part = strdup(part_list[num]); - stage = UPD_LOAD; - } - - case UPD_PROMPT: - checked_asprintf(&buf, _("Insert your updates disk into %s and " - "press \"OK\" to continue."), part); - - rc = newtWinChoice(_("Updates Disk"), _("OK"), _("Back"), buf); - free(buf); - buf = NULL; - - if (rc == 2) { - stage = UPD_PART; - dir = -1; - break; - } - - stage = UPD_LOAD; - break; - - case UPD_LOAD: - logMessage(INFO, "UPDATES device is %s", part); - - if (doPwMount(part, "/mnt/install/update-disk", "auto", "ro", NULL)) { - newtWinMessage(_("Error"), _("OK"), - _("Failed to mount updates disk")); - stage = UPD_PROMPT; - break; - } else { - /* Copy everything to /tmp/updates so we can unmount the disk */ - winStatus(40, 3, _("Updates"), _("Reading anaconda updates")); - if (!copyDirectory("/mnt/install/update-disk", "/tmp/updates", copyWarnFn, - copyErrorFn)) { - dir = 1; - stage = UPD_DONE; - } - - newtPopWindow(); - umount("/mnt/install/update-disk"); - } - - case UPD_DONE: - break; - } - } - - return; -} - -static char *newUpdatesLocation(const char *origLocation) { - const char *location; - char *retval = NULL; - newtComponent f, okay, cancel, answer, locationEntry; - newtGrid grid, buttons; - - startNewt(); - - locationEntry = newtEntry(-1, -1, NULL, 60, &location, NEWT_FLAG_SCROLL); - newtEntrySet(locationEntry, origLocation, 1); - - /* button bar at the bottom of the window */ - buttons = newtButtonBar(_("OK"), &okay, _("Cancel"), &cancel, NULL); - - grid = newtCreateGrid(1, 3); - - newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, - newtTextboxReflowed(-1, -1, _("Unable to download the updates image. Please modify the updates location below or press Cancel to proceed without updates.."), 60, 0, 0, 0), - 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, locationEntry, - 0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons, - 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX); - - f = newtForm(NULL, NULL, 0); - newtGridAddComponentsToForm(grid, f, 1); - newtGridWrappedWindow(grid, _("Error downloading updates image")); - newtGridFree(grid, 1); - - /* run the form */ - answer = newtRunForm(f); - - if (answer != cancel) - retval = strdup(location); - - newtFormDestroy(f); - newtPopWindow(); - - return retval; -} - -static int loadUpdatesFromRemote(char * url, struct loaderData_s * loaderData) { - int rc = getFileFromUrl(url, "/tmp/updates.img", loaderData); - - if (rc != 0) { - char *newLocation = newUpdatesLocation(url); - - if (!newLocation) - return rc; - else - return loadUpdatesFromRemote(newLocation, loaderData); - } - - copyUpdatesImg("/tmp/updates.img"); - unlink("/tmp/updates.img"); - return 0; -} - -static void writeVNCPasswordFile(char *pfile, char *password) { - FILE *f; - - f = fopen(pfile, "w+"); - fprintf(f, "%s\n", password); - fclose(f); -} - -/* read information from /etc/sysconfig/network-scripts/ifcfg-$INTERFACE - * (written by linuxrc), the linuxrc mess should be firing up NM too - */ -static void readNetInfo(struct loaderData_s ** ld) { - struct loaderData_s * loaderData = *ld; - char *cfgfile = NULL, *devfile = "/tmp/s390net"; - gchar *contents = NULL, *device = NULL; - gchar **lines = NULL, **line = NULL; - GError *e = NULL; - - /* when this function is called, /tmp/s390net - * contains the device name whose ifcfg file we want to read - */ - if (!g_file_test(devfile, G_FILE_TEST_EXISTS)) { - logMessage(DEBUGLVL, "readNetInfo %s not found, early return", devfile); - return; - } - if (!g_file_get_contents(devfile, &contents, NULL, &e)) { - logMessage(ERROR, "error reading %s: %s", devfile, e->message); - g_error_free(e); - abort(); - } - line = lines = g_strsplit(contents, "\n", 0); - g_free(contents); - while (*line != NULL) { - gchar *tmp = g_strdup(*line); - tmp = g_strstrip(tmp); - logMessage(DEBUGLVL, "readNetInfo stripped line: %s", tmp); - if (strlen(tmp) > 0) { - device = strdup(tmp); - g_free(tmp); - logMessage(DEBUGLVL, "readNetInfo found device: %s", device); - break; - } - g_free(tmp); - line++; - } - g_strfreev(lines); - if (strlen(device) == 0) { - logMessage(DEBUGLVL, "readNetInfo no device found"); - return; - } - - checked_asprintf(&cfgfile, "/etc/sysconfig/network-scripts/ifcfg-%s", - device); - logMessage(INFO, "readNetInfo cfgfile: %s", cfgfile); - - /* make sure everything is NULL before we begin copying info */ - loaderData->ipv4 = NULL; - loaderData->netmask = NULL; - loaderData->gateway = NULL; - loaderData->dns = NULL; - loaderData->peerid = NULL; - loaderData->subchannels = NULL; - loaderData->portname = NULL; - loaderData->nettype = NULL; - loaderData->ctcprot = NULL; - loaderData->options = NULL; - loaderData->macaddr = NULL; -#ifdef ENABLE_IPV6 - loaderData->ipv6 = NULL; - loaderData->ipv6prefix = NULL; - loaderData->gateway6 = NULL; -#endif - - /* - * The ifcfg file is written out by /sbin/init on s390x (which is - * really the linuxrc.s390 script). It's a shell-sourcable file with - * various system settings needing for the system instance. - * - * The goal of this function is to read in only the network settings - * and populate the loaderData structure. - */ - if (!g_file_get_contents(cfgfile, &contents, NULL, &e)) { - logMessage(ERROR, "error reading %s: %s", cfgfile, e->message); - g_error_free(e); - return; - } - - line = lines = g_strsplit(contents, "\n", 0); - g_free(contents); - - while (*line != NULL) { - gchar *tmp = g_strdup(*line); - gchar **pair = NULL; - - if (!strstr(tmp, "=")) { - g_free(tmp); - line++; - continue; - } - - tmp = g_strstrip(tmp); - pair = g_strsplit(tmp, "=", 2); - - if (g_strv_length(pair) == 2) { - gchar *val = g_shell_unquote(pair[1], &e); - - if (e != NULL) { - logMessage(WARNING, - "error reading %s from %s (line=%s): %s", - pair[0], cfgfile, tmp, e->message); - g_error_free(e); - } else { - if (!g_strcmp0(pair[0], "IPADDR")) { - loaderData->ipv4 = strdup(val); - loaderData->ipinfo_set = 1; - flags |= LOADER_FLAGS_IP_PARAM; - } else if (!g_strcmp0(pair[0], "NETMASK")) { - loaderData->netmask = strdup(val); - } else if (!g_strcmp0(pair[0], "GATEWAY")) { - loaderData->gateway = strdup(val); -#ifdef ENABLE_IPV6 - } else if (!g_strcmp0(pair[0], "IPV6ADDR")) { - if (split_ipv6addr_prefix_length(val, - &(loaderData->ipv6), - &(loaderData->ipv6prefix))) { - loaderData->ipv6info_set = 1; - flags |= LOADER_FLAGS_IPV6_PARAM; - } else { - logMessage(WARNING, "readNetInfo could not parse IPV6ADDR: %s", val); - } - } else if (!g_strcmp0(pair[0], "IPV6_DEFAULTGW")) { - loaderData->gateway6 = strdup(val); -#endif - } else if (!g_strcmp0(pair[0], "DNS")) { - loaderData->dns = strdup(val); - } else if (!g_strcmp0(pair[0], "DOMAIN")) { - loaderData->domain = strdup(val); - } else if (!g_strcmp0(pair[0], "MTU")) { - errno = 0; - loaderData->mtu = strtol(val, NULL, 10); - - if ((errno == ERANGE && (loaderData->mtu == LONG_MIN || - loaderData->mtu == LONG_MAX)) || - (errno != 0 && loaderData->mtu == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - } else if (!g_strcmp0(pair[0], "PEERID")) { - loaderData->peerid = strdup(val); - } else if (!g_strcmp0(pair[0], "SUBCHANNELS")) { - loaderData->subchannels = strdup(val); - } else if (!g_strcmp0(pair[0], "PORTNAME")) { - loaderData->portname = strdup(val); - } else if (!g_strcmp0(pair[0], "NETTYPE")) { - loaderData->nettype = strdup(val); - } else if (!g_strcmp0(pair[0], "CTCPROT")) { - loaderData->ctcprot = strdup(val); - } else if (!g_strcmp0(pair[0], "OPTIONS")) { - loaderData->options = strdup(val); - } else if (!g_strcmp0(pair[0], "MACADDR")) { - loaderData->macaddr = strdup(val); - } else if (!g_strcmp0(pair[0], "HOSTNAME")) { - loaderData->hostname = strdup(val); - } - } - - g_free(val); - } - - g_strfreev(pair); - g_free(tmp); - line++; - } - - if (loaderData->ipv4 && loaderData->netmask) { - flags |= LOADER_FLAGS_HAVE_CMSCONF; - } - - loaderData->netDev = device; - loaderData->netDev_set = 1; - - - free(cfgfile); - g_strfreev(lines); - return; -} - -/* parse anaconda or pxelinux-style ip= arguments - * pxelinux format: ip=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask> - * anaconda format: ip=<client-ip> netmask=<netmask> gateway=<gw-ip> -*/ -static void parseCmdLineIp(struct loaderData_s * loaderData, char *argv) -{ - /* Detect pxelinux */ - if (strstr(argv, ":") != NULL) { - char *start = argv; - char *end; - - end = strstr(start, ":"); - loaderData->ipv4 = strndup(start, end-start); - loaderData->ipinfo_set = 1; - - /* Boot server */ - if (end + 1 == '\0') - return; - start = end + 1; - end = strstr(start, ":"); - if (end == NULL) - return; - - /* Gateway */ - if (end + 1 == '\0') - return; - start = end + 1; - end = strstr(start, ":"); - if (end == NULL) { - loaderData->gateway = strdup (start); - return; - } else { - loaderData->gateway = strndup(start, end-start); - } - - /* Netmask */ - if (end + 1 == '\0') - return; - start = end + 1; - loaderData->netmask = strdup(start); - } else { - loaderData->ipv4 = strdup(argv); - loaderData->ipinfo_set = 1; - } - - if (loaderData->ipinfo_set) - flags |= LOADER_FLAGS_IP_PARAM; -} - -#ifdef ENABLE_IPV6 -/* - * parse anaconda ipv6= arguments - split prefix length if found - */ -static void parseCmdLineIpv6(struct loaderData_s * loaderData, char *argv) -{ - if (split_ipv6addr_prefix_length(argv+5, - &(loaderData->ipv6), - &(loaderData->ipv6prefix))) { - loaderData->ipv6info_set = 1; - flags |= LOADER_FLAGS_IPV6_PARAM; - } else { - logMessage(WARNING, "parseCmdLineIpv6 could not parse %s", argv); - } -} -#endif - -static long argToLong(char *arg) { - long retval; - - errno = 0; - - retval = strtol(arg, NULL, 10); - if ((errno == ERANGE && (retval == LONG_MIN || retval == LONG_MAX)) || - (errno != 0 && retval == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - return retval; -} - -/* parses /proc/cmdline for any arguments which are important to us. */ -static void parseCmdLineFlags(struct loaderData_s * loaderData) { - int numExtraArgs = 0; - GHashTableIter iter; - gpointer key = NULL, value = NULL; - - /* we want to default to graphical and allow override with 'text' */ - flags |= LOADER_FLAGS_GRAPHICAL; - - if (cmdline == NULL) { - logMessage(INFO, "kernel command line was empty"); - return; - } - - logMessage(INFO, "kernel command line:"); - g_hash_table_iter_init(&iter, cmdline); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - gchar *k = (gchar *) key; - gchar *v = (gchar *) value; - - if (v == NULL) { - logMessage(INFO, " %s", k); - } else { - logMessage(INFO, " %s=%s", k, v); - } - - /* handle installer boot arguments */ - if (!strcasecmp(k, "askmethod")) { - flags |= LOADER_FLAGS_ASKMETHOD; - } else if (!strcasecmp(k, "asknetwork")) { - flags |= LOADER_FLAGS_ASKNETWORK; - } else if (!strcasecmp(k, "noshell")) { - flags |= LOADER_FLAGS_NOSHELL; - } else if (!strcasecmp(k, "nokill")) { - flags |= LOADER_FLAGS_NOKILL; - } else if (!strcasecmp(k, "mediacheck")) { - flags |= LOADER_FLAGS_MEDIACHECK; - } else if (!strcasecmp(k, "allowwireless")) { - flags |= LOADER_FLAGS_ALLOW_WIRELESS; - } else if (!strcasecmp(k, "noprobe")) { - flags |= LOADER_FLAGS_NOPROBE; - } else if (!strcasecmp(k, "text")) { - logMessage(INFO, "text mode forced from cmdline"); - flags |= LOADER_FLAGS_TEXT; - flags &= ~LOADER_FLAGS_GRAPHICAL; - } else if (!strcasecmp(k, "graphical")) { - logMessage(INFO, "graphical mode forced from cmdline"); - flags |= LOADER_FLAGS_GRAPHICAL; - } else if (!strcasecmp(k, "cmdline")) { - logMessage(INFO, "cmdline mode forced from cmdline"); - flags |= LOADER_FLAGS_CMDLINE; - } else if (!strcasecmp(k, "updates")) { - if (v != NULL) { - loaderData->updatessrc = g_strdup(v); - } else { - flags |= LOADER_FLAGS_UPDATES; - } - } else if (!strcasecmp(k, "dd") || !strcasecmp(k, "driverdisk")) { - if (v != NULL) { - loaderData->ddsrc = g_strdup(v); - } else { - flags |= LOADER_FLAGS_MODDISK; - } - } else if (!strcasecmp(k, "rescue")) { - flags |= LOADER_FLAGS_RESCUE; - } else if (!strcasecmp(k, "nopass")) { - flags |= LOADER_FLAGS_NOPASS; - } else if (!strcasecmp(k, "serial")) { - flags |= LOADER_FLAGS_SERIAL; - } else if (!strcasecmp(k, "noipv4")) { - flags |= LOADER_FLAGS_NOIPV4; -#ifdef ENABLE_IPV6 - } else if (!strcasecmp(k, "noipv6")) { - flags |= LOADER_FLAGS_NOIPV6; -#endif - } else if (!strcasecmp(k, "kssendmac")) { - flags |= LOADER_FLAGS_KICKSTART_SEND_MAC; - } else if (!strcasecmp(k, "kssendsn")) { - flags |= LOADER_FLAGS_KICKSTART_SEND_SERIAL; - /* deprecated hardware bits */ - } else if (!strcasecmp(k, "nousb")) { - mlAddBlacklist("ehci-hcd"); - mlAddBlacklist("ohci-hcd"); - mlAddBlacklist("uhci-hcd"); - } else if (!strcasecmp(k, "nofirewire")) { - mlAddBlacklist("firewire-ohci"); - } else if (!strcasecmp(k, "ks")) { - GString *tmp = g_string_new("ks"); - - if (v != NULL) { - g_string_append_printf(tmp, "=%s", v); - } - - loaderData->ksFile = g_strdup(tmp->str); - g_string_free(tmp, TRUE); - } else if (!strcasecmp(k, "selinux")) { - if (v != NULL && !strcasecmp(v, "0")) { - flags &= ~LOADER_FLAGS_SELINUX; - } else { - flags |= LOADER_FLAGS_SELINUX; - } - } else if (!strcasecmp(k, "noeject")) { - flags |= LOADER_FLAGS_NOEJECT; - } else if (!strcasecmp(k, "sshd")) { - logMessage(INFO, "early networking required for sshd"); - flags |= LOADER_FLAGS_EARLY_NETWORKING; - } else if (!strcasecmp(k, "noverifyssl")) { - flags |= LOADER_FLAGS_NOVERIFYSSL; - } else if (v != NULL) { - /* boot arguments that are of the form name=value */ - /* all arguments in this block require the value */ - - if (!strcasecmp(k, "dlabel")) { - if (!strcasecmp(v, "on")) { - flags |= LOADER_FLAGS_AUTOMODDISK; - } else if (!strcasecmp(v, "off")) { - flags &= ~LOADER_FLAGS_AUTOMODDISK; - } - } else if (!strcasecmp(k, "loglevel")) { - if (!strcasecmp(v, "debug")) { - loaderData->logLevel = g_strdup(v); - setLogLevel(DEBUGLVL); - } else if (!strcasecmp(v, "info")) { - loaderData->logLevel = g_strdup(v); - setLogLevel(INFO); - } else if (!strcasecmp(v, "warning")) { - loaderData->logLevel = g_strdup(v); - setLogLevel(WARNING); - } else if (!strcasecmp(v, "error")) { - loaderData->logLevel = g_strdup(v); - setLogLevel(ERROR); - } else if (!strcasecmp(v, "critical")) { - loaderData->logLevel = g_strdup(v); - setLogLevel(CRITICAL); - } - } else if (!strcasecmp(k, "ksdevice")) { - loaderData->netDev = g_strdup(v); - loaderData->netDev_set = 1; - } else if (!strcmp(k, "BOOTIF")) { - /* trim leading '01-' if it exists */ - if (!strncmp(v, "01-", 3)) { - loaderData->bootIf = g_strdup(v + 3); - } else { - loaderData->bootIf = g_strdup(v); - } - - loaderData->bootIf_set = 1; - - /* scan the BOOTIF value and replace '-' with ':' */ - char *front = loaderData->bootIf; - if (front) { - while (*front != '\0') { - if (*front == '-') { - *front = ':'; - } - - front++; - } - } - } else if (!strcasecmp(k, "dhcpclass")) { - loaderData->netCls = g_strdup(v); - loaderData->netCls_set = 1; - } else if (!strcasecmp(k, "display")) { - setenv("DISPLAY", v, 1); - } else if (!strcasecmp(k, "lang")) { - loaderData->lang = normalizeLang(v); - loaderData->lang_set = 1; - } else if (!strcasecmp(k, "keymap")) { - loaderData->kbd = g_strdup(v); - loaderData->kbd_set = 1; - } else if (!strcasecmp(k, "method")) { - logMessage(WARNING, "method= is deprecated. Please use repo= instead."); - loaderData->instRepo = g_strdup(v); - } else if (!strcasecmp(k, "stage2")) { - logMessage(WARNING, "stage2= is deprecated. Please use repo= instead."); - flags |= LOADER_FLAGS_ASKMETHOD; - } else if (!strcasecmp(k, "repo")) { - loaderData->instRepo = g_strdup(v); - - /* We still have to set the method in case repo= was used so we - * know how to get updates.img and product.img, and it only - * gets set elsewhere on interactive installs. - */ - if (!strncmp(v, "nfs:", 4)) - loaderData->method = METHOD_NFS; - else if (!strncmp(v, "hd:", 3)) - loaderData->method = METHOD_HD; - else if (!strncmp(v, "cd:", 3)) - loaderData->method = METHOD_CDROM; - } else if (!strcasecmp(k, "hostname")) { - loaderData->hostname = g_strdup(v); - } else if (!strcasecmp(k, "ip")) { - parseCmdLineIp(loaderData, v); -#ifdef ENABLE_IPV6 - } else if (!strcasecmp(k, "ipv6")) { - parseCmdLineIpv6(loaderData, v); -#endif - } else if (!strcasecmp(k, "netmask")) { - loaderData->netmask = g_strdup(v); - } else if (!strcasecmp(k, "gateway")) { - char *gateway = g_strdup(v); - if (isValidIPv4Address(gateway)) { - loaderData->gateway = gateway; -#ifdef ENABLE_IPV6 - } else if (isValidIPv6Address(gateway)) { - loaderData->gateway6 = gateway; -#endif - } else { - logMessage(WARNING, - "invalid address in boot option gateway"); - free(gateway); - } - } else if (!strcasecmp(k, "dns")) { - loaderData->dns = g_strdup(v); - } else if (!strcasecmp(k, "ethtool")) { - loaderData->ethtool = g_strdup(v); - } else if (!strcasecmp(k, "essid")) { - loaderData->essid = g_strdup(v); - } else if (!strcasecmp(k, "mtu")) { - loaderData->mtu = argToLong(v); - } else if (!strcasecmp(k, "wepkey")) { - loaderData->wepkey = g_strdup(v); - } else if (!strcasecmp(k, "wpakey")) { - loaderData->wpakey = g_strdup(v); - } else if (!strcasecmp(k, "linksleep")) { - num_link_checks = argToLong(v); - } else if (!strcasecmp(k, "nicdelay")) { - post_link_sleep = argToLong(v); - } else if (!strcasecmp(k, "dhcptimeout")) { - loaderData->dhcpTimeout = argToLong(v); - } else if (!strcasecmp(k, "gdb")) { - loaderData->gdbServer = g_strdup(v); - } else if (!strcasecmp(k, "proxy")) { - splitProxyParam(v, &loaderData->proxyUser, - &loaderData->proxyPassword, &loaderData->proxy); - } - } - - if (numExtraArgs < (MAX_EXTRA_ARGS - 1)) { - /* go through and append args we just want to pass on to */ - /* the anaconda script, but don't want to represent as a */ - /* LOADER_FLAGS_XXX since loader doesn't care about these */ - /* particular options. */ - /* do vncpassword case first */ - if (!strcasecmp(k, "vncpassword") && v != NULL) { - writeVNCPasswordFile("/tmp/vncpassword.dat", v); - } else if (!strcasecmp(k, "resolution") || - !strcasecmp(k, "nomount") || - !strcasecmp(k, "vnc") || - !strcasecmp(k, "vncconnect") || - !strcasecmp(k, "headless") || - !strcasecmp(k, "usefbx") || - !strcasecmp(k, "mpath") || - !strcasecmp(k, "nompath") || - !strcasecmp(k, "dmraid") || - !strcasecmp(k, "nodmraid") || - !strcasecmp(k, "xdriver") || - !strcasecmp(k, "syslog")) { - - /* vnc implies graphical */ - if (!strcasecmp(k, "vnc")) { - logMessage(INFO, "vnc forced graphical mode from cmdline"); - flags |= LOADER_FLAGS_GRAPHICAL; - } - - /* the following things require networking to be configured - * by loader, so an active connection is ready once we get - * to anaconda - */ - if (!strcasecmp(k, "syslog") || !strcasecmp(k, "vnc")) { - logMessage(INFO, "early networking required for %s", k); - flags |= LOADER_FLAGS_EARLY_NETWORKING; - } - - if (isKickstartFileRemote(loaderData->ksFile)) { - logMessage(INFO, "early networking required for remote kickstart configuration"); - flags |= LOADER_FLAGS_EARLY_NETWORKING; - } - - if (v != NULL) { - checked_asprintf(&extraArgs[numExtraArgs], "--%s=%s", k, v) - } else { - checked_asprintf(&extraArgs[numExtraArgs],"--%s", k); - } - - numExtraArgs += 1; - - if (numExtraArgs > (MAX_EXTRA_ARGS - 2)) { - logMessage(WARNING, "Too many command line arguments (max " - "allowed is %d), rest will be dropped.", - MAX_EXTRA_ARGS); - } - } - } - } - - readNetInfo(&loaderData); - - /* NULL terminates the array of extra args */ - extraArgs[numExtraArgs] = NULL; - - return; -} - -/* make sure they have enough ram */ -static void checkForRam(int install_method) { - char *reason = _("%s requires %d MB of memory, to install, but you only have %d MB."); - int needed = MIN_RAM; - int installed = totalMemory(); - - if (totalMemory() < needed) { - char *buf; - checked_asprintf(&buf, reason, getProductName(), needed/1024, installed/1024); - - startNewt(); - newtWinMessage(_("Error"), _("OK"), buf); - free(buf); - stopNewt(); - doExit(0); - } -} - -static void checkTaintFlag(void) { - unsigned long l; - gchar *contents = NULL; - GError *fileErr = NULL; - - if (!g_file_get_contents("/proc/sys/kernel/tainted", &contents, NULL, &fileErr)) { - logMessage(ERROR, "error reading /proc/sys/kernel/tainted: %s", fileErr->message); - g_error_free(fileErr); - return; - } - - errno = 0; - l = strtol(contents, NULL, 10); - if (errno == EINVAL || errno == ERANGE) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - g_free(contents); - return; - } - - if (l & (1 << 28)) { - startNewt(); - newtWinMessage(_("Unsupported Hardware Detected"), _("OK"), - _("This hardware (or a combination thereof) is not " - "supported by Red Hat. For more information on " - "supported hardware, please refer to " - "http://www.redhat.com/hardware.")); - stopNewt(); - } - - g_free(contents); -} - -static int haveDeviceOfType(int type) { - struct device ** devices; - - devices = getDevices(type); - if (devices) { - return 1; - } - return 0; -} - -/* - * Use anything you can find to determine if we are running on a QEMU virtual - * machine. - */ -static int onQEMU(void) -{ - const gchar *lookfor = "QEMU Virtual CPU"; - gchar *contents = NULL; - GError *fileErr = NULL; - int ret = 0; - - if (!g_file_get_contents("/proc/cpuinfo", &contents, NULL, &fileErr)) { - fprintf(stderr, "Unable to read /proc/cpuinfo.\n"); - sleep(5); - return 0; - } - if (strstr(contents, lookfor)) { - ret = 1; - } - g_free(contents); - return ret; -} - -/* - * Detects the non-static part of rsyslog configuration. - * - * Remote TCP logging is enabled if syslog= is found on the kernel command - * line. Remote virtio-serial logging is enabled if the declared virtio port - * exists. - */ -static int getSyslog(gchar **addr, gchar **virtiolog) { - gpointer value = NULL; - int ret = 0; - - if (g_hash_table_lookup_extended(cmdline, "syslog", NULL, &value)) { - *addr = (gchar *) value; - /* address can be either a hostname or IPv4 or IPv6, with or without port; - thus we only allow the following characters in the address: letters and - digits, dots, colons, slashes, dashes and square brackets */ - if (g_regex_match_simple("^[\\w.:/\\-\\[\\]]*$", *addr, 0, 0)) { - ++ret; - } else { - /* malformed, disable use */ - *addr = NULL; - printf("The syslog= command line parameter is malformed and will be\n"); - printf("ignored by the installer.\n"); - sleep(5); - } - } - - if (onQEMU()) { - /* look for virtio-serial logging on a QEMU machine. */ - printf("Looking for the virtio ports... "); - if (system("/sbin/udevadm trigger --action=add --sysname-match='vport*'") || - system("/sbin/udevadm settle")) { - fprintf(stderr, "Error calling udevadm trigger to get virtio ports.\n"); - sleep(5); - } else { - printf("done.\n"); - } - if (!access(VIRTIO_PORT, W_OK)) { - /* that means we really have virtio-serial logging */ - *virtiolog = VIRTIO_PORT; - ++ret; - } - } - - return ret; -} - -/* sets up and restarts syslog */ -static void restartSyslog(void) { - int conf_fd; - gchar *addr = NULL, *virtiolog = NULL; - const char *forward_tcp = "*.* @@"; - const char *forward_format_tcp = "\n"; - const char *forward_virtio = "*.* "; - const char *forward_format_virtio = ";virtio_ForwardFormat\n"; - - /* update the config file with command line arguments first */ - if (!getSyslog(&addr, &virtiolog)) - return; - - conf_fd = open("/etc/rsyslog.conf", O_WRONLY|O_APPEND); - if (conf_fd < 0) { - printf("error opening /etc/rsyslog.conf: %d\n", errno); - printf("syslog forwarding will not be enabled\n"); - sleep(5); - } else { - if (addr != NULL) { - write(conf_fd, forward_tcp, strlen(forward_tcp)); - write(conf_fd, addr, strlen(addr)); - write(conf_fd, forward_format_tcp, strlen(forward_format_tcp)); - } - if (virtiolog != NULL) { - write(conf_fd, forward_virtio, strlen(forward_virtio)); - write(conf_fd, virtiolog, strlen(virtiolog)); - write(conf_fd, forward_format_virtio, strlen(forward_format_virtio)); - } - close(conf_fd); - } - - /* now we really start the daemon. */ - int status = system("/bin/systemctl --quiet restart rsyslog.service"); - if (status < 0 || - !WIFEXITED(status) || - WEXITSTATUS(status) != 0) { - printf("Unable to start syslog daemon.\n"); - doExit(EXIT_FAILURE); - } -} - -static void doLoaderMain(struct loaderData_s *loaderData, - moduleInfoSet modInfo) { - enum { STEP_LANG, STEP_KBD, STEP_METHOD, STEP_DRIVER, - STEP_DRIVERDISK, STEP_NETWORK, STEP_IFACE, - STEP_IP, STEP_EXTRAS, STEP_DONE } step; - char *step_names[] = { "STEP_LANG", "STEP_KBD", "STEP_METHOD", "STEP_DRIVER", - "STEP_DRIVERDISK", "STEP_NETWORK", "STEP_IFACE", - "STEP_IP", "STEP_EXTRAS", "STEP_DONE" }; - - char *ret = NULL, *devName = NULL, *kbdtype = NULL; - static iface_t iface; - int i, rc = LOADER_NOOP, dir = 1; - int needsNetwork = 0, class = -1; - int skipLangKbd = 0; - - char *installNames[10]; - int numValidMethods = 0; - int validMethods[10]; - - for (i = 0; i < numMethods; i++, numValidMethods++) { - installNames[numValidMethods] = installMethods[i].name; - validMethods[numValidMethods] = i; - } - installNames[numValidMethods] = NULL; - - i = 0; - step = STEP_LANG; - - /* Before anything, check if we're installing from CD/DVD. If so, we can - * skip right over most of these steps. Note that askmethod or repo= will - * override this check. - */ - if (!FL_ASKMETHOD(flags) && !loaderData->instRepo && findInstallCD(loaderData) == LOADER_OK) { - logMessage(DEBUGLVL, "Found installation media, so skipping lang and kbd"); - queryCDMediaCheck(loaderData->instRepo); - skipLangKbd = 1; - flags |= LOADER_FLAGS_NOPASS; - } - - while (step != STEP_DONE) { - logMessage(DEBUGLVL, "in doLoaderMain, step = %s", step_names[step]); - - switch(step) { - case STEP_LANG: { - if (loaderData->lang && (loaderData->lang_set == 1)) - setLanguage(loaderData->lang, 1); - else if (FL_RESCUE(flags) || !skipLangKbd) - chooseLanguage(&loaderData->lang); - - step = STEP_KBD; - dir = 1; - break; - } - - case STEP_KBD: { - if (loaderData->kbd && (loaderData->kbd_set == 1)) { - /* JKFIXME: this is broken -- we should tell of the - * failure; best by pulling code out in kbd.c to use */ - if (isysLoadKeymap(loaderData->kbd)) { - logMessage(WARNING, "requested keymap %s is not valid, asking", - loaderData->kbd); - loaderData->kbd = NULL; - loaderData->kbd_set = 0; - break; - } - rc = LOADER_NOOP; - } else if (FL_RESCUE(flags) || !skipLangKbd) { - /* JKFIXME: should handle kbdtype, too probably... but it - * just matters for sparc */ - if (!FL_CMDLINE(flags)) - rc = chooseKeyboard(loaderData, &kbdtype); - else - rc = LOADER_NOOP; - } else { - step = STEP_METHOD; - dir = 1; - } - - if (rc == LOADER_NOOP) { - if (dir == -1) - step = STEP_LANG; - else - step = STEP_METHOD; - - break; - } - - if (rc == LOADER_BACK) { - step = STEP_LANG; - dir = -1; - } else { - step = STEP_METHOD; - dir = 1; - } - - break; - } - - case STEP_METHOD: { - if (FL_ASKMETHOD(flags)) { - if (FL_CMDLINE(flags)) { - fprintf(stderr, "No method given for cmdline mode, aborting\n"); - doExit(EXIT_FAILURE); - } - } else { - step = (dir == -1) ? STEP_KBD : STEP_DRIVER; - break; - } - - /* we need to set these each time through so that we get - * updated for language changes (#83672) */ - for (i = 0; i < numMethods; i++) { - installNames[i] = _(installMethods[i].name); - } - installNames[i] = NULL; - - rc = newtWinMenu(_("Installation Method"), - _("What type of media contains the installation tree?"), - 30, 10, 20, 6, installNames, &loaderData->method, - _("OK"), _("Back"), NULL); - if (rc == 2) { - flags |= LOADER_FLAGS_ASKMETHOD; - } - - if (rc && (rc != 1)) { - step = STEP_KBD; - dir = -1; - } else { - /* Now prompt for the method-specific config info. */ - rc = installMethods[validMethods[loaderData->method]].prompt(loaderData); - - /* Just go back to the method selection screen. */ - if (rc == LOADER_BACK) - break; - - class = installMethods[validMethods[loaderData->method]].type; - step = STEP_DRIVER; - dir = 1; - } - - break; - } - - case STEP_DRIVER: { - if ((FL_EARLY_NETWORKING(flags) && haveDeviceOfType(DEVICE_NETWORK)) || - (class == -1 || haveDeviceOfType(class))) { - step = STEP_NETWORK; - dir = 1; - class = -1; - break; - } - - if (skipLangKbd) { - skipLangKbd = 0; - step = STEP_KBD; - break; - } - - rc = newtWinTernary(_("No driver found"), _("Select driver"), - _("Use a driver disk"), _("Back"), - _("Unable to find any devices of the type " - "needed for this installation type. " - "Would you like to manually select your " - "driver or use a driver disk?")); - if (rc == 2) { - step = STEP_DRIVERDISK; - dir = 1; - break; - } else if (rc == 3) { - step = STEP_METHOD; - flags |= LOADER_FLAGS_ASKMETHOD; - dir = -1; - break; - } - - chooseManualDriver(installMethods[validMethods[loaderData->method]].type, - loaderData); - /* it doesn't really matter what we return here; we just want - * to reprobe and make sure we have the driver */ - step = STEP_DRIVER; - break; - } - - case STEP_DRIVERDISK: { - if (skipLangKbd) { - skipLangKbd = 0; - step = STEP_KBD; - break; - } - - rc = loadDriverFromMedia(class, loaderData, 0, 0, NULL); - if (rc == LOADER_BACK) { - step = STEP_DRIVER; - dir = -1; - break; - } - - /* need to come back to driver so that we can ensure that we found - * the right kind of driver after loading the driver disk */ - step = STEP_DRIVER; - break; - } - - case STEP_NETWORK: { - if ((!isURLRemote(loaderData->instRepo) && - !FL_ASKNETWORK(flags) && - !FL_EARLY_NETWORKING(flags) && - !ibft_present()) || - (is_nm_connected())) { - needsNetwork = 0; - if (dir == 1) - step = STEP_EXTRAS; - else if (dir == -1) - step = STEP_METHOD; - break; - } - - needsNetwork = 1; - if (!haveDeviceOfType(DEVICE_NETWORK)) { - class = DEVICE_NETWORK; - step = STEP_DRIVER; - break; - } - logMessage(INFO, "need to set up networking"); - - iface_init_iface_t(&iface); - - /* fall through to interface selection */ - } - - case STEP_IFACE: { - /* skip configureTCPIP() screen for kickstart (#260621) */ - if (loaderData->ksFile) - flags |= LOADER_FLAGS_IS_KICKSTART; - - if (FL_HAVE_CMSCONF(flags)) { - loaderData->ipinfo_set = 1; -#ifdef ENABLE_IPV6 - loaderData->ipv6info_set = 1; -#endif - } - - rc = chooseNetworkInterface(loaderData); - if (rc == LOADER_BACK || rc == LOADER_ERROR || (dir == -1 && rc == LOADER_NOOP)) { - step = STEP_METHOD; - dir = -1; - /* Clear current device selection so we prompt on re-entry to STEP_IFACE */ - loaderData->netDev_set = 0; - break; - } - - devName = loaderData->netDev; - strcpy(iface.device, devName); - - /* continue to ip config */ - step = STEP_IP; - dir = 1; - break; - } - - case STEP_IP: { - if (!needsNetwork || dir == -1) { - step = STEP_METHOD; /* only hit going back */ - break; - } - - if ((ret = malloc(INET6_ADDRSTRLEN+1)) == NULL) { - logMessage(ERROR, "malloc failure for ret in STEP_IP"); - doExit(EXIT_FAILURE); - } - - - /* s390 provides all config info by way of linuxrc.s390 */ - if (FL_HAVE_CMSCONF(flags)) { - loaderData->ipinfo_set = 1; -#ifdef ENABLE_IPV6 - loaderData->ipv6info_set = 1; -#endif - } - - /* populate netDev based on any kickstart data */ - logMessage(DEBUGLVL, "in doLoaderMain, calling setupIfaceStruct()"); - setupIfaceStruct(&iface, loaderData); - logMessage(DEBUGLVL, "in doLoaderMain, calling readNetConfig()"); - rc = readNetConfig(devName, &iface, loaderData->netCls, loaderData->method); - - free(ret); - ret = NULL; - - /* Go to STEP_IFACE */ - if (rc == LOADER_BACK || (dir == -1 && rc == LOADER_NOOP)) { - needsNetwork = 1; - step = STEP_IFACE; - dir = -1; - - /* Clear out netDev_set so we prompt the user in - * STEP_IFACE */ - loaderData->netDev_set = 0; - /* Clear ipinfo_set so we prompt the user in when they - * return to STEP_IP */ - loaderData->ipinfo_set = 0; -#ifdef ENABLE_IPV6 - loaderData->ipv6info_set = 0; -#endif - logMessage(DEBUGLVL, "in STEP_IP, going to STEP_IFACE (LOADER_BACK)"); - - break; - } - /* Retry STEP_IP */ - if (rc == LOADER_ERROR) { - needsNetwork = 1; - - /* Don't retry the same failed settings. Clear ipinfo-set - * so the user can enter new data */ - loaderData->ipinfo_set = 0; -#ifdef ENABLE_IPV6 - loaderData->ipv6info_set = 0; -#endif - logMessage(DEBUGLVL, "in STEP_IP, retry (LOADER_ERROR)"); - - break; - } - - writeEnabledNetInfo(&iface); - /* Prevent asking about interface for updates.img */ - loaderData->netDev_set = 1; - step = STEP_EXTRAS; - dir = 1; - break; - } - - case STEP_EXTRAS: { - logMessage(DEBUGLVL, "in STEP_EXTRAS, method = %s", - installMethods[validMethods[loaderData->method]].desc); - - installMethods[validMethods[loaderData->method]].findExtras(loaderData); - step = STEP_DONE; - break; - } - - case STEP_DONE: - break; - } - } -} -static int manualDeviceCheck(struct loaderData_s *loaderData) { - char ** devices; - int i, j, rc, num = 0; - unsigned int width = 40; - char * buf; - - do { - /* FIXME */ - devices = malloc(1 * sizeof(*devices)); - j = 0; - devices[j] = NULL; - - if (width > 70) - width = 70; - - if (j > 0) { - buf = _("The following devices have been found on your system."); - } else { - buf = _("No device drivers have been loaded for your system. " - "Would you like to load any now?"); - } - - rc = newtWinMenu(_("Devices"), buf, width, 10, 20, - (j > 6) ? 6 : j, devices, &num, _("Done"), - _("Add Device"), NULL); - - /* no leaky */ - for (i = 0; i < j; i++) - free(devices[j]); - free(devices); - - if (rc != 2) - break; - - chooseManualDriver(DEVICE_ANY, loaderData); - } while (1); - return 0; -} - -static int hasGraphicalOverride() { - int i; - - if (getenv("DISPLAY")) - return 1; - - for (i = 0; extraArgs[i] != NULL; i++) { - if (!strncasecmp(extraArgs[i], "--vnc", 5)) - return 1; - } - return 0; -} - -void loaderSegvHandler(int signum) { - void *array[30]; - size_t i; - const char const * const errmsgs[] = { - "loader received SIG", - "! Backtrace:\n", - "Loader exited unexpectedly! Backtrace:\n", - }; - - /* XXX This should really be in a glibc header somewhere... */ - extern const char *const sys_sigabbrev[NSIG]; - - signal(signum, SIG_DFL); /* back to default */ - - newtFinished(); - if (signum == 0) { - i = write(STDERR_FILENO, errmsgs[2], strlen(errmsgs[2])); - } else { - i = write(STDERR_FILENO, errmsgs[0], strlen(errmsgs[0])); - i = write(STDERR_FILENO, sys_sigabbrev[signum], - strlen(sys_sigabbrev[signum])); - i = write(STDERR_FILENO, errmsgs[1], strlen(errmsgs[1])); - } - - i = backtrace (array, 30); - if (signum == SIGSEGV) - backtrace_symbols_fd(array+2, i-2, STDERR_FILENO); - else - backtrace_symbols_fd(array+1, i-1, STDERR_FILENO); - _exit(1); -} - -void loaderExitHandler(void) -{ - if (expected_exit) - return; - - loaderSegvHandler(0); -} - -static void setupBacktrace(void) -{ - void *array; - - signal(SIGSEGV, loaderSegvHandler); - signal(SIGABRT, loaderSegvHandler); - atexit(loaderExitHandler); - - /* Turns out, there's an initializer at the top of backtrace() that - * (on some arches) calls dlopen(). dlopen(), unsurprisingly, calls - * malloc(). So, call backtrace() early in signal handler setup so - * we can later safely call it from the signal handler itself. */ - backtrace(&array, 1); -} - -void loaderUsrXHandler(int signum) { - logMessage(INFO, "Remembering signal %d\n", signum); - init_sig = signum; -} - -void restart_anaconda() { - if (access("/tmp/restart_anaconda", R_OK)) { - printf("Starting Anaconda version %s.\n", VERSION); - return; - } - - puts("Restarting Anaconda."); - unlink("/tmp/restart_anaconda"); - - if (!access("/var/run/loader.run", R_OK)) - unlink("/var/run/loader.run"); - - int updates_fd = open("/tmp/updates", O_RDONLY); - if (recursiveRemove(updates_fd)) - fprintf(stderr, "Error removing /tmp/updates. Updates won't be re-downloaded."); -} - -static int anaconda_trace_init(int isDevelMode) { - /* if anaconda dies suddenly we are doomed, so at least make a coredump */ - struct rlimit corelimit = { RLIM_INFINITY, RLIM_INFINITY}; - if (setrlimit(RLIMIT_CORE, &corelimit)) { - perror("setrlimit failed - no coredumps will be available"); - } - -#ifdef USE_MTRACE - setenv("MALLOC_TRACE","/malloc",1); - mtrace(); -#endif - /* We have to do this before we init bogl(), which doLoaderMain will do - * when setting fonts for different languages. It's also best if this - * is well before we might take a SEGV, so they'll go to tty8 */ - initializeTtys(); - - /* set up signal handler unless we want it to crash in devel mode */ - if(!isDevelMode) - setupBacktrace(); - - return 0; -} - -static char *setupMallocPerturb(char *value) -{ - FILE *f; - unsigned char x; - size_t rc; - char *ret = NULL; - - f = fopen("/dev/urandom", "r"); - if (!f) - return NULL; - - rc = fread(&x, 1, 1, f); - fclose(f); - if (rc < 1) - return NULL; - - rc = asprintf(&ret, "MALLOC_PERTURB_=%hhu", x); - if (rc < 0) - return NULL; - return ret; -} - -/* these functions return a newly allocated string that never gets freed; - * their lifetime is essentially that of main(), and we'd have to track which - * are allocated and which aren't, which is pretty pointless... */ -typedef char *(*setupEnvCallback)(char *entry); - -static void setupEnv(void) -{ - struct { - char *name; - setupEnvCallback cb; - } setupEnvCallbacks[] = { - { "MALLOC_PERTURB_", setupMallocPerturb }, - { NULL, NULL } - }; - int x; - - /* neither array is very big, so this algorithm isn't so bad. If env[] - * gets bigger for some reason, we should probably just alphebatize both - * (manually) and then only initialize y one time. - */ - for (x = 0; setupEnvCallbacks[x].name != NULL; x++) { - char *value = getenv(setupEnvCallbacks[x].name); - - if (value != NULL) { - char *new = setupEnvCallbacks[x].cb(value); - if (new) - setenv(setupEnvCallbacks[x].name, new, 1); - } - } -} - -static void add_to_path_env(const char *env, const char *val) -{ - char *oldenv, *newenv; - - oldenv = getenv(env); - if (oldenv) { - checked_asprintf(&newenv, "%s:%s", val, oldenv); - - oldenv = strdupa(newenv); - free(newenv); - newenv = oldenv; - } else { - newenv = strdupa(val); - } - - setenv(env, newenv, 1); -} - -static void loadScsiDhModules(void) -{ - struct utsname utsname; - char *modules = NULL; - char *tmp = NULL; - struct dirent *ent = NULL; - - uname(&utsname); - checked_asprintf(&tmp, - "/lib/modules/%s/kernel/drivers/scsi/device_handler", utsname.release); - - DIR *dir = opendir(tmp); - free(tmp); - if (!dir) - return; - - int fd = dirfd(dir); - while ((ent = readdir(dir)) != NULL) { - struct stat sb; - - if (fstatat(fd, ent->d_name, &sb, 0) < 0) - continue; - - size_t len = strlen(ent->d_name) - 3; - if (strcmp(ent->d_name+len, ".ko")) - continue; - - if (S_ISREG(sb.st_mode)) { - char modname[len+1]; - strncpy(modname, ent->d_name, len); - modname[len] = '\0'; - - if (modules && modules[0]) { - checked_asprintf(&tmp, "%s:%s", modules, modname); - } else { - checked_asprintf(&tmp, "%s", modname); - } - - free(modules); - modules = tmp; - } - } - closedir(dir); - - mlLoadModuleSet(modules); - free(modules); -} - -int main(int argc, char ** argv) { - int rc; - int isDevelMode = 0; - - char * arg; - FILE *f; - - moduleInfoSet modInfo; - iface_t iface; - - char ** argptr, ** tmparg; - char * anacondaArgs[50]; - char * outputKSFile = NULL; - - struct loaderData_s loaderData; - struct termios orig_cmode; - int orig_flags; - - char *path, *fmt; - GSList *dd, *dditer; - GTree *moduleState; - - cmdline = readvars_parse_file("/proc/cmdline"); - - restartSyslog(); - /* disable console logging so we don't clog the ttys */ - klogctl(8, NULL, 1); - - /* If the anaconda process is now being restarted, we need to do some - * environment cleanup first. - */ - restart_anaconda(); - - /* check for development mode early */ - if (cmdline && g_hash_table_lookup_extended(cmdline, "devel", NULL, NULL)) { - printf("Enabling development mode - cores will be dumped\n"); - isDevelMode = 1; - } - - signal(SIGUSR1, loaderUsrXHandler); - signal(SIGUSR2, loaderUsrXHandler); - - /* Make sure sort order is right. */ - setenv ("LC_COLLATE", "C", 1); - - /* Very first thing, set up tracebacks and debug features. */ - rc = anaconda_trace_init(isDevelMode); - setupEnv(); - - /* uncomment to send mac address in ks=http:/ header by default*/ - flags |= LOADER_FLAGS_KICKSTART_SEND_MAC; - - /* JKFIXME: I do NOT like this... it also looks kind of bogus */ -#if defined(__s390__) || defined(__s390x__) - flags |= LOADER_FLAGS_NOSHELL; -#endif - - openLog(); - - /* XXX if RHEL, enable the AUTODD feature by default, - * but we should come with more general way how to control this */ - if (!strncmp(getProductName(), "Red Hat", 7)) { - flags |= LOADER_FLAGS_AUTOMODDISK; - } - - memset(&loaderData, 0, sizeof(loaderData)); - loaderData.method = METHOD_URL; - loaderData.fw_loader_pid = -1; - loaderData.fw_search_pathz_len = -1; - loaderData.dhcpTimeout = -1; - - extraArgs[0] = NULL; - parseCmdLineFlags(&loaderData); - - /* Set this now so it's valid for all udev trigger calls. */ - system("udevadm control --env=ANACONDA=1"); - - if (!access("/var/run/loader.run", R_OK)) { - printf(_("loader has already been run. Starting shell.\n")); - execl("/bin/sh", "-/bin/sh", NULL); - doExit(0); - } - - f = fopen("/var/run/loader.run", "w+"); - fprintf(f, "%d\n", getpid()); - fclose(f); - - logMessage(INFO, "anaconda version %s on %s starting", VERSION, getProductArch()); - - init_serial(&orig_cmode, &orig_flags, cmdline); - - if ((FL_SERIAL(flags) || FL_VIRTPCONSOLE(flags)) && - !hasGraphicalOverride()) { - logMessage(INFO, "text mode forced due to serial/virtpconsole"); - flags |= LOADER_FLAGS_TEXT; - } - if (hasGraphicalOverride()) - flags |= LOADER_FLAGS_EARLY_NETWORKING; - set_fw_search_path(&loaderData, "/firmware:/lib/firmware"); - start_fw_loader(&loaderData); - - arg = "/lib/modules/module-info"; - modInfo = newModuleInfoSet(); - if (readModuleInfo(arg, modInfo, NULL, 0)) { - fprintf(stderr, "failed to read %s\n", arg); - sleep(5); - stop_fw_loader(&loaderData); - doExit(1); - } - initializeConsole(); - - checkForRam(-1); - - /* iSeries vio console users will be ssh'ing in to the primary - partition, so use a terminal type that is appripriate */ - if (isVioConsole()) - setenv("TERM", "vt100", 1); - - mlLoadModuleSet("cramfs:squashfs:iscsi_tcp"); - - loadScsiDhModules(); - -#if !defined(__s390__) && !defined(__s390x__) - mlLoadModuleSet("floppy:edd:iscsi_ibft"); -#endif - -#ifdef ENABLE_IPV6 - if (!FL_NOIPV6(flags)) - mlLoadModule("ipv6", NULL); -#endif - - /* now let's do some initial hardware-type setup */ -#if defined(__powerpc__) - mlLoadModule("spufs", NULL); -#endif - - if (loaderData.lang && loaderData.lang_set == 1) { - setLanguage(loaderData.lang, 1); - } else { - setLanguage(LANG_DEFAULT, 1); - } - - /* FIXME: this is a bit of a hack */ - loaderData.modInfo = modInfo; - - /* If there is /.rundepmod file present, rerun depmod */ - if (!access("/.rundepmod", R_OK)){ - if (system("depmod -a")) { - /* this is not really fatal error, it might still work, log it */ - logMessage(ERROR, "Error running depmod -a for initrd overlay"); - } - } - - /* this allows us to do an early load of modules specified on the - * command line to allow automating the load order of modules so that - * eg, certain scsi controllers are definitely first. - * FIXME: this syntax is likely to change in a future release - * but is done as a quick hack for the present. - */ - if (!mlInitModuleConfig()) { - logMessage(ERROR, "unable to initialize kernel module loading"); - abort(); - } - - earlyModuleLoad(0); - - /* Save list of preloaded modules so we can restore the state */ - moduleState = mlSaveModuleState(); - - if (FL_AUTOMODDISK(flags)) { - /* Load all autodetected DDs */ - logMessage(INFO, "Trying to detect vendor driver discs"); - dd = findDriverDiskByLabel(); - dditer = dd; - - if (dd && !loaderData.ksFile) { - startNewt(); - } - - - while(dditer) { - /* If in interactive mode, ask for confirmation before loading the DD */ - if (!loaderData.ksFile) { - char * buf; - - checked_asprintf(&buf, - _("Driver disc was detected in %s. " - "Do you want to use it?."), dditer->data); - - rc = newtWinChoice(_("Driver disc detected"), _("Use it"), _("Skip it"), - buf); - free(buf); - if (rc == 2) { - logMessage(INFO, "Skipping driver disk %s.", (char*)(dditer->data)); - - /* clean the device record */ - free((char*)(dditer->data)); - dditer->data = NULL; - - /* next DD */ - dditer = g_slist_next(dditer); - continue; - } - } - - /* load the DD */ - if (loadDriverDiskFromPartition(&loaderData, (char*)(dditer->data))) { - logMessage(ERROR, "Automatic driver disk loader failed for %s.", (char*)(dditer->data)); - } - else { - logMessage(INFO, "Automatic driver disk loader succeeded for %s.", (char*)(dditer->data)); - - /* Unload all devices and load them again to use the updated modules */ - mlRestoreModuleState(moduleState); - busProbe(0); - } - - /* clean the device record */ - free((char*)(dditer->data)); - dditer->data = NULL; - - /* next DD */ - dditer = g_slist_next(dditer); - } - - if (dd && !loaderData.ksFile) { - stopNewt(); - } - - g_slist_free(dd); - } - - if (FL_MODDISK(flags)) { - startNewt(); - loadDriverDisks(DEVICE_ANY, &loaderData, moduleState); - } - - if (!access("/dd.img", R_OK)) { - logMessage(INFO, "found /dd.img, loading drivers"); - getDDFromSource(&loaderData, "path:/dd.img", moduleState); - } - - /* Reset depmod & modprobe to normal mode and get the rest of drivers*/ - mlFreeModuleState(moduleState); - busProbe(FL_NOPROBE(flags)); - - /* Disable all network interfaces in NetworkManager by default */ -#if !defined(__s390__) && !defined(__s390x__) - { - int i; - - if ((i = writeDisabledNetInfo()) != 0) { - logMessage(ERROR, "writeDisabledNetInfo failure: %d", i); - } - } -#endif - -#if defined(__s390__) || defined(__s390x__) - /* Start NetworkManager until we have systemd init on s390 too */ - if (iface_start_NetworkManager()) - logMessage(INFO, "failed to start NetworkManager"); -#else - /* Restart NetworkManager now so that it uses our inital ifcfg config */ - logMessage(INFO, "restarting NetworkManager"); - if (iface_restart_NetworkManager()) - logMessage(ERROR, "failed to restart NetworkManager"); -#endif - - if (!FL_CMDLINE(flags)) - startNewt(); - - /* can't run gdbserver until after network modules are loaded */ - doGdbserver(&loaderData); - - /* JKFIXME: we'd really like to do this before the busprobe, but then - * we won't have network devices available (and that's the only thing - * we support with this right now */ - if (loaderData.ddsrc != NULL) { - getDDFromSource(&loaderData, loaderData.ddsrc, NULL); - } - - /* JKFIXME: loaderData->ksFile is set to the arg from the command line, - * and then getKickstartFile() changes it and sets FL_KICKSTART. - * kind of weird. */ - if (loaderData.ksFile) { - logMessage(INFO, "getting kickstart file"); - - getKickstartFile(&loaderData); - if (FL_KICKSTART(flags)) - outputKSFile = runKickstart(&loaderData, loaderData.ksFile); - } - - if (FL_EARLY_NETWORKING(flags)) { - kickstartNetworkUp(&loaderData, &iface); - } - - doLoaderMain(&loaderData, modInfo); -#ifdef USESELINUX - /* now load SELinux policy before exec'ing anaconda and the shell - * (if we're using SELinux) */ - if (FL_SELINUX(flags)) { - if (loadpolicy() == 0) { - setexeccon(ANACONDA_CONTEXT); - } else { - logMessage(ERROR, "failed to load policy, disabling SELinux"); - flags &= ~LOADER_FLAGS_SELINUX; - } - } -#endif - if (FL_NOPROBE(flags) && !loaderData.ksFile) { - startNewt(); - manualDeviceCheck(&loaderData); - } - - checkTaintFlag(); - - if (loaderData.updatessrc) - loadUpdatesFromRemote(loaderData.updatessrc, &loaderData); - else if (FL_UPDATES(flags)) - loadUpdates(&loaderData); - - /* make sure /tmp/updates exists so that magic in anaconda to */ - /* symlink rhpl/ will work */ - if (unpack_mkpath("/tmp/updates") == ARCHIVE_OK) { - add_fw_search_dir(&loaderData, "/tmp/updates/firmware"); - add_to_path_env("PYTHONPATH", "/tmp/updates"); - add_to_path_env("LD_LIBRARY_PATH", "/tmp/updates"); - add_to_path_env("PATH", "/tmp/updates"); - } - - add_fw_search_dir(&loaderData, "/tmp/product/firmware"); - add_to_path_env("PYTHONPATH", "/tmp/product"); - add_to_path_env("LD_LIBRARY_PATH", "/tmp/product"); - add_to_path_env("PATH", "/tmp/product"); - - stop_fw_loader(&loaderData); - start_fw_loader(&loaderData); - - mlLoadModuleSet("raid0:raid1:raid5:raid6:raid456:raid10:linear:dm-mod:dm-zero:dm-mirror:dm-snapshot:dm-multipath:dm-round-robin:dm-crypt:cbc:sha256:lrw:xts"); - - argptr = anacondaArgs; - - path = getenv("PATH"); - while (path && path[0]) { - int n = strcspn(path, ":"); - char c, *binpath; - - c = path[n]; - path[n] = '\0'; - checked_asprintf(&binpath, "%s/anaconda", path); - path[n] = c; - - if (!access(binpath, X_OK)) { - *argptr++ = strdupa(binpath); - free(binpath); - break; - } - free(binpath); - path += n + 1; - } - - logMessage(INFO, "Running anaconda script %s", *(argptr-1)); - - /* add extra args - this potentially munges extraArgs */ - tmparg = extraArgs; - while (*tmparg) { - char *idx; - - logMessage(DEBUGLVL, "adding extraArg %s", *tmparg); - idx = strchr(*tmparg, '='); - if (idx && ((idx-*tmparg) < strlen(*tmparg))) { - *idx = '\0'; - *argptr++ = *tmparg; - *argptr++ = idx+1; - } else { - *argptr++ = *tmparg; - } - - tmparg++; - } - - if (FL_AUTOMODDISK(flags)) - *argptr++ = "--dlabel"; - - if (FL_NOIPV4(flags)) - *argptr++ = "--noipv4"; - -#ifdef ENABLE_IPV6 - if (FL_NOIPV6(flags)) - *argptr++ = "--noipv6"; -#endif - -#if defined(__s390__) || defined(__s390x__) - *argptr++ = "--headless"; -#endif - - /* Pass the local, preprocessed kickstart file to anaconda. There's no - * need for another fetch and another call to preprocessKickstart. - */ - if (FL_KICKSTART(flags) && outputKSFile) { - *argptr++ = "--kickstart"; - *argptr++ = outputKSFile; - } - - if (FL_SERIAL(flags)) - *argptr++ = "--serial"; - - if (FL_NOEJECT(flags)) - *argptr++ = "--noeject"; - - if (FL_RESCUE(flags)) { - *argptr++ = "--rescue"; - } else { - if (FL_TEXT(flags)) - *argptr++ = "-T"; - else if (FL_GRAPHICAL(flags)) - *argptr++ = "--graphical"; - if (FL_CMDLINE(flags)) - *argptr++ = "-C"; - if (!FL_SELINUX(flags)) - *argptr++ = "--noselinux"; - else if (FL_SELINUX(flags)) - *argptr++ = "--selinux"; - - /* - if (FL_VIRTPCONSOLE(flags)) { - *argptr++ = "--virtpconsole"; - *argptr++ = virtpcon; - } - */ - - if (loaderData.updatessrc && FL_UPDATES(flags)) { - *argptr++ = "--updates"; - *argptr++ = loaderData.updatessrc; - } - - if ((loaderData.lang) && !FL_NOPASS(flags)) { - *argptr++ = "--lang"; - *argptr++ = loaderData.lang; - } - - if ((loaderData.kbd) && !FL_NOPASS(flags)) { - *argptr++ = "--keymap"; - *argptr++ = loaderData.kbd; - } - - if (loaderData.logLevel) { - *argptr++ = "--loglevel"; - *argptr++ = loaderData.logLevel; - } - - if (loaderData.instRepo) { - *argptr++ = "--repo"; - if (strncmp(loaderData.instRepo, "ftp:", 4)) { - *argptr++ = loaderData.instRepo; - } else { - int fd; - - fd = open("/tmp/ftp-repo", O_CREAT | O_TRUNC | O_RDWR, 0600); - write(fd, loaderData.instRepo, strlen(loaderData.instRepo)); - write(fd, "\r", 1); - close(fd); - *argptr++ = "@/tmp/ftp-repo"; - } - } - - if (loaderData.instRepo_noverifyssl || FL_NOVERIFYSSL(flags)) { - *argptr++ = "--noverifyssl"; - } - - if (loaderData.proxy && strcmp("", loaderData.proxy)) { - *argptr++ = "--proxy"; - - *argptr++ = strdup(loaderData.proxy); - - if (loaderData.proxyUser && strcmp(loaderData.proxyUser, "")) { - int fd; - - fd = open("/tmp/proxy", O_CREAT|O_TRUNC|O_RDWR, 0600); - write(fd, loaderData.proxyUser, strlen(loaderData.proxyUser)); - write(fd, "\r\n", 2); - - if (loaderData.proxyPassword && strcmp(loaderData.proxyPassword, "")) { - write(fd, loaderData.proxyPassword, strlen(loaderData.proxyPassword)); - write(fd, "\r\n", 2); - } - - close(fd); - - *argptr++ = "--proxyAuth"; - *argptr++ = "/tmp/proxy"; - } - } - } - - *argptr = NULL; - - stopNewt(); - closeLog(); - - if (FL_RESCUE(flags)) { - fmt = _("Running anaconda %s, the %s rescue mode - please wait.\n"); - } else { - fmt = _("Running anaconda %s, the %s system installer - please wait.\n"); - } - printf(fmt, VERSION, getProductName()); - - /* Just replace the current process with anaconda. */ - if (execv(anacondaArgs[0], anacondaArgs) == -1){ - fprintf(stderr, "exec of anaconda failed: %m\n"); - doExit(1); - } - - doExit(0); -} - -/* vim:set sw=4 sts=4 et: */ diff --git a/loader/loader.h b/loader/loader.h deleted file mode 100644 index 4603158..0000000 --- a/loader/loader.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * loader.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#include <stdint.h> - -#ifndef LOADER_H -#define LOADER_H - -#define LOADER_OK 0 -#define LOADER_BACK 1 -#define LOADER_NOOP 2 -#define LOADER_ERROR -1 - -/* #0 unused */ -/* #1 unused */ -#define LOADER_FLAGS_TEXT (((uint64_t) 1) << 2) -#define LOADER_FLAGS_RESCUE (((uint64_t) 1) << 3) -#define LOADER_FLAGS_KICKSTART (((uint64_t) 1) << 4) -#define LOADER_FLAGS_KICKSTART_SEND_MAC (((uint64_t) 1) << 5) -/* #6 unused */ -#define LOADER_FLAGS_NOPROBE (((uint64_t) 1) << 7) -#define LOADER_FLAGS_MODDISK (((uint64_t) 1) << 8) -#define LOADER_FLAGS_EARLY_NETWORKING (((uint64_t) 1) << 9) -#define LOADER_FLAGS_SERIAL (((uint64_t) 1) << 10) -#define LOADER_FLAGS_UPDATES (((uint64_t) 1) << 11) -#define LOADER_FLAGS_KSFILE (((uint64_t) 1) << 12) -/* #13 unused */ -#define LOADER_FLAGS_SELINUX (((uint64_t) 1) << 14) -#define LOADER_FLAGS_VIRTPCONSOLE (((uint64_t) 1) << 15) -/* #16 unused */ -#define LOADER_FLAGS_NOSHELL (((uint64_t) 1) << 17) -/* #18 unused */ -/* #19 unused */ -#define LOADER_FLAGS_NOPASS (((uint64_t) 1) << 20) -/* #21 unused */ -#define LOADER_FLAGS_MEDIACHECK (((uint64_t) 1) << 22) -/* #23 unused */ -#define LOADER_FLAGS_ASKMETHOD (((uint64_t) 1) << 24) -#define LOADER_FLAGS_ASKNETWORK (((uint64_t) 1) << 25) -/* #26 unused */ -/* #27 unused */ -#define LOADER_FLAGS_CMDLINE (((uint64_t) 1) << 28) -#define LOADER_FLAGS_GRAPHICAL (((uint64_t) 1) << 29) -#define LOADER_FLAGS_NOIPV4 (((uint64_t) 1) << 31) -#ifdef ENABLE_IPV6 -#define LOADER_FLAGS_NOIPV6 (((uint64_t) 1) << 32) -#endif -#define LOADER_FLAGS_IP_PARAM (((uint64_t) 1) << 33) -#ifdef ENABLE_IPV6 -#define LOADER_FLAGS_IPV6_PARAM (((uint64_t) 1) << 34) -#endif -#define LOADER_FLAGS_IS_KICKSTART (((uint64_t) 1) << 35) -#define LOADER_FLAGS_ALLOW_WIRELESS (((uint64_t) 1) << 36) -#define LOADER_FLAGS_HAVE_CMSCONF (((uint64_t) 1) << 37) -#define LOADER_FLAGS_NOKILL (((uint64_t) 1) << 38) -#define LOADER_FLAGS_KICKSTART_SEND_SERIAL (((uint64_t) 1) << 39) -#define LOADER_FLAGS_AUTOMODDISK (((uint64_t) 1) << 40) -#define LOADER_FLAGS_NOEJECT (((uint64_t) 1) << 41) -#define LOADER_FLAGS_NOVERIFYSSL (((uint64_t) 1) << 42) - -#define FL_TEXT(a) ((a) & LOADER_FLAGS_TEXT) -#define FL_RESCUE(a) ((a) & LOADER_FLAGS_RESCUE) -#define FL_KICKSTART(a) ((a) & LOADER_FLAGS_KICKSTART) -#define FL_KICKSTART_SEND_MAC(a) ((a) & LOADER_FLAGS_KICKSTART_SEND_MAC) -#define FL_NOPROBE(a) ((a) & LOADER_FLAGS_NOPROBE) -#define FL_MODDISK(a) ((a) & LOADER_FLAGS_MODDISK) -#define FL_EARLY_NETWORKING(a) ((a) & LOADER_FLAGS_EARLY_NETWORKING) -#define FL_SERIAL(a) ((a) & LOADER_FLAGS_SERIAL) -#define FL_UPDATES(a) ((a) & LOADER_FLAGS_UPDATES) -#define FL_KSFILE(a) ((a) & LOADER_FLAGS_KSFILE) -#define FL_NOSHELL(a) ((a) & LOADER_FLAGS_NOSHELL) -#define FL_NOPASS(a) ((a) & LOADER_FLAGS_NOPASS) -#define FL_MEDIACHECK(a) ((a) & LOADER_FLAGS_MEDIACHECK) -#define FL_ASKMETHOD(a) ((a) & LOADER_FLAGS_ASKMETHOD) -#define FL_GRAPHICAL(a) ((a) & LOADER_FLAGS_GRAPHICAL) -#define FL_CMDLINE(a) ((a) & LOADER_FLAGS_CMDLINE) -#define FL_SELINUX(a) ((a) & LOADER_FLAGS_SELINUX) -#define FL_VIRTPCONSOLE(a) ((a) & LOADER_FLAGS_VIRTPCONSOLE) -#define FL_ASKNETWORK(a) ((a) & LOADER_FLAGS_ASKNETWORK) -#define FL_NOIPV4(a) ((a) & LOADER_FLAGS_NOIPV4) -#ifdef ENABLE_IPV6 -#define FL_NOIPV6(a) ((a) & LOADER_FLAGS_NOIPV6) -#endif -#define FL_IP_PARAM(a) ((a) & LOADER_FLAGS_IP_PARAM) -#ifdef ENABLE_IPV6 -#define FL_IPV6_PARAM(a) ((a) & LOADER_FLAGS_IPV6_PARAM) -#endif -#define FL_IS_KICKSTART(a) ((a) & LOADER_FLAGS_IS_KICKSTART) -#define FL_ALLOW_WIRELESS(a) ((a) & LOADER_FLAGS_ALLOW_WIRELESS) -#define FL_HAVE_CMSCONF(a) ((a) & LOADER_FLAGS_HAVE_CMSCONF) -#define FL_NOKILL(a) ((a) & LOADER_FLAGS_NOKILL) -#define FL_KICKSTART_SEND_SERIAL(a) ((a) & LOADER_FLAGS_KICKSTART_SEND_SERIAL) -#define FL_AUTOMODDISK(a) ((a) & LOADER_FLAGS_AUTOMODDISK) -#define FL_NOEJECT(a) ((a) & LOADER_FLAGS_NOEJECT) -#define FL_NOVERIFYSSL(a) ((a) & LOADER_FLAGS_NOVERIFYSSL) - -void doExit(int) __attribute__ ((noreturn)); -void startNewt(void); -void stopNewt(void); -char * getProductName(void); -char * getProductArch(void); - -#include "moduleinfo.h" -#include "../pyanaconda/isys/devices.h" -/* JKFIXME: I don't like all of the _set attribs, but without them, - * we can't tell if it was explicitly set by kickstart/cmdline or - * if we just got it going through the install. */ -struct loaderData_s { - char * lang; - int lang_set; - char * kbd; - int kbd_set; - char * netDev; - int netDev_set; - char * bootIf; - int bootIf_set; - char * netCls; - int netCls_set; - char *ipv4, *netmask, *gateway, *dns, *domain, *hostname, *peerid, *ethtool; - char *subchannels, *portname, *nettype, *ctcprot, *options, *macaddr; - char *essid, *wepkey, *wpakey; -#ifdef ENABLE_IPV6 - char *ipv6; - char *ipv6prefix; - int ipv6info_set; - char *gateway6; -#endif - int mtu; - int noDns; - int dhcpTimeout; - int ipinfo_set; - char * ksFile; - int method; - char * ddsrc; - char * logLevel; - char * updatessrc; - char * gdbServer; - char * instRepo; - int instRepo_noverifyssl; - - pid_t fw_loader_pid; - char *fw_search_pathz; - size_t fw_search_pathz_len; - - moduleInfoSet modInfo; - - /* Proxy info needs to be in the loaderData so we can get these - * settings off the command line, too. - */ - char *proxy; - char *proxyUser; - char *proxyPassword; -}; - -/* 64 bit platforms, definitions courtesy of glib */ -#if defined (__x86_64__) || defined(__ia64__) || defined(__alpha__) || defined(__powerpc64__) || defined(__s390x__) || (defined(__sparc__) && defined(__arch64__)) -#define POINTER_TO_INT(p) ((int) (long) (p)) -#define INT_TO_POINTER(i) ((void *) (long) (i)) -#else -#define POINTER_TO_INT(p) ((int) (p)) -#define INT_TO_POINTER(i) ((void *) (i)) -#endif - -/* library paths */ -#if defined(__x86_64__) || defined(__s390x__) || defined(__powerpc64__) -#define LIBPATH "/lib64:/usr/lib64:/usr/X11R6/lib64:/usr/kerberos/lib64:/mnt/usr/lib64:/mnt/sysimage/lib64:/mnt/sysimage/usr/lib64" -#else -#define LIBPATH "/lib:/usr/lib:/usr/X11R6/lib:/usr/kerberos/lib:/mnt/usr/lib:/mnt/sysimage/lib:/mnt/sysimage/usr/lib" -#endif - -#define checked_asprintf(...) \ - if (asprintf( __VA_ARGS__ ) == -1) { \ - logMessage(CRITICAL, "%s: %d: %m", __func__, __LINE__); \ - abort(); \ - } - -#endif diff --git a/loader/loadermisc.c b/loader/loadermisc.c deleted file mode 100644 index 61e77bf..0000000 --- a/loader/loadermisc.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * loadermisc.c - miscellaneous loader functions that don't seem to fit - * anywhere else (yet) (was misc.c) - * JKFIXME: need to break out into reasonable files based on function - * - * Copyright (C) 1999, 2000, 2001, 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <ctype.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <unistd.h> -#include <stdarg.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "../pyanaconda/isys/log.h" -#include "windows.h" - -int copyFileFd(int infd, char * dest, progressCB pbcb, - struct progressCBdata *data, long long total) { - int outfd; - char buf[4096]; - int i; - int rc = 0; - long long count = 0; - - outfd = open(dest, O_CREAT | O_RDWR, 0666); - - if (outfd < 0) { - logMessage(ERROR, "failed to open %s: %m", dest); - return 1; - } - - while ((i = read(infd, buf, sizeof(buf))) > 0) { - if (write(outfd, buf, i) != i) { - rc = 1; - break; - } - - count += i; - - if (pbcb && data && total) { - pbcb(data, count, total); - } - } - - close(outfd); - - return rc; -} - -int copyFile(char * source, char * dest) { - int infd = -1; - int rc; - - infd = open(source, O_RDONLY); - - if (infd < 0) { - logMessage(ERROR, "failed to open %s: %m", source); - return 1; - } - - rc = copyFileFd(infd, dest, NULL, NULL, 0); - - close(infd); - - return rc; -} - -/** - * Do "rm -rf" on the target directory. - * - * Returns 0 on success, nonzero otherwise (i.e. directory doesn't exist or - * some of its contents couldn't be removed). - * - * This is copied from the util-linux-ng project. - */ -int recursiveRemove(int fd) -{ - struct stat rb; - DIR *dir; - int rc = -1; - int dfd; - - if (!(dir = fdopendir(fd))) { - goto done; - } - - /* fdopendir() precludes us from continuing to use the input fd */ - dfd = dirfd(dir); - - if (fstat(dfd, &rb)) { - goto done; - } - - while(1) { - struct dirent *d; - - errno = 0; - if (!(d = readdir(dir))) { - if (errno) { - goto done; - } - break; /* end of directory */ - } - - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) - continue; - - if (d->d_type == DT_DIR) { - struct stat sb; - - if (fstatat(dfd, d->d_name, &sb, AT_SYMLINK_NOFOLLOW)) { - continue; - } - - /* remove subdirectories if device is same as dir */ - if (sb.st_dev == rb.st_dev) { - int cfd; - - cfd = openat(dfd, d->d_name, O_RDONLY); - if (cfd >= 0) { - recursiveRemove(cfd); - close(cfd); - } - } else - continue; - } - - unlinkat(dfd, d->d_name, d->d_type == DT_DIR ? AT_REMOVEDIR : 0); - } - - rc = 0; /* success */ - - done: - if (dir) - closedir(dir); - return rc; -} - -int simpleStringCmp(const void * a, const void * b) { - const char * first = *((const char **) a); - const char * second = *((const char **) b); - - return strverscmp(first, second); -} diff --git a/loader/loadermisc.h b/loader/loadermisc.h deleted file mode 100644 index 3ffacb2..0000000 --- a/loader/loadermisc.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * loadermisc.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef H_LOADER_MISC_H -#define H_LOADER_MISC_H -#include <stdio.h> -#include <stdarg.h> - -#include "windows.h" - -int copyFile(char * source, char * dest); -int copyFileFd(int infd, char * dest, progressCB pbcb, - struct progressCBdata *data, long long total); -int recursiveRemove(int fd); -int simpleStringCmp(const void * a, const void * b); - -#endif diff --git a/loader/mediacheck.c b/loader/mediacheck.c deleted file mode 100644 index c4c1aa0..0000000 --- a/loader/mediacheck.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * simple program to check implanted md5sum in an iso 9660 image - * - * Copyright (C) 2001, 2005 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Michael Fulbright <msf@xxxxxxxxxx> - * Dustin Kirkland <dustin.kirkland@xxxxxxxxx> - */ - -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <newt.h> -#include <libcheckisomd5.h> - -#include "../pyanaconda/isys/log.h" - -#include "lang.h" -#include "windows.h" - -int doMediaCheck(char *file, char *descr) { - struct progressCBdata data; - newtComponent t, f, scale, label; - int rc; - int dlen; - int llen; - char tmpstr[1024]; - - if (access(file, R_OK) < 0) { - newtWinMessage(_("Error"), _("OK"), _("Unable to find install image " - "%s"), file); - return -1; - } - - if (descr) - snprintf(tmpstr, sizeof(tmpstr), _("Checking \"%s\"."), descr); - else - snprintf(tmpstr, sizeof(tmpstr), _("Checking media.")); - - dlen = strlen(tmpstr); - if (dlen > 65) - dlen = 65; - - newtCenteredWindow(dlen+8, 6, _("Media Check")); - t = newtTextbox(1, 1, dlen+4, 3, NEWT_TEXTBOX_WRAP); - - newtTextboxSetText(t, tmpstr); - llen = strlen(tmpstr); - - label = newtLabel(llen+1, 1, "-"); - f = newtForm(NULL, NULL, 0); - newtFormAddComponent(f, t); - scale = newtScale(3, 3, dlen, 100); - newtFormAddComponent(f, scale); - - newtDrawForm(f); - newtRefresh(); - - data.scale = scale; - data.label = label; - - rc = mediaCheckFile(file, progressCallback, &data); - - newtFormDestroy(f); - newtPopWindow(); - - if (rc == ISOMD5SUM_CHECK_NOT_FOUND) { - logMessage(WARNING, "mediacheck: %s (%s) has no checksum info", file, descr); - newtWinMessage(_("Error"), _("OK"), - _("Unable to find the checksum in the " - "image. This probably " - "means the disc was created without adding the " - "checksum.")); - } else if (rc == ISOMD5SUM_FILE_NOT_FOUND) { - logMessage(WARNING, "mediacheck: %s (%s) open failed", file, descr); - newtWinMessage(_("Error"), _("OK"), - _("Unable to open the image.")); - } else if (rc == ISOMD5SUM_CHECK_FAILED) { - logMessage(ERROR, "mediacheck: %s (%s) FAILED", file, descr); - newtWinMessage(_("Error"), _("OK"), - _("The image which was just tested has errors. " - "This could be due to a " - "corrupt download or a bad disc. " - "If applicable, please clean the disc " - "and try again. If this test continues to fail you " - "should not continue the install.")); - } else if (rc == ISOMD5SUM_CHECK_PASSED) { - logMessage(INFO, "mediacheck: %s (%s) PASSED", file, descr); - newtWinMessage(_("Success"), _("OK"), - _("The image which was just tested was successfully " - "verified. It should be OK to install from this " - "media. Note that not all media/drive errors can " - "be detected by the media check.")); - } - - - return rc; -} diff --git a/loader/mediacheck.h b/loader/mediacheck.h deleted file mode 100644 index ab2f887..0000000 --- a/loader/mediacheck.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * mediacheck.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef MEDIACHECK_H -#define MEDIACHECK_H - -int doMediaCheck(char *file, char *descr); - -#endif diff --git a/loader/method.c b/loader/method.c deleted file mode 100644 index 2fb9de5..0000000 --- a/loader/method.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <ctype.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <libgen.h> -#include <newt.h> -#include <stdlib.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> -#include <libgen.h> - -#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; -} diff --git a/loader/method.h b/loader/method.h deleted file mode 100644 index 6218343..0000000 --- a/loader/method.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * method.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef H_METHOD -#define H_METHOD - -#include "loader.h" -#include "windows.h" - -/* method identifiers, needs to match struct installMethod order in loader.c */ -enum { - METHOD_CDROM, - METHOD_HD, - METHOD_NFS, - METHOD_URL -}; - -struct installMethod { - char * name; - char * desc; - int network; - enum deviceType type; - int (*prompt)(struct loaderData_s *loaderData); - int (*findExtras)(struct loaderData_s *loaderData); -}; - -int readStampFileFromIso(char *file, char **descr, char **timestamp); -void queryIsoMediaCheck(char * isoDir); - -int getFileFromBlockDevice(char *device, char *path, char * dest); - -void copyUpdatesImg(char * path); -void copyProductImg(char * path); - -#endif diff --git a/loader/moduleinfo.c b/loader/moduleinfo.c deleted file mode 100644 index 61d1681..0000000 --- a/loader/moduleinfo.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * moduleinfo.c - module info functionality - * - * Copyright (C) 1997, 1998, 1999, 2000, 2001, 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - */ - -#include <alloca.h> -#include <ctype.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <stdio.h> - -#include "moduleinfo.h" - -struct moduleInfo * getModuleList(moduleInfoSet mis, - enum driverMajor major) { - struct moduleInfo * miList, * next; - int i; - - next = miList = malloc(sizeof(*miList) * mis->numModules + 1); - for (i = 0; i < mis->numModules; i++) { - if (mis->moduleList[i].major == major || major == DRIVER_NONE) { - *next = mis->moduleList[i]; - next++; - } - } - - if (next == miList) { - free(next); - return NULL; - } - - next->moduleName = NULL; - next++; - - miList = realloc(miList, sizeof(*miList) * (next - miList)); - return miList; -} - -struct moduleInfo * findModuleInfo(moduleInfoSet mis, - const char * moduleName) { - int i; - struct moduleInfo * found = NULL; - - for (i = 0; i < mis->numModules; i++) { - if (!strcmp(moduleName, mis->moduleList[i].moduleName)) { - if (!found) - found = mis->moduleList + i; - else if (found->locationID && !mis->moduleList[i].locationID) - ; - else - found = mis->moduleList + i; - } - } - - return found; -} - -moduleInfoSet newModuleInfoSet(void) { - return calloc(sizeof(struct moduleInfoSet_s), 1); -} - -/* filename: file to read module-info from - * mis: moduleInfoSet - * location: moduleBallLocation struct describing the location of - * these modules. (may be NULL) - * override: 1 if modules from this module ball should override old ones - * of the same name. - */ -int readModuleInfo(const char * filename, moduleInfoSet mis, - void * location, int override) { - int fd, isIndented; - char * buf, * start, * next = NULL, * chptr; - struct stat sb; - struct moduleInfo * nextModule; - int modulesAlloced; - int i; - int found = 0, skipModule = 0; - - fd = open(filename, O_RDONLY); - if (fd < 0) return -1; - - fstat(fd, &sb); - buf = alloca(sb.st_size + 1); - i = read(fd, buf, sb.st_size); - buf[sb.st_size] = '\0'; - close(fd); - - if (i != sb.st_size) - return -1; - - nextModule = NULL; - modulesAlloced = mis->numModules; - - if (strncmp(buf, "Version 0\n", 10)) return -1; - - start = buf + 10; - while (start && *start) { - chptr = strchr(start, '\n'); - if (chptr) { - /* slice and dice */ - next = chptr + 1; - } else { - chptr += strlen(start) - 1; - } - - chptr--; - while (isspace(*chptr)) chptr--; - chptr++; - *chptr = '\0'; - - isIndented = 0; - if (isspace(*start)) { - while (isspace(*start) && *start != '\n') start++; - isIndented = 1; - } - - if (*start != '\n' && *start && *start != '#') { - if (!isIndented) { - if (nextModule && nextModule->moduleName && - nextModule == (mis->moduleList + mis->numModules)) { - mis->numModules++; - } - - if (mis->numModules == modulesAlloced) { - modulesAlloced += 5; - mis->moduleList = realloc(mis->moduleList, - modulesAlloced * sizeof(*mis->moduleList)); - } - - nextModule = NULL; - found = 0; - skipModule = 0; - for (i = 0; i < mis->numModules; i++) { - if (!strcmp(mis->moduleList[i].moduleName, start)) { - if (override) - nextModule = mis->moduleList + i; - else - skipModule = 1; - found = 1; - break; - } - } - - if (!found && !nextModule) { - nextModule = mis->moduleList + mis->numModules; - - nextModule->moduleName = strdup(start); - } - - if (nextModule) { - nextModule->major = DRIVER_NONE; - nextModule->minor = DRIVER_MINOR_NONE; - nextModule->description = NULL; - nextModule->flags = 0; - nextModule->args = NULL; - nextModule->numArgs = 0; - nextModule->locationID = location; - } - } else if (!nextModule && skipModule) { - /* we're skipping this one (not overriding), do nothing */ - } else if (!nextModule && skipModule) { - /* ACK! syntax error */ - fprintf(stderr, "module-info syntax error in %s\n", filename); - return 1; - } else if (nextModule->major == DRIVER_NONE) { - chptr = start + strlen(start) - 1; - while (!isspace(*chptr) && chptr > start) chptr--; - if (chptr != start) chptr++; - - if (!strcmp(chptr, "eth")) { - nextModule->major = DRIVER_NET; - nextModule->minor = DRIVER_MINOR_ETHERNET; - } else if (!strcmp(chptr, "tr")) { - nextModule->major = DRIVER_NET; - nextModule->minor = DRIVER_MINOR_TR; - } else if (!strcmp(chptr, "scsi_hostadapter") || - !strcmp(chptr, "scsi")) { - nextModule->major = DRIVER_SCSI; - } else if (!strcmp(chptr, "pcmcia")) { - nextModule->major = DRIVER_PCMCIA; - } else if (!strcmp(chptr, "fs")) { - nextModule->major = DRIVER_FS; - } else if (!strcmp(chptr, "cdrom")) { - nextModule->major = DRIVER_CDROM; - } else if (!strcmp(chptr, "ide")) { - nextModule->major = DRIVER_IDE; - } else { - nextModule->major = DRIVER_OTHER; - } - } else if (!nextModule->description) { - chptr = start + strlen(start) - 1; - if (*start == '"' && *chptr == '"') { - start++; - *chptr = '\0'; - nextModule->description = strdup(start); - } - } else { - nextModule->args = realloc(nextModule->args, - sizeof(*nextModule->args) * (nextModule->numArgs + 1)); - chptr = start; - while (!isspace(*chptr) && *chptr) chptr++; - if (*chptr) { - *chptr = '\0'; - nextModule->args[nextModule->numArgs].arg = strdup(start); - - start = chptr + 1; - while (*start && isspace(*start)) start++; - - if (*start == '"') { - start++; - chptr = strchr(start, '"'); - if (chptr) { - *chptr = '\0'; - nextModule->args[nextModule->numArgs].description = - strdup(start); - nextModule->numArgs++; - } - } - } - } - } - - start = next; - } - - /* do we need to add in this last module? */ - if (nextModule && ((nextModule - mis->moduleList) == mis->numModules)) - mis->numModules++; - - return 0; -} - -void freeModuleInfoSet(moduleInfoSet mis) { - int i, j; - - for (i = 0; i < mis->numModules; i++) { - if (mis->moduleList[i].moduleName) - free(mis->moduleList[i].moduleName); - - if (mis->moduleList[i].description) - free(mis->moduleList[i].description); - - for (j = 0; i < mis->moduleList[i].numArgs; j++) { - if (mis->moduleList[i].args[j].arg) - free(mis->moduleList[i].args[j].arg) ; - if (mis->moduleList[i].args[j].description) - free(mis->moduleList[i].args[j].description) ; - } - } - - free(mis); -} diff --git a/loader/moduleinfo.h b/loader/moduleinfo.h deleted file mode 100644 index 72f6d71..0000000 --- a/loader/moduleinfo.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * moduleinfo.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef MODULEINFO_H -#define MODULEINFO_H - -enum driverMajor { DRIVER_NONE = 0, DRIVER_SCSI, DRIVER_NET, DRIVER_CDROM, - DRIVER_PCMCIA, DRIVER_FS, DRIVER_IDE, DRIVER_OTHER = 1000, - DRIVER_ANY = 5000 }; -enum driverMinor { DRIVER_MINOR_NONE = 0, DRIVER_MINOR_ETHERNET, - DRIVER_MINOR_TR }; - -struct moduleArg { - char * arg; - char * description; -}; - -#define MI_FLAG_NOMISCARGS (1 << 0) - -struct moduleInfo { - char * moduleName; - char * description; - enum driverMajor major; - enum driverMinor minor; - int numArgs; - struct moduleArg * args; - int flags; - void * locationID; -}; - -struct moduleInfoSet_s { - struct moduleInfo * moduleList; - int numModules; -}; - -struct moduleBallLocation { - char * path; /* path to module ball that this driver is from. if NULL, - * implies /modules/modules.cgz */ - char * title; /* title used for driver disk -- may be NULL */ - int version; /* module ball version, used to determine layout */ -}; -#define CURRENT_MODBALLVER 1 - -/* valid moduleball versions - * 0: old single-arch module ball, modules are in uname.release - * 1: multi-arch, modules are in uname.release/arch - */ - -typedef struct moduleInfoSet_s * moduleInfoSet; - -moduleInfoSet newModuleInfoSet(void); -void freeModuleInfoSet(moduleInfoSet mis); -int readModuleInfo(const char * filename, moduleInfoSet mis, void * path, int override); -struct moduleInfo * findModuleInfo(moduleInfoSet mis, - const char * moduleName); - -/* NULL moduleName indicates the end of the list; the list must be freed() */ -struct moduleInfo * getModuleList(moduleInfoSet mis, - enum driverMajor major); - - -#endif diff --git a/loader/modules.c b/loader/modules.c deleted file mode 100644 index a48ccc9..0000000 --- a/loader/modules.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * modules.c - module loading functionality - * - * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - * 2008, 2009 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - * David Cantrell <dcantrell@xxxxxxxxxx> - */ -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/utsname.h> -#include <sys/wait.h> -#include <unistd.h> -#include <glib.h> -#include <glib/gprintf.h> -#include <assert.h> -#include <stdint.h> - -#include "../pyanaconda/isys/log.h" - -#include "loader.h" -#include "modules.h" -#include "readvars.h" - -/* boot flags */ -extern uint64_t flags; - -static GSList *modopts = NULL; -static GSList *blacklist = NULL; - -static gboolean _isValidModule(gchar *module) { - gint fd = -1, i = 0; - gchar *path = NULL, *buf = NULL, *modname = NULL; - gchar *ends[] = { ".ko.gz:", ".ko:", NULL }; - struct utsname utsbuf; - struct stat sbuf; - - if (uname(&utsbuf) == -1) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - return FALSE; - } - - if (asprintf(&path, "/lib/modules/%s/modules.dep", utsbuf.release) == -1) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - return FALSE; - } - - if (stat(path, &sbuf) == -1) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - free(path); - return FALSE; - } - - if ((fd = open(path, O_RDONLY)) == -1) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - free(path); - return FALSE; - } else { - free(path); - } - - buf = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (!buf || buf == MAP_FAILED) { - close(fd); - return FALSE; - } - - close(fd); - - while (ends[i] != NULL) { - if (asprintf(&modname, "/%s%s", module, ends[i]) == -1) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - return FALSE; - } - - if (g_strstr_len(buf, -1, modname) != NULL) { - munmap(buf, sbuf.st_size); - free(modname); - return TRUE; - } - - free(modname); - modname = NULL; - i++; - } - - munmap(buf, sbuf.st_size); - return FALSE; -} - -static void _addOption(const gchar *module, const gchar *option) { - gboolean found = FALSE; - GSList *iterator = modopts; - module_t *modopt = NULL; - gchar *tmpopt = g_strdup(option); - - while (iterator != NULL) { - modopt = (module_t *) iterator->data; - - if (!strncmp(modopt->name, module, strlen(modopt->name))) { - found = TRUE; - break; - } - - iterator = g_slist_next(iterator); - } - - if (found) { - modopt->options = g_slist_append(modopt->options, tmpopt); - } else { - if ((modopt = g_malloc0(sizeof(module_t))) == NULL) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - abort(); - } - - modopt->name = g_strdup(module); - modopt->options = NULL; - modopt->options = g_slist_append(modopt->options, tmpopt); - modopts = g_slist_append(modopts, modopt); - } - - return; -} - -static gboolean _writeModulesConf(gchar *conf) { - gint fd = -1, rc = 0, len = 0; - GSList *iterator = modopts; - GString *buf = g_string_new("# Module options and blacklists written by anaconda\n"); - - if (conf == NULL) { - /* XXX: should this use mkstemp() ? */ - conf = "/tmp/modprobe.conf"; - } - - if ((fd = open(conf, O_WRONLY | O_CREAT, 0644)) == -1) { - logMessage(ERROR, "error opening to %s: %m", conf); - return FALSE; - } - - while (iterator != NULL) { - module_t *modopt = iterator->data; - GSList *optiterator = modopt->options; - g_string_append_printf(buf, "options %s", modopt->name); - - while (optiterator != NULL) { - gchar *option = (gchar *) optiterator->data; - g_string_append_printf(buf, " %s", option); - optiterator = g_slist_next(optiterator); - } - - g_string_append(buf, "\n"); - iterator = g_slist_next(iterator); - } - - iterator = blacklist; - - while (iterator != NULL) { - gchar *module = (gchar *) iterator->data; - g_string_append_printf(buf, "blacklist %s\n", module); - iterator = g_slist_next(iterator); - } - - len = buf->len; - rc = write(fd, buf->str, len); - close(fd); - g_string_free(buf, TRUE); - - return (rc == len); -} - -static gboolean _doLoadModule(const gchar *module, gchar **args) { - gint child; - gint status; - - if (!(child = fork())) { - gint i, rc; - gchar **argv = NULL; - gint fd = -1; - - if ((argv = g_malloc0(3 * sizeof(*argv))) == NULL) { - if (loggingReady()) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - } - abort(); - } - - if ((fd = open("/dev/tty3", O_RDWR)) == -1) { - if (loggingReady()) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - } - } else { - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - close(fd); - } - - argv[0] = "/sbin/modprobe"; - argv[1] = g_strdup(module); - argv[2] = NULL; - - if (args) { - for (i = 0; args[i] ; i++) { - _addOption(module, args[i]); - } - _writeModulesConf(MODULES_CONF); - } - - rc = execv("/sbin/modprobe", argv); - g_strfreev(argv); - _exit(rc); - } - - waitpid(child, &status, 0); - - if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { - return TRUE; - } else { - return FALSE; - } -} - -gboolean mlInitModuleConfig(void) { - GHashTableIter iter; - gpointer key = NULL, value = NULL; - GHashTable *cmdline = readvars_parse_file("/proc/cmdline"); - - if (cmdline == NULL) { - return _writeModulesConf(MODULES_CONF); - } - - g_hash_table_iter_init(&iter, cmdline); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - gchar *k = (gchar *) key; - gchar *v = (gchar *) value; - - if (v == NULL) { - continue; - } else if (!strcasecmp(k, "blacklist")) { - gchar *tmpmod = g_strdup(v); - blacklist = g_slist_append(blacklist, tmpmod); - } else if (!strstr(k, ".")) { - gchar **fields = g_strsplit(k, ".", 0); - - if (g_strv_length(fields) == 2 && _isValidModule(fields[0])) { - GString *tmp = g_string_new(fields[1]); - g_string_append_printf(tmp, "=%s", v); - _addOption(fields[0], tmp->str); - g_string_free(tmp, TRUE); - } - - g_strfreev(fields); - } - } - - g_hash_table_destroy(cmdline); - - return _writeModulesConf(MODULES_CONF); -} - -/* load a module with a given list of arguments */ -gboolean mlLoadModule(const gchar *module, gchar **args) { - return _doLoadModule(module, args); -} - -/* loads a : separated list of modules */ -gboolean mlLoadModuleSet(const gchar *modNames) { - gchar **mods = NULL, **iterator = NULL; - gboolean rc = FALSE; - - if (modNames == NULL) { - return FALSE; - } - - if ((mods = g_strsplit(modNames, ":", 0)) != NULL) { - iterator = mods; - - while (*iterator != NULL) { - rc |= _doLoadModule(*iterator, NULL); - iterator++; - } - } else { - return FALSE; - } - - g_strfreev(mods); - return rc; -} - -gboolean mlAddBlacklist(gchar *module) { - gchar *tmpmod = NULL; - - if (module == NULL) { - return FALSE; - } - - tmpmod = g_strdup(module); - blacklist = g_slist_append(blacklist, tmpmod); - return _writeModulesConf(MODULES_CONF); -} - -gboolean mlRemoveBlacklist(gchar *module) { - GSList *iterator = blacklist; - - if (module == NULL) { - return FALSE; - } - - while (iterator != NULL) { - if (!strcmp((gchar *) iterator->data, module)) { - iterator = g_slist_delete_link(blacklist, iterator); - continue; - } else { - iterator = g_slist_next(iterator); - } - } - - return TRUE; -} - -inline gint gcmp(gconstpointer a, gconstpointer b, gpointer userptr) -{ - return g_strcmp0(a, b); -} - -int processModuleLines(int (*f)(gchar**, void*), void *data) -{ - char *line = NULL; - size_t linesize = 0; - gchar** lineparts = NULL; - int count = 0; - - FILE *file = fopen("/proc/modules", "r"); - if (file == NULL) - return -1; - - while (1) { - if (getline(&line, &linesize, file) < 0) - break; - - if (line == NULL) - break; - - lineparts = g_strsplit_set(line, " ", 4); - - free(line); - line = NULL; - - int ret = f(lineparts, data); - g_strfreev(lineparts); - - if (ret < 0) - break; - count+=ret; - } - - fclose(file); - return count; -} - -inline int cb_savestate(gchar** parts, void *data0) -{ - GTree *data = data0; - logMessage(DEBUGLVL, "Saving module %s", parts[0]); - g_tree_insert(data, g_strdup(parts[0]), (gchar*)1); - return 1; -} - -GTree* mlSaveModuleState() -{ - GTree *state = NULL; - - state = g_tree_new_full(gcmp, NULL, g_free, NULL); - if(!state) - return NULL; - - processModuleLines(cb_savestate, state); - - return state; -} - -inline int cb_restorestate(gchar** parts, void *data0) -{ - GTree *data = data0; - pid_t pid; - int status; - - /* this module has to stay loaded */ - if (g_tree_lookup(data, parts[0])){ - return 0; - } - - /* this module is still required */ - if (parts[2][0] != '0') { - return 0; - } - - /* rmmod parts[0] */ - pid = fork(); - if (pid == 0) { - execl("/sbin/rmmod", "-f", parts[0], NULL); - _exit(1); - } - else if (pid < 0) { - logMessage(ERROR, "Module %s removal FAILED", parts[0]); - return 0; - } - - waitpid(pid, &status, 0); - if (WEXITSTATUS(status)) { - logMessage(DEBUGLVL, "Module %s was NOT removed", parts[0]); - return 0; - } - else{ - logMessage(DEBUGLVL, "Module %s was removed", parts[0]); - return 1; - } - - return 0; -} - -void mlRestoreModuleState(GTree *state) -{ - if(!state) - return; - - logMessage(INFO, "Restoring module state..."); - - /* repeat until we can't remove anything else */ - while (processModuleLines(cb_restorestate, state) > 0) - /* noop */; -} - -void mlFreeModuleState(GTree *state) -{ - if(!state) - return; - - g_tree_destroy(state); -} - -inline int cb_saveversions(gchar** parts, void *data0) -{ - GHashTable *ht = data0; - gchar *module = g_strdup(parts[0]); - char *versionfilename; - char *srcversionfilename; - gchar *version; - gchar *srcversion; - gchar *value, *value2; - - checked_asprintf(&versionfilename, "/sys/module/%s/version", module); - checked_asprintf(&srcversionfilename, "/sys/module/%s/srcversion", module); - - /* emty string */ - value = g_new0(gchar, 1); - - /* get possible version file */ - if (g_file_get_contents(versionfilename, &version, NULL, NULL)) { - value2 = g_strconcat(value, version, "/", NULL); - g_free(value); - g_free(version); - value = value2; - } - - /* get possible src version file */ - if (g_file_get_contents(srcversionfilename, &srcversion, NULL, NULL)) { - value2 = g_strconcat(value, srcversion, NULL); - g_free(value); - g_free(srcversion); - value = value2; - } - - free(versionfilename); - free(srcversionfilename); - - g_hash_table_insert(ht, module, value); - - return 1; -} - -VersionState mlVersions() -{ - GHashTable *ht = NULL; - - ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - if(!ht) return NULL; - - /* read version info about all modules */ - processModuleLines(cb_saveversions, ht); - - return (VersionState)ht; -} - -void mlFreeVersions(VersionState ht) -{ - g_hash_table_destroy((GHashTable*)ht); -} - -int mlDetectUpdate(VersionState a, VersionState b) -{ - int rc = 0; - - if(!a && !b) return 0; - if(!a) return 1; - if(!b) return 1; - - GList *modules = g_hash_table_get_keys(b); - if(!modules) return 0; - - GList *iter = modules; - while (iter && !rc) { - gchar *va = g_hash_table_lookup(a, iter->data); - gchar *vb = g_hash_table_lookup(b, iter->data); - - if (!va) rc = 1; // new module - else rc = strcmp(va, vb); // check versions for match - - iter = iter->next; - } - - g_list_free(modules); - - return abs(rc); -} diff --git a/loader/modules.h b/loader/modules.h deleted file mode 100644 index 19eb029..0000000 --- a/loader/modules.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * modules.h - * - * Copyright (C) 2007, 2009 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 <http://www.gnu.org/licenses/>. - * - * Author(s): David Cantrell <dcantrell@xxxxxxxxxx> - */ - -#ifndef H_MODULES -#define H_MODULES - -#include <glib.h> -#include "moduleinfo.h" - -#define MODULES_CONF "/etc/modprobe.d/anaconda.conf" - -typedef struct _module_t { - gchar *name; - GSList *options; -} module_t; - -gboolean mlInitModuleConfig(void); -gboolean mlLoadModule(const gchar *, gchar **); -gboolean mlLoadModuleSet(const gchar *); -gboolean mlAddBlacklist(gchar *); -gboolean mlRemoveBlacklist(gchar *); - -GTree* mlSaveModuleState(); -void mlRestoreModuleState(GTree *state); -void mlFreeModuleState(GTree *state); - -typedef GHashTable* VersionState; -VersionState mlVersions(); -int mlDetectUpdate(VersionState a, VersionState b); -void mlFreeVersions(); - -#endif diff --git a/loader/net.c b/loader/net.c deleted file mode 100644 index d556554..0000000 --- a/loader/net.c +++ /dev/null @@ -1,2466 +0,0 @@ -/* - * net.c - * - * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. - * 2006, 2007, 2008, 2009 - * - * 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 <http://www.gnu.org/licenses/>. - * - * Author(s): David Cantrell <dcantrell@xxxxxxxxxx> - */ - -#include <netdb.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/utsname.h> -#include <arpa/inet.h> -#include <errno.h> -#include <resolv.h> -#include <net/if.h> -#include <newt.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <unistd.h> - -#include <glib.h> -#include <NetworkManager.h> -#include <nm-client.h> -#include <nm-device-wifi.h> - -#include "../pyanaconda/isys/isys.h" -#include "../pyanaconda/isys/ethtool.h" -#include "../pyanaconda/isys/iface.h" -#include "../pyanaconda/isys/log.h" - -#include "lang.h" -#include "loader.h" -#include "loadermisc.h" -#include "method.h" -#include "net.h" -#include "windows.h" -#include "ibft.h" - -#include <nm-device.h> -#include <nm-setting-connection.h> -#include <nm-setting-wireless.h> -#include <nm-setting-ip4-config.h> -#include <nm-utils.h> -#include <dbus/dbus.h> -#include <dbus/dbus-glib.h> - -/* boot flags */ -extern uint64_t flags; - -/** - * Callback function for the CIDR entry boxes on the manual TCP/IP - * configuration window. - * - * @param co The entry field that triggered the callback. - * @param dptr Pointer to intfconfig_s data structure for this field. - * @see intfconfig_s - */ -static void cidrCallback(newtComponent co, void * dptr) { - struct intfconfig_s * data = dptr; - int cidr, upper = 0; - - if (co == data->cidr4Entry) { - if (data->cidr4 == NULL && data->ipv4 == NULL) - return; - - if (isValidIPv4Address(data->cidr4)) - return; - - errno = 0; - cidr = strtol(data->cidr4, NULL, 10); - if ((errno == ERANGE && (cidr == LONG_MIN || cidr == LONG_MAX)) || - (errno != 0 && cidr == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - if (strcmp(data->ipv4, "")) - upper = 32; -#ifdef ENABLE_IPV6 - } else if (co == data->cidr6Entry) { - if (data->cidr6 == NULL && data->ipv6 == NULL) - return; - - errno = 0; - cidr = strtol(data->cidr6, NULL, 10); - if ((errno == ERANGE && (cidr == LONG_MIN || cidr == LONG_MAX)) || - (errno != 0 && cidr == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - if (strcmp(data->ipv6, "")) - upper = 128; -#endif - } - - if (upper != 0) { - if (cidr < 1 || cidr > upper) { - newtWinMessage(_("Invalid Prefix"), _("Retry"), - _("Prefix must be between 1 and 32 " - "for IPv4 networks or between 1 and 128 " - "for IPv6 networks")); - } - } -} - -static void ipCallback(newtComponent co, void * dptr) { - int i; - char *buf, *octet; - struct intfconfig_s * data = dptr; - - if (co == data->ipv4Entry) { - /* do we need to guess a netmask for the user? */ - if (data->cidr4 == NULL && data->ipv4 != NULL) { - buf = strdup(data->ipv4); - octet = strtok(buf, "."); - errno = 0; - i = strtol(octet, NULL, 10); - - if ((errno == ERANGE && (i == LONG_MIN || i == LONG_MAX)) || - (errno != 0 && i == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - free(buf); - free(octet); - - if (i >= 0 && i <= 127) - newtEntrySet(data->cidr4Entry, "8", 1); - else if (i >= 128 && i <= 191) - newtEntrySet(data->cidr4Entry, "16", 1); - else if (i >= 192 && i <= 222) - newtEntrySet(data->cidr4Entry, "24", 1); - } - - return; -#ifdef ENABLE_IPV6 - } else if (co == data->ipv6Entry) { - /* users must provide a mask, we can't guess for ipv6 */ - return; -#endif - } -} - -static void setMethodSensitivity(void *dptr, int radio_button_count) { - int i = 0; - - for (i = 0; i < radio_button_count; i++) { - newtCheckboxSetFlags(*((newtComponent *) dptr), NEWT_FLAG_DISABLED, - NEWT_FLAGS_TOGGLE); - dptr += sizeof (newtComponent); - } - - return; -} - -static void v4MethodCallback(newtComponent co, void *dptr) { - setMethodSensitivity(dptr, 2); - return; -} - -#ifdef ENABLE_IPV6 -static void v6MethodCallback(newtComponent co, void *dptr) { - setMethodSensitivity(dptr, 3); - return; -} -#endif - -static void parseEthtoolSettings(struct loaderData_s * loaderData) { - char * option, * buf; - ethtool_duplex duplex = ETHTOOL_DUPLEX_UNSPEC; - ethtool_speed speed = ETHTOOL_SPEED_UNSPEC; - - buf = strdup(loaderData->ethtool); - option = strtok(buf, " "); - while (option) { - if (option[strlen(option) - 1] == '\"') - option[strlen(option) - 1] = '\0'; - if (option[0] == '\"') - option++; - if (!strncmp(option, "duplex", 6)) { - if (!strncmp(option + 7, "full", 4)) - duplex = ETHTOOL_DUPLEX_FULL; - else if (!strncmp(option + 7, "half", 4)) - duplex = ETHTOOL_DUPLEX_HALF; - else - logMessage(WARNING, "Unknown duplex setting: %s", option + 7); - option = strtok(NULL, " "); - } else if (!strncmp("speed", option, 5)) { - if (!strncmp(option + 6, "1000", 4)) - speed = ETHTOOL_SPEED_1000; - else if (!strncmp(option + 6, "100", 3)) - speed = ETHTOOL_SPEED_100; - else if (!strncmp(option + 6, "10", 2)) - speed = ETHTOOL_SPEED_10; - else - logMessage(WARNING, "Unknown speed setting: %s", option + 6); - option = strtok(NULL, " "); - } else { - logMessage(WARNING, "Unknown ethtool setting: %s", option); - } - option = strtok(NULL, " "); - } - setEthtoolSettings(loaderData->netDev, speed, duplex); - free(buf); -} - -int split_ipv6addr_prefix_length(char *str, char **address, char **prefix) { - gchar **elements = g_strsplit(str, "/", 2); - int rc = 0; - - if (elements[0]) { - *address = strdup(elements[0]); - if (elements[1]) { - *prefix = strdup(elements[1]); - } - rc = 1; - } - g_strfreev(elements); - return rc; -} - - -/* given loader data from kickstart, populate network configuration struct */ -void setupIfaceStruct(iface_t * iface, struct loaderData_s * loaderData) { - struct in_addr addr; - struct in6_addr addr6; - char * c; - - memset(&addr, 0, sizeof(addr)); - memset(&addr6, 0, sizeof(addr6)); - - if (loaderData->ethtool) { - parseEthtoolSettings(loaderData); - } - - if (loaderData->netCls_set) { - iface->vendorclass = loaderData->netCls; - } else { - iface->vendorclass = NULL; - } - - if (loaderData->ipinfo_set && loaderData->ipv4 != NULL) { - /* this is iBFT configured device */ - if (!strncmp(loaderData->ipv4, "ibft", 4)) { - iface->ipv4method = IPV4_IBFT_METHOD; - /* this is how we specify dhcp */ - } else if (!strncmp(loaderData->ipv4, "dhcp", 4)) { - iface->dhcptimeout = loaderData->dhcpTimeout; - iface->ipv4method = IPV4_DHCP_METHOD; - } else if (inet_pton(AF_INET, loaderData->ipv4, &addr) >= 1) { - iface->ipaddr.s_addr = addr.s_addr; - iface->ipv4method = IPV4_MANUAL_METHOD; - } else { /* invalid ip information, disable the setting of ip info */ - loaderData->ipinfo_set = 0; - iface->ipv4method = 0; - loaderData->ipv4 = NULL; - } - } - - if (loaderData->netmask != NULL) { - if (inet_pton(AF_INET, loaderData->netmask, &iface->netmask) <= 0) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - } - } - - if (loaderData->gateway != NULL) { - if (inet_pton(AF_INET, loaderData->gateway, &iface->gateway) <= 0) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - } - } - -#ifdef ENABLE_IPV6 - if (loaderData->ipv6info_set && loaderData->ipv6 != NULL) { - if (!strncmp(loaderData->ipv6, "dhcp", 4)) { - iface->ipv6method = IPV6_DHCP_METHOD; - } else if (!strncmp(loaderData->ipv6, "auto", 4)) { - iface->ipv6method = IPV6_AUTO_METHOD; - } else if (inet_pton(AF_INET6, loaderData->ipv6, &addr6) >= 1) { - memcpy(&iface->ip6addr, &addr6, sizeof(struct in6_addr)); - iface->ipv6method = IPV6_MANUAL_METHOD; - - iface->ip6prefix = 0; - if (loaderData->ipv6prefix) { - int prefix; - - errno = 0; - prefix = strtol(loaderData->ipv6prefix, NULL, 10); - if ((errno == ERANGE && (prefix == LONG_MIN || - prefix == LONG_MAX)) || - (errno != 0 && prefix == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - if (prefix > 0 || prefix <= 128) { - iface->ip6prefix = prefix; - } - } - } else { - iface->ipv6method = 0; - loaderData->ipv6info_set = 0; - loaderData->ipv6 = NULL; - } - } - - if (loaderData->gateway6 != NULL) { - if (inet_pton(AF_INET6, loaderData->gateway6, &iface->gateway6) <= 0) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - } - } -#endif - - if (loaderData->dns) { - char * buf; - char ret[INET6_ADDRSTRLEN+1]; - buf = strdup(loaderData->dns); - - /* Scan the dns parameter for multiple comma-separated IP addresses */ - c = strtok(buf, ","); - while ((iface->numdns < MAXNS) && (c != NULL)) { - if (inet_pton(AF_INET, c, &addr) >= 1) { - iface->dns[iface->numdns] = strdup(c); - iface->numdns++; - - if (inet_ntop(AF_INET, &addr, ret, INET_ADDRSTRLEN) == NULL) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, strerror(errno)); - } else { - logMessage(DEBUGLVL, "adding dns4 %s", ret); - c = strtok(NULL, ","); - } - } else if (inet_pton(AF_INET6, c, &addr6) >= 1) { - iface->dns[iface->numdns] = strdup(c); - iface->numdns++; - - if (inet_ntop(AF_INET6, &addr6, ret, INET6_ADDRSTRLEN) == NULL) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, strerror(errno)); - } else { - logMessage(DEBUGLVL, "adding dns6 %s", ret); - c = strtok(NULL, ","); - } - } - } - - - - logMessage(INFO, "dnsservers is %s", loaderData->dns); - } - - if (loaderData->domain) { - logMessage(INFO, "dnsdomains is %s", loaderData->domain); - iface->domain = strdup(loaderData->domain); - } - - if (loaderData->hostname) { - logMessage(INFO, "setting specified hostname of %s", - loaderData->hostname); - iface->hostname = strdup(loaderData->hostname); - } - - if (loaderData->mtu) { - iface->mtu = loaderData->mtu; - } - - if (loaderData->peerid) { - iface->peerid = strdup(loaderData->peerid); - } - - if (loaderData->subchannels) { - iface->subchannels = strdup(loaderData->subchannels); - } - - if (loaderData->ctcprot) { - iface->ctcprot = strdup(loaderData->ctcprot); - } - - if (loaderData->portname) { - iface->portname = strdup(loaderData->portname); - } - - if (loaderData->nettype) { - iface->nettype = strdup(loaderData->nettype); - } - - if (loaderData->ethtool) { - parseEthtoolSettings(loaderData); - } - - if (loaderData->options) { - iface->options = strdup(loaderData->options); - } - - if (loaderData->wepkey) { - if (is_wireless_device(loaderData->netDev)) { - iface->wepkey = strdup(loaderData->wepkey); - } else { - iface->wepkey = NULL; - } - } - - if (loaderData->essid) { - if (is_wireless_device(loaderData->netDev)) { - iface->ssid = strdup(loaderData->essid); - } else { - iface->ssid = NULL; - } - } - - if (loaderData->noDns) { - iface->flags |= IFACE_FLAGS_NO_WRITE_RESOLV_CONF; - } - - iface->dhcptimeout = loaderData->dhcpTimeout; - - if (loaderData->macaddr) { - iface->macaddr = strdup(loaderData->macaddr); - } - - return; -} - -int readNetConfig(char * device, iface_t * iface, - char * dhcpclass, int methodNum) { - int err; - int ret; - int i = 0; - struct netconfopts opts; - struct in_addr addr; - struct intfconfig_s ipcomps; - - /* ipcomps contains the user interface components */ - ipcomps.ipv4 = NULL; - ipcomps.cidr4 = NULL; - ipcomps.gw = NULL; -#ifdef ENABLE_IPV6 - ipcomps.ipv6 = NULL; - ipcomps.cidr6 = NULL; - ipcomps.gw6 = NULL; -#endif - ipcomps.ns = NULL; - - /* init opts */ - opts.ipv4Choice = 0; - opts.v4Method = 0; -#ifdef ENABLE_IPV6 - opts.ipv6Choice = 0; - opts.v6Method = 0; -#endif - - /* JKFIXME: we really need a way to override this and be able to change - * our network config */ - if (!FL_ASKNETWORK(flags) && - ((iface->ipv4method > IPV4_UNUSED_METHOD) || - (iface->ipv6method > IPV4_UNUSED_METHOD))) { - logMessage(INFO, "doing kickstart... setting it up"); - - err = writeEnabledNetInfo(iface); - if (err) { - logMessage(ERROR, "failed to write %s data for %s (%d)", - SYSCONFIG_PATH, iface->device, err); - return LOADER_BACK; - } - - i = wait_for_iface_activation(iface->device); - newtPopWindow(); - - if (i > 0) { - if (FL_CMDLINE(flags)) { - fprintf(stderr, _("There was an error configuring your network " - "interface.")); - fprintf(stderr, _("\nThis cannot be corrected in cmdline mode.\n" - "Halting.\n")); - exit(1); - } - - logMessage(ERROR, "failed to configure network interface"); - iface->ipv4method = IPV4_UNUSED_METHOD; - iface->ipv6method = IPV6_UNUSED_METHOD; - return LOADER_ERROR; - } - - return LOADER_NOOP; - } - - /* dhcp/manual network configuration loop */ - i = 1; - while (i == 1) { - ret = configureTCPIP(device, iface, &opts, methodNum); - - if (ret == LOADER_NOOP) { - /* dhcp selected, proceed */ - i = 0; - } else if (ret == LOADER_OK) { - /* do manual configuration */ - ret = manualNetConfig(device, iface, &ipcomps, &opts); - - if (ret == LOADER_BACK) { - continue; - } else if (ret == LOADER_OK) { - i = 0; - } - } else if (ret == LOADER_BACK) { - return LOADER_BACK; - } - } - - /* calculate any missing IPv4 pieces */ - if (opts.ipv4Choice == '*') { - memset(&addr, 0, sizeof(addr)); - addr.s_addr = (iface->ipaddr.s_addr) & (iface->netmask.s_addr); - - if (iface->broadcast.s_addr == 0) { - iface->broadcast.s_addr = addr.s_addr | ~(iface->netmask.s_addr); - } - } - - /* bring up the interface */ - err = writeEnabledNetInfo(iface); - if (err) { - logMessage(ERROR, "failed to write %s data for %s (%d)", - SYSCONFIG_PATH, iface->device, err); - iface->ipv4method = IPV4_UNUSED_METHOD; - iface->ipv6method = IPV6_UNUSED_METHOD; - return LOADER_BACK; - } - - i = wait_for_iface_activation(iface->device); - newtPopWindow(); - - if (i > 0) { - newtWinMessage(_("Network Error"), _("Retry"), - _("There was an error configuring your network " - "interface.")); - /* Clear out selections to allow for re-entry */ - iface->ipv4method = IPV4_UNUSED_METHOD; - iface->ipv6method = IPV6_UNUSED_METHOD; - return LOADER_ERROR; - } - - return LOADER_OK; -} - -int configureTCPIP(char * device, iface_t * iface, - struct netconfopts * opts, int methodNum) { - int i = 0, z = 0, skipForm = 0, ret; - newtComponent f, okay, back, answer; - newtComponent ipv4Checkbox, v4Method[2]; -#ifdef ENABLE_IPV6 - newtComponent ipv6Checkbox, v6Method[3]; -#endif - newtGrid grid, checkgrid, buttons; - - /* UI WINDOW 1: ask for ipv4 choice, ipv6 choice, and conf methods */ - - /* IPv4 checkbox */ - if (!opts->ipv4Choice) { - if (FL_NOIPV4(flags) && !FL_IP_PARAM(flags)) - opts->ipv4Choice = ' '; - else - opts->ipv4Choice = '*'; - } - - ipv4Checkbox = newtCheckbox(-1, -1, _("Enable IPv4 support"), - opts->ipv4Choice, NULL, &(opts->ipv4Choice)); - v4Method[0] = newtRadiobutton(-1, -1, DHCP_METHOD_STR, (opts->v4Method == 0), NULL); - v4Method[1] = newtRadiobutton(-1, -1, MANUAL_METHOD_STR, (opts->v4Method == 1), v4Method[0]); - -#ifdef ENABLE_IPV6 - /* IPv6 checkbox */ - if (!opts->ipv6Choice) { - if (FL_NOIPV6(flags) && !FL_IPV6_PARAM(flags)) - opts->ipv6Choice = ' '; - else - opts->ipv6Choice = '*'; - } - - ipv6Checkbox = newtCheckbox(-1, -1, _("Enable IPv6 support"), - opts->ipv6Choice, NULL, &(opts->ipv6Choice)); - v6Method[0] = newtRadiobutton(-1, -1, AUTO_METHOD_STR, (opts->v6Method == 0), NULL); - v6Method[1] = newtRadiobutton(-1, -1, DHCPV6_METHOD_STR, (opts->v6Method == 1), v6Method[0]); - v6Method[2] = newtRadiobutton(-1, -1, MANUAL_METHOD_STR, (opts->v6Method == 2), v6Method[1]); -#endif - - /* button bar at the bottom of the window */ - buttons = newtButtonBar(_("OK"), &okay, _("Back"), &back, NULL); - - /* checkgrid contains the toggle options for net configuration */ -#ifdef ENABLE_IPV6 - checkgrid = newtCreateGrid(1, 8); -#else - checkgrid = newtCreateGrid(1, 3); -#endif - - newtGridSetField(checkgrid, 0, 0, NEWT_GRID_COMPONENT, ipv4Checkbox, - 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - for (i = 1; i < 3; i++) - newtGridSetField(checkgrid, 0, i, NEWT_GRID_COMPONENT, v4Method[i-1], - 7, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - -#ifdef ENABLE_IPV6 - newtGridSetField(checkgrid, 0, 4, NEWT_GRID_COMPONENT, ipv6Checkbox, - 0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0); - for (i = 5; i < 8; i++) - newtGridSetField(checkgrid, 0, i, NEWT_GRID_COMPONENT, v6Method[i-5], - 7, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); -#endif - - /* main window layout */ - grid = newtCreateGrid(1, 2); - newtGridSetField(grid, 0, 0, NEWT_GRID_SUBGRID, checkgrid, - 0, 0, 0, 1, 0, 0); - newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, buttons, - 0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX); - - f = newtForm(NULL, NULL, 0); - newtGridAddComponentsToForm(grid, f, 1); - newtGridWrappedWindow(grid, _("Configure TCP/IP")); - newtGridFree(grid, 1); - - /* callbacks */ - newtComponentAddCallback(ipv4Checkbox, v4MethodCallback, &v4Method); -#ifdef ENABLE_IPV6 - newtComponentAddCallback(ipv6Checkbox, v6MethodCallback, &v6Method); -#endif - - /* match radio button sensitivity to initial checkbox choices */ - if (opts->ipv4Choice == ' ') - setMethodSensitivity(&v4Method, 2); - -#ifdef ENABLE_IPV6 - if (opts->ipv6Choice == ' ') - setMethodSensitivity(&v6Method, 3); -#endif - -#ifdef ENABLE_IPV6 - /* If the user provided any of the following boot paramters, skip - * prompting for network configuration information: - * ip=<val> ipv6=<val> - * noipv4 noipv6 - * ip=<val> noipv6 - * ipv6=<val> noipv4 - */ - if ((iface->ipv4method > IPV4_UNUSED_METHOD && iface->ipv6method > IPV6_UNUSED_METHOD) || /* both */ - (iface->ipv4method > IPV4_UNUSED_METHOD && FL_NOIPV6(flags)) || /* only ipv4 */ - (FL_NOIPV4(flags) && iface->ipv6method > IPV6_UNUSED_METHOD) || /* only ipv6 */ - (FL_NOIPV4(flags) && FL_NOIPV6(flags))) { /* neither ipv4 or ipv6 -- what else? */ - skipForm = 1; - newtPopWindow(); - logMessage(DEBUGLVL, "in configureTCPIP(), detected network boot args, skipping form"); - } -#else - if (iface->ipv4method > IPV4_UNUSED_METHOD || FL_NOIPV4(flags)) { - skipForm = 1; - newtPopWindow(); - logMessage(DEBUGLVL, "in configureTCPIP(), detected network boot args, skipping form"); - } -#endif - - /* run the form */ - do { - if (!skipForm) { - answer = newtRunForm(f); - - if (answer == back) { - newtFormDestroy(f); - newtPopWindow(); - return LOADER_BACK; - } - - /* need at least one stack */ -#ifdef ENABLE_IPV6 - if (opts->ipv4Choice == ' ' && opts->ipv6Choice == ' ') { -#else - if (opts->ipv4Choice == ' ') { -#endif - newtWinMessage(_("Missing Protocol"), _("Retry"), - _("You must select at least one protocol (IPv4 " - "or IPv6).")); - continue; - } - - /* NFS only works over IPv4 */ - if (opts->ipv4Choice == ' ' && methodNum == METHOD_NFS) { - newtWinMessage(_("IPv4 Needed for NFS"), _("Retry"), - _("NFS installation method requires IPv4 support.")); - continue; - } - } - - /* what TCP/IP stacks do we use? what conf methods? */ - if (opts->ipv4Choice == '*') { - flags &= ~LOADER_FLAGS_NOIPV4; - for (z = IPV4_FIRST_METHOD; z <= IPV4_LAST_METHOD; z++) - if (newtRadioGetCurrent(v4Method[0]) == v4Method[z-1]) - iface->ipv4method = z; - } else { - flags |= LOADER_FLAGS_NOIPV4; - } - -#ifdef ENABLE_IPV6 - if (opts->ipv6Choice == '*') { - flags &= ~LOADER_FLAGS_NOIPV6; - for (z = IPV6_FIRST_METHOD; z <= IPV6_LAST_METHOD; z++) - if (newtRadioGetCurrent(v6Method[0]) == v6Method[z-1]) - iface->ipv6method = z; - } else { - flags |= LOADER_FLAGS_NOIPV6; - } -#endif - - /* update opts keeping method choice for UI */ - for (z = IPV4_FIRST_METHOD; z <= IPV4_LAST_METHOD; z++) { - if (newtRadioGetCurrent(v4Method[0]) == v4Method[z-1]) - opts->v4Method = z-1; - } -#ifdef ENABLE_IPV6 - for (z = IPV6_FIRST_METHOD; z <= IPV6_LAST_METHOD; z++) { - if (newtRadioGetCurrent(v6Method[0]) == v6Method[z-1]) - opts->v6Method = z-1; - } -#endif - - /* do interface configuration (call DHCP here, or return for manual) */ -#ifdef ENABLE_IPV6 - if ((!FL_NOIPV4(flags) && iface->ipv4method == IPV4_MANUAL_METHOD) || - (!FL_NOIPV6(flags) && iface->ipv6method == IPV6_MANUAL_METHOD)) { -#else - if (!FL_NOIPV4(flags) && iface->ipv4method == IPV4_MANUAL_METHOD) { -#endif - /* manual IP configuration selected */ - ret = LOADER_OK; - i = 1; -#ifdef ENABLE_IPV6 - } else if (!FL_NOIPV4(flags) || !FL_NOIPV6(flags)) { -#else - } else if (!FL_NOIPV4(flags)) { -#endif - /* only auto configuration selected, exit the loop */ - ret = LOADER_NOOP; - i = 1; - } - } while (i != 1); - - newtFormDestroy(f); - newtPopWindow(); - return ret; -} - -int manualNetConfig(char * device, iface_t * iface, - struct intfconfig_s * ipcomps, struct netconfopts * opts) { - int i, rows, pos, cidr, have[2], stack[2]; - char *buf = NULL; - char ret[48]; -#ifdef ENABLE_IPV6 - int prefix; -#endif - struct in_addr *tmpaddr = NULL; - newtComponent f, okay, back, answer; - newtGrid egrid = NULL; - newtGrid qgrid = NULL; -#ifdef ENABLE_IPV6 - newtGrid rgrid = NULL; -#endif - newtGrid buttons, grid; - newtComponent text = NULL; - - memset(ret, '\0', INET6_ADDRSTRLEN+1); - - /* so we don't perform this test over and over */ - stack[IPV4] = opts->ipv4Choice == '*' && - iface->ipv4method == IPV4_MANUAL_METHOD; -#ifdef ENABLE_IPV6 - stack[IPV6] = opts->ipv6Choice == '*' && - iface->ipv6method == IPV6_MANUAL_METHOD; -#endif - - /* UI WINDOW 2 (optional): manual IP config for non-DHCP installs */ - rows = 2; - for (i = 0; i < 2; i++) { - if (stack[i]) { - rows++; - } - } - egrid = newtCreateGrid(4, rows); - - pos = 0; - - /* IPv4 entry items */ - if (stack[IPV4]) { - newtGridSetField(egrid, 0, pos, NEWT_GRID_COMPONENT, - newtLabel(-1, -1, _("IPv4 address:")), - 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - - ipcomps->ipv4Entry = newtEntry(-1, -1, NULL, 16, &ipcomps->ipv4, 0); - ipcomps->cidr4Entry = newtEntry(-1, -1, NULL, 16, &ipcomps->cidr4, 0); - - /* use a nested grid for ipv4 addr & netmask */ - qgrid = newtCreateGrid(3, 1); - - newtGridSetField(qgrid, 0, 0, NEWT_GRID_COMPONENT, - ipcomps->ipv4Entry, 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(qgrid, 1, 0, NEWT_GRID_COMPONENT, - newtLabel(-1, -1, _("/")), - 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(qgrid, 2, 0, NEWT_GRID_COMPONENT, - ipcomps->cidr4Entry, 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - - newtGridSetField(egrid, 1, pos, NEWT_GRID_SUBGRID, qgrid, - 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - - newtComponentAddCallback(ipcomps->ipv4Entry, ipCallback, ipcomps); - newtComponentAddCallback(ipcomps->cidr4Entry, cidrCallback, ipcomps); - - /* populate fields if we have data already */ - if (iface_have_in_addr(&iface->ipaddr)) { - if (inet_ntop(AF_INET, &iface->ipaddr, ret, - INET_ADDRSTRLEN) == NULL) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - } - } - - if (*ret) { - newtEntrySet(ipcomps->ipv4Entry, ret, 1); - } - - if (iface_have_in_addr(&iface->netmask)) { - if (inet_ntop(AF_INET, &iface->netmask, ret, - INET_ADDRSTRLEN) == NULL) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - } - } - - if (*ret) { - newtEntrySet(ipcomps->cidr4Entry, ret, 1); - } - - pos++; - } - -#ifdef ENABLE_IPV6 - /* IPv6 entry items */ - if (stack[IPV6]) { - newtGridSetField(egrid, 0, pos, NEWT_GRID_COMPONENT, - newtLabel(-1, -1, _("IPv6 address:")), - 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - - ipcomps->ipv6Entry = newtEntry(-1, -1, NULL, 41, &ipcomps->ipv6, 0); - ipcomps->cidr6Entry = newtEntry(-1, -1, NULL, 4, &ipcomps->cidr6, 0); - - /* use a nested grid for ipv6 addr & netmask */ - rgrid = newtCreateGrid(3, 1); - - newtGridSetField(rgrid, 0, 0, NEWT_GRID_COMPONENT, - ipcomps->ipv6Entry, 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(rgrid, 1, 0, NEWT_GRID_COMPONENT, - newtLabel(-1, -1, _("/")), - 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(rgrid, 2, 0, NEWT_GRID_COMPONENT, - ipcomps->cidr6Entry, 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - - newtGridSetField(egrid, 1, pos, NEWT_GRID_SUBGRID, rgrid, - 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - - newtComponentAddCallback(ipcomps->ipv6Entry, ipCallback, ipcomps); - newtComponentAddCallback(ipcomps->cidr6Entry, cidrCallback, ipcomps); - - /* populate fields if we have data already */ - if (iface_have_in6_addr(&iface->ip6addr)) { - if (inet_ntop(AF_INET6, &iface->ip6addr, ret, - INET6_ADDRSTRLEN) == NULL) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - } - } - - if (*ret) { - newtEntrySet(ipcomps->ipv6Entry, ret, 1); - } - - if (iface->ip6prefix) { - if (asprintf(&buf, "%d", iface->ip6prefix) == -1) { - buf = NULL; - } - } else if (iface->ip6prefix) { - if (asprintf(&buf, "%d", iface->ip6prefix) == -1) { - buf = NULL; - } - } - - if (buf != NULL) { - newtEntrySet(ipcomps->cidr6Entry, buf, 1); - free(buf); - } - - pos++; - } -#endif - - /* common entry items */ - ipcomps->gwEntry = newtEntry(-1, -1, NULL, 41, &ipcomps->gw, 0); - ipcomps->nsEntry = newtEntry(-1, -1, NULL, 41, &ipcomps->ns, 0); - - newtGridSetField(egrid, 0, pos, NEWT_GRID_COMPONENT, - newtLabel(-1, -1, _("Gateway:")), - 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(egrid, 1, pos, NEWT_GRID_COMPONENT, - ipcomps->gwEntry, 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - - pos++; - - newtGridSetField(egrid, 0, pos, NEWT_GRID_COMPONENT, - newtLabel(-1, -1, _("Name Server:")), - 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(egrid, 1, pos, NEWT_GRID_COMPONENT, - ipcomps->nsEntry, 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); - - if (iface_have_in_addr(&iface->gateway)) { - if (inet_ntop(AF_INET, &iface->gateway, ret, - INET_ADDRSTRLEN) == NULL) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - } else { - newtEntrySet(ipcomps->gwEntry, ret, 1); - } - } else if (iface_have_in6_addr(&iface->gateway6)) { - if (inet_ntop(AF_INET6, &iface->gateway6, ret, - INET6_ADDRSTRLEN) == NULL) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - } else { - newtEntrySet(ipcomps->gwEntry, ret, 1); - } - } - - if (iface->numdns) { - newtEntrySet(ipcomps->nsEntry, iface->dns[0], 1); - } else if (iface->numdns) { - newtEntrySet(ipcomps->nsEntry, iface->dns[0], 1); - } - - newtComponentAddCallback(ipcomps->gwEntry, ipCallback, ipcomps); - newtComponentAddCallback(ipcomps->nsEntry, ipCallback, ipcomps); - - /* button bar at the bottom of the window */ - buttons = newtButtonBar(_("OK"), &okay, _("Back"), &back, NULL); - - /* main window layout */ - grid = newtCreateGrid(1, 3); - - checked_asprintf(&buf, - _("Enter the IPv4 and/or the IPv6 address and prefix " - "(address / prefix). For IPv4, the dotted-quad " - "netmask or the CIDR-style prefix are acceptable. " - "The gateway and name server fields must be valid IPv4 " - "or IPv6 addresses.")); - - text = newtTextboxReflowed(-1, -1, buf, 52, 0, 10, 0); - - newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text, - 0, 0, 0, 1, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, egrid, - 0, 0, 0, 1, NEWT_ANCHOR_LEFT, 0); - newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons, - 0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX); - - f = newtForm(NULL, NULL, 0); - newtGridAddComponentsToForm(grid, f, 1); - newtGridWrappedWindow(grid, _("Manual TCP/IP Configuration")); - newtGridFree(grid, 1); - - have[IPV4] = 0; - have[IPV6] = 0; - - for (i = IPV4; i <= IPV6; i++) { - if (!stack[i]) { - have[i] = 2; - } - } - - /* run the form */ - while ((have[IPV4] != 2) || (have[IPV6] != 2)) { - answer = newtRunForm(f); - - /* collect IPv4 data */ - if (stack[IPV4]) { - if (ipcomps->ipv4) { - if (inet_pton(AF_INET, ipcomps->ipv4, &iface->ipaddr) <= 0) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - } else { - have[IPV4]++; - } - } - - if (ipcomps->cidr4) { - if (inet_pton(AF_INET, ipcomps->cidr4, &iface->netmask) >= 1) { - have[IPV4]++; - } else { - errno = 0; - cidr = strtol(ipcomps->cidr4, NULL, 10); - - if ((errno == ERANGE && (cidr == LONG_MIN || - cidr == LONG_MAX)) || - (errno != 0 && cidr == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - if (cidr >= 1 && cidr <= 32) { - tmpaddr = iface_prefix2netmask(cidr); - if (tmpaddr != NULL) { - memcpy(&iface->netmask, tmpaddr, - sizeof(struct in_addr)); - have[IPV4]++; - } else { - iface->netmask.s_addr = 0; - } - } - } - } - } - -#ifdef ENABLE_IPV6 - /* collect IPv6 data */ - if (stack[IPV6]) { - if (ipcomps->ipv6) { - if (inet_pton(AF_INET6, ipcomps->ipv6, &iface->ip6addr) <= 0) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - } else { - have[IPV6]++; - } - } - - if (ipcomps->cidr6) { - errno = 0; - prefix = strtol(ipcomps->cidr6, NULL, 10); - - if ((errno == ERANGE && (prefix == LONG_MIN || - prefix == LONG_MAX)) || - (errno != 0 && prefix == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - if (prefix > 0 || prefix <= 128) { - iface->ip6prefix = prefix; - have[IPV6]++; - } - } - } -#endif - - /* collect common network settings */ - if (ipcomps->gw) { - if (inet_pton(AF_INET, ipcomps->gw, &iface->gateway) <= 0) { - memset(&iface->gateway, 0, sizeof(iface->gateway)); - - if (inet_pton(AF_INET6, ipcomps->gw, &iface->gateway6) <= 0) { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - memset(&iface->gateway6, 0, sizeof(iface->gateway6)); - } - } - } - - /* gather nameservers */ - if (ipcomps->ns) { -#ifdef ENABLE_IPV6 - if (isValidIPv4Address(ipcomps->ns) || - isValidIPv6Address(ipcomps->ns)) { -#else - if (isValidIPv4Address(ipcomps->ns)) { -#endif - iface->dns[0] = strdup(ipcomps->ns); - if (iface->numdns < 1) - iface->numdns = 1; - } - } - - /* user selected back, but we've saved what they entered already */ - if (answer == back) { - newtFormDestroy(f); - newtPopWindow(); - free(buf); - return LOADER_BACK; - } - - /* we might be done now */ - if (stack[IPV4] && have[IPV4] != 2) { - have[IPV4] = 0; - newtWinMessage(_("Missing Information"), _("Retry"), - _("You must enter both a valid IPv4 address and a " - "network mask or CIDR prefix.")); - } - -#ifdef ENABLE_IPV6 - if (stack[IPV6] && have[IPV6] != 2) { - have[IPV6] = 0; - newtWinMessage(_("Missing Information"), _("Retry"), - _("You must enter both a valid IPv6 address and a " - "CIDR prefix.")); - } -#endif - - strcpy(iface->device, device); - } - - free(buf); - newtFormDestroy(f); - newtPopWindow(); - - return LOADER_OK; -} - -/* - * By default, we disable all network interfaces and then only - * bring up the ones the user wants. - */ -int writeDisabledNetInfo(void) { - int i = 0, rc; - struct device **devs = NULL; - - devs = getDevices(DEVICE_NETWORK); - - if (devs == NULL) { - return 1; - } - - for (i = 0; devs[i]; i++) { - /* remove dhclient-DEVICE.conf if we have it */ - if ((rc = removeDhclientConfFile(devs[i]->device)) != 0) { - return rc; - } - /* write disabled ifcfg-DEVICE file */ - if (!is_wireless_device(devs[i]->device)) - if ((rc = writeDisabledIfcfgFile(devs[i]->device)) != 0) - return rc; - } - return 0; -} - -int removeIfcfgFile(char *device) { - char *fname = NULL; - checked_asprintf(&fname, "%s/ifcfg-%s", - NETWORK_SCRIPTS_PATH, - device); - - if (!access(fname, R_OK|W_OK)) { - if (unlink(fname)) { - logMessage(ERROR, "error removing %s", fname); - } - } - - free(fname); - return 0; -} - -int removeDhclientConfFile(char *device) { - char *ofile = NULL; - if (asprintf(&ofile, "/etc/dhcp/dhclient-%s.conf", device) == -1) { - return 5; - } - - if (!access(ofile, R_OK|W_OK)) { - if (unlink(ofile)) { - logMessage(ERROR, "error removing %s", ofile); - } - } - - free(ofile); - return 0; -} - -int writeDisabledIfcfgFile(char *device) { - char *ofile = NULL; - char *nfile = NULL; - FILE *fp = NULL; - - checked_asprintf(&ofile, "%s/.ifcfg-%s", - NETWORK_SCRIPTS_PATH, - device); - checked_asprintf(&nfile, "%s/ifcfg-%s", - NETWORK_SCRIPTS_PATH, - device); - - if ((fp = fopen(ofile, "w")) == NULL) { - free(ofile); - return 2; - } - fprintf(fp, "DEVICE=%s\n", device); - fprintf(fp, "HWADDR=%s\n", iface_mac2str(device)); - fprintf(fp, "ONBOOT=no\n"); - fprintf(fp, "NM_CONTROLLED=no\n"); - /* default for network service, NM assumes it */ - fprintf(fp, "BOOTPROTO=dhcp\n"); - - if (fclose(fp) == EOF) { - return 3; - } - - if (rename(ofile, nfile) == -1) { - free(ofile); - free(nfile); - return 4; - } - - if (ofile) { - free(ofile); - ofile = NULL; - } - - if (nfile) { - free(nfile); - nfile = NULL; - } - - return 0; -} - -/* - * Write out network interface control files: - * /etc/sysconfig/network-scripts/ifcfg-DEVICE - * /etc/sysconfig/network - */ -int writeEnabledNetInfo(iface_t *iface) { - int i = 0; - mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - FILE *fp = NULL; - char buf[INET6_ADDRSTRLEN+1]; - char *ofile = NULL; - char *nfile = NULL; - struct utsname kv; - - memset(&buf, '\0', sizeof(buf)); - - if ((mkdir(NETWORK_SCRIPTS_PATH, mode) == -1) && (errno != EEXIST)) { - return 16; - } - - /* write vendor class */ - if (iface->vendorclass == NULL) { - if (uname(&kv) == -1) { - iface->vendorclass = "anaconda"; - } else { - if (asprintf(&iface->vendorclass, "anaconda-%s %s %s", - kv.sysname, kv.release, kv.machine) == -1 ) { - return 20; - } - } - } - - if (asprintf(&ofile, "/etc/dhcp/dhclient-%s.conf", iface->device) == -1) { - return 17; - } - - if ((fp = fopen(ofile, "w")) == NULL) { - free(ofile); - return 18; - } - - fprintf(fp, "send vendor-class-identifier \"%s\";\n", - iface->vendorclass); - - if (fclose(fp) == EOF) { - free(ofile); - return 19; - } - - if (ofile) { - free(ofile); - ofile = NULL; - } - - /* write out new ifcfg-DEVICE file */ - if (asprintf(&ofile, "%s/.ifcfg-%s", - NETWORK_SCRIPTS_PATH, iface->device) == -1) { - return 1; - } - - if (asprintf(&nfile, "%s/ifcfg-%s", - NETWORK_SCRIPTS_PATH, iface->device) == -1) { - return 13; - } - - if ((fp = fopen(ofile, "w")) == NULL) { - free(ofile); - return 2; - } - - fprintf(fp, "DEVICE=%s\n", iface->device); -#if !defined(__s390__) && !defined(__s390x__) - fprintf(fp, "HWADDR=%s\n", iface_mac2str(iface->device)); -#endif - fprintf(fp, "ONBOOT=yes\n"); - - if (!FL_NOIPV4(flags)) { - if (iface->ipv4method == IPV4_IBFT_METHOD) { - fprintf(fp, "BOOTPROTO=ibft\n"); - } else if (iface->ipv4method == IPV4_DHCP_METHOD) { - fprintf(fp, "BOOTPROTO=dhcp\n"); - } else if (iface->ipv4method == IPV4_MANUAL_METHOD) { - fprintf(fp, "BOOTPROTO=static\n"); - - if (iface_have_in_addr(&iface->ipaddr)) { - if (inet_ntop(AF_INET, &iface->ipaddr, buf, - INET_ADDRSTRLEN) == NULL) { - free(ofile); - fclose(fp); - return 3; - } - - fprintf(fp, "IPADDR=%s\n", buf); - } - - if (iface_have_in_addr(&iface->netmask)) { - if (inet_ntop(AF_INET, &iface->netmask, buf, - INET_ADDRSTRLEN) == NULL) { - free(ofile); - fclose(fp); - return 4; - } - - fprintf(fp, "NETMASK=%s\n", buf); - } - - if (iface_have_in_addr(&iface->broadcast)) { - if (inet_ntop(AF_INET, &iface->broadcast, buf, - INET_ADDRSTRLEN) == NULL) { - free(ofile); - fclose(fp); - return 5; - } - - fprintf(fp, "BROADCAST=%s\n", buf); - } - - if (iface_have_in_addr(&iface->gateway)) { - if (inet_ntop(AF_INET, &iface->gateway, buf, - INET_ADDRSTRLEN) == NULL) { - free(ofile); - fclose(fp); - return 6; - } - - fprintf(fp, "GATEWAY=%s\n", buf); - } - } - } - -#ifdef ENABLE_IPV6 - if (!FL_NOIPV6(flags)) { - if (iface->ipv6method == IPV6_AUTO_METHOD || - iface->ipv6method == IPV6_DHCP_METHOD || - iface->ipv6method == IPV6_MANUAL_METHOD) { - fprintf(fp, "IPV6INIT=yes\n"); - - if (iface->ipv6method == IPV6_AUTO_METHOD) { - fprintf(fp, "IPV6_AUTOCONF=yes\n"); - } else if (iface->ipv6method == IPV6_DHCP_METHOD) { - fprintf(fp, "IPV6_AUTOCONF=no\n"); - fprintf(fp, "DHCPV6C=yes\n"); - } else if (iface->ipv6method == IPV6_MANUAL_METHOD) { - fprintf(fp, "IPV6_AUTOCONF=no\n"); - if (iface_have_in6_addr(&iface->ip6addr)) { - if (inet_ntop(AF_INET6, &iface->ip6addr, buf, - INET6_ADDRSTRLEN) == NULL) { - free(ofile); - fclose(fp); - return 7; - } - - if (iface->ip6prefix) { - fprintf(fp, "IPV6ADDR=%s/%d\n", buf, iface->ip6prefix); - } else { - fprintf(fp, "IPV6ADDR=%s\n", buf); - } - } - } - - if (iface_have_in6_addr(&iface->gateway6)) { - if (inet_ntop(AF_INET6, &iface->gateway6, buf, - INET6_ADDRSTRLEN) == NULL) { - free(ofile); - fclose(fp); - return 8; - } - - fprintf(fp, "IPV6_DEFAULTGW=%s\n", buf); - } - } - } -#endif - - if (iface->numdns > 0) { - for (i = 0; i < iface->numdns; i++) { - fprintf(fp, "DNS%d=%s\n", i+1, iface->dns[i]); - } - } - - if (iface->hostname && iface->ipv4method == IPV4_DHCP_METHOD) { - fprintf(fp, "DHCP_HOSTNAME=%s\n", iface->hostname); - } - - if (iface->domain) { - fprintf(fp, "DOMAIN=\"%s\"\n", iface->domain); - } - - if (iface->mtu) { - fprintf(fp, "MTU=%d\n", iface->mtu); - } - - if (iface->peerid) { - fprintf(fp, "PEERID=%s\n", iface->peerid); - } - - if (iface->subchannels) { - fprintf(fp, "SUBCHANNELS=%s\n", iface->subchannels); - } - - if (iface->portname) { - fprintf(fp, "PORTNAME=%s\n", iface->portname); - } - - if (iface->nettype) { - fprintf(fp, "NETTYPE=%s\n", iface->nettype); - } - - if (iface->ctcprot) { - fprintf(fp, "CTCPROT=%s\n", iface->ctcprot); - } - - if (iface->options) { - fprintf(fp, "OPTIONS=\'%s\'\n", iface->options); - } - - if (iface->macaddr) { - fprintf(fp, "MACADDR=%s\n", iface->macaddr); - } - - if (!iface->defroute) { - fprintf(fp, "DEFROUTE=no\n"); - logMessage(INFO, "not setting default route via %s", iface->device); - } - - if (fclose(fp) == EOF) { - free(ofile); - free(nfile); - return 8; - } - - if (rename(ofile, nfile) == -1) { - free(ofile); - free(nfile); - return 14; - } - - if (ofile) { - free(ofile); - } - - if (nfile) { - free(nfile); - } - - return 0; -} - -/* if multiple interfaces get one to use from user. */ -/* NOTE - uses kickstart data available in loaderData */ -int chooseNetworkInterface(struct loaderData_s * loaderData) { - int i, rc, ask, idrc, secs, deviceNums = 0, deviceNum, foundDev = 0; - unsigned int max = 40; - char **devices; - char **deviceNames; - char *ksMacAddr = NULL, *seconds = strdup("10"), *idstr = NULL; - struct device **devs; - int lookForLink = 0; - struct newtWinEntry entry[] = {{N_("Seconds:"), (char **) &seconds, 0}, - {NULL, NULL, 0 }}; - extern int num_link_checks; - - devs = getDevices(DEVICE_NETWORK); - if (!devs) { - logMessage(ERROR, "no network devices in choose network device!"); - return LOADER_ERROR; - } - - for (i = 0; devs[i]; i++); - - devices = alloca((i + 1) * sizeof(*devices)); - deviceNames = alloca((i + 1) * sizeof(*devices)); - if (loaderData->netDev && (loaderData->netDev_set) == 1) { - if ((loaderData->bootIf && (loaderData->bootIf_set) == 1) && - !strcasecmp(loaderData->netDev, "bootif")) { - ksMacAddr = g_ascii_strup(loaderData->bootIf, -1); - } else { - ksMacAddr = g_ascii_strup(loaderData->netDev, -1); - } - } - - for (i = 0; devs[i]; i++) { - if (!devs[i]->device) - continue; - - if (devs[i]->description) { - deviceNames[deviceNums] = alloca(strlen(devs[i]->device) + - strlen(devs[i]->description) + 4); - sprintf(deviceNames[deviceNums],"%s - %.50s", - devs[i]->device, devs[i]->description); - - if (strlen(deviceNames[deviceNums]) > max) - max = strlen(deviceNames[deviceNums]); - - devices[deviceNums] = devs[i]->device; - } else { - devices[deviceNums] = devs[i]->device; - deviceNames[deviceNums] = devs[i]->device; - } - - deviceNums++; - - /* this device has been set and we don't really need to ask - * about it again... */ - if (loaderData->netDev && (loaderData->netDev_set == 1)) { - if (!strcmp(loaderData->netDev, devs[i]->device)) { - foundDev = 1; - } else if (ksMacAddr != NULL) { - /* maybe it's a mac address */ - char *devmacaddr = iface_mac2str(devs[i]->device); - - if ((devmacaddr != NULL) && !strcmp(ksMacAddr, devmacaddr)) { - foundDev = 1; - free(loaderData->netDev); - loaderData->netDev = devs[i]->device; - if (devmacaddr != NULL) - free(devmacaddr); - break; - } - - if (devmacaddr != NULL) - free(devmacaddr); - } - } - } - - if (ksMacAddr) - free(ksMacAddr); - if (foundDev == 1) - return LOADER_NOOP; - - devices[deviceNums] = NULL; - deviceNames[deviceNums] = NULL; - qsort(devices, deviceNums, sizeof(*devices), simpleStringCmp); - qsort(deviceNames, deviceNums, sizeof(*devices), simpleStringCmp); - - /* ASSERT: we should *ALWAYS* have a network device when we get here */ - if (!deviceNums) { - logMessage(CRITICAL, "no network device in chooseNetworkInterface"); - return LOADER_ERROR; - } - - /* If there is iBFT table and ksdevice doesn't say otherwise, use it */ - while (!loaderData->netDev_set || !strcmp(loaderData->netDev, "ibft")) { - char *devmacaddr = NULL; - char *ibftmacaddr = ""; - - /* get MAC from the iBFT table */ - if (!(ibftmacaddr = ibft_iface_mac())) { /* iBFT not present or error */ - logMessage(INFO, "No iBFT table detected."); - break; - } - - logMessage(INFO, "looking for iBFT configured device %s with link", - ibftmacaddr); - - for (i = 0; devs[i]; i++) { - if (!devs[i]->device) - continue; - - devmacaddr = iface_mac2str(devs[i]->device); - - if(!strcasecmp(devmacaddr, ibftmacaddr)){ - logMessage(INFO, - "%s has the right MAC (%s), checking for link", - devs[i]->device, devmacaddr); - free(devmacaddr); - - /* wait for the link */ - for (rc = 0; rc < num_link_checks; rc++) { - if (get_link_status(devs[i]->device) == 0) { - logMessage(INFO, "%s still has no link, waiting", devs[i]->device); - sleep(1); - } else { - lookForLink = 0; - loaderData->netDev = devs[i]->device; - loaderData->netDev_set = 1; - logMessage(INFO, "%s has link, using it", devs[i]->device); - - /* set the IP method to ibft if not requested differently */ - if (loaderData->ipv4 == NULL) { - loaderData->ipv4 = strdup("ibft"); - loaderData->ipinfo_set = 1; - logMessage(INFO, - "%s will be configured using iBFT values", - devices[i]); - } - - return LOADER_NOOP; - } - } - - logMessage(INFO, "%s has no link, skipping it", devices[i]); - - break; - } else { - free(devmacaddr); - } - } - - break; - } - - if ((loaderData->netDev && (loaderData->netDev_set == 1)) && - !strcmp(loaderData->netDev, "link")) { - lookForLink = 1; - } - - if (lookForLink) { - logMessage(INFO, "looking for first netDev with link"); - - for (rc = 0; rc < num_link_checks; rc++) { - for (i = 0; i < deviceNums; i++) { - if (get_link_status(devices[i]) == 1) { - loaderData->netDev = devices[i]; - logMessage(INFO, "%s has link, using it", devices[i]); - return LOADER_NOOP; - } - } - - sleep(1); - } - - logMessage(WARNING, - "wanted netdev with link, but none present. prompting"); - } - - /* JKFIXME: if we only have one interface and it doesn't have link, - * do we go ahead? */ - if (deviceNums == 1) { - logMessage(INFO, "only have one network device: %s", devices[0]); - loaderData->netDev = devices[0]; - loaderData->netDev_set = 1; - return LOADER_NOOP; - } - - if (FL_CMDLINE(flags)) { - fprintf(stderr, "No way to determine which NIC to use, and cannot " - "prompt in cmdline\nmode. Halting.\n"); - fprintf(stderr, "Please use the ksdevice= parameter to specify the " - "device name (e.g., eth0)\n or the MAC address of " - "the NIC to use for installation.\n"); - exit(1); - } - - startNewt(); - - if (max > 70) - max = 70; - - /* JKFIXME: should display link status */ - deviceNum = 0; - ask = 1; - while (ask) { - rc = newtWinMenu(_("Networking Device"), - _("You have multiple network devices on this system. " - "Which would you like to install through?"), - max, 10, 10, - deviceNums < 6 ? deviceNums : 6, deviceNames, - &deviceNum, _("OK"), _("Identify"), _("Back"), NULL); - - if (rc == 2) { - if (!devices[deviceNum]) { - logMessage(ERROR, "NIC %d contains no device name", deviceNum); - continue; - } - - checked_asprintf(&idstr, "%s %s %s", - _("You can identify the physical port for"), - devices[deviceNum], - _("by flashing the LED lights for a number of " - "seconds. Enter a number between 1 and 30 to " - "set the duration to flash the LED port " - "lights.")); - - i = 1; - while (i) { - idrc = newtWinEntries(_("Identify NIC"), idstr, 50, 5, 15, 24, - entry, _("OK"), _("Back"), NULL); - - if (idrc == 0 || idrc == 1) { - errno = 0; - secs = strtol((const char *) seconds, NULL, 10); - if (errno == EINVAL || errno == ERANGE) { - logMessage(ERROR, "strtol() failure in %s: %m", - __func__); - continue; - } - - if (secs <=0 || secs > 300) { - newtWinMessage(_("Invalid Duration"), _("OK"), - _("You must enter the number of " - "seconds as an integer between 1 " - "and 30.")); - continue; - } - - idrc = 41 + strlen(devices[deviceNum]); - if (secs > 9) { - idrc += 1; - } - - winStatus(idrc, 3, NULL, - _("Flashing %s port lights for %d seconds."), - devices[deviceNum], secs); - - if (identifyNIC(devices[deviceNum], secs)) { - logMessage(ERROR, - "error during physical NIC identification"); - } - - newtPopWindow(); - i = 0; - } else if (idrc == 2) { - i = 0; - } - } - } else if (rc == 3) { - ask = 0; - return LOADER_BACK; - } else { - ask = 0; - } - } - - loaderData->netDev = devices[deviceNum]; - return LOADER_OK; -} - -/* JKFIXME: bad name. this function brings up networking early on a - * kickstart install so that we can do things like grab the ks.cfg from - * the network */ -int kickstartNetworkUp(struct loaderData_s * loaderData, iface_t * iface) { - int rc = -1; - - if ((is_nm_connected() == TRUE) && - (loaderData->netDev != NULL) && (loaderData->netDev_set == 1)) - return 0; - - iface_init_iface_t(iface); - - if (loaderData->essid != NULL) { - checkIPsettings(&(loaderData->ipinfo_set), &(loaderData->ipv4), &(loaderData->gateway), - &(loaderData->netmask)); - if (loaderData->wepkey != NULL) - rc = add_and_activate_wifi_connection(&(loaderData->netDev), - loaderData->essid, WIFI_PROTECTION_WEP, loaderData->wepkey, - loaderData->ipinfo_set, loaderData->ipv4, loaderData->gateway, - loaderData->dns, loaderData->netmask); - - else if (loaderData->wpakey != NULL) - rc = add_and_activate_wifi_connection(&(loaderData->netDev), - loaderData->essid, WIFI_PROTECTION_WPA, loaderData->wpakey, - loaderData->ipinfo_set, loaderData->ipv4, loaderData->gateway, - loaderData->dns, loaderData->netmask); - - else - rc = add_and_activate_wifi_connection(&(loaderData->netDev), - loaderData->essid, WIFI_PROTECTION_UNPROTECTED, NULL, - loaderData->ipinfo_set, loaderData->ipv4, loaderData->gateway, - loaderData->dns, loaderData->netmask); - - if (rc == WIFI_ACTIVATION_OK) { - loaderData->netDev_set = 1; - return 0; - } - else logMessage(ERROR, "wifi activation failed"); - } - - return activateDevice(loaderData, iface); -} - -int disconnectDevice(char *device) { - int rc; - - if ((rc = removeDhclientConfFile(device)) != 0) { - logMessage(ERROR, "removeDhclientConfFile failure (%s): %d", - __func__, rc); - } - - /* - * This will disconnect the device - */ - if ((rc = removeIfcfgFile(device)) != 0) { - logMessage(ERROR, "removeIfcfgFile failure (%s): %d", - __func__, rc); - return rc; - } - - if ((rc = wait_for_iface_disconnection(device)) != 0) { - return rc; - } - - if ((rc = writeDisabledIfcfgFile(device)) != 0) { - logMessage(ERROR, "writeDisabledIfcfgFile failure (%s): %d", - __func__, rc); - return rc; - } - return 0; -} - -int activateDevice(struct loaderData_s * loaderData, iface_t * iface) { - int rc; - - do { - do { - /* this is smart and does the right thing based on whether or not - * we have ksdevice= specified */ - rc = chooseNetworkInterface(loaderData); - - if (rc == LOADER_ERROR) { - /* JKFIXME: ask for a driver disk? */ - logMessage(ERROR, "no network drivers for doing kickstart"); - return -1; - } else if (rc == LOADER_BACK) { - return -1; - } - - /* insert device into iface structure */ - strcpy(iface->device, loaderData->netDev); - - break; - } while (1); - - if (is_iface_activated(iface->device)) { - logMessage(INFO, "device %s is already activated", iface->device); - if ((rc = disconnectDevice(iface->device)) != 0) { - logMessage(ERROR, "device disconnection failed with return code %d", rc); - return -1; - } - } - - /* we don't want to end up asking about interface more than once - * if we're in a kickstart-ish case (#100724) */ - loaderData->netDev_set = 1; - - /* default to DHCP for IPv4 if nothing is provided */ - if (loaderData->ipv4 == NULL) { - loaderData->ipv4 = strdup("dhcp"); - loaderData->ipinfo_set = 1; - } - - setupIfaceStruct(iface, loaderData); - rc = readNetConfig(loaderData->netDev, iface, loaderData->netCls, - loaderData->method); - - if (rc == LOADER_ERROR) { - logMessage(ERROR, "unable to activate device %s", iface->device); - return -1; - } else if (rc == LOADER_BACK) { - /* Going back to the interface selection screen, so unset anything - * we set before attempting to bring the incorrect interface up. - */ - logMessage(ERROR, "unable to activate device %s", iface->device); - if ((rc = removeDhclientConfFile(iface->device)) != 0) { - logMessage(ERROR, "removeDhclientConfFile failure (%s): %d", - __func__, rc); - } - if ((rc = writeDisabledIfcfgFile(iface->device)) != 0) { - logMessage(ERROR, "writeDisabledIfcfgFile failure (%s): %d", - __func__, rc); - } - - /* Forget network device so we prompt the user */ - loaderData->netDev_set = 0; - /* Forget IP information so we prompt the user */ - loaderData->ipinfo_set = 0; - free(loaderData->ipv4); - loaderData->ipv4 = NULL; - break; - } else { - break; - } - } while (1); - - return 0; -} - -void splitHostname (char *str, char **host, char **port) -{ - char *rightbrack = strchr(str, ']'); - char *firstcolon = strchr(str, ':'); - char *secondcolon = strrchr(str, ':'); - - *host = NULL; - *port = NULL; - - if (*str == '[' && rightbrack) { - /* An IPv6 address surrounded by brackets, optionally with a colon and - * port number. - */ - char *colon = strrchr(rightbrack, ':'); - - if (colon) { - *host = strndup(str+1, rightbrack-1-str); - *port = strdup(colon+1); - } - else - *host = strndup(str+1, rightbrack-1-str); - } else if (firstcolon && secondcolon && firstcolon != secondcolon) { - /* An IPv6 address without brackets. Don't make the user surround the - * address with brackets if there's no port number. - */ - *host = strdup(str); - } else { - /* An IPv4 address, optionally with a colon and port number. */ - char *colon = strrchr(str, ':'); - - if (colon) { - *host = strndup(str, colon-str); - *port = strdup(colon+1); - } - else - *host = strdup(str); - } -} - -/* - * Wait for activation of iface by NetworkManager, return non-zero on error. - */ -int wait_for_iface_activation(char *ifname) { - int count = 0, i; - NMClient *client = NULL; - GMainLoop *loop; - GMainContext *ctx; - const GPtrArray *devices; - NMDevice *device = NULL; - - if (ifname == NULL) { - return 1; - } - - logMessage(DEBUGLVL, "activating device %s", ifname); - - /* display status */ - if (FL_CMDLINE(flags)) { - printf(_("Waiting for NetworkManager to configure %s.\n"), - ifname); - } else { - winStatus(55, 3, NULL, - _("Waiting for NetworkManager to configure %s.\n"), - ifname, 0); - } - - g_type_init(); - - client = nm_client_new(); - if (!client) { - logMessage(ERROR, "%s (%d): could not connect to system bus", - __func__, __LINE__); - return 2; - } - - devices = nm_client_get_devices(client); - for (i = 0; i < devices->len; i++) { - NMDevice *candidate = g_ptr_array_index(devices, i); - const char *name = nm_device_get_iface(candidate); - if (!strcmp(name, ifname)) { - device = candidate; - break; - } - } - if (device == NULL) { - logMessage(ERROR, "%s (%d): network device %s not found", - __func__, __LINE__, ifname); - g_object_unref(client); - return 3; - } - - /* Create a loop for processing dbus signals */ - loop = g_main_loop_new(NULL, FALSE); - ctx = g_main_loop_get_context(loop); - - /* pump the loop until all the messages are clear */ - while (g_main_context_pending (ctx)) { - g_main_context_iteration (ctx, FALSE); - } - - /* send message and block until a reply or error comes back */ - while (count < 45) { - /* pump the loop again to clear the messages */ - while (g_main_context_pending (ctx)) { - g_main_context_iteration (ctx, FALSE); - } - if (nm_device_get_state(device) == NM_DEVICE_STATE_ACTIVATED) { - logMessage(INFO, "%s (%d): device %s activated", - __func__, __LINE__, ifname); - res_init(); - g_main_loop_unref(loop); - g_object_unref(client); - return 0; - } - - sleep(1); - count++; - } - - g_main_loop_unref(loop); - g_object_unref(client); - return 3; -} - -/* - * Wait for disconnection of iface by NetworkManager, return non-zero on error. - */ -int wait_for_iface_disconnection(char *ifname) { - int count = 0, i; - NMClient *client = NULL; - GMainLoop *loop; - GMainContext *ctx; - const GPtrArray *devices; - NMDevice *device = NULL; - - if (ifname == NULL) { - return 1; - } - - logMessage(INFO, "disconnecting device %s", ifname); - - g_type_init(); - - client = nm_client_new(); - if (!client) { - logMessage(ERROR, "%s (%d): could not connect to system bus", - __func__, __LINE__); - return 2; - } - - devices = nm_client_get_devices(client); - for (i = 0; i < devices->len; i++) { - NMDevice *candidate = g_ptr_array_index(devices, i); - const char *name = nm_device_get_iface(candidate); - if (!strcmp(name, ifname)) { - device = candidate; - break; - } - } - if (device == NULL) { - logMessage(ERROR, "%s (%d): network device %s not found", - __func__, __LINE__, ifname); - g_object_unref(client); - return 3; - } - - /* Create a loop for processing dbus signals */ - loop = g_main_loop_new(NULL, FALSE); - ctx = g_main_loop_get_context(loop); - - /* pump the loop until all the messages are clear */ - while (g_main_context_pending (ctx)) { - g_main_context_iteration (ctx, FALSE); - } - - /* send message and block until a reply or error comes back */ - while (count < 5) { - /* pump the loop again to clear the messages */ - while (g_main_context_pending (ctx)) { - g_main_context_iteration (ctx, FALSE); - } - if (nm_device_get_state(device) == NM_DEVICE_STATE_DISCONNECTED) { - logMessage(INFO, "%s (%d): device %s disconnected", - __func__, __LINE__, ifname); - res_init(); - g_main_loop_unref(loop); - g_object_unref(client); - return 0; - } - - sleep(1); - count++; - } - - g_main_loop_unref(loop); - g_object_unref(client); - return 3; -} - -int isValidIPv4Address(const char *address) { - int rc; - struct in_addr addr; - if ((rc = inet_pton(AF_INET, address, &addr)) >= 1) { - return 1; - } else if (rc == 0) { - return 0; - } else { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - return 0; - } -} - -#ifdef ENABLE_IPV6 -int isValidIPv6Address(const char *address) { - int rc; - struct in6_addr addr; - if ((rc = inet_pton(AF_INET6, address, &addr)) >= 1) { - return 1; - } else if (rc == 0) { - return 0; - } else { - logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, - strerror(errno)); - return 0; - } -} -#endif - -int isURLRemote(char *url) { - if (url == NULL) { - return 0; - } - - if (!strncmp(url, "http", 4) || - !strncmp(url, "ftp://", 6) || - !strncmp(url, "nfs:", 4)) { - return 1; - } else { - return 0; - } -} - -gboolean byte_array_cmp(const GByteArray *array, char *string) { - //returns TRUE if array and char* contain the same strings - int i=0; - gboolean ret = TRUE; - if (array->len != strlen(string)) { - return FALSE; - } - while (i<array->len && ret) { - ret = ret && array->data[i] == string[i]; - i++; - } - return ret; -} - -NMAccessPoint* get_best_ap(NMDeviceWifi *device, char *ssid) { - const GPtrArray *aps; - int i; - NMAccessPoint *candidate = NULL; - guint8 max = 0; - aps = nm_device_wifi_get_access_points(device); - - if (!aps) return NULL; - - for (i = 0; i < aps->len; i++) { - NMAccessPoint *ap = g_ptr_array_index(aps, i); - const GByteArray *byte_ssid = nm_access_point_get_ssid(ap); - if (byte_array_cmp(byte_ssid, ssid)) { - if (nm_access_point_get_strength(ap) > max) { - max = nm_access_point_get_strength(ap); - candidate = ap; - } - } - } - return candidate; -} - -gboolean get_device_and_ap(NMClient *client, char **iface, char *ssid, - NMDeviceWifi **device, NMAccessPoint **ap) { - //returns TRUE if device and ap (according to iface and ssid) - //were found - //iface, device and ap are used for storing the results - //iface is also used as argument - - const GPtrArray *devices; - int i; - NMAccessPoint *candidate_ap = NULL; - NMDevice *candidate = NULL; - char *tmp_iface = NULL; - char *dev_iface = NULL; - - devices = nm_client_get_devices(client); - - for (i = 0; i < devices->len; i++) { - candidate = g_ptr_array_index(devices, i); - tmp_iface = (char *)nm_device_get_iface(candidate); - - if (!tmp_iface) continue; - dev_iface = strdup((char *)tmp_iface); - if (strcmp(*iface, "") && strcmp(dev_iface, *iface)) continue; - if (NM_IS_DEVICE_WIFI(candidate)) { - candidate_ap = get_best_ap((NMDeviceWifi*)candidate, ssid); - if (candidate_ap != NULL) { - *device = (NMDeviceWifi*)candidate; - *ap = candidate_ap; - *iface = dev_iface; - return TRUE; - } - } - else free(dev_iface); - } - return FALSE; -} - - -static void -add_cb(NMClient *client, - const char *connection_path, - const char *active_path, - GError *error, - gpointer user_data) { - if (error) logMessage(ERROR, "Error adding wifi connection: %s", error->message); -} - -gboolean ip_str_to_nbo(char* ip, guint32 *result) { - //get NBO representation of ip address - struct in_addr tmp_addr = { 0 }; - - if (inet_pton(AF_INET, ip, &tmp_addr) == 1) { - *result = tmp_addr.s_addr; - return TRUE; - } else return FALSE; -} - - -int add_and_activate_wifi_connection(char **iface, char *ssid, - int protection, char *password, int ip_method_manual, char *address, - char *gateway, char *dns, char *netmask) { - - NMClient *client = NULL; - NMDeviceWifi *device = NULL; - NMAccessPoint *ap = NULL; - GMainLoop *loop; - GMainContext *ctx; - DBusGConnection *DBconnection; - GError *error; - GByteArray *ssid_ba; - int ssid_len; - gboolean success = FALSE; - gint8 count = 0, ret; - NMConnection *connection; - NMSettingConnection *s_con; - NMSettingWireless *s_wireless; - NMSettingWirelessSecurity *s_sec; - NMSettingIP4Config *s_ip; - char *uuid; - char *buf; - - if (*iface == NULL) *iface = ""; - error = NULL; - DBconnection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); - if (DBconnection == NULL) { - g_error_free(error); - return WIFI_ACTIVATION_DBUS_ERROR; - } - - client = nm_client_new(); - if (!client) return WIFI_ACTIVATION_NM_CLIENT_ERROR; - - if (!nm_client_wireless_hardware_get_enabled(client)) - return WIFI_ACTIVATION_WIFI_HW_DISABLED; - - if (!nm_client_wireless_get_enabled(client)) - nm_client_wireless_set_enabled(client, TRUE); - - if (!ssid) return WIFI_ACTIVATION_BAD_SSID; - ssid_len = strlen(ssid); - if (!ssid_len || ssid_len > 32) return WIFI_ACTIVATION_BAD_SSID; - ssid_ba = g_byte_array_sized_new(ssid_len); - g_byte_array_append(ssid_ba, (unsigned char *) ssid, ssid_len); - - loop = g_main_loop_new(NULL, FALSE); - ctx = g_main_loop_get_context(loop); - - while (g_main_context_pending(ctx)) - g_main_context_iteration(ctx, FALSE); - - /* display status */ - if (FL_CMDLINE(flags)) - printf(_("Waiting for NetworkManager to activate wifi.\n")); - else - winStatus(55, 3, NULL, - _("Waiting for NetworkManager to activate wifi.\n"), 0); - - while (count < 45 && !success) { - while (g_main_context_pending(ctx)) - g_main_context_iteration(ctx, FALSE); - success = get_device_and_ap(client, iface, ssid, &device, &ap); - sleep(1); - count++; - } - - if (!FL_CMDLINE(flags)) newtPopWindow(); - - if (!success) return WIFI_ACTIVATION_CANNOT_FIND_AP; - - connection = nm_connection_new(); - - s_con = (NMSettingConnection*) nm_setting_connection_new(); - uuid = nm_utils_uuid_generate(); - g_object_set(G_OBJECT (s_con), - NM_SETTING_CONNECTION_UUID, uuid, - NM_SETTING_CONNECTION_ID, ssid, - NM_SETTING_CONNECTION_TYPE, "802-11-wireless", - NULL); - g_free(uuid); - nm_connection_add_setting(connection, NM_SETTING (s_con)); - - s_wireless = (NMSettingWireless*) nm_setting_wireless_new(); - g_object_set(G_OBJECT (s_wireless), - NM_SETTING_WIRELESS_SSID, ssid_ba, - NM_SETTING_WIRELESS_MODE, "infrastructure", - NULL); - g_byte_array_free(ssid_ba, TRUE); - if ((protection == WIFI_PROTECTION_WEP) || protection == WIFI_PROTECTION_WPA) { - g_object_set(G_OBJECT (s_wireless), - NM_SETTING_WIRELESS_SEC, "802-11-wireless-security", - NULL); - } - nm_connection_add_setting(connection, NM_SETTING (s_wireless)); - - if (protection == WIFI_PROTECTION_WEP) { - s_sec = (NMSettingWirelessSecurity*) nm_setting_wireless_security_new(); - g_object_set (G_OBJECT (s_sec), - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", - NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, 0, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, 1, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, password, - NULL); - if (strlen(password) == 32) { - g_object_set(G_OBJECT (s_sec), - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, 2, - NULL); - } - nm_connection_add_setting(connection, NM_SETTING (s_sec)); - - } else if (protection == WIFI_PROTECTION_WPA) { - s_sec = (NMSettingWirelessSecurity*) nm_setting_wireless_security_new(); - g_object_set(G_OBJECT (s_sec), - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", - NM_SETTING_WIRELESS_SECURITY_PSK, password, - NULL); - nm_connection_add_setting(connection, NM_SETTING (s_sec)); - } - - if (ip_method_manual) { - GPtrArray *addresses = g_ptr_array_new(); - GArray *address_array = g_array_new(FALSE, FALSE, sizeof(guint32)); - guint32 nbo_ip = 0; - guint32 nbo_gw = 0; - guint32 nbo_dns = 0; - guint32 nbo_netmask = 0; - guint32 nbo_prefix = 0; - char *dns_addr = NULL; - - ip_str_to_nbo(address, &nbo_ip); - - if (gateway) ip_str_to_nbo(gateway, &nbo_gw); - - nbo_prefix = nm_utils_ip4_get_default_prefix(nbo_ip); - if (netmask && ip_str_to_nbo(netmask, &nbo_netmask)) - nbo_prefix = nm_utils_ip4_netmask_to_prefix(nbo_netmask); - - g_array_append_val(address_array, nbo_ip); - g_array_append_val(address_array, nbo_prefix); - g_array_append_val(address_array, nbo_gw); - - g_ptr_array_add(addresses, address_array); - - s_ip = (NMSettingIP4Config*) nm_setting_ip4_config_new(); - g_object_set(G_OBJECT (s_ip), - NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, - NM_SETTING_IP4_CONFIG_ADDRESSES, addresses, - NULL); - if (dns) { - count = 0; - buf = strdup(dns); - dns_addr = strtok(buf, ","); - while (dns_addr && count <= MAXNS) { - if (ip_str_to_nbo(dns_addr, &nbo_dns)) { - nm_setting_ip4_config_add_dns(s_ip, nbo_dns); - count++; - } - dns_addr = strtok(NULL, ","); - } - } - nm_connection_add_setting(connection, NM_SETTING (s_ip)); - g_array_free(address_array, TRUE); - g_ptr_array_free(addresses, TRUE); - } - - const char *ap_path = nm_object_get_path((NMObject*) ap); - nm_client_add_and_activate_connection(client, connection, - (NMDevice*) device, ap_path, (NMClientAddActivateFn) add_cb, - NULL); - - ret = wait_for_iface_activation(*iface); - if (!FL_CMDLINE(flags)) newtPopWindow(); - if (ret == 0) { - g_main_loop_unref(loop); - return WIFI_ACTIVATION_OK; - } - - *iface = NULL; - g_main_loop_unref(loop); - return WIFI_ACTIVATION_TIMED_OUT; -} - -gboolean checkIPsettings (int *ip_info_set, char **ip, char **gateway, char **netmask) { - gboolean ok = TRUE; - guint32 tmp = 0; - - if (*ip && !ip_str_to_nbo(*ip, &tmp)) { - free(*ip); - *ip = NULL; - *ip_info_set = 0; - ok = FALSE; - } - if (*gateway && !ip_str_to_nbo(*gateway, &tmp)) { - free(*gateway); - *gateway = NULL; - ok = FALSE; - } - if (*netmask && !ip_str_to_nbo(*netmask, &tmp)) { - free(*netmask); - *netmask = NULL; - ok = FALSE; - } - return ok; -} - -/* vim:set shiftwidth=4 softtabstop=4: */ diff --git a/loader/net.h b/loader/net.h deleted file mode 100644 index e5debb2..0000000 --- a/loader/net.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * net.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef H_LOADER_NET -#define H_LOADER_NET - -#include <newt.h> -#include "../pyanaconda/isys/iface.h" -#include "loader.h" - -#define DHCP_METHOD_STR _("Dynamic IP configuration (DHCP)") -#define MANUAL_METHOD_STR _("Manual configuration") -#ifdef ENABLE_IPV6 -#define DHCPV6_METHOD_STR _("Dynamic IP configuration (DHCPv6)") -#define AUTO_METHOD_STR _("Automatic neighbor discovery") -#endif - -#define SYSCONFIG_PATH "/etc/sysconfig" -#define NETWORK_SCRIPTS_PATH "/etc/sysconfig/network-scripts" - -struct intfconfig_s { - newtComponent ipv4Entry, cidr4Entry; - newtComponent gwEntry, nsEntry; - const char *ipv4, *cidr4; -#ifdef ENABLE_IPV6 - newtComponent ipv6Entry, cidr6Entry; - const char *ipv6, *cidr6; - const char *gw6; -#endif - const char *gw, *ns; -}; - -struct netconfopts { - char ipv4Choice; - int v4Method; -#ifdef ENABLE_IPV6 - char ipv6Choice; - int v6Method; -#endif -}; - -typedef int int32; - -int readNetConfig(char * device, iface_t * iface, - char * dhcpclass, int methodNum); -int configureTCPIP(char * device, iface_t * iface, struct netconfopts * opts, - int methodNum); -int manualNetConfig(char * device, iface_t * iface, - struct intfconfig_s * ipcomps, struct netconfopts * opts); -void debugNetworkInfo(iface_t * iface); -int writeDisabledNetInfo(void); -int writeDisabledIfcfgFile(char *device); -int removeDhclientConfFile(char *device); -int removeIfcfgFile(char *device); -int writeEnabledNetInfo(iface_t * iface); -int chooseNetworkInterface(struct loaderData_s * loaderData); -void setupIfaceStruct(iface_t * iface, struct loaderData_s * loaderData); -int setupWireless(iface_t * iface); -int kickstartNetworkUp(struct loaderData_s * loaderData, - iface_t * iface); -int activateDevice(struct loaderData_s * loaderData, - iface_t * iface); -int disconnectDevice(char *device); -void splitHostname (char *str, char **host, char **port); -int split_ipv6addr_prefix_length(char *str, char **address, char **prefix); -int wait_for_iface_activation(char * ifname); -int wait_for_iface_disconnection(char *ifname); -int isURLRemote(char *url); -int isValidIPv4Address(const char *address); -int add_and_activate_wifi_connection (char **iface, char *ssid, - int protection, char *password, - int ip_method_manual, char *address, - char *gateway, char *dns, - char *netmask); -int checkIPsettings (int *ip_info_set, char **ip, char **gateway, - char **netmask); -#ifdef ENABLE_IPV6 -int isValidIPv6Address(const char *address); -#endif - -#endif - -#define WIFI_PROTECTION_UNPROTECTED 0 -#define WIFI_PROTECTION_WEP 1 -#define WIFI_PROTECTION_WPA 2 - -#define WIFI_ACTIVATION_OK 0 -#define WIFI_ACTIVATION_DBUS_ERROR 1 -#define WIFI_ACTIVATION_NM_CLIENT_ERROR 2 -#define WIFI_ACTIVATION_WIFI_HW_DISABLED 3 -#define WIFI_ACTIVATION_BAD_SSID 4 -#define WIFI_ACTIVATION_CANNOT_FIND_AP 5 -#define WIFI_ACTIVATION_TIMED_OUT 6 diff --git a/loader/nfsinstall.c b/loader/nfsinstall.c deleted file mode 100644 index f46e79e..0000000 --- a/loader/nfsinstall.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * nfsinstall.c - code to set up nfs installs - * - * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006, 2007 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <fcntl.h> -#include <newt.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <glib.h> -#include <nm-client.h> -#include <nm-device.h> -#include <nm-dhcp4-config.h> - -#include "copy.h" -#include "dirbrowser.h" -#include "loader.h" -#include "lang.h" -#include "loadermisc.h" -#include "kickstart.h" -#include "method.h" -#include "nfsinstall.h" -#include "net.h" -#include "cdinstall.h" -#include "windows.h" - -#include "../pyanaconda/isys/imount.h" -#include "../pyanaconda/isys/iface.h" -#include "../pyanaconda/isys/log.h" - -/* boot flags */ -extern uint64_t flags; - -static int nfsGetSetup(char ** hostptr, char ** dirptr, char ** optsptr) { - struct newtWinEntry entries[4]; - char * buf; - char * newServer = *hostptr ? strdup(*hostptr) : NULL; - char * newDir = *dirptr ? strdup(*dirptr) : NULL; - char * newMountOpts = *optsptr ? strdup(*optsptr) : NULL; - int rc; - - entries[0].text = _("NFS server name:"); - entries[0].value = &newServer; - entries[0].flags = NEWT_FLAG_SCROLL; - - checked_asprintf(&entries[1].text, _("%s directory:"), getProductName()); - - entries[1].value = &newDir; - entries[1].flags = NEWT_FLAG_SCROLL; - entries[2].text = _("NFS mount options (optional):"); - entries[2].value = &newMountOpts; - entries[2].flags = NEWT_FLAG_SCROLL; - entries[3].text = NULL; - entries[3].value = NULL; - - if (asprintf(&buf, _("Please enter the server and path to your %s " - "installation tree and optionally additional " - "NFS mount options."), getProductName()) == -1) { - logMessage(CRITICAL, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - do { - rc = newtWinEntries(_("NFS Setup"), buf, 60, 5, 15, - 24, entries, _("OK"), _("Back"), NULL); - } while ((!strcmp(newServer, "") || !strcmp(newDir, "")) && rc != 2); - - free(buf); - free(entries[1].text); - - if (rc == 2) { - if (newServer) free(newServer); - if (newDir) free(newDir); - if (newMountOpts) free(newMountOpts); - return LOADER_BACK; - } - - if (*hostptr) free(*hostptr); - if (*dirptr) free(*dirptr); - if (*optsptr) free(*optsptr); - - *hostptr = newServer; - *dirptr = newDir; - - /* The rest of loader expects opts to be NULL if there are none, but newt - * gives us "" instead. - */ - if (newMountOpts && strcmp(newMountOpts, "")) - *optsptr = newMountOpts; - else - *optsptr = NULL; - - return LOADER_OK; -} - -/* Parse nfs: url and return its componenets - * - * (nfs|nfsiso)[:options]:<server>:<path> - */ -void parseNfsHostPathOpts(char *url, char **host, char **path, char **opts) { - /* Skip over the leading nfs: or nfsiso: if present. */ - if (!strncmp(url, "nfs:", 4)) - url += 4; - else if (!strncmp(url, "nfsiso:", 7)) - url += 7; - - logMessage(DEBUGLVL, "parseNfsHostPathOpts url: |%s|", url); - - gchar **parts = g_strsplit(url, ":", 3) ; - if (parts == NULL || g_strv_length(parts) < 2) { - *opts = g_strdup(""); - *host = g_strdup(""); - *path = g_strdup(""); - } else if (g_strv_length(parts) == 2) { - *opts = g_strdup(""); - *host = g_strdup(parts[0]); - *path = g_strdup(parts[1]); - g_strfreev(parts); - } else { - *opts = g_strdup(parts[0]); - *host = g_strdup(parts[1]); - *path = g_strdup(parts[2]); - g_strfreev(parts); - } - - logMessage(DEBUGLVL, "parseNfsHostPathOpts host: |%s|", *host); - logMessage(DEBUGLVL, "parseNfsHostPathOpts path: |%s|", *path); - logMessage(DEBUGLVL, "parseNfsHostPathOpts opts: |%s|", *opts); -} - -static void addDefaultKickstartFile(char **file, char *ip) { - /* if the filename ends with / or is null, use default kickstart - * name of IP_ADDRESS-kickstart appended to *file - */ - if ((*file) && (((*file)[strlen(*file) - 1] == '/') || - ((*file)[strlen(*file) - 1] == '\0'))) { - checked_asprintf(file, "%s%s-kickstart", *file, ip); - logMessage(DEBUGLVL, "addDefaultKickstartFile file: |%s|", *file); - } -} - -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 (suffix && !strcmp(suffix, ".iso")); -} - -static unsigned int isNfsIso(struct loaderData_s *loaderData) { - char **files = NULL; - char *host, *path, *opts, *url; - char *buf; - int rc = 0; - - parseNfsHostPathOpts(loaderData->instRepo, &host, &path, &opts); - checked_asprintf(&url, "%s:%s", host, path); - - if (doPwMount(url, "/mnt/install/isodir", "nfs", opts, NULL)) { - logMessage(ERROR, "couldn't mount %s to look for NFSISO", url); - goto cleanup1; - } - - files = get_file_list("/mnt/install/isodir", ends_with_iso); - if (!files || !files[0] || !strlen(files[0])) { - logMessage(ERROR, "no ISO images present in /mnt/install/isodir"); - goto cleanup2; - } - - /* mount the first image and check for a .treeinfo file */ - checked_asprintf(&buf, "/mnt/install/isodir/%s", files[0]); - if (doPwMount(buf, "/mnt/install/testmnt", "auto", "ro", NULL)) { - logMessage(ERROR, "ISO image %s does not contain a .treeinfo file", files[0]); - goto cleanup3; - } - - if (access("/mnt/install/testmnt/.treeinfo", R_OK)) { - logMessage(ERROR, ".treeinfo file is not accessible"); - goto cleanup4; - } - - free(loaderData->instRepo); - rc = 1; - - if (opts) { - checked_asprintf(&loaderData->instRepo, "nfsiso:%s:%s:%s", opts, host, path); - } else { - checked_asprintf(&loaderData->instRepo, "nfsiso:%s:%s", host, path); - } - -cleanup4: - umount("/mnt/install/testmnt"); -cleanup3: - free(buf); -cleanup2: - umount("/mnt/install/isodir"); -cleanup1: - g_free(host); - g_free(path); - g_free(opts); - free(url); - return rc; -} - -int promptForNfs(struct loaderData_s *loaderData) { - char *url = NULL; - char *host = NULL; - char *directory = NULL; - char *mountOpts = NULL; - - do { - if (nfsGetSetup(&host, &directory, &mountOpts) == LOADER_BACK) { - loaderData->instRepo = NULL; - return LOADER_BACK; - } - - if (mountOpts) { - checked_asprintf(&loaderData->instRepo, "nfs:%s:%s:%s", mountOpts, host, - directory); - } else { - checked_asprintf(&loaderData->instRepo, "nfs:%s:%s", host, directory); - } - - checked_asprintf(&url, "%s/.treeinfo", loaderData->instRepo); - - if (getFileFromNfs(url, "/tmp/.treeinfo", loaderData) && !isNfsIso(loaderData)) { - newtWinMessage(_("Error"), _("OK"), - _("The URL provided does not contain an installable tree.")); - free(url); - continue; - } - - free(url); - break; - } while (1); - - loaderData->method = METHOD_NFS; - return LOADER_OK; -} - -int loadNfsImages(struct loaderData_s *loaderData) { - char *host, *path, *opts; - char *url; - - logMessage(DEBUGLVL, "looking for extras for NFS install"); - - if (!loaderData->instRepo) - return 0; - - parseNfsHostPathOpts(loaderData->instRepo, &host, &path, &opts); - - checked_asprintf(&url, "%s:%s/RHupdates", host, path); - logMessage(INFO, "Looking for updates in %s", url); - - if (!doPwMount(url, "/mnt/install/update-disk", "nfs", opts, NULL)) { - logMessage(INFO, "Using RHupdates/ for NFS install"); - copyDirectory("/mnt/install/update-disk", "/tmp/updates", NULL, NULL); - umount("/mnt/install/update-disk"); - unlink("/mnt/install/update-disk"); - } else { - logMessage(INFO, "No RHupdates/ directory found, skipping"); - } - - free(url); - checked_asprintf(&url, "%s:%s", host, path); - - if (!doPwMount(url, "/mnt/install/disk-image", "nfs", opts, NULL)) { - free(url); - - logMessage(INFO, "Looking for updates in %s/updates.img", loaderData->instRepo); - copyUpdatesImg("/mnt/install/disk-image/updates.img"); - - logMessage(INFO, "Looking for product in %s/product.img", loaderData->instRepo); - copyProductImg("/mnt/install/disk-image/product.img"); - - umount("/mnt/install/disk-image"); - unlink("/mnt/install/disk-image"); - } else { - logMessage(INFO, "Couldn't mount %s for updates and product", loaderData->instRepo); - free(url); - } - - g_free(host); - g_free(path); - g_free(opts); - return 1; -} - -int getFileFromNfs(char * url, char * dest, struct loaderData_s * loaderData) { - char * host = NULL, *path = NULL, * file = NULL, * opts = NULL; - char * chk = NULL, *ip = NULL; - int failed = 0, i = 0; - iface_t iface; - NMClient *client = NULL; - NMState state; - const GPtrArray *devices; - - if (kickstartNetworkUp(loaderData, &iface)) { - logMessage(ERROR, "unable to bring up network"); - return 1; - } - - /* if they just did 'linux ks', they want us to figure it out from - * the dhcp/bootp information - */ - if (!url) { - g_type_init(); - - client = nm_client_new(); - if (!client) { - logMessage(CRITICAL, "%s (%d): failure creating NM proxy", - __func__, __LINE__); - return 1; - } - - state = nm_client_get_state(client); - if (! is_connected_state(state)) { - logMessage(ERROR, "%s (%d): no active network devices", - __func__, __LINE__); - g_object_unref(client); - return 1; - } - - devices = nm_client_get_devices(client); - for (i = 0; i < devices->len; i++) { - NMDevice *candidate = g_ptr_array_index(devices, i); - const char *devname = nm_device_get_iface(candidate); - NMDHCP4Config *dhcp = NULL; - const char *server_name = NULL; - const char *filename = NULL; - char nextserver[INET_ADDRSTRLEN+1]; - - if (nm_device_get_state(candidate) != NM_DEVICE_STATE_ACTIVATED) - continue; - - if (strcmp(iface.device, devname)) - continue; - - dhcp = nm_device_get_dhcp4_config(candidate); - if (!dhcp) { - logMessage(ERROR, "no boot options received by DHCP"); - continue; - } - - server_name = nm_dhcp4_config_get_one_option(dhcp, "server_name"); - if (!server_name) { - logMessage(ERROR, "no bootserver was found"); - g_object_unref(client); - return 1; - } - - /* 'server_name' may be a hostname or an IPv4 address */ - memset(&nextserver, '\0', sizeof(nextserver)); - if (isValidIPv4Address(server_name)) { - strcpy(nextserver, server_name); - } else { - struct hostent *he = gethostbyname(server_name); - if (he != NULL) { - if (inet_ntop(AF_INET, he->h_addr_list[0], - nextserver, INET_ADDRSTRLEN) == NULL) { - memset(&nextserver, '\0', sizeof(nextserver)); - } - } - } - - filename = nm_dhcp4_config_get_one_option(dhcp, "filename"); - if (filename == NULL) { - checked_asprintf(&url, "%s:/kickstart/", nextserver); - logMessage(ERROR, "bootp: no bootfile received"); - } else { - checked_asprintf(&url, "%s:%s", nextserver, filename); - logMessage(INFO, "bootp: bootfile is %s", filename); - } - - break; - } - - g_object_unref(client); - } - - /* get the IP of the target system */ - if ((ip = iface_ip2str(loaderData->netDev, AF_INET)) == NULL) { - logMessage(ERROR, "iface_ip2str returned NULL"); - return 1; - } - - logMessage(INFO, "url is %s", url); - - parseNfsHostPathOpts(url, &host, &path, &opts); - addDefaultKickstartFile(&path, ip); - - /* nfs has to be a little bit different... split off the last part as - * the file and then concatenate host + dir path */ - file = strrchr(path, '/'); - if (!file) { - file = path; - } else { - *file++ ='\0'; - chk = host + strlen(host)-1; - - if (*chk == '/' || *path == '/') { - checked_asprintf(&host, "%s:%s", host, path); - } else { - checked_asprintf(&host, "%s:/%s", host, path); - } - } - - logMessage(INFO, "file location: nfs:%s/%s", host, file); - - if (!doPwMount(host, "/mnt/install/testmnt", "nfs", opts, NULL)) { - char * buf; - - checked_asprintf(&buf, "/mnt/install/testmnt/%s", file); - - if (copyFile(buf, dest)) { - logMessage(ERROR, "failed to copy file to %s", dest); - failed = 1; - } - - free(buf); - } else { - logMessage(ERROR, "failed to mount nfs source"); - failed = 1; - } - - g_free(host); - g_free(path); - g_free(opts); - if (ip) free(ip); - - if (umount("/mnt/install/testmnt") == -1) - logMessage(ERROR, "could not unmount /mnt/install/testmnt in getFileFromNfs: %s", strerror(errno)); - else - unlink("/mnt/install/testmnt"); - - return failed; -} - -int kickstartFromNfs(char * url, struct loaderData_s * loaderData) { - return getFileFromNfs(url, "/tmp/ks.cfg", loaderData); -} - -/* vim:set shiftwidth=4 softtabstop=4: */ diff --git a/loader/nfsinstall.h b/loader/nfsinstall.h deleted file mode 100644 index ace38b1..0000000 --- a/loader/nfsinstall.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * nfsinstall.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef NFSINSTALL_H -#define NFSINSTALL_H - -#include "method.h" - -int kickstartFromNfs(char * url, struct loaderData_s * loaderData); -int promptForNfs(struct loaderData_s *loaderData); -int loadNfsImages(struct loaderData_s *loaderData); -int getFileFromNfs(char * url, char * dest, struct loaderData_s * loaderData); -void parseNfsHostPathOpts(char * url, char ** host, char ** path, char ** opts); - -#endif diff --git a/loader/readvars.c b/loader/readvars.c deleted file mode 100644 index da175c3..0000000 --- a/loader/readvars.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * readvars.c - * Copyright (C) 2009, 2010 Red Hat, Inc. - * - * 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 <http://www.gnu.org/licenses/>. - * - * Author(s): David Cantrell <dcantrell@xxxxxxxxxx> - */ - -#include <stdio.h> -#include <ctype.h> -#include <glib.h> - -#include "../pyanaconda/isys/log.h" - -/* - * Given a string with shell-style variables listed (e.g., the contents of an - * /etc/sysconfig file), parse the contents and generate a hash table of the - * variables read. Return the hash table to the caller. Caller is - * responsible for freeing memory associated with the hash table: - * - * table = readvars_read_conf("VAR1=val1\nVAR2=val2\n"); - * g_hash_table_destroy(table); - * - * Errors encountered during parsing will result in this function returning - * NULL. - * - * Variables can also be standalone (done so this function can parse the - * contents of /proc/cmdline). If they lack a value and are just in the - * string as a single token, they will become a hash table key with an - * NULL value. - */ -GHashTable *readvars_parse_string(gchar *contents) { - gint argc = 0, i = 0; - gchar **argv = NULL; - GError *e = NULL; - GHashTable *conf = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - - if (contents == NULL) { - return NULL; - } - - if (!g_shell_parse_argv(contents, &argc, &argv, &e)) { - if (e != NULL) { - logMessage(ERROR, "%s(%d): %s", __func__, __LINE__, e->message); - g_error_free(e); - } - - return NULL; - } - - while (i < argc) { - gchar **tokens = g_strsplit(argv[i], "=", 2); - guint len = g_strv_length(tokens); - gchar *key = NULL, *value = NULL; - e = NULL; - - if (len == 1 || len == 2) { - key = g_strdup(tokens[0]); - } - - if (len == 2) { - value = g_shell_unquote(tokens[1], &e); - - if (value == NULL && e != NULL) { - logMessage(ERROR, "%s(%d): %s", __func__, __LINE__, - e->message); - g_error_free(e); - } - } - - if (key != NULL) { - g_hash_table_insert(conf, key, value); - } - - g_strfreev(tokens); - i++; - } - - g_strfreev(argv); - return conf; -} - -/* - * Read contents of file and call readvars_parse_string() with that string, - * caller is responsible for cleanup in the same style as - * readvars_parse_string(). - */ -GHashTable *readvars_parse_file(gchar *filename) { - gsize len = 0; - gchar *input = NULL; - GError *e = NULL; - GHashTable *ret = NULL; - - if (filename == NULL) { - return NULL; - } - - if (!g_file_get_contents(filename, &input, &len, &e)) { - if (e != NULL) { - logMessage(ERROR, "%s(%d): %s", __func__, __LINE__, e->message); - g_error_free(e); - } - - g_free(input); - return NULL; - } - - ret = readvars_parse_string(input); - g_free(input); - - return ret; -} diff --git a/loader/readvars.h b/loader/readvars.h deleted file mode 100644 index 8938c04..0000000 --- a/loader/readvars.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * readvars.h - * Copyright (C) 2009, 2010 Red Hat, Inc. - * - * 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 <http://www.gnu.org/licenses/>. - * - * Author(s): David Cantrell <dcantrell@xxxxxxxxxx> - */ - -#include <glib.h> - -#ifndef READVARS_H -#define READVARS_H - -GHashTable *readvars_parse_string(gchar *); -GHashTable *readvars_parse_file(gchar *); - -#endif diff --git a/loader/rpmextract.c b/loader/rpmextract.c deleted file mode 100644 index 97e0c7b..0000000 --- a/loader/rpmextract.c +++ /dev/null @@ -1,260 +0,0 @@ -/* unpack the payload of RPM package to the current directory - * - * File name: rpmextract.c - * Date: 2009/12/18 - * Author: Martin Sivak <msivak at redhat dot com> - * - * Copyright (C) 2009 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 <http://www.gnu.org/licenses/>. - * - * */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include <rpm/rpmlib.h> /* rpmReadPackageFile .. */ -#include <rpm/rpmtag.h> -#include <rpm/rpmio.h> -#include <rpm/rpmpgp.h> - -#include <rpm/rpmts.h> - -#include <stdio.h> -#include <archive.h> -#include <archive_entry.h> - -#include "loader.h" -#include "rpmextract.h" -#include "unpack.h" - -#include "../pyanaconda/isys/log.h" - -/* - * internal structure to pass to libarchive callbacks - */ - -struct cpio_mydata { - FD_t gzdi; - char *buffer; -}; - -/* - * libarchive callbacks - */ - -ssize_t rpm_myread(struct archive *a, void *client_data, const void **buff) -{ - struct cpio_mydata *mydata = client_data; - *buff = mydata->buffer; - return Fread(mydata->buffer, 1, BUFFERSIZE, mydata->gzdi); -} - -int rpm_myclose(struct archive *a, void *client_data) -{ - struct cpio_mydata *mydata = client_data; - if (mydata->gzdi > 0) - Fclose(mydata->gzdi); - return ARCHIVE_OK; -} - -/* read data from RPM header */ - -const char * headerGetString(Header h, rpmTag tag) -{ - const char *res = NULL; - struct rpmtd_s td; - - if (headerGet(h, tag, &td, HEADERGET_MINMEM)) { - if (rpmtdCount(&td) == 1) { - res = rpmtdGetString(&td); - } - rpmtdFreeData(&td); - } - return res; -} - -/* - * explode source RPM into the current directory - * use filters to skip packages and files we do not need - */ -int explodeRPM(const char *source, - filterfunc filter, - dependencyfunc provides, - dependencyfunc deps, - void* userptr, - char *destination) -{ - char buffer[BUFFERSIZE+1]; /* make space for trailing \0 */ - FD_t fdi; - Header h; - char * rpmio_flags = NULL; - rpmRC rc; - FD_t gzdi; - struct archive *cpio; - struct cpio_mydata cpio_mydata; - - rpmts ts; - rpmVSFlags vsflags; - const char *compr; - - if (strcmp(source, "-") == 0) - fdi = fdDup(STDIN_FILENO); - else - fdi = Fopen(source, "r.ufdio"); - - if (Ferror(fdi)) { - const char *srcname = (strcmp(source, "-") == 0) ? "<stdin>" : source; - logMessage(ERROR, "%s: %s\n", srcname, Fstrerror(fdi)); - return EXIT_FAILURE; - } - rpmReadConfigFiles(NULL, NULL); - - /* Initialize RPM transaction */ - ts = rpmtsCreate(); - vsflags = 0; - - /* Do not check digests, signatures or headers */ - vsflags |= _RPMVSF_NODIGESTS; - vsflags |= _RPMVSF_NOSIGNATURES; - vsflags |= RPMVSF_NOHDRCHK; - (void) rpmtsSetVSFlags(ts, vsflags); - - rc = rpmReadPackageFile(ts, fdi, "rpm2dir", &h); - - ts = rpmtsFree(ts); - - switch (rc) { - case RPMRC_OK: - case RPMRC_NOKEY: - case RPMRC_NOTTRUSTED: - break; - case RPMRC_NOTFOUND: - logMessage(ERROR, "%s is not an RPM package", source); - return EXIT_FAILURE; - break; - case RPMRC_FAIL: - default: - logMessage(ERROR, "error reading header from %s package\n", source); - return EXIT_FAILURE; - break; - } - - /* Retrieve all dependencies and run them through deps function */ - while (deps) { - struct rpmtd_s tddep; - struct rpmtd_s tdver; - const char *depname; - const char *depversion; - - if (!headerGet(h, RPMTAG_PROVIDES, &tddep, HEADERGET_MINMEM)) - break; - - if (!headerGet(h, RPMTAG_PROVIDEVERSION, &tdver, HEADERGET_MINMEM)){ - rpmtdFreeData(&tddep); - break; - } - - /* iterator */ - while ((depname = rpmtdNextString(&tddep))) { - depversion = rpmtdNextString(&tdver); - if (deps(depname, depversion, userptr)) { - rpmtdFreeData(&tddep); - rpmtdFreeData(&tdver); - Fclose(fdi); - return EXIT_BADDEPS; - } - } - - rpmtdFreeData(&tddep); - rpmtdFreeData(&tdver); - - break; - } - - /* Retrieve all provides and run them through provides function */ - while (provides) { - struct rpmtd_s tddep; - struct rpmtd_s tdver; - const char *depname; - const char *depversion; - int found = 0; - - if (!headerGet(h, RPMTAG_PROVIDES, &tddep, HEADERGET_MINMEM)) - break; - - if (!headerGet(h, RPMTAG_PROVIDEVERSION, &tdver, HEADERGET_MINMEM)){ - rpmtdFreeData(&tddep); - break; - } - - /* iterator */ - while ((depname = rpmtdNextString(&tddep))) { - depversion = rpmtdNextString(&tdver); - if (!provides(depname, depversion, userptr)) { - found++; - } - } - - rpmtdFreeData(&tddep); - rpmtdFreeData(&tdver); - - if (found<=0){ - Fclose(fdi); - return EXIT_BADDEPS; - } - break; - } - - /* Retrieve type of payload compression. */ - compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR); - if (compr && strcmp(compr, "gzip")) { - checked_asprintf(&rpmio_flags, "r.%sdio", compr); - } - else { - checked_asprintf(&rpmio_flags, "r.gzdio"); - } - - /* Open uncompressed cpio stream */ - gzdi = Fdopen(fdi, rpmio_flags); - free(rpmio_flags); - - if (gzdi == NULL) { - logMessage(ERROR, "cannot re-open payload: %s", Fstrerror(gzdi)); - return EXIT_FAILURE; - } - - cpio_mydata.gzdi = gzdi; - cpio_mydata.buffer = buffer; - - /* initialize cpio decompressor */ - if (unpack_init(&cpio) != ARCHIVE_OK) { - Fclose(gzdi); - return -1; - } - - rc = archive_read_open(cpio, &cpio_mydata, NULL, rpm_myread, rpm_myclose); - - /* check the status of archive_open */ - if (rc != ARCHIVE_OK){ - Fclose(gzdi); - return -1; - } - - /* read all files in cpio archive and close */ - rc = unpack_members_and_finish(cpio, destination, filter, userptr); - - return rc != ARCHIVE_OK; -} diff --git a/loader/rpmextract.h b/loader/rpmextract.h deleted file mode 100644 index 976047c..0000000 --- a/loader/rpmextract.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - File name: rpmextract.h - Date: 2009/09/16 - Author: msivak - - Copyright (C) 2009 Red Hat, Inc. - - 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 <http://www.gnu.org/licenses/>. -*/ - - -#ifndef __RPMEXTRACT_H__ -#define __RPMEXTRACT_H__ - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#define EXIT_BADDEPS 4 -#define BUFFERSIZE 1024 - -/* both filter functions return 0 - match, 1 - match not found */ -typedef int (*filterfunc)(const char* name, const struct stat *fstat, void *userptr); -typedef int (*dependencyfunc)(const char* depname, const char* depversion, void *userptr); - -int explodeRPM(const char* file, - filterfunc filter, - dependencyfunc provides, - dependencyfunc deps, - void* userptr, - char *destination); - -#endif - -/* end of rpmextract.h */ diff --git a/loader/selinux.c b/loader/selinux.c deleted file mode 100644 index 0d17cb0..0000000 --- a/loader/selinux.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * selinux.c - Various SELinux related functionality needed for the loader. - * Portions extracted from libselinux which was released as public domain - * software by the NSA. - * - * Copyright (C) 2004 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <string.h> - -#include "loader.h" -#include "loadermisc.h" -#include "../pyanaconda/isys/log.h" - -int loadpolicy() { - int pid, status; - - logMessage(INFO, "Loading SELinux policy"); - - if (!(pid = fork())) { - setenv("LD_LIBRARY_PATH", LIBPATH, 1); - execl("/sbin/load_policy", - "/sbin/load_policy", "-q", NULL); - logMessage(ERROR, "exec of load_policy failed: %m"); - exit(1); - } - - waitpid(pid, &status, 0); - if (WIFEXITED(status) && (WEXITSTATUS(status) != 0)) - return 1; - - return 0; -} - diff --git a/loader/selinux.h b/loader/selinux.h deleted file mode 100644 index 5877ddd..0000000 --- a/loader/selinux.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * selinux.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef SELINUX_H -#define SELINUX_H - -int loadpolicy(); - -#define ANACONDA_CONTEXT "system_u:system_r:anaconda_t:s0" - -#endif diff --git a/loader/serial.c b/loader/serial.c deleted file mode 100644 index c4b722a..0000000 --- a/loader/serial.c +++ /dev/null @@ -1,222 +0,0 @@ -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include <linux/serial.h> - -#include <sys/ioctl.h> - -#include <glib.h> - -#include "../pyanaconda/isys/log.h" - -#if defined(__sparc__) -static int termcmp(struct termios *a, struct termios *b) { - if (a->c_iflag != b->c_iflag || a->c_oflag != b->c_oflag || - a->c_cflag != b->c_cflag || a->c_lflag != b->c_lflag) - return 1; - return memcmp(a->c_cc, b->c_cc, sizeof(a->c_cc)); -} -#endif - -#if !defined(__s390__) && !defined(__s390x__) && !defined(__sparc__) -static int termcmp(struct termios *a, struct termios *b) { - if (a->c_iflag != b->c_iflag || a->c_oflag != b->c_oflag || - a->c_cflag != b->c_cflag || a->c_lflag != b->c_lflag || - a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed) - return 1; - return memcmp(a->c_cc, b->c_cc, sizeof(a->c_cc)); -} -#endif - -void get_mode_and_flags(struct termios *cmode, int *flags) { - int fd; - - fd = open("/dev/console", O_RDONLY); - tcgetattr(fd, cmode); - *flags = fcntl(fd, F_GETFL); - close(fd); -} - -void set_mode(struct termios *cmode) { - int fd; - - fd = open("/dev/console", O_WRONLY); - tcsetattr(fd, TCSANOW, cmode); - close(fd); -} - -void restore_mode(struct termios *orig_cmode) { - int fd; - - fd = open("/dev/console", O_WRONLY); - tcsetattr(fd, TCSANOW, orig_cmode); - close(fd); -} - -void restore_flags(int orig_flags) { - int fd; - - fd = open("/dev/console", O_WRONLY); - fcntl(fd, F_SETFL, orig_flags); - close(fd); -} - -#if !defined(__s390__) && !defined(__s390x__) -static int serial_requested(GHashTable *cmdline) { - if (cmdline && g_hash_table_lookup_extended(cmdline, "serial", NULL, NULL)) - return 1; - else - return 0; -} - -static int get_serial_fd() { - int i, fd = -1; - int weird = 0; - char twelve = 12; - char *console = NULL; - static struct serial_struct si; - - struct termios orig_cmode, cmode, mode; - int orig_flags; - - get_mode_and_flags(&orig_cmode, &orig_flags); - - cmode = orig_cmode; - cmode.c_lflag &= (~ECHO); - - set_mode(&cmode); - - /* handle weird consoles */ -#if defined(__powerpc__) - char * consoles[] = { "/dev/hvc0", /* hvc for JS20 */ - - "/dev/hvsi0", "/dev/hvsi1", - "/dev/hvsi2", /* hvsi for POWER5 */ - NULL }; -#elif defined (__i386__) || defined (__x86_64__) - char * consoles[] = { "/dev/xvc0", "/dev/hvc0", NULL }; -#else - char * consoles[] = { NULL }; -#endif - for (i = 0; consoles[i] != NULL; i++) { - if ((fd = open(consoles[i], O_RDWR)) >= 0 && !tcgetattr(fd, &mode) && !termcmp(&cmode, &mode)) { - console = strdup(consoles[i]); - logMessage(INFO, "set console to %s at %d", console, __LINE__); - weird = 1; - break; - } - close(fd); - } - - restore_mode(&orig_cmode); - - if (fd < 0 && ioctl(0, TIOCLINUX, &twelve) < 0) { - console = "/dev/console"; - - if (ioctl(0, TIOCGSERIAL, &si) == -1) - console = NULL; - } - else - console = "/dev/ttyS0"; - - if (console && !weird) { - fd = open(console, O_RDWR, 0); - if (fd < 0) - console = "/dev/tts/0"; - - if (fd < 0) { - logMessage(ERROR, "failed to open %s", console); - return -1; - } - } - - return fd; -} - -static void set_term(int fd, GHashTable *cmdline) { - if (!strcmp(ttyname(fd), "/dev/hvc0")) { - /* using an HMC on a POWER system, use vt320 */ - setenv("TERM", "vt320", 1); - } else { - if (cmdline && g_hash_table_lookup_extended(cmdline, "utf8", NULL, NULL)) - setenv("TERM", "vt100", 1); - else - /* use the no-advanced-video vt100 definition */ - setenv("TERM", "vt100-nav", 1); - } -} -#endif - -void init_serial(struct termios *orig_cmode, int *orig_flags, GHashTable *cmdline) { -#if !defined(__s390__) && !defined(__s390x__) - int fd; - - /* We need to get the original mode and flags here (in addition to inside - * get_serial) so we'll have them for later when we restore the console - * prior to rebooting. - */ - get_mode_and_flags(orig_cmode, orig_flags); - - if (!serial_requested(cmdline) || (fd = get_serial_fd()) == -1) { - /* This is not a serial console install. */ - if ((fd = open("/dev/tty1", O_RDWR, 0)) < 0) { - if ((fd = open("/dev/vc/1", O_RDWR, 0)) < 0) { - fprintf(stderr, "failed to open /dev/tty1 and /dev/vc/1"); - exit(1); - } - } - } - else { - struct winsize winsize; - - if (ioctl(fd, TIOCGWINSZ, &winsize)) { - logMessage(ERROR, "failed to get window size"); - exit(1); - } - - winsize.ws_row = 24; - winsize.ws_col = 80; - - if (ioctl(fd, TIOCSWINSZ, &winsize)) { - logMessage(ERROR, "failed to set window size"); - exit(1); - } - - set_term(fd, cmdline); - } - - setsid(); - if (ioctl(0, TIOCSCTTY, NULL)) - fprintf(stderr, "could not set new controlling tty\n"); - - if (dup2(fd, 0) == -1) - logMessage(ERROR, "dup2(%d): %m", __LINE__); - - if (dup2(fd, 1) == -1) - logMessage(ERROR, "dup2(%d): %m", __LINE__); - - if (dup2(fd, 2) == -1) - logMessage(ERROR, "dup2(%d): %m", __LINE__); - - if (fd > 2) - close(fd); -#else - dup2(0, 1); - dup2(0, 2); -#endif - - /* disable Ctrl+Z, Ctrl+C, etc ... but not in rescue mode */ - if (cmdline && !g_hash_table_lookup_extended(cmdline, "rescue", NULL, NULL)) { - struct termios ts; - - tcgetattr(0, &ts); - ts.c_iflag &= ~BRKINT; - ts.c_iflag |= IGNBRK; - ts.c_iflag &= ~ISIG; - tcsetattr(0, TCSANOW, &ts); - } -} diff --git a/loader/serial.h b/loader/serial.h deleted file mode 100644 index 82e086c..0000000 --- a/loader/serial.h +++ /dev/null @@ -1,9 +0,0 @@ -#include <termios.h> -#include <unistd.h> - -#include <glib.h> - -void get_mode_and_flags(struct termios *cmode, int *flags); -void set_mode(struct termios *cmode); -void restore_console(struct termios *orig_cmode, int orig_flags); -void init_serial(struct termios *orig_cmode, int *orig_flags, GHashTable *cmdline); diff --git a/loader/simplemot b/loader/simplemot deleted file mode 100755 index bebc1cf..0000000 --- a/loader/simplemot +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/perl -# -# simplemot -# -# Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. -# - -$inone = 0; -$intran = 0; -$total = 0; - -binmode(STDIN, ":raw"); -binmode(STDOUT, ":raw"); - -while (<>) { - if (!$inone && /^msgid/) { - chop; - $str = substr($_, 7, length($_) - 8); - $inone = 1; - } elsif ($inone && /^"/) { - chop; - $str .= substr($_, 1, length($_) - 2); - } elsif ($inone) { - $inone = 0; - - $str =~ s/\\n/\n/g; - $str =~ s/\\t/\t/g; - $str =~ s/\\"/"/g; - - # the string is complete -- calculate a hash - $sum = 0; - $xor = 0; - for ($i = 0; $i < length($str); $i++) { - $char = ord(substr($str, $i, 1)); - $sum += $char; - $xor ^= $char; - } - - $total = ($sum << 16) | (($xor & 0xFF) << 8) | (length($str) & 0xFF); - } - - if (!$intran && /^msgstr/) { - chop; - $tran = substr($_, 8, length($_) - 9); - $intran = 1; - } elsif ($intran && /^"/) { - chop; - $tran .= substr($_, 1, length($_) - 2); - } elsif ($intran) { - $intran = 0; - - $tran =~ s/\\n/\n/g; - $tran =~ s/\\t/\t/g; - $tran =~ s/\\"/"/g; - - if (!$total && $str) { - print STDERR "Missing string for $tran"; - exit 1 - } elsif ($str && $tran) { - print pack("Nn", $total, length($tran)); - print $tran; - - #if ($tran < 60) { - #printf STDERR ("0x%x %s\n", $total, $tran); - #} - } - } -} diff --git a/loader/udelay.h b/loader/udelay.h deleted file mode 100644 index 5315074..0000000 --- a/loader/udelay.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * udelay.h -- udelay and other time related functions. - * - * Copyright (C) 2006, 2007 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Peter Jones <pjones@xxxxxxxxxx> - */ - -#ifndef UDELAY_H -#define UDELAY_H 1 - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <time.h> - -#define USECS_PER_SEC 1000000LL -#define NSECS_PER_USEC 1000LL -#define NSECS_PER_SEC (NSECS_PER_USEC * USECS_PER_SEC) - -static inline void -nsectospec(long long nsecs, struct timespec *ts) -{ - if (nsecs < 0) { - ts->tv_sec = -1; - ts->tv_nsec = -1; - return; - } - ts->tv_sec = nsecs / NSECS_PER_SEC; - ts->tv_nsec = (nsecs % NSECS_PER_SEC); -} - -static inline void -usectospec(long long usecs, struct timespec *ts) -{ - if (usecs > 0 && LLONG_MAX / NSECS_PER_USEC > usecs) - usecs *= NSECS_PER_USEC; - - nsectospec(usecs, ts); -} - -static inline int -speczero(struct timespec *ts) -{ - return (ts->tv_sec == 0 && ts->tv_nsec == 0); -} - -static inline int -specinf(struct timespec *ts) -{ - return (ts->tv_sec < 0 || ts->tv_nsec < 0); -} - -static inline long long -spectonsec(struct timespec *ts) -{ - long long nsecs = 0; - if (specinf(ts)) - return -1; - - nsecs = ts->tv_sec * NSECS_PER_SEC; - nsecs += ts->tv_nsec; - return nsecs; -} - -static inline long long -spectousec(struct timespec *ts) -{ - long long usecs = spectonsec(ts); - - return usecs < 0 ? usecs : usecs / NSECS_PER_USEC; -} - -static inline int -gettimespecofday(struct timespec *ts) -{ - struct timeval tv = {0, 0}; - int rc; - - rc = gettimeofday(&tv, NULL); - if (rc >= 0) { - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec * NSECS_PER_USEC; - } - return rc; -} - -/* minuend minus subtrahend equals difference */ -static inline void -tssub(struct timespec *minuend, struct timespec *subtrahend, - struct timespec *difference) -{ - long long m, s, d; - - m = spectonsec(minuend); - s = spectonsec(subtrahend); - - if (s < 0) { - d = 0; - } else if (m < 0) { - d = -1; - } else { - m -= s; - d = m < 0 ? 0 : m; - } - - nsectospec(d, difference); - return; -} - -static inline void -tsadd(struct timespec *augend, struct timespec *addend, struct timespec *sum) -{ - long long aug, add; - - aug = spectonsec(augend); - add = spectonsec(addend); - -// printf("aug: %Ld add: %Ld\n", aug, add); - - if (aug < 0 || add < 0) - nsectospec(-1, sum); - else if (LLONG_MAX - MAX(add,aug) < MAX(add,aug)) - nsectospec(LLONG_MAX, sum); - else - nsectospec(aug+add, sum); - return; -} - -#define tsGT(x,y) (tscmp((x), (y)) < 0) -#define tsGE(x,y) (tscmp((x), (y)) <= 0) -#define tsET(x,y) (tscmp((x), (y)) == 0) -#define tsNE(x,y) (tscmp((x), (y)) != 0) -#define tsLE(x,y) (tscmp((x), (y)) >= 0) -#define tsLT(x,y) (tscmp((x), (y)) > 0) - -static inline int -tscmp(struct timespec *a, struct timespec *b) -{ - long long m, s; - long long rc; - - m = spectonsec(a); - s = spectonsec(b); - - if (s < 0) { - rc = 1; - if (m < 0) - rc = 0; - } else if (m < 0) { - rc = -1; - } else { - rc = MIN(MAX(s-m, -1), 1); - } - - return rc; -} - -static inline void -udelayspec(struct timespec total) -{ - struct timespec rem; - if (specinf(&total)) { - do { - usectospec(LLONG_MAX, &rem); - } while (nanosleep(&rem, &rem) == -1 && errno == EINTR); - } else { - rem = total; - while (nanosleep(&rem, &rem) == -1 && errno == EINTR) - ; - } -} - -static inline void -udelay(long long usecs) -{ - struct timespec rem = {0,0}; - - usectospec(usecs, &rem); - udelayspec(rem); -} - -#endif /* UDELAY_H */ -/* - * vim:ts=8:sw=4:sts=4:et - */ diff --git a/loader/unpack.c b/loader/unpack.c deleted file mode 100644 index 0323d11..0000000 --- a/loader/unpack.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * unpack.c - libarchive helper functions - * - * Copyright (C) 2010 Red Hat, Inc. - * - * 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 <http://www.gnu.org/licenses/>. - * - * Author(s): David Cantrell <dcantrell@xxxxxxxxxx> - */ - -#include <limits.h> -#include <unistd.h> - -#include <archive.h> -#include <archive_entry.h> -#include <glib.h> - -#include "rpmextract.h" - -#include "../pyanaconda/isys/log.h" - -/* - * Wrapper for g_mkdir_with_parents() - */ -int unpack_mkpath(char *path) { - if (path == NULL) - return ARCHIVE_FATAL; - - if (access(path, R_OK|W_OK|X_OK)) { - if (g_mkdir_with_parents(path, 0755) == -1) { - logMessage(ERROR, "unable to mkdir %s (%s:%d): %m", - path, __func__, __LINE__); - return ARCHIVE_FATAL; - } - } - - return ARCHIVE_OK; -} - -/* - * Initialize libarchive object for unpacking an archive file. - * Args: - * struct archive **a The archive object to use. - * Returns: ARCHIVE_OK on success, ARCHIVE_* on failure - */ -int unpack_init(struct archive **a) { - int r = ARCHIVE_OK; - - if ((*a = archive_read_new()) == NULL) - return ARCHIVE_FATAL; - - if ((r = archive_read_support_compression_all(*a)) != ARCHIVE_OK) - return r; - - if ((r = archive_read_support_format_all(*a)) != ARCHIVE_OK) - return r; - - return r; -} - -/* - * Extract all of the archive members of the specified archive - * object. If dest is not NULL, extract archive members to that - * directory. If dest is not NULL and does not exist as a directory, - * create it first. Return ARCHIVE_OK on success, ARCHIVE_* otherwise. - */ -int unpack_members_and_finish(struct archive *a, char *dest, - filterfunc filter, void* userptr) { - int restore = 0; - char prevcwd[PATH_MAX]; - struct archive_entry *e = NULL; - - if (getcwd(prevcwd, PATH_MAX) == NULL) { - logMessage(ERROR, "unable to getcwd() (%s:%d): %m", __func__, - __LINE__); - return ARCHIVE_FATAL; - } else { - restore = 1; - } - - if (dest != NULL) { - if (unpack_mkpath(dest) != ARCHIVE_OK) { - return ARCHIVE_FATAL; - } else if (chdir(dest) == -1) { - logMessage(ERROR, "unable to chdir %s (%s:%d): %m", - dest, __func__, __LINE__); - return ARCHIVE_FATAL; - } - } - - while (archive_read_next_header(a, &e) == ARCHIVE_OK) { - const char *pathname = archive_entry_pathname(e); - const struct stat *fstat = archive_entry_stat(e); - - if (filter && filter(pathname, fstat, userptr)) - continue; - - if (archive_read_extract(a, e, 0) != ARCHIVE_OK) { - logMessage(ERROR, "error unpacking %s (%s:%d): %s", - pathname, __func__, __LINE__, - archive_error_string(a)); - return ARCHIVE_FATAL; - } - } - - if (restore && chdir(prevcwd) == -1) { - logMessage(ERROR, "unable to chdir %s (%s:%d): %m", - dest, __func__, __LINE__); - return ARCHIVE_FATAL; - } - - if (archive_read_finish(a) != ARCHIVE_OK) { - logMessage(ERROR, "error closing archive (%s:%d): %s", - __func__, __LINE__, archive_error_string(a)); - return ARCHIVE_FATAL; - } - - return ARCHIVE_OK; -} - -/* - * Extract an archive (optionally compressed). - * Args: - * filename Full path to archive to unpack. - * dest Directory to unpack in, or NULL for current dir. - * Returns ARCHIVE_OK on success, or appropriate ARCHIVE_* value - * on failure (see /usr/include/archive.h). - */ -int unpack_archive_file(char *filename, char *dest) { - int rc = 0; - struct archive *a = NULL; - - if (filename == NULL || access(filename, R_OK) == -1) { - logMessage(ERROR, "unable to read %s (%s:%d): %m", - filename, __func__, __LINE__); - return ARCHIVE_FATAL; - } - - if ((rc = unpack_init(&a)) != ARCHIVE_OK) { - logMessage(ERROR, "unable to initialize libarchive"); - return rc; - } - - rc = archive_read_open_filename(a, filename, 10240); - if (rc != ARCHIVE_OK) { - logMessage(ERROR, "error opening %s (%s:%d): %s", - filename, __func__, __LINE__, - archive_error_string(a)); - return rc; - } - - return unpack_members_and_finish(a, dest, NULL, NULL); -} diff --git a/loader/unpack.h b/loader/unpack.h deleted file mode 100644 index 2d93345..0000000 --- a/loader/unpack.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * unpack.h - libarchive helper functions - * - * Copyright (C) 2010 Red Hat, Inc. - * - * 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 <http://www.gnu.org/licenses/>. - * - * Author(s): David Cantrell <dcantrell@xxxxxxxxxx> - */ - -#ifndef UNPACK_H -#define UNPACK_H - -#include <archive.h> -#include "rpmextract.h" - -int unpack_mkpath(char *); -int unpack_init(struct archive **); -int unpack_members_and_finish(struct archive *, char *, - filterfunc, void *); -int unpack_archive_file(char *, char *); - -#endif diff --git a/loader/urlinstall.c b/loader/urlinstall.c deleted file mode 100644 index f3713d0..0000000 --- a/loader/urlinstall.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <newt.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mount.h> -#include <unistd.h> -#include <errno.h> -#include <glib.h> - -#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", "/mnt/install/update-disk", 1)) { - copyDirectory("/mnt/install/update-disk", "/tmp/updates", copyWarnFn, - copyErrorFn); - umount("/mnt/install/update-disk"); - unlink("/tmp/updates-disk.img"); - unlink("/mnt/install/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", "/mnt/install/product-disk", 1)) { - copyDirectory("/mnt/install/product-disk", "/tmp/product", copyWarnFn, - copyErrorFn); - umount("/mnt/install/product-disk"); - unlink("/tmp/product-disk.img"); - unlink("/mnt/install/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 an installable tree.")); - 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: */ diff --git a/loader/urlinstall.h b/loader/urlinstall.h deleted file mode 100644 index ba83b75..0000000 --- a/loader/urlinstall.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * urlinstall.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef URLINSTALL_H -#define URLINSTALL_H - -#include "method.h" -#include "urls.h" - -int kickstartFromUrl(char * url, struct loaderData_s * loaderData); -int getFileFromUrl(char * url, char * dest, struct loaderData_s * loaderData); -int promptForUrl(struct loaderData_s *loaderData); -int loadUrlImages(struct loaderData_s *loaderData); - - -#endif diff --git a/loader/urls.c b/loader/urls.c deleted file mode 100644 index f96e1e3..0000000 --- a/loader/urls.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * urls.c - url handling code - * - * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2009 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - * Chris Lumens <clumens@xxxxxxxxxx> - */ - -#include <arpa/inet.h> -#include <ctype.h> -#include <fcntl.h> -#include <netinet/in.h> -#include <newt.h> -#include <regex.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> -#include <netdb.h> -#include <errno.h> -#include <curl/curl.h> - -#include "../pyanaconda/isys/log.h" - -#include "lang.h" -#include "loader.h" -#include "loadermisc.h" -#include "urls.h" -#include "windows.h" -#include "net.h" - -#define NMATCH 10 - -/* boot flags */ -extern uint64_t flags; - -/* This is just a wrapper around the windows.c progress callback that accepts - * the arguments libcurl provides. - */ -int progress_cb(void *data, double dltotal, double dlnow, double ultotal, double ulnow) { - struct progressCBdata *cb_data = (struct progressCBdata *) data; - - progressCallback(cb_data, dlnow, dltotal); - return 0; -} - -int splitProxyParam(char *param, char **user, char **password, char **proxy) { - /* proxy=[protocol://][username[:password]@]host[:port] */ - char *pattern = "([A-Za-z]+://)?(([A-Za-z0-9]+)(:[^:@]+)?@)?([^:/]+)(:[0-9]+)?(/.*)?"; - regex_t re; - regmatch_t pmatch[NMATCH]; - - if (regcomp(&re, pattern, REG_EXTENDED)) { - return 0; - } - - if (regexec(&re, param, NMATCH, pmatch, 0) == REG_NOMATCH) { - regfree(&re); - return 0; - } - - /* Match 0 is always the whole string (assuming regexec matched anything) - * so skip it. Then, these indices are just the number of the starting - * paren in pattern above. Make sure to change these whenever changing - * the pattern. - */ - if (pmatch[3].rm_so != -1) - *user = strndup(param+pmatch[3].rm_so, pmatch[3].rm_eo-pmatch[3].rm_so); - - /* Skip the leading colon. */ - if (pmatch[4].rm_so != -1) - *password = strndup(param+pmatch[4].rm_so+1, pmatch[4].rm_eo-pmatch[4].rm_so-1); - - if (pmatch[5].rm_so != -1) { - char *portStr = ""; - - if (pmatch[6].rm_so != -1) - portStr = strndup(param+pmatch[6].rm_so, pmatch[6].rm_eo-pmatch[6].rm_so); - - /* If no parameter was given, default to HTTP. yum will want to know - * the protocol, and curl will just ignore it if given. - */ - if (pmatch[1].rm_so != -1) { - checked_asprintf(proxy, "%.*s%.*s%s", pmatch[1].rm_eo-pmatch[1].rm_so, - param+pmatch[1].rm_so, - pmatch[5].rm_eo-pmatch[5].rm_so, - param+pmatch[5].rm_so, - portStr); - } else { - checked_asprintf(proxy, "http://%.*s%s", pmatch[5].rm_eo-pmatch[5].rm_so, - param+pmatch[5].rm_so, - portStr); - } - } - - regfree(&re); - return 1; -} - -int urlinstTransfer(struct loaderData_s *loaderData, const char *src, - char **extraHeaders, char *dest) { - struct progressCBdata *cb_data; - CURL *curl = NULL; - CURLcode status; - struct curl_slist *headers = NULL; - char *version; - FILE *f = NULL; - - logMessage(INFO, "transferring %s", src); - - f = fopen(dest, "w"); - - /* Initialize libcurl */ - curl_global_init(CURL_GLOBAL_SSL); - curl = curl_easy_init(); - - checked_asprintf(&version, "anaconda/%s", VERSION); - - curl_easy_setopt(curl, CURLOPT_USERAGENT, version); - curl_easy_setopt(curl, CURLOPT_URL, src); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, f); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10); - curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); - - /* If a proxy was provided, add the options for that now. */ - if (loaderData->proxy && strcmp(loaderData->proxy, "")) { - curl_easy_setopt(curl, CURLOPT_PROXY, loaderData->proxy); - - if (loaderData->proxyUser && strcmp(loaderData->proxyUser, "")) - curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, - loaderData->proxyUser); - - if (loaderData->proxyPassword && strcmp(loaderData->proxyPassword, "")) - curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, - loaderData->proxyPassword); - } - - if (extraHeaders) { - int i; - for (i = 0; extraHeaders[i] != NULL; i++) { - headers = curl_slist_append(headers, extraHeaders[i]); - } - - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - } - - if (loaderData->instRepo_noverifyssl || FL_NOVERIFYSSL(flags)) { - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); - } - - /* Only set up the progress bar if we've got a UI to display it. */ - if (FL_CMDLINE(flags)) { - printf("%s %s...\n", _("Retrieving"), src); - } else { - const char *filename; - - filename = strrchr(src, '/'); - if (!filename) - filename = src; - - cb_data = winProgressBar(70, 5, _("Retrieving"), "%s %s...", _("Retrieving"), filename); - - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_cb); - curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, cb_data); - } - - /* Finally, do the transfer. */ - status = curl_easy_perform(curl); - if (status) - logMessage(ERROR, "Error downloading %s: %s", src, curl_easy_strerror(status)); - - if (!FL_CMDLINE(flags)) - newtPopWindow(); - - if (headers) - curl_slist_free_all(headers); - - fclose(f); - free(version); - - curl_easy_cleanup(curl); - curl_global_cleanup(); - - return status; -} - -char * addrToIp(char * hostname) { - struct in_addr ad; - struct in6_addr ad6; - char *ret; - struct hostent *host; - - if ((ret = malloc(INET6_ADDRSTRLEN+1)) == NULL) - return hostname; - - if (inet_ntop(AF_INET, &ad, ret, INET_ADDRSTRLEN) != NULL) - return ret; - else if (inet_ntop(AF_INET6, &ad6, ret, INET6_ADDRSTRLEN) != NULL) - return ret; - else if ((host = gethostbyname(hostname)) != NULL) - return host->h_name; - else - return NULL; -} - -static void setProxySensitivity(newtComponent co, void *dptr) { - int i; - - /* It's 3 because there are three entry boxes in the proxy grid. Lame. */ - for (i = 0; i < 3; i++) { - newtEntrySetFlags(*((newtComponent *) dptr), NEWT_FLAG_DISABLED, - NEWT_FLAGS_TOGGLE); - dptr += sizeof(newtComponent); - } - - return; -} - -int urlMainSetupPanel(struct loaderData_s *loaderData) { - newtComponent form, okay, cancel, urlEntry, proxyCheckbox; - newtComponent proxyEntries[3]; - newtComponent answer, text; - char enableProxy; - char *url = "", *proxy = "", *proxyUser = "", *proxyPassword = ""; - char * reflowedText = NULL; - int width, height; - newtGrid buttons, grid, proxyGrid; - char * buf = NULL; - - /* Populate the UI with whatever initial value we've got. */ - if (loaderData->instRepo) - url = loaderData->instRepo; - - if (loaderData->proxy) - proxy = loaderData->proxy; - - if (loaderData->proxyUser) - proxyUser = loaderData->proxyUser; - - if (loaderData->proxyPassword) - proxyPassword = loaderData->proxyPassword; - - buttons = newtButtonBar(_("OK"), &okay, _("Back"), &cancel, NULL); - - checked_asprintf(&buf, - _("Please enter the URL containing the %s installation tree on your server."), - getProductName()); - - reflowedText = newtReflowText(buf, 47, 5, 5, &width, &height); - free(buf); - - text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP); - newtTextboxSetText(text, reflowedText); - free(reflowedText); - - urlEntry = newtEntry(22, 8, url, 60, (const char **) &url, - NEWT_ENTRY_SCROLL); - - /* If we've been provided with proxy settings already, enable the proxy - * grid. This will make sure all the fields get filled in, too. - */ - enableProxy = loaderData->proxy != NULL && strcmp("", loaderData->proxy) ? '*' : ' '; - - proxyCheckbox = newtCheckbox(-1, -1, _("Enable HTTP proxy"), enableProxy, - NULL, &enableProxy); - newtComponentAddCallback(proxyCheckbox, setProxySensitivity, &proxyEntries); - - proxyEntries[0] = newtEntry(-1, -1, proxy, 35, (const char **) &proxy, NEWT_FLAG_SCROLL); - proxyEntries[1] = newtEntry(-1, -1, proxyUser, 15, (const char **) &proxyUser, NEWT_FLAG_SCROLL); - proxyEntries[2] = newtEntry(-1, -1, proxyPassword, 15, (const char **) &proxyPassword, NEWT_FLAG_SCROLL|NEWT_FLAG_PASSWORD); - - /* Set the initial proxy grid sensitivity to match. */ - if (enableProxy == ' ') - setProxySensitivity(proxyCheckbox, proxyEntries); - - proxyGrid = newtCreateGrid(2, 3); - newtGridSetField(proxyGrid, 0, 0, NEWT_GRID_COMPONENT, - newtLabel(-1, -1, _("Proxy URL")), - 0, 0, 0, 0, 0, NEWT_ANCHOR_LEFT); - newtGridSetField(proxyGrid, 1, 0, NEWT_GRID_COMPONENT, proxyEntries[0], - 0, 0, 0, 0, 0, NEWT_ANCHOR_LEFT); - newtGridSetField(proxyGrid, 0, 1, NEWT_GRID_COMPONENT, - newtLabel(-1, -1, _("Username")), - 0, 0, 0, 1, 0, NEWT_ANCHOR_LEFT); - newtGridSetField(proxyGrid, 1, 1, NEWT_GRID_COMPONENT, proxyEntries[1], - 0, 0, 0, 1, 0, NEWT_ANCHOR_LEFT); - newtGridSetField(proxyGrid, 0, 2, NEWT_GRID_COMPONENT, - newtLabel(-1, -1, _("Password")), - 0, 0, 0, 1, 0, NEWT_ANCHOR_LEFT); - newtGridSetField(proxyGrid, 1, 2, NEWT_GRID_COMPONENT, proxyEntries[2], - 0, 0, 0, 1, 0, NEWT_ANCHOR_LEFT); - - grid = newtCreateGrid(1, 5); - newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text, - 0, 0, 0, 1, 0, 0); - newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, urlEntry, - 0, 0, 0, 1, 0, 0); - newtGridSetField(grid, 0, 2, NEWT_GRID_COMPONENT, proxyCheckbox, - 0, 0, 0, 1, 0, NEWT_ANCHOR_LEFT); - newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, proxyGrid, - 0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX); - newtGridSetField(grid, 0, 4, NEWT_GRID_SUBGRID, buttons, - 0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX); - - form = newtForm(NULL, NULL, 0); - newtGridAddComponentsToForm(grid, form, 1); - newtGridWrappedWindow(grid, _("URL Setup")); - newtGridFree(grid, 1); - - do { - answer = newtRunForm(form); - if (answer != cancel) { - if (!strlen(url)) { - newtWinMessage(_("Error"), _("OK"), - _("You must enter a URL.")); - continue; - } - - loaderData->instRepo = strdup(url); - - if (strncmp(url, "http", 4) && strncmp(url, "ftp://", 6)) { - newtWinMessage(_("Error"), _("OK"), - _("URL must be either an ftp or http URL")); - continue; - } - - if (enableProxy == '*') { - if (strncmp(proxy, "http", 4) && strncmp(proxy, "ftp://", 6)) { - newtWinMessage(_("Error"), _("OK"), - _("Proxy must be either an ftp or http URL")); - continue; - } - - loaderData->proxy = strdup(proxy); - loaderData->proxyUser = strdup(proxyUser); - loaderData->proxyPassword = strdup(proxyPassword); - } else { - loaderData->proxy = ""; - loaderData->proxyUser = ""; - loaderData->proxyPassword = ""; - } - - /* FIXME: add back in hostname checking */ - } - - break; - } while (1); - - if (answer == cancel) { - newtFormDestroy(form); - newtPopWindow(); - - return LOADER_BACK; - } - - newtFormDestroy(form); - newtPopWindow(); - - return 0; -} diff --git a/loader/urls.h b/loader/urls.h deleted file mode 100644 index 5e984e1..0000000 --- a/loader/urls.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * urls.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef H_LOADER_URLS -#define H_LOADER_URLS - -#include "loader.h" -#include "windows.h" - -int splitProxyParam(char *param, char **user, char **password, char **proxy); -int urlMainSetupPanel(struct loaderData_s *loaderData); -int urlinstTransfer(struct loaderData_s *loaderData, const char *src, - char **extraHeaders, char *dest); - -#endif diff --git a/loader/windows.c b/loader/windows.c deleted file mode 100644 index 9095619..0000000 --- a/loader/windows.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * windows.c - simple popup windows used by the loader - * - * Copyright (C) 1997, 1998, 1999, 2000, 2001, 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 <http://www.gnu.org/licenses/>. - * - * Author(s): Erik Troan <ewt@xxxxxxxxxx> - * Matt Wilson <msw@xxxxxxxxxx> - * Michael Fulbright <msf@xxxxxxxxxx> - * Jeremy Katz <katzj@xxxxxxxxxx> - */ - -#include <errno.h> -#include <newt.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdarg.h> -#include <math.h> - -#include "../pyanaconda/isys/log.h" - -#include "windows.h" - -void winStatus(int width, int height, char * title, char * text, ...) { - newtComponent t, f; - char * buf = NULL; - va_list args; - - va_start(args, text); - - if (vasprintf(&buf, text, args) != -1) { - newtCenteredWindow(width, height, title); - - t = newtTextbox(1, 1, width - 2, height - 2, NEWT_TEXTBOX_WRAP); - newtTextboxSetText(t, buf); - f = newtForm(NULL, NULL, 0); - - free(buf); - - newtFormAddComponent(f, t); - - newtDrawForm(f); - newtRefresh(); - newtFormDestroy(f); - } - - va_end(args); -} - - -int progressCallback(void *pbdata, long long pos, long long total) { - struct progressCBdata *data = pbdata; - char tickmark[2] = "-"; - char *ticks = "-\\|/"; - int x = ceil(pos * 100.0 / total); - - newtScaleSet(data->scale, x); - *tickmark = ticks[x % 4]; - - newtLabelSetText(data->label, tickmark); - newtRefresh(); - return 0; -} - -struct progressCBdata *winProgressBar(int width, int height, char *title, char *text, ...) { - struct progressCBdata *data; - char *buf = NULL; - va_list args; - int llen; - newtComponent t, f, scale, label; - - va_start(args, text); - - if (vasprintf(&buf, text, args) != -1) { - va_end(args); - newtCenteredWindow(width, height, title); - t = newtTextbox(1, 1, width - 2, height - 2, NEWT_TEXTBOX_WRAP); - newtTextboxSetText(t, buf); - llen = strlen(buf); - free(buf); - label = newtLabel(llen + 1, 1, "-"); - f = newtForm(NULL, NULL, 0); - newtFormAddComponent(f, t); - scale = newtScale(3, 3, width - 6, 100); - newtFormAddComponent(f, scale); - newtDrawForm(f); - newtRefresh(); - - if ((data = malloc(sizeof(struct progressCBdata))) == NULL) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - data->scale = scale; - data->label = label; - return data; - } - - return NULL; -} - -/* vim:set shiftwidth=4 softtabstop=4: */ diff --git a/loader/windows.h b/loader/windows.h deleted file mode 100644 index 9356994..0000000 --- a/loader/windows.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * windows.h - * - * Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef _WINDOWS_H_ -#define _WINDOWS_H_ - -#include <newt.h> - -#include "lang.h" - -void winStatus(int width, int height, char * title, char * text, ...); - -#define errorWindow(String) \ - newtWinMessage(_("Error"), _("OK"), String, strerror (errno)); - -typedef void (*progressCB) (void *pbdata, long long offset, long long total); - -struct progressCBdata { - newtComponent scale; - newtComponent label; -}; - -int progressCallback(void *pbdata, long long pos, long long total); -struct progressCBdata *winProgressBar(int width, int height, char *title, char *text, ...); - -#endif /* _WINDOWS_H_ */ -- 1.7.7.6 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list