summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--loader/kickstart.c3
-rw-r--r--loader/loader.c6
-rw-r--r--loader/loader.h2
-rw-r--r--loader/modules.c506
-rw-r--r--loader/modules.h25
5 files changed, 276 insertions, 266 deletions
diff --git a/loader/kickstart.c b/loader/kickstart.c
index b92c6da1d..764df5d69 100644
--- a/loader/kickstart.c
+++ b/loader/kickstart.c
@@ -39,6 +39,7 @@
#include "lang.h"
#include "log.h"
#include "kickstart.h"
+#include "modules.h"
#include "kbd.h"
#include "driverdisk.h"
@@ -86,8 +87,6 @@ static void setMediaCheck(struct loaderData_s * loaderData, int argc,
char ** argv);
static void setUpdates(struct loaderData_s * loaderData, int argc,
char ** argv);
-void loadKickstartModule(struct loaderData_s * loaderData, int argc,
- char ** argv);
struct ksCommandNames ksTable[] = {
{ KS_CMD_NFS, "nfs", setKickstartNfs },
diff --git a/loader/loader.c b/loader/loader.c
index dea600f74..0ea57cb31 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -1987,7 +1987,11 @@ int main(int argc, char ** argv) {
* FIXME: this syntax is likely to change in a future release
* but is done as a quick hack for the present.
*/
- mlInitModuleConfig();
+ if (!mlInitModuleConfig()) {
+ logMessage(ERROR, "unable to initialize kernel module loading");
+ abort();
+ }
+
earlyModuleLoad(0);
busProbe(FL_NOPROBE(flags));
diff --git a/loader/loader.h b/loader/loader.h
index f942b7e1d..ffb408772 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -115,7 +115,7 @@ char * getProductName(void);
char * getProductPath(void);
char * getProductArch(void);
-#include "modules.h"
+#include "moduleinfo.h"
#include "../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
diff --git a/loader/modules.c b/loader/modules.c
index fbdd0c94e..a174dc11b 100644
--- a/loader/modules.c
+++ b/loader/modules.c
@@ -1,7 +1,8 @@
/*
* modules.c - module loading functionality
*
- * Copyright (C) 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
+ * 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
@@ -21,6 +22,7 @@
* Matt Wilson <msw@redhat.com>
* Michael Fulbright <msf@redhat.com>
* Jeremy Katz <katzj@redhat.com>
+ * David Cantrell <dcantrell@redhat.com>
*/
#include <ctype.h>
@@ -37,339 +39,351 @@
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <glib.h>
#include "loader.h"
#include "log.h"
#include "modules.h"
#include "windows.h"
-#include "../isys/cpio.h"
-
/* boot flags */
extern uint64_t flags;
-static int writeModulesConf(char *conf);
-struct moduleOptions {
- char *name;
- int numopts;
- char **options;
-};
+static GSList *modopts = NULL;
+static GSList *blacklist = NULL;
-static struct moduleOptions * modopts = NULL;
-static int nummodopts = -1;
+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;
-static char ** blacklists = NULL;
-static int numblacklists = 0;
+ if (uname(&utsbuf) == -1) {
+ logMessage(ERROR, "%s (%d): %m", __func__, __LINE__);
+ return FALSE;
+ }
-static void readBlacklist() {
- int fd;
- size_t len = 0;
- char buf[1024];
- char *start, *end;
+ if (asprintf(&path, "/lib/modules/%s/modules.dep", utsbuf.release) == -1) {
+ logMessage(ERROR, "%s (%d): %m", __func__, __LINE__);
+ return FALSE;
+ }
- if ((fd = open("/proc/cmdline", O_RDONLY)) < 0)
- return;
+ 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;
+ }
- len = read(fd, buf, sizeof(buf) - 1);
close(fd);
- buf[len] = '\0';
- start = buf;
-
- while (start) {
- end = strstr(start, " ");
- if (end)
- *end = '\0';
- if (strncmp(start,"blacklist=",10)) {
- if (!end)
- break;
- start = end + 1;
- continue;
+
+ while (ends[i] != NULL) {
+ if (asprintf(&modname, "/%s%s", module, ends[i]) == -1) {
+ logMessage(ERROR, "%s (%d): %m", __func__, __LINE__);
+ return FALSE;
}
- printf("found %s\n",start);
- blacklists = realloc(blacklists, sizeof(*blacklists) * (numblacklists + 1));
- blacklists[numblacklists] = strdup(start+10);
- numblacklists++;
+ if (g_strstr_len(buf, -1, modname) != NULL) {
+ munmap(buf, sbuf.st_size);
+ free(modname);
+ return TRUE;
+ }
- if (!end)
- break;
- start = end + 1;
+ free(modname);
+ modname = NULL;
+ i++;
}
-}
-void mlAddBlacklist(char *module) {
- blacklists = realloc(blacklists, sizeof(*blacklists) * (numblacklists + 1));
- blacklists[numblacklists] = strdup(module);
- numblacklists++;
- writeModulesConf("/etc/modprobe.d/anaconda.conf");
+ munmap(buf, sbuf.st_size);
+ return FALSE;
}
-static void addOption(const char *module, const char *option) {
- int found = 0, i, sz;
-
- found = 0;
- for (i = 0; i < nummodopts; i++) {
- if (strncmp(modopts[i].name, module, strlen(modopts[i].name)))
- continue;
- modopts[i].numopts++;
- found = 1;
- break;
- }
-
- if (found) {
- modopts[i].options = realloc(modopts[i].options,
- sizeof(modopts[i].options) *
- (modopts[i].numopts + 1));
- if (modopts[i].options == NULL) {
- logMessage(ERROR, "%s (%d): %m", __func__, __LINE__);
- abort();
- }
+static void _addOption(const gchar *module, const gchar *option) {
+ gboolean found = FALSE;
+ GSList *iterator = modopts;
+ module_t *modopt = NULL;
+ gchar *tmpopt = g_strdup(option);
- modopts[i].options[modopts[i].numopts - 1] = strdup(option);
- modopts[i].options[modopts[i].numopts] = NULL;
- } else {
- if (modopts == NULL) {
- modopts = malloc(sizeof(struct moduleOptions) * (nummodopts + 1));
- } else {
- modopts = realloc(modopts, sizeof(*modopts) * (nummodopts + 1));
- }
+ while (iterator != NULL) {
+ modopt = (module_t *) iterator->data;
- if (modopts == NULL) {
- logMessage(ERROR, "%s (%d): %m", __func__, __LINE__);
- abort();
+ if (!strncmp(modopt->name, module, strlen(modopt->name))) {
+ found = TRUE;
+ break;
}
- modopts[nummodopts].name = strdup(module);
- modopts[nummodopts].numopts = 1;
+ iterator = g_slist_next(iterator);
+ }
- sz = sizeof(modopts[nummodopts].options) * 2;
- if ((modopts[nummodopts].options = malloc(sz)) == NULL) {
+ 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();
}
- modopts[nummodopts].options[0] = strdup(option);
- modopts[nummodopts].options[1] = NULL;
-
- nummodopts++;
+ modopt->name = g_strdup(module);
+ modopt->options = NULL;
+ modopt->options = g_slist_append(modopt->options, tmpopt);
+ modopts = g_slist_append(modopts, modopt);
}
return;
}
-static int isValidModule(char *module) {
- char mod_name[64], path[512];
- struct utsname utsbuf;
- struct stat sbuf;
- char *buf;
-
- uname(&utsbuf);
- snprintf(path, 512, "/lib/modules/%s/modules.dep", utsbuf.release);
- if (!stat(path, &sbuf)) {
- int fd;
-
- fd = open(path, O_RDONLY);
- buf = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
- if (!buf || buf == MAP_FAILED)
- return 0;
- close(fd);
- snprintf(mod_name, 64, "/%s.ko.gz:", module);
- if (strstr(buf, mod_name)) {
- munmap(buf, sbuf.st_size);
- return 1;
- }
- snprintf(mod_name, 64, "/%s.ko:", module);
- if (strstr(buf, mod_name)) {
- munmap(buf, sbuf.st_size);
- return 1;
- }
- munmap(buf, sbuf.st_size);
+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";
}
- return 0;
-}
-/* read module options out of /proc/cmdline and into a structure */
-static void readModuleOpts() {
- int fd;
- size_t len = 0;
- char buf[1024];
- char *start, *end, *sep;
+ if ((fd = open(conf, O_WRONLY | O_CREAT, 0644)) == -1) {
+ logMessage(ERROR, "error opening to %s: %m", conf);
+ return FALSE;
+ }
- nummodopts = 0;
- if ((fd = open("/proc/cmdline", O_RDONLY)) < 0)
- return;
+ while (iterator != NULL) {
+ module_t *modopt = iterator->data;
+ GSList *optiterator = modopt->options;
+ g_string_append_printf(buf, "options %s", modopt->name);
- len = read(fd, buf, sizeof(buf) - 1);
- close(fd);
- buf[len] = '\0';
- start = buf;
-
- while (start) {
- end = strstr(start, " ");
- if (end)
- *end = '\0';
- sep = strstr(start, "=");
- if (sep == NULL) {
- if (!end)
- break;
- start = end + 1;
- continue;
+ while (optiterator != NULL) {
+ gchar *option = (gchar *) optiterator->data;
+ g_string_append_printf(buf, " %s", option);
+ optiterator = g_slist_next(optiterator);
}
- sep = strstr(start, ".");
- if (sep == NULL) {
- if (!end)
- break;
- start = end + 1;
- continue;
- }
- *sep = '\0'; sep++;
- if (isValidModule(start))
- addOption(start, sep);
+ g_string_append(buf, "\n");
+ iterator = g_slist_next(iterator);
+ }
- if (!end)
- break;
- start = end + 1;
+ 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 int doLoadModule(const char *module, char ** args) {
- int child;
- int status;
+static gboolean _doLoadModule(const gchar *module, gchar **args) {
+ gint child;
+ gint status;
if (!(child = fork())) {
- int i, rc;
- char **argv = malloc(3 * sizeof(*argv));
- int fd = open("/dev/tty3", O_RDWR);
+ gint i, rc;
+ gchar **argv = NULL;
+ gint fd = -1;
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- close(fd);
+ if ((argv = g_malloc0(3 * sizeof(*argv))) == NULL) {
+ logMessage(ERROR, "%s (%d): %m", __func__, __LINE__);
+ abort();
+ }
+
+ if ((fd = open("/dev/tty3", O_RDWR)) == -1) {
+ 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] = strdup(module);
+ argv[1] = g_strdup(module);
argv[2] = NULL;
+
if (args) {
for (i = 0; args[i] ; i++) {
- addOption(module, args[i]);
+ _addOption(module, args[i]);
}
- writeModulesConf("/etc/modprobe.d/anaconda.conf");
+ _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 1;
+ return TRUE;
} else {
- return 0;
+ return FALSE;
}
}
-void mlRemoveBlacklist(char *module) {
- int i;
+gboolean mlInitModuleConfig(void) {
+ gint i = 0;
+ gchar *cmdline = NULL;
+ gchar **options = NULL;
+ GError *readErr = NULL;
+
+ /* read module options out of /proc/cmdline and into a structure */
+ if (!g_file_get_contents("/proc/cmdline", &cmdline, NULL, &readErr)) {
+ logMessage(ERROR, "unable to read /proc/cmdline: %s", readErr->message);
+ g_error_free(readErr);
+ return _writeModulesConf(MODULES_CONF);
+ }
+
+ cmdline = g_strchomp(cmdline);
+ options = g_strsplit(cmdline, " ", 0);
+ g_free(cmdline);
- for (i = 0 ; i < numblacklists ; i++) {
- if (!strcmp(blacklists[i], module))
- blacklists[i] = NULL;
+ if (options == NULL) {
+ return _writeModulesConf(MODULES_CONF);
}
-}
-void mlInitModuleConfig() {
- readModuleOpts();
- readBlacklist();
- writeModulesConf("/etc/modprobe.d/anaconda.conf");
+ while (options[i] != NULL) {
+ gchar *tmpmod = NULL;
+ gchar **fields = NULL;
+
+ if (g_strstr_len(options[i], -1, "=") == NULL) {
+ i++;
+ continue;
+ }
+
+ if (!strncmp(options[i], "blacklist=", 10)) {
+ if ((fields = g_strsplit(options[i], "=", 0)) != NULL) {
+ if (g_strv_length(fields) == 2) {
+ tmpmod = g_strdup(fields[1]);
+ blacklist = g_slist_append(blacklist, tmpmod);
+ }
+ }
+ } else if ((fields = g_strsplit(options[i], ".", 0)) != NULL) {
+ if (g_strv_length(fields) == 2) {
+ if (_isValidModule(fields[0])) {
+ _addOption(fields[0], fields[1]);
+ }
+ }
+ }
+
+ if (fields != NULL) {
+ g_strfreev(fields);
+ }
+
+ i++;
+ }
+
+ if (options != NULL) {
+ g_strfreev(options);
+ }
+
+ return _writeModulesConf(MODULES_CONF);
}
/* load a module with a given list of arguments */
-int mlLoadModule(const char * module, char ** args) {
- return doLoadModule(module, args);
+gboolean mlLoadModule(const gchar *module, gchar **args) {
+ return _doLoadModule(module, args);
}
/* loads a : separated list of modules */
-int mlLoadModuleSet(const char * modNames) {
- char *ptr, *name;
- int rc = 0;
-
- if (!modNames) return 1;
- name = strdup(modNames); while (name) {
- ptr = strchr(name, ':');
- if (ptr) *ptr = '\0';
- rc |= doLoadModule(name, NULL);
- if (ptr)
- name = ptr+1;
- else
- name = NULL;
+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;
}
-static int writeModulesConf(char *conf) {
- int i;
- char buf[16384];
- int fd, rc;
+gboolean mlAddBlacklist(gchar *module) {
+ gchar *tmpmod = NULL;
- if (!conf)
- conf = "/tmp/modprobe.conf";
-
- fd = open(conf, O_WRONLY | O_CREAT, 0644);
- if (fd == -1) {
- logMessage(ERROR, "error opening to %s: %m\n", conf);
- return 0;
+ if (module == NULL) {
+ return FALSE;
}
- strcat(buf, "# Module options and blacklists written by anaconda\n");
- for (i = 0; i < nummodopts ; i++) {
- int j;
-
- strcat(buf, "options ");
- strcat(buf, modopts[i].name);
- for (j = 0; j < modopts[i].numopts ; j++) {
- strcat(buf, " ");
- strcat(buf, modopts[i].options[j]);
- }
- strcat(buf, "\n");
+
+ 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;
}
- for (i = 0; i < numblacklists ; i++) {
- if (blacklists[i]) {
- strcat(buf, "blacklist ");
- strcat(buf, blacklists[i]);
- strcat(buf, "\n");
+
+ while (iterator != NULL) {
+ if (!strcmp((gchar *) iterator->data, module)) {
+ iterator = g_slist_delete_link(blacklist, iterator);
+ continue;
+ } else {
+ iterator = g_slist_next(iterator);
}
}
-
- rc = write(fd, buf, strlen(buf));
- close(fd);
- return (rc != strlen(buf));
+
+ return TRUE;
}
-void loadKickstartModule(struct loaderData_s * loaderData, int argc,
- char ** argv) {
- char * opts = NULL;
- char * module = NULL;
- char ** args = NULL;
+void loadKickstartModule(struct loaderData_s * loaderData,
+ int argc, char **argv) {
+ gchar *opts = NULL;
+ gchar *module = NULL;
+ gchar **args = NULL;
poptContext optCon;
- int rc;
+ gboolean rc;
struct poptOption ksDeviceOptions[] = {
{ "opts", '\0', POPT_ARG_STRING, &opts, 0, NULL, NULL },
{ 0, 0, 0, 0, 0, 0, 0 }
};
-
- optCon = poptGetContext(NULL, argc, (const char **) argv,
+
+ optCon = poptGetContext(NULL, argc, (const char **) argv,
ksDeviceOptions, 0);
if ((rc = poptGetNextOpt(optCon)) < -1) {
startNewt();
newtWinMessage(_("Kickstart Error"), _("OK"),
_("Bad argument to device kickstart method "
"command %s: %s"),
- poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
+ poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(rc));
return;
}
- module = (char *) poptGetArg(optCon);
+ module = (gchar *) poptGetArg(optCon);
if (!module) {
startNewt();
@@ -380,30 +394,10 @@ void loadKickstartModule(struct loaderData_s * loaderData, int argc,
}
if (opts) {
- int numAlloced = 5, i = 0;
- char * start;
- char * end;
-
- args = malloc((numAlloced + 1) * sizeof(args));
- start = opts;
- while (start && *start) {
- end = start;
- while (!isspace(*end) && *end) end++;
- *end = '\0';
- (args)[i++] = strdup(start);
- start = end + 1;
- *end = ' ';
- start = strchr(end, ' ');
- if (start) start++;
-
- if (i >= numAlloced) {
- numAlloced += 5;
- args = realloc(args, sizeof(args) * (numAlloced + 1));
- }
- }
- args[i] = NULL;
+ args = g_strsplit(opts, " ", 0);
}
-
- mlLoadModule(module, args);
+ rc = mlLoadModule(module, args);
+ g_strfreev(args);
+ return;
}
diff --git a/loader/modules.h b/loader/modules.h
index 6c0d8adcd..88fa25fc7 100644
--- a/loader/modules.h
+++ b/loader/modules.h
@@ -1,7 +1,7 @@
/*
* modules.h
*
- * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ * 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
@@ -15,16 +15,29 @@
*
* 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@redhat.com>
*/
#ifndef H_MODULES
#define H_MODULES
+#include <glib.h>
+#include "loader.h"
#include "moduleinfo.h"
-void mlInitModuleConfig();
-int mlLoadModule(const char * module, char ** args);
-int mlLoadModuleSet(const char * modNames);
-void mlAddBlacklist(char *module);
-void mlRemoveBlacklist(char *module);
+#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 *);
+void loadKickstartModule(struct loaderData_s *, int, char **);
+
#endif